diff --git a/roles/roles.go b/roles/roles.go index d531b1684..6842a8c95 100644 --- a/roles/roles.go +++ b/roles/roles.go @@ -9,6 +9,7 @@ const ContextKey = contextKey("role") // Chronograf User Roles const ( MemberRoleName = "member" + ReaderRoleName = "reader" ViewerRoleName = "viewer" EditorRoleName = "editor" AdminRoleName = "admin" diff --git a/server/auth.go b/server/auth.go index 986dac36c..2eb0825b5 100644 --- a/server/auth.go +++ b/server/auth.go @@ -293,7 +293,6 @@ func AuthorizedUser( } Error(w, http.StatusForbidden, "User is not authorized", logger) - return }) } @@ -306,7 +305,14 @@ func hasAuthorizedRole(u *chronograf.User, role string) bool { case roles.MemberRoleName: for _, r := range u.Roles { switch r.Name { - case roles.MemberRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName: + case roles.MemberRoleName, roles.ReaderRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName: + return true + } + } + case roles.ReaderRoleName: + for _, r := range u.Roles { + switch r.Name { + case roles.ReaderRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName: return true } } diff --git a/server/auth_test.go b/server/auth_test.go index c73ab394d..28839b8c9 100644 --- a/server/auth_test.go +++ b/server/auth_test.go @@ -193,6 +193,62 @@ func TestAuthorizedUser(t *testing.T) { hasRoleContext: true, hasServerContext: false, }, + { + name: "User with reader role is member authorized", + fields: fields{ + UsersStore: &mocks.UsersStore{ + GetF: func(ctx context.Context, q chronograf.UserQuery) (*chronograf.User, error) { + if q.Name == nil || q.Provider == nil || q.Scheme == nil { + return nil, fmt.Errorf("Invalid user query: missing Name, Provider, and/or Scheme") + } + return &chronograf.User{ + ID: 1337, + Name: "billysteve", + Provider: "google", + Scheme: "oauth2", + Roles: []chronograf.Role{ + { + Name: roles.ReaderRoleName, + Organization: "1337", + }, + }, + }, nil + }, + }, + OrganizationsStore: &mocks.OrganizationsStore{ + DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) { + return &chronograf.Organization{ + ID: "0", + }, nil + }, + GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) { + if q.ID == nil { + return nil, fmt.Errorf("Invalid organization query: missing ID") + } + return &chronograf.Organization{ + ID: "1337", + Name: "The ShillBillThrilliettas", + }, nil + }, + }, + Logger: clog.New(clog.DebugLevel), + }, + args: args{ + principal: &oauth2.Principal{ + Subject: "billysteve", + Issuer: "google", + Organization: "1337", + }, + scheme: "oauth2", + role: "member", + useAuth: true, + }, + authorized: true, + hasOrganizationContext: true, + hasSuperAdminContext: false, + hasRoleContext: true, + hasServerContext: false, + }, { name: "User with viewer role is member authorized", fields: fields{ diff --git a/server/organizations.go b/server/organizations.go index d9e223954..c4d60021c 100644 --- a/server/organizations.go +++ b/server/organizations.go @@ -43,10 +43,10 @@ func (r *organizationRequest) ValidDefaultRole() error { } switch r.DefaultRole { - case roles.MemberRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName: + case roles.MemberRoleName, roles.ReaderRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName: return nil default: - return fmt.Errorf("default role must be member, viewer, editor, or admin") + return fmt.Errorf("default role must be member, reader, viewer, editor, or admin") } } diff --git a/server/organizations_test.go b/server/organizations_test.go index 2f134acc0..fa3e0898c 100644 --- a/server/organizations_test.go +++ b/server/organizations_test.go @@ -385,7 +385,7 @@ func TestService_UpdateOrganization(t *testing.T) { id: "1337", wantStatus: http.StatusUnprocessableEntity, wantContentType: "application/json", - wantBody: `{"code":422,"message":"default role must be member, viewer, editor, or admin"}`, + wantBody: `{"code":422,"message":"default role must be member, reader, viewer, editor, or admin"}`, }, } diff --git a/server/stores.go b/server/stores.go index ecaee0a2c..4c65dfabf 100644 --- a/server/stores.go +++ b/server/stores.go @@ -40,7 +40,7 @@ func hasRoleContext(ctx context.Context) (string, bool) { return "", false } switch role { - case roles.MemberRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName: + case roles.MemberRoleName, roles.ReaderRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName: return role, true default: return "", false diff --git a/server/users.go b/server/users.go index 480fa3ea6..5ede6c75e 100644 --- a/server/users.go +++ b/server/users.go @@ -59,10 +59,10 @@ func (r *userRequest) ValidRoles() error { } orgs[r.Organization] = true switch r.Name { - case roles.MemberRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName, roles.WildcardRoleName: + case roles.MemberRoleName, roles.ReaderRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName, roles.WildcardRoleName: continue default: - return fmt.Errorf("Unknown role %s. Valid roles are 'member', 'viewer', 'editor', 'admin', and '*'", r.Name) + return fmt.Errorf("Unknown role %s. Valid roles are 'member', 'reader', 'viewer', 'editor', 'admin', and '*'", r.Name) } } } diff --git a/server/users_test.go b/server/users_test.go index eda9b58ce..a841e027d 100644 --- a/server/users_test.go +++ b/server/users_test.go @@ -1702,7 +1702,7 @@ func TestUserRequest_ValidCreate(t *testing.T) { }, }, wantErr: true, - err: fmt.Errorf("Unknown role BilliettaSpecialRole. Valid roles are 'member', 'viewer', 'editor', 'admin', and '*'"), + err: fmt.Errorf("Unknown role BilliettaSpecialRole. Valid roles are 'member', 'reader', 'viewer', 'editor', 'admin', and '*'"), }, { name: "Invalid roles - missing organization", @@ -1792,7 +1792,7 @@ func TestUserRequest_ValidUpdate(t *testing.T) { }, }, wantErr: true, - err: fmt.Errorf("Unknown role BillietaSpecialOrg. Valid roles are 'member', 'viewer', 'editor', 'admin', and '*'"), + err: fmt.Errorf("Unknown role BillietaSpecialOrg. Valid roles are 'member', 'reader', 'viewer', 'editor', 'admin', and '*'"), }, { name: "Valid – roles empty", @@ -1824,7 +1824,7 @@ func TestUserRequest_ValidUpdate(t *testing.T) { }, }, wantErr: true, - err: fmt.Errorf("Unknown role BillietaSpecialOrg. Valid roles are 'member', 'viewer', 'editor', 'admin', and '*'"), + err: fmt.Errorf("Unknown role BillietaSpecialOrg. Valid roles are 'member', 'reader', 'viewer', 'editor', 'admin', and '*'"), }, { name: "Invalid - duplicate organization",