Freunde, privates Teilen, Artikelrechte, Reiserouten
- Freunde (freunde.py, Tabelle friendships): suchen, anfragen, annehmen, ablehnen, entfernen; neue Seite "Freunde" im Menü - Vorratslisten und Kanban-Projekte immer privat: sichtbar für Ersteller und Mitglieder; teilen nur mit Freunden (Admins: mit allen); Kanban-Mitglieder (Tabelle kanban_project_members), Bearbeiter nur aus dem Projekt, ausgetretene Mitglieder verlieren ihre Zuteilung - Artikel: lesen alle; bearbeiten Autor, Mitarbeitende verknüpfter Kanban-Projekte und Admins; verknüpfen nur bearbeitbare Artikel (sonst ließen sich Rechte erschleichen); Board-Liste auf der Artikelseite zeigt nur sichtbare Boards - Administratoren sehen und bearbeiten alles - Reisen: Städte nur von Freunden (Admins: alle); "Reiserouten zeigen" zeichnet die Strecken der Kilometer-Rechnung als Bögen - Migration Schritt 6: bisher gemeinsame Listen und alle Projekte bekommen die vorhandenen Konten als Mitglieder, ohne Ersteller → erster Admin; erste Liste einer neuen Installation gehört dem ersten Konto - Tests: test_freunde.py, test_zugriff.py, bestehende auf Privat-Modell umgestellt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1d7497bead
commit
0fb3521c2f
34 files changed
+833
-245
No files matched your search
+15
-7
@@ -12,7 +12,7 @@ from .config import DATA_DIR
|
||||
from .common import ValidationError, clean_text, now_iso
|
||||
from .db import transaction
|
||||
from .htmlclean import sanitize
|
||||
from .kanban import boards_for_article
|
||||
from .kanban import boards_for_article, can_edit_article
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -133,12 +133,18 @@ def _summary(row) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _get(conn, project_id: str) -> dict | None:
|
||||
def _get(conn, project_id: str, user: dict) -> dict | None:
|
||||
row = conn.execute(f"{_SELECT} WHERE p.id = ?", (project_id,)).fetchone()
|
||||
if not row:
|
||||
return None
|
||||
# Verknüpfte Kanban-Boards für die Seitenleiste
|
||||
return {**_summary(row), "cover": row["cover"], "content": row["content"], "boards": boards_for_article(conn, project_id)}
|
||||
return {
|
||||
**_summary(row), "cover": row["cover"], "content": row["content"],
|
||||
"boards": boards_for_article(conn, project_id, user),
|
||||
# Lesen dürfen alle; bearbeiten Autor, Mitarbeitende verknüpfter Kanban-Projekte und Administratoren
|
||||
"canEdit": can_edit_article(conn, user, project_id),
|
||||
"canDelete": user["isAdmin"] or row["created_by"] == user["id"],
|
||||
}
|
||||
|
||||
|
||||
def _not_found():
|
||||
@@ -169,13 +175,13 @@ def create_project(data: dict = Body(...), user: dict = Depends(current_user)):
|
||||
now, user["id"], now, user["id"],
|
||||
),
|
||||
)
|
||||
return _get(conn, project_id)
|
||||
return _get(conn, project_id, user)
|
||||
|
||||
|
||||
@router.get("/api/projects/{project_id}")
|
||||
def get_project(project_id: str, _: dict = Depends(current_user)):
|
||||
def get_project(project_id: str, user: dict = Depends(current_user)):
|
||||
with transaction() as conn:
|
||||
return _get(conn, project_id) or _raise(_not_found())
|
||||
return _get(conn, project_id, user) or _raise(_not_found())
|
||||
|
||||
|
||||
@router.patch("/api/projects/{project_id}")
|
||||
@@ -197,10 +203,12 @@ def update_project(project_id: str, data: dict = Body(...), user: dict = Depends
|
||||
old = conn.execute("SELECT cover, content FROM projects WHERE id = ?", (project_id,)).fetchone()
|
||||
if not old:
|
||||
raise _not_found()
|
||||
if not can_edit_article(conn, user, project_id):
|
||||
raise HTTPException(403, "Bearbeiten dürfen nur der Autor und wer an einem verknüpften Kanban-Projekt mitarbeitet.")
|
||||
assignments = ", ".join(f"{k} = ?" for k in fields)
|
||||
conn.execute(f"UPDATE projects SET {assignments} WHERE id = ?", (*fields.values(), project_id))
|
||||
_remove_unused(conn, [old["cover"], *_content_images(old["content"])])
|
||||
return _get(conn, project_id)
|
||||
return _get(conn, project_id, user)
|
||||
|
||||
|
||||
@router.delete("/api/projects/{project_id}")
|
||||
|
||||
Reference in new issue
Block a user