auth
39:690561c6619a Browse Files
Include client updates and tests. Flesh out updating clients, and include unit tests to ensure that clientstores actually update appropriately. Add TODO comments where functionality is planned but stubbed out.
1.1 --- a/client.go Sun Sep 07 19:09:01 2014 -0400 1.2 +++ b/client.go Thu Sep 18 19:33:49 2014 -0400 1.3 @@ -24,6 +24,27 @@ 1.4 Website string 1.5 } 1.6 1.7 +func (c *Client) ApplyChange(change ClientChange) { 1.8 + if change.Secret != nil { 1.9 + c.Secret = *change.Secret 1.10 + } 1.11 + if change.RedirectURI != nil { 1.12 + c.RedirectURI = *change.RedirectURI 1.13 + } 1.14 + if change.OwnerID != nil { 1.15 + c.OwnerID = change.OwnerID 1.16 + } 1.17 + if change.Name != nil { 1.18 + c.Name = *change.Name 1.19 + } 1.20 + if change.Logo != nil { 1.21 + c.Logo = *change.Logo 1.22 + } 1.23 + if change.Website != nil { 1.24 + c.Website = *change.Website 1.25 + } 1.26 +} 1.27 + 1.28 type ClientChange struct { 1.29 Secret *string 1.30 RedirectURI *string 1.31 @@ -33,6 +54,11 @@ 1.32 Website *string 1.33 } 1.34 1.35 +func (c ClientChange) Validate() error { 1.36 + // TODO: validate client changes 1.37 + return nil 1.38 +} 1.39 + 1.40 // ClientStore abstracts the storage interface for 1.41 // storing and retrieving Clients. 1.42 type ClientStore interface { 1.43 @@ -65,6 +91,14 @@ 1.44 } 1.45 1.46 func (m *Memstore) UpdateClient(id uuid.ID, change ClientChange) error { 1.47 + m.clientLock.Lock() 1.48 + defer m.clientLock.Unlock() 1.49 + c, ok := m.clients[id.String()] 1.50 + if !ok { 1.51 + return ErrClientNotFound 1.52 + } 1.53 + c.ApplyChange(change) 1.54 + m.clients[id.String()] = c 1.55 return nil 1.56 } 1.57
2.1 --- a/client_test.go Sun Sep 07 19:09:01 2014 -0400 2.2 +++ b/client_test.go Thu Sep 18 19:33:49 2014 -0400 2.3 @@ -1,11 +1,21 @@ 2.4 package auth 2.5 2.6 import ( 2.7 + "fmt" 2.8 "testing" 2.9 2.10 "secondbit.org/uuid" 2.11 ) 2.12 2.13 +const ( 2.14 + clientChangeSecret = 1 << iota 2.15 + clientChangeRedirectURI 2.16 + clientChangeOwnerID 2.17 + clientChangeName 2.18 + clientChangeLogo 2.19 + clientChangeWebsite 2.20 +) 2.21 + 2.22 var clientStores = []ClientStore{NewMemstore()} 2.23 2.24 func compareClients(client1, client2 Client) (success bool, field string, val1, val2 interface{}) { 2.25 @@ -93,3 +103,83 @@ 2.26 } 2.27 } 2.28 } 2.29 + 2.30 +func TestClientUpdates(t *testing.T) { 2.31 + t.Parallel() 2.32 + variations := 1 << 10 2.33 + client := Client{ 2.34 + ID: uuid.NewID(), 2.35 + Secret: "secret", 2.36 + RedirectURI: "redirectURI", 2.37 + OwnerID: uuid.NewID(), 2.38 + Name: "name", 2.39 + Logo: "logo", 2.40 + Website: "website", 2.41 + } 2.42 + for i := 0; i < variations; i++ { 2.43 + var secret, redirectURI, name, logo, website string 2.44 + change := ClientChange{} 2.45 + expectation := client 2.46 + result := client 2.47 + if i&clientChangeSecret != 0 { 2.48 + secret = fmt.Sprintf("secret-%d", i) 2.49 + change.Secret = &secret 2.50 + expectation.Secret = secret 2.51 + } 2.52 + if i&clientChangeRedirectURI != 0 { 2.53 + redirectURI = fmt.Sprintf("redirect-uri-%d", i) 2.54 + change.RedirectURI = &redirectURI 2.55 + expectation.RedirectURI = redirectURI 2.56 + } 2.57 + if i&clientChangeOwnerID != 0 { 2.58 + change.OwnerID = uuid.NewID() 2.59 + expectation.OwnerID = change.OwnerID 2.60 + } 2.61 + if i&clientChangeName != 0 { 2.62 + name = fmt.Sprintf("name-%d", i) 2.63 + change.Name = &name 2.64 + expectation.Name = name 2.65 + } 2.66 + if i&clientChangeLogo != 0 { 2.67 + logo = fmt.Sprintf("logo-%d", i) 2.68 + change.Logo = &logo 2.69 + expectation.Logo = logo 2.70 + } 2.71 + if i&clientChangeWebsite != 0 { 2.72 + website = fmt.Sprintf("website-%d", i) 2.73 + change.Website = &website 2.74 + expectation.Website = website 2.75 + } 2.76 + result.ApplyChange(change) 2.77 + match, field, expected, got := compareClients(expectation, result) 2.78 + if !match { 2.79 + t.Errorf("Expected field `%s` to be `%v`, got `%v`", field, expected, got) 2.80 + } 2.81 + for _, store := range clientStores { 2.82 + err := store.SaveClient(client) 2.83 + if err != nil { 2.84 + t.Errorf("Error saving client in %T: %s", store, err) 2.85 + } 2.86 + err = store.UpdateClient(client.ID, change) 2.87 + if err != nil { 2.88 + t.Errorf("Error updating client in %T: %s", store, err) 2.89 + } 2.90 + retrieved, err := store.GetClient(client.ID) 2.91 + if err != nil { 2.92 + t.Errorf("Error getting profile from %T: %s", store, err) 2.93 + } 2.94 + match, field, expected, got = compareClients(expectation, retrieved) 2.95 + if !match { 2.96 + t.Errorf("Expected field `%s` to be `%v`, got `%v` from %T", field, expected, got, store) 2.97 + } 2.98 + err = store.DeleteClient(client.ID) 2.99 + if err != nil { 2.100 + t.Errorf("Error deleting client from %T: %s", store, err) 2.101 + } 2.102 + err = store.UpdateClient(client.ID, change) 2.103 + if err != ErrClientNotFound { 2.104 + t.Errorf("Expected ErrClientNotFound, got %v from %T", err, store) 2.105 + } 2.106 + } 2.107 + } 2.108 +}