Let editors manage projects they created; add project created_by #118

Merged
qwc merged 1 commit from feature/editor-manage-own-projects into main 2026-06-18 08:04:07 +02:00
Owner

Problem

Two bugs reported by the user, plus a "created by" feature request — all one underlying gap: a non-admin editor could create a project but had no authority over it afterward.

  1. Editors couldn't edit projects they created — the edit routes were requireAdmin, while create was requireEditorOrAdmin.
  2. Editors couldn't grant access to their own custom projects — the per-project access routes were also requireAdmin, so a custom project an editor created was unusable (nobody could be granted access without an admin). The user reached for group mappings, which are correctly admin-only.
  3. The manage-projects overview had no way to see who created a project (no created_by was ever stored).

Changes

  • Migration 010 adds nullable projects.created_by (ON DELETE SET NULL, mirroring uploaded_by from 009) across sqlite/postgres/mysql. Project struct gains CreatedBy; projects.Service.Create records the creator for all create paths (admin form, API, auto-create-on-upload).
  • access.Checker.CanManage(user, project) — admins manage everything; everyone else only the projects they created. Pure (no store lookups).
  • /admin/projects/{slug}/edit, /delete, /access/grant, /access/revoke move from requireAdminrequireEditorOrAdmin; each handler now gates on CanManage. Non-admins still cannot promote a project to public (mirrors ErrPublicRequiresAdmin).
  • Manage-projects overview gains a Created by column; Edit/Delete render only on rows the user can manage. The edit page shows the creator and hides the public-visibility option from non-admins.
  • Built-in docs (roles-permissions, first-project) updated; unit tests for CanManage, created_by persistence, and the editor edit / non-creator-403 / public-deny paths.

Design note

Group-mapping management stays admin-only by design — it's a global LDAP/OAuth2 feature spanning all projects. The genuine gap it exposed (creators couldn't grant access to their own projects) is closed by the per-project access changes here.

Edit authority is creator + admins only (not any granted editor), per the chosen scope.

Testing

Full suite green under go test -race ./... (exit 0).

🤖 Generated with Claude Code

## Problem Two bugs reported by the user, plus a "created by" feature request — all one underlying gap: **a non-admin editor could create a project but had no authority over it afterward.** 1. Editors couldn't **edit** projects they created — the edit routes were `requireAdmin`, while create was `requireEditorOrAdmin`. 2. Editors couldn't grant access to their own **custom** projects — the per-project access routes were also `requireAdmin`, so a custom project an editor created was unusable (nobody could be granted access without an admin). The user reached for *group mappings*, which are correctly admin-only. 3. The manage-projects overview had no way to see who created a project (no `created_by` was ever stored). ## Changes - **Migration 010** adds nullable `projects.created_by` (`ON DELETE SET NULL`, mirroring `uploaded_by` from 009) across sqlite/postgres/mysql. `Project` struct gains `CreatedBy`; `projects.Service.Create` records the creator for **all** create paths (admin form, API, auto-create-on-upload). - **`access.Checker.CanManage(user, project)`** — admins manage everything; everyone else only the projects they created. Pure (no store lookups). - `/admin/projects/{slug}/edit`, `/delete`, `/access/grant`, `/access/revoke` move from `requireAdmin` → `requireEditorOrAdmin`; each handler now gates on `CanManage`. Non-admins still **cannot promote a project to public** (mirrors `ErrPublicRequiresAdmin`). - Manage-projects overview gains a **Created by** column; Edit/Delete render only on rows the user can manage. The edit page shows the creator and hides the public-visibility option from non-admins. - Built-in docs (`roles-permissions`, `first-project`) updated; unit tests for `CanManage`, `created_by` persistence, and the editor edit / non-creator-403 / public-deny paths. ## Design note Group-mapping management stays admin-only by design — it's a global LDAP/OAuth2 feature spanning all projects. The genuine gap it exposed (creators couldn't grant access to their own projects) is closed by the per-project access changes here. Edit authority is **creator + admins only** (not any granted editor), per the chosen scope. ## Testing Full suite green under `go test -race ./...` (exit 0). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Let editors manage projects they created; add project created_by
All checks were successful
CI / test (pull_request) Successful in 1m7s
CI / build (pull_request) Successful in 40s
CI / docker (pull_request) Has been skipped
1508af130f
Editors could create projects (and were auto-granted editor access) but
could not edit them or grant access to others — the edit, delete, and
access routes were admin-only. Custom projects an editor created were thus
unusable: nobody could be granted access to them without an admin.

Changes:
- Migration 010 adds a nullable projects.created_by (ON DELETE SET NULL,
  mirroring uploaded_by from 009) across sqlite/postgres/mysql. Project
  struct gains CreatedBy; projects.Service.Create records the creator for
  all create paths (admin form, API, auto-create).
- access.Checker.CanManage(user, project): admins manage everything;
  everyone else only projects they created. Pure (no store lookups).
- /admin/projects/{slug}/edit,/delete,/access/{grant,revoke} move from
  requireAdmin to requireEditorOrAdmin; each handler now gates on
  CanManage. Non-admins still cannot promote a project to public.
- Manage-projects overview shows a "Created by" column; Edit/Delete render
  only on rows the user can manage. Edit page shows the creator and hides
  the public-visibility option from non-admins.
- Built-in docs (roles-permissions, first-project) updated; unit tests for
  CanManage, created_by persistence, and the editor edit/grant/public-deny
  paths. Full suite green under -race.

Group-mapping management stays admin-only by design (it's a global
LDAP/OAuth2 feature); the real gap it exposed — creators having no way to
grant access to their own projects — is closed by the per-project access
changes above.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
qwc merged commit 4c83adfdc3 into main 2026-06-18 08:04:07 +02:00
qwc deleted branch feature/editor-manage-own-projects 2026-06-18 08:04:07 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
qwc-open/asiakirjat!118
No description provided.