91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.config import get_settings
|
|
from app.db.session import get_db
|
|
from app.repositories.permissions_repo import PermissionsRepository
|
|
from app.schemas.internal import InternalUpsertUserBySubResponse
|
|
from app.repositories.users_repo import UsersRepository
|
|
from app.schemas.authentik_admin import AuthentikEnsureUserRequest, AuthentikEnsureUserResponse
|
|
from app.schemas.permissions import PermissionSnapshotResponse
|
|
from app.schemas.users import UserUpsertBySubRequest
|
|
from app.security.api_client_auth import require_api_client
|
|
from app.services.authentik_admin_service import AuthentikAdminService
|
|
from app.services.permission_service import PermissionService
|
|
|
|
router = APIRouter(prefix="/internal", tags=["internal"], dependencies=[Depends(require_api_client)])
|
|
|
|
|
|
@router.post("/users/upsert-by-sub", response_model=InternalUpsertUserBySubResponse)
|
|
def upsert_user_by_sub(
|
|
payload: UserUpsertBySubRequest,
|
|
db: Session = Depends(get_db),
|
|
) -> InternalUpsertUserBySubResponse:
|
|
repo = UsersRepository(db)
|
|
user = repo.upsert_by_sub(
|
|
user_sub=payload.user_sub,
|
|
username=payload.username,
|
|
email=payload.email,
|
|
display_name=payload.display_name,
|
|
is_active=payload.is_active,
|
|
)
|
|
return {
|
|
"id": user.id,
|
|
"user_sub": user.user_sub,
|
|
"idp_user_id": user.idp_user_id,
|
|
"username": user.username,
|
|
"email": user.email,
|
|
"display_name": user.display_name,
|
|
"is_active": user.is_active,
|
|
}
|
|
|
|
|
|
@router.get("/permissions/{user_sub}/snapshot", response_model=PermissionSnapshotResponse)
|
|
def get_permission_snapshot(
|
|
user_sub: str,
|
|
db: Session = Depends(get_db),
|
|
) -> PermissionSnapshotResponse:
|
|
users_repo = UsersRepository(db)
|
|
perms_repo = PermissionsRepository(db)
|
|
|
|
user = users_repo.get_by_sub(user_sub)
|
|
if user is None:
|
|
return PermissionSnapshotResponse(user_sub=user_sub, permissions=[])
|
|
|
|
permissions = perms_repo.list_by_user(user.id, user.user_sub)
|
|
return PermissionService.build_snapshot(user_sub=user_sub, permissions=permissions)
|
|
|
|
|
|
@router.post("/authentik/users/ensure", response_model=AuthentikEnsureUserResponse)
|
|
@router.post("/idp/users/ensure", response_model=AuthentikEnsureUserResponse)
|
|
@router.post("/keycloak/users/ensure", response_model=AuthentikEnsureUserResponse)
|
|
def ensure_authentik_user(
|
|
payload: AuthentikEnsureUserRequest,
|
|
db: Session = Depends(get_db),
|
|
) -> AuthentikEnsureUserResponse:
|
|
settings = get_settings()
|
|
authentik_service = AuthentikAdminService(settings=settings)
|
|
sync_result = authentik_service.ensure_user(
|
|
sub=payload.user_sub,
|
|
email=payload.email,
|
|
username=payload.username,
|
|
display_name=payload.display_name,
|
|
is_active=payload.is_active,
|
|
)
|
|
|
|
users_repo = UsersRepository(db)
|
|
resolved_sub = payload.user_sub or ""
|
|
if sync_result.user_sub:
|
|
resolved_sub = sync_result.user_sub
|
|
if not resolved_sub:
|
|
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail="authentik_missing_sub")
|
|
users_repo.upsert_by_sub(
|
|
user_sub=resolved_sub,
|
|
username=payload.username,
|
|
email=payload.email,
|
|
display_name=payload.display_name,
|
|
is_active=payload.is_active,
|
|
idp_user_id=sync_result.user_id,
|
|
)
|
|
return AuthentikEnsureUserResponse(idp_user_id=sync_result.user_id, action=sync_result.action)
|