|
| 1 | +package rbac |
| 2 | + |
| 3 | +import ( |
| 4 | + "sort" |
| 5 | + "strings" |
| 6 | +) |
| 7 | + |
| 8 | +// externalLowLevel is the curated set of low-level scope names exposed to users. |
| 9 | +// Any valid resource:action pair not in this set is considered internal-only |
| 10 | +// and must not be user-requestable. |
| 11 | +var externalLowLevel = map[ScopeName]struct{}{ |
| 12 | + // Workspaces |
| 13 | + "workspace:read": {}, |
| 14 | + "workspace:create": {}, |
| 15 | + "workspace:update": {}, |
| 16 | + "workspace:delete": {}, |
| 17 | + "workspace:ssh": {}, |
| 18 | + "workspace:start": {}, |
| 19 | + "workspace:stop": {}, |
| 20 | + "workspace:application_connect": {}, |
| 21 | + "workspace:*": {}, |
| 22 | + |
| 23 | + // Templates |
| 24 | + "template:read": {}, |
| 25 | + "template:create": {}, |
| 26 | + "template:update": {}, |
| 27 | + "template:delete": {}, |
| 28 | + "template:use": {}, |
| 29 | + "template:*": {}, |
| 30 | + |
| 31 | + // API keys (self-management) |
| 32 | + "api_key:read": {}, |
| 33 | + "api_key:create": {}, |
| 34 | + "api_key:update": {}, |
| 35 | + "api_key:delete": {}, |
| 36 | + "api_key:*": {}, |
| 37 | + |
| 38 | + // Files |
| 39 | + "file:read": {}, |
| 40 | + "file:create": {}, |
| 41 | + "file:*": {}, |
| 42 | + |
| 43 | + // Users (personal profile only) |
| 44 | + "user:read_personal": {}, |
| 45 | + "user:update_personal": {}, |
| 46 | + |
| 47 | + // User secrets |
| 48 | + "user_secret:read": {}, |
| 49 | + "user_secret:create": {}, |
| 50 | + "user_secret:update": {}, |
| 51 | + "user_secret:delete": {}, |
| 52 | + "user_secret:*": {}, |
| 53 | +} |
| 54 | + |
| 55 | +// IsExternalScope returns true if the scope is public, including the |
| 56 | +// `all` and `application_connect` special scopes and the curated |
| 57 | +// low-level resource:action scopes. |
| 58 | +func IsExternalScope(name ScopeName) bool { |
| 59 | + switch name { |
| 60 | + case ScopeAll, ScopeApplicationConnect: |
| 61 | + return true |
| 62 | + } |
| 63 | + if _, ok := externalLowLevel[name]; ok { |
| 64 | + return true |
| 65 | + } |
| 66 | + |
| 67 | + return false |
| 68 | +} |
| 69 | + |
| 70 | +// ExternalScopeNames returns a sorted list of all public scopes, which includes |
| 71 | +// the `all` and `application_connect` special scopes and the curated public |
| 72 | +// low-level names. |
| 73 | +func ExternalScopeNames() []string { |
| 74 | + names := make([]string, 0, len(externalLowLevel)+2) |
| 75 | + names = append(names, string(ScopeAll)) |
| 76 | + names = append(names, string(ScopeApplicationConnect)) |
| 77 | + |
| 78 | + // curated low-level names, filtered for validity |
| 79 | + for name := range externalLowLevel { |
| 80 | + if _, _, ok := parseLowLevelScope(name); ok { |
| 81 | + names = append(names, string(name)) |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + sort.Slice(names, func(i, j int) bool { return strings.Compare(names[i], names[j]) < 0 }) |
| 86 | + return names |
| 87 | +} |
0 commit comments