auth

Paddy 2014-09-07 Parent:88523dab00a5 Child:690561c6619a

33:607708cd8829 Go to Latest

auth/client.go

Add more tests for ClientStores. Test that deleting a client that doesn't exist throws an ErrClientNotFound. Test that adding a client twice returns an ErrClientAlreadyExists. Test that clients retrieve have properties that all match the client that was stored. Remove the unused error return from the internal MemoryStore helper for getting a list of clients by their OwnerID. If a profile doesn't exist, return an empty list of clients, as we're technically returning any client that has that OwnerID. There's no guarantee that that OwnerID is actually valid.

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