67 lines
2.2 KiB
Python
67 lines
2.2 KiB
Python
|
|
"""Session establishment after verified identity claims."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from django.conf import settings
|
||
|
|
from django.contrib.auth import login
|
||
|
|
from django.http import HttpRequest
|
||
|
|
from django.utils import timezone
|
||
|
|
|
||
|
|
from coulomb_social.apps.members.models import Member, User
|
||
|
|
|
||
|
|
from .user_engine import IdentityClaims, get_user_engine_client
|
||
|
|
|
||
|
|
|
||
|
|
def establish_session(request: HttpRequest, claims: IdentityClaims) -> Member:
|
||
|
|
"""Link platform identity → Member, log Django user in. No passwords."""
|
||
|
|
tenant_id = settings.DEFAULT_TENANT_ID
|
||
|
|
application_id = settings.USER_ENGINE_APPLICATION_ID
|
||
|
|
link = get_user_engine_client().link_or_create(
|
||
|
|
claims, tenant_id=tenant_id, application_id=application_id
|
||
|
|
)
|
||
|
|
|
||
|
|
member = Member.objects.filter(issuer=claims.issuer, subject=claims.subject).first()
|
||
|
|
display = claims.name or claims.preferred_username or claims.email or claims.subject
|
||
|
|
username = f"{claims.subject}@{_issuer_slug(claims.issuer)}"[:255]
|
||
|
|
|
||
|
|
if member is None:
|
||
|
|
user = User.objects.create_user(
|
||
|
|
username=username,
|
||
|
|
email=claims.email or "",
|
||
|
|
full_name=display,
|
||
|
|
)
|
||
|
|
member = Member.objects.create(
|
||
|
|
tenant_id=tenant_id,
|
||
|
|
user=user,
|
||
|
|
user_engine_user_id=link.user_id,
|
||
|
|
issuer=claims.issuer,
|
||
|
|
subject=claims.subject,
|
||
|
|
display_name=display,
|
||
|
|
email=claims.email or "",
|
||
|
|
)
|
||
|
|
else:
|
||
|
|
user = member.user
|
||
|
|
user.email = claims.email or user.email
|
||
|
|
user.full_name = display or user.full_name
|
||
|
|
user.save(update_fields=["email", "full_name"])
|
||
|
|
member.display_name = display
|
||
|
|
member.email = claims.email or member.email
|
||
|
|
member.user_engine_user_id = link.user_id
|
||
|
|
member.tenant_id = tenant_id
|
||
|
|
|
||
|
|
member.last_login_at = timezone.now()
|
||
|
|
member.save()
|
||
|
|
|
||
|
|
login(request, user, backend="django.contrib.auth.backends.ModelBackend")
|
||
|
|
return member
|
||
|
|
|
||
|
|
|
||
|
|
def _issuer_slug(issuer: str) -> str:
|
||
|
|
return (
|
||
|
|
issuer.replace("https://", "")
|
||
|
|
.replace("http://", "")
|
||
|
|
.replace("/", "_")
|
||
|
|
.replace(":", "_")[:64]
|
||
|
|
or "issuer"
|
||
|
|
)
|