diff --git a/rbac/sessions_test.go b/rbac/sessions_test.go index e1ec34d2b..19e482c3e 100644 --- a/rbac/sessions_test.go +++ b/rbac/sessions_test.go @@ -30,7 +30,7 @@ func TestSessions(t *testing.T) { return } - if err := users.Assign("test-user", "test-role"); err != nil { + if err := users.AddRole("test-user", "test-role"); err != nil { t.Errorf("Unexpected error when assigning test-role to test-user, %+v", err) return } diff --git a/rbac/users.go b/rbac/users.go index 60e958f3c..6bb32da4b 100644 --- a/rbac/users.go +++ b/rbac/users.go @@ -1,6 +1,7 @@ package rbac import ( + "fmt" "encoding/json" "github.com/crusttech/crust/rbac/types" "github.com/pkg/errors" @@ -16,16 +17,26 @@ type ( Get(username string) (*types.User, error) Delete(username string) error - Assign(username string, roles []string) error + AddRole(username string, roles ...string) error + RemoveRole(username string, roles ...string) error } ) +const ( + usersCreate = "/users/%s" + usersGet = "/users/%s" + usersDelete = "/users/%s" + // @todo: plural for users, but singular for sessions + usersAddRole = "/users/%s/assignRoles" + usersRemoveRole = "/users/%s/deassignRoles" +) + func (u *Users) Create(username, password string) error { body := struct { Password string `json:"password"` }{password} - resp, err := u.Client.Post("/users/"+username, body) + resp, err := u.Client.Post(fmt.Sprintf(usersCreate, username), body) if err != nil { return errors.Wrap(err, "request failed") } @@ -38,12 +49,12 @@ func (u *Users) Create(username, password string) error { } } -func (u *Users) Assign(username string, roles []string) error { +func (u *Users) AddRole(username string, roles ...string) error { body := struct { Roles []string `json:"roles"` }{roles} - resp, err := u.Client.Patch("/users/"+username+"/assignRoles", body) + resp, err := u.Client.Patch(fmt.Sprintf(usersAddRole, username), body) if err != nil { return errors.Wrap(err, "request failed") } @@ -56,12 +67,12 @@ func (u *Users) Assign(username string, roles []string) error { } } -func (u *Users) Deassign(username string, roles []string) error { +func (u *Users) RemoveRole(username string, roles ...string) error { body := struct { Roles []string `json:"roles"` }{roles} - resp, err := u.Client.Patch("/users/"+username+"/deassignRoles", body) + resp, err := u.Client.Patch(fmt.Sprintf(usersRemoveRole, username), body) if err != nil { return errors.Wrap(err, "request failed") } @@ -75,7 +86,7 @@ func (u *Users) Deassign(username string, roles []string) error { } func (u *Users) Get(username string) (*types.User, error) { - resp, err := u.Client.Get("/users/" + username) + resp, err := u.Client.Get(fmt.Sprintf(usersGet, username)) if err != nil { return nil, errors.Wrap(err, "request failed") } @@ -90,7 +101,7 @@ func (u *Users) Get(username string) (*types.User, error) { } func (u *Users) Delete(username string) error { - resp, err := u.Client.Delete("/users/" + username) + resp, err := u.Client.Delete(fmt.Sprintf(usersDelete, username)) if err != nil { return errors.Wrap(err, "request failed") } diff --git a/rbac/users_test.go b/rbac/users_test.go index 41b9b6519..edf29b7bf 100644 --- a/rbac/users_test.go +++ b/rbac/users_test.go @@ -9,24 +9,75 @@ func TestUsers(t *testing.T) { if err != nil { t.Errorf("Unexpected error when creating RBAC instance: %+v", err) } - rbac.Debug(false) + rbac.Debug("info") users := rbac.Users() + roles := rbac.Roles() + users.Delete("test-user") + roles.Delete("test-role") + + if err := roles.Create("test-role"); err != nil { + t.Errorf("Unexpected error when creating test-role, %+v", err) + return + } if err := users.Create("test-user", "test-password"); err != nil { t.Errorf("Error when creating test-user: %+v", err) } + // check if we inherited some roles (should be empty) + { + user, err := users.Get("test-user") + if !assert(t, err == nil, "Unexpected error when retrieving test-user 1, %+v", err) { + return + } + assert(t, user.Username == "test-user", "Unexpected username, test-user != '%s'", user.Username) + assert(t, len(user.AssignedRoles) == 0, "Unexpected number of roles, expected empty, got %+v", user.AssignedRoles) + } + + if err := users.AddRole("test-user", "test-role"); err != nil { + t.Errorf("Unexpected error when assigning test-role to test-user 2, %+v", err) + return + } + + // check if we inherited some roles (should be empty) + { + user, err := users.Get("test-user") + if !assert(t, err == nil, "Unexpected error when retrieving test-user 3, %+v", err) { + return + } + assert(t, user.Username == "test-user", "Unexpected username, test-user != '%s'", user.Username) + if !assert(t, len(user.AssignedRoles) == 1, "Unexpected number of roles, expected 1, got %+v", user.AssignedRoles) { + return + } + assert(t, user.AssignedRoles[0] == "test-role", "Unexpected role name, test-role != '%s'", user.AssignedRoles[0]) + } + + if err := users.RemoveRole("test-user", "test-role"); err != nil { + t.Errorf("Unexpected error when deassigning test-role to test-user, %+v", err) + return + } + + // check roles are empty after de-assign + { + user, err := users.Get("test-user") + if !assert(t, err == nil, "Unexpected error when retrieving test-user 4, %+v", err) { + return + } + assert(t, user.Username == "test-user", "Unexpected username, test-user != '%s'", user.Username) + assert(t, len(user.AssignedRoles) == 0, "Unexpected number of roles, expected empty, got %+v", user.AssignedRoles) + } + if err := users.Delete("test-user"); err != nil { t.Errorf("Error when deleting test-user: %+v", err) } - if _, err := users.Get("non-existant"); err == nil { + if _, err := users.Get("test-user"); err == nil { t.Errorf("Expected error on retrieving a non-existant user") } - if err := users.Delete("non-existant"); err == nil { + if err := users.Delete("test-user"); err == nil { t.Errorf("Expected error on deleting a non-existant user") } }