Skip to content

Commit 139f908

Browse files
authored
support alpha 03 (#16)
1 parent 908d259 commit 139f908

File tree

4 files changed

+121
-81
lines changed

4 files changed

+121
-81
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: Added
2+
body: Support for scopie alpha03
3+
time: 2024-12-15T13:09:20.15909473-08:00
4+
custom:
5+
Issue: "15"

scopie.go

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,40 @@ package scopie
33
import (
44
"errors"
55
"fmt"
6+
"strings"
67
)
78

89
const (
910
BlockSeperator = byte('/')
1011
ArraySeperator = byte('|')
1112
VariablePrefix = byte('@')
1213
Wildcard = byte('*')
14+
15+
AllowPermission = "allow"
16+
DenyPermission = "deny"
1317
)
1418

1519
const (
1620
fmtAllowedInvalidChar = "scopie-100 in %s: invalid character '%s'"
17-
fmtAllowedVarInArray = "scopie-101 in actor: variable '%s' found in array block"
18-
fmtAllowedVarNotFound = "scopie-104 in actor: variable '%s' not found"
21+
fmtAllowedVarInArray = "scopie-101: variable '%s' found in array block"
22+
fmtAllowedVarNotFound = "scopie-104: variable '%s' not found"
1923

2024
fmtValidateVarInArray = "scopie-101: variable '%s' found in array block"
2125
fmtValidateInvalidChar = "scopie-100: invalid character '%s'"
2226
)
2327

2428
var (
25-
errAllowedSuperNotLast = errors.New("scopie-105 in actor: super wildcard not in the last block")
26-
errAllowedSuperInArray = errors.New("scopie-103 in actor: super wildcard found in array block")
27-
errAllowedWildcardInArray = errors.New("scopie-102 in actor: wildcard found in array block")
28-
errAllowedActionScopesEmpty = errors.New("scopie-106: action scopes was empty")
29-
errAllowedActionScopeEmpty = errors.New("scopie-106: action scope was empty")
30-
errAllowedActorRuleEmpty = errors.New("scopie-106: actor rule was empty")
31-
32-
errValidateWildcardInArray = errors.New("scopie-102: wildcard found in array block")
33-
errValidateSuperInArray = errors.New("scopie-103: super wildcard found in array block")
34-
errValidateSuperNotLast = errors.New("scopie-105: super wildcard not in the last block")
35-
errValidateEmpty = errors.New("scopie-106: scope was empty")
29+
errSuperNotLast = errors.New("scopie-105: super wildcard not in the last block")
30+
errSuperInArray = errors.New("scopie-103: super wildcard found in array block")
31+
errWildcardInArray = errors.New("scopie-102: wildcard found in array block")
32+
errActionScopesEmpty = errors.New("scopie-106 in action: scopes was empty")
33+
errActionScopeEmpty = errors.New("scopie-106 in action: scope was empty")
34+
errActorRuleEmpty = errors.New("scopie-106 in actor: rule was empty")
35+
36+
// validation specific
37+
errValidateScopeRulesEmpty = errors.New("scopie-106: scope or rule was empty")
38+
errValidateNoScopeRules = errors.New("scopie-106: scope or rule array was empty")
39+
errValidateInconsistent = errors.New("scopie-107: inconsistent array of scopes and rules")
3640
)
3741

3842
// IsAllowedFunc is a type wrapper for IsAllowed that can be used as
@@ -46,7 +50,7 @@ type ValidateScopeFunc func(string) error
4650
// IsAllowed returns whether or not the required role scopes are fulfilled by our actor scopes.
4751
func IsAllowed(actionScopes, actorRules []string, vars map[string]string) (bool, error) {
4852
if len(actionScopes) == 0 {
49-
return false, errAllowedActionScopesEmpty
53+
return false, errActionScopesEmpty
5054
}
5155

5256
if len(actorRules) == 0 {
@@ -57,19 +61,19 @@ func IsAllowed(actionScopes, actorRules []string, vars map[string]string) (bool,
5761

5862
for _, actorRule := range actorRules {
5963
if len(actorRule) == 0 {
60-
return false, errAllowedActorRuleEmpty
64+
return false, errActorRuleEmpty
6165
}
6266

6367
actorRule := actorRule
6468

65-
isAllowBlock := actorRule[0] == 'a'
69+
isAllowBlock := strings.HasPrefix(actorRule, AllowPermission)
6670
if isAllowBlock && hasBeenAllowed {
6771
continue
6872
}
6973

7074
for _, actionScope := range actionScopes {
7175
if len(actionScope) == 0 {
72-
return false, errAllowedActionScopeEmpty
76+
return false, errActionScopeEmpty
7377
}
7478

7579
actionScope := actionScope
@@ -90,45 +94,61 @@ func IsAllowed(actionScopes, actorRules []string, vars map[string]string) (bool,
9094
return hasBeenAllowed, nil
9195
}
9296

93-
func ValidateScope(scope string) error {
94-
if scope == "" {
95-
return errValidateEmpty
97+
func ValidateScopes(scopeOrRules []string) error {
98+
if len(scopeOrRules) == 0 {
99+
return errValidateNoScopeRules
96100
}
97101

98-
inArray := false
102+
isRules := strings.HasPrefix(scopeOrRules[0], AllowPermission) ||
103+
strings.HasPrefix(scopeOrRules[0], DenyPermission)
99104

100-
for i := range scope {
101-
if scope[i] == BlockSeperator {
102-
inArray = false
103-
continue
105+
for _, scope := range scopeOrRules {
106+
if scope == "" {
107+
return errValidateScopeRulesEmpty
104108
}
105109

106-
if scope[i] == ArraySeperator {
107-
inArray = true
108-
continue
110+
scopeIsRule := strings.HasPrefix(scope, AllowPermission) ||
111+
strings.HasPrefix(scope, DenyPermission)
112+
113+
if isRules != scopeIsRule {
114+
return errValidateInconsistent
109115
}
110116

111-
if inArray {
112-
if scope[i] == Wildcard && i < len(scope)-1 && scope[i+1] == Wildcard {
113-
return errValidateSuperInArray
117+
inArray := false
118+
119+
for i := range scope {
120+
if scope[i] == BlockSeperator {
121+
inArray = false
122+
continue
114123
}
115124

116-
if scope[i] == Wildcard {
117-
return errValidateWildcardInArray
125+
if scope[i] == ArraySeperator {
126+
inArray = true
127+
continue
118128
}
119129

120-
if scope[i] == VariablePrefix {
121-
end := endOfArrayElement(&scope, i)
122-
return fmt.Errorf(fmtValidateVarInArray, scope[i+1:end])
130+
if inArray {
131+
if scope[i] == Wildcard && i < len(scope)-1 && scope[i+1] == Wildcard {
132+
return errSuperInArray
133+
}
134+
135+
if scope[i] == Wildcard {
136+
return errWildcardInArray
137+
}
138+
139+
if scope[i] == VariablePrefix {
140+
end := endOfArrayElement(&scope, i)
141+
return fmt.Errorf(fmtValidateVarInArray, scope[i+1:end])
142+
}
123143
}
124-
}
125144

126-
if !isValidCharacter(scope[i]) {
127-
return fmt.Errorf(fmtValidateInvalidChar, string(scope[i]))
128-
}
145+
if !isValidCharacter(scope[i]) {
146+
return fmt.Errorf(fmtValidateInvalidChar, string(scope[i]))
147+
}
129148

130-
if scope[i] == Wildcard && i < len(scope)-1 && scope[i+1] == Wildcard && i < len(scope)-2 {
131-
return errValidateSuperNotLast
149+
if scope[i] == Wildcard && i < len(scope)-1 && scope[i+1] == Wildcard && i < len(scope)-2 {
150+
return errSuperNotLast
151+
}
132152
}
133153
}
134154

@@ -165,7 +185,7 @@ func compareActorToAction(
165185
// Super wildcards are checked here as it skips the who rest of the checks.
166186
if actorSlider-actorLeft == 2 && (*actor)[actorLeft] == Wildcard && (*actor)[actorLeft+1] == Wildcard {
167187
if len(*actor) > actorSlider {
168-
return false, errAllowedSuperNotLast
188+
return false, errSuperNotLast
169189
}
170190

171191
return true, nil
@@ -218,10 +238,10 @@ func compareBlock(
218238

219239
if (*actor)[actorLeft] == Wildcard {
220240
if arrayRight-actorLeft > 1 && (*actor)[actorLeft+1] == Wildcard {
221-
return false, errAllowedSuperInArray
241+
return false, errSuperInArray
222242
}
223243

224-
return false, errAllowedWildcardInArray
244+
return false, errWildcardInArray
225245
}
226246

227247
if (*actor)[actorLeft:arrayRight] == (*action)[actionLeft:actionSlider] {

scopie_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@ type testAllowedScenario struct {
1919
}
2020

2121
type testValidScenario struct {
22-
ID string `json:"id"`
23-
Scope string `json:"scope"`
24-
Error string `json:"error"`
22+
ID string `json:"id"`
23+
Scopes []string `json:"scopes"`
24+
Error string `json:"error"`
2525
}
2626

2727
type coreTestCase struct {
2828
Version string `json:"version"`
2929
IsAllowedTests []testAllowedScenario `json:"isAllowedTests"`
30-
ScopeValidTests []testValidScenario `json:"scopeValidTests"`
30+
ScopeValidTests []testValidScenario `json:"validateScopesTests"`
3131
Benchmarks []testAllowedScenario `json:"benchmarks"`
3232
}
3333

3434
var testCases coreTestCase
3535

3636
func TestMain(m *testing.M) {
37-
testFile, err := os.Open("testdata/scopie_scenarios.json")
37+
testFile, err := os.Open("testdata/scenarios.json")
3838
if err != nil {
3939
fmt.Println("unable to read scenarios", err)
4040
os.Exit(1)
@@ -78,7 +78,7 @@ func Test_IsAllowedBenchmarks(t *testing.T) {
7878
func Test_ScopeValid(t *testing.T) {
7979
for _, scenario := range testCases.ScopeValidTests {
8080
t.Run(scenario.ID, func(t *testing.T) {
81-
err := ValidateScope(scenario.Scope)
81+
err := ValidateScopes(scenario.Scopes)
8282
if scenario.Error == "" {
8383
then.Nil(t, err)
8484
} else {

0 commit comments

Comments
 (0)