auth

Paddy 2015-04-25 Parent:d103a598548c Child:b7e685839a1b

164:cf1aef6eb81f Go to Latest

auth/memstore.go

Clean up after Client deletion, finish cleaning up after Profile deletion. 6f473576c6ae started cleaning up after Profiles when they're deleted, but didn't clean up the Clients created by that Profile. This fixes that, and also fixes a BUG note about cleaning up after a Client when it's deleted. Extend the authorizationCodeStore to have a deleteAuthorizationCodesByClientID method that will delete the AuthorizationCodes that have been granted by the Client specified by the passed ID. We also implemented this in memstore and postgres, so tests continue to pass. Extend the clientStore to have a deleteClientsByOwner method that will delete the Clients that were created by the Profile specified by the passed ID. We also implemented this in memstore and postgres, so tests continue to pass. Extend the clientStore to have a removeEndpointsByClientID method that will delete the Endpoints that belong(ed) to a the Client specified by the passed ID. We also implemented this in memstore and postgres, so tests continue to pass. Extend the tokenStore to have a revokeTokensByClientID method that will revoke all the Tokens that were granted to the Client specified by the passed ID. We also implemented this in memstore and postgres, so tests continue to pass. When listing Clients by their owner, allow setting the num argument (which controls how many to return) to 0 or lower, and using that to signal "return all Clients belonging to this owner", instead of paging. This is useful when deleting the Clients belonging to a Profile as part of the cleanup after deleting the Profile. Create a cleanUpAfterClientDeletion helper function that will delete the Endpoints and AuthorizationCodes belonging to a Client, and revoke the Tokens belonging to a Client, as part of cleaning up after a Client has been deleted. Add a check in the handler for listing Clients owned by a Profile to disallow the num argument to be lower than 1, because the API should be forced to page. Call our cleanUpAfterClientDeletion once the Client has been deleted in the appropriate handler. Fill out our Context with new methods to wrap all the new methods we're adding to our *Stores. In cleanUpAfterProfileDeletion, obtain a list of clients belonging to the owner, use our new DeleteClientsByOwner method to remove all of them, and then use the list to run our new cleanUpAfterClientDeletion function to clear away the final remnants of a Profile when it's deleted.

History
1 package auth
3 import (
4 "sync"
6 "code.secondbit.org/uuid.hg"
7 )
9 type memstore struct {
10 tokens map[string]Token
11 refreshTokenLookup map[string]string
12 profileTokenLookup map[string][]string
13 tokenLock sync.RWMutex
15 authCodes map[string]AuthorizationCode
16 authCodeLock sync.RWMutex
18 clients map[string]Client
19 profileClientLookup map[string][]uuid.ID
20 clientLock sync.RWMutex
22 endpoints map[string][]Endpoint
23 endpointLock sync.RWMutex
25 profiles map[string]Profile
26 profileLock sync.RWMutex
28 logins map[string]Login
29 profileLoginLookup map[string][]string
30 loginLock sync.RWMutex
32 sessions map[string]Session
33 sessionLock sync.RWMutex
35 scopes map[string]Scope
36 scopeLock sync.RWMutex
37 }
39 // NewMemstore returns an in-memory version of our datastores,
40 // which is handy for tests. Though the implementation is concurrency-safe,
41 // if makes no attempt to persist the data, and therefore it is inadvisable
42 // to use it in a production setting.
43 func NewMemstore() *memstore {
44 return &memstore{
45 tokens: map[string]Token{},
46 refreshTokenLookup: map[string]string{},
47 profileTokenLookup: map[string][]string{},
48 authCodes: map[string]AuthorizationCode{},
49 clients: map[string]Client{},
50 profileClientLookup: map[string][]uuid.ID{},
51 endpoints: map[string][]Endpoint{},
52 profiles: map[string]Profile{},
53 logins: map[string]Login{},
54 profileLoginLookup: map[string][]string{},
55 sessions: map[string]Session{},
56 scopes: map[string]Scope{},
57 }
58 }
60 func (m *memstore) lookupTokenByRefresh(token string) (string, error) {
61 m.tokenLock.RLock()
62 defer m.tokenLock.RUnlock()
63 t, ok := m.refreshTokenLookup[token]
64 if !ok {
65 return "", ErrTokenNotFound
66 }
67 return t, nil
68 }
70 func (m *memstore) lookupTokensByProfileID(id string) ([]string, error) {
71 m.tokenLock.RLock()
72 defer m.tokenLock.RUnlock()
73 return m.profileTokenLookup[id], nil
74 }
76 func (m *memstore) lookupClientsByProfileID(id string) []uuid.ID {
77 m.clientLock.RLock()
78 defer m.clientLock.RUnlock()
79 c, ok := m.profileClientLookup[id]
80 if !ok {
81 return []uuid.ID{}
82 }
83 return c
84 }