refactor(server): consolidate workspace permission checks into middleware

Move workspace membership and role validation from individual handlers
into dedicated Chi middleware. The new middleware resolves workspace ID
(from query param, X-Workspace-ID header, or URL param), validates
membership via DB, and injects the member into request context.

Handlers now read workspace ID and member from context instead of
calling requireWorkspaceMember/requireWorkspaceRole directly. This
eliminates ~17 duplicated permission checks across handlers and makes
it harder to accidentally omit access control on new routes.
This commit is contained in:
Jiayuan 2026-03-30 03:40:20 +08:00
parent e1e4079da1
commit f4a6e7c475
8 changed files with 198 additions and 64 deletions

View file

@ -142,9 +142,6 @@ func (h *Handler) loadSkillForUser(w http.ResponseWriter, r *http.Request, id st
func (h *Handler) ListSkills(w http.ResponseWriter, r *http.Request) {
workspaceID := resolveWorkspaceID(r)
if _, ok := h.requireWorkspaceMember(w, r, workspaceID, "workspace not found"); !ok {
return
}
skills, err := h.Queries.ListSkillsByWorkspace(r.Context(), parseUUID(workspaceID))
if err != nil {
@ -186,9 +183,6 @@ func (h *Handler) GetSkill(w http.ResponseWriter, r *http.Request) {
func (h *Handler) CreateSkill(w http.ResponseWriter, r *http.Request) {
workspaceID := resolveWorkspaceID(r)
if _, ok := h.requireWorkspaceRole(w, r, workspaceID, "workspace not found", "owner", "admin"); !ok {
return
}
creatorID, ok := requireUserID(w, r)
if !ok {
@ -768,9 +762,6 @@ func fetchRawFile(httpClient *http.Client, fileURL string) ([]byte, error) {
func (h *Handler) ImportSkill(w http.ResponseWriter, r *http.Request) {
workspaceID := resolveWorkspaceID(r)
if _, ok := h.requireWorkspaceRole(w, r, workspaceID, "workspace not found", "owner", "admin"); !ok {
return
}
creatorID, ok := requireUserID(w, r)
if !ok {