rastrillo / idear Public

Clone
git clone https://amadan.net/rastrillo/idear

Plain git — no account needed to clone.

Download

Download this file

1// Package idear is the roster for a Rastrillo instance: who is in it,
2// at what role, and who may change that. It never mints a session,
3// hashes a password, or renders a sign-in form — it sits on top of
4// sessions and whichever identity plugin the app already chose.
5package idear
6
7// Role is a member's rank within one instance. It is a string, not an
8// int, because it round-trips through form posts and database columns
9// without a mapping table to keep in sync — but that means any string
10// decodes without error, so every caller that receives one from outside
11// the package (a form, a query) must run it through ParseRole rather
12// than trust the cast.
13type Role string
14
15const (
16 RoleOwner Role = "owner"
17 RoleAdmin Role = "admin"
18 RoleMember Role = "member"
19)
20
21// rank orders the three roles for comparison; 0 means "not a role; see
22// Valid" rather than "below Member" so it never wins a comparison it
23// has no business winning.
24func rank(r Role) int {
25 switch r {
26 case RoleOwner:
27 return 3
28 case RoleAdmin:
29 return 2
30 case RoleMember:
31 return 1
32 default:
33 return 0
34 }
35}
36
37// Valid reports whether r is one of the three known roles.
38func (r Role) Valid() bool {
39 return rank(r) > 0
40}
41
42// AtLeast reports whether r's rank is at or above min's. Both sides
43// must be valid roles — an invalid r is never at least anything, not
44// even an equally invalid min, and an invalid min is never a threshold
45// anything can clear. Without that second half, two unknown strings
46// would compare equal by falling through to the same rank(0), and
47// AtLeast would call garbage "at least" garbage.
48func (r Role) AtLeast(min Role) bool {
49 if !r.Valid() || !min.Valid() {
50 return false
51 }
52 return rank(r) >= rank(min)
53}
54
55// Title is the display form of r — "Owner", "Admin", "Member" — and
56// the empty string for anything that isn't a role, so a template that
57// prints it renders nothing rather than a raw lowercase form value.
58func (r Role) Title() string {
59 switch r {
60 case RoleOwner:
61 return "Owner"
62 case RoleAdmin:
63 return "Admin"
64 case RoleMember:
65 return "Member"
66 default:
67 return ""
68 }
69}
70
71// ParseRole accepts only the three known lowercase spellings. It is the
72// one place a string from outside the package (a posted form field, a
73// query parameter) becomes a Role; everywhere else in idear a Role is
74// assumed already valid.
75func ParseRole(s string) (Role, bool) {
76 r := Role(s)
77 if !r.Valid() {
78 return "", false
79 }
80 return r, true
81}
82