auth
auth/memstore.go
Do a first, naive pass at storing profiles in Postgres. This is untested against an actual database. It's a best-guess attempt at SQL. It _should_ work. I think. Start storing things in Postgres, starting with Profiles and Logins. This necessitates the addition of a Deleted property to the Profile type, because I'm not deleting those in case of accidental deletion. Logins, though, we'll delete. This also necessitates updating the profileStore interface to no longer have a deleteProfile method, because we're tracking that through updates now. Then we need to update our profileStore tests, because they no longer clean up after themselves. Which, come to think of it, may cause some problems later.
| 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@134 | 34 |
| paddy@134 | 35 scopes map[string]Scope |
| paddy@134 | 36 scopeLock sync.RWMutex |
| paddy@28 | 37 } |
| paddy@28 | 38 |
| paddy@57 | 39 // NewMemstore returns an in-memory version of our datastores, |
| paddy@57 | 40 // which is handy for tests. Though the implementation is concurrency-safe, |
| paddy@57 | 41 // if makes no attempt to persist the data, and therefore it is inadvisable |
| paddy@57 | 42 // to use it in a production setting. |
| paddy@57 | 43 func NewMemstore() *memstore { |
| paddy@57 | 44 return &memstore{ |
| paddy@31 | 45 tokens: map[string]Token{}, |
| paddy@31 | 46 refreshTokenLookup: map[string]string{}, |
| paddy@31 | 47 profileTokenLookup: map[string][]string{}, |
| paddy@87 | 48 authCodes: map[string]AuthorizationCode{}, |
| paddy@31 | 49 clients: map[string]Client{}, |
| paddy@31 | 50 profileClientLookup: map[string][]uuid.ID{}, |
| paddy@41 | 51 endpoints: map[string][]Endpoint{}, |
| paddy@38 | 52 profiles: map[string]Profile{}, |
| paddy@44 | 53 logins: map[string]Login{}, |
| paddy@44 | 54 profileLoginLookup: map[string][]string{}, |
| paddy@77 | 55 sessions: map[string]Session{}, |
| paddy@134 | 56 scopes: map[string]Scope{}, |
| paddy@28 | 57 } |
| paddy@28 | 58 } |
| paddy@28 | 59 |
| paddy@57 | 60 func (m *memstore) lookupTokenByRefresh(token string) (string, error) { |
| paddy@28 | 61 m.tokenLock.RLock() |
| paddy@28 | 62 defer m.tokenLock.RUnlock() |
| paddy@28 | 63 t, ok := m.refreshTokenLookup[token] |
| paddy@28 | 64 if !ok { |
| paddy@28 | 65 return "", ErrTokenNotFound |
| paddy@28 | 66 } |
| paddy@28 | 67 return t, nil |
| paddy@28 | 68 } |
| paddy@28 | 69 |
| paddy@57 | 70 func (m *memstore) lookupTokensByProfileID(id string) ([]string, error) { |
| paddy@28 | 71 m.tokenLock.RLock() |
| paddy@28 | 72 defer m.tokenLock.RUnlock() |
| paddy@28 | 73 return m.profileTokenLookup[id], nil |
| paddy@28 | 74 } |
| paddy@31 | 75 |
| paddy@57 | 76 func (m *memstore) lookupClientsByProfileID(id string) []uuid.ID { |
| paddy@31 | 77 m.clientLock.RLock() |
| paddy@31 | 78 defer m.clientLock.RUnlock() |
| paddy@33 | 79 c, ok := m.profileClientLookup[id] |
| paddy@33 | 80 if !ok { |
| paddy@33 | 81 return []uuid.ID{} |
| paddy@33 | 82 } |
| paddy@33 | 83 return c |
| paddy@31 | 84 } |