auth

Paddy 2014-09-18 Parent:690561c6619a Child:113ccb15b919

40:0b86c2d3ec75 Go to Latest

auth/client.go

Add TODOs. Add TODO comments where functionality is stubbed out or anticipated, but work is needed to implement it.

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@39 27 func (c *Client) ApplyChange(change ClientChange) {
paddy@39 28 if change.Secret != nil {
paddy@39 29 c.Secret = *change.Secret
paddy@39 30 }
paddy@39 31 if change.RedirectURI != nil {
paddy@39 32 c.RedirectURI = *change.RedirectURI
paddy@39 33 }
paddy@39 34 if change.OwnerID != nil {
paddy@39 35 c.OwnerID = change.OwnerID
paddy@39 36 }
paddy@39 37 if change.Name != nil {
paddy@39 38 c.Name = *change.Name
paddy@39 39 }
paddy@39 40 if change.Logo != nil {
paddy@39 41 c.Logo = *change.Logo
paddy@39 42 }
paddy@39 43 if change.Website != nil {
paddy@39 44 c.Website = *change.Website
paddy@39 45 }
paddy@39 46 }
paddy@39 47
paddy@31 48 type ClientChange struct {
paddy@31 49 Secret *string
paddy@31 50 RedirectURI *string
paddy@31 51 OwnerID uuid.ID
paddy@31 52 Name *string
paddy@31 53 Logo *string
paddy@31 54 Website *string
paddy@31 55 }
paddy@31 56
paddy@39 57 func (c ClientChange) Validate() error {
paddy@39 58 // TODO: validate client changes
paddy@39 59 return nil
paddy@39 60 }
paddy@39 61
paddy@25 62 // ClientStore abstracts the storage interface for
paddy@25 63 // storing and retrieving Clients.
paddy@25 64 type ClientStore interface {
paddy@25 65 GetClient(id uuid.ID) (Client, error)
paddy@25 66 SaveClient(client Client) error
paddy@31 67 UpdateClient(id uuid.ID, change ClientChange) error
paddy@25 68 DeleteClient(id uuid.ID) error
paddy@31 69 ListClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error)
paddy@0 70 }
paddy@31 71
paddy@31 72 func (m *Memstore) GetClient(id uuid.ID) (Client, error) {
paddy@31 73 m.clientLock.RLock()
paddy@31 74 defer m.clientLock.RUnlock()
paddy@31 75 c, ok := m.clients[id.String()]
paddy@31 76 if !ok {
paddy@31 77 return Client{}, ErrClientNotFound
paddy@31 78 }
paddy@31 79 return c, nil
paddy@31 80 }
paddy@31 81
paddy@31 82 func (m *Memstore) SaveClient(client Client) error {
paddy@31 83 m.clientLock.Lock()
paddy@31 84 defer m.clientLock.Unlock()
paddy@31 85 if _, ok := m.clients[client.ID.String()]; ok {
paddy@31 86 return ErrClientAlreadyExists
paddy@31 87 }
paddy@31 88 m.clients[client.ID.String()] = client
paddy@31 89 m.profileClientLookup[client.OwnerID.String()] = append(m.profileClientLookup[client.OwnerID.String()], client.ID)
paddy@31 90 return nil
paddy@31 91 }
paddy@31 92
paddy@31 93 func (m *Memstore) UpdateClient(id uuid.ID, change ClientChange) error {
paddy@39 94 m.clientLock.Lock()
paddy@39 95 defer m.clientLock.Unlock()
paddy@39 96 c, ok := m.clients[id.String()]
paddy@39 97 if !ok {
paddy@39 98 return ErrClientNotFound
paddy@39 99 }
paddy@39 100 c.ApplyChange(change)
paddy@39 101 m.clients[id.String()] = c
paddy@31 102 return nil
paddy@31 103 }
paddy@31 104
paddy@31 105 func (m *Memstore) DeleteClient(id uuid.ID) error {
paddy@31 106 client, err := m.GetClient(id)
paddy@31 107 if err != nil {
paddy@31 108 return err
paddy@31 109 }
paddy@31 110 m.clientLock.Lock()
paddy@31 111 defer m.clientLock.Unlock()
paddy@31 112 delete(m.clients, id.String())
paddy@31 113 pos := -1
paddy@31 114 for p, item := range m.profileClientLookup[client.OwnerID.String()] {
paddy@31 115 if item.Equal(id) {
paddy@31 116 pos = p
paddy@31 117 break
paddy@31 118 }
paddy@31 119 }
paddy@31 120 if pos >= 0 {
paddy@31 121 m.profileClientLookup[client.OwnerID.String()] = append(m.profileClientLookup[client.OwnerID.String()][:pos], m.profileClientLookup[client.OwnerID.String()][pos+1:]...)
paddy@31 122 }
paddy@31 123 return nil
paddy@31 124 }
paddy@31 125
paddy@31 126 func (m *Memstore) ListClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error) {
paddy@33 127 ids := m.lookupClientsByProfileID(ownerID.String())
paddy@31 128 if len(ids) > num+offset {
paddy@31 129 ids = ids[offset : num+offset]
paddy@31 130 } else if len(ids) > offset {
paddy@31 131 ids = ids[offset:]
paddy@31 132 } else {
paddy@31 133 return []Client{}, nil
paddy@31 134 }
paddy@31 135 clients := []Client{}
paddy@31 136 for _, id := range ids {
paddy@31 137 client, err := m.GetClient(id)
paddy@31 138 if err != nil {
paddy@31 139 return []Client{}, err
paddy@31 140 }
paddy@31 141 clients = append(clients, client)
paddy@31 142 }
paddy@31 143 return clients, nil
paddy@31 144 }