169 lines
5.1 KiB
Go
169 lines
5.1 KiB
Go
// Copyright (c) Mainflux
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package api
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-kit/kit/endpoint"
|
|
kithttp "github.com/go-kit/kit/transport/http"
|
|
"github.com/mainflux/mainflux/internal/api"
|
|
"github.com/mainflux/mainflux/internal/apiutil"
|
|
gapi "github.com/mainflux/mainflux/internal/groups/api"
|
|
"github.com/mainflux/mainflux/logger"
|
|
"github.com/mainflux/mainflux/pkg/errors"
|
|
"github.com/mainflux/mainflux/pkg/groups"
|
|
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
|
)
|
|
|
|
// MakeHandler returns a HTTP handler for Groups API endpoints.
|
|
func groupsHandler(svc groups.Service, r *chi.Mux, logger logger.Logger) http.Handler {
|
|
opts := []kithttp.ServerOption{
|
|
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)),
|
|
}
|
|
|
|
r.Route("/groups", func(r chi.Router) {
|
|
r.Post("/", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.CreateGroupEndpoint(svc),
|
|
gapi.DecodeGroupCreate,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "create_group").ServeHTTP)
|
|
|
|
r.Get("/{groupID}", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.ViewGroupEndpoint(svc),
|
|
gapi.DecodeGroupRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "view_group").ServeHTTP)
|
|
|
|
r.Put("/{groupID}", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.UpdateGroupEndpoint(svc),
|
|
gapi.DecodeGroupUpdate,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "update_group").ServeHTTP)
|
|
|
|
r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.ListGroupsEndpoint(svc, "users"),
|
|
gapi.DecodeListGroupsRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "list_groups").ServeHTTP)
|
|
|
|
r.Get("/{groupID}/children", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.ListGroupsEndpoint(svc, "users"),
|
|
gapi.DecodeListChildrenRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "list_children").ServeHTTP)
|
|
|
|
r.Get("/{groupID}/parents", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.ListGroupsEndpoint(svc, "users"),
|
|
gapi.DecodeListParentsRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "list_parents").ServeHTTP)
|
|
|
|
r.Post("/{groupID}/enable", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.EnableGroupEndpoint(svc),
|
|
gapi.DecodeChangeGroupStatus,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "enable_group").ServeHTTP)
|
|
|
|
r.Post("/{groupID}/disable", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.DisableGroupEndpoint(svc),
|
|
gapi.DecodeChangeGroupStatus,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "disable_group").ServeHTTP)
|
|
|
|
r.Post("/{groupID}/users/assign", otelhttp.NewHandler(kithttp.NewServer(
|
|
assignUsersEndpoint(svc),
|
|
decodeAssignUsersRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "assign_users").ServeHTTP)
|
|
|
|
r.Post("/{groupID}/users/unassign", otelhttp.NewHandler(kithttp.NewServer(
|
|
unassignUsersEndpoint(svc),
|
|
decodeUnassignUsersRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "unassign_users").ServeHTTP)
|
|
})
|
|
|
|
// The ideal placeholder name should be {channelID}, but gapi.DecodeListGroupsRequest uses {memberID} as a placeholder for the ID.
|
|
// So here, we are using {memberID} as the placeholder.
|
|
r.Get("/channels/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.ListGroupsEndpoint(svc, "channels"),
|
|
gapi.DecodeListGroupsRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "list_groups_by_channel_id").ServeHTTP)
|
|
|
|
r.Get("/users/{memberID}/groups", otelhttp.NewHandler(kithttp.NewServer(
|
|
gapi.ListGroupsEndpoint(svc, "users"),
|
|
gapi.DecodeListGroupsRequest,
|
|
api.EncodeResponse,
|
|
opts...,
|
|
), "list_groups_by_user_id").ServeHTTP)
|
|
return r
|
|
}
|
|
|
|
func decodeAssignUsersRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
|
req := assignUsersReq{
|
|
token: apiutil.ExtractBearerToken(r),
|
|
groupID: chi.URLParam(r, "groupID"),
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
|
|
}
|
|
return req, nil
|
|
}
|
|
|
|
func decodeUnassignUsersRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
|
req := unassignUsersReq{
|
|
token: apiutil.ExtractBearerToken(r),
|
|
groupID: chi.URLParam(r, "groupID"),
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
|
|
}
|
|
return req, nil
|
|
}
|
|
|
|
func assignUsersEndpoint(svc groups.Service) endpoint.Endpoint {
|
|
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
|
req := request.(assignUsersReq)
|
|
|
|
if err := req.validate(); err != nil {
|
|
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
|
}
|
|
if err := svc.Assign(ctx, req.token, req.groupID, req.Relation, "users", req.UserIDs...); err != nil {
|
|
return nil, err
|
|
}
|
|
return assignUsersRes{}, nil
|
|
}
|
|
}
|
|
|
|
func unassignUsersEndpoint(svc groups.Service) endpoint.Endpoint {
|
|
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
|
req := request.(unassignUsersReq)
|
|
|
|
if err := req.validate(); err != nil {
|
|
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
|
}
|
|
|
|
if err := svc.Unassign(ctx, req.token, req.groupID, req.Relation, "users", req.UserIDs...); err != nil {
|
|
return nil, err
|
|
}
|
|
return unassignUsersRes{}, nil
|
|
}
|
|
}
|