diff --git a/cmd/users/main.go b/cmd/users/main.go index ae84549b94..d96e648c71 100644 --- a/cmd/users/main.go +++ b/cmd/users/main.go @@ -186,7 +186,7 @@ func main() { oauthProvider := googleoauth.NewProvider(oauthConfig, cfg.OAuthUIRedirectURL, cfg.OAuthUIErrorURL) mux := chi.NewRouter() - httpSrv := httpserver.New(ctx, cancel, svcName, httpServerConfig, capi.MakeHandler(csvc, gsvc, mux, logger, cfg.InstanceID, oauthProvider), logger) + httpSrv := httpserver.New(ctx, cancel, svcName, httpServerConfig, capi.MakeHandler(csvc, gsvc, mux, logger, cfg.InstanceID, cfg.PassRegex, oauthProvider), logger) if cfg.SendTelemetry { chc := chclient.New(svcName, magistrala.Version, logger, cancel) @@ -219,7 +219,7 @@ func newService(ctx context.Context, authClient magistrala.AuthServiceClient, db logger.Error(fmt.Sprintf("failed to configure e-mailing util: %s", err.Error())) } - csvc := users.NewService(cRepo, authClient, emailerClient, hsr, idp, c.PassRegex, c.SelfRegister) + csvc := users.NewService(cRepo, authClient, emailerClient, hsr, idp, c.SelfRegister) gsvc := mggroups.NewService(gRepo, idp, authClient) csvc, err = uevents.NewEventStoreMiddleware(ctx, csvc, c.ESURL) diff --git a/internal/api/common.go b/internal/api/common.go index 886b934657..998402ad1c 100644 --- a/internal/api/common.go +++ b/internal/api/common.go @@ -106,8 +106,7 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) { w.Header().Set("Content-Type", ContentType) switch { - case errors.Contains(err, apiutil.ErrInvalidSecret), - errors.Contains(err, svcerr.ErrMalformedEntity), + case errors.Contains(err, svcerr.ErrMalformedEntity), errors.Contains(err, errors.ErrMalformedEntity), errors.Contains(err, apiutil.ErrMissingID), errors.Contains(err, apiutil.ErrEmptyList), @@ -121,7 +120,12 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) { errors.Contains(err, apiutil.ErrInvalidQueryParams), errors.Contains(err, apiutil.ErrInvalidStatus), errors.Contains(err, apiutil.ErrMissingRelation), - errors.Contains(err, apiutil.ErrValidation): + errors.Contains(err, apiutil.ErrValidation), + errors.Contains(err, apiutil.ErrMissingIdentity), + errors.Contains(err, apiutil.ErrMissingSecret), + errors.Contains(err, apiutil.ErrMissingPass), + errors.Contains(err, apiutil.ErrMissingConfPass), + errors.Contains(err, apiutil.ErrPasswordFormat): w.WriteHeader(http.StatusBadRequest) case errors.Contains(err, svcerr.ErrAuthentication), errors.Contains(err, apiutil.ErrBearerToken): diff --git a/internal/api/common_test.go b/internal/api/common_test.go index c243aac1b5..ac1adf40c4 100644 --- a/internal/api/common_test.go +++ b/internal/api/common_test.go @@ -225,7 +225,7 @@ func TestEncodeError(t *testing.T) { { desc: "BadRequest", errs: []error{ - apiutil.ErrInvalidSecret, + apiutil.ErrMissingSecret, svcerr.ErrMalformedEntity, errors.ErrMalformedEntity, apiutil.ErrMissingID, @@ -240,7 +240,7 @@ func TestEncodeError(t *testing.T) { { desc: "BadRequest with validation error", errs: []error{ - errors.Wrap(apiutil.ErrValidation, apiutil.ErrInvalidSecret), + errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingSecret), errors.Wrap(apiutil.ErrValidation, svcerr.ErrMalformedEntity), errors.Wrap(apiutil.ErrValidation, errors.ErrMalformedEntity), errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), diff --git a/internal/apiutil/errors.go b/internal/apiutil/errors.go index 11b880106d..2f2261fa03 100644 --- a/internal/apiutil/errors.go +++ b/internal/apiutil/errors.go @@ -132,6 +132,9 @@ var ( // ErrMissingSecret indicates missing secret. ErrMissingSecret = errors.New("missing secret") + // ErrPasswordFormat indicates weak password. + ErrPasswordFormat = errors.New("password does not meet the requirements") + // ErrMissingOwner indicates missing entity owner. ErrMissingOwner = errors.New("missing entity owner") @@ -144,9 +147,6 @@ var ( // ErrMissingName indicates missing identity name. ErrMissingName = errors.New("missing identity name") - // ErrInvalidSecret indicates invalid secret. - ErrInvalidSecret = errors.New("missing secret") - // ErrInvalidLevel indicates an invalid group level. ErrInvalidLevel = errors.New("invalid group level (should be between 0 and 5)") diff --git a/pkg/sdk/go/groups_test.go b/pkg/sdk/go/groups_test.go index 9ac23c7620..5b82db9a92 100644 --- a/pkg/sdk/go/groups_test.go +++ b/pkg/sdk/go/groups_test.go @@ -37,14 +37,14 @@ func setupGroups() (*httptest.Server, *mocks.Repository, *authmocks.AuthClient) grepo := new(mocks.Repository) auth := new(authmocks.AuthClient) - csvc := users.NewService(crepo, auth, emailer, phasher, idProvider, passRegex, true) + csvc := users.NewService(crepo, auth, emailer, phasher, idProvider, true) gsvc := groups.NewService(grepo, idProvider, auth) logger := mglog.NewMock() mux := chi.NewRouter() provider := new(oauth2mocks.Provider) provider.On("Name").Return("test") - api.MakeHandler(csvc, gsvc, mux, logger, "", provider) + api.MakeHandler(csvc, gsvc, mux, logger, "", passRegex, provider) return httptest.NewServer(mux), grepo, auth } diff --git a/pkg/sdk/go/things_test.go b/pkg/sdk/go/things_test.go index 40fd38d0ee..613b57084f 100644 --- a/pkg/sdk/go/things_test.go +++ b/pkg/sdk/go/things_test.go @@ -892,8 +892,8 @@ func TestUpdateThingSecret(t *testing.T) { newSecret: "newSecret", token: validToken, response: sdk.Thing{}, - repoErr: apiutil.ErrInvalidSecret, - err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, apiutil.ErrInvalidSecret), http.StatusBadRequest), + repoErr: apiutil.ErrMissingSecret, + err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrUpdateEntity, apiutil.ErrMissingSecret), http.StatusBadRequest), }, } for _, tc := range cases { diff --git a/pkg/sdk/go/tokens_test.go b/pkg/sdk/go/tokens_test.go index ebf6cfbd53..ad5f07a957 100644 --- a/pkg/sdk/go/tokens_test.go +++ b/pkg/sdk/go/tokens_test.go @@ -62,7 +62,7 @@ func TestIssueToken(t *testing.T) { desc: "issue token for an empty user", login: sdk.Login{}, token: &magistrala.Token{}, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingIdentity), http.StatusInternalServerError), + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingIdentity), http.StatusBadRequest), }, { desc: "issue token for invalid identity", diff --git a/pkg/sdk/go/users_test.go b/pkg/sdk/go/users_test.go index ca5191d160..54b0f93f87 100644 --- a/pkg/sdk/go/users_test.go +++ b/pkg/sdk/go/users_test.go @@ -43,14 +43,14 @@ func setupUsers() (*httptest.Server, *umocks.Repository, *gmocks.Repository, *au gRepo := new(gmocks.Repository) auth := new(authmocks.AuthClient) - csvc := users.NewService(crepo, auth, emailer, phasher, idProvider, passRegex, true) + csvc := users.NewService(crepo, auth, emailer, phasher, idProvider, true) gsvc := groups.NewService(gRepo, idProvider, auth) logger := mglog.NewMock() mux := chi.NewRouter() provider := new(oauth2mocks.Provider) provider.On("Name").Return("test") - api.MakeHandler(csvc, gsvc, mux, logger, "", provider) + api.MakeHandler(csvc, gsvc, mux, logger, "", passRegex, provider) return httptest.NewServer(mux), crepo, gRepo, auth } @@ -62,7 +62,7 @@ func TestCreateClient(t *testing.T) { user := sdk.User{ Name: "clientname", Tags: []string{"tag1", "tag2"}, - Credentials: sdk.Credentials{Identity: "admin@example.com", Secret: "secret"}, + Credentials: sdk.Credentials{Identity: "admin@example.com", Secret: "12345678"}, Status: mgclients.EnabledStatus.String(), } conf := sdk.Config{ @@ -96,7 +96,7 @@ func TestCreateClient(t *testing.T) { client: sdk.User{}, response: sdk.User{}, token: token, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, errors.ErrMalformedEntity), http.StatusBadRequest), + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingIdentity), http.StatusBadRequest), }, { desc: "register a user that can't be marshalled", @@ -135,7 +135,7 @@ func TestCreateClient(t *testing.T) { }, response: sdk.User{}, token: token, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, errors.ErrMalformedEntity), http.StatusBadRequest), + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingIdentity), http.StatusBadRequest), }, { desc: "register user with empty identity", @@ -147,14 +147,7 @@ func TestCreateClient(t *testing.T) { }, response: sdk.User{}, token: token, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, errors.ErrMalformedEntity), http.StatusBadRequest), - }, - { - desc: "register empty user", - client: sdk.User{}, - response: sdk.User{}, - token: token, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, errors.ErrMalformedEntity), http.StatusBadRequest), + err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingIdentity), http.StatusBadRequest), }, { desc: "register user with every field defined", @@ -828,7 +821,7 @@ func TestUpdateClientSecret(t *testing.T) { newSecret: "newSecret", token: validToken, response: sdk.User{}, - repoErr: apiutil.ErrInvalidSecret, + repoErr: apiutil.ErrMissingSecret, err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrNotFound, repoerr.ErrMissingSecret), http.StatusBadRequest), }, } diff --git a/users/api/clients.go b/users/api/clients.go index 991728d8c6..65b6527d8e 100644 --- a/users/api/clients.go +++ b/users/api/clients.go @@ -8,6 +8,7 @@ import ( "encoding/json" "log/slog" "net/http" + "regexp" "strings" "github.com/absmach/magistrala/auth" @@ -22,8 +23,12 @@ import ( "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) +var passRegex = regexp.MustCompile("^.{8,}$") + // MakeHandler returns a HTTP handler for API endpoints. -func clientsHandler(svc users.Service, r *chi.Mux, logger *slog.Logger, providers ...oauth2.Provider) http.Handler { +func clientsHandler(svc users.Service, r *chi.Mux, logger *slog.Logger, pr *regexp.Regexp, providers ...oauth2.Provider) http.Handler { + passRegex = pr + opts := []kithttp.ServerOption{ kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)), } diff --git a/users/api/endpoint_test.go b/users/api/endpoint_test.go index 3ec2ea791d..dc1dcb4a0c 100644 --- a/users/api/endpoint_test.go +++ b/users/api/endpoint_test.go @@ -9,6 +9,7 @@ import ( "io" "net/http" "net/http/httptest" + "regexp" "strings" "testing" @@ -44,11 +45,11 @@ var ( Metadata: validCMetadata, Status: mgclients.EnabledStatus, } - validToken = "valid" - inValidToken = "invalid" - inValid = "invalid" - validID = "d4ebb847-5d0e-4e46-bdd9-b6aceaaa3a22" - ErrPasswordFormat = errors.New("password does not meet the requirements") + validToken = "valid" + inValidToken = "invalid" + inValid = "invalid" + validID = "d4ebb847-5d0e-4e46-bdd9-b6aceaaa3a22" + passRegex = regexp.MustCompile("^.{8,}$") ) const contentType = "application/json" @@ -92,7 +93,7 @@ func newUsersServer() (*httptest.Server, *mocks.Service) { mux := chi.NewRouter() provider := new(oauth2mocks.Provider) provider.On("Name").Return("test") - httpapi.MakeHandler(svc, gsvc, mux, logger, "", provider) + httpapi.MakeHandler(svc, gsvc, mux, logger, "", passRegex, provider) return httptest.NewServer(mux), svc } @@ -1166,8 +1167,8 @@ func TestPasswordReset(t *testing.T) { data: fmt.Sprintf(`{"token": "%s", "password": "%s", "confirm_password": "%s"}`, validToken, "weak", "weak"), token: validToken, contentType: contentType, - status: http.StatusInternalServerError, - err: ErrPasswordFormat, + status: http.StatusBadRequest, + err: apiutil.ErrPasswordFormat, }, { desc: "password reset with empty token", @@ -1182,7 +1183,7 @@ func TestPasswordReset(t *testing.T) { data: fmt.Sprintf(`{"token": "%s", "password": "%s", "confirm_password": "%s"}`, validToken, "", ""), token: validToken, contentType: contentType, - status: http.StatusInternalServerError, + status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { @@ -1338,7 +1339,7 @@ func TestUpdateClientSecret(t *testing.T) { }{ { desc: "update user secret with valid token", - data: fmt.Sprintf(`{"secret": "%s"}`, "strongersecret"), + data: `{"old_secret": "strongersecret", "new_secret": "strongersecret"}`, client: mgclients.Client{ ID: client.ID, Credentials: mgclients.Credentials{ @@ -1353,7 +1354,7 @@ func TestUpdateClientSecret(t *testing.T) { }, { desc: "update user secret with empty token", - data: fmt.Sprintf(`{"secret": "%s"}`, "strongersecret"), + data: `{"old_secret": "strongersecret", "new_secret": "strongersecret"}`, client: mgclients.Client{ ID: client.ID, Credentials: mgclients.Credentials{ @@ -1368,7 +1369,7 @@ func TestUpdateClientSecret(t *testing.T) { }, { desc: "update user secret with invalid token", - data: fmt.Sprintf(`{"secret": "%s"}`, "strongersecret"), + data: `{"old_secret": "strongersecret", "new_secret": "strongersecret"}`, client: mgclients.Client{ ID: client.ID, Credentials: mgclients.Credentials{ @@ -1384,7 +1385,7 @@ func TestUpdateClientSecret(t *testing.T) { { desc: "update user secret with empty secret", - data: fmt.Sprintf(`{"secret": "%s"}`, ""), + data: `{"old_secret": "", "new_secret": "strongersecret"}`, client: mgclients.Client{ ID: client.ID, Credentials: mgclients.Credentials{ @@ -1395,11 +1396,11 @@ func TestUpdateClientSecret(t *testing.T) { contentType: contentType, token: validToken, status: http.StatusBadRequest, - err: apiutil.ErrBearerKey, + err: apiutil.ErrMissingPass, }, { desc: "update user secret with invalid contentype", - data: fmt.Sprintf(`{"secret": "%s"}`, ""), + data: `{"old_secret": "strongersecret", "new_secret": "strongersecret"}`, client: mgclients.Client{ ID: client.ID, Credentials: mgclients.Credentials{ @@ -1479,7 +1480,7 @@ func TestIssueToken(t *testing.T) { desc: "issue token with empty identity", data: fmt.Sprintf(`{"identity": "%s", "secret": "%s", "domainID": "%s"}`, "", secret, validID), contentType: contentType, - status: http.StatusInternalServerError, + status: http.StatusBadRequest, err: apiutil.ErrValidation, }, { diff --git a/users/api/requests.go b/users/api/requests.go index 394cca1240..471f726096 100644 --- a/users/api/requests.go +++ b/users/api/requests.go @@ -20,6 +20,15 @@ func (req createClientReq) validate() error { if len(req.client.Name) > api.MaxNameSize { return apiutil.ErrNameSize } + if req.client.Credentials.Identity == "" { + return apiutil.ErrMissingIdentity + } + if req.client.Credentials.Secret == "" { + return apiutil.ErrMissingPass + } + if !passRegex.MatchString(req.client.Credentials.Secret) { + return apiutil.ErrPasswordFormat + } return req.client.Validate() } @@ -180,6 +189,12 @@ func (req updateClientSecretReq) validate() error { if req.token == "" { return apiutil.ErrBearerToken } + if req.OldSecret == "" || req.NewSecret == "" { + return apiutil.ErrMissingPass + } + if !passRegex.MatchString(req.NewSecret) { + return apiutil.ErrPasswordFormat + } return nil } @@ -211,7 +226,7 @@ func (req loginClientReq) validate() error { return apiutil.ErrMissingIdentity } if req.Secret == "" { - return apiutil.ErrMissingSecret + return apiutil.ErrMissingPass } return nil @@ -265,6 +280,9 @@ func (req resetTokenReq) validate() error { if req.Password != req.ConfPass { return apiutil.ErrInvalidResetPass } + if !passRegex.MatchString(req.ConfPass) { + return apiutil.ErrPasswordFormat + } return nil } diff --git a/users/api/requests_test.go b/users/api/requests_test.go index 571233ae86..760e50eda1 100644 --- a/users/api/requests_test.go +++ b/users/api/requests_test.go @@ -17,6 +17,7 @@ import ( const ( valid = "valid" invalid = "invalid" + secret = "QJg58*aMan7j" ) var validID = testsutil.GenerateUUID(&testing.T{}) @@ -36,7 +37,7 @@ func TestCreateClientReqValidate(t *testing.T) { Name: valid, Credentials: mgclients.Credentials{ Identity: "example@example.com", - Secret: valid, + Secret: secret, }, }, }, @@ -51,7 +52,7 @@ func TestCreateClientReqValidate(t *testing.T) { Name: valid, Credentials: mgclients.Credentials{ Identity: "example@example.com", - Secret: valid, + Secret: secret, }, }, }, @@ -67,6 +68,49 @@ func TestCreateClientReqValidate(t *testing.T) { }, err: apiutil.ErrNameSize, }, + { + desc: "missing identity in request", + req: createClientReq{ + token: valid, + client: mgclients.Client{ + ID: validID, + Name: valid, + Credentials: mgclients.Credentials{ + Secret: valid, + }, + }, + }, + err: apiutil.ErrMissingIdentity, + }, + { + desc: "missing secret in request", + req: createClientReq{ + token: valid, + client: mgclients.Client{ + ID: validID, + Name: valid, + Credentials: mgclients.Credentials{ + Identity: "example@example.com", + }, + }, + }, + err: apiutil.ErrMissingPass, + }, + { + desc: "invalid secret in request", + req: createClientReq{ + token: valid, + client: mgclients.Client{ + ID: validID, + Name: valid, + Credentials: mgclients.Credentials{ + Identity: "example@example.com", + Secret: "invalid", + }, + }, + }, + err: apiutil.ErrPasswordFormat, + }, } for _, tc := range cases { err := tc.req.validate() @@ -411,8 +455,8 @@ func TestUpdateClientSecretReqValidate(t *testing.T) { desc: "valid request", req: updateClientSecretReq{ token: valid, - OldSecret: valid, - NewSecret: valid, + OldSecret: secret, + NewSecret: secret, }, err: nil, }, @@ -420,11 +464,38 @@ func TestUpdateClientSecretReqValidate(t *testing.T) { desc: "empty token", req: updateClientSecretReq{ token: "", - OldSecret: valid, - NewSecret: valid, + OldSecret: secret, + NewSecret: secret, }, err: apiutil.ErrBearerToken, }, + { + desc: "missing old secret", + req: updateClientSecretReq{ + token: valid, + OldSecret: "", + NewSecret: secret, + }, + err: apiutil.ErrMissingPass, + }, + { + desc: "missing new secret", + req: updateClientSecretReq{ + token: valid, + OldSecret: secret, + NewSecret: "", + }, + err: apiutil.ErrMissingPass, + }, + { + desc: "invalid new secret", + req: updateClientSecretReq{ + token: valid, + OldSecret: secret, + NewSecret: "invalid", + }, + err: apiutil.ErrPasswordFormat, + }, } for _, c := range cases { err := c.req.validate() @@ -479,7 +550,7 @@ func TestLoginClientReqValidate(t *testing.T) { desc: "valid request", req: loginClientReq{ Identity: "eaxmple,example.com", - Secret: valid, + Secret: secret, }, err: nil, }, @@ -487,7 +558,7 @@ func TestLoginClientReqValidate(t *testing.T) { desc: "empty identity", req: loginClientReq{ Identity: "", - Secret: valid, + Secret: secret, }, err: apiutil.ErrMissingIdentity, }, @@ -497,7 +568,7 @@ func TestLoginClientReqValidate(t *testing.T) { Identity: "eaxmple,example.com", Secret: "", }, - err: apiutil.ErrMissingSecret, + err: apiutil.ErrMissingPass, }, } for _, c := range cases { @@ -580,8 +651,8 @@ func TestResetTokenReqValidate(t *testing.T) { desc: "valid request", req: resetTokenReq{ Token: valid, - Password: valid, - ConfPass: valid, + Password: secret, + ConfPass: secret, }, err: nil, }, @@ -589,8 +660,8 @@ func TestResetTokenReqValidate(t *testing.T) { desc: "empty token", req: resetTokenReq{ Token: "", - Password: valid, - ConfPass: valid, + Password: secret, + ConfPass: secret, }, err: apiutil.ErrBearerToken, }, @@ -599,7 +670,7 @@ func TestResetTokenReqValidate(t *testing.T) { req: resetTokenReq{ Token: valid, Password: "", - ConfPass: valid, + ConfPass: secret, }, err: apiutil.ErrMissingPass, }, @@ -607,7 +678,7 @@ func TestResetTokenReqValidate(t *testing.T) { desc: "empty confpass", req: resetTokenReq{ Token: valid, - Password: valid, + Password: secret, ConfPass: "", }, err: apiutil.ErrMissingConfPass, @@ -616,8 +687,8 @@ func TestResetTokenReqValidate(t *testing.T) { desc: "mismatching password and confpass", req: resetTokenReq{ Token: valid, - Password: "valid2", - ConfPass: valid, + Password: "secret", + ConfPass: secret, }, err: apiutil.ErrInvalidResetPass, }, diff --git a/users/api/transport.go b/users/api/transport.go index 354d7b5d5f..e3defd315f 100644 --- a/users/api/transport.go +++ b/users/api/transport.go @@ -6,6 +6,7 @@ package api import ( "log/slog" "net/http" + "regexp" "github.com/absmach/magistrala" "github.com/absmach/magistrala/pkg/groups" @@ -16,8 +17,8 @@ import ( ) // MakeHandler returns a HTTP handler for Users and Groups API endpoints. -func MakeHandler(cls users.Service, grps groups.Service, mux *chi.Mux, logger *slog.Logger, instanceID string, providers ...oauth2.Provider) http.Handler { - clientsHandler(cls, mux, logger, providers...) +func MakeHandler(cls users.Service, grps groups.Service, mux *chi.Mux, logger *slog.Logger, instanceID string, pr *regexp.Regexp, providers ...oauth2.Provider) http.Handler { + clientsHandler(cls, mux, logger, pr, providers...) groupsHandler(grps, mux, logger) mux.Get("/health", magistrala.Health("users", instanceID)) diff --git a/users/service.go b/users/service.go index 5d7fd1998b..ca30d7f2a4 100644 --- a/users/service.go +++ b/users/service.go @@ -6,7 +6,6 @@ package users import ( "context" "fmt" - "regexp" "time" "github.com/absmach/magistrala" @@ -25,9 +24,6 @@ var ( // ErrRecoveryToken indicates error in generating password recovery token. ErrRecoveryToken = errors.New("failed to generate password recovery token") - // ErrPasswordFormat indicates weak password. - ErrPasswordFormat = errors.New("password does not meet the requirements") - // ErrFailedPolicyUpdate indicates a failure to update user policy. ErrFailedPolicyUpdate = errors.New("failed to update user policy") @@ -50,19 +46,17 @@ type service struct { auth magistrala.AuthServiceClient hasher Hasher email Emailer - passRegex *regexp.Regexp selfRegister bool } // NewService returns a new Users service implementation. -func NewService(crepo postgres.Repository, authClient magistrala.AuthServiceClient, emailer Emailer, hasher Hasher, idp magistrala.IDProvider, pr *regexp.Regexp, selfRegister bool) Service { +func NewService(crepo postgres.Repository, authClient magistrala.AuthServiceClient, emailer Emailer, hasher Hasher, idp magistrala.IDProvider, selfRegister bool) Service { return service{ clients: crepo, auth: authClient, hasher: hasher, email: emailer, idProvider: idp, - passRegex: pr, selfRegister: selfRegister, } } @@ -92,10 +86,10 @@ func (svc service) RegisterClient(ctx context.Context, token string, cli mgclien } if cli.Status != mgclients.DisabledStatus && cli.Status != mgclients.EnabledStatus { - return mgclients.Client{}, svcerr.ErrInvalidStatus + return mgclients.Client{}, errors.Wrap(svcerr.ErrMalformedEntity, svcerr.ErrInvalidStatus) } if cli.Role != mgclients.UserRole && cli.Role != mgclients.AdminRole { - return mgclients.Client{}, svcerr.ErrInvalidRole + return mgclients.Client{}, errors.Wrap(svcerr.ErrMalformedEntity, svcerr.ErrInvalidRole) } cli.ID = clientID cli.CreatedAt = time.Now() @@ -313,9 +307,6 @@ func (svc service) ResetSecret(ctx context.Context, resetToken, secret string) e if c.Credentials.Identity == "" { return repoerr.ErrNotFound } - if !svc.passRegex.MatchString(secret) { - return ErrPasswordFormat - } secret, err = svc.hasher.Hash(secret) if err != nil { return err @@ -339,9 +330,6 @@ func (svc service) UpdateClientSecret(ctx context.Context, token, oldSecret, new if err != nil { return mgclients.Client{}, err } - if !svc.passRegex.MatchString(newSecret) { - return mgclients.Client{}, ErrPasswordFormat - } dbClient, err := svc.clients.RetrieveByID(ctx, id) if err != nil { return mgclients.Client{}, errors.Wrap(repoerr.ErrNotFound, err) diff --git a/users/service_test.go b/users/service_test.go index 94b24651b3..b60858ca7d 100644 --- a/users/service_test.go +++ b/users/service_test.go @@ -6,7 +6,6 @@ package users_test import ( "context" "fmt" - "regexp" "strings" "testing" @@ -42,7 +41,6 @@ var ( Metadata: validCMetadata, Status: mgclients.EnabledStatus, } - passRegex = regexp.MustCompile("^.{8,}$") validToken = "token" inValidToken = "invalid" validID = "d4ebb847-5d0e-4e46-bdd9-b6aceaaa3a22" @@ -56,7 +54,7 @@ func newService(selfRegister bool) (users.Service, *mocks.Repository, *authmocks cRepo := new(mocks.Repository) auth := new(authmocks.AuthClient) e := mocks.NewEmailer() - return users.NewService(cRepo, auth, e, phasher, idProvider, passRegex, selfRegister), cRepo, auth, e + return users.NewService(cRepo, auth, e, phasher, idProvider, selfRegister), cRepo, auth, e } func TestRegisterClient(t *testing.T) { @@ -163,19 +161,6 @@ func TestRegisterClient(t *testing.T) { deletePoliciesResponse: &magistrala.DeletePoliciesRes{Deleted: true}, err: nil, }, - { - desc: "register a new client with a weak secret", - client: mgclients.Client{ - Name: "clientWithWeakSecret", - Credentials: mgclients.Credentials{ - Identity: "clientwithweaksecret@example.com", - Secret: "weak", - }, - }, - addPoliciesResponse: &magistrala.AddPoliciesRes{Added: true}, - deletePoliciesResponse: &magistrala.DeletePoliciesRes{Deleted: true}, - err: nil, - }, { desc: " register a client with a secret that is too long", client: mgclients.Client{ @@ -1179,14 +1164,6 @@ func TestUpdateClientSecret(t *testing.T) { identifyErr: svcerr.ErrAuthentication, err: svcerr.ErrAuthentication, }, - { - desc: "update client secret with weak secret", - oldSecret: client.Credentials.Secret, - newSecret: "weak", - token: validToken, - identifyResponse: &magistrala.IdentityRes{UserId: client.ID}, - err: users.ErrPasswordFormat, - }, { desc: "update client secret with failed to retrieve client by ID", oldSecret: client.Credentials.Secret, @@ -2363,14 +2340,6 @@ func TestResetSecret(t *testing.T) { }, err: repoerr.ErrNotFound, }, - { - desc: "reset secret with invalid secret format", - token: validToken, - newSecret: "weak", - identifyResponse: &magistrala.IdentityRes{UserId: client.ID}, - retrieveByIDResponse: client, - err: users.ErrPasswordFormat, - }, { desc: "reset secret with failed to update secret", token: validToken,