auth
auth/memstore.go
Test our getClientAuth helper, switch to table-based tests. Our getClientAuth helper was being tested implicitly when we tested our verifyClient helper, but let's test them separately. While we're at it, let's use table based tests instead of copy and paste. I noticed a lot of copy/paste errors while I was updating this, and the less test code we have and the easier we make it to test new edge cases, the better of we are.
| paddy@28 | 1 package auth |
| paddy@28 | 2 |
| paddy@31 | 3 import ( |
| paddy@31 | 4 "sync" |
| paddy@31 | 5 |
| paddy@107 | 6 "code.secondbit.org/uuid.hg" |
| paddy@31 | 7 ) |
| paddy@28 | 8 |
| paddy@57 | 9 type memstore struct { |
| paddy@28 | 10 tokens map[string]Token |
| paddy@28 | 11 refreshTokenLookup map[string]string |
| paddy@28 | 12 profileTokenLookup map[string][]string |
| paddy@28 | 13 tokenLock sync.RWMutex |
| paddy@29 | 14 |
| paddy@87 | 15 authCodes map[string]AuthorizationCode |
| paddy@87 | 16 authCodeLock sync.RWMutex |
| paddy@31 | 17 |
| paddy@31 | 18 clients map[string]Client |
| paddy@31 | 19 profileClientLookup map[string][]uuid.ID |
| paddy@31 | 20 clientLock sync.RWMutex |
| paddy@38 | 21 |
| paddy@41 | 22 endpoints map[string][]Endpoint |
| paddy@41 | 23 endpointLock sync.RWMutex |
| paddy@41 | 24 |
| paddy@38 | 25 profiles map[string]Profile |
| paddy@38 | 26 profileLock sync.RWMutex |
| paddy@44 | 27 |
| paddy@44 | 28 logins map[string]Login |
| paddy@44 | 29 profileLoginLookup map[string][]string |
| paddy@44 | 30 loginLock sync.RWMutex |
| paddy@77 | 31 |
| paddy@77 | 32 sessions map[string]Session |
| paddy@77 | 33 sessionLock sync.RWMutex |
| paddy@28 | 34 } |
| paddy@28 | 35 |
| paddy@57 | 36 // NewMemstore returns an in-memory version of our datastores, |
| paddy@57 | 37 // which is handy for tests. Though the implementation is concurrency-safe, |
| paddy@57 | 38 // if makes no attempt to persist the data, and therefore it is inadvisable |
| paddy@57 | 39 // to use it in a production setting. |
| paddy@57 | 40 func NewMemstore() *memstore { |
| paddy@57 | 41 return &memstore{ |
| paddy@31 | 42 tokens: map[string]Token{}, |
| paddy@31 | 43 refreshTokenLookup: map[string]string{}, |
| paddy@31 | 44 profileTokenLookup: map[string][]string{}, |
| paddy@87 | 45 authCodes: map[string]AuthorizationCode{}, |
| paddy@31 | 46 clients: map[string]Client{}, |
| paddy@31 | 47 profileClientLookup: map[string][]uuid.ID{}, |
| paddy@41 | 48 endpoints: map[string][]Endpoint{}, |
| paddy@38 | 49 profiles: map[string]Profile{}, |
| paddy@44 | 50 logins: map[string]Login{}, |
| paddy@44 | 51 profileLoginLookup: map[string][]string{}, |
| paddy@77 | 52 sessions: map[string]Session{}, |
| paddy@28 | 53 } |
| paddy@28 | 54 } |
| paddy@28 | 55 |
| paddy@57 | 56 func (m *memstore) lookupTokenByRefresh(token string) (string, error) { |
| paddy@28 | 57 m.tokenLock.RLock() |
| paddy@28 | 58 defer m.tokenLock.RUnlock() |
| paddy@28 | 59 t, ok := m.refreshTokenLookup[token] |
| paddy@28 | 60 if !ok { |
| paddy@28 | 61 return "", ErrTokenNotFound |
| paddy@28 | 62 } |
| paddy@28 | 63 return t, nil |
| paddy@28 | 64 } |
| paddy@28 | 65 |
| paddy@57 | 66 func (m *memstore) lookupTokensByProfileID(id string) ([]string, error) { |
| paddy@28 | 67 m.tokenLock.RLock() |
| paddy@28 | 68 defer m.tokenLock.RUnlock() |
| paddy@28 | 69 return m.profileTokenLookup[id], nil |
| paddy@28 | 70 } |
| paddy@31 | 71 |
| paddy@57 | 72 func (m *memstore) lookupClientsByProfileID(id string) []uuid.ID { |
| paddy@31 | 73 m.clientLock.RLock() |
| paddy@31 | 74 defer m.clientLock.RUnlock() |
| paddy@33 | 75 c, ok := m.profileClientLookup[id] |
| paddy@33 | 76 if !ok { |
| paddy@33 | 77 return []uuid.ID{} |
| paddy@33 | 78 } |
| paddy@33 | 79 return c |
| paddy@31 | 80 } |