-
Notifications
You must be signed in to change notification settings - Fork 3
/
validate.go
87 lines (83 loc) · 2.15 KB
/
validate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package iampermission
import (
"fmt"
"unicode"
)
// Validate a permission.
//
// A permission is valid on the format `<service>.<resource>.<verb>`.
//
// - It contains at most 3 segments.
// - When no segment is a wildcard, it contains exactly 3 segments.
// - All segments are non-empty.
// - All segments are lower-case.
// - The first (service) segment is not a wildcard.
// - A wildcard only occurs in the last segment.
func Validate(permission string) error {
var sc Scanner
sc.Init(permission)
// Segment 1: Service.
if !sc.Scan() {
return fmt.Errorf("permission is empty")
}
if sc.Wildcard() {
return fmt.Errorf("permission `%s`: service segment must not be wildcard", permission)
}
if !isValidSegment(sc.Segment()) {
return fmt.Errorf("permission `%s`: invalid service segment", permission)
}
// Segment 2: Resource.
if !sc.Scan() {
return fmt.Errorf("permission `%s`: missing resource segment", permission)
}
if sc.Wildcard() {
if sc.Scan() {
return fmt.Errorf("permission `%s`: only final segment can be wildcard", permission)
}
return nil
}
if !isValidSegment(sc.Segment()) {
return fmt.Errorf("permission `%s`: invalid resource segment", permission)
}
// Segment 3: Verb.
if !sc.Scan() {
return fmt.Errorf("permission `%s`: missing verb segment", permission)
}
if sc.Wildcard() {
if sc.Scan() {
return fmt.Errorf("permission `%s`: only final segment can be wildcard", permission)
}
return nil
}
if !isValidSegment(sc.Segment()) {
return fmt.Errorf("permission `%s`: invalid verb segment", permission)
}
// Segment 4? Invalid!
if sc.Scan() {
return fmt.Errorf("permission `%s`: too many segments", permission)
}
return nil
}
// Valid checks whether the provided permission is valid.
// See Validate for what constitutes a valid permission.
func Valid(permission string) bool {
return Validate(permission) == nil
}
func isValidSegment(segment string) bool {
if len(segment) == 0 {
return false
}
for i, r := range segment {
switch i {
case 0:
if !unicode.IsLower(r) {
return false
}
default:
if !unicode.In(r, unicode.Lower, unicode.Upper, unicode.Digit) {
return false
}
}
}
return true
}