Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Code

392 commit(s) on main

Merge change request 01M70WES5ZZDJ6RP226WB11BBZ: Let people rename and remove their own passkeys keenan · 24m ago 4b8c9e1d
history blame raw 4.0 KiB
1package web
2
3// What a viewer may do in one repository, in the terms the pages use.
4//
5// Each function is one rule from forge/access, stated once. The tab that is
6// shown, the button that is rendered, and the handler that would accept the write
7// all ask the same question here, so a control cannot be offered to somebody the
8// writer would refuse.
9//
10// The account name passed in is always the one a credential resolved to. Nothing
11// here takes a name from a form field.
12
13import "rodent.software/vole/forge/access"
14
15// canDiscuss reports whether the account may take part in a repository at all:
16// file an issue, comment on one, or open a change request. Those are one
17// capability because discussing is what each of them is.
18func canDiscuss(acl *access.ACL, name string) bool {
19 return acl != nil && name != "" && acl.CanDiscuss(name)
20}
21
22// canOpenChangeRequest reports whether the account may open a change request. It
23// is separate from canDiscuss because a repository can allow discussion while
24// only trusting established contributors with requests.
25func canOpenChangeRequest(acl *access.ACL, name string) bool {
26 return acl != nil && name != "" && acl.CanOpenRequest(name)
27}
28
29// canMaintain reports whether the account holds the repository's maintainer
30// capability: triaging other people's issues, approving change requests,
31// allowing contributor CI, and managing releases. It says nothing about whose
32// item is in front of it; that is canTriage's job.
33func canMaintain(acl *access.ACL, name string) bool {
34 return acl != nil && name != "" && acl.CanTriage(name)
35}
36
37// canTriage reports whether the account may manage one issue or change request:
38// a maintainer may triage any of them, and its author may manage their own.
39func canTriage(acl *access.ACL, name, author string) bool {
40 return canMaintain(acl, name) || (author != "" && author == name)
41}
42
43// canApprove reports whether the account may approve change requests here. It
44// does not decide whether one request may be approved: approving your own is a
45// separate rule (see canApproveRequest), because the reader is owed the reason
46// that applies rather than a general refusal.
47func canApprove(acl *access.ACL, name string) bool {
48 return canMaintain(acl, name)
49}
50
51// canApproveRequest is canApprove plus the self-approval rule. It is what the
52// approve control is drawn from.
53func canApproveRequest(acl *access.ACL, name, author string) bool {
54 return canApprove(acl, name) && name != author
55}
56
57// canMerge reports whether the account may land a change request here. It is the
58// approve capability: landing is the act of accepting the review, so the accounts
59// that may approve may merge. The author is not excluded — merging your own request
60// after somebody else approved it is the point of separating the two — and whether
61// this approval count is satisfied is the gate's question, not this one.
62func canMerge(acl *access.ACL, name string) bool {
63 return canMaintain(acl, name)
64}
65
66// contributorOnly reports whether the account is a contributor and nothing more,
67// so every branch it may push is inside its own contrib/ namespace. The rule
68// matters to change requests: a contributor must open one from their own branch,
69// because that is the only branch the pre-receive hook would have let them write.
70func contributorOnly(acl *access.ACL, name string) bool {
71 return acl != nil && name != "" && acl.RoleFor(name) == access.Contribute
72}
73
74// canAdminister reports whether the account holds the repository's admin role.
75// An instance admin gets this on every repository through EffectiveRole, which is
76// why the read path asks canRead rather than this.
77func canAdminister(acl *access.ACL, name string) bool {
78 return acl != nil && name != "" && acl.Can(name, access.Admin)
79}
80
81// canModerateComment reports whether the account may edit or delete a comment:
82// the account that wrote it, or an admin repairing a thread.
83func canModerateComment(acl *access.ACL, name, author string) bool {
84 if acl == nil || name == "" {
85 return false
86 }
87 return name == author || acl.RoleFor(name).AtLeast(access.Admin)
88}
89