Merge pull request #1486 from zhulongcheng/fix-member-endpoint

fix(http): Update members/owners endpoints to implement swagger definitions
pull/10616/head
Jade McGough 2018-12-14 13:16:42 -08:00 committed by GitHub
commit 943018a06c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 595 additions and 110 deletions

View File

@ -75,11 +75,13 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
h.BucketHandler = NewBucketHandler(b.UserResourceMappingService, b.LabelService)
h.BucketHandler.BucketService = b.BucketService
h.BucketHandler.BucketOperationLogService = b.BucketOperationLogService
h.BucketHandler.UserService = b.UserService
h.OrgHandler = NewOrgHandler(b.UserResourceMappingService, b.LabelService)
h.OrgHandler.OrganizationService = b.OrganizationService
h.OrgHandler.BucketService = b.BucketService
h.OrgHandler.OrganizationOperationLogService = b.OrganizationOperationLogService
h.OrgHandler.UserService = b.UserService
h.UserHandler = NewUserHandler()
h.UserHandler.UserService = b.UserService
@ -89,9 +91,11 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
h.DashboardHandler = NewDashboardHandler(b.UserResourceMappingService, b.LabelService)
h.DashboardHandler.DashboardService = b.DashboardService
h.DashboardHandler.DashboardOperationLogService = b.DashboardOperationLogService
h.DashboardHandler.UserService = b.UserService
h.ViewHandler = NewViewHandler(b.UserResourceMappingService, b.LabelService)
h.ViewHandler.ViewService = b.ViewService
h.ViewHandler.UserService = b.UserService
h.MacroHandler = NewMacroHandler()
h.MacroHandler.MacroService = b.MacroService
@ -112,6 +116,7 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
h.TaskHandler.TaskService = b.TaskService
h.TaskHandler.AuthorizationService = b.AuthorizationService
h.TaskHandler.UserResourceMappingService = b.UserResourceMappingService
h.TaskHandler.UserService = b.UserService
h.TelegrafHandler = NewTelegrafHandler(
b.Logger.With(zap.String("handler", "telegraf")),
@ -119,6 +124,7 @@ func NewAPIHandler(b *APIBackend) *APIHandler {
b.LabelService,
b.TelegrafService,
)
h.TelegrafHandler.UserService = b.UserService
h.WriteHandler = NewWriteHandler(b.PointsWriter)
h.WriteHandler.OrganizationService = b.OrganizationService

View File

@ -23,6 +23,7 @@ type BucketHandler struct {
BucketOperationLogService platform.BucketOperationLogService
UserResourceMappingService platform.UserResourceMappingService
LabelService platform.LabelService
UserService platform.UserService
}
const (
@ -52,12 +53,12 @@ func NewBucketHandler(mappingService platform.UserResourceMappingService, labelS
h.HandlerFunc("PATCH", bucketsIDPath, h.handlePatchBucket)
h.HandlerFunc("DELETE", bucketsIDPath, h.handleDeleteBucket)
h.HandlerFunc("POST", bucketsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, platform.BucketResourceType, platform.Member))
h.HandlerFunc("GET", bucketsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", bucketsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.BucketResourceType, platform.Member))
h.HandlerFunc("GET", bucketsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.BucketResourceType, platform.Member))
h.HandlerFunc("DELETE", bucketsIDMembersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", bucketsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, platform.BucketResourceType, platform.Owner))
h.HandlerFunc("GET", bucketsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("POST", bucketsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.BucketResourceType, platform.Owner))
h.HandlerFunc("GET", bucketsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.BucketResourceType, platform.Owner))
h.HandlerFunc("DELETE", bucketsIDOwnersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("GET", bucketsIDLabelsPath, newGetLabelsHandler(h.LabelService))

View File

@ -23,6 +23,7 @@ type DashboardHandler struct {
DashboardOperationLogService platform.DashboardOperationLogService
UserResourceMappingService platform.UserResourceMappingService
LabelService platform.LabelService
UserService platform.UserService
}
const (
@ -59,12 +60,12 @@ func NewDashboardHandler(mappingService platform.UserResourceMappingService, lab
h.HandlerFunc("DELETE", dashboardsIDCellsIDPath, h.handleDeleteDashboardCell)
h.HandlerFunc("PATCH", dashboardsIDCellsIDPath, h.handlePatchDashboardCell)
h.HandlerFunc("POST", dashboardsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, platform.DashboardResourceType, platform.Member))
h.HandlerFunc("GET", dashboardsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", dashboardsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.DashboardResourceType, platform.Member))
h.HandlerFunc("GET", dashboardsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.DashboardResourceType, platform.Member))
h.HandlerFunc("DELETE", dashboardsIDMembersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", dashboardsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, platform.DashboardResourceType, platform.Owner))
h.HandlerFunc("GET", dashboardsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("POST", dashboardsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.DashboardResourceType, platform.Owner))
h.HandlerFunc("GET", dashboardsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.DashboardResourceType, platform.Owner))
h.HandlerFunc("DELETE", dashboardsIDOwnersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("GET", dashboardsIDLabelsPath, newGetLabelsHandler(h.LabelService))

View File

@ -24,6 +24,7 @@ type OrgHandler struct {
UserResourceMappingService platform.UserResourceMappingService
SecretService platform.SecretService
LabelService platform.LabelService
UserService platform.UserService
}
const (
@ -57,12 +58,12 @@ func NewOrgHandler(mappingService platform.UserResourceMappingService,
h.HandlerFunc("PATCH", organizationsIDPath, h.handlePatchOrg)
h.HandlerFunc("DELETE", organizationsIDPath, h.handleDeleteOrg)
h.HandlerFunc("POST", organizationsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, platform.OrgResourceType, platform.Member))
h.HandlerFunc("GET", organizationsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", organizationsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.OrgResourceType, platform.Member))
h.HandlerFunc("GET", organizationsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.OrgResourceType, platform.Member))
h.HandlerFunc("DELETE", organizationsIDMembersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", organizationsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, platform.OrgResourceType, platform.Owner))
h.HandlerFunc("GET", organizationsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("POST", organizationsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.OrgResourceType, platform.Owner))
h.HandlerFunc("GET", organizationsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.OrgResourceType, platform.Owner))
h.HandlerFunc("DELETE", organizationsIDOwnersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("GET", organizationsIDSecretsPath, h.handleGetSecrets)

View File

@ -316,7 +316,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceMembers"
default:
description: unexpected error
content:
@ -341,14 +341,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: member added to telegraf
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceMember"
default:
description: unexpected error
content:
@ -402,7 +402,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceOwners"
default:
description: unexpected error
content:
@ -427,14 +427,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: telegraf config owner added
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceOwner"
default:
description: unexpected error
content:
@ -1252,7 +1252,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceMembers"
default:
description: unexpected error
content:
@ -1277,14 +1277,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: added to view members
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceMember"
default:
description: unexpected error
content:
@ -1338,7 +1338,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceOwners"
default:
description: unexpected error
content:
@ -1363,14 +1363,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: added to view owners
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceOwner"
default:
description: unexpected error
content:
@ -1817,7 +1817,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceMembers"
default:
description: unexpected error
content:
@ -1842,14 +1842,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: added to dashboard members
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceMember"
default:
description: unexpected error
content:
@ -1903,7 +1903,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceOwners"
default:
description: unexpected error
content:
@ -1928,14 +1928,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: added to dashboard owners
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceOwner"
default:
description: unexpected error
content:
@ -2584,7 +2584,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceOwners"
default:
description: unexpected error
content:
@ -2609,14 +2609,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: member added to bucket
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceMember"
default:
description: unexpected error
content:
@ -2670,7 +2670,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceMembers"
default:
description: unexpected error
content:
@ -2695,14 +2695,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: bucket owner added
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceOwner"
default:
description: unexpected error
content:
@ -3069,7 +3069,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceOwners"
default:
description: unexpected error
content:
@ -3094,14 +3094,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: added to organization created
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceMember"
default:
description: unexpected error
content:
@ -3155,7 +3155,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceMembers"
default:
description: unexpected error
content:
@ -3180,14 +3180,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: organization owner added
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceOwner"
default:
description: unexpected error
content:
@ -3601,7 +3601,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceMembers"
default:
description: unexpected error
content:
@ -3626,14 +3626,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: added to task members
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceMember"
default:
description: unexpected error
content:
@ -3687,7 +3687,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Users"
$ref: "#/components/schemas/ResourceOwners"
default:
description: unexpected error
content:
@ -3712,14 +3712,14 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/AddResourceMemberRequestBody"
responses:
'201':
description: added to task owners
content:
application/json:
schema:
$ref: "#/components/schemas/User"
$ref: "#/components/schemas/ResourceOwner"
default:
description: unexpected error
content:
@ -3789,7 +3789,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/UserResponse"
$ref: "#/components/schemas/User"
default:
description: unexpected error
content:
@ -3814,7 +3814,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/UserResponse"
$ref: "#/components/schemas/User"
default:
description: unexpected error
content:
@ -3899,7 +3899,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/UserResponse"
$ref: "#/components/schemas/User"
default:
description: unsuccessful authentication
content:
@ -4421,25 +4421,9 @@ components:
format: uri
required: [name, organization, flux]
Tasks:
type: object
properties:
tasks:
type: array
items:
$ref: "#/components/schemas/Task"
links:
$ref: "#/components/schemas/Links"
UserResponse:
type: object
properties:
user:
$ref: "#/components/schemas/User"
links:
type: object
properties:
self:
type: string
format: uri
type: array
items:
$ref: "#/components/schemas/Task"
User:
properties:
id:
@ -4454,6 +4438,19 @@ components:
enum:
- active
- inactive
links:
type: object
readOnly: true
example:
self: "/api/v2/users/1"
log: "/api/v2/users/1/log"
properties:
self:
type: string
format: uri
log:
type: string
format: uri
required: [name]
Users:
type: object
@ -4467,7 +4464,53 @@ components:
users:
type: array
items:
$ref: "#/components/schemas/UserResponse"
$ref: "#/components/schemas/User"
ResourceMember:
allOf:
- $ref: "#/components/schemas/User"
- type: object
properties:
role:
type: string
default: member
enum:
- member
ResourceMembers:
type: object
properties:
links:
type: object
properties:
self:
type: string
format: uri
users:
type: array
items:
$ref: "#/components/schemas/ResourceMember"
ResourceOwner:
allOf:
- $ref: "#/components/schemas/User"
- type: object
properties:
role:
type: string
default: owner
enum:
- owner
ResourceOwners:
type: object
properties:
links:
type: object
properties:
self:
type: string
format: uri
users:
type: array
items:
$ref: "#/components/schemas/ResourceOwner"
FluxSuggestions:
type: object
properties:
@ -6045,6 +6088,15 @@ components:
type: string
required:
- password
AddResourceMemberRequestBody:
type: object
properties:
id:
type: string
name:
type: string
required:
- id
Check:
type: object
required:

View File

@ -30,6 +30,7 @@ type TaskHandler struct {
OrganizationService platform.OrganizationService
UserResourceMappingService platform.UserResourceMappingService
LabelService platform.LabelService
UserService platform.UserService
}
const (
@ -68,12 +69,12 @@ func NewTaskHandler(mappingService platform.UserResourceMappingService, labelSer
h.HandlerFunc("GET", tasksIDLogsPath, h.handleGetLogs)
h.HandlerFunc("GET", tasksIDRunsIDLogsPath, h.handleGetLogs)
h.HandlerFunc("POST", tasksIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, platform.TaskResourceType, platform.Member))
h.HandlerFunc("GET", tasksIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", tasksIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.TaskResourceType, platform.Member))
h.HandlerFunc("GET", tasksIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.TaskResourceType, platform.Member))
h.HandlerFunc("DELETE", tasksIDMembersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", tasksIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, platform.TaskResourceType, platform.Owner))
h.HandlerFunc("GET", tasksIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("POST", tasksIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.TaskResourceType, platform.Owner))
h.HandlerFunc("GET", tasksIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.TaskResourceType, platform.Owner))
h.HandlerFunc("DELETE", tasksIDOwnersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("GET", tasksIDRunsPath, h.handleGetRuns)

View File

@ -23,11 +23,13 @@ type TelegrafHandler struct {
TelegrafService platform.TelegrafConfigStore
UserResourceMappingService platform.UserResourceMappingService
LabelService platform.LabelService
UserService platform.UserService
}
const (
telegrafsPath = "/api/v2/telegrafs"
telegrafsIDPath = "/api/v2/telegrafs/:id"
telegrafsIDMembersPath = "/api/v2/telegrafs/:id/members"
telegrafsIDMembersIDPath = "/api/v2/telegrafs/:id/members/:userID"
telegrafsIDOwnersPath = "/api/v2/telegrafs/:id/owners"
telegrafsIDOwnersIDPath = "/api/v2/telegrafs/:id/owners/:userID"
@ -56,12 +58,12 @@ func NewTelegrafHandler(
h.HandlerFunc("DELETE", telegrafsIDPath, h.handleDeleteTelegraf)
h.HandlerFunc("PUT", telegrafsIDPath, h.handlePutTelegraf)
h.HandlerFunc("POST", telegrafsIDMembersIDPath, newPostMemberHandler(h.UserResourceMappingService, platform.TelegrafResourceType, platform.Member))
h.HandlerFunc("GET", telegrafsIDMembersIDPath, newGetMembersHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", telegrafsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.TelegrafResourceType, platform.Member))
h.HandlerFunc("GET", telegrafsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.TelegrafResourceType, platform.Member))
h.HandlerFunc("DELETE", telegrafsIDMembersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", telegrafsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, platform.TelegrafResourceType, platform.Owner))
h.HandlerFunc("GET", telegrafsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("POST", telegrafsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.TelegrafResourceType, platform.Owner))
h.HandlerFunc("GET", telegrafsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.TelegrafResourceType, platform.Owner))
h.HandlerFunc("DELETE", telegrafsIDOwnersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("GET", telegrafsIDLabelsPath, newGetLabelsHandler(h.LabelService))

View File

@ -21,37 +21,39 @@ type UserResourceMappingService struct {
BasePath string
}
type userResourceResponse struct {
Links map[string]string `json:"links"`
platform.UserResourceMapping
type resourceUserResponse struct {
Role platform.UserType `json:"role"`
*userResponse
}
func newUserResourceResponse(u *platform.UserResourceMapping) *userResourceResponse {
return &userResourceResponse{
func newResourceUserResponse(u *platform.User, userType platform.UserType) *resourceUserResponse {
return &resourceUserResponse{
Role: userType,
userResponse: newUserResponse(u),
}
}
type resourceUsersResponse struct {
Links map[string]string `json:"links"`
Users []*resourceUserResponse `json:"users"`
}
func newResourceUsersResponse(opts platform.FindOptions, f platform.UserResourceMappingFilter, users []*platform.User) *resourceUsersResponse {
rs := resourceUsersResponse{
Links: map[string]string{
"user": fmt.Sprintf("/api/v2/users/%s", u.UserID),
"resource": fmt.Sprintf("/api/v2/%ss/%s", u.ResourceType, u.ResourceID),
"self": fmt.Sprintf("/api/v2/%ss/%s/%ss", f.ResourceType, f.ResourceID, f.UserType),
},
UserResourceMapping: *u,
Users: make([]*resourceUserResponse, 0, len(users)),
}
}
type userResourcesResponse struct {
UserResourceMappings []*userResourceResponse `json:"userResourceMappings"`
}
func newUserResourcesResponse(opt platform.FindOptions, f platform.UserResourceMappingFilter, ms []*platform.UserResourceMapping) *userResourcesResponse {
rs := make([]*userResourceResponse, 0, len(ms))
for _, m := range ms {
rs = append(rs, newUserResourceResponse(m))
}
return &userResourcesResponse{
UserResourceMappings: rs,
for _, user := range users {
rs.Users = append(rs.Users, newResourceUserResponse(user, f.UserType))
}
return &rs
}
// newPostMemberHandler returns a handler func for a POST to /members or /owners endpoints
func newPostMemberHandler(s platform.UserResourceMappingService, resourceType platform.ResourceType, userType platform.UserType) http.HandlerFunc {
func newPostMemberHandler(s platform.UserResourceMappingService, userService platform.UserService, resourceType platform.ResourceType, userType platform.UserType) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
@ -61,6 +63,12 @@ func newPostMemberHandler(s platform.UserResourceMappingService, resourceType pl
return
}
user, err := userService.FindUserByID(ctx, req.MemberID)
if err != nil {
EncodeError(ctx, err, w)
return
}
mapping := &platform.UserResourceMapping{
ResourceID: req.ResourceID,
ResourceType: resourceType,
@ -73,7 +81,7 @@ func newPostMemberHandler(s platform.UserResourceMappingService, resourceType pl
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, newUserResourceResponse(mapping)); err != nil {
if err := encodeResponse(ctx, w, http.StatusCreated, newResourceUserResponse(user, userType)); err != nil {
EncodeError(ctx, err, w)
return
}
@ -112,8 +120,8 @@ func decodePostMemberRequest(ctx context.Context, r *http.Request) (*postMemberR
}, nil
}
// newPostMemberHandler returns a handler func for a GET to /members or /owners endpoints
func newGetMembersHandler(s platform.UserResourceMappingService, userType platform.UserType) http.HandlerFunc {
// newGetMembersHandler returns a handler func for a GET to /members or /owners endpoints
func newGetMembersHandler(s platform.UserResourceMappingService, userService platform.UserService, resourceType platform.ResourceType, userType platform.UserType) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
@ -124,8 +132,9 @@ func newGetMembersHandler(s platform.UserResourceMappingService, userType platfo
}
filter := platform.UserResourceMappingFilter{
ResourceID: req.ResourceID,
UserType: userType,
ResourceID: req.ResourceID,
ResourceType: resourceType,
UserType: userType,
}
opts := platform.FindOptions{}
@ -135,7 +144,18 @@ func newGetMembersHandler(s platform.UserResourceMappingService, userType platfo
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newUserResourcesResponse(opts, filter, mappings)); err != nil {
users := make([]*platform.User, 0, len(mappings))
for _, m := range mappings {
user, err := userService.FindUserByID(ctx, m.UserID)
if err != nil {
EncodeError(ctx, err, w)
return
}
users = append(users, user)
}
if err := encodeResponse(ctx, w, http.StatusOK, newResourceUsersResponse(opts, filter, users)); err != nil {
EncodeError(ctx, err, w)
return
}

View File

@ -0,0 +1,359 @@
package http
import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/influxdata/platform"
"github.com/influxdata/platform/mock"
"github.com/julienschmidt/httprouter"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
)
func TestUserResourceMappingService_GetMembersHandler(t *testing.T) {
type fields struct {
userService platform.UserService
userResourceMappingService platform.UserResourceMappingService
}
type args struct {
resourceID string
userType platform.UserType
}
type wants struct {
statusCode int
contentType string
body string
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "get members",
fields: fields{
userService: &mock.UserService{
FindUserByIDFn: func(ctx context.Context, id platform.ID) (*platform.User, error) {
return &platform.User{ID: id, Name: fmt.Sprintf("user%s", id)}, nil
},
},
userResourceMappingService: &mock.UserResourceMappingService{
FindMappingsFn: func(ctx context.Context, filter platform.UserResourceMappingFilter) ([]*platform.UserResourceMapping, int, error) {
ms := []*platform.UserResourceMapping{
{
ResourceID: filter.ResourceID,
ResourceType: filter.ResourceType,
UserType: filter.UserType,
UserID: 1,
},
{
ResourceID: filter.ResourceID,
ResourceType: filter.ResourceType,
UserType: filter.UserType,
UserID: 2,
},
}
return ms, len(ms), nil
},
},
},
args: args{
resourceID: "0000000000000099",
userType: platform.Member,
},
wants: wants{
statusCode: http.StatusOK,
contentType: "application/json; charset=utf-8",
body: `
{
"links": {
"self": "/api/v2/%ss/0000000000000099/members"
},
"users": [
{
"links": {
"log": "/api/v2/users/0000000000000001/log",
"self": "/api/v2/users/0000000000000001"
},
"id": "0000000000000001",
"name": "user0000000000000001",
"role": "member"
},
{
"links": {
"log": "/api/v2/users/0000000000000002/log",
"self": "/api/v2/users/0000000000000002"
},
"id": "0000000000000002",
"name": "user0000000000000002",
"role": "member"
}
]
}`,
},
},
{
name: "get owners",
fields: fields{
userService: &mock.UserService{
FindUserByIDFn: func(ctx context.Context, id platform.ID) (*platform.User, error) {
return &platform.User{ID: id, Name: fmt.Sprintf("user%s", id)}, nil
},
},
userResourceMappingService: &mock.UserResourceMappingService{
FindMappingsFn: func(ctx context.Context, filter platform.UserResourceMappingFilter) ([]*platform.UserResourceMapping, int, error) {
ms := []*platform.UserResourceMapping{
{
ResourceID: filter.ResourceID,
ResourceType: filter.ResourceType,
UserType: filter.UserType,
UserID: 1,
},
{
ResourceID: filter.ResourceID,
ResourceType: filter.ResourceType,
UserType: filter.UserType,
UserID: 2,
},
}
return ms, len(ms), nil
},
},
},
args: args{
resourceID: "0000000000000099",
userType: platform.Owner,
},
wants: wants{
statusCode: http.StatusOK,
contentType: "application/json; charset=utf-8",
body: `
{
"links": {
"self": "/api/v2/%ss/0000000000000099/owners"
},
"users": [
{
"links": {
"log": "/api/v2/users/0000000000000001/log",
"self": "/api/v2/users/0000000000000001"
},
"id": "0000000000000001",
"name": "user0000000000000001",
"role": "owner"
},
{
"links": {
"log": "/api/v2/users/0000000000000002/log",
"self": "/api/v2/users/0000000000000002"
},
"id": "0000000000000002",
"name": "user0000000000000002",
"role": "owner"
}
]
}`,
},
},
}
for _, tt := range tests {
resourceTypes := []platform.ResourceType{
platform.BucketResourceType,
platform.DashboardResourceType,
platform.OrgResourceType,
platform.TaskResourceType,
platform.TelegrafResourceType,
platform.ViewResourceType,
}
for _, resourceType := range resourceTypes {
t.Run(tt.name+"_"+string(resourceType), func(t *testing.T) {
r := httptest.NewRequest("GET", "http://any.url", nil)
r = r.WithContext(context.WithValue(
context.TODO(),
httprouter.ParamsKey,
httprouter.Params{
{
Key: "id",
Value: tt.args.resourceID,
},
}))
w := httptest.NewRecorder()
h := newGetMembersHandler(tt.fields.userResourceMappingService, tt.fields.userService, resourceType, tt.args.userType)
h.ServeHTTP(w, r)
res := w.Result()
content := res.Header.Get("Content-Type")
body, _ := ioutil.ReadAll(res.Body)
if res.StatusCode != tt.wants.statusCode {
t.Errorf("%q. GetMembersHandler() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
}
if tt.wants.contentType != "" && content != tt.wants.contentType {
t.Errorf("%q. GetMembersHandler() = %v, want %v", tt.name, content, tt.wants.contentType)
}
if eq, _ := jsonEqual(string(body), fmt.Sprintf(tt.wants.body, resourceType)); tt.wants.body != "" && !eq {
t.Errorf("%q. GetMembersHandler() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), fmt.Sprintf(tt.wants.body, resourceType))
}
})
}
}
}
func TestUserResourceMappingService_PostMembersHandler(t *testing.T) {
type fields struct {
userService platform.UserService
userResourceMappingService platform.UserResourceMappingService
}
type args struct {
resourceID string
userType platform.UserType
user platform.User
}
type wants struct {
statusCode int
contentType string
body string
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "post members",
fields: fields{
userService: &mock.UserService{
FindUserByIDFn: func(ctx context.Context, id platform.ID) (*platform.User, error) {
return &platform.User{ID: id, Name: fmt.Sprintf("user%s", id)}, nil
},
},
userResourceMappingService: &mock.UserResourceMappingService{
CreateMappingFn: func(ctx context.Context, m *platform.UserResourceMapping) error {
return nil
},
},
},
args: args{
resourceID: "0000000000000099",
user: platform.User{
ID: 1,
Name: "user0000000000000001",
},
userType: platform.Member,
},
wants: wants{
statusCode: http.StatusCreated,
contentType: "application/json; charset=utf-8",
body: `
{
"links": {
"log": "/api/v2/users/0000000000000001/log",
"self": "/api/v2/users/0000000000000001"
},
"id": "0000000000000001",
"name": "user0000000000000001",
"role": "member"
}`,
},
},
{
name: "post owners",
fields: fields{
userService: &mock.UserService{
FindUserByIDFn: func(ctx context.Context, id platform.ID) (*platform.User, error) {
return &platform.User{ID: id, Name: fmt.Sprintf("user%s", id)}, nil
},
},
userResourceMappingService: &mock.UserResourceMappingService{
CreateMappingFn: func(ctx context.Context, m *platform.UserResourceMapping) error {
return nil
},
},
},
args: args{
resourceID: "0000000000000099",
user: platform.User{
ID: 2,
Name: "user0000000000000002",
},
userType: platform.Owner,
},
wants: wants{
statusCode: http.StatusCreated,
contentType: "application/json; charset=utf-8",
body: `
{
"links": {
"log": "/api/v2/users/0000000000000002/log",
"self": "/api/v2/users/0000000000000002"
},
"id": "0000000000000002",
"name": "user0000000000000002",
"role": "owner"
}`,
},
},
}
for _, tt := range tests {
resourceTypes := []platform.ResourceType{
platform.BucketResourceType,
platform.DashboardResourceType,
platform.OrgResourceType,
platform.TaskResourceType,
platform.TelegrafResourceType,
platform.ViewResourceType,
}
for _, resourceType := range resourceTypes {
t.Run(tt.name+"_"+string(resourceType), func(t *testing.T) {
b, err := json.Marshal(tt.args.user)
if err != nil {
t.Fatalf("failed to unmarshal user: %v", err)
}
r := httptest.NewRequest("POST", "http://any.url", bytes.NewReader(b))
r = r.WithContext(context.WithValue(
context.TODO(),
httprouter.ParamsKey,
httprouter.Params{
{
Key: "id",
Value: tt.args.resourceID,
},
}))
w := httptest.NewRecorder()
h := newPostMemberHandler(tt.fields.userResourceMappingService, tt.fields.userService, resourceType, tt.args.userType)
h.ServeHTTP(w, r)
res := w.Result()
content := res.Header.Get("Content-Type")
body, _ := ioutil.ReadAll(res.Body)
if res.StatusCode != tt.wants.statusCode {
t.Errorf("%q. PostMembersHandler() = %v, want %v", tt.name, res.StatusCode, tt.wants.statusCode)
}
if tt.wants.contentType != "" && content != tt.wants.contentType {
t.Errorf("%q. PostMembersHandler() = %v, want %v", tt.name, content, tt.wants.contentType)
}
if eq, _ := jsonEqual(string(body), tt.wants.body); tt.wants.body != "" && !eq {
t.Errorf("%q. PostMembersHandler() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wants.body)
}
})
}
}
}

View File

@ -18,6 +18,7 @@ type ViewHandler struct {
ViewService platform.ViewService
UserResourceMappingService platform.UserResourceMappingService
LabelService platform.LabelService
UserService platform.UserService
}
const (
@ -46,12 +47,12 @@ func NewViewHandler(mappingService platform.UserResourceMappingService, labelSer
h.HandlerFunc("DELETE", viewsIDPath, h.handleDeleteView)
h.HandlerFunc("PATCH", viewsIDPath, h.handlePatchView)
h.HandlerFunc("POST", viewsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, platform.ViewResourceType, platform.Member))
h.HandlerFunc("GET", viewsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", viewsIDMembersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.ViewResourceType, platform.Member))
h.HandlerFunc("GET", viewsIDMembersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.ViewResourceType, platform.Member))
h.HandlerFunc("DELETE", viewsIDMembersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Member))
h.HandlerFunc("POST", viewsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, platform.ViewResourceType, platform.Owner))
h.HandlerFunc("GET", viewsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("POST", viewsIDOwnersPath, newPostMemberHandler(h.UserResourceMappingService, h.UserService, platform.ViewResourceType, platform.Owner))
h.HandlerFunc("GET", viewsIDOwnersPath, newGetMembersHandler(h.UserResourceMappingService, h.UserService, platform.ViewResourceType, platform.Owner))
h.HandlerFunc("DELETE", viewsIDOwnersIDPath, newDeleteMemberHandler(h.UserResourceMappingService, platform.Owner))
h.HandlerFunc("GET", viewsIDLabelsPath, newGetLabelsHandler(h.LabelService))

41
mock/user_service.go Normal file
View File

@ -0,0 +1,41 @@
package mock
import (
"context"
"github.com/influxdata/platform"
)
var _ platform.UserService = &UserService{}
type UserService struct {
FindUserByIDFn func(context.Context, platform.ID) (*platform.User, error)
FindUserFn func(context.Context, platform.UserFilter) (*platform.User, error)
FindUsersFn func(context.Context, platform.UserFilter, ...platform.FindOptions) ([]*platform.User, int, error)
CreateUserFn func(context.Context, *platform.User) error
UpdateUserFn func(context.Context, platform.ID, platform.UserUpdate) (*platform.User, error)
DeleteUserFn func(context.Context, platform.ID) error
}
func (s *UserService) FindUserByID(ctx context.Context, id platform.ID) (*platform.User, error) {
return s.FindUserByIDFn(ctx, id)
}
func (s *UserService) FindUser(ctx context.Context, filter platform.UserFilter) (*platform.User, error) {
return s.FindUserFn(ctx, filter)
}
func (s *UserService) FindUsers(ctx context.Context, filter platform.UserFilter, opt ...platform.FindOptions) ([]*platform.User, int, error) {
return s.FindUsersFn(ctx, filter, opt...)
}
func (s *UserService) CreateUser(ctx context.Context, u *platform.User) error {
return s.CreateUserFn(ctx, u)
}
func (s *UserService) UpdateUser(ctx context.Context, id platform.ID, update platform.UserUpdate) (*platform.User, error) {
return s.UpdateUserFn(ctx, id, update)
}
func (s *UserService) DeleteUser(ctx context.Context, id platform.ID) error {
return s.DeleteUserFn(ctx, id)
}