0001-provisionning-log-received-provisionning-messages-an.patch
hobo/agent/common/management/commands/hobo_notify.py | ||
---|---|---|
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 | 17 |
import json |
18 |
import logging |
|
18 | 19 |
import os |
19 | 20 |
import sys |
20 | 21 | |
... | ... | |
24 | 25 |
from hobo.multitenant.middleware import TenantMiddleware |
25 | 26 |
from hobo.provisionning.utils import NotificationProcessing, TryAgain |
26 | 27 | |
28 |
logger = logging.getLogger(__name__) |
|
29 | ||
27 | 30 | |
28 | 31 |
class Command(BaseCommand, NotificationProcessing): |
29 | 32 |
requires_system_checks = False |
... | ... | |
60 | 63 |
if entity_id not in audience: |
61 | 64 |
return |
62 | 65 |
object_type = notification['objects']['@type'] |
66 |
msg = 'received request for %sing %%d %%s objects (Celery)' % action |
|
67 |
logger.info(msg, len(notification['objects']['data']), object_type) |
|
63 | 68 |
for i in range(20): |
64 | 69 |
try: |
65 | 70 |
getattr(cls, 'provision_' + object_type)( |
hobo/multitenant/utils.py | ||
---|---|---|
12 | 12 |
return |
13 | 13 |
logger = logging.getLogger(__name__) |
14 | 14 | |
15 |
existing_pks = user.groups.values_list('pk', flat=True) |
|
16 |
for role in Role.objects.filter(uuid__in=uuids).exclude(pk__in=existing_pks): |
|
15 |
existing_pks = set(user.groups.values_list('pk', flat=True)) |
|
16 |
uuids = set(uuids) |
|
17 |
not_found = uuids.copy() |
|
18 |
for role in Role.objects.filter(uuid__in=uuids): |
|
19 |
not_found.discard(role.uuid) |
|
20 |
if role.pk in existing_pks: |
|
21 |
continue |
|
17 | 22 |
user.groups.through.objects.get_or_create(group=role, user=user) |
18 |
logger.info(u'adding role %s to %s (%s)', role, user, user.pk)
|
|
23 |
logger.info('adding role %s to %s (%s)', role, user, user.pk) |
|
19 | 24 |
qs = user.groups.through.objects.filter(user=user, group__role__isnull=False).exclude( |
20 | 25 |
group__role__uuid__in=uuids |
21 | 26 |
) |
... | ... | |
26 | 31 |
except DatabaseError: |
27 | 32 |
pass |
28 | 33 |
else: |
29 |
logger.info(u'removed role %s from %s (%s)', rel.group, user, user.pk) |
|
34 |
logger.info('removed role %s from %s (%s)', rel.group, user, user.pk) |
|
35 |
for uuid in not_found: |
|
36 |
logger.warning('role %s of user %s does not exist', uuid, user) |
hobo/provisionning/middleware.py | ||
---|---|---|
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 | 17 |
import json |
18 |
import logging |
|
18 | 19 | |
19 | 20 |
from django.conf import settings |
20 | 21 |
from django.http import HttpResponseBadRequest, HttpResponseForbidden, JsonResponse |
... | ... | |
25 | 26 |
from hobo.provisionning.utils import NotificationProcessing, TryAgain |
26 | 27 |
from hobo.rest_authentication import PublikAuthentication, PublikAuthenticationFailed |
27 | 28 | |
29 |
logger = logging.getLogger(__name__) |
|
30 | ||
28 | 31 | |
29 | 32 |
class ProvisionningMiddleware(MiddlewareMixin, NotificationProcessing): |
30 | 33 |
def process_request(self, request): |
... | ... | |
51 | 54 |
return HttpResponseBadRequest() |
52 | 55 |
full = notification['full'] if 'full' in notification else False |
53 | 56 | |
57 |
msg = 'received request for %sing %%d %%s objects (HTTP)' % action |
|
58 |
logger.info(msg, len(notification['objects']['data']), object_type) |
|
59 | ||
54 | 60 |
for i in range(20): |
55 | 61 |
try: |
56 | 62 |
getattr(self, 'provision_' + object_type)( |
hobo/provisionning/utils.py | ||
---|---|---|
26 | 26 |
from hobo.agent.common.models import Role |
27 | 27 |
from hobo.multitenant.utils import provision_user_groups |
28 | 28 | |
29 |
logger = logging.getLogger(__name__) |
|
30 | ||
29 | 31 | |
30 | 32 |
class TryAgain(Exception): |
31 | 33 |
pass |
... | ... | |
72 | 74 |
try: |
73 | 75 |
with atomic(): |
74 | 76 |
if action == 'provision': |
77 |
new = False |
|
75 | 78 |
assert cls.check_valid_user(o) |
76 | 79 |
try: |
77 | 80 |
mellon_user = UserSAMLIdentifier.objects.get(issuer=issuer, name_id=o['uuid']) |
... | ... | |
85 | 88 |
# temp user object |
86 | 89 |
random_uid = str(random.randint(1, 10000000000000)) |
87 | 90 |
user = User.objects.create(username=random_uid) |
91 |
new = True |
|
88 | 92 |
mellon_user = UserSAMLIdentifier.objects.create( |
89 | 93 |
user=user, issuer=issuer, name_id=o['uuid'] |
90 | 94 |
) |
... | ... | |
98 | 102 |
user.save() |
99 | 103 |
role_uuids = [role['uuid'] for role in o.get('roles', [])] |
100 | 104 |
provision_user_groups(user, role_uuids) |
105 |
msg = '%s user %%s' % ('provisionned new' if new else 'updated') |
|
106 |
user_description = '' |
|
107 |
if user.email: |
|
108 |
user_description += user.email + ' ' |
|
109 |
user_description += '(%s)' % o['uuid'] |
|
110 |
logger.info(msg, user_description) |
|
101 | 111 |
elif action == 'deprovision': |
102 | 112 |
assert 'uuid' in o |
103 | 113 |
uuids.add(o['uuid']) |
104 | 114 |
except IntegrityError: |
105 | 115 |
raise TryAgain |
106 | 116 |
if full and action == 'provision': |
107 |
for usi in UserSAMLIdentifier.objects.exclude(name_id__in=uuids): |
|
117 |
qs = UserSAMLIdentifier.objects.exclude(name_id__in=uuids) |
|
118 |
logger.info( |
|
119 |
'deprovisionning users %s', |
|
120 |
', '.join( |
|
121 |
((email + ' ' if email else '') + '(%s)' % username) |
|
122 |
for email, username in qs.values_list('email', 'username') |
|
123 |
), |
|
124 |
) |
|
125 |
for usi in qs: |
|
108 | 126 |
usi.user.delete() |
109 | 127 |
elif action == 'deprovision': |
110 |
for user in User.objects.filter(saml_identifiers__name_id__in=uuids): |
|
128 |
qs = User.objects.filter(saml_identifiers__name_id__in=uuids) |
|
129 |
for user in qs: |
|
111 | 130 |
user.delete() |
131 |
logger.info( |
|
132 |
'deprovisionning users %s', |
|
133 |
', '.join( |
|
134 |
((email + ' ' if email else '') + '(%s)' % username) |
|
135 |
for email, username in qs.values_list('email', 'username') |
|
136 |
), |
|
137 |
) |
|
112 | 138 | |
113 | 139 |
group_name_max_length = Group._meta.get_field('name').max_length |
114 | 140 | |
... | ... | |
125 | 151 | |
126 | 152 |
@classmethod |
127 | 153 |
def provision_role(cls, issuer, action, data, full=False): |
128 |
logger = logging.getLogger(__name__) |
|
129 | 154 |
uuids = set() |
130 | 155 |
for o in data: |
131 | 156 |
assert 'uuid' in o |
132 | 157 |
uuids.add(o['uuid']) |
133 | 158 |
if action == 'provision': |
159 |
created = False |
|
160 |
save = False |
|
134 | 161 |
assert cls.check_valid_role(o) |
135 | 162 |
role_name = cls.truncate_role_name(o['name']) |
136 | 163 |
try: |
137 | 164 |
role = Role.objects.get(uuid=o['uuid']) |
138 |
created = False |
|
139 | 165 |
except Role.DoesNotExist: |
140 | 166 |
try: |
141 | 167 |
with atomic(): |
... | ... | |
144 | 170 |
defaults={ |
145 | 171 |
'uuid': o['uuid'], |
146 | 172 |
'description': o['description'], |
147 |
'details': o.get('details', u''),
|
|
173 |
'details': o.get('details', ''), |
|
148 | 174 |
'emails': o.get('emails', []), |
149 | 175 |
'emails_to_members': o.get('emails_to_members', True), |
150 | 176 |
}, |
151 | 177 |
) |
152 | 178 |
except IntegrityError: |
153 | 179 |
# Can happen if uuid and name already exist |
154 |
logger.error(u'cannot provision role "%s" (%s)', o['name'], o['uuid'])
|
|
180 |
logger.error('cannot provision role "%s" (%s)', o['name'], o['uuid']) |
|
155 | 181 |
continue |
156 | 182 |
if not created: |
157 |
save = False |
|
158 | 183 |
if role.name != role_name: |
159 | 184 |
role.name = role_name |
160 | 185 |
save = True |
... | ... | |
164 | 189 |
if role.description != o['description']: |
165 | 190 |
role.description = o['description'] |
166 | 191 |
save = True |
167 |
if role.details != o.get('details', u''):
|
|
168 |
role.details = o.get('details', u'')
|
|
192 |
if role.details != o.get('details', ''): |
|
193 |
role.details = o.get('details', '') |
|
169 | 194 |
save = True |
170 | 195 |
if role.emails != o.get('emails', []): |
171 | 196 |
role.emails = o.get('emails', []) |
... | ... | |
179 | 204 |
role.save() |
180 | 205 |
except IntegrityError: |
181 | 206 |
# Can happen if uuid and name already exist |
182 |
logger.error(u'cannot provision role "%s" (%s)', o['name'], o['uuid'])
|
|
207 |
logger.error('cannot provision role "%s" (%s)', o['name'], o['uuid']) |
|
183 | 208 |
continue |
209 |
if created: |
|
210 |
logger.info('provisionned new role %s (%s)', o['name'], o['uuid']) |
|
211 |
if save: |
|
212 |
logger.info('updated role %s (%s)', o['name'], o['uuid']) |
|
184 | 213 |
if full and action == 'provision': |
185 |
for role in Role.objects.exclude(uuid__in=uuids): |
|
214 |
qs = Role.objects.exclude(uuid__in=uuids) |
|
215 |
logger.info( |
|
216 |
'deprovisionning roles %s', |
|
217 |
', '.join('%s (%s)' % (name, uuid) for name, uuid in qs.values_list('name', 'uuid')), |
|
218 |
) |
|
219 |
for role in qs: |
|
186 | 220 |
role.delete() |
187 | 221 |
elif action == 'deprovision': |
188 |
for role in Role.objects.filter(uuid__in=uuids): |
|
222 |
qs = Role.objects.filter(uuid__in=uuids) |
|
223 |
logger.info( |
|
224 |
'deprovisionning roles %s', |
|
225 |
', '.join('%s (%s)' % (name, uuid) for name, uuid in qs.values_list('name', 'uuid')), |
|
226 |
) |
|
227 |
for role in qs: |
|
189 | 228 |
role.delete() |
190 |
- |