Apply mapping to user in /me
parent
c833020944
commit
0b89623db8
|
@ -1303,6 +1303,201 @@ func TestServer(t *testing.T) {
|
|||
"code": 401,
|
||||
"message": "user cannot modify their own SuperAdmin status"
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GET /me",
|
||||
subName: "New user hits me for the first time",
|
||||
fields: fields{
|
||||
Config: &chronograf.Config{
|
||||
Auth: chronograf.AuthConfig{
|
||||
SuperAdminNewUsers: false,
|
||||
},
|
||||
},
|
||||
Organizations: []chronograf.Organization{
|
||||
{
|
||||
ID: "1",
|
||||
Name: "Sweet",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.EditorRoleName,
|
||||
},
|
||||
chronograf.Mapping{
|
||||
Provider: "github",
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: "influxdata",
|
||||
GrantedRole: roles.AdminRoleName,
|
||||
},
|
||||
chronograf.Mapping{
|
||||
Provider: "github",
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: "mimi",
|
||||
GrantedRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "2",
|
||||
Name: "What",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.MemberRoleName,
|
||||
},
|
||||
chronograf.Mapping{
|
||||
Provider: "github",
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: "mimi",
|
||||
GrantedRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "3",
|
||||
Name: "Okay",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Mappings: []chronograf.Mapping{},
|
||||
},
|
||||
},
|
||||
Users: []chronograf.User{
|
||||
{
|
||||
ID: 1, // This is artificial, but should be reflective of the users actual ID
|
||||
Name: "billibob",
|
||||
Provider: "github",
|
||||
Scheme: "oauth2",
|
||||
SuperAdmin: true,
|
||||
Roles: []chronograf.Role{
|
||||
{
|
||||
Name: "admin",
|
||||
Organization: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
server: &server.Server{
|
||||
GithubClientID: "not empty",
|
||||
GithubClientSecret: "not empty",
|
||||
},
|
||||
method: "GET",
|
||||
path: "/chronograf/v1/me",
|
||||
principal: oauth2.Principal{
|
||||
Subject: "billietta",
|
||||
Issuer: "github",
|
||||
Group: "influxdata,idk,mimi",
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
statusCode: 200,
|
||||
body: `
|
||||
{
|
||||
"id": "2",
|
||||
"name": "billietta",
|
||||
"roles": [
|
||||
{
|
||||
"name": "admin",
|
||||
"organization": "1"
|
||||
},
|
||||
{
|
||||
"name": "viewer",
|
||||
"organization": "2"
|
||||
},
|
||||
{
|
||||
"name": "member",
|
||||
"organization": "default"
|
||||
}
|
||||
],
|
||||
"provider": "github",
|
||||
"scheme": "oauth2",
|
||||
"links": {
|
||||
"self": "/chronograf/v1/users/2"
|
||||
},
|
||||
"organizations": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Sweet",
|
||||
"defaultRole": "viewer",
|
||||
"public": false,
|
||||
"mappings": [
|
||||
{
|
||||
"provider": "*",
|
||||
"scheme": "*",
|
||||
"group": "*",
|
||||
"grantedRole": "editor"
|
||||
},
|
||||
{
|
||||
"provider": "github",
|
||||
"scheme": "*",
|
||||
"group": "influxdata",
|
||||
"grantedRole": "admin"
|
||||
},
|
||||
{
|
||||
"provider": "github",
|
||||
"scheme": "*",
|
||||
"group": "mimi",
|
||||
"grantedRole": "viewer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "What",
|
||||
"defaultRole": "viewer",
|
||||
"public": false,
|
||||
"mappings": [
|
||||
{
|
||||
"provider": "*",
|
||||
"scheme": "*",
|
||||
"group": "*",
|
||||
"grantedRole": "member"
|
||||
},
|
||||
{
|
||||
"provider": "github",
|
||||
"scheme": "*",
|
||||
"group": "mimi",
|
||||
"grantedRole": "viewer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "default",
|
||||
"name": "Default",
|
||||
"defaultRole": "member",
|
||||
"public": true,
|
||||
"mappings": [
|
||||
{
|
||||
"provider": "*",
|
||||
"scheme": "*",
|
||||
"group": "*",
|
||||
"grantedRole": "member"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"currentOrganization": {
|
||||
"id": "default",
|
||||
"name": "Default",
|
||||
"defaultRole": "member",
|
||||
"public": true,
|
||||
"mappings": [
|
||||
{
|
||||
"provider": "*",
|
||||
"scheme": "*",
|
||||
"group": "*",
|
||||
"grantedRole": "member"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/influxdata/chronograf/roles"
|
||||
)
|
||||
|
||||
func MappedRole(o *chronograf.Organization, p oauth2.Principal) *chronograf.Role {
|
||||
func MappedRole(o chronograf.Organization, p oauth2.Principal) *chronograf.Role {
|
||||
roles := []*chronograf.Role{}
|
||||
for _, mapping := range o.Mappings {
|
||||
role := applyMapping(mapping, p)
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
func TestMappedRole(t *testing.T) {
|
||||
type args struct {
|
||||
org *chronograf.Organization
|
||||
org chronograf.Organization
|
||||
principal oauth2.Principal
|
||||
}
|
||||
type wants struct {
|
||||
|
@ -27,7 +27,7 @@ func TestMappedRole(t *testing.T) {
|
|||
{
|
||||
name: "single mapping all wildcards",
|
||||
args: args{
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -50,7 +50,7 @@ func TestMappedRole(t *testing.T) {
|
|||
{
|
||||
name: "two mapping all wildcards",
|
||||
args: args{
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -79,7 +79,7 @@ func TestMappedRole(t *testing.T) {
|
|||
{
|
||||
name: "two mapping all wildcards, different order",
|
||||
args: args{
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -113,7 +113,7 @@ func TestMappedRole(t *testing.T) {
|
|||
Issuer: "google",
|
||||
Group: "influxdata.com",
|
||||
},
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -142,7 +142,7 @@ func TestMappedRole(t *testing.T) {
|
|||
{
|
||||
name: "different two mapping all wildcards",
|
||||
args: args{
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -171,7 +171,7 @@ func TestMappedRole(t *testing.T) {
|
|||
{
|
||||
name: "different two mapping all wildcards, different ordering",
|
||||
args: args{
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -200,7 +200,7 @@ func TestMappedRole(t *testing.T) {
|
|||
{
|
||||
name: "three mapping all wildcards",
|
||||
args: args{
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -240,7 +240,7 @@ func TestMappedRole(t *testing.T) {
|
|||
Issuer: "google",
|
||||
Group: "influxdata.com",
|
||||
},
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -280,7 +280,7 @@ func TestMappedRole(t *testing.T) {
|
|||
Issuer: "google",
|
||||
Group: "influxdata.com",
|
||||
},
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -320,7 +320,7 @@ func TestMappedRole(t *testing.T) {
|
|||
Issuer: "google",
|
||||
Group: "influxdata.com",
|
||||
},
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
@ -345,7 +345,7 @@ func TestMappedRole(t *testing.T) {
|
|||
Issuer: "github",
|
||||
Group: "influxdata,another,mimi",
|
||||
},
|
||||
org: &chronograf.Organization{
|
||||
org: chronograf.Organization{
|
||||
ID: "cool",
|
||||
Name: "Cool Org",
|
||||
Mappings: []chronograf.Mapping{
|
||||
|
|
22
server/me.go
22
server/me.go
|
@ -284,17 +284,25 @@ func (s *Service) Me(w http.ResponseWriter, r *http.Request) {
|
|||
// support OAuth2. This hard-coding should be removed whenever we add
|
||||
// support for other authentication schemes.
|
||||
Scheme: scheme,
|
||||
Roles: []chronograf.Role{
|
||||
{
|
||||
Name: defaultOrg.DefaultRole,
|
||||
// This is the ID of the default organization
|
||||
Organization: defaultOrg.ID,
|
||||
},
|
||||
},
|
||||
// TODO(desa): this needs a better name
|
||||
SuperAdmin: s.newUsersAreSuperAdmin(),
|
||||
}
|
||||
|
||||
allOrgs, err := s.Store.Organizations(serverCtx).All(serverCtx)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, err.Error(), s.Logger)
|
||||
return
|
||||
}
|
||||
roles := []chronograf.Role{}
|
||||
for _, org := range allOrgs {
|
||||
role := MappedRole(org, p)
|
||||
if role != nil {
|
||||
roles = append(roles, *role)
|
||||
}
|
||||
}
|
||||
|
||||
user.Roles = roles
|
||||
|
||||
newUser, err := s.Store.Users(serverCtx).Add(serverCtx, user)
|
||||
if err != nil {
|
||||
msg := fmt.Errorf("error storing user %s: %v", user.Name, err)
|
||||
|
|
|
@ -413,6 +413,24 @@ func TestService_Me(t *testing.T) {
|
|||
Mappings: []chronograf.Mapping{},
|
||||
}, nil
|
||||
},
|
||||
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
|
||||
return []chronograf.Organization{
|
||||
chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Gnarly Default",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
NumF: func(ctx context.Context) (int, error) {
|
||||
|
@ -476,6 +494,24 @@ func TestService_Me(t *testing.T) {
|
|||
Mappings: []chronograf.Mapping{},
|
||||
}, nil
|
||||
},
|
||||
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
|
||||
return []chronograf.Organization{
|
||||
chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Gnarly Default",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
NumF: func(ctx context.Context) (int, error) {
|
||||
|
@ -539,6 +575,24 @@ func TestService_Me(t *testing.T) {
|
|||
Mappings: []chronograf.Mapping{},
|
||||
}, nil
|
||||
},
|
||||
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
|
||||
return []chronograf.Organization{
|
||||
chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Gnarly Default",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
NumF: func(ctx context.Context) (int, error) {
|
||||
|
@ -586,6 +640,7 @@ func TestService_Me(t *testing.T) {
|
|||
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
|
||||
return &chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Bad Place",
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{},
|
||||
}, nil
|
||||
|
@ -598,6 +653,24 @@ func TestService_Me(t *testing.T) {
|
|||
Mappings: []chronograf.Mapping{},
|
||||
}, nil
|
||||
},
|
||||
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
|
||||
return []chronograf.Organization{
|
||||
chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Bad Place",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
NumF: func(ctx context.Context) (int, error) {
|
||||
|
@ -716,6 +789,101 @@ func TestService_Me(t *testing.T) {
|
|||
wantContentType: "application/json",
|
||||
wantBody: `{"code":403,"message":"This organization is private. To gain access, you must be explicitly added by an administrator."}`,
|
||||
},
|
||||
{
|
||||
name: "New user multiple mappings",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest("GET", "http://example.com/foo", nil),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
ConfigStore: &mocks.ConfigStore{
|
||||
Config: &chronograf.Config{
|
||||
Auth: chronograf.AuthConfig{
|
||||
SuperAdminNewUsers: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
OrganizationsStore: &mocks.OrganizationsStore{
|
||||
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
|
||||
return &chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Gnarly Default",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{},
|
||||
}, nil
|
||||
},
|
||||
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
|
||||
return &chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Gnarly Default",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{},
|
||||
}, nil
|
||||
},
|
||||
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
|
||||
return []chronograf.Organization{
|
||||
chronograf.Organization{
|
||||
ID: "0",
|
||||
Name: "The Gnarly Default",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
chronograf.Organization{
|
||||
ID: "1",
|
||||
Name: "another org",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
Public: true,
|
||||
Mappings: []chronograf.Mapping{
|
||||
chronograf.Mapping{
|
||||
Provider: chronograf.MappingWildcard,
|
||||
Scheme: chronograf.MappingWildcard,
|
||||
Group: chronograf.MappingWildcard,
|
||||
GrantedRole: roles.EditorRoleName,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
NumF: func(ctx context.Context) (int, error) {
|
||||
// This function gets to verify that there is at least one first user
|
||||
return 1, nil
|
||||
},
|
||||
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 nil, chronograf.ErrUserNotFound
|
||||
},
|
||||
AddF: func(ctx context.Context, u *chronograf.User) (*chronograf.User, error) {
|
||||
return u, nil
|
||||
},
|
||||
UpdateF: func(ctx context.Context, u *chronograf.User) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
principal: oauth2.Principal{
|
||||
Subject: "secret",
|
||||
Issuer: "auth0",
|
||||
},
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"},{"name":"editor","organization":"1"}],"provider":"auth0","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]},{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}}`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt.args.r = tt.args.r.WithContext(context.WithValue(context.Background(), oauth2.PrincipalKey, tt.principal))
|
||||
|
|
Loading…
Reference in New Issue