Add CurrentOrganization & Organizations to me resp
Remove CurrentOrganization from chronograf.Userpull/10616/head
parent
92466975a2
commit
311c68f457
|
@ -618,15 +618,14 @@ type Scope string
|
|||
|
||||
// User represents an authenticated user.
|
||||
type User struct {
|
||||
ID uint64 `json:"id,string,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Passwd string `json:"password,omitempty"`
|
||||
Permissions Permissions `json:"permissions,omitempty"`
|
||||
Roles []Role `json:"roles,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
CurrentOrganization string `json:"currentOrganization,omitempty"`
|
||||
SuperAdmin bool `json:"superAdmin,omitempty"`
|
||||
ID uint64 `json:"id,string,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Passwd string `json:"password,omitempty"`
|
||||
Permissions Permissions `json:"permissions,omitempty"`
|
||||
Roles []Role `json:"roles,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
SuperAdmin bool `json:"superAdmin,omitempty"`
|
||||
}
|
||||
|
||||
// UserQuery represents the attributes that a user may be retrieved by.
|
||||
|
@ -771,7 +770,7 @@ type LayoutsStore interface {
|
|||
|
||||
// Organization is a group of resources under a common name
|
||||
type Organization struct {
|
||||
ID uint64 `json:"id"`
|
||||
ID uint64 `json:"id,string"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
|
|
68
server/me.go
68
server/me.go
|
@ -18,7 +18,9 @@ type meLinks struct {
|
|||
|
||||
type meResponse struct {
|
||||
*chronograf.User
|
||||
Links meLinks `json:"links"`
|
||||
Links meLinks `json:"links"`
|
||||
Organizations []chronograf.Organization `json:"organizations,omitempty"`
|
||||
CurrentOrganization *chronograf.Organization `json:"currentOrganization,omitempty"`
|
||||
}
|
||||
|
||||
// If new user response is nil, return an empty meResponse because it
|
||||
|
@ -65,6 +67,10 @@ func getValidPrincipal(ctx context.Context) (oauth2.Principal, error) {
|
|||
if p.Issuer == "" {
|
||||
return oauth2.Principal{}, fmt.Errorf("Token not found")
|
||||
}
|
||||
// TODO(desa): make this default org
|
||||
if p.Organization == "" {
|
||||
p.Organization = "0"
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
@ -176,8 +182,24 @@ func (s *Service) Me(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
if usr != nil {
|
||||
usr.CurrentOrganization = p.Organization
|
||||
orgs, err := s.usersOrganizations(ctx, usr)
|
||||
if err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
}
|
||||
orgID, err := parseOrganizationID(p.Organization)
|
||||
if err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
}
|
||||
currentOrg, err := s.Store.Organizations(ctx).Get(ctx, chronograf.OrganizationQuery{ID: &orgID})
|
||||
if err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
}
|
||||
res := newMeResponse(usr)
|
||||
res.Organizations = orgs
|
||||
res.CurrentOrganization = currentOrg
|
||||
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||
return
|
||||
}
|
||||
|
@ -207,8 +229,24 @@ func (s *Service) Me(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
newUser.CurrentOrganization = p.Organization
|
||||
orgs, err := s.usersOrganizations(ctx, newUser)
|
||||
if err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
}
|
||||
orgID, err := parseOrganizationID(p.Organization)
|
||||
if err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
}
|
||||
currentOrg, err := s.Store.Organizations(ctx).Get(ctx, chronograf.OrganizationQuery{ID: &orgID})
|
||||
if err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
}
|
||||
res := newMeResponse(newUser)
|
||||
res.Organizations = orgs
|
||||
res.CurrentOrganization = currentOrg
|
||||
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||
}
|
||||
|
||||
|
@ -222,3 +260,27 @@ func (s *Service) firstUser() bool {
|
|||
|
||||
return len(users) == 0
|
||||
}
|
||||
|
||||
func (s *Service) usersOrganizations(ctx context.Context, u *chronograf.User) ([]chronograf.Organization, error) {
|
||||
if u == nil {
|
||||
// TODO(desa): better error
|
||||
return nil, fmt.Errorf("user was nil")
|
||||
}
|
||||
|
||||
orgIDs := map[string]bool{}
|
||||
for _, role := range u.Roles {
|
||||
orgIDs[role.Organization] = true
|
||||
}
|
||||
|
||||
orgs := []chronograf.Organization{}
|
||||
for orgID, _ := range orgIDs {
|
||||
id, err := parseOrganizationID(orgID)
|
||||
org, err := s.Store.Organizations(ctx).Get(ctx, chronograf.OrganizationQuery{ID: &id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
orgs = append(orgs, *org)
|
||||
}
|
||||
|
||||
return orgs, nil
|
||||
}
|
||||
|
|
|
@ -20,9 +20,10 @@ type MockUsers struct{}
|
|||
|
||||
func TestService_Me(t *testing.T) {
|
||||
type fields struct {
|
||||
UsersStore chronograf.UsersStore
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
UsersStore chronograf.UsersStore
|
||||
OrganizationsStore chronograf.OrganizationsStore
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
}
|
||||
type args struct {
|
||||
w *httptest.ResponseRecorder
|
||||
|
@ -46,6 +47,14 @@ func TestService_Me(t *testing.T) {
|
|||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
OrganizationsStore: &mocks.OrganizationsStore{
|
||||
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
|
||||
return &chronograf.Organization{
|
||||
ID: 0,
|
||||
Name: "The Bad Place",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.User, error) {
|
||||
// This function gets to verify that there is at least one first user
|
||||
|
@ -69,7 +78,7 @@ func TestService_Me(t *testing.T) {
|
|||
},
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"name":"me","provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/me"}}
|
||||
wantBody: `{"name":"me","provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/me"},"currentOrganization":{"id":"0","name":"The Bad Place"}}
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -81,6 +90,14 @@ func TestService_Me(t *testing.T) {
|
|||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
OrganizationsStore: &mocks.OrganizationsStore{
|
||||
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
|
||||
return &chronograf.Organization{
|
||||
ID: 0,
|
||||
Name: "The Bad Place",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.User, error) {
|
||||
// This function gets to verify that there is at least one first user
|
||||
|
@ -103,7 +120,7 @@ func TestService_Me(t *testing.T) {
|
|||
},
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"name":"secret","roles":[{"name":"member","organization":"\"0\""}],"provider":"auth0","scheme":"oauth2","links":{"self":"/chronograf/v1/users/secret"}}
|
||||
wantBody: `{"name":"secret","roles":[{"name":"member","organization":"\"0\""}],"provider":"auth0","scheme":"oauth2","links":{"self":"/chronograf/v1/users/secret"},"organizations":[{"id":"0","name":"The Bad Place"}],"currentOrganization":{"id":"0","name":"The Bad Place"}}
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -114,6 +131,14 @@ func TestService_Me(t *testing.T) {
|
|||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
OrganizationsStore: &mocks.OrganizationsStore{
|
||||
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
|
||||
return &chronograf.Organization{
|
||||
ID: 0,
|
||||
Name: "The Bad Place",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
UsersStore: &mocks.UsersStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.User, error) {
|
||||
// This function gets to verify that there is at least one first user
|
||||
|
@ -172,7 +197,8 @@ func TestService_Me(t *testing.T) {
|
|||
tt.args.r = tt.args.r.WithContext(context.WithValue(context.Background(), oauth2.PrincipalKey, tt.principal))
|
||||
s := &Service{
|
||||
Store: &mocks.Store{
|
||||
UsersStore: tt.fields.UsersStore,
|
||||
UsersStore: tt.fields.UsersStore,
|
||||
OrganizationsStore: tt.fields.OrganizationsStore,
|
||||
},
|
||||
Logger: tt.fields.Logger,
|
||||
UseAuth: tt.fields.UseAuth,
|
||||
|
@ -267,7 +293,7 @@ func TestService_MeOrganizations(t *testing.T) {
|
|||
},
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"\"1337\""}],"provider":"github","scheme":"oauth2","currentOrganization":"1337","links":{"self":"/chronograf/v1/users/me"}}`,
|
||||
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"\"1337\""}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/me"},"organizations":[{"id":"1337","name":"The ShillBillThrilliettas"}],"currentOrganization":{"id":"1337","name":"The ShillBillThrilliettas"}}`,
|
||||
},
|
||||
{
|
||||
name: "Change the current User's organization",
|
||||
|
@ -319,7 +345,8 @@ func TestService_MeOrganizations(t *testing.T) {
|
|||
},
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"\"1337\""}],"provider":"github","scheme":"oauth2","currentOrganization":"1337","links":{"self":"/chronograf/v1/users/me"}}`,
|
||||
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"\"1337\""}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/me"},"organizations":[{"id":"1337","name":"The ThrillShilliettos"}],"currentOrganization":{"id":"1337","name":"The ThrillShilliettos"}}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "Unable to find requested user in valid organization",
|
||||
|
|
Loading…
Reference in New Issue