Configuration model added for account recover command
This commit is contained in:
@@ -40,7 +40,8 @@ from student.models import (
|
|||||||
UserAttribute,
|
UserAttribute,
|
||||||
UserProfile,
|
UserProfile,
|
||||||
UserTestGroup,
|
UserTestGroup,
|
||||||
BulkUnenrollConfiguration
|
BulkUnenrollConfiguration,
|
||||||
|
AccountRecoveryConfiguration
|
||||||
)
|
)
|
||||||
from student.roles import REGISTERED_ACCESS_ROLES
|
from student.roles import REGISTERED_ACCESS_ROLES
|
||||||
from xmodule.modulestore.django import modulestore
|
from xmodule.modulestore.django import modulestore
|
||||||
@@ -492,6 +493,7 @@ class AllowedAuthUserAdmin(admin.ModelAdmin):
|
|||||||
admin.site.register(UserTestGroup)
|
admin.site.register(UserTestGroup)
|
||||||
admin.site.register(Registration)
|
admin.site.register(Registration)
|
||||||
admin.site.register(PendingNameChange)
|
admin.site.register(PendingNameChange)
|
||||||
|
admin.site.register(AccountRecoveryConfiguration, ConfigurationModelAdmin)
|
||||||
admin.site.register(DashboardConfiguration, ConfigurationModelAdmin)
|
admin.site.register(DashboardConfiguration, ConfigurationModelAdmin)
|
||||||
admin.site.register(RegistrationCookieConfiguration, ConfigurationModelAdmin)
|
admin.site.register(RegistrationCookieConfiguration, ConfigurationModelAdmin)
|
||||||
admin.site.register(BulkUnenrollConfiguration, ConfigurationModelAdmin)
|
admin.site.register(BulkUnenrollConfiguration, ConfigurationModelAdmin)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from django.utils.http import int_to_base36
|
|||||||
from edx_ace import ace
|
from edx_ace import ace
|
||||||
from edx_ace.recipient import Recipient
|
from edx_ace.recipient import Recipient
|
||||||
|
|
||||||
|
from student.models import AccountRecoveryConfiguration
|
||||||
from openedx.core.djangoapps.ace_common.template_context import get_base_template_context
|
from openedx.core.djangoapps.ace_common.template_context import get_base_template_context
|
||||||
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
|
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
|
||||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||||
@@ -49,18 +50,24 @@ class Command(BaseCommand):
|
|||||||
""" Add argument to the command parser. """
|
""" Add argument to the command parser. """
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--csv_file_path',
|
'--csv_file_path',
|
||||||
required=True,
|
required=False,
|
||||||
help='Csv file path'
|
help='Csv file path'
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
""" Main handler for the command."""
|
""" Main handler for the command."""
|
||||||
file_path = options['csv_file_path']
|
file_path = options['csv_file_path']
|
||||||
|
if file_path:
|
||||||
|
if not path.isfile(file_path):
|
||||||
|
raise CommandError('File not found.')
|
||||||
|
|
||||||
if not path.isfile(file_path):
|
with open(file_path, 'rb') as csv_file:
|
||||||
raise CommandError('File not found.')
|
csv_reader = list(unicodecsv.DictReader(csv_file))
|
||||||
|
else:
|
||||||
with open(file_path, 'rb') as csv_file:
|
csv_file = AccountRecoveryConfiguration.current().csv_file
|
||||||
|
if not csv_file:
|
||||||
|
logger.error('No csv file found. Please make sure csv file is uploaded')
|
||||||
|
return
|
||||||
csv_reader = list(unicodecsv.DictReader(csv_file))
|
csv_reader = list(unicodecsv.DictReader(csv_file))
|
||||||
|
|
||||||
successful_updates = []
|
successful_updates = []
|
||||||
|
|||||||
@@ -6,12 +6,15 @@ from tempfile import NamedTemporaryFile
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.management import call_command, CommandError
|
from django.core.management import call_command, CommandError
|
||||||
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.test import TestCase, RequestFactory
|
from django.test import TestCase, RequestFactory
|
||||||
|
|
||||||
from testfixtures import LogCapture
|
from testfixtures import LogCapture
|
||||||
from student.tests.factories import UserFactory
|
from student.tests.factories import UserFactory
|
||||||
|
|
||||||
|
from student.models import AccountRecoveryConfiguration
|
||||||
|
|
||||||
LOGGER_NAME = 'student.management.commands.recover_account'
|
LOGGER_NAME = 'student.management.commands.recover_account'
|
||||||
|
|
||||||
@@ -101,4 +104,17 @@ class RecoverAccountTests(TestCase):
|
|||||||
|
|
||||||
log.check_present(
|
log.check_present(
|
||||||
(LOGGER_NAME, 'INFO', expected_message)
|
(LOGGER_NAME, 'INFO', expected_message)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_account_recovery_from_config_model(self):
|
||||||
|
"""Verify learners account recovery using config model."""
|
||||||
|
lines = 'username,email,new_email\namy,amy@edx.com,amy@newemail.com\n'
|
||||||
|
|
||||||
|
csv_file = SimpleUploadedFile(name='test.csv', content=lines.encode('utf-8'), content_type='text/csv')
|
||||||
|
AccountRecoveryConfiguration.objects.create(enabled=True, csv_file=csv_file)
|
||||||
|
|
||||||
|
call_command("recover_account")
|
||||||
|
|
||||||
|
email = get_user_model().objects.get(pk=self.user.pk).email
|
||||||
|
self.assertEqual(email, 'amy@newemail.com')
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.29 on 2020-03-17 11:22
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('student', '0030_userprofile_phone_number'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AccountRecoveryConfiguration',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||||
|
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||||
|
('csv_file', models.FileField(help_text='It expect that the data will be provided in a csv file format with first row being the header and columns will be as follows: username, email, new_email', upload_to='', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['csv'])])),
|
||||||
|
('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('-change_date',),
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
@@ -2996,3 +2996,15 @@ class AllowedAuthUser(TimeStampedModel):
|
|||||||
"this model then that employee can login via third party authentication backend only."),
|
"this model then that employee can login via third party authentication backend only."),
|
||||||
unique=True,
|
unique=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AccountRecoveryConfiguration(ConfigurationModel):
|
||||||
|
"""
|
||||||
|
configuration model for recover account management command
|
||||||
|
"""
|
||||||
|
csv_file = models.FileField(
|
||||||
|
validators=[FileExtensionValidator(allowed_extensions=[u'csv'])],
|
||||||
|
help_text=_(u"It expect that the data will be provided in a csv file format with \
|
||||||
|
first row being the header and columns will be as follows: \
|
||||||
|
username, email, new_email")
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user