package platform import "net/http" func (s *service) materialGrants(w http.ResponseWriter, r *http.Request, project, account string) error { workspace, material := r.PathValue("workspace"), r.PathValue("material") if r.Method != http.MethodGet && r.Method != http.MethodPost { reject(w, 405, "method_not_allowed") return nil } tx, err := s.db.BeginTx(r.Context(), nil) if err != nil { return err } defer tx.Rollback() _, role, err := lockMaterial(r.Context(), tx, project, workspace, material, account) if err != nil { return err } if role != "admin" { reject(w, 403, "admin_required") return nil } if r.Method == http.MethodGet { rows, err := tx.QueryContext(r.Context(), "SELECT account_id::text,role FROM material_grants WHERE project=$1 AND workspace_id=$2 AND material_id=$3 ORDER BY account_id LIMIT 1000", project, workspace, material) if err != nil { return err } defer rows.Close() items := []response{} for rows.Next() { var id, role string if err := rows.Scan(&id, &role); err != nil { return err } items = append(items, response{"account_id": id, "role": role}) } if err := rows.Err(); err != nil { return err } reply(w, 200, response{"items": items}) return nil } var input struct { AccountID string `json:"account_id"` Role string `json:"role"` } if !decode(w, r, &input) { return nil } if input.Role != "editor" && input.Role != "viewer" { reject(w, 400, "invalid_role") return nil } _, err = tx.ExecContext(r.Context(), ` INSERT INTO material_grants(project,workspace_id,material_id,account_id,role) VALUES($1,$2,$3,$4,$5) ON CONFLICT(project,workspace_id,material_id,account_id) DO UPDATE SET role=EXCLUDED.role `, project, workspace, material, input.AccountID, input.Role) if err != nil { return err } if err = tx.Commit(); err != nil { return err } reply(w, 204, nil) return nil } func (s *service) deleteMaterialGrant(w http.ResponseWriter, r *http.Request, project, account string) error { if r.Method != http.MethodDelete { reject(w, 405, "method_not_allowed") return nil } workspace, material := r.PathValue("workspace"), r.PathValue("material") tx, err := s.db.BeginTx(r.Context(), nil) if err != nil { return err } defer tx.Rollback() _, role, err := lockMaterial(r.Context(), tx, project, workspace, material, account) if err != nil { return err } if role != "admin" { reject(w, 403, "admin_required") return nil } _, err = tx.ExecContext(r.Context(), "DELETE FROM material_grants WHERE project=$1 AND workspace_id=$2 AND material_id=$3 AND account_id=$4", project, workspace, material, r.PathValue("account")) if err != nil { return err } if err = tx.Commit(); err != nil { return err } reply(w, 204, nil) return nil }