Extract internal/access.Checker (H-11) #105
No reviewers
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
qwc-open/asiakirjat!105
Loading…
Reference in a new issue
No description provided.
Delete branch "refactor/access-checker"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Workstream item #10. Audit finding H-11 (High) — authz helpers can't be unit-tested in isolation.
canViewProject,canUpload,filterAccessibleProjectslived as methods onHandlerand took*Handleras receiver. Each consulted the stores directly. Testing required a full Handler with five stores + a logger, and the rules had already drifted across these three methods plus the inline copies inproject.go(the #94 root cause and the audit's H-1/H-2).Changes
internal/accesspackage withChecker:CanView(ctx, user, project) boolCanUpload(ctx, user, project) boolFilterAccessible(ctx, user, []Project) []ProjectCheckerconstructed inhandler.Newfrom existingDeps. The three handler methods become one-line delegations toh.checker.CanView/h.checker.CanUpload/h.checker.FilterAccessible, so all 17 existing call sites are untouched.TestCanView,TestCanUpload,TestFilterAccessible. Anonymous + every role/visibility/grant combination, including the per-project-grant-on-private edge that PR #95 wants to flip (currently pinned to pre-#95 behavior so the test will alert when #95 lands).Test plan
go test ./...passesFollow-up that this unblocks
handleDeleteVersioncan callh.canUpload(...)instead of the inline ad-hoc check (one-line fix).handleProjectDetail'sCanUpload/CanDeletetemplate flag becomes the same call.internal/access/checker.gonow (one place, not three).🤖 Generated with Claude Code
Audit finding H-11. The three authorization helpers — canViewProject, canUpload, filterAccessibleProjects — lived as methods on Handler and took *Handler as receiver. Each consulted ProjectAccessStore + GlobalAccessStore directly. Three consequences: - Tests of the authorization rules needed a full Handler with five stores + a logger to construct, which discouraged exhaustive case coverage. - The view / upload rules drifted across the three methods plus inline copies in project.go (#94 and the audit's H-1/H-2). - Future structural splits (PublicHandler vs AdminHandler from the architecture audit) had no clean seam. Move all three to a new internal/access package: type Checker struct { access, globalAccess, logger } func NewChecker(...) func (c *Checker) CanView(ctx, user, project) bool func (c *Checker) CanUpload(ctx, user, project) bool func (c *Checker) FilterAccessible(ctx, user, []Project) []Project This is a pure code-move: rules preserved byte-for-byte from the prior implementation, including the upload-without-view asymmetry the audit flagged as M-2 (it's documented in CanUpload's godoc). PR #95 still applies on top. Wiring: Handler.checker is constructed in handler.New from the existing Deps (Access + GlobalAccess + Logger). The three handler methods (h.canViewProject, h.canUpload, h.filterAccessibleProjects) become one-line delegations, keeping all 17 existing call sites unchanged and the diff small. Tests: - TestCanView (13 cases) covers anonymous + every role/visibility/ grant combination, including the per-project-grant-on-private edge that PR #95 wants to flip (test currently pins the pre-#95 behavior). - TestCanUpload (10 cases) covers the same matrix from the upload side, with explicit notes on the M-2 asymmetry. - TestFilterAccessible verifies the batch form returns the same subset CanView would on each project. Net handler diff: -85 / +12 lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>