"""Sharing a document with departments beyond its own. Management, not new permission logic: the read filter's EXISTS branch already unions `doc_permissions` in, so this endpoint only maintains those rows. Grants are evaluated live against the table, which is why nothing is reindexed here. """ import uuid from typing import Annotated from fastapi import Depends from sqlalchemy import delete, select from sqlalchemy.ext.asyncio import AsyncSession from app.api.documents.access import ( guard_self_lockout, readable_document, require_author_or_admin, ) from app.api.documents.routing import documents_router from app.api.documents.schemas import DocumentDepartments, DocumentDetail from app.api.documents.view import full_detail, granted_department_ids from app.auth.deps import get_current_user from app.db import get_db from app.errors import ApiError from app.models import Department, DocPermission, PermissionLevel, User router = documents_router() @router.put("/{document_id}/departments") async def set_shared_departments( document_id: uuid.UUID, body: DocumentDepartments, user: Annotated[User, Depends(get_current_user)], db: Annotated[AsyncSession, Depends(get_db)], ) -> DocumentDetail: """Replace the full set of ADDITIONAL departments this document is shared with. Author or admin only.""" document = await readable_document(db, document_id, user) require_author_or_admin(document, user) requested = set(body.department_ids) # A document is never "shared with" its own owning department. requested.discard(document.department_id) if requested: found = set( ( await db.execute( select(Department.id).where(Department.id.in_(requested)) ) ) .scalars() .all() ) if requested - found: raise ApiError(404, "One or more departments do not exist.", "not_found") # Removing a grant can drop the editing admin's own department access. guard_self_lockout( user, author_id=document.author_id, visibility=document.visibility, department_id=document.department_id, granted_department_ids=requested, confirm=bool(body.confirm_lockout), ) existing = await granted_department_ids(db, document.id) for dept_id in existing - requested: await db.execute( delete(DocPermission).where( DocPermission.document_id == document.id, DocPermission.department_id == dept_id, ) ) for dept_id in requested - existing: db.add( DocPermission( document_id=document.id, department_id=dept_id, level=PermissionLevel.read, ) ) await db.commit() return await full_detail(db, document, user)