auth
auth/scope.go
Return client Secrets when listing clients with basic auth. If the request to list clients is sent with basic auth containing the login and password for the owner of the client, its secret is not removed from the response before sending it.
| paddy@134 | 1 package auth |
| paddy@134 | 2 |
| paddy@134 | 3 import ( |
| paddy@134 | 4 "errors" |
| paddy@134 | 5 "fmt" |
| paddy@134 | 6 "sort" |
| paddy@134 | 7 ) |
| paddy@134 | 8 |
| paddy@134 | 9 var ( |
| paddy@134 | 10 ErrNoScopeStore = errors.New("scopeStore not set in Context") |
| paddy@134 | 11 ) |
| paddy@134 | 12 |
| paddy@134 | 13 type ErrScopeNotFound struct { |
| paddy@134 | 14 Pos int |
| paddy@134 | 15 ID string |
| paddy@134 | 16 } |
| paddy@134 | 17 |
| paddy@134 | 18 func (e ErrScopeNotFound) Error() string { |
| paddy@134 | 19 return fmt.Sprintf("scope %s couldn't be found", e.ID) |
| paddy@134 | 20 } |
| paddy@134 | 21 |
| paddy@134 | 22 type ErrScopeAlreadyExists struct { |
| paddy@134 | 23 Pos int |
| paddy@134 | 24 ID string |
| paddy@134 | 25 } |
| paddy@134 | 26 |
| paddy@134 | 27 func (e ErrScopeAlreadyExists) Error() string { |
| paddy@134 | 28 return fmt.Sprintf("scope %s already exists", e.ID) |
| paddy@134 | 29 } |
| paddy@134 | 30 |
| paddy@134 | 31 // Scope represents a limit on the access that a grant provides. |
| paddy@134 | 32 type Scope struct { |
| paddy@134 | 33 ID string |
| paddy@134 | 34 Name string |
| paddy@134 | 35 Description string |
| paddy@134 | 36 } |
| paddy@134 | 37 |
| paddy@134 | 38 func (s *Scope) ApplyChange(change ScopeChange) { |
| paddy@134 | 39 if change.Name != nil { |
| paddy@134 | 40 s.Name = *change.Name |
| paddy@134 | 41 } |
| paddy@134 | 42 if change.Description != nil { |
| paddy@134 | 43 s.Description = *change.Description |
| paddy@134 | 44 } |
| paddy@134 | 45 } |
| paddy@134 | 46 |
| paddy@134 | 47 type sortedScopes []Scope |
| paddy@134 | 48 |
| paddy@134 | 49 func (s sortedScopes) Len() int { |
| paddy@134 | 50 return len(s) |
| paddy@134 | 51 } |
| paddy@134 | 52 |
| paddy@134 | 53 func (s sortedScopes) Swap(i, j int) { |
| paddy@134 | 54 s[i], s[j] = s[j], s[i] |
| paddy@134 | 55 } |
| paddy@134 | 56 |
| paddy@134 | 57 func (s sortedScopes) Less(i, j int) bool { |
| paddy@134 | 58 return s[i].ID < s[j].ID |
| paddy@134 | 59 } |
| paddy@134 | 60 |
| paddy@134 | 61 // ScopeChange represents a change to a Scope. |
| paddy@134 | 62 type ScopeChange struct { |
| paddy@134 | 63 ID string |
| paddy@134 | 64 Name *string |
| paddy@134 | 65 Description *string |
| paddy@134 | 66 } |
| paddy@134 | 67 |
| paddy@134 | 68 type scopeStore interface { |
| paddy@134 | 69 createScopes(scopes []Scope) error |
| paddy@134 | 70 getScopes(ids []string) ([]Scope, error) |
| paddy@134 | 71 updateScopes(changes []ScopeChange) ([]Scope, error) |
| paddy@134 | 72 removeScopes(ids []string) error |
| paddy@134 | 73 listScopes() ([]Scope, error) |
| paddy@134 | 74 } |
| paddy@134 | 75 |
| paddy@134 | 76 func (m *memstore) createScopes(scopes []Scope) error { |
| paddy@134 | 77 m.scopeLock.Lock() |
| paddy@134 | 78 defer m.scopeLock.Unlock() |
| paddy@134 | 79 |
| paddy@134 | 80 for pos, scope := range scopes { |
| paddy@134 | 81 if _, ok := m.scopes[scope.ID]; ok { |
| paddy@134 | 82 return ErrScopeAlreadyExists{Pos: pos, ID: scope.ID} |
| paddy@134 | 83 } |
| paddy@134 | 84 } |
| paddy@134 | 85 for _, scope := range scopes { |
| paddy@134 | 86 m.scopes[scope.ID] = scope |
| paddy@134 | 87 } |
| paddy@134 | 88 return nil |
| paddy@134 | 89 } |
| paddy@134 | 90 |
| paddy@134 | 91 func (m *memstore) getScopes(ids []string) ([]Scope, error) { |
| paddy@134 | 92 m.scopeLock.RLock() |
| paddy@134 | 93 defer m.scopeLock.RUnlock() |
| paddy@134 | 94 |
| paddy@134 | 95 scopes := []Scope{} |
| paddy@134 | 96 for pos, id := range ids { |
| paddy@134 | 97 scope, ok := m.scopes[id] |
| paddy@134 | 98 if !ok { |
| paddy@134 | 99 return []Scope{}, ErrScopeNotFound{ID: id, Pos: pos} |
| paddy@134 | 100 } |
| paddy@134 | 101 scopes = append(scopes, scope) |
| paddy@134 | 102 } |
| paddy@134 | 103 sorted := sortedScopes(scopes) |
| paddy@134 | 104 sort.Sort(sorted) |
| paddy@134 | 105 scopes = sorted |
| paddy@134 | 106 return scopes, nil |
| paddy@134 | 107 } |
| paddy@134 | 108 |
| paddy@134 | 109 func (m *memstore) updateScopes(changes []ScopeChange) ([]Scope, error) { |
| paddy@134 | 110 m.scopeLock.Lock() |
| paddy@134 | 111 defer m.scopeLock.Unlock() |
| paddy@134 | 112 |
| paddy@134 | 113 scopes := []Scope{} |
| paddy@134 | 114 |
| paddy@134 | 115 for pos, change := range changes { |
| paddy@134 | 116 if _, ok := m.scopes[change.ID]; !ok { |
| paddy@134 | 117 return []Scope{}, ErrScopeNotFound{Pos: pos, ID: change.ID} |
| paddy@134 | 118 } |
| paddy@134 | 119 } |
| paddy@134 | 120 for _, change := range changes { |
| paddy@134 | 121 scope := m.scopes[change.ID] |
| paddy@134 | 122 scope.ApplyChange(change) |
| paddy@134 | 123 m.scopes[change.ID] = scope |
| paddy@134 | 124 scopes = append(scopes, scope) |
| paddy@134 | 125 } |
| paddy@134 | 126 sorted := sortedScopes(scopes) |
| paddy@134 | 127 sort.Sort(sorted) |
| paddy@134 | 128 scopes = sorted |
| paddy@134 | 129 return scopes, nil |
| paddy@134 | 130 } |
| paddy@134 | 131 |
| paddy@134 | 132 func (m *memstore) removeScopes(ids []string) error { |
| paddy@134 | 133 m.scopeLock.Lock() |
| paddy@134 | 134 defer m.scopeLock.Unlock() |
| paddy@134 | 135 |
| paddy@134 | 136 for pos, id := range ids { |
| paddy@134 | 137 if _, ok := m.scopes[id]; !ok { |
| paddy@134 | 138 return ErrScopeNotFound{Pos: pos, ID: id} |
| paddy@134 | 139 } |
| paddy@134 | 140 } |
| paddy@134 | 141 for _, id := range ids { |
| paddy@134 | 142 delete(m.scopes, id) |
| paddy@134 | 143 } |
| paddy@134 | 144 return nil |
| paddy@134 | 145 } |
| paddy@134 | 146 |
| paddy@134 | 147 func (m *memstore) listScopes() ([]Scope, error) { |
| paddy@134 | 148 m.scopeLock.RLock() |
| paddy@134 | 149 defer m.scopeLock.RUnlock() |
| paddy@134 | 150 |
| paddy@134 | 151 scopes := []Scope{} |
| paddy@134 | 152 for _, scope := range m.scopes { |
| paddy@134 | 153 scopes = append(scopes, scope) |
| paddy@134 | 154 } |
| paddy@134 | 155 sorted := sortedScopes(scopes) |
| paddy@134 | 156 sort.Sort(sorted) |
| paddy@134 | 157 scopes = sorted |
| paddy@134 | 158 return scopes, nil |
| paddy@134 | 159 } |