feat: document delete permissions + three-dots menu portal fix

- Add can_delete column to document_shares (migration 0005)
- Inject x-user-is-admin header from backend proxy to doc-service
- Add get_user_is_admin() dep in doc-service
- Delete endpoint now allows: owner, admin, or group member with can_delete=true
- Watch documents (user_id='watch') deletable by admins only
- DocumentOut gains viewer_can_delete (computed per-request)
- Share UI: 'Allow group members to delete' checkbox + trash badge on shares
- RowActionsMenu dropdown portaled to document.body — fixes overflow-hidden clipping
- Delete mutation onError handler — no more silent failures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-04-18 21:39:01 +02:00
parent 05d79d3d21
commit 6e5e5c08bf
13 changed files with 239 additions and 55 deletions
+5 -2
View File
@@ -50,13 +50,16 @@ _HOP_BY_HOP = frozenset([
_STRIP_RESPONSE = frozenset([*_HOP_BY_HOP, "content-length", "content-type"])
async def _forward_headers(request: Request, user_id: str, db: AsyncSession) -> dict:
async def _forward_headers(
request: Request, user_id: str, is_admin: bool, db: AsyncSession
) -> dict:
headers = {
k: v
for k, v in request.headers.items()
if k.lower() not in _HOP_BY_HOP
}
headers["x-user-id"] = user_id
headers["x-user-is-admin"] = "true" if is_admin else "false"
# Inject the user's group memberships so the doc-service can evaluate
# group-shared document access without querying the backend DB.
@@ -78,7 +81,7 @@ async def proxy_documents(
path: str = "",
) -> Response:
url = f"/documents/{path}" if path else "/documents"
headers = await _forward_headers(request, str(current_user.id), db)
headers = await _forward_headers(request, str(current_user.id), current_user.is_superuser, db)
body = await request.body()
try: