Add comments suggested from PR review
Add tests to server/stores_test.gopull/2249/head
parent
9a548983d0
commit
cbbf9d96d7
|
@ -14,7 +14,7 @@ message Source {
|
|||
string MetaURL = 10; // MetaURL is the connection URL for the meta node.
|
||||
string SharedSecret = 11; // SharedSecret signs the optional InfluxDB JWT Authorization
|
||||
string Organization = 12; // Organization is the organization ID that resource belongs to
|
||||
string Role = 13; // Role is the name of the role that a user must posses to access the resource
|
||||
string Role = 13; // Role is the name of the miniumum role that a user must possess to access the resource
|
||||
}
|
||||
|
||||
message Dashboard {
|
||||
|
|
|
@ -450,7 +450,7 @@ type Source struct {
|
|||
Default bool `json:"default"` // Default specifies the default source for the application
|
||||
Telegraf string `json:"telegraf"` // Telegraf is the db telegraf is written to. By default it is "telegraf"
|
||||
Organization string `json:"organization"` // Organization is the organization ID that resource belongs to
|
||||
Role string `json:"role"` // Role is the name of the role that a user must posses to access the resource.
|
||||
Role string `json:"role"` // Role is the name of the minimum role that a user must possess to access the resource.
|
||||
}
|
||||
|
||||
// SourcesStore stores connection information for a `TimeSeries`
|
||||
|
|
|
@ -46,17 +46,17 @@ var (
|
|||
Name: MemberRoleName,
|
||||
}
|
||||
|
||||
// ViewerRole is the role for a user who can only perform READ operations on Dashboards, Rules, and Sources
|
||||
// ViewerRole is the role for a user who can only perform READ operations on Dashboards, Rules, Sources, and Servers,
|
||||
ViewerRole = chronograf.Role{
|
||||
Name: ViewerRoleName,
|
||||
}
|
||||
|
||||
// EditorRole is the role for a user who can perform READ and WRITE operations on Dashboards, Rules, and Sources
|
||||
// EditorRole is the role for a user who can perform READ and WRITE operations on Dashboards, Rules, Sources, and Servers.
|
||||
EditorRole = chronograf.Role{
|
||||
Name: EditorRoleName,
|
||||
}
|
||||
|
||||
// AdminRole is the role for a user who can perform READ and WRITE operations on Dashboards, Rules, Sources, and Users
|
||||
// AdminRole is the role for a user who can perform READ and WRITE operations on Dashboards, Rules, Sources, Servers, and Users
|
||||
AdminRole = chronograf.Role{
|
||||
Name: AdminRoleName,
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@ import (
|
|||
var _ chronograf.SourcesStore = &SourcesStore{}
|
||||
|
||||
// SourcesStore facade on a SourceStore that filters sources
|
||||
// by role.
|
||||
// by minimum role required to access the source.
|
||||
//
|
||||
// The role is passed around on the context and set when the
|
||||
// SourcesStore is instantiated.
|
||||
type SourcesStore struct {
|
||||
store chronograf.SourcesStore
|
||||
role string
|
||||
|
@ -110,6 +113,8 @@ func (s *SourcesStore) Update(ctx context.Context, d chronograf.Source) error {
|
|||
return s.store.Update(ctx, d)
|
||||
}
|
||||
|
||||
// hasAuthorizedRole checks that the role provided has at least
|
||||
// the minimum role required.
|
||||
func hasAuthorizedRole(sourceRole, providedRole string) bool {
|
||||
switch sourceRole {
|
||||
case ViewerRoleName:
|
||||
|
|
|
@ -69,7 +69,6 @@ func AuthorizedUser(
|
|||
return
|
||||
}
|
||||
ctx = context.WithValue(ctx, organizations.ContextKey, fmt.Sprintf("%d", defaultOrg.ID))
|
||||
// TODO(desa): remove this in place of actual string value
|
||||
ctx = context.WithValue(ctx, roles.ContextKey, roles.AdminRoleName)
|
||||
r = r.WithContext(ctx)
|
||||
next(w, r)
|
||||
|
|
|
@ -33,7 +33,7 @@ func TestStore_SourcesGet(t *testing.T) {
|
|||
wants wants
|
||||
}{
|
||||
{
|
||||
name: "Get user as super admin",
|
||||
name: "Get viewer source as viewer",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
|
@ -47,7 +47,6 @@ func TestStore_SourcesGet(t *testing.T) {
|
|||
},
|
||||
},
|
||||
args: args{
|
||||
superAdmin: true,
|
||||
organization: "0",
|
||||
role: "viewer",
|
||||
},
|
||||
|
@ -61,7 +60,236 @@ func TestStore_SourcesGet(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "Get user as super admin",
|
||||
name: "Get viewer source as editor",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "viewer",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "editor",
|
||||
},
|
||||
wants: wants{
|
||||
source: chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "viewer",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get viewer source as admin",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "viewer",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "admin",
|
||||
},
|
||||
wants: wants{
|
||||
source: chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "viewer",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get admin source as viewer",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "admin",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "viewer",
|
||||
},
|
||||
wants: wants{
|
||||
err: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get editor source as viewer",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "editor",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "viewer",
|
||||
},
|
||||
wants: wants{
|
||||
err: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get editor source as editor",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "editor",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "editor",
|
||||
},
|
||||
wants: wants{
|
||||
source: chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "editor",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get editor source as admin",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "editor",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "admin",
|
||||
},
|
||||
wants: wants{
|
||||
source: chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "editor",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get editor source as viewer",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "editor",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "viewer",
|
||||
},
|
||||
wants: wants{
|
||||
err: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get admin source as admin",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "admin",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "admin",
|
||||
},
|
||||
wants: wants{
|
||||
source: chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "admin",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get source as super admin",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "viewer",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
organization: "0",
|
||||
role: "viewer",
|
||||
superAdmin: true,
|
||||
},
|
||||
wants: wants{
|
||||
source: chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "viewer",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get source as super admin - no organization or role",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
|
@ -82,7 +310,29 @@ func TestStore_SourcesGet(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "Get user as super admin",
|
||||
name: "Get source as super admin - no role",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "my sweet name",
|
||||
Organization: "0",
|
||||
Role: "viewer",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
superAdmin: true,
|
||||
organization: "0",
|
||||
},
|
||||
wants: wants{
|
||||
err: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get source as super admin - no organization",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, id int) (chronograf.Source, error) {
|
||||
|
@ -97,6 +347,7 @@ func TestStore_SourcesGet(t *testing.T) {
|
|||
},
|
||||
args: args{
|
||||
superAdmin: true,
|
||||
role: "viewer",
|
||||
},
|
||||
wants: wants{
|
||||
err: true,
|
||||
|
|
|
@ -68,7 +68,7 @@ func (r *userRequest) ValidRoles() error {
|
|||
case roles.MemberRoleName, roles.ViewerRoleName, roles.EditorRoleName, roles.AdminRoleName:
|
||||
continue
|
||||
default:
|
||||
return fmt.Errorf("Unknown role %s. Valid roles are 'member', 'viewer', 'editor', 'admin', and 'superadmin'", r.Name)
|
||||
return fmt.Errorf("Unknown role %s. Valid roles are 'member', 'viewer', 'editor', and 'admin'", r.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -984,7 +984,7 @@ func TestUserRequest_ValidCreate(t *testing.T) {
|
|||
},
|
||||
},
|
||||
wantErr: true,
|
||||
err: fmt.Errorf("Unknown role BilliettaSpecialRole. Valid roles are 'member', 'viewer', 'editor', 'admin', and 'superadmin'"),
|
||||
err: fmt.Errorf("Unknown role BilliettaSpecialRole. Valid roles are 'member', 'viewer', 'editor', and 'admin'"),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue