mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
MF-1348 - Add transport errors logging (#1544)
* MF-1348 - Add go-kit transport level logging Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix reviews Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix reviews Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix merge Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix remark Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix go test flags Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Use httputil errors in things and http service Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix SDK tests Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Use httputil errors in certs and provision service Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Use httputil errors in consumers service Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * General renaming and add ErrMissingToken Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Rename httputil -> apiutil and use errors in users servive Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Use apiutil errors in auth, bootstrap, readers, things and twins Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Replace errors.Contain by comparison Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix remarks Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Simplify validateID Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Simplify validateID Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Simplify and rename ExtractAuthToken -> ExtractBearerToken Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix readers Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix auth key test and remarks Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Improve comment Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Simplify validateUUID check Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> * Fix typo Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com> Co-authored-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
This commit is contained in:
@@ -109,7 +109,7 @@ components:
|
||||
parameters:
|
||||
Authorization:
|
||||
name: Authorization
|
||||
description: |
|
||||
description: |
|
||||
Thing or User access token:
|
||||
* For thing access use "Authorization: Thing <thing_key>"
|
||||
* For user access use "Authorization: Bearer <user_token>"
|
||||
|
||||
@@ -183,7 +183,7 @@ func (client grpcClient) AddPolicy(ctx context.Context, in *mainflux.AddPolicyRe
|
||||
ctx, close := context.WithTimeout(ctx, client.timeout)
|
||||
defer close()
|
||||
|
||||
res, err := client.addPolicy(ctx, addPolicyReq{Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()})
|
||||
res, err := client.addPolicy(ctx, policyReq{Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()})
|
||||
if err != nil {
|
||||
return &mainflux.AddPolicyRes{}, err
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func decodeAddPolicyResponse(_ context.Context, grpcRes interface{}) (interface{
|
||||
}
|
||||
|
||||
func encodeAddPolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
req := grpcReq.(addPolicyReq)
|
||||
req := grpcReq.(policyReq)
|
||||
return &mainflux.AddPolicyReq{
|
||||
Sub: req.Sub,
|
||||
Obj: req.Obj,
|
||||
@@ -210,7 +210,7 @@ func (client grpcClient) DeletePolicy(ctx context.Context, in *mainflux.DeletePo
|
||||
ctx, close := context.WithTimeout(ctx, client.timeout)
|
||||
defer close()
|
||||
|
||||
res, err := client.deletePolicy(ctx, deletePolicyReq{Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()})
|
||||
res, err := client.deletePolicy(ctx, policyReq{Act: in.GetAct(), Obj: in.GetObj(), Sub: in.GetSub()})
|
||||
if err != nil {
|
||||
return &mainflux.DeletePolicyRes{}, err
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func decodeDeletePolicyResponse(_ context.Context, grpcRes interface{}) (interfa
|
||||
}
|
||||
|
||||
func encodeDeletePolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
req := grpcReq.(deletePolicyReq)
|
||||
req := grpcReq.(policyReq)
|
||||
return &mainflux.DeletePolicyReq{
|
||||
Sub: req.Sub,
|
||||
Obj: req.Obj,
|
||||
|
||||
@@ -72,7 +72,7 @@ func authorizeEndpoint(svc auth.Service) endpoint.Endpoint {
|
||||
|
||||
func addPolicyEndpoint(svc auth.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(addPolicyReq)
|
||||
req := request.(policyReq)
|
||||
if err := req.validate(); err != nil {
|
||||
return addPolicyRes{}, err
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func addPolicyEndpoint(svc auth.Service) endpoint.Endpoint {
|
||||
|
||||
func deletePolicyEndpoint(svc auth.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(deletePolicyReq)
|
||||
req := request.(policyReq)
|
||||
if err := req.validate(); err != nil {
|
||||
return deletePolicyRes{}, err
|
||||
}
|
||||
|
||||
@@ -176,11 +176,11 @@ func TestIdentify(t *testing.T) {
|
||||
code: codes.Unauthenticated,
|
||||
},
|
||||
{
|
||||
desc: "identify user that doesn't exist",
|
||||
desc: "identify user with empty token",
|
||||
token: "",
|
||||
idt: mainflux.UserIdentity{},
|
||||
err: status.Error(codes.InvalidArgument, "received invalid token request"),
|
||||
code: codes.InvalidArgument,
|
||||
code: codes.Unauthenticated,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+24
-28
@@ -5,7 +5,7 @@ package grpc
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/auth"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
)
|
||||
|
||||
type identityReq struct {
|
||||
@@ -15,12 +15,12 @@ type identityReq struct {
|
||||
|
||||
func (req identityReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.kind != auth.LoginKey &&
|
||||
req.kind != auth.APIKey &&
|
||||
req.kind != auth.RecoveryKey {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidAuthKey
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -34,12 +34,12 @@ type issueReq struct {
|
||||
|
||||
func (req issueReq) validate() error {
|
||||
if req.email == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrMissingEmail
|
||||
}
|
||||
if req.keyType != auth.LoginKey &&
|
||||
req.keyType != auth.APIKey &&
|
||||
req.keyType != auth.RecoveryKey {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidAuthKey
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -54,10 +54,10 @@ type assignReq struct {
|
||||
|
||||
func (req assignReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.groupID == "" || req.memberID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -72,13 +72,13 @@ type membersReq struct {
|
||||
|
||||
func (req membersReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.groupID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
if req.memberType == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingMemberType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -95,43 +95,39 @@ type authReq struct {
|
||||
|
||||
func (req authReq) validate() error {
|
||||
if req.Sub == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingPolicySub
|
||||
}
|
||||
|
||||
if req.Obj == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingPolicyObj
|
||||
}
|
||||
|
||||
if req.Act == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingPolicyAct
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type addPolicyReq struct {
|
||||
type policyReq struct {
|
||||
Sub string
|
||||
Obj string
|
||||
Act string
|
||||
}
|
||||
|
||||
func (req addPolicyReq) validate() error {
|
||||
if req.Sub == "" || req.Obj == "" || req.Act == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
func (req policyReq) validate() error {
|
||||
if req.Sub == "" {
|
||||
return apiutil.ErrMissingPolicySub
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type deletePolicyReq struct {
|
||||
Sub string
|
||||
Obj string
|
||||
Act string
|
||||
}
|
||||
|
||||
func (req deletePolicyReq) validate() error {
|
||||
if req.Sub == "" || req.Obj == "" || req.Act == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.Obj == "" {
|
||||
return apiutil.ErrMissingPolicyObj
|
||||
}
|
||||
|
||||
if req.Act == "" {
|
||||
return apiutil.ErrMissingPolicyAct
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+15
-7
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
mainflux "github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/auth"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -172,7 +173,7 @@ func encodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{
|
||||
|
||||
func decodeAddPolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
req := grpcReq.(*mainflux.AddPolicyReq)
|
||||
return addPolicyReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil
|
||||
return policyReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil
|
||||
}
|
||||
|
||||
func encodeAddPolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
|
||||
@@ -187,7 +188,7 @@ func decodeAssignRequest(_ context.Context, grpcReq interface{}) (interface{}, e
|
||||
|
||||
func decodeDeletePolicyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
req := grpcReq.(*mainflux.DeletePolicyReq)
|
||||
return deletePolicyReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil
|
||||
return policyReq{Sub: req.GetSub(), Obj: req.GetObj(), Act: req.GetAct()}, nil
|
||||
}
|
||||
|
||||
func encodeDeletePolicyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
|
||||
@@ -236,14 +237,21 @@ func encodeError(err error) error {
|
||||
switch {
|
||||
case errors.Contains(err, nil):
|
||||
return nil
|
||||
case errors.Contains(err, errors.ErrMalformedEntity):
|
||||
return status.Error(codes.InvalidArgument, "received invalid token request")
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrInvalidAuthKey,
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrMissingMemberType,
|
||||
err == apiutil.ErrMissingPolicySub,
|
||||
err == apiutil.ErrMissingPolicyObj,
|
||||
err == apiutil.ErrMissingPolicyAct:
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
errors.Contains(err, auth.ErrKeyExpired),
|
||||
err == apiutil.ErrMissingEmail,
|
||||
err == apiutil.ErrBearerToken:
|
||||
return status.Error(codes.Unauthenticated, err.Error())
|
||||
case errors.Contains(err, errors.ErrAuthorization):
|
||||
return status.Error(codes.PermissionDenied, err.Error())
|
||||
case errors.Contains(err, auth.ErrKeyExpired):
|
||||
return status.Error(codes.Unauthenticated, err.Error())
|
||||
default:
|
||||
return status.Error(codes.Internal, "internal server error")
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
httpapi "github.com/mainflux/mainflux/auth/api/http"
|
||||
"github.com/mainflux/mainflux/auth/jwt"
|
||||
"github.com/mainflux/mainflux/auth/mocks"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -47,7 +48,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
@@ -65,7 +66,8 @@ func newService() auth.Service {
|
||||
}
|
||||
|
||||
func newServer(svc auth.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package groups
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/auth"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
)
|
||||
|
||||
type createGroupReq struct {
|
||||
@@ -15,10 +15,10 @@ type createGroupReq struct {
|
||||
|
||||
func (req createGroupReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if len(req.Name) > maxNameSize || req.Name == "" {
|
||||
return errors.Wrap(errors.ErrMalformedEntity, auth.ErrBadGroupName)
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -34,11 +34,11 @@ type updateGroupReq struct {
|
||||
|
||||
func (req updateGroupReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -56,11 +56,11 @@ type listGroupsReq struct {
|
||||
|
||||
func (req listGroupsReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.level > auth.MaxLevel || req.level < auth.MinLevel {
|
||||
return auth.ErrMaxLevelExceeded
|
||||
return apiutil.ErrMaxLevelExceeded
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -78,11 +78,11 @@ type listMembersReq struct {
|
||||
|
||||
func (req listMembersReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -98,11 +98,11 @@ type listMembershipsReq struct {
|
||||
|
||||
func (req listMembershipsReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -117,11 +117,19 @@ type assignReq struct {
|
||||
|
||||
func (req assignReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.Type == "" || req.groupID == "" || len(req.Members) == 0 {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.Type == "" {
|
||||
return apiutil.ErrMissingMemberType
|
||||
}
|
||||
|
||||
if req.groupID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.Members) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -135,11 +143,11 @@ type shareGroupAccessReq struct {
|
||||
|
||||
func (req shareGroupAccessReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.ThingGroupID == "" || req.userGroupID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -151,11 +159,15 @@ type unassignReq struct {
|
||||
|
||||
func (req unassignReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.groupID == "" || len(req.Members) == 0 {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.groupID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.Members) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -168,11 +180,11 @@ type groupReq struct {
|
||||
|
||||
func (req groupReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/auth"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
)
|
||||
@@ -31,9 +32,9 @@ const (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer) *bone.Mux {
|
||||
func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer, logger logger.Logger) *bone.Mux {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
mux.Post("/groups", kithttp.NewServer(
|
||||
kitot.TraceServer(tracer, "create_group")(createGroupEndpoint(svc)),
|
||||
@@ -127,13 +128,8 @@ func decodeShareGroupRequest(ctx context.Context, r *http.Request) (interface{},
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := shareGroupAccessReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
userGroupID: bone.GetValue(r, "subjectGroupID"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -144,28 +140,23 @@ func decodeShareGroupRequest(ctx context.Context, r *http.Request) (interface{},
|
||||
}
|
||||
|
||||
func decodeListGroupsRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
l, err := httputil.ReadUintQuery(r, levelKey, defLevel)
|
||||
l, err := apiutil.ReadUintQuery(r, levelKey, defLevel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ReadBoolQuery(r, treeKey, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
to, err := httputil.ExtractAuthToken(r)
|
||||
t, err := apiutil.ReadBoolQuery(r, treeKey, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listGroupsReq{
|
||||
token: to,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
level: l,
|
||||
metadata: m,
|
||||
tree: t,
|
||||
@@ -175,38 +166,33 @@ func decodeListGroupsRequest(_ context.Context, r *http.Request) (interface{}, e
|
||||
}
|
||||
|
||||
func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tree, err := httputil.ReadBoolQuery(r, treeKey, false)
|
||||
tree, err := apiutil.ReadBoolQuery(r, treeKey, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ReadStringQuery(r, groupType, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
to, err := httputil.ExtractAuthToken(r)
|
||||
t, err := apiutil.ReadStringQuery(r, groupType, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listMembersReq{
|
||||
token: to,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "groupID"),
|
||||
groupType: t,
|
||||
offset: o,
|
||||
@@ -218,28 +204,23 @@ func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{},
|
||||
}
|
||||
|
||||
func decodeListMembershipsRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listMembershipsReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "memberID"),
|
||||
offset: o,
|
||||
limit: l,
|
||||
@@ -254,17 +235,11 @@ func decodeGroupCreate(_ context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
var req createGroupReq
|
||||
req := createGroupReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.token = t
|
||||
return req, nil
|
||||
}
|
||||
|
||||
@@ -273,29 +248,20 @@ func decodeGroupUpdate(_ context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
var req updateGroupReq
|
||||
req := updateGroupReq{
|
||||
id: bone.GetValue(r, "groupID"),
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.id = bone.GetValue(r, "groupID")
|
||||
req.token = t
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeGroupRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := groupReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "groupID"),
|
||||
}
|
||||
|
||||
@@ -303,13 +269,8 @@ func decodeGroupRequest(_ context.Context, r *http.Request) (interface{}, error)
|
||||
}
|
||||
|
||||
func decodeAssignRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := assignReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
groupID: bone.GetValue(r, "groupID"),
|
||||
}
|
||||
|
||||
@@ -321,14 +282,9 @@ func decodeAssignRequest(_ context.Context, r *http.Request) (interface{}, error
|
||||
}
|
||||
|
||||
func decodeUnassignRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := unassignReq{
|
||||
assignReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
groupID: bone.GetValue(r, "groupID"),
|
||||
},
|
||||
}
|
||||
@@ -360,7 +316,11 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrMalformedEntity):
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrEmptyList,
|
||||
err == apiutil.ErrMissingMemberType,
|
||||
err == apiutil.ErrNameSize:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
@@ -387,7 +347,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
httpapi "github.com/mainflux/mainflux/auth/api/http"
|
||||
"github.com/mainflux/mainflux/auth/jwt"
|
||||
"github.com/mainflux/mainflux/auth/mocks"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -52,7 +53,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
@@ -76,7 +77,8 @@ func newService() auth.Service {
|
||||
}
|
||||
|
||||
func newServer(svc auth.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -106,7 +108,7 @@ func TestIssue(t *testing.T) {
|
||||
status int
|
||||
}{
|
||||
{
|
||||
desc: "issue login key",
|
||||
desc: "issue login key with empty token",
|
||||
req: toJSON(lk),
|
||||
ct: contentType,
|
||||
token: "",
|
||||
@@ -124,7 +126,7 @@ func TestIssue(t *testing.T) {
|
||||
req: toJSON(rk),
|
||||
ct: contentType,
|
||||
token: loginSecret,
|
||||
status: http.StatusUnauthorized,
|
||||
status: http.StatusCreated,
|
||||
},
|
||||
{
|
||||
desc: "issue login key wrong content type",
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mainflux/mainflux/auth"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
)
|
||||
|
||||
type issueKeyReq struct {
|
||||
@@ -18,9 +18,16 @@ type issueKeyReq struct {
|
||||
|
||||
// It is not possible to issue Reset key using HTTP API.
|
||||
func (req issueKeyReq) validate() error {
|
||||
if req.Type != auth.APIKey || req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
if req.token == "" {
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.Type != auth.LoginKey &&
|
||||
req.Type != auth.RecoveryKey &&
|
||||
req.Type != auth.APIKey {
|
||||
return apiutil.ErrInvalidAPIKey
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -30,8 +37,12 @@ type keyReq struct {
|
||||
}
|
||||
|
||||
func (req keyReq) validate() error {
|
||||
if req.token == "" || req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.token == "" {
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@ import (
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/auth"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
)
|
||||
@@ -22,9 +23,9 @@ import (
|
||||
const contentType = "application/json"
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer) *bone.Mux {
|
||||
func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer, logger logger.Logger) *bone.Mux {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
mux.Post("/keys", kithttp.NewServer(
|
||||
kitot.TraceServer(tracer, "issue")(issueEndpoint(svc)),
|
||||
@@ -54,13 +55,8 @@ func decodeIssue(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := issueKeyReq{
|
||||
token: t,
|
||||
}
|
||||
|
||||
req := issueKeyReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -69,12 +65,8 @@ func decodeIssue(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeKeyReq(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := keyReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
return req, nil
|
||||
@@ -100,9 +92,12 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrMalformedEntity):
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrInvalidAPIKey:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
@@ -116,7 +111,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
httpapi "github.com/mainflux/mainflux/auth/api/http"
|
||||
"github.com/mainflux/mainflux/auth/jwt"
|
||||
"github.com/mainflux/mainflux/auth/mocks"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -49,7 +50,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
@@ -74,7 +75,8 @@ func newService() auth.Service {
|
||||
}
|
||||
|
||||
func newServer(svc auth.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package policies
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
import "github.com/mainflux/mainflux/internal/apiutil"
|
||||
|
||||
// Action represents an enum for the policies used in the Mainflux.
|
||||
type Action int
|
||||
@@ -35,22 +33,30 @@ type policiesReq struct {
|
||||
|
||||
func (req policiesReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if len(req.SubjectIDs) == 0 || len(req.Policies) == 0 || req.Object == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if len(req.SubjectIDs) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
if len(req.Policies) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
if req.Object == "" {
|
||||
return apiutil.ErrMissingPolicyObj
|
||||
}
|
||||
|
||||
for _, policy := range req.Policies {
|
||||
if _, ok := actions[policy]; !ok {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMalformedPolicy
|
||||
}
|
||||
}
|
||||
|
||||
for _, subject := range req.SubjectIDs {
|
||||
if subject == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
for _, subID := range req.SubjectIDs {
|
||||
if subID == "" {
|
||||
return apiutil.ErrMissingPolicySub
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/auth"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
)
|
||||
@@ -19,9 +20,9 @@ import (
|
||||
const contentType = "application/json"
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer) *bone.Mux {
|
||||
func MakeHandler(svc auth.Service, mux *bone.Mux, tracer opentracing.Tracer, logger logger.Logger) *bone.Mux {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
mux.Post("/policies", kithttp.NewServer(
|
||||
@@ -46,14 +47,7 @@ func decodePoliciesRequest(ctx context.Context, r *http.Request) (interface{}, e
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := policiesReq{
|
||||
token: t,
|
||||
}
|
||||
req := policiesReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -81,9 +75,14 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrMalformedEntity):
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrEmptyList,
|
||||
err == apiutil.ErrMissingPolicyObj,
|
||||
err == apiutil.ErrMissingPolicySub,
|
||||
err == apiutil.ErrMalformedPolicy:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
@@ -101,7 +100,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,17 @@ import (
|
||||
"github.com/mainflux/mainflux/auth/api/http/groups"
|
||||
"github.com/mainflux/mainflux/auth/api/http/keys"
|
||||
"github.com/mainflux/mainflux/auth/api/http/policies"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc auth.Service, tracer opentracing.Tracer) http.Handler {
|
||||
func MakeHandler(svc auth.Service, tracer opentracing.Tracer, logger logger.Logger) http.Handler {
|
||||
mux := bone.New()
|
||||
mux = keys.MakeHandler(svc, mux, tracer)
|
||||
mux = groups.MakeHandler(svc, mux, tracer)
|
||||
mux = policies.MakeHandler(svc, mux, tracer)
|
||||
mux = keys.MakeHandler(svc, mux, tracer, logger)
|
||||
mux = groups.MakeHandler(svc, mux, tracer, logger)
|
||||
mux = policies.MakeHandler(svc, mux, tracer, logger)
|
||||
mux.GetFunc("/health", mainflux.Health("auth"))
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
return mux
|
||||
|
||||
@@ -14,12 +14,6 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrMaxLevelExceeded malformed entity.
|
||||
ErrMaxLevelExceeded = errors.New("level must be less than or equal 5")
|
||||
|
||||
// ErrBadGroupName malformed entity.
|
||||
ErrBadGroupName = errors.New("incorrect group name")
|
||||
|
||||
// ErrAssignToGroup indicates failure to assign member to a group.
|
||||
ErrAssignToGroup = errors.New("failed to assign member to a group")
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ import (
|
||||
"github.com/mainflux/mainflux/bootstrap"
|
||||
bsapi "github.com/mainflux/mainflux/bootstrap/api"
|
||||
"github.com/mainflux/mainflux/bootstrap/mocks"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
mfsdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
@@ -82,12 +83,14 @@ var (
|
||||
CACert: "newca",
|
||||
}
|
||||
|
||||
bsErrorRes = toJSON(httputil.ErrorRes{Err: bootstrap.ErrBootstrap.Error()})
|
||||
authnRes = toJSON(httputil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
authzRes = toJSON(httputil.ErrorRes{Err: errors.ErrAuthorization.Error()})
|
||||
malformedRes = toJSON(httputil.ErrorRes{Err: errors.ErrMalformedEntity.Error()})
|
||||
extKeyRes = toJSON(httputil.ErrorRes{Err: bootstrap.ErrExternalKey.Error()})
|
||||
extSecKeyRes = toJSON(httputil.ErrorRes{Err: bootstrap.ErrExternalKeySecure.Error()})
|
||||
bsErrorRes = toJSON(apiutil.ErrorRes{Err: bootstrap.ErrBootstrap.Error()})
|
||||
authnRes = toJSON(apiutil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
authzRes = toJSON(apiutil.ErrorRes{Err: errors.ErrAuthorization.Error()})
|
||||
malformedRes = toJSON(apiutil.ErrorRes{Err: errors.ErrMalformedEntity.Error()})
|
||||
extKeyRes = toJSON(apiutil.ErrorRes{Err: bootstrap.ErrExternalKey.Error()})
|
||||
extSecKeyRes = toJSON(apiutil.ErrorRes{Err: bootstrap.ErrExternalKeySecure.Error()})
|
||||
missingIDRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrMissingID.Error()})
|
||||
missingKeyRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrBearerKey.Error()})
|
||||
)
|
||||
|
||||
type testRequest struct {
|
||||
@@ -120,7 +123,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
}
|
||||
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
|
||||
if tr.contentType != "" {
|
||||
@@ -188,12 +191,14 @@ func newThingsService(auth mainflux.AuthServiceClient) things.Service {
|
||||
}
|
||||
|
||||
func newThingsServer(svc things.Service) *httptest.Server {
|
||||
mux := thingsapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := thingsapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
func newBootstrapServer(svc bootstrap.Service) *httptest.Server {
|
||||
mux := bsapi.MakeHandler(svc, bootstrap.NewConfigReader(encKey))
|
||||
logger := logger.NewMock()
|
||||
mux := bsapi.MakeHandler(svc, bootstrap.NewConfigReader(encKey), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -1092,7 +1097,7 @@ func TestBootstrap(t *testing.T) {
|
||||
externalID: "",
|
||||
externalKey: c.ExternalKey,
|
||||
status: http.StatusBadRequest,
|
||||
res: malformedRes,
|
||||
res: missingIDRes,
|
||||
secure: false,
|
||||
},
|
||||
{
|
||||
@@ -1108,7 +1113,7 @@ func TestBootstrap(t *testing.T) {
|
||||
externalID: c.ExternalID,
|
||||
externalKey: "",
|
||||
status: http.StatusUnauthorized,
|
||||
res: authnRes,
|
||||
res: missingKeyRes,
|
||||
secure: false,
|
||||
},
|
||||
{
|
||||
|
||||
+23
-19
@@ -5,7 +5,7 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/bootstrap"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
)
|
||||
|
||||
const maxLimitSize = 100
|
||||
@@ -29,11 +29,15 @@ type addReq struct {
|
||||
|
||||
func (req addReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.ExternalID == "" || req.ExternalKey == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.ExternalID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.ExternalKey == "" {
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -46,11 +50,11 @@ type entityReq struct {
|
||||
|
||||
func (req entityReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -65,11 +69,11 @@ type updateReq struct {
|
||||
|
||||
func (req updateReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -85,11 +89,11 @@ type updateCertReq struct {
|
||||
|
||||
func (req updateCertReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
if req.thingID == "" {
|
||||
return errors.ErrNotFound
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -103,11 +107,11 @@ type updateConnReq struct {
|
||||
|
||||
func (req updateConnReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -122,11 +126,11 @@ type listReq struct {
|
||||
|
||||
func (req listReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
if req.limit > maxLimitSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -139,11 +143,11 @@ type bootstrapReq struct {
|
||||
|
||||
func (req bootstrapReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -157,16 +161,16 @@ type changeStateReq struct {
|
||||
|
||||
func (req changeStateReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.State != bootstrap.Inactive &&
|
||||
req.State != bootstrap.Active {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrBootstrapState
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mainflux/mainflux/bootstrap"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -22,21 +22,21 @@ func TestAddReqValidation(t *testing.T) {
|
||||
token: "",
|
||||
externalID: "external-id",
|
||||
externalKey: "external-key",
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerToken,
|
||||
},
|
||||
{
|
||||
desc: "empty external ID",
|
||||
token: "token",
|
||||
externalID: "",
|
||||
externalKey: "external-key",
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
{
|
||||
desc: "empty external key",
|
||||
token: "token",
|
||||
externalID: "external-id",
|
||||
externalKey: "",
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -63,13 +63,13 @@ func TestEntityReqValidation(t *testing.T) {
|
||||
desc: "empty key",
|
||||
key: "",
|
||||
id: "id",
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
{
|
||||
desc: "empty id",
|
||||
key: "key",
|
||||
id: "",
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -94,13 +94,13 @@ func TestUpdateReqValidation(t *testing.T) {
|
||||
desc: "empty key",
|
||||
key: "",
|
||||
id: "id",
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
{
|
||||
desc: "empty id",
|
||||
key: "key",
|
||||
id: "",
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -126,13 +126,13 @@ func TestUpdateCertReqValidation(t *testing.T) {
|
||||
desc: "empty key",
|
||||
key: "",
|
||||
thingID: "thingID",
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
{
|
||||
desc: "empty thing key",
|
||||
desc: "empty thing id",
|
||||
key: "key",
|
||||
thingID: "",
|
||||
err: errors.ErrNotFound,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -158,13 +158,13 @@ func TestUpdateConnReqValidation(t *testing.T) {
|
||||
desc: "empty key",
|
||||
key: "",
|
||||
id: "id",
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
{
|
||||
desc: "empty id",
|
||||
key: "key",
|
||||
id: "",
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -192,17 +192,17 @@ func TestListReqValidation(t *testing.T) {
|
||||
key: "",
|
||||
offset: 0,
|
||||
limit: 1,
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
{
|
||||
desc: "too large limit",
|
||||
key: "key",
|
||||
offset: 0,
|
||||
limit: maxLimitSize + 1,
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrLimitSize,
|
||||
},
|
||||
{
|
||||
desc: "zero limit",
|
||||
desc: "default limit",
|
||||
key: "key",
|
||||
offset: 0,
|
||||
limit: defLimit,
|
||||
@@ -233,13 +233,13 @@ func TestBootstrapReqValidation(t *testing.T) {
|
||||
desc: "empty external key",
|
||||
externKey: "",
|
||||
externID: "id",
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
{
|
||||
desc: "empty external id",
|
||||
externKey: "key",
|
||||
externID: "",
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -267,21 +267,21 @@ func TestChangeStateReqValidation(t *testing.T) {
|
||||
key: "",
|
||||
id: "id",
|
||||
state: bootstrap.State(1),
|
||||
err: errors.ErrAuthentication,
|
||||
err: apiutil.ErrBearerKey,
|
||||
},
|
||||
{
|
||||
desc: "empty id",
|
||||
key: "key",
|
||||
id: "",
|
||||
state: bootstrap.State(0),
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
{
|
||||
desc: "invalid state",
|
||||
key: "key",
|
||||
id: "id",
|
||||
state: bootstrap.State(14),
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrBootstrapState,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+30
-61
@@ -14,7 +14,8 @@ import (
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/bootstrap"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
@@ -33,9 +34,9 @@ var (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc bootstrap.Service, reader bootstrap.ConfigReader) http.Handler {
|
||||
func MakeHandler(svc bootstrap.Service, reader bootstrap.ConfigReader, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
r := bone.New()
|
||||
|
||||
@@ -110,12 +111,7 @@ func decodeAddRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := addReq{token: t}
|
||||
req := addReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -128,13 +124,10 @@ func decodeUpdateRequest(_ context.Context, r *http.Request) (interface{}, error
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
req := updateReq{
|
||||
key: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
|
||||
req := updateReq{key: t}
|
||||
req.id = bone.GetValue(r, "id")
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -147,16 +140,10 @@ func decodeUpdateCertRequest(_ context.Context, r *http.Request) (interface{}, e
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := updateCertReq{
|
||||
key: t,
|
||||
key: apiutil.ExtractBearerToken(r),
|
||||
thingID: bone.GetValue(r, "id"),
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -169,13 +156,10 @@ func decodeUpdateConnRequest(_ context.Context, r *http.Request) (interface{}, e
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
req := updateConnReq{
|
||||
key: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
|
||||
req := updateConnReq{key: t}
|
||||
req.id = bone.GetValue(r, "id")
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -184,12 +168,12 @@ func decodeUpdateConnRequest(_ context.Context, r *http.Request) (interface{}, e
|
||||
}
|
||||
|
||||
func decodeListRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -199,16 +183,9 @@ func decodeListRequest(_ context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrInvalidQueryParams
|
||||
}
|
||||
|
||||
filter := parseFilter(q)
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listReq{
|
||||
key: t,
|
||||
filter: filter,
|
||||
key: apiutil.ExtractBearerToken(r),
|
||||
filter: parseFilter(q),
|
||||
offset: o,
|
||||
limit: l,
|
||||
}
|
||||
@@ -217,14 +194,9 @@ func decodeListRequest(_ context.Context, r *http.Request) (interface{}, error)
|
||||
}
|
||||
|
||||
func decodeBootstrapRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := bootstrapReq{
|
||||
id: bone.GetValue(r, "external_id"),
|
||||
key: t,
|
||||
key: apiutil.ExtractBearerToken(r),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
@@ -235,13 +207,10 @@ func decodeStateRequest(_ context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
req := changeStateReq{
|
||||
key: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
|
||||
req := changeStateReq{key: t}
|
||||
req.id = bone.GetValue(r, "id")
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -250,13 +219,8 @@ func decodeStateRequest(_ context.Context, r *http.Request) (interface{}, error)
|
||||
}
|
||||
|
||||
func decodeEntityRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := entityReq{
|
||||
key: t,
|
||||
key: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
|
||||
@@ -293,15 +257,20 @@ func encodeSecureRes(_ context.Context, w http.ResponseWriter, response interfac
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken,
|
||||
err == apiutil.ErrBearerKey:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrUnsupportedContentType):
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
case errors.Contains(err, errors.ErrInvalidQueryParams),
|
||||
errors.Contains(err, errors.ErrMalformedEntity):
|
||||
errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrBootstrapState,
|
||||
err == apiutil.ErrLimitSize:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, bootstrap.ErrExternalKey),
|
||||
errors.Contains(err, bootstrap.ErrExternalKeySecure),
|
||||
errors.Contains(err, errors.ErrAuthorization):
|
||||
@@ -323,7 +292,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
|
||||
@@ -87,7 +88,8 @@ func newThingsService(auth mainflux.AuthServiceClient) things.Service {
|
||||
}
|
||||
|
||||
func newThingsServer(svc things.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
func TestAdd(t *testing.T) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/bootstrap"
|
||||
"github.com/mainflux/mainflux/bootstrap/mocks"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
mfsdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
@@ -79,7 +80,8 @@ func newThingsService(auth mainflux.AuthServiceClient) things.Service {
|
||||
}
|
||||
|
||||
func newThingsServer(svc things.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
+16
-13
@@ -3,9 +3,7 @@
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
import "github.com/mainflux/mainflux/internal/apiutil"
|
||||
|
||||
const maxLimitSize = 100
|
||||
|
||||
@@ -19,12 +17,17 @@ type addCertsReq struct {
|
||||
|
||||
func (req addCertsReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.ThingID == "" || req.TTL == "" || req.KeyType == "" || req.KeyBits == 0 {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.ThingID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.TTL == "" || req.KeyType == "" || req.KeyBits == 0 {
|
||||
return apiutil.ErrMissingCertData
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -37,10 +40,10 @@ type listReq struct {
|
||||
|
||||
func (req *listReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.limit == 0 || req.limit > maxLimitSize {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.limit > 1 || req.limit > maxLimitSize {
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -52,10 +55,10 @@ type viewReq struct {
|
||||
|
||||
func (req *viewReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.serialID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -68,11 +71,11 @@ type revokeReq struct {
|
||||
|
||||
func (req *revokeReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.certID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+19
-28
@@ -12,7 +12,8 @@ import (
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/certs"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
@@ -26,9 +27,9 @@ const (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc certs.Service) http.Handler {
|
||||
func MakeHandler(svc certs.Service, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
r := bone.New()
|
||||
@@ -86,20 +87,17 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
}
|
||||
|
||||
func decodeListCerts(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
thingID: bone.GetValue(r, "thingId"),
|
||||
limit: l,
|
||||
offset: o,
|
||||
@@ -108,13 +106,8 @@ func decodeListCerts(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeViewCert(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := viewReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
serialID: bone.GetValue(r, "certId"),
|
||||
}
|
||||
|
||||
@@ -125,11 +118,8 @@ func decodeCerts(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
if r.Header.Get("Content-Type") != contentType {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := addCertsReq{token: t}
|
||||
|
||||
req := addCertsReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -138,12 +128,8 @@ func decodeCerts(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeRevokeCerts(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := revokeReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
certID: bone.GetValue(r, "certId"),
|
||||
}
|
||||
|
||||
@@ -152,10 +138,15 @@ func decodeRevokeCerts(_ context.Context, r *http.Request) (interface{}, error)
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrUnsupportedContentType):
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
errors.Contains(err, errors.ErrInvalidQueryParams):
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrMissingCertData,
|
||||
err == apiutil.ErrLimitSize:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrConflict):
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
@@ -171,7 +162,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
bsmocks "github.com/mainflux/mainflux/bootstrap/mocks"
|
||||
"github.com/mainflux/mainflux/certs"
|
||||
"github.com/mainflux/mainflux/certs/mocks"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
mfsdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
@@ -413,7 +414,8 @@ func TestViewCert(t *testing.T) {
|
||||
}
|
||||
|
||||
func newThingsServer(svc things.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -258,11 +258,11 @@ func startHTTPServer(tracer opentracing.Tracer, svc auth.Service, port string, c
|
||||
p := fmt.Sprintf(":%s", port)
|
||||
if certFile != "" || keyFile != "" {
|
||||
logger.Info(fmt.Sprintf("Authentication service started using https, cert %s key %s, exposed port %s", certFile, keyFile, port))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, httpapi.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, httpapi.MakeHandler(svc, tracer, logger))
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Authentication service started using http, exposed port %s", port))
|
||||
errs <- http.ListenAndServe(p, httpapi.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServe(p, httpapi.MakeHandler(svc, tracer, logger))
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -325,11 +325,11 @@ func startHTTPServer(svc bootstrap.Service, cfg config, logger mflog.Logger, err
|
||||
if cfg.serverCert != "" || cfg.serverKey != "" {
|
||||
logger.Info(fmt.Sprintf("Bootstrap service started using https on port %s with cert %s key %s",
|
||||
cfg.httpPort, cfg.serverCert, cfg.serverKey))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(svc, bootstrap.NewConfigReader(cfg.encKey)))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(svc, bootstrap.NewConfigReader(cfg.encKey), logger))
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Bootstrap service started using http on port %s", cfg.httpPort))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, bootstrap.NewConfigReader(cfg.encKey)))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, bootstrap.NewConfigReader(cfg.encKey), logger))
|
||||
}
|
||||
|
||||
func subscribeToThingsES(svc bootstrap.Service, client *r.Client, consumer string, logger mflog.Logger) {
|
||||
|
||||
@@ -33,8 +33,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
sep = ","
|
||||
|
||||
svcName = "cassandra-reader"
|
||||
sep = ","
|
||||
defLogLevel = "error"
|
||||
defPort = "8180"
|
||||
defCluster = "127.0.0.1"
|
||||
@@ -284,9 +284,9 @@ func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceCl
|
||||
if cfg.serverCert != "" || cfg.serverKey != "" {
|
||||
logger.Info(fmt.Sprintf("Cassandra reader service started using https on port %s with cert %s key %s",
|
||||
cfg.port, cfg.serverCert, cfg.serverKey))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(repo, tc, ac, "cassandra-reader"))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Cassandra reader service started, exposed port %s", cfg.port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, "cassandra-reader"))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
}
|
||||
|
||||
+2
-2
@@ -368,11 +368,11 @@ func startHTTPServer(svc certs.Service, cfg config, logger mflog.Logger, errs ch
|
||||
if cfg.serverCert != "" || cfg.serverKey != "" {
|
||||
logger.Info(fmt.Sprintf("Certs service started using https on port %s with cert %s key %s",
|
||||
cfg.httpPort, cfg.serverCert, cfg.serverKey))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(svc))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(svc, logger))
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Certs service started using http on port %s", cfg.httpPort))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, logger))
|
||||
}
|
||||
|
||||
func loadCertificates(conf config) (tls.Certificate, *x509.Certificate, error) {
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ func main() {
|
||||
go func() {
|
||||
p := fmt.Sprintf(":%s", cfg.port)
|
||||
logger.Info(fmt.Sprintf("HTTP adapter service started on port %s", cfg.port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer, logger))
|
||||
}()
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
svcName = "influxdb-reader"
|
||||
defLogLevel = "error"
|
||||
defPort = "8180"
|
||||
defDB = "mainflux"
|
||||
@@ -274,9 +275,9 @@ func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceCl
|
||||
if cfg.serverCert != "" || cfg.serverKey != "" {
|
||||
logger.Info(fmt.Sprintf("InfluxDB reader service started using https on port %s with cert %s key %s",
|
||||
cfg.port, cfg.serverCert, cfg.serverKey))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(repo, tc, ac, "influxdb-reader"))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("InfluxDB reader service started, exposed port %s", cfg.port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, "influxdb-reader"))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
svcName = "mongodb-reader"
|
||||
defLogLevel = "error"
|
||||
defPort = "8180"
|
||||
defDB = "mainflux"
|
||||
@@ -269,9 +270,9 @@ func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceCl
|
||||
if cfg.serverCert != "" || cfg.serverKey != "" {
|
||||
logger.Info(fmt.Sprintf("Mongo reader service started using https on port %s with cert %s key %s",
|
||||
cfg.port, cfg.serverCert, cfg.serverKey))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(repo, tc, ac, "mongodb-reader"))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.serverCert, cfg.serverKey, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Mongo reader service started, exposed port %s", cfg.port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, "mongodb-reader"))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
}
|
||||
|
||||
+1
-1
@@ -219,5 +219,5 @@ func newRouteMapRepositoy(client *r.Client, prefix string, logger logger.Logger)
|
||||
func startHTTPServer(svc opcua.Service, cfg config, logger logger.Logger, errs chan error) {
|
||||
p := fmt.Sprintf(":%s", cfg.httpPort)
|
||||
logger.Info(fmt.Sprintf("opcua-adapter service started, exposed port %s", cfg.httpPort))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, logger))
|
||||
}
|
||||
|
||||
@@ -281,5 +281,5 @@ func newService(db *sqlx.DB, logger logger.Logger) readers.MessageRepository {
|
||||
func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient, port string, logger logger.Logger, errs chan error) {
|
||||
p := fmt.Sprintf(":%s", port)
|
||||
logger.Info(fmt.Sprintf("Postgres reader service started, exposed port %s", port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, svcName))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
}
|
||||
|
||||
@@ -126,11 +126,11 @@ func startHTTPServer(svc provision.Service, cfg provision.Config, logger logger.
|
||||
if cfg.Server.ServerCert != "" || cfg.Server.ServerKey != "" {
|
||||
logger.Info(fmt.Sprintf("Provision service started using https on port %s with cert %s key %s",
|
||||
cfg.Server.HTTPPort, cfg.Server.ServerCert, cfg.Server.ServerKey))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.Server.ServerCert, cfg.Server.ServerKey, api.MakeHandler(svc))
|
||||
errs <- http.ListenAndServeTLS(p, cfg.Server.ServerCert, cfg.Server.ServerKey, api.MakeHandler(svc, logger))
|
||||
return
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Provision service started using http on port %s", cfg.Server.HTTPPort))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, logger))
|
||||
}
|
||||
|
||||
func loadConfigFromFile(file string) (provision.Config, error) {
|
||||
|
||||
@@ -327,9 +327,9 @@ func startHTTPServer(tracer opentracing.Tracer, svc notifiers.Service, port stri
|
||||
p := fmt.Sprintf(":%s", port)
|
||||
if certFile != "" || keyFile != "" {
|
||||
logger.Info(fmt.Sprintf("SMPP notifier service started using https, cert %s key %s, exposed port %s", certFile, keyFile, port))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, api.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, api.MakeHandler(svc, tracer, logger))
|
||||
} else {
|
||||
logger.Info(fmt.Sprintf("SMPP notifier service started using http, exposed port %s", port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer, logger))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,9 +314,9 @@ func startHTTPServer(tracer opentracing.Tracer, svc notifiers.Service, port stri
|
||||
p := fmt.Sprintf(":%s", port)
|
||||
if certFile != "" || keyFile != "" {
|
||||
logger.Info(fmt.Sprintf("SMTP notifier service started using https, cert %s key %s, exposed port %s", certFile, keyFile, port))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, api.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, api.MakeHandler(svc, tracer, logger))
|
||||
} else {
|
||||
logger.Info(fmt.Sprintf("SMTP notifier service started using http, exposed port %s", port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer, logger))
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -157,8 +157,8 @@ func main() {
|
||||
svc := newService(auth, dbTracer, cacheTracer, db, cacheClient, esClient, logger)
|
||||
errs := make(chan error, 2)
|
||||
|
||||
go startHTTPServer(thhttpapi.MakeHandler(thingsTracer, svc), cfg.httpPort, cfg, logger, errs)
|
||||
go startHTTPServer(authhttpapi.MakeHandler(thingsTracer, svc), cfg.authHTTPPort, cfg, logger, errs)
|
||||
go startHTTPServer(thhttpapi.MakeHandler(thingsTracer, svc, logger), cfg.httpPort, cfg, logger, errs)
|
||||
go startHTTPServer(authhttpapi.MakeHandler(thingsTracer, svc, logger), cfg.authHTTPPort, cfg, logger, errs)
|
||||
go startGRPCServer(svc, thingsTracer, cfg, logger, errs)
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -267,5 +267,5 @@ func newService(db *sqlx.DB, logger logger.Logger) readers.MessageRepository {
|
||||
func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient, port string, logger logger.Logger, errs chan error) {
|
||||
p := fmt.Sprintf(":%s", port)
|
||||
logger.Info(fmt.Sprintf("Timescale reader service started, exposed port %s", port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, svcName))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, ac, svcName, logger))
|
||||
}
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ func main() {
|
||||
tracer, closer := initJaeger("twins", cfg.jaegerURL, logger)
|
||||
defer closer.Close()
|
||||
errs := make(chan error, 2)
|
||||
go startHTTPServer(twapi.MakeHandler(tracer, svc), cfg.httpPort, cfg, logger, errs)
|
||||
go startHTTPServer(twapi.MakeHandler(tracer, svc, logger), cfg.httpPort, cfg, logger, errs)
|
||||
|
||||
go func() {
|
||||
c := make(chan os.Signal)
|
||||
|
||||
+2
-2
@@ -415,9 +415,9 @@ func startHTTPServer(tracer opentracing.Tracer, svc users.Service, port string,
|
||||
p := fmt.Sprintf(":%s", port)
|
||||
if certFile != "" || keyFile != "" {
|
||||
logger.Info(fmt.Sprintf("Users service started using https, cert %s key %s, exposed port %s", certFile, keyFile, port))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, api.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServeTLS(p, certFile, keyFile, api.MakeHandler(svc, tracer, logger))
|
||||
} else {
|
||||
logger.Info(fmt.Sprintf("Users service started using http, exposed port %s", port))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer))
|
||||
errs <- http.ListenAndServe(p, api.MakeHandler(svc, tracer, logger))
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -17,7 +17,8 @@ import (
|
||||
notifiers "github.com/mainflux/mainflux/consumers/notifiers"
|
||||
httpapi "github.com/mainflux/mainflux/consumers/notifiers/api"
|
||||
"github.com/mainflux/mainflux/consumers/notifiers/mocks"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
@@ -36,9 +37,10 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
notFoundRes = toJSON(httputil.ErrorRes{Err: errors.ErrNotFound.Error()})
|
||||
unauthRes = toJSON(httputil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
invalidRes = toJSON(httputil.ErrorRes{Err: errors.ErrInvalidQueryParams.Error()})
|
||||
notFoundRes = toJSON(apiutil.ErrorRes{Err: errors.ErrNotFound.Error()})
|
||||
unauthRes = toJSON(apiutil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
invalidRes = toJSON(apiutil.ErrorRes{Err: errors.ErrInvalidQueryParams.Error()})
|
||||
missingTokRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrBearerToken.Error()})
|
||||
)
|
||||
|
||||
type testRequest struct {
|
||||
@@ -56,7 +58,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
@@ -74,7 +76,8 @@ func newService(tokens map[string]string) notifiers.Service {
|
||||
}
|
||||
|
||||
func newServer(svc notifiers.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -242,7 +245,7 @@ func TestView(t *testing.T) {
|
||||
id: id,
|
||||
auth: "",
|
||||
status: http.StatusUnauthorized,
|
||||
res: unauthRes,
|
||||
res: missingTokRes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -362,7 +365,7 @@ func TestList(t *testing.T) {
|
||||
desc: "list with empty auth token",
|
||||
auth: "",
|
||||
status: http.StatusUnauthorized,
|
||||
res: unauthRes,
|
||||
res: missingTokRes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -418,7 +421,7 @@ func TestRemove(t *testing.T) {
|
||||
desc: "remove empty id",
|
||||
id: "",
|
||||
auth: token,
|
||||
status: http.StatusNotFound,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "view with invalid auth token",
|
||||
@@ -432,7 +435,7 @@ func TestRemove(t *testing.T) {
|
||||
id: id,
|
||||
auth: "",
|
||||
status: http.StatusUnauthorized,
|
||||
res: unauthRes,
|
||||
res: missingTokRes,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,7 @@
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidTopic = errors.New("invalid Subscription topic")
|
||||
errInvalidContact = errors.New("invalid Subscription contact")
|
||||
)
|
||||
import "github.com/mainflux/mainflux/internal/apiutil"
|
||||
|
||||
type createSubReq struct {
|
||||
token string
|
||||
@@ -20,13 +13,13 @@ type createSubReq struct {
|
||||
|
||||
func (req createSubReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.Topic == "" {
|
||||
return errInvalidTopic
|
||||
return apiutil.ErrInvalidTopic
|
||||
}
|
||||
if req.Contact == "" {
|
||||
return errInvalidContact
|
||||
return apiutil.ErrInvalidContact
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -38,10 +31,10 @@ type subReq struct {
|
||||
|
||||
func (req subReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.id == "" {
|
||||
return errors.ErrNotFound
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -56,7 +49,7 @@ type listSubsReq struct {
|
||||
|
||||
func (req listSubsReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,18 +14,27 @@ import (
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
notifiers "github.com/mainflux/mainflux/consumers/notifiers"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
const contentType = "application/json"
|
||||
const (
|
||||
contentType = "application/json"
|
||||
offsetKey = "offset"
|
||||
limitKey = "limit"
|
||||
topicKey = "topic"
|
||||
contactKey = "contact"
|
||||
defOffset = 0
|
||||
defLimit = 20
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc notifiers.Service, tracer opentracing.Tracer) http.Handler {
|
||||
func MakeHandler(svc notifiers.Service, tracer opentracing.Tracer, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
mux := bone.New()
|
||||
@@ -68,56 +77,43 @@ func decodeCreate(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
var req createSubReq
|
||||
|
||||
req := createSubReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.token = t
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeSubscription(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := subReq{
|
||||
id: bone.GetValue(r, "id"),
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeList(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listSubsReq{
|
||||
token: t,
|
||||
}
|
||||
vals := bone.GetQuery(r, "topic")
|
||||
req := listSubsReq{token: apiutil.ExtractBearerToken(r)}
|
||||
vals := bone.GetQuery(r, topicKey)
|
||||
if len(vals) > 0 {
|
||||
req.topic = vals[0]
|
||||
}
|
||||
|
||||
vals = bone.GetQuery(r, "contact")
|
||||
vals = bone.GetQuery(r, contactKey)
|
||||
if len(vals) > 0 {
|
||||
req.contact = vals[0]
|
||||
}
|
||||
|
||||
offset, err := httputil.ReadUintQuery(r, "offset", 0)
|
||||
offset, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return listSubsReq{}, err
|
||||
}
|
||||
req.offset = uint(offset)
|
||||
|
||||
limit, err := httputil.ReadUintQuery(r, "limit", 20)
|
||||
limit, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return listSubsReq{}, err
|
||||
}
|
||||
@@ -145,13 +141,15 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
errors.Contains(err, errInvalidContact),
|
||||
errors.Contains(err, errInvalidTopic),
|
||||
err == apiutil.ErrInvalidContact,
|
||||
err == apiutil.ErrInvalidTopic,
|
||||
err == apiutil.ErrMissingID,
|
||||
errors.Contains(err, errors.ErrInvalidQueryParams):
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrConflict):
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
@@ -169,7 +167,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ import (
|
||||
adapter "github.com/mainflux/mainflux/http"
|
||||
"github.com/mainflux/mainflux/http/api"
|
||||
"github.com/mainflux/mainflux/http/mocks"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -27,7 +28,8 @@ func newService(cc mainflux.ThingsServiceClient) adapter.Service {
|
||||
}
|
||||
|
||||
func newHTTPServer(svc adapter.Service) *httptest.Server {
|
||||
mux := api.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := api.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -48,7 +50,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
}
|
||||
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.basicAuth && tr.token != "" {
|
||||
req.SetBasicAuth("", tr.token)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/pkg/messaging"
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ type publishReq struct {
|
||||
|
||||
func (req publishReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
adapter "github.com/mainflux/mainflux/http"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/pkg/messaging"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
@@ -39,7 +40,7 @@ var (
|
||||
var channelPartRegExp = regexp.MustCompile(`^/channels/([\w\-]+)/messages(/[^?]*)?(\?.*)?$`)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc adapter.Service, tracer opentracing.Tracer) http.Handler {
|
||||
func MakeHandler(svc adapter.Service, tracer opentracing.Tracer, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
}
|
||||
@@ -115,10 +116,7 @@ func decodeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
case ok:
|
||||
token = pass
|
||||
case !ok:
|
||||
token, err = httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
token = apiutil.ExtractBearerToken(r)
|
||||
}
|
||||
|
||||
payload, err := ioutil.ReadAll(r.Body)
|
||||
@@ -148,7 +146,8 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrAuthorization):
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
@@ -178,7 +177,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package apiutil
|
||||
|
||||
import "github.com/mainflux/mainflux/pkg/errors"
|
||||
|
||||
// Errors defined in this file are used by the LoggingErrorEncoder decorator
|
||||
// to distinguish and log API request validation errors and avoid that service
|
||||
// errors are logged twice.
|
||||
var (
|
||||
// ErrBearerToken indicates missing or invalid bearer user token.
|
||||
ErrBearerToken = errors.New("missing or invalid bearer user token")
|
||||
|
||||
// ErrBearerKey indicates missing or invalid bearer entity key.
|
||||
ErrBearerKey = errors.New("missing or invalid bearer entity key")
|
||||
|
||||
// ErrMissingID indicates missing entity ID.
|
||||
ErrMissingID = errors.New("missing entity id")
|
||||
|
||||
// ErrInvalidAuthKey indicates invalid auth key.
|
||||
ErrInvalidAuthKey = errors.New("invalid auth key")
|
||||
|
||||
// ErrInvalidIDFormat indicates an invalid ID format.
|
||||
ErrInvalidIDFormat = errors.New("invalid id format provided")
|
||||
|
||||
// ErrNameSize indicates that name size exceeds the max.
|
||||
ErrNameSize = errors.New("invalid name size")
|
||||
|
||||
// ErrLimitSize indicates that an invalid limit.
|
||||
ErrLimitSize = errors.New("invalid limit size")
|
||||
|
||||
// ErrOffsetSize indicates an invalid offset.
|
||||
ErrOffsetSize = errors.New("invalid offset size")
|
||||
|
||||
// ErrInvalidOrder indicates an invalid list order.
|
||||
ErrInvalidOrder = errors.New("invalid list order provided")
|
||||
|
||||
// ErrInvalidDirection indicates an invalid list direction.
|
||||
ErrInvalidDirection = errors.New("invalid list direction provided")
|
||||
|
||||
// ErrEmptyList indicates that entity data is empty.
|
||||
ErrEmptyList = errors.New("empty list provided")
|
||||
|
||||
// ErrMalformedPolicy indicates that policies are malformed.
|
||||
ErrMalformedPolicy = errors.New("falmormed policy")
|
||||
|
||||
// ErrMissingPolicySub indicates that policies are subject.
|
||||
ErrMissingPolicySub = errors.New("falmormed policy subject")
|
||||
|
||||
// ErrMissingPolicyObj indicates missing policies object.
|
||||
ErrMissingPolicyObj = errors.New("falmormed policy object")
|
||||
|
||||
// ErrMissingPolicyAct indicates missing policies action.
|
||||
ErrMissingPolicyAct = errors.New("falmormed policy action")
|
||||
|
||||
// ErrMissingCertData indicates missing cert data (ttl, key_type or key_bits).
|
||||
ErrMissingCertData = errors.New("missing certificate data")
|
||||
|
||||
// ErrInvalidTopic indicates an invalid subscription topic.
|
||||
ErrInvalidTopic = errors.New("invalid Subscription topic")
|
||||
|
||||
// ErrInvalidContact indicates an invalid subscription contract.
|
||||
ErrInvalidContact = errors.New("invalid Subscription contact")
|
||||
|
||||
// ErrMissingEmail indicates missing email.
|
||||
ErrMissingEmail = errors.New("missing email")
|
||||
|
||||
// ErrMissingHost indicates missing host.
|
||||
ErrMissingHost = errors.New("missing host")
|
||||
|
||||
// ErrMissingPass indicates missing password.
|
||||
ErrMissingPass = errors.New("missing password")
|
||||
|
||||
// ErrMissingConfPass indicates missing conf password.
|
||||
ErrMissingConfPass = errors.New("missing conf password")
|
||||
|
||||
// ErrInvalidResetPass indicates an invalid reset password.
|
||||
ErrInvalidResetPass = errors.New("invalid reset password")
|
||||
|
||||
// ErrInvalidComparator indicates an invalid comparator.
|
||||
ErrInvalidComparator = errors.New("invalid comparator")
|
||||
|
||||
// ErrMissingMemberType indicates missing group member type.
|
||||
ErrMissingMemberType = errors.New("missing group member type")
|
||||
|
||||
// ErrInvalidAPIKey indicates an invalid API key type.
|
||||
ErrInvalidAPIKey = errors.New("invalid api key type")
|
||||
|
||||
// ErrMaxLevelExceeded indicates an invalid group level.
|
||||
ErrMaxLevelExceeded = errors.New("invalid group level (should be lower than 5)")
|
||||
|
||||
// ErrBootstrapState indicates an invalid boostrap state.
|
||||
ErrBootstrapState = errors.New("invalid bootstrap state")
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package httputil
|
||||
package apiutil
|
||||
|
||||
// ErrorRes represents the HTTP error response body.
|
||||
type ErrorRes struct {
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BearerPrefix represents the token prefix for Bearer authentication scheme.
|
||||
const BearerPrefix = "Bearer "
|
||||
|
||||
// ExtractBearerToken returns value of the bearer token. If there is no bearer token - an empty value is returned.
|
||||
func ExtractBearerToken(r *http.Request) string {
|
||||
token := r.Header.Get("Authorization")
|
||||
|
||||
if !strings.HasPrefix(token, BearerPrefix) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.TrimPrefix(token, BearerPrefix)
|
||||
}
|
||||
@@ -1,17 +1,59 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package httputil
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
|
||||
// LoggingErrorEncoder is a go-kit error encoder logging decorator.
|
||||
func LoggingErrorEncoder(logger logger.Logger, enc kithttp.ErrorEncoder) kithttp.ErrorEncoder {
|
||||
return func(ctx context.Context, err error, w http.ResponseWriter) {
|
||||
switch err {
|
||||
case ErrBearerToken,
|
||||
ErrMissingID,
|
||||
ErrBearerKey,
|
||||
ErrInvalidAuthKey,
|
||||
ErrInvalidIDFormat,
|
||||
ErrNameSize,
|
||||
ErrLimitSize,
|
||||
ErrOffsetSize,
|
||||
ErrInvalidOrder,
|
||||
ErrInvalidDirection,
|
||||
ErrEmptyList,
|
||||
ErrMalformedPolicy,
|
||||
ErrMissingPolicySub,
|
||||
ErrMissingPolicyObj,
|
||||
ErrMissingPolicyAct,
|
||||
ErrMissingCertData,
|
||||
ErrInvalidTopic,
|
||||
ErrInvalidContact,
|
||||
ErrMissingEmail,
|
||||
ErrMissingHost,
|
||||
ErrMissingPass,
|
||||
ErrMissingConfPass,
|
||||
ErrInvalidResetPass,
|
||||
ErrInvalidComparator,
|
||||
ErrMissingMemberType,
|
||||
ErrInvalidAPIKey,
|
||||
ErrMaxLevelExceeded,
|
||||
ErrBootstrapState:
|
||||
logger.Error(err.Error())
|
||||
}
|
||||
|
||||
enc(ctx, err, w)
|
||||
}
|
||||
}
|
||||
|
||||
// ReadUintQuery reads the value of uint64 http query parameters for a given key
|
||||
func ReadUintQuery(r *http.Request, key string, def uint64) (uint64, error) {
|
||||
vals := bone.GetQuery(r, key)
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package httputil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
|
||||
// BearerPrefix represents the token prefix for Bearer authentication scheme.
|
||||
const BearerPrefix = "Bearer "
|
||||
|
||||
// ExtractAuthToken reads the value of request Authorization and removes the Bearer substring or returns error if it does not exist
|
||||
func ExtractAuthToken(r *http.Request) (string, error) {
|
||||
token := r.Header.Get("Authorization")
|
||||
|
||||
if !strings.HasPrefix(token, BearerPrefix) {
|
||||
return token, errors.ErrAuthentication
|
||||
}
|
||||
|
||||
return strings.TrimPrefix(token, BearerPrefix), nil
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package httputil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrMissingToken indicates missing user token.
|
||||
ErrMissingToken = errors.New("missing user token")
|
||||
|
||||
// ErrMissingID indicates missing entity ID.
|
||||
ErrMissingID = errors.New("missing entity id")
|
||||
)
|
||||
|
||||
// Middleware is an ErrorEncoder middleware
|
||||
type Middleware func(kithttp.ErrorEncoder) kithttp.ErrorEncoder
|
||||
|
||||
// LoggingErrorEncoder is a go-kit error encoder logging decorator.
|
||||
func LoggingErrorEncoder(logger logger.Logger, enc kithttp.ErrorEncoder) kithttp.ErrorEncoder {
|
||||
return func(ctx context.Context, err error, w http.ResponseWriter) {
|
||||
logger.Error(err.Error())
|
||||
enc(ctx, err, w)
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
Debug
|
||||
)
|
||||
|
||||
// ErrInvalidLogLevel indicates an unrecognized log level.
|
||||
var ErrInvalidLogLevel = errors.New("unrecognized log level")
|
||||
|
||||
// Level represents severity level while logging.
|
||||
|
||||
+2
-1
@@ -5,9 +5,10 @@ package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-kit/kit/log"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
)
|
||||
|
||||
// Logger specifies logging API.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package logger
|
||||
|
||||
var _ Logger = (*loggerMock)(nil)
|
||||
|
||||
type loggerMock struct{}
|
||||
|
||||
// NewMock returns wrapped go kit logger mock.
|
||||
func NewMock() Logger {
|
||||
return &loggerMock{}
|
||||
}
|
||||
|
||||
func (l loggerMock) Debug(msg string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (l loggerMock) Info(msg string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (l loggerMock) Warn(msg string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (l loggerMock) Error(msg string) {
|
||||
return
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
package api
|
||||
|
||||
import "github.com/mainflux/mainflux/pkg/errors"
|
||||
import "github.com/mainflux/mainflux/internal/apiutil"
|
||||
|
||||
type browseReq struct {
|
||||
ServerURI string
|
||||
@@ -13,7 +13,7 @@ type browseReq struct {
|
||||
|
||||
func (req *browseReq) validate() error {
|
||||
if req.ServerURI == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+10
-8
@@ -11,7 +11,8 @@ import (
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/opcua"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
@@ -29,9 +30,9 @@ const (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc opcua.Service) http.Handler {
|
||||
func MakeHandler(svc opcua.Service, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
r := bone.New()
|
||||
@@ -50,17 +51,17 @@ func MakeHandler(svc opcua.Service) http.Handler {
|
||||
}
|
||||
|
||||
func decodeBrowse(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
s, err := httputil.ReadStringQuery(r, serverParam, "")
|
||||
s, err := apiutil.ReadStringQuery(r, serverParam, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n, err := httputil.ReadStringQuery(r, namespaceParam, "")
|
||||
n, err := apiutil.ReadStringQuery(r, namespaceParam, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i, err := httputil.ReadStringQuery(r, identifierParam, "")
|
||||
i, err := apiutil.ReadStringQuery(r, identifierParam, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -100,7 +101,8 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrInvalidQueryParams),
|
||||
errors.Contains(err, errors.ErrMalformedEntity):
|
||||
errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
||||
default:
|
||||
@@ -109,7 +111,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func TestCreateChannel(t *testing.T) {
|
||||
ts := newThingsServer(svc)
|
||||
defer ts.Close()
|
||||
|
||||
chWrongExtID := sdk.Channel{ID: "b0aa-000000000001", Name: "1", Metadata:metadata}
|
||||
chWrongExtID := sdk.Channel{ID: "b0aa-000000000001", Name: "1", Metadata: metadata}
|
||||
|
||||
sdkConf := sdk.Config{
|
||||
ThingsURL: ts.URL,
|
||||
@@ -73,14 +73,14 @@ func TestCreateChannel(t *testing.T) {
|
||||
empty: false,
|
||||
},
|
||||
{
|
||||
desc: "create a new channel with external UUID",
|
||||
desc: "create a new channel with external UUID",
|
||||
channel: ch2,
|
||||
token: token,
|
||||
err: nil,
|
||||
empty: false,
|
||||
},
|
||||
{
|
||||
desc: "create a new channel with wrong external UUID",
|
||||
desc: "create a new channel with wrong external UUID",
|
||||
channel: chWrongExtID,
|
||||
token: token,
|
||||
err: createError(sdk.ErrFailedCreation, http.StatusBadRequest),
|
||||
@@ -269,8 +269,8 @@ func TestChannels(t *testing.T) {
|
||||
token: token,
|
||||
offset: 0,
|
||||
limit: 0,
|
||||
err: nil,
|
||||
response: channels[0:10],
|
||||
err: createError(sdk.ErrFailedFetch, http.StatusBadRequest),
|
||||
response: nil,
|
||||
},
|
||||
{
|
||||
desc: "get a list of channels with limit greater than max",
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
adapter "github.com/mainflux/mainflux/http"
|
||||
"github.com/mainflux/mainflux/http/api"
|
||||
"github.com/mainflux/mainflux/http/mocks"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
sdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -24,7 +25,8 @@ func newMessageService(cc mainflux.ThingsServiceClient) adapter.Service {
|
||||
}
|
||||
|
||||
func newMessageServer(svc adapter.Service) *httptest.Server {
|
||||
mux := api.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := api.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -328,7 +328,7 @@ func NewSDK(conf Config) SDK {
|
||||
|
||||
func (sdk mfSDK) sendRequest(req *http.Request, token, contentType string) (*http.Response, error) {
|
||||
if token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+token)
|
||||
}
|
||||
|
||||
if contentType != "" {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
sdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
@@ -55,7 +56,8 @@ func newThingsService(tokens map[string]string) things.Service {
|
||||
}
|
||||
|
||||
func newThingsServer(svc things.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -316,8 +318,8 @@ func TestThings(t *testing.T) {
|
||||
token: token,
|
||||
offset: 0,
|
||||
limit: 0,
|
||||
err: nil,
|
||||
response: things[0:10],
|
||||
err: createError(sdk.ErrFailedFetch, http.StatusBadRequest),
|
||||
response: nil,
|
||||
},
|
||||
{
|
||||
desc: "get a list of things with limit greater than max",
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
sdk "github.com/mainflux/mainflux/pkg/sdk/go"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/users"
|
||||
@@ -46,7 +47,8 @@ func newUserService() users.Service {
|
||||
}
|
||||
|
||||
func newUserServer(svc users.Service) *httptest.Server {
|
||||
mux := api.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := api.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package api
|
||||
|
||||
import "github.com/mainflux/mainflux/pkg/errors"
|
||||
import "github.com/mainflux/mainflux/internal/apiutil"
|
||||
|
||||
type provisionReq struct {
|
||||
token string
|
||||
@@ -10,9 +10,14 @@ type provisionReq struct {
|
||||
}
|
||||
|
||||
func (req provisionReq) validate() error {
|
||||
if req.ExternalID == "" || req.ExternalKey == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.ExternalID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.ExternalKey == "" {
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -22,7 +27,7 @@ type mappingReq struct {
|
||||
|
||||
func (req mappingReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -21,7 +22,7 @@ func TestValidate(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
"external id for device empty": {
|
||||
err: errors.ErrMalformedEntity,
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+15
-17
@@ -8,7 +8,8 @@ import (
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/provision"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
@@ -19,10 +20,10 @@ const (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc provision.Service) http.Handler {
|
||||
func MakeHandler(svc provision.Service, logger logger.Logger) http.Handler {
|
||||
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
r := bone.New()
|
||||
@@ -69,11 +70,8 @@ func decodeProvisionRequest(_ context.Context, r *http.Request) (interface{}, er
|
||||
if r.Header.Get("Content-Type") != contentType {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := provisionReq{token: t}
|
||||
|
||||
req := provisionReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -85,25 +83,25 @@ func decodeMappingRequest(_ context.Context, r *http.Request) (interface{}, erro
|
||||
if r.Header.Get("Content-Type") != contentType {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := mappingReq{token: t}
|
||||
|
||||
req := mappingReq{token: apiutil.ExtractBearerToken(r)}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrUnsupportedContentType):
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
case errors.Contains(err, errors.ErrMalformedEntity):
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrBearerKey:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrConflict):
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
@@ -111,7 +109,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/transformers/senml"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/readers"
|
||||
@@ -49,7 +49,8 @@ var (
|
||||
)
|
||||
|
||||
func newServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient) *httptest.Server {
|
||||
mux := api.MakeHandler(repo, tc, ac, svcName)
|
||||
logger := logger.NewMock()
|
||||
mux := api.MakeHandler(repo, tc, ac, svcName, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", tr.token)
|
||||
}
|
||||
|
||||
return tr.client.Do(req)
|
||||
|
||||
+15
-6
@@ -4,10 +4,12 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/readers"
|
||||
)
|
||||
|
||||
const maxLimitSize = 1000
|
||||
|
||||
type apiReq interface {
|
||||
validate() error
|
||||
}
|
||||
@@ -20,21 +22,28 @@ type listMessagesReq struct {
|
||||
|
||||
func (req listMessagesReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.chanID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
if req.pageMeta.Limit < 1 || req.pageMeta.Offset < 0 {
|
||||
return errors.ErrInvalidQueryParams
|
||||
|
||||
if req.pageMeta.Limit < 1 || req.pageMeta.Limit > maxLimitSize {
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
|
||||
if req.pageMeta.Offset < 0 {
|
||||
return apiutil.ErrOffsetSize
|
||||
}
|
||||
|
||||
if req.pageMeta.Comparator != "" &&
|
||||
req.pageMeta.Comparator != readers.EqualKey &&
|
||||
req.pageMeta.Comparator != readers.LowerThanKey &&
|
||||
req.pageMeta.Comparator != readers.LowerThanEqualKey &&
|
||||
req.pageMeta.Comparator != readers.GreaterThanKey &&
|
||||
req.pageMeta.Comparator != readers.GreaterThanEqualKey {
|
||||
return errors.ErrInvalidQueryParams
|
||||
return apiutil.ErrInvalidComparator
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+26
-26
@@ -12,7 +12,8 @@ import (
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/readers"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
@@ -51,7 +52,7 @@ var (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient, svcName string) http.Handler {
|
||||
func MakeHandler(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, ac mainflux.AuthServiceClient, svcName string, logger logger.Logger) http.Handler {
|
||||
thingsAuth = tc
|
||||
usersAuth = ac
|
||||
|
||||
@@ -74,79 +75,74 @@ func MakeHandler(svc readers.MessageRepository, tc mainflux.ThingsServiceClient,
|
||||
}
|
||||
|
||||
func decodeList(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
offset, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
offset, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limit, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
limit, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
format, err := httputil.ReadStringQuery(r, formatKey, defFormat)
|
||||
format, err := apiutil.ReadStringQuery(r, formatKey, defFormat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subtopic, err := httputil.ReadStringQuery(r, subtopicKey, "")
|
||||
subtopic, err := apiutil.ReadStringQuery(r, subtopicKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
publisher, err := httputil.ReadStringQuery(r, publisherKey, "")
|
||||
publisher, err := apiutil.ReadStringQuery(r, publisherKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
protocol, err := httputil.ReadStringQuery(r, protocolKey, "")
|
||||
protocol, err := apiutil.ReadStringQuery(r, protocolKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name, err := httputil.ReadStringQuery(r, nameKey, "")
|
||||
name, err := apiutil.ReadStringQuery(r, nameKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, err := httputil.ReadFloatQuery(r, valueKey, 0)
|
||||
v, err := apiutil.ReadFloatQuery(r, valueKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
comparator, err := httputil.ReadStringQuery(r, comparatorKey, "")
|
||||
comparator, err := apiutil.ReadStringQuery(r, comparatorKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vs, err := httputil.ReadStringQuery(r, stringValueKey, "")
|
||||
vs, err := apiutil.ReadStringQuery(r, stringValueKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vd, err := httputil.ReadStringQuery(r, dataValueKey, "")
|
||||
vd, err := apiutil.ReadStringQuery(r, dataValueKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
from, err := httputil.ReadFloatQuery(r, fromKey, 0)
|
||||
from, err := apiutil.ReadFloatQuery(r, fromKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
to, err := httputil.ReadFloatQuery(r, toKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
to, err := apiutil.ReadFloatQuery(r, toKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listMessagesReq{
|
||||
chanID: bone.GetValue(r, "chanID"),
|
||||
token: t,
|
||||
token: r.Header.Get("Authorization"),
|
||||
pageMeta: readers.PageMetadata{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
@@ -164,7 +160,7 @@ func decodeList(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
},
|
||||
}
|
||||
|
||||
vb, err := httputil.ReadBoolQuery(r, boolValueKey, false)
|
||||
vb, err := apiutil.ReadBoolQuery(r, boolValueKey, false)
|
||||
if err != nil && err != errors.ErrNotFoundParam {
|
||||
return nil, err
|
||||
}
|
||||
@@ -197,11 +193,15 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, nil):
|
||||
case errors.Contains(err, errors.ErrInvalidQueryParams),
|
||||
errors.Contains(err, errors.ErrMalformedEntity):
|
||||
errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrLimitSize,
|
||||
err == apiutil.ErrOffsetSize,
|
||||
err == apiutil.ErrInvalidComparator:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
|
||||
case errors.Contains(err, readers.ErrReadMessages):
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
@@ -211,7 +211,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func (client grpcClient) CanAccessByKey(ctx context.Context, req *mainflux.Acces
|
||||
ctx, cancel := context.WithTimeout(ctx, client.timeout)
|
||||
defer cancel()
|
||||
|
||||
ar := AccessByKeyReq{
|
||||
ar := accessByKeyReq{
|
||||
thingKey: req.GetToken(),
|
||||
chanID: req.GetChanID(),
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (client grpcClient) Identify(ctx context.Context, req *mainflux.Token, _ ..
|
||||
}
|
||||
|
||||
func encodeCanAccessByKeyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
req := grpcReq.(AccessByKeyReq)
|
||||
req := grpcReq.(accessByKeyReq)
|
||||
return &mainflux.AccessByKeyReq{Token: req.thingKey, ChanID: req.chanID}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func canAccessEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(AccessByKeyReq)
|
||||
req := request.(accessByKeyReq)
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3,16 +3,20 @@
|
||||
|
||||
package grpc
|
||||
|
||||
import "github.com/mainflux/mainflux/pkg/errors"
|
||||
import "github.com/mainflux/mainflux/internal/apiutil"
|
||||
|
||||
type AccessByKeyReq struct {
|
||||
type accessByKeyReq struct {
|
||||
thingKey string
|
||||
chanID string
|
||||
}
|
||||
|
||||
func (req AccessByKeyReq) validate() error {
|
||||
if req.chanID == "" || req.thingKey == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
func (req accessByKeyReq) validate() error {
|
||||
if req.chanID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.thingKey == "" {
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -25,7 +29,7 @@ type accessByIDReq struct {
|
||||
|
||||
func (req accessByIDReq) validate() error {
|
||||
if req.thingID == "" || req.chanID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -38,7 +42,7 @@ type channelOwnerReq struct {
|
||||
|
||||
func (req channelOwnerReq) validate() error {
|
||||
if req.owner == "" || req.chanID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -50,7 +54,7 @@ type identifyReq struct {
|
||||
|
||||
func (req identifyReq) validate() error {
|
||||
if req.key == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
kitgrpc "github.com/go-kit/kit/transport/grpc"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
@@ -90,7 +91,7 @@ func (gs *grpcServer) Identify(ctx context.Context, req *mainflux.Token) (*mainf
|
||||
|
||||
func decodeCanAccessByKeyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
req := grpcReq.(*mainflux.AccessByKeyReq)
|
||||
return AccessByKeyReq{thingKey: req.GetToken(), chanID: req.GetChanID()}, nil
|
||||
return accessByKeyReq{thingKey: req.GetToken(), chanID: req.GetChanID()}, nil
|
||||
}
|
||||
|
||||
func decodeCanAccessByIDRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
@@ -122,7 +123,9 @@ func encodeError(err error) error {
|
||||
switch err {
|
||||
case nil:
|
||||
return nil
|
||||
case errors.ErrMalformedEntity:
|
||||
case errors.ErrMalformedEntity,
|
||||
apiutil.ErrMissingID,
|
||||
apiutil.ErrBearerKey:
|
||||
return status.Error(codes.InvalidArgument, "received invalid can access request")
|
||||
case errors.ErrAuthentication:
|
||||
return status.Error(codes.Unauthenticated, "missing or invalid credentials provided")
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
httpapi "github.com/mainflux/mainflux/things/api/auth/http"
|
||||
@@ -79,7 +80,8 @@ func newService(tokens map[string]string) things.Service {
|
||||
}
|
||||
|
||||
func newServer(svc things.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
package http
|
||||
|
||||
import "github.com/mainflux/mainflux/pkg/errors"
|
||||
import "github.com/mainflux/mainflux/internal/apiutil"
|
||||
|
||||
type identifyReq struct {
|
||||
Token string `json:"token"`
|
||||
@@ -11,7 +11,7 @@ type identifyReq struct {
|
||||
|
||||
func (req identifyReq) validate() error {
|
||||
if req.Token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -24,11 +24,11 @@ type canAccessByKeyReq struct {
|
||||
|
||||
func (req canAccessByKeyReq) validate() error {
|
||||
if req.Token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.chanID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -41,7 +41,7 @@ type canAccessByIDReq struct {
|
||||
|
||||
func (req canAccessByIDReq) validate() error {
|
||||
if req.ThingID == "" || req.chanID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -13,7 +13,8 @@ import (
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
@@ -22,9 +23,9 @@ import (
|
||||
const contentType = "application/json"
|
||||
|
||||
// MakeHandler returns a HTTP handler for auth API endpoints.
|
||||
func MakeHandler(tracer opentracing.Tracer, svc things.Service) http.Handler {
|
||||
func MakeHandler(tracer opentracing.Tracer, svc things.Service, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
r := bone.New()
|
||||
@@ -114,7 +115,8 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case err == apiutil.ErrBearerToken,
|
||||
errors.Contains(err, errors.ErrAuthentication):
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
@@ -122,7 +124,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
case errors.Contains(err, errors.ErrUnsupportedContentType):
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
case errors.Contains(err, errors.ErrMalformedEntity):
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
default:
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
@@ -130,7 +133,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
@@ -51,9 +52,10 @@ var (
|
||||
Metadata: map[string]interface{}{"test": "data"},
|
||||
}
|
||||
invalidName = strings.Repeat("m", maxNameSize+1)
|
||||
notFoundRes = toJSON(httputil.ErrorRes{Err: errors.ErrNotFound.Error()})
|
||||
unauthzRes = toJSON(httputil.ErrorRes{Err: errors.ErrAuthorization.Error()})
|
||||
unauthRes = toJSON(httputil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
notFoundRes = toJSON(apiutil.ErrorRes{Err: errors.ErrNotFound.Error()})
|
||||
unauthzRes = toJSON(apiutil.ErrorRes{Err: errors.ErrAuthorization.Error()})
|
||||
unauthRes = toJSON(apiutil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
missingTokRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrBearerToken.Error()})
|
||||
searchThingReq = things.PageMetadata{
|
||||
Limit: 5,
|
||||
Offset: 0,
|
||||
@@ -75,7 +77,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
@@ -99,7 +101,8 @@ func newService(tokens map[string]string) things.Service {
|
||||
}
|
||||
|
||||
func newServer(svc things.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -734,7 +737,7 @@ func TestViewThing(t *testing.T) {
|
||||
id: th.ID,
|
||||
auth: "",
|
||||
status: http.StatusUnauthorized,
|
||||
res: unauthRes,
|
||||
res: missingTokRes,
|
||||
},
|
||||
{
|
||||
desc: "view thing by passing invalid id",
|
||||
@@ -857,9 +860,9 @@ func TestListThings(t *testing.T) {
|
||||
{
|
||||
desc: "get a list of things with zero limit and offset 1",
|
||||
auth: token,
|
||||
status: http.StatusOK,
|
||||
status: http.StatusBadRequest,
|
||||
url: fmt.Sprintf("%s?offset=%d&limit=%d", thingURL, 1, 0),
|
||||
res: data[1:11],
|
||||
res: nil,
|
||||
},
|
||||
{
|
||||
desc: "get a list of things without offset",
|
||||
@@ -1087,9 +1090,9 @@ func TestSearchThings(t *testing.T) {
|
||||
{
|
||||
desc: "search things with zero limit",
|
||||
auth: token,
|
||||
status: http.StatusOK,
|
||||
status: http.StatusBadRequest,
|
||||
req: zeroLimitData,
|
||||
res: data[0:10],
|
||||
res: nil,
|
||||
},
|
||||
{
|
||||
desc: "search things without offset",
|
||||
@@ -1778,7 +1781,7 @@ func TestViewChannel(t *testing.T) {
|
||||
id: sch.ID,
|
||||
auth: "",
|
||||
status: http.StatusUnauthorized,
|
||||
res: unauthRes,
|
||||
res: missingTokRes,
|
||||
},
|
||||
{
|
||||
desc: "view channel with invalid id",
|
||||
@@ -1907,9 +1910,9 @@ func TestListChannels(t *testing.T) {
|
||||
{
|
||||
desc: "get a list of channels with zero limit and offset 1",
|
||||
auth: token,
|
||||
status: http.StatusOK,
|
||||
status: http.StatusBadRequest,
|
||||
url: fmt.Sprintf("%s?offset=%d&limit=%d", channelURL, 1, 0),
|
||||
res: channels[1:11],
|
||||
res: nil,
|
||||
},
|
||||
{
|
||||
desc: "get a list of channels with no offset provided",
|
||||
|
||||
@@ -5,7 +5,7 @@ package http
|
||||
|
||||
import (
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ type createThingReq struct {
|
||||
func validateUUID(extID string) (err error) {
|
||||
id, err := uuid.FromString(extID)
|
||||
if id.String() != extID || err != nil {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidIDFormat
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -40,15 +40,16 @@ func validateUUID(extID string) (err error) {
|
||||
|
||||
func (req createThingReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
}
|
||||
|
||||
if req.ID != "" && validateUUID(req.ID) != nil {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if len(req.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
// Do the validation only if request contains ID
|
||||
if req.ID != "" {
|
||||
return validateUUID(req.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -61,20 +62,22 @@ type createThingsReq struct {
|
||||
|
||||
func (req createThingsReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if len(req.Things) <= 0 {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
for _, thing := range req.Things {
|
||||
if thing.ID != "" && validateUUID(thing.ID) != nil {
|
||||
return errors.ErrMalformedEntity
|
||||
if thing.ID != "" {
|
||||
if err := validateUUID(thing.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(thing.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,15 +93,20 @@ type shareThingReq struct {
|
||||
|
||||
func (req shareThingReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.thingID == "" || len(req.UserIDs) == 0 || len(req.Policies) == 0 {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.thingID == "" || len(req.UserIDs) == 0 {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.Policies) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
for _, p := range req.Policies {
|
||||
if p != readPolicy && p != writePolicy && p != deletePolicy {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMalformedPolicy
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -113,15 +121,15 @@ type updateThingReq struct {
|
||||
|
||||
func (req updateThingReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -135,11 +143,15 @@ type updateKeyReq struct {
|
||||
|
||||
func (req updateKeyReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" || req.Key == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.id == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.Key == "" {
|
||||
return apiutil.ErrBearerKey
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -154,15 +166,16 @@ type createChannelReq struct {
|
||||
|
||||
func (req createChannelReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
}
|
||||
|
||||
if req.ID != "" && validateUUID(req.ID) != nil {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if len(req.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
// Do the validation only if request contains ID
|
||||
if req.ID != "" {
|
||||
return validateUUID(req.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -175,20 +188,22 @@ type createChannelsReq struct {
|
||||
|
||||
func (req createChannelsReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if len(req.Channels) <= 0 {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
for _, channel := range req.Channels {
|
||||
if channel.ID != "" && validateUUID(channel.ID) != nil {
|
||||
return errors.ErrMalformedEntity
|
||||
if channel.ID != "" {
|
||||
if err := validateUUID(channel.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(channel.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,15 +219,15 @@ type updateChannelReq struct {
|
||||
|
||||
func (req updateChannelReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -225,11 +240,11 @@ type viewResourceReq struct {
|
||||
|
||||
func (req viewResourceReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -242,29 +257,25 @@ type listResourcesReq struct {
|
||||
|
||||
func (req *listResourcesReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.pageMetadata.Limit == 0 {
|
||||
req.pageMetadata.Limit = defLimit
|
||||
}
|
||||
|
||||
if req.pageMetadata.Limit > maxLimitSize {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.pageMetadata.Limit > maxLimitSize || req.pageMetadata.Limit < 1 {
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
|
||||
if len(req.pageMetadata.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
if req.pageMetadata.Order != "" &&
|
||||
req.pageMetadata.Order != nameOrder && req.pageMetadata.Order != idOrder {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidOrder
|
||||
}
|
||||
|
||||
if req.pageMetadata.Dir != "" &&
|
||||
req.pageMetadata.Dir != ascDir && req.pageMetadata.Dir != descDir {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidDirection
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -278,25 +289,25 @@ type listByConnectionReq struct {
|
||||
|
||||
func (req listByConnectionReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.pageMetadata.Limit == 0 || req.pageMetadata.Limit > maxLimitSize {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.pageMetadata.Limit > maxLimitSize || req.pageMetadata.Limit < 1 {
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
|
||||
if req.pageMetadata.Order != "" &&
|
||||
req.pageMetadata.Order != nameOrder && req.pageMetadata.Order != idOrder {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidOrder
|
||||
}
|
||||
|
||||
if req.pageMetadata.Dir != "" &&
|
||||
req.pageMetadata.Dir != ascDir && req.pageMetadata.Dir != descDir {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidDirection
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -310,11 +321,11 @@ type connectThingReq struct {
|
||||
|
||||
func (req connectThingReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.chanID == "" || req.thingID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -328,21 +339,21 @@ type connectReq struct {
|
||||
|
||||
func (req connectReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if len(req.ChannelIDs) == 0 || len(req.ThingIDs) == 0 {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
|
||||
for _, chID := range req.ChannelIDs {
|
||||
if chID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
}
|
||||
for _, thingID := range req.ThingIDs {
|
||||
if thingID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,29 +368,29 @@ type listThingsGroupReq struct {
|
||||
|
||||
func (req listThingsGroupReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.groupID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.pageMetadata.Limit == 0 || req.pageMetadata.Limit > maxLimitSize {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.pageMetadata.Limit > maxLimitSize || req.pageMetadata.Limit < 1 {
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
|
||||
if len(req.pageMetadata.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
if req.pageMetadata.Order != "" &&
|
||||
req.pageMetadata.Order != "name" && req.pageMetadata.Order != "id" {
|
||||
return errors.ErrMalformedEntity
|
||||
req.pageMetadata.Order != nameOrder && req.pageMetadata.Order != idOrder {
|
||||
return apiutil.ErrInvalidOrder
|
||||
}
|
||||
|
||||
if req.pageMetadata.Dir != "" &&
|
||||
req.pageMetadata.Dir != "asc" && req.pageMetadata.Dir != "desc" {
|
||||
return errors.ErrMalformedEntity
|
||||
req.pageMetadata.Dir != ascDir && req.pageMetadata.Dir != descDir {
|
||||
return apiutil.ErrInvalidDirection
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -13,7 +13,8 @@ import (
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
log "github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/things"
|
||||
@@ -36,9 +37,9 @@ const (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(tracer opentracing.Tracer, svc things.Service) http.Handler {
|
||||
func MakeHandler(tracer opentracing.Tracer, svc things.Service, logger log.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
r := bone.New()
|
||||
@@ -208,13 +209,7 @@ func decodeThingCreation(_ context.Context, r *http.Request) (interface{}, error
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := createThingReq{token: t}
|
||||
|
||||
req := createThingReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -227,12 +222,7 @@ func decodeThingsCreation(_ context.Context, r *http.Request) (interface{}, erro
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := createThingsReq{token: t}
|
||||
req := createThingsReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req.Things); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -245,13 +235,8 @@ func decodeShareThing(ctx context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := shareThingReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
thingID: bone.GetValue(r, "id"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -266,13 +251,8 @@ func decodeThingUpdate(_ context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := updateThingReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -287,13 +267,8 @@ func decodeKeyUpdate(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := updateKeyReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -308,12 +283,7 @@ func decodeChannelCreation(_ context.Context, r *http.Request) (interface{}, err
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := createChannelReq{token: t}
|
||||
req := createChannelReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -326,13 +296,7 @@ func decodeChannelsCreation(_ context.Context, r *http.Request) (interface{}, er
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := createChannelsReq{token: t}
|
||||
|
||||
req := createChannelsReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req.Channels); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -345,13 +309,8 @@ func decodeChannelUpdate(_ context.Context, r *http.Request) (interface{}, error
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := updateChannelReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -362,13 +321,8 @@ func decodeChannelUpdate(_ context.Context, r *http.Request) (interface{}, error
|
||||
}
|
||||
|
||||
func decodeView(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := viewResourceReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
|
||||
@@ -376,47 +330,42 @@ func decodeView(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeList(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n, err := httputil.ReadStringQuery(r, nameKey, "")
|
||||
n, err := apiutil.ReadStringQuery(r, nameKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
or, err := httputil.ReadStringQuery(r, orderKey, "")
|
||||
or, err := apiutil.ReadStringQuery(r, orderKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d, err := httputil.ReadStringQuery(r, dirKey, "")
|
||||
d, err := apiutil.ReadStringQuery(r, dirKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
shared, err := httputil.ReadBoolQuery(r, sharedKey, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
shared, err := apiutil.ReadBoolQuery(r, sharedKey, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listResourcesReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
pageMetadata: things.PageMetadata{
|
||||
Offset: o,
|
||||
Limit: l,
|
||||
@@ -432,12 +381,7 @@ func decodeList(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeListByMetadata(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listResourcesReq{token: t}
|
||||
req := listResourcesReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req.pageMetadata); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -446,38 +390,33 @@ func decodeListByMetadata(_ context.Context, r *http.Request) (interface{}, erro
|
||||
}
|
||||
|
||||
func decodeListByConnection(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := httputil.ReadBoolQuery(r, disconnKey, false)
|
||||
c, err := apiutil.ReadBoolQuery(r, disconnKey, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
or, err := httputil.ReadStringQuery(r, orderKey, "")
|
||||
or, err := apiutil.ReadStringQuery(r, orderKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d, err := httputil.ReadStringQuery(r, dirKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
d, err := apiutil.ReadStringQuery(r, dirKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listByConnectionReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
pageMetadata: things.PageMetadata{
|
||||
Offset: o,
|
||||
@@ -492,13 +431,8 @@ func decodeListByConnection(_ context.Context, r *http.Request) (interface{}, er
|
||||
}
|
||||
|
||||
func decodeConnectThing(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := connectThingReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
chanID: bone.GetValue(r, "chanId"),
|
||||
thingID: bone.GetValue(r, "thingId"),
|
||||
}
|
||||
@@ -511,12 +445,7 @@ func decodeConnectList(_ context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := connectReq{token: t}
|
||||
req := connectReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -525,28 +454,23 @@ func decodeConnectList(_ context.Context, r *http.Request) (interface{}, error)
|
||||
}
|
||||
|
||||
func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := listThingsGroupReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
groupID: bone.GetValue(r, "groupId"),
|
||||
pageMetadata: things.PageMetadata{
|
||||
Offset: o,
|
||||
@@ -577,14 +501,24 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrAuthorization):
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
case errors.Contains(err, errors.ErrUnsupportedContentType):
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
case errors.Contains(err, errors.ErrInvalidQueryParams),
|
||||
errors.Contains(err, errors.ErrMalformedEntity):
|
||||
errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrNameSize,
|
||||
err == apiutil.ErrEmptyList,
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrMalformedPolicy,
|
||||
err == apiutil.ErrBearerKey,
|
||||
err == apiutil.ErrLimitSize,
|
||||
err == apiutil.ErrInvalidOrder,
|
||||
err == apiutil.ErrInvalidDirection,
|
||||
err == apiutil.ErrInvalidIDFormat:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
@@ -608,7 +542,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/twins"
|
||||
httpapi "github.com/mainflux/mainflux/twins/api/http"
|
||||
"github.com/mainflux/mainflux/twins/mocks"
|
||||
@@ -76,7 +77,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
@@ -85,7 +86,8 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
}
|
||||
|
||||
func newServer(svc twins.Service) *httptest.Server {
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc)
|
||||
logger := logger.NewMock()
|
||||
mux := httpapi.MakeHandler(mocktracer.New(), svc, logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
|
||||
+15
-15
@@ -4,7 +4,7 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/twins"
|
||||
)
|
||||
|
||||
@@ -26,11 +26,11 @@ type addTwinReq struct {
|
||||
|
||||
func (req addTwinReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if len(req.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -46,15 +46,15 @@ type updateTwinReq struct {
|
||||
|
||||
func (req updateTwinReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if len(req.Name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -67,11 +67,11 @@ type viewTwinReq struct {
|
||||
|
||||
func (req viewTwinReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -87,15 +87,15 @@ type listReq struct {
|
||||
|
||||
func (req *listReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.limit == 0 || req.limit > maxLimitSize {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.limit < 1 || req.limit > maxLimitSize {
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
|
||||
if len(req.name) > maxNameSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -110,15 +110,15 @@ type listStatesReq struct {
|
||||
|
||||
func (req *listStatesReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.id == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
if req.limit == 0 || req.limit > maxLimitSize {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrLimitSize
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+22
-37
@@ -13,7 +13,8 @@ import (
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/twins"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
@@ -31,9 +32,9 @@ const (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(tracer opentracing.Tracer, svc twins.Service) http.Handler {
|
||||
func MakeHandler(tracer opentracing.Tracer, svc twins.Service, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
r := bone.New()
|
||||
@@ -91,11 +92,7 @@ func decodeTwinCreation(_ context.Context, r *http.Request) (interface{}, error)
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := addTwinReq{token: t}
|
||||
req := addTwinReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
@@ -108,12 +105,8 @@ func decodeTwinUpdate(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := updateTwinReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -124,12 +117,8 @@ func decodeTwinUpdate(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeView(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := viewTwinReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: bone.GetValue(r, "id"),
|
||||
}
|
||||
|
||||
@@ -137,32 +126,28 @@ func decodeView(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeList(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n, err := httputil.ReadStringQuery(r, nameKey, "")
|
||||
n, err := apiutil.ReadStringQuery(r, nameKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
limit: l,
|
||||
offset: o,
|
||||
name: n,
|
||||
@@ -173,22 +158,18 @@ func decodeList(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeListStates(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listStatesReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
limit: l,
|
||||
offset: o,
|
||||
id: bone.GetValue(r, "id"),
|
||||
@@ -217,13 +198,17 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response interface
|
||||
|
||||
func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrAuthentication):
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrInvalidQueryParams):
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrUnsupportedContentType):
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
case errors.Contains(err, errors.ErrMalformedEntity):
|
||||
case errors.Contains(err, errors.ErrMalformedEntity),
|
||||
err == apiutil.ErrMissingID,
|
||||
err == apiutil.ErrNameSize,
|
||||
err == apiutil.ErrLimitSize:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
@@ -242,7 +227,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ func passwordChangeEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return nil, err
|
||||
}
|
||||
res := passwChangeRes{}
|
||||
if err := svc.ChangePassword(ctx, req.Token, req.Password, req.OldPassword); err != nil {
|
||||
if err := svc.ChangePassword(ctx, req.token, req.Password, req.OldPassword); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
|
||||
+26
-17
@@ -16,7 +16,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/users"
|
||||
@@ -39,14 +40,18 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
user = users.User{Email: validEmail, Password: validPass}
|
||||
notFoundRes = toJSON(httputil.ErrorRes{Err: errors.ErrNotFound.Error()})
|
||||
unauthRes = toJSON(httputil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
malformedRes = toJSON(httputil.ErrorRes{Err: errors.ErrMalformedEntity.Error()})
|
||||
weakPassword = toJSON(httputil.ErrorRes{Err: users.ErrPasswordFormat.Error()})
|
||||
unsupportedRes = toJSON(httputil.ErrorRes{Err: errors.ErrUnsupportedContentType.Error()})
|
||||
failDecodeRes = toJSON(httputil.ErrorRes{Err: errors.ErrMalformedEntity.Error()})
|
||||
passRegex = regexp.MustCompile("^.{8,}$")
|
||||
user = users.User{Email: validEmail, Password: validPass}
|
||||
notFoundRes = toJSON(apiutil.ErrorRes{Err: errors.ErrNotFound.Error()})
|
||||
unauthRes = toJSON(apiutil.ErrorRes{Err: errors.ErrAuthentication.Error()})
|
||||
malformedRes = toJSON(apiutil.ErrorRes{Err: errors.ErrMalformedEntity.Error()})
|
||||
weakPassword = toJSON(apiutil.ErrorRes{Err: users.ErrPasswordFormat.Error()})
|
||||
unsupportedRes = toJSON(apiutil.ErrorRes{Err: errors.ErrUnsupportedContentType.Error()})
|
||||
missingTokRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrBearerToken.Error()})
|
||||
missingEmailRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrMissingEmail.Error()})
|
||||
missingPassRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrMissingPass.Error()})
|
||||
invalidRestPassRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrInvalidResetPass.Error()})
|
||||
failDecodeRes = toJSON(apiutil.ErrorRes{Err: errors.ErrMalformedEntity.Error()})
|
||||
passRegex = regexp.MustCompile("^.{8,}$")
|
||||
)
|
||||
|
||||
type testRequest struct {
|
||||
@@ -64,7 +69,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
return nil, err
|
||||
}
|
||||
if tr.token != "" {
|
||||
req.Header.Set("Authorization", httputil.BearerPrefix+tr.token)
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.contentType != "" {
|
||||
req.Header.Set("Content-Type", tr.contentType)
|
||||
@@ -89,7 +94,8 @@ func newService() users.Service {
|
||||
}
|
||||
|
||||
func newServer(svc users.Service) *httptest.Server {
|
||||
mux := api.MakeHandler(svc, mocktracer.New())
|
||||
logger := logger.NewMock()
|
||||
mux := api.MakeHandler(svc, mocktracer.New(), logger)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -109,6 +115,8 @@ func TestRegister(t *testing.T) {
|
||||
invalidData := toJSON(users.User{Email: invalidEmail, Password: validPass})
|
||||
invalidPasswordData := toJSON(users.User{Email: validEmail, Password: invalidPass})
|
||||
invalidFieldData := fmt.Sprintf(`{"email": "%s", "pass": "%s"}`, user.Email, user.Password)
|
||||
emptyEmailData := `{"email": ""}`
|
||||
emptyHostData := fmt.Sprintf(`{"email": "%s"}`, user.Email)
|
||||
|
||||
mockAuthzDB := map[string][]mocks.SubjectSet{}
|
||||
mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey})
|
||||
@@ -131,7 +139,8 @@ func TestRegister(t *testing.T) {
|
||||
{"register new user with unauthenticated access", userNew, contentType, http.StatusUnauthorized, "wrong"},
|
||||
{"register existing user with unauthenticated access", data, contentType, http.StatusUnauthorized, "wrong"},
|
||||
{"register user with invalid request format", "{", contentType, http.StatusBadRequest, token},
|
||||
{"register user with empty JSON request", "{}", contentType, http.StatusBadRequest, token},
|
||||
{"register user with empty email request", emptyEmailData, contentType, http.StatusBadRequest, token},
|
||||
{"register user with empty host request", emptyHostData, contentType, http.StatusBadRequest, token},
|
||||
{"register user with empty request", "", contentType, http.StatusBadRequest, token},
|
||||
{"register user with invalid field name", invalidFieldData, contentType, http.StatusBadRequest, token},
|
||||
{"register user with missing content type", data, "", http.StatusUnsupportedMediaType, token},
|
||||
@@ -299,7 +308,7 @@ func TestPasswordResetRequest(t *testing.T) {
|
||||
{"password reset request with valid email", data, contentType, http.StatusCreated, expectedExisting},
|
||||
{"password reset request with invalid email", nonexistentData, contentType, http.StatusNotFound, notFoundRes},
|
||||
{"password reset request with invalid request format", "{", contentType, http.StatusBadRequest, malformedRes},
|
||||
{"password reset request with empty JSON request", "{}", contentType, http.StatusBadRequest, malformedRes},
|
||||
{"password reset request with empty email request", "{}", contentType, http.StatusBadRequest, missingEmailRes},
|
||||
{"password reset request with empty request", "", contentType, http.StatusBadRequest, malformedRes},
|
||||
{"password reset request with missing content type", data, "", http.StatusUnsupportedMediaType, unsupportedRes},
|
||||
}
|
||||
@@ -374,9 +383,9 @@ func TestPasswordReset(t *testing.T) {
|
||||
}{
|
||||
{"password reset with valid token", reqExisting, contentType, http.StatusCreated, "{}", token},
|
||||
{"password reset with invalid token", reqNoExist, contentType, http.StatusUnauthorized, unauthRes, token},
|
||||
{"password reset with confirm password not matching", reqPassNoMatch, contentType, http.StatusBadRequest, malformedRes, token},
|
||||
{"password reset with confirm password not matching", reqPassNoMatch, contentType, http.StatusBadRequest, invalidRestPassRes, token},
|
||||
{"password reset request with invalid request format", "{", contentType, http.StatusBadRequest, malformedRes, token},
|
||||
{"password reset request with empty JSON request", "{}", contentType, http.StatusBadRequest, malformedRes, token},
|
||||
{"password reset request with empty JSON request", "{}", contentType, http.StatusBadRequest, missingPassRes, token},
|
||||
{"password reset request with empty request", "", contentType, http.StatusBadRequest, malformedRes, token},
|
||||
{"password reset request with missing content type", reqExisting, "", http.StatusUnsupportedMediaType, unsupportedRes, token},
|
||||
{"password reset with weak password", reqPassWeak, contentType, http.StatusBadRequest, weakPassword, token},
|
||||
@@ -447,10 +456,10 @@ func TestPasswordChange(t *testing.T) {
|
||||
tok string
|
||||
}{
|
||||
{"password change with valid token", dataResExisting, contentType, http.StatusCreated, "{}", token},
|
||||
{"password change with invalid token", reqNoExist, contentType, http.StatusUnauthorized, unauthRes, ""},
|
||||
{"password change with empty token", reqNoExist, contentType, http.StatusUnauthorized, missingTokRes, ""},
|
||||
{"password change with invalid old password", reqWrongPass, contentType, http.StatusUnauthorized, unauthRes, token},
|
||||
{"password change with invalid new password", reqWeakPass, contentType, http.StatusBadRequest, weakPassword, token},
|
||||
{"password change with empty JSON request", "{}", contentType, http.StatusBadRequest, malformedRes, token},
|
||||
{"password change with empty JSON request", "{}", contentType, http.StatusBadRequest, missingPassRes, token},
|
||||
{"password change empty request", "", contentType, http.StatusBadRequest, malformedRes, token},
|
||||
{"password change missing content type", dataResExisting, "", http.StatusUnsupportedMediaType, unsupportedRes, token},
|
||||
}
|
||||
|
||||
+28
-16
@@ -4,7 +4,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/users"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ type viewUserReq struct {
|
||||
|
||||
func (req viewUserReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -47,7 +47,7 @@ type listUsersReq struct {
|
||||
|
||||
func (req listUsersReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -59,7 +59,7 @@ type updateUserReq struct {
|
||||
|
||||
func (req updateUserReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -70,9 +70,14 @@ type passwResetReq struct {
|
||||
}
|
||||
|
||||
func (req passwResetReq) validate() error {
|
||||
if req.Email == "" || req.Host == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.Email == "" {
|
||||
return apiutil.ErrMissingEmail
|
||||
}
|
||||
|
||||
if req.Host == "" {
|
||||
return apiutil.ErrMissingHost
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -83,30 +88,37 @@ type resetTokenReq struct {
|
||||
}
|
||||
|
||||
func (req resetTokenReq) validate() error {
|
||||
if req.Password == "" || req.ConfPass == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
if req.Password == "" {
|
||||
return apiutil.ErrMissingPass
|
||||
}
|
||||
|
||||
if req.ConfPass == "" {
|
||||
return apiutil.ErrMissingConfPass
|
||||
}
|
||||
|
||||
if req.Token == "" {
|
||||
return users.ErrMissingResetToken
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.Password != req.ConfPass {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrInvalidResetPass
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type passwChangeReq struct {
|
||||
Token string `json:"token"`
|
||||
token string
|
||||
Password string `json:"password"`
|
||||
OldPassword string `json:"old_password"`
|
||||
}
|
||||
|
||||
func (req passwChangeReq) validate() error {
|
||||
if req.Token == "" {
|
||||
return errors.ErrAuthentication
|
||||
if req.token == "" {
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.OldPassword == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingPass
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -121,11 +133,11 @@ type listMemberGroupReq struct {
|
||||
|
||||
func (req listMemberGroupReq) validate() error {
|
||||
if req.token == "" {
|
||||
return errors.ErrAuthentication
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
|
||||
if req.groupID == "" {
|
||||
return errors.ErrMalformedEntity
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+30
-55
@@ -13,7 +13,8 @@ import (
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/go-zoo/bone"
|
||||
"github.com/mainflux/mainflux"
|
||||
"github.com/mainflux/mainflux/internal/httputil"
|
||||
"github.com/mainflux/mainflux/internal/apiutil"
|
||||
"github.com/mainflux/mainflux/logger"
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
"github.com/mainflux/mainflux/pkg/uuid"
|
||||
"github.com/mainflux/mainflux/users"
|
||||
@@ -32,9 +33,9 @@ const (
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc users.Service, tracer opentracing.Tracer) http.Handler {
|
||||
func MakeHandler(svc users.Service, tracer opentracing.Tracer, logger logger.Logger) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, encodeError)),
|
||||
}
|
||||
|
||||
mux := bone.New()
|
||||
@@ -116,55 +117,43 @@ func MakeHandler(svc users.Service, tracer opentracing.Tracer) http.Handler {
|
||||
}
|
||||
|
||||
func decodeViewUser(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := viewUserReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
userID: bone.GetValue(r, "userID"),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeViewProfile(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := viewUserReq{
|
||||
token: t,
|
||||
}
|
||||
req := viewUserReq{token: apiutil.ExtractBearerToken(r)}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListUsers(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e, err := httputil.ReadStringQuery(r, emailKey, "")
|
||||
e, err := apiutil.ReadStringQuery(r, emailKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listUsersReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
offset: o,
|
||||
limit: l,
|
||||
email: e,
|
||||
@@ -174,16 +163,11 @@ func decodeListUsers(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
func decodeUpdateUser(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
var req updateUserReq
|
||||
req := updateUserReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.token = t
|
||||
return req, nil
|
||||
}
|
||||
|
||||
@@ -205,11 +189,6 @@ func decodeCreateUserReq(_ context.Context, r *http.Request) (interface{}, error
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var user users.User
|
||||
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
@@ -217,7 +196,7 @@ func decodeCreateUserReq(_ context.Context, r *http.Request) (interface{}, error
|
||||
|
||||
req := createUserReq{
|
||||
user: user,
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
@@ -256,42 +235,32 @@ func decodePasswordChange(_ context.Context, r *http.Request) (interface{}, erro
|
||||
return nil, errors.ErrUnsupportedContentType
|
||||
}
|
||||
|
||||
var req passwChangeReq
|
||||
req := passwChangeReq{token: apiutil.ExtractBearerToken(r)}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Token = t
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
o, err := httputil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
o, err := apiutil.ReadUintQuery(r, offsetKey, defOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := httputil.ReadUintQuery(r, limitKey, defLimit)
|
||||
l, err := apiutil.ReadUintQuery(r, limitKey, defLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m, err := httputil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
m, err := apiutil.ReadMetadataQuery(r, metadataKey, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := httputil.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := listMemberGroupReq{
|
||||
token: t,
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
groupID: bone.GetValue(r, "groupId"),
|
||||
offset: o,
|
||||
limit: l,
|
||||
@@ -320,10 +289,15 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
switch {
|
||||
case errors.Contains(err, errors.ErrInvalidQueryParams),
|
||||
errors.Contains(err, errors.ErrMalformedEntity),
|
||||
errors.Contains(err, users.ErrPasswordFormat):
|
||||
errors.Contains(err, users.ErrPasswordFormat),
|
||||
err == apiutil.ErrMissingEmail,
|
||||
err == apiutil.ErrMissingHost,
|
||||
err == apiutil.ErrMissingPass,
|
||||
err == apiutil.ErrMissingConfPass,
|
||||
err == apiutil.ErrInvalidResetPass:
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, errors.ErrAuthentication),
|
||||
errors.Contains(err, users.ErrRecoveryToken):
|
||||
err == apiutil.ErrBearerToken:
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
case errors.Contains(err, errors.ErrAuthorization):
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
@@ -335,7 +309,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
case errors.Contains(err, errors.ErrNotFound):
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
|
||||
case errors.Contains(err, uuid.ErrGeneratingID):
|
||||
case errors.Contains(err, uuid.ErrGeneratingID),
|
||||
errors.Contains(err, users.ErrRecoveryToken):
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
case errors.Contains(err, errors.ErrCreateEntity),
|
||||
@@ -350,7 +325,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
|
||||
if errorVal, ok := err.(errors.Error); ok {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if err := json.NewEncoder(w).Encode(httputil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(apiutil.ErrorRes{Err: errorVal.Msg()}); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user