Projet

Général

Profil

0002-csv_import-allow-setting-user-password-and-sending-m.patch

Valentin Deniaud, 25 novembre 2019 14:57

Télécharger (6,16 ko)

Voir les différences:

Subject: [PATCH 2/2] csv_import: allow setting user password and sending mail
 (#35774)

 src/authentic2/csv_import.py | 39 ++++++++++++++++++++++++++++++--
 tests/test_csv_import.py     | 44 +++++++++++++++++++++++++++++++++++-
 2 files changed, 80 insertions(+), 3 deletions(-)
src/authentic2/csv_import.py
36 36
from authentic2.a2_rbac.utils import get_default_ou
37 37
from authentic2.custom_user.models import User
38 38
from authentic2.forms.profile import modelform_factory, BaseUserForm
39
from authentic2.models import Attribute, AttributeValue, UserExternalId
39
from authentic2.models import Attribute, AttributeValue, UserExternalId, PasswordReset
40
from authentic2.utils import (send_password_reset_mail, generate_password,
41
                              send_templated_mail)
40 42

  
41 43
Role = get_role_model()
42 44

  
......
197 199
SOURCE_COLUMNS = set([SOURCE_NAME, SOURCE_ID])
198 200
ROLE_NAME = '_role_name'
199 201
ROLE_SLUG = '_role_slug'
200
SPECIAL_COLUMNS = SOURCE_COLUMNS | {ROLE_NAME, ROLE_SLUG}
202
REGISTRATION = '@registration'
203
REGISTRATION_RESET_EMAIL = 'send-set-password-link'
204
REGISTRATION_PASSWORD_EMAIL = 'send-password'
205
SPECIAL_COLUMNS = SOURCE_COLUMNS | {ROLE_NAME, ROLE_SLUG, REGISTRATION}
201 206

  
202 207

  
203 208
class ImportUserForm(BaseUserForm):
......
207 212
    locals()[ROLE_SLUG] = forms.CharField(
208 213
        label=_('Role slug'),
209 214
        required=False)
215
    choices = [
216
        (REGISTRATION_RESET_EMAIL, _('Email user so they can set a password')),
217
        (REGISTRATION_PASSWORD_EMAIL, _('Email user with a password they will have to change')),
218
    ]
219
    locals()[REGISTRATION] = forms.ChoiceField(
220
        choices,
221
        label=_('Registration option'),
222
        required=False)
210 223

  
211 224
    def clean(self):
212 225
        super(BaseUserForm, self).clean()
......
593 606

  
594 607
        if not user:
595 608
            user = User(ou=self.ou)
609
            user.set_password(generate_password())
596 610

  
597 611
        for cell in row.cells:
598 612
            if not cell.header.field:
......
639 653
                continue
640 654
            if cell.header.name in {ROLE_NAME, ROLE_SLUG}:
641 655
                success &= self.add_role(cell, user, do_clear=True)
656
            elif cell.header.name == REGISTRATION and row.action == 'create':
657
                success &= self.registration_option(cell, user)
642 658

  
643 659
        setattr(self, row.action + 'd', getattr(self, row.action + 'd') + 1)
644 660
        return success
......
664 680
            user.roles.add(role)
665 681
        cell.action = 'updated'
666 682
        return True
683

  
684
    def registration_option(self, cell, user):
685
        if cell.value == REGISTRATION_RESET_EMAIL:
686
            send_password_reset_mail(
687
                user,
688
                template_names=['authentic2/manager/user_create_registration_email',
689
                                'authentic2/password_reset'],
690
                next_url='/accounts/',
691
                context={'user': user})
692
        elif cell.value == REGISTRATION_PASSWORD_EMAIL:
693
            new_password = generate_password()
694
            user.set_password(new_password)
695
            user.save()
696
            PasswordReset.objects.get_or_create(user=user)
697
            send_templated_mail(
698
                user,
699
                'authentic2/manager/new-account-notification',
700
                context={'new_password': new_password, 'user': user})
701
        return True
tests/test_csv_import.py
21 21

  
22 22
import io
23 23

  
24
from django.core import mail
25

  
24 26
from django_rbac.utils import get_role_model
25 27

  
26 28
from authentic2.custom_user.models import User
27
from authentic2.models import Attribute
29
from authentic2.models import Attribute, PasswordReset
28 30
from authentic2.a2_rbac.utils import get_default_ou
29 31

  
30 32
from authentic2.csv_import import CsvImporter, UserCsvImporter, CsvHeader, Error, LineError
......
164 166
    assert thomas.last_name == 'Noël'
165 167
    assert thomas.attributes.last_name == 'Noël'
166 168
    assert thomas.attributes.phone == '1234'
169
    assert thomas.password
167 170

  
168 171
    fpeters = User.objects.get(email='fpeters@entrouvert.com')
169 172
    assert fpeters.ou == get_default_ou()
......
476 479
    assert not importer.run()
477 480
    assert importer.has_errors
478 481
    assert importer.errors[0].code == 'invalid-role-column'
482

  
483

  
484
def test_csv_registration_options(profile, user_csv_importer_factory):
485
    content = '''email key,first_name,last_name,@registration
486
tnoel@entrouvert.com,Thomas,Noël,'''
487

  
488
    importer = user_csv_importer_factory(content + 'send-password')
489
    assert importer.run()
490
    thomas = User.objects.get(email='tnoel@entrouvert.com')
491
    assert len(mail.outbox) == 1
492
    assert PasswordReset.objects.get(user=thomas)
493

  
494
    del mail.outbox[0]
495
    password = thomas.password
496
    importer = user_csv_importer_factory(content + 'send-password')
497
    assert importer.run()
498
    thomas.refresh_from_db()
499
    assert thomas.password == password
500
    assert not mail.outbox
501

  
502
    thomas.delete()
503
    assert not mail.outbox
504
    importer = user_csv_importer_factory(content + 'send-set-password-link')
505
    assert importer.run()
506
    thomas = User.objects.get(email='tnoel@entrouvert.com')
507
    assert len(mail.outbox) == 1
508

  
509
    password = thomas.password
510
    del mail.outbox[0]
511
    importer = user_csv_importer_factory(content + 'send-set-password-link')
512
    assert importer.run()
513
    thomas.refresh_from_db()
514
    assert thomas.password == password
515
    assert not mail.outbox
516

  
517
    importer = user_csv_importer_factory(content + 'invalid-option')
518
    assert importer.run()
519
    assert importer.has_errors
520
    assert importer.rows[0].cells[-1].errors[0].code == 'data-error'
479
-