auth

Paddy 2014-09-01 Parent:9fc5fd8196b4 Child:607708cd8829

31:88523dab00a5 Go to Latest

auth/client.go

Implement ClientStore in Memstore. Add the ClientStore interface implementation to Memstore. Change the ClientStore interface's UpdateClient function to take a new type, ClientChange, rather than enumerating the arguments in the function signature, which is a much cleaner interface. Add tests for the successful (works-as-intended) scenarios involving ClientStores. Ignore UpdateClient for now--I want to do tests that test every combination of ClientUpdate attributes being specified, to be sure that only the attributes specified are updated and that all the attributes specified are updated.

History
1 package auth
3 import (
4 "errors"
6 "secondbit.org/uuid"
7 )
9 var (
10 ErrClientNotFound = errors.New("Client not found in ClientStore.")
11 ErrClientAlreadyExists = errors.New("Client already exists in ClientStore.")
12 )
14 // Client represents a client that grants access
15 // to the auth server, exchanging grants for tokens,
16 // and tokens for access.
17 type Client struct {
18 ID uuid.ID
19 Secret string
20 RedirectURI string
21 OwnerID uuid.ID
22 Name string
23 Logo string
24 Website string
25 }
27 type ClientChange struct {
28 Secret *string
29 RedirectURI *string
30 OwnerID uuid.ID
31 Name *string
32 Logo *string
33 Website *string
34 }
36 // ClientStore abstracts the storage interface for
37 // storing and retrieving Clients.
38 type ClientStore interface {
39 GetClient(id uuid.ID) (Client, error)
40 SaveClient(client Client) error
41 UpdateClient(id uuid.ID, change ClientChange) error
42 DeleteClient(id uuid.ID) error
43 ListClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error)
44 }
46 func (m *Memstore) GetClient(id uuid.ID) (Client, error) {
47 m.clientLock.RLock()
48 defer m.clientLock.RUnlock()
49 c, ok := m.clients[id.String()]
50 if !ok {
51 return Client{}, ErrClientNotFound
52 }
53 return c, nil
54 }
56 func (m *Memstore) SaveClient(client Client) error {
57 m.clientLock.Lock()
58 defer m.clientLock.Unlock()
59 if _, ok := m.clients[client.ID.String()]; ok {
60 return ErrClientAlreadyExists
61 }
62 m.clients[client.ID.String()] = client
63 m.profileClientLookup[client.OwnerID.String()] = append(m.profileClientLookup[client.OwnerID.String()], client.ID)
64 return nil
65 }
67 func (m *Memstore) UpdateClient(id uuid.ID, change ClientChange) error {
68 return nil
69 }
71 func (m *Memstore) DeleteClient(id uuid.ID) error {
72 client, err := m.GetClient(id)
73 if err != nil {
74 return err
75 }
76 m.clientLock.Lock()
77 defer m.clientLock.Unlock()
78 delete(m.clients, id.String())
79 pos := -1
80 for p, item := range m.profileClientLookup[client.OwnerID.String()] {
81 if item.Equal(id) {
82 pos = p
83 break
84 }
85 }
86 if pos >= 0 {
87 m.profileClientLookup[client.OwnerID.String()] = append(m.profileClientLookup[client.OwnerID.String()][:pos], m.profileClientLookup[client.OwnerID.String()][pos+1:]...)
88 }
89 return nil
90 }
92 func (m *Memstore) ListClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error) {
93 ids, err := m.lookupClientsByProfileID(ownerID.String())
94 if err != nil {
95 return []Client{}, err
96 }
97 if len(ids) > num+offset {
98 ids = ids[offset : num+offset]
99 } else if len(ids) > offset {
100 ids = ids[offset:]
101 } else {
102 return []Client{}, nil
103 }
104 clients := []Client{}
105 for _, id := range ids {
106 client, err := m.GetClient(id)
107 if err != nil {
108 return []Client{}, err
109 }
110 clients = append(clients, client)
111 }
112 return clients, nil
113 }