Projet

Général

Profil

0001-models-add-User.email_verified_date-field-19634.patch

Benjamin Dauvergne, 27 janvier 2022 10:45

Télécharger (11,6 ko)

Voir les différences:

Subject: [PATCH] models: add User.email_verified_date field (#19634)

 src/authentic2/api_views.py                   |  4 +--
 src/authentic2/csv_import.py                  |  2 +-
 .../0028_user_email_verified_date.py          | 28 +++++++++++++++++++
 src/authentic2/custom_user/models.py          | 14 ++++++++++
 src/authentic2/forms/registration.py          |  2 +-
 src/authentic2/manager/user_views.py          |  2 +-
 src/authentic2/views.py                       |  4 +--
 src/authentic2_auth_oidc/backends.py          |  4 +--
 tests/test_all.py                             |  3 +-
 tests/test_api.py                             |  1 +
 tests/test_migrations.py                      | 12 ++++++++
 tests/test_user_manager.py                    |  4 +--
 12 files changed, 68 insertions(+), 12 deletions(-)
 create mode 100644 src/authentic2/custom_user/migrations/0028_user_email_verified_date.py
src/authentic2/api_views.py
463 463
        if 'ou' in validated_data:
464 464
            self.check_perm('custom_user.change_user', validated_data.get('ou'))
465 465
        if validated_data.get('email') != instance.email and not validated_data.get('email_verified'):
466
            instance.email_verified = False
466
            instance.set_email_verified(False)
467 467
        super().update(instance, validated_data)
468 468
        for key, value in attributes.items():
469 469
            if is_verified.get(key):
......
863 863
        if not serializer.is_valid():
864 864
            response = {'result': 0, 'errors': serializer.errors}
865 865
            return Response(response, status.HTTP_400_BAD_REQUEST)
866
        user.email_verified = False
866
        user.set_email_verified(False)
867 867
        user.save()
868 868
        utils_misc.send_email_change_email(user, serializer.validated_data['email'], request=request)
869 869
        return Response({'result': 1})
src/authentic2/csv_import.py
710 710
                if getattr(user, cell.header.name) != cell.value:
711 711
                    setattr(user, cell.header.name, cell.value)
712 712
                    if cell.header.name == 'email' and cell.header.verified:
713
                        user.email_verified = True
713
                        user.set_email_verified(True)
714 714
                    cell.action = 'updated'
715 715
                    continue
716 716
            cell.action = 'nothing'
src/authentic2/custom_user/migrations/0028_user_email_verified_date.py
1
# Generated by Django 2.2.23 on 2022-01-27 08:03
2

  
3

  
4
from django.db import migrations, models
5

  
6

  
7
def set_email_verified_date(apps, schema_editor):
8
    User = apps.get_model('custom_user', 'User')
9
    qs = User.objects.filter(email_verified=True, email_verified_date__isnull=True)
10
    # set all unknown dates to date joined
11
    qs.update(email_verified_date=models.F('date_joined'))
12

  
13

  
14
class Migration(migrations.Migration):
15
    dependencies = [
16
        ('custom_user', '0027_user_deactivation_reason'),
17
    ]
18

  
19
    operations = [
20
        migrations.AddField(
21
            model_name='user',
22
            name='email_verified_date',
23
            field=models.DateTimeField(
24
                default=None, blank=True, null=True, verbose_name='email verified date'
25
            ),
26
        ),
27
        migrations.RunPython(set_email_verified_date, migrations.RunPython.noop),
28
    ]
src/authentic2/custom_user/models.py
150 150
    last_name = models.CharField(_('last name'), max_length=128, blank=True)
151 151
    email = models.EmailField(_('email address'), blank=True, max_length=254, validators=[email_validator])
152 152
    email_verified = models.BooleanField(default=False, verbose_name=_('email verified'))
153
    email_verified_date = models.DateTimeField(
154
        default=None, blank=True, null=True, verbose_name=_('email verified date')
155
    )
153 156
    is_staff = models.BooleanField(
154 157
        _('staff status'),
155 158
        default=False,
......
428 431
    def get_absolute_url(self):
429 432
        return reverse('a2-manager-user-detail', kwargs={'pk': self.pk})
430 433

  
434
    def set_email_verified(self, value):
435
        if isinstance(value, datetime.datetime):
436
            self.email_verified = True
437
            self.email_verified_date = value
438
        elif bool(value):
439
            self.email_verified = True
440
            self.email_verified_date = timezone.now()
441
        else:
442
            self.email_verified = False
443
            self.email_verified_date = None
444

  
431 445

  
432 446
class DeletedUser(models.Model):
433 447
    deleted = models.DateTimeField(verbose_name=_('Deletion date'), auto_now_add=True)
src/authentic2/forms/registration.py
138 138
            return BaseUserManager.normalize_email(email)
139 139

  
140 140
    def save(self, commit=True):
141
        self.instance.email_verified = True
141
        self.instance.set_email_verified(True)
142 142
        self.instance.is_active = True
143 143
        user = super().save(commit=commit)
144 144
        if commit and app_settings.A2_REGISTRATION_GROUPS:
src/authentic2/manager/user_views.py
485 485

  
486 486
    def form_valid(self, form):
487 487
        if 'email' in form.changed_data:
488
            self.object.email_verified = False
488
            self.object.set_email_verified(False)
489 489
            self.object.save()
490 490
        response = super().form_valid(form)
491 491
        if form.has_changed():
src/authentic2/views.py
246 246
                    raise ValidationError(_('This email is already used by another account.'))
247 247
                old_email = user.email
248 248
                user.email = email
249
                user.email_verified = True
249
                user.set_email_verified(True)
250 250
                user.save()
251 251
                messages.info(
252 252
                    request, _('your request for changing your email for {0} is successful').format(email)
......
873 873

  
874 874
    def form_valid(self, form):
875 875
        # Changing password by mail validate the email
876
        form.user.email_verified = True
876
        form.user.set_email_verified(True)
877 877
        form.save()
878 878
        hooks.call_hooks('event', name='password-reset-confirm', user=form.user, token=self.token, form=form)
879 879
        logger.info('password reset for user %s with token %r', self.user, self.token.uuid)
src/authentic2_auth_oidc/backends.py
310 310
            if getattr(user, attribute) != value:
311 311
                logger.info('auth_oidc: set user %s attribute %s to value %s', user, attribute, value)
312 312
                setattr(user, attribute, value)
313
                if attribute == 'email' and verified:
314
                    user.email_verified = True
313
                if attribute == 'email':
314
                    user.set_email_verified(verified)
315 315
                save_user = True
316 316

  
317 317
        if user.ou != user_ou:
tests/test_all.py
70 70
                'fields': {
71 71
                    'uuid': u.uuid,
72 72
                    'email_verified': False,
73
                    'email_verified_date': None,
73 74
                    'username': 'john.doe',
74 75
                    'email': '',
75 76
                    'first_name': '',
......
123 124
        expected = json.loads(json.dumps(expected, cls=DjangoJSONEncoder))
124 125
        for obj in serializers.deserialize('json', result):
125 126
            obj.save()
126
        self.assertEqual(json.loads(result), expected)
127
        assert json.loads(result) == expected
127 128
        self.assertEqual(User.objects.count(), ucount + 1)
128 129
        self.assertEqual(Attribute.objects.count(), acount + 1)
129 130
        # first_name and last_name attribute value not recreated since they were not dumped
tests/test_api.py
64 64
    'is_active',
65 65
    'modified',
66 66
    'email_verified',
67
    'email_verified_date',
67 68
    'last_account_deletion_alert',
68 69
    'deactivation',
69 70
    'deactivation_reason',
tests/test_migrations.py
46 46
    DeletedUser = new_apps.get_model('custom_user', 'DeletedUser')
47 47
    assert User.objects.count() == 1
48 48
    assert DeletedUser.objects.count() == 1
49

  
50

  
51
def test_migration_custom_user_0028_user_email_verified_date(transactional_db, migration):
52
    old_apps = migration.before([('custom_user', '0027_user_deactivation_reason')])
53

  
54
    User = old_apps.get_model('custom_user', 'User')
55
    User.objects.create(email='john.doe@example.com', email_verified=True)
56

  
57
    new_apps = migration.apply([('custom_user', '0028_user_email_verified_date')])
58
    User = new_apps.get_model('custom_user', 'User')
59
    user = User.objects.get()
60
    assert user.email_verified_date == user.date_joined
tests/test_user_manager.py
918 918

  
919 919

  
920 920
def test_manager_edit_user_email_verified(app, simple_user, superuser_or_admin):
921
    simple_user.email_verified = True
921
    simple_user.set_email_verified(True)
922 922
    simple_user.save()
923 923

  
924 924
    url = '/manage/users/%s/edit/' % simple_user.pk
......
959 959
    resp = app.get('/manage/users/')
960 960
    assert not resp.html.find('span', {'class': 'verified'})
961 961

  
962
    simple_user.email_verified = True
962
    simple_user.set_email_verified(True)
963 963
    simple_user.save()
964 964
    resp = app.get('/manage/users/')
965 965
    assert resp.html.find('span', {'class': 'verified'}).text == simple_user.email
966
-