auth
auth/client.go
Create .hgignore. Don't store the cover.out files, but don't make me delete them every time I want to check my test coverage.
| 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@31 | 93 ids, err := m.lookupClientsByProfileID(ownerID.String()) |
| paddy@31 | 94 if err != nil { |
| paddy@31 | 95 return []Client{}, err |
| paddy@31 | 96 } |
| paddy@31 | 97 if len(ids) > num+offset { |
| paddy@31 | 98 ids = ids[offset : num+offset] |
| paddy@31 | 99 } else if len(ids) > offset { |
| paddy@31 | 100 ids = ids[offset:] |
| paddy@31 | 101 } else { |
| paddy@31 | 102 return []Client{}, nil |
| paddy@31 | 103 } |
| paddy@31 | 104 clients := []Client{} |
| paddy@31 | 105 for _, id := range ids { |
| paddy@31 | 106 client, err := m.GetClient(id) |
| paddy@31 | 107 if err != nil { |
| paddy@31 | 108 return []Client{}, err |
| paddy@31 | 109 } |
| paddy@31 | 110 clients = append(clients, client) |
| paddy@31 | 111 } |
| paddy@31 | 112 return clients, nil |
| paddy@31 | 113 } |