Project

General

Profile

0001-provisionning-factorize-user-creation-59135.patch

Benjamin Dauvergne, 05 October 2022 04:39 PM

Download (6.28 KB)

View differences:

Subject: [PATCH 1/3] provisionning: factorize user creation (#59135)

 hobo/provisionning/utils.py | 116 +++++++++++++++++++-----------------
 1 file changed, 60 insertions(+), 56 deletions(-)
hobo/provisionning/utils.py
17 17
import hashlib
18 18
import logging
19 19

  
20
from django.contrib.auth import get_user_model
20 21
from django.contrib.auth.models import Group
21 22
from django.db import IntegrityError
22
from django.db.models.query import Q
23 23
from django.db.transaction import atomic
24
from mellon.models import Issuer
24 25

  
25 26
from hobo.agent.common.models import Role
26 27
from hobo.multitenant.utils import provision_user_groups
......
50 51
    return s
51 52

  
52 53

  
54
def get_issuer(entity_id):
55
    issuer, created = Issuer.objects.get_or_create(entity_id=entity_id)
56
    return issuer
57

  
58

  
59
def provision_user(entity_id, o, tries=0):
60
    updated = set()
61
    attributes = {
62
        'first_name': o['first_name'][:30],
63
        'last_name': o['last_name'][:150],
64
        'email': o['email'][:254],
65
        'username': o['uuid'][:150],
66
        'is_superuser': o['is_superuser'],
67
        'is_staff': o['is_superuser'],
68
        'is_active': o.get('is_active', True),
69
    }
70

  
71
    User = get_user_model()
72
    try:
73
        user = User.objects.get(
74
            saml_identifiers__name_id=o['uuid'], saml_identifiers__issuer__entity_id=entity_id
75
        )
76
    except User.DoesNotExist:
77
        user = User()
78

  
79
    for key in attributes:
80
        if getattr(user, key) != attributes[key]:
81
            setattr(user, key, attributes[key])
82
            updated.add(key)
83

  
84
    if not user.id:  # user is new
85
        issuer = get_issuer(entity_id)
86
        try:
87
            with atomic(savepoint=False):
88
                user.save()
89
                user.saml_identifiers.create(issuer=issuer, name_id=o['uuid'])
90
            logger.info('provisionned new user %s', user_str(user))
91
        except IntegrityError:
92
            if tries > 0:
93
                raise
94
            return provision_user(user, o, tries=tries + 1)
95
    elif updated:
96
        user.save()
97
        logger.info('updated user %s(%s)', user_str(user), updated)
98
    return user
99

  
100

  
53 101
class NotificationProcessing:
54 102
    @classmethod
55 103
    def check_valid_notification(cls, notification):
......
80 128

  
81 129
    @classmethod
82 130
    def provision_user(cls, issuer, action, data, full=False):
83
        from django.contrib.auth import get_user_model
84
        from mellon.models import UserSAMLIdentifier
85
        from mellon.models_utils import get_issuer
131
        assert not full  # provisionning all users is dangerous, we prefer deprovision
86 132

  
87 133
        User = get_user_model()
88

  
89
        assert not full  # provisionning all users is dangerous, we prefer deprovision
90 134
        uuids = set()
135

  
91 136
        for o in data:
92
            try:
93
                with atomic():
94
                    if action == 'provision':
95
                        new = False
96
                        updated = set()
97
                        attributes = {
98
                            'first_name': o['first_name'][:30],
99
                            'last_name': o['last_name'][:150],
100
                            'email': o['email'][:254],
101
                            'username': o['uuid'][:150],
102
                            'is_superuser': o['is_superuser'],
103
                            'is_staff': o['is_superuser'],
104
                            'is_active': o.get('is_active', True),
105
                        }
106
                        assert cls.check_valid_user(o)
107
                        try:
108
                            mellon_user = UserSAMLIdentifier.objects.get(
109
                                issuer__entity_id=issuer, name_id=o['uuid']
110
                            )
111
                            user = mellon_user.user
112
                        except UserSAMLIdentifier.DoesNotExist:
113
                            try:
114
                                user = User.objects.get(
115
                                    Q(username=o['uuid'][:30]) | Q(username=o['uuid'][:150])
116
                                )
117
                            except User.DoesNotExist:
118
                                # temp user object
119
                                user = User.objects.create(**attributes)
120
                                new = True
121
                            saml_issuer = get_issuer(issuer)
122
                            mellon_user = UserSAMLIdentifier.objects.create(
123
                                user=user, issuer=saml_issuer, name_id=o['uuid']
124
                            )
125
                        if new:
126
                            logger.info('provisionned new user %s', user_str(user))
127
                        else:
128
                            for key in attributes:
129
                                if getattr(user, key) != attributes[key]:
130
                                    setattr(user, key, attributes[key])
131
                                    updated.add(key)
132
                            if updated:
133
                                user.save()
134
                                logger.info('updated user %s(%s)', user_str(user), updated)
135
                        role_uuids = [role['uuid'] for role in o.get('roles', [])]
136
                        provision_user_groups(user, role_uuids)
137
                    elif action == 'deprovision':
138
                        assert 'uuid' in o
139
                uuids.add(o['uuid'])
140
            except IntegrityError:
141
                raise TryAgain
137
            if action == 'provision':
138
                assert cls.check_valid_user(o)
139
                user = provision_user(issuer, o)
140
                role_uuids = [role['uuid'] for role in o.get('roles', [])]
141
                provision_user_groups(user, role_uuids)
142
            elif action == 'deprovision':
143
                assert 'uuid' in o
144
            uuids.add(o['uuid'])
145

  
142 146
        if (full and action == 'provision') or (action == 'deprovision'):
143 147
            if action == 'deprovision':
144 148
                qs = User.objects.filter(saml_identifiers__name_id__in=uuids)
145
-