feat(members): split username/display_name, sync updates to authentik, add password reset API and refresh docs
This commit is contained in:
@@ -21,6 +21,7 @@ from app.schemas.catalog import (
|
||||
MemberItem,
|
||||
MemberPermissionGroupsResponse,
|
||||
MemberPermissionGroupsUpdateRequest,
|
||||
MemberPasswordResetResponse,
|
||||
MemberUpdateRequest,
|
||||
MemberUpsertRequest,
|
||||
ModuleCreateRequest,
|
||||
@@ -100,7 +101,9 @@ def _generate_unique_key(prefix: str, exists_fn) -> str:
|
||||
|
||||
def _sync_member_to_authentik(
|
||||
*,
|
||||
authentik_sub: str,
|
||||
authentik_sub: str | None,
|
||||
authentik_user_id: int | None,
|
||||
username: str | None,
|
||||
email: str | None,
|
||||
display_name: str | None,
|
||||
is_active: bool,
|
||||
@@ -112,8 +115,10 @@ def _sync_member_to_authentik(
|
||||
result = service.ensure_user(
|
||||
sub=authentik_sub,
|
||||
email=email,
|
||||
username=username,
|
||||
display_name=display_name,
|
||||
is_active=is_active,
|
||||
authentik_user_id=authentik_user_id,
|
||||
)
|
||||
return {
|
||||
"authentik_user_id": result.user_id,
|
||||
@@ -450,7 +455,22 @@ def list_members(
|
||||
) -> dict:
|
||||
users_repo = UsersRepository(db)
|
||||
items, total = users_repo.list(keyword=keyword, limit=limit, offset=offset)
|
||||
return {"items": [MemberItem(id=i.id, authentik_sub=i.authentik_sub, email=i.email, display_name=i.display_name, is_active=i.is_active).model_dump() for i in items], "total": total, "limit": limit, "offset": offset}
|
||||
return {
|
||||
"items": [
|
||||
MemberItem(
|
||||
id=i.id,
|
||||
authentik_sub=i.authentik_sub,
|
||||
username=i.username,
|
||||
email=i.email,
|
||||
display_name=i.display_name,
|
||||
is_active=i.is_active,
|
||||
).model_dump()
|
||||
for i in items
|
||||
],
|
||||
"total": total,
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
}
|
||||
|
||||
|
||||
@router.post("/members/upsert", response_model=MemberItem)
|
||||
@@ -460,13 +480,16 @@ def upsert_member(
|
||||
) -> MemberItem:
|
||||
users_repo = UsersRepository(db)
|
||||
resolved_sub = payload.authentik_sub
|
||||
resolved_username = payload.username
|
||||
authentik_user_id = None
|
||||
if payload.sync_to_authentik:
|
||||
seed_sub = payload.authentik_sub or (payload.email or "")
|
||||
seed_sub = payload.authentik_sub or payload.username
|
||||
if not seed_sub:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="authentik_sub_or_email_required")
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="authentik_sub_or_username_required")
|
||||
sync = _sync_member_to_authentik(
|
||||
authentik_sub=seed_sub,
|
||||
authentik_user_id=authentik_user_id,
|
||||
username=payload.username,
|
||||
email=payload.email,
|
||||
display_name=payload.display_name,
|
||||
is_active=payload.is_active,
|
||||
@@ -478,6 +501,7 @@ def upsert_member(
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="authentik_sub_required")
|
||||
row = users_repo.upsert_by_sub(
|
||||
authentik_sub=resolved_sub,
|
||||
username=resolved_username,
|
||||
email=payload.email,
|
||||
display_name=payload.display_name,
|
||||
is_active=payload.is_active,
|
||||
@@ -486,6 +510,7 @@ def upsert_member(
|
||||
return MemberItem(
|
||||
id=row.id,
|
||||
authentik_sub=row.authentik_sub,
|
||||
username=row.username,
|
||||
email=row.email,
|
||||
display_name=row.display_name,
|
||||
is_active=row.is_active,
|
||||
@@ -504,6 +529,7 @@ def update_member(
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="user_not_found")
|
||||
|
||||
next_email = payload.email if payload.email is not None else row.email
|
||||
next_username = payload.username if payload.username is not None else row.username
|
||||
next_display_name = payload.display_name if payload.display_name is not None else row.display_name
|
||||
next_is_active = payload.is_active if payload.is_active is not None else row.is_active
|
||||
|
||||
@@ -511,6 +537,8 @@ def update_member(
|
||||
if payload.sync_to_authentik:
|
||||
sync = _sync_member_to_authentik(
|
||||
authentik_sub=row.authentik_sub,
|
||||
authentik_user_id=row.authentik_user_id,
|
||||
username=next_username,
|
||||
email=next_email,
|
||||
display_name=next_display_name,
|
||||
is_active=next_is_active,
|
||||
@@ -519,6 +547,7 @@ def update_member(
|
||||
|
||||
row = users_repo.upsert_by_sub(
|
||||
authentik_sub=row.authentik_sub,
|
||||
username=next_username,
|
||||
email=next_email,
|
||||
display_name=next_display_name,
|
||||
is_active=next_is_active,
|
||||
@@ -527,12 +556,40 @@ def update_member(
|
||||
return MemberItem(
|
||||
id=row.id,
|
||||
authentik_sub=row.authentik_sub,
|
||||
username=row.username,
|
||||
email=row.email,
|
||||
display_name=row.display_name,
|
||||
is_active=row.is_active,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/members/{authentik_sub}/password/reset", response_model=MemberPasswordResetResponse)
|
||||
def reset_member_password(
|
||||
authentik_sub: str,
|
||||
db: Session = Depends(get_db),
|
||||
) -> MemberPasswordResetResponse:
|
||||
users_repo = UsersRepository(db)
|
||||
user = users_repo.get_by_sub(authentik_sub)
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="user_not_found")
|
||||
settings = get_settings()
|
||||
service = AuthentikAdminService(settings=settings)
|
||||
result = service.reset_password(
|
||||
authentik_user_id=user.authentik_user_id,
|
||||
email=user.email,
|
||||
username=user.username,
|
||||
)
|
||||
user = users_repo.upsert_by_sub(
|
||||
authentik_sub=user.authentik_sub,
|
||||
username=user.username,
|
||||
email=user.email,
|
||||
display_name=user.display_name,
|
||||
is_active=user.is_active,
|
||||
authentik_user_id=result.user_id,
|
||||
)
|
||||
return MemberPasswordResetResponse(authentik_sub=user.authentik_sub, temporary_password=result.temporary_password)
|
||||
|
||||
|
||||
@router.get("/members/{authentik_sub}/permission-groups", response_model=MemberPermissionGroupsResponse)
|
||||
def get_member_permission_groups(
|
||||
authentik_sub: str,
|
||||
|
||||
Reference in New Issue
Block a user