auth

Paddy 2015-03-24 Parent:d103a598548c Child:3e8964a914ef

152:de5e09680f6b Go to Latest

auth/scope.go

Implement postgres version of scopeStore. Update the authd server to use postgres as its scopeStore, instead of memstore. panic when starting the authd server if the CreateScopes call fails. This should, ideally, ignore ErrScopeAlreadyExists errors, but does not as of this commit. Update the simple.gotmpl template to properly display scopes, after switching to the Scope type instead of simply passing around the string the client supplied broke the template and I never bothered fixing it. Update the updateScopes method on the scopeStore (and the corresponding UpdateScopes method on the Context type) to be updateScope/UpdateScope. Operating on several scopes at a time like that is simply too challenging in SQL and I can't justify the complexity with a use case. Add a helper method to ScopeChange called Empty(), which returns true if the ScopeChange is full of nil values. Remove the ID from the ScopeChange type, because we're no longer accepting multiple ScopeChange types in UpdateScope, so we can supply that information outside the ScopeChange, which matches the rest of our update* methods. Correct our tests in scope_test.go to correctly use the updateScope method instead of the old updateScopes method. This generally just resulted in calling updateScope multiple times, as opposed to just once. Add a scope table initialization to the sql/postgres_init.sql script.

History
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 Name *string
paddy@134 64 Description *string
paddy@134 65 }
paddy@134 66
paddy@152 67 func (s ScopeChange) Empty() bool {
paddy@152 68 return s.Name == nil && s.Description == nil
paddy@152 69 }
paddy@152 70
paddy@134 71 type scopeStore interface {
paddy@134 72 createScopes(scopes []Scope) error
paddy@134 73 getScopes(ids []string) ([]Scope, error)
paddy@152 74 updateScope(id string, change ScopeChange) error
paddy@134 75 removeScopes(ids []string) error
paddy@134 76 listScopes() ([]Scope, error)
paddy@134 77 }
paddy@134 78
paddy@134 79 func (m *memstore) createScopes(scopes []Scope) error {
paddy@134 80 m.scopeLock.Lock()
paddy@134 81 defer m.scopeLock.Unlock()
paddy@134 82
paddy@134 83 for pos, scope := range scopes {
paddy@134 84 if _, ok := m.scopes[scope.ID]; ok {
paddy@134 85 return ErrScopeAlreadyExists{Pos: pos, ID: scope.ID}
paddy@134 86 }
paddy@134 87 }
paddy@134 88 for _, scope := range scopes {
paddy@134 89 m.scopes[scope.ID] = scope
paddy@134 90 }
paddy@134 91 return nil
paddy@134 92 }
paddy@134 93
paddy@134 94 func (m *memstore) getScopes(ids []string) ([]Scope, error) {
paddy@134 95 m.scopeLock.RLock()
paddy@134 96 defer m.scopeLock.RUnlock()
paddy@134 97
paddy@134 98 scopes := []Scope{}
paddy@134 99 for pos, id := range ids {
paddy@134 100 scope, ok := m.scopes[id]
paddy@134 101 if !ok {
paddy@134 102 return []Scope{}, ErrScopeNotFound{ID: id, Pos: pos}
paddy@134 103 }
paddy@134 104 scopes = append(scopes, scope)
paddy@134 105 }
paddy@134 106 sorted := sortedScopes(scopes)
paddy@134 107 sort.Sort(sorted)
paddy@134 108 scopes = sorted
paddy@134 109 return scopes, nil
paddy@134 110 }
paddy@134 111
paddy@152 112 func (m *memstore) updateScope(id string, change ScopeChange) error {
paddy@134 113 m.scopeLock.Lock()
paddy@134 114 defer m.scopeLock.Unlock()
paddy@134 115
paddy@152 116 scope, ok := m.scopes[id]
paddy@152 117 if !ok {
paddy@152 118 return ErrScopeNotFound{Pos: 0, ID: id}
paddy@134 119 }
paddy@152 120 scope.ApplyChange(change)
paddy@152 121 m.scopes[id] = scope
paddy@152 122 return nil
paddy@134 123 }
paddy@134 124
paddy@134 125 func (m *memstore) removeScopes(ids []string) error {
paddy@134 126 m.scopeLock.Lock()
paddy@134 127 defer m.scopeLock.Unlock()
paddy@134 128
paddy@134 129 for pos, id := range ids {
paddy@134 130 if _, ok := m.scopes[id]; !ok {
paddy@134 131 return ErrScopeNotFound{Pos: pos, ID: id}
paddy@134 132 }
paddy@134 133 }
paddy@134 134 for _, id := range ids {
paddy@134 135 delete(m.scopes, id)
paddy@134 136 }
paddy@134 137 return nil
paddy@134 138 }
paddy@134 139
paddy@134 140 func (m *memstore) listScopes() ([]Scope, error) {
paddy@134 141 m.scopeLock.RLock()
paddy@134 142 defer m.scopeLock.RUnlock()
paddy@134 143
paddy@134 144 scopes := []Scope{}
paddy@134 145 for _, scope := range m.scopes {
paddy@134 146 scopes = append(scopes, scope)
paddy@134 147 }
paddy@134 148 sorted := sortedScopes(scopes)
paddy@134 149 sort.Sort(sorted)
paddy@134 150 scopes = sorted
paddy@134 151 return scopes, nil
paddy@134 152 }