Adding LDAP support

This commit is contained in:
Ian Roddis committed 2026-07-19 12:02:41 -03:00
1 parent d60ad42f0c
commit f2b99089ea
17 files changed
+541 -23

No files matched your search

+51 -1
View File
@@ -1,7 +1,7 @@
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.security import hash_password, verify_password
from app.core.security import hash_password, make_unusable_password, verify_password
from app.models.role import Role
from app.models.user import User
@@ -32,6 +32,13 @@ async def _resolve_roles(db: AsyncSession, role_ids: list[int]) -> list[Role]:
return list(result.scalars().all())
async def _resolve_roles_by_name(db: AsyncSession, names: list[str]) -> list[Role]:
if not names:
return []
result = await db.execute(select(Role).where(Role.name.in_(names)))
return list(result.scalars().all())
async def create(
db: AsyncSession,
*,
@@ -40,12 +47,14 @@ async def create(
full_name: str | None = None,
is_superuser: bool = False,
role_ids: list[int] | None = None,
auth_provider: str = "local",
) -> User:
user = User(
email=email,
hashed_password=hash_password(password),
full_name=full_name,
is_superuser=is_superuser,
auth_provider=auth_provider,
roles=await _resolve_roles(db, role_ids or []),
)
db.add(user)
@@ -54,6 +63,47 @@ async def create(
return user
async def upsert_ldap_user(
db: AsyncSession,
*,
email: str,
full_name: str | None = None,
default_role_names: list[str] | None = None,
) -> User:
"""Provision (or refresh) the local row for an LDAP-authenticated user.
On first login the user is created with an unusable local password (so
password auth can never succeed) and the configured default roles. On later
logins the existing row is reused; only ``full_name`` is synced from the
directory. Roles assigned afterwards in the admin UI are preserved.
"""
user = await get_by_email(db, email)
if user is None:
user = User(
email=email,
hashed_password=make_unusable_password(),
full_name=full_name,
auth_provider="ldap",
roles=await _resolve_roles_by_name(db, default_role_names or []),
)
db.add(user)
await db.commit()
await db.refresh(user)
return user
changed = False
if user.auth_provider != "ldap":
user.auth_provider = "ldap"
changed = True
if full_name and user.full_name != full_name:
user.full_name = full_name
changed = True
if changed:
await db.commit()
await db.refresh(user)
return user
async def update(db: AsyncSession, user: User, data: dict) -> User:
if "password" in data and data["password"]:
user.hashed_password = hash_password(data.pop("password"))