coverage~bigbes/sr-ht-dolt3523280ccore/access.go

Coverage
100.0% 22/22 statements
Δ
+0.0
Blob
75bd8fe
Uncovered nothing — every instrumented line ran
1 package core
2
3 // Allowed decides whether caller may perform op on repo, given the caller's
4 // resolved per-repo ACL grant (aclMode, nil if the caller has no ACL entry).
5 // It implements the dolt.sr.ht access matrix exactly:
6 //
7 // Caller \ Visibility | PUBLIC | UNLISTED | PRIVATE
8 // --------------------|---------------|---------------|----------------------
9 // anon / any user | browse, clone | browse, clone | —
10 // ACL RO | browse, clone | browse, clone | browse, clone
11 // ACL RW | + push | + push | browse, clone, push
12 // owner | all | all | all
13 //
14 // Rules:
15 // - The owner may do anything (subject to the suspension rule below).
16 // - An ACL RO grant permits browse and clone on any visibility, including
17 // PRIVATE.
18 // - An ACL RW grant additionally permits push (but never admin).
19 // - With no ACL and non-owner: PUBLIC and UNLISTED permit browse and clone
20 // for everyone (including anonymous); PRIVATE permits nothing.
21 // - A suspended caller may read (browse, clone) but never push or admin,
22 // regardless of ownership or ACL.
23 // - Any operation outside the four known Ops is denied.
24 //
25 // Access control fails closed: a nil repo denies everything.
26 89 func Allowed(caller *Caller, repo *Repo, aclMode *AccessMode, op Op) bool {
27 89 switch op {
28 case OpBrowse, OpCloneRead, OpPush, OpAdmin:
29 // known op
30 1 default:
31 1 return false
32 }
33 88 if repo == nil {
34 4 return false
35 4 }
36
37 84 suspended := caller != nil && caller.Suspended
38 84 isWrite := op == OpPush || op == OpAdmin
39 84 if suspended && isWrite {
40 10 return false
41 10 }
42
43 // Owner may do anything (write already gated by the suspension check).
44 74 if caller != nil && caller.UserID == repo.OwnerID {
45 17 return true
46 17 }
47
48 // Explicit ACL grants (only meaningful for authenticated callers).
49 57 if caller != nil && aclMode != nil {
50 31 switch *aclMode {
51 15 case AccessRO:
52 15 return op == OpBrowse || op == OpCloneRead
53 16 case AccessRW:
54 16 // RO reads plus push; never admin.
55 16 return op == OpBrowse || op == OpCloneRead || op == OpPush
56 }
57 }
58
59 // No ownership, no ACL: fall back to visibility. Only reads are ever
60 // granted this way.
61 26 switch repo.Visibility {
62 16 case VisibilityPublic, VisibilityUnlisted:
63 16 return op == OpBrowse || op == OpCloneRead
64 10 default: // VisibilityPrivate and anything unrecognized
65 10 return false
66 }
67 }
68
69 // NotFoundForPrivate reports whether a denied request for repo should be
70 // surfaced as "not found" (404) rather than "forbidden" (403), so that the
71 // existence of PRIVATE repositories is not leaked. Consult it only after
72 // Allowed has already returned false for the request.
73 //
74 // A PRIVATE repo that the caller cannot even browse is reported as not found;
75 // PUBLIC/UNLISTED repos, and PRIVATE repos the caller may browse, reveal their
76 // existence normally (a plain 403). A nil repo is always "not found".
77 7 func NotFoundForPrivate(caller *Caller, repo *Repo, aclMode *AccessMode) bool {
78 7 if repo == nil {
79 1 return true
80 1 }
81 6 if repo.Visibility != VisibilityPrivate {
82 2 return false
83 2 }
84 4 return !Allowed(caller, repo, aclMode, OpBrowse)
85 }