111 |
111 |
|
112 |
112 |
_next_url = None
|
113 |
113 |
display_message_on_redirect = False
|
|
114 |
fc_account = None
|
114 |
115 |
|
115 |
116 |
@property
|
116 |
117 |
def next_url(self):
|
... | ... | |
333 |
334 |
|
334 |
335 |
def link(self, request):
|
335 |
336 |
'''Request an access grant code and associate it to the current user'''
|
336 |
|
try:
|
337 |
|
self.fc_account, created = models.FcAccount.objects.get_or_create(
|
338 |
|
sub=self.sub,
|
339 |
|
user=request.user,
|
340 |
|
order=0,
|
341 |
|
defaults={
|
342 |
|
'token': json.dumps(self.token),
|
343 |
|
'user_info': json.dumps(self.user_info),
|
344 |
|
},
|
345 |
|
)
|
|
337 |
|
|
338 |
created = False
|
|
339 |
with transaction.atomic():
|
|
340 |
Lock.lock_identifier(identifier=self.sub)
|
|
341 |
|
346 |
342 |
# Prevent adding a link with an FC account already linked with another user.
|
347 |
|
except IntegrityError:
|
348 |
|
# unique index check failed, find why.
|
349 |
|
return self.uniqueness_check_failed(request)
|
|
343 |
if not models.FcAccount.objects.filter(sub=self.sub).exclude(user=request.user).count():
|
|
344 |
self.fc_account, created = models.FcAccount.objects.get_or_create(
|
|
345 |
sub=self.sub,
|
|
346 |
user=request.user,
|
|
347 |
order=0,
|
|
348 |
defaults={
|
|
349 |
'token': json.dumps(self.token),
|
|
350 |
'user_info': json.dumps(self.user_info),
|
|
351 |
},
|
|
352 |
)
|
|
353 |
else:
|
|
354 |
# unique index check failed, find why.
|
|
355 |
return self.uniqueness_check_failed(request)
|
350 |
356 |
|
351 |
357 |
if created:
|
352 |
358 |
logger.info('auth_fc: link created sub %s', self.sub)
|
... | ... | |
355 |
361 |
)
|
356 |
362 |
hooks.call_hooks('event', name='fc-link', user=request.user, sub=self.sub, request=request)
|
357 |
363 |
else:
|
358 |
|
if self.fc_account.created <= request.user.last_login:
|
|
364 |
if self.fc_account and self.fc_account.created <= request.user.last_login:
|
359 |
365 |
utils_misc.record_authentication_event(request, 'france-connect')
|
360 |
366 |
self.update_user_info(request.user, self.user_info)
|
361 |
367 |
return self.redirect()
|
... | ... | |
450 |
456 |
user = User.objects.create(ou=get_default_ou())
|
451 |
457 |
created = True
|
452 |
458 |
|
453 |
|
try:
|
454 |
|
if created:
|
455 |
|
user.set_unusable_password()
|
456 |
|
user.save()
|
457 |
|
|
458 |
|
# As we intercept IntegrityError and we can never be sure if we are
|
459 |
|
# in a transaction or not, we must use one to prevent later SQL
|
460 |
|
# queries to fail.
|
461 |
|
with transaction.atomic():
|
|
459 |
if created:
|
|
460 |
user.set_unusable_password()
|
|
461 |
user.save()
|
|
462 |
|
|
463 |
# As we intercept IntegrityError and we can never be sure if we are
|
|
464 |
# in a transaction or not, we must use one to prevent later SQL
|
|
465 |
# queries to fail.
|
|
466 |
with transaction.atomic():
|
|
467 |
|
|
468 |
Lock.lock_identifier(identifier=sub)
|
|
469 |
|
|
470 |
# reshuffle existing accounts order
|
|
471 |
Lock.lock_email(email=user.email)
|
|
472 |
for account in models.FcAccount.objects.filter(user=user).order_by('-order'):
|
|
473 |
account.order += 1
|
|
474 |
account.save()
|
|
475 |
|
|
476 |
if not models.FcAccount.objects.filter(sub=sub).count():
|
462 |
477 |
models.FcAccount.objects.create(
|
463 |
478 |
user=user,
|
464 |
479 |
sub=sub,
|
... | ... | |
466 |
481 |
token=json.dumps(token),
|
467 |
482 |
user_info=json.dumps(user_info),
|
468 |
483 |
)
|
469 |
|
except IntegrityError:
|
470 |
|
# uniqueness check failed, as the user is new, it can only mean that the sub is not unique
|
471 |
|
# let's try again
|
472 |
|
if created:
|
473 |
|
user.delete()
|
474 |
|
return utils_misc.authenticate(request, sub=sub, token=token, user_info=user_info), False
|
475 |
|
except Exception:
|
476 |
|
# if anything unexpected happen and user was created, delete it and re-raise
|
477 |
|
if created:
|
478 |
|
user.delete()
|
479 |
|
raise
|
|
484 |
if created:
|
|
485 |
logger.info('auth_fc: new account "%s" created with FranceConnect sub "%s"', user, sub)
|
|
486 |
hooks.call_hooks('event', name='fc-create', user=user, sub=sub, request=request)
|
|
487 |
# FC account creation does not rely on the registration_completion generic view.
|
|
488 |
# Registration event has to be recorded here:
|
|
489 |
request.journal.record('user.registration', user=user, how='france-connect')
|
480 |
490 |
else:
|
481 |
|
if created:
|
482 |
|
logger.info('auth_fc: new account "%s" created with FranceConnect sub "%s"', user, sub)
|
483 |
|
hooks.call_hooks('event', name='fc-create', user=user, sub=sub, request=request)
|
484 |
|
# FC account creation does not rely on the registration_completion generic view.
|
485 |
|
# Registration event has to be recorded here:
|
486 |
|
request.journal.record('user.registration', user=user, how='france-connect')
|
487 |
|
else:
|
488 |
|
logger.info('auth_fc: existing account "%s" linked to FranceConnect sub "%s"', user, sub)
|
489 |
|
hooks.call_hooks('event', name='fc-link', user=user, sub=sub, request=request)
|
|
491 |
logger.info('auth_fc: existing account "%s" linked to FranceConnect sub "%s"', user, sub)
|
|
492 |
hooks.call_hooks('event', name='fc-link', user=user, sub=sub, request=request)
|
490 |
493 |
|
491 |
494 |
authenticated_user = utils_misc.authenticate(request, sub=sub, user_info=user_info, token=token)
|
492 |
495 |
return authenticated_user, created
|
... | ... | |
528 |
531 |
if not a2_app_settings.A2_EMAIL_IS_UNIQUE:
|
529 |
532 |
qs = qs.filter(ou=ou)
|
530 |
533 |
|
531 |
|
Lock.lock_email(email)
|
532 |
|
try:
|
533 |
|
user = qs.get_by_email(email)
|
534 |
|
except User.DoesNotExist:
|
535 |
|
return User.objects.create(ou=ou, email=email), True
|
|
534 |
with transaction.atomic():
|
|
535 |
Lock.lock_email(email)
|
|
536 |
|
|
537 |
users = qs.filter_by_email(email)
|
|
538 |
if not users:
|
|
539 |
return User.objects.create(ou=ou, email=email), True
|
|
540 |
|
|
541 |
if len(users) > 1:
|
|
542 |
# oops, something went wrong there, several users with the same
|
|
543 |
# email within the same organization unit, aborting.
|
|
544 |
return None, False
|
536 |
545 |
|
|
546 |
user = users[0]
|
537 |
547 |
if user.ou != ou:
|
538 |
548 |
raise UserOutsideDefaultOu
|
539 |
549 |
return user, False
|
540 |
|
-
|