v0.6.0 d5cc8fe

access.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package app
4
5import (
6	"fmt"
7
8	"bnema.dev/ermite/internal/domain"
9)
10
11// canRead is the access rule for reading a repository, the single place that
12// decides it: root reads everything, anyone reads a public repository, and a
13// stored token reads a private one only with repo:read on it (the scope, and
14// the repository within its list). Callers answer domain.ErrNotFound when it
15// is false, so a private repository never shows itself.
16func canRead(p domain.Principal, repo domain.Repo) bool {
17	return canReadAs(p, repo.Name, repo.Visibility)
18}
19
20// canReadAs is canRead for a repository known by its name and visibility only,
21// such as one that no longer exists.
22func canReadAs(p domain.Principal, name domain.RepoName, vis domain.Visibility) bool {
23	if vis == domain.VisibilityPublic {
24		return true
25	}
26	return p.Allows(domain.ScopeRepoRead, name)
27}
28
29// adminAccess is the access rule for changing or deleting a repository. A
30// caller that may not administer it learns nothing it could not already read:
31// not found when it cannot see the repository, unauthenticated when it is
32// anonymous, forbidden otherwise.
33func adminAccess(p domain.Principal, repo domain.Repo) error {
34	switch {
35	case canAdmin(p, repo.Name):
36		return nil
37	case !canRead(p, repo):
38		return domain.ErrNotFound
39	case p.IsAnonymous():
40		return domain.ErrUnauthenticated
41	}
42	return domain.ErrForbidden
43}
44
45// canWrite is the access rule for pushing to a repository, or creating it on
46// first push: repo:write on it.
47func canWrite(p domain.Principal, name domain.RepoName) bool {
48	return p.Allows(domain.ScopeRepoWrite, name)
49}
50
51// canManageTokens is the access rule for creating, listing and revoking
52// stored tokens: token:admin, which root holds.
53func canManageTokens(p domain.Principal) bool {
54	return p.HasScope(domain.ScopeTokenAdmin)
55}
56
57// canAdmin is the access rule for deleting a repository and changing its
58// visibility, description or default branch: repo:admin on it.
59func canAdmin(p domain.Principal, name domain.RepoName) bool {
60	return p.Allows(domain.ScopeRepoAdmin, name)
61}
62
63// scopeAccess is the access rule for an action that needs a scope on a
64// repository the caller can already read, such as mr:write or mr:merge:
65// unauthenticated for an anonymous caller, forbidden for one without the scope
66// on this repository.
67func scopeAccess(p domain.Principal, repo domain.Repo, scope domain.Scope) error {
68	switch {
69	case p.Allows(scope, repo.Name):
70		return nil
71	case p.IsAnonymous():
72		return domain.ErrUnauthenticated
73	}
74	return fmt.Errorf("%w: this needs the %s scope on %s", domain.ErrForbidden, scope, repo.Name)
75}
76
77// authorOf names who acts, for the author of a merge request or a comment: the
78// label of the token, "root" for the root token, "owner" for the owner signed
79// in on the web and for any other caller without a label.
80func authorOf(p domain.Principal) string {
81	switch {
82	case p.IsOwner():
83		return "owner"
84	case p.IsRoot():
85		return "root"
86	case p.TokenLabel() != "":
87		return p.TokenLabel()
88	}
89	return "owner"
90}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 44

↑↓ moveenter openesc close