auth
auth/client.go
Further grant testing. Use the %T format to return the name of the GrantStore that failed the test, rather than just returning the position of the store. Test that storing a grant twice yields an ErrGrantAlreadyExists. Test that retrieving a grant that doesn't exist yields an ErrGrantNotFound. Compare returned grants against expectations.
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 := m.lookupClientsByProfileID(ownerID.String())
94 if len(ids) > num+offset {
95 ids = ids[offset : num+offset]
96 } else if len(ids) > offset {
97 ids = ids[offset:]
98 } else {
99 return []Client{}, nil
100 }
101 clients := []Client{}
102 for _, id := range ids {
103 client, err := m.GetClient(id)
104 if err != nil {
105 return []Client{}, err
106 }
107 clients = append(clients, client)
108 }
109 return clients, nil
110 }