package role import "strings" type Kind string const ( KindScoped Kind = "scoped" KindToggle Kind = "toggle" ) const contentGroup = "content" type Permission struct { Key string Group string Kind Kind OwnerOnly bool } func (p Permission) PerType() bool { return strings.HasPrefix(p.Key, contentGroup+".") } func scoped(group, key string) Permission { return Permission{Key: key, Group: group, Kind: KindScoped} } func toggle(group, key string) Permission { return Permission{Key: key, Group: group, Kind: KindToggle} } func ownerOnly(group, key string) Permission { return Permission{Key: key, Group: group, Kind: KindToggle, OwnerOnly: true} } var catalogue = []Permission{ scoped("content", "content.read"), toggle("content", "content.create"), scoped("content", "content.update"), scoped("content", "content.delete"), scoped("content", "content.publish"), toggle("schema", "schema.view"), toggle("schema", "schema.edit"), toggle("schema", "schema.delete"), toggle("media", "media.view"), toggle("media", "media.upload"), scoped("media", "media.delete"), toggle("authors", "authors.view"), toggle("authors", "authors.create"), scoped("authors", "authors.edit"), toggle("authors", "authors.delete"), scoped("activity", "activity.view"), toggle("activity", "activity.export"), toggle("users", "users.view"), toggle("users", "users.invite"), toggle("users", "users.change_role"), toggle("users", "users.remove"), toggle("settings", "settings.view"), toggle("settings", "settings.edit_general"), toggle("settings", "settings.manage_sites"), ownerOnly("settings", "settings.delete_site"), scoped("settings", "apikeys.view"), toggle("settings", "apikeys.create"), scoped("settings", "apikeys.revoke"), toggle("roles", "roles.view"), toggle("roles", "roles.manage"), ownerOnly("roles", "roles.edit_owner_only"), ownerOnly("system", "system.apply_updates"), ownerOnly("system", "system.edit_retention"), ownerOnly("system", "system.transfer_ownership"), } func Catalogue() []Permission { return append([]Permission(nil), catalogue...) } func Lookup(key string) (Permission, error) { for _, permission := range catalogue { if permission.Key == key { return permission, nil } } return Permission{}, ErrUnknownPermission } func Groups() []string { groups := []string{} for _, permission := range catalogue { if len(groups) == 0 || groups[len(groups)-1] != permission.Group { groups = append(groups, permission.Group) } } return groups } const ( typeSeparator = ":" maxKeyLength = 100 typeKeyAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789_-" ) func ParseTypedKey(composite string) (string, string, error) { base, typeKey, found := strings.Cut(composite, typeSeparator) if !found || len(composite) > maxKeyLength || typeKey == "" { return "", "", ErrUnknownPermission } permission, err := Lookup(base) if err != nil || !permission.PerType() { return "", "", ErrUnknownPermission } for _, char := range typeKey { if !strings.ContainsRune(typeKeyAlphabet, char) { return "", "", ErrUnknownPermission } } return base, typeKey, nil }