From e129d143ff23d55eeb61a4a71de2b933da9ecef2 Mon Sep 17 00:00:00 2001 From: Saranya Jena Date: Mon, 7 Mar 2022 10:16:27 +0530 Subject: [PATCH] Fixed Authentication API issues (#3467) * Added authentication API fixes in backend Signed-off-by: Saranya-jena * Added generalized error messages Signed-off-by: Saranya-jena * Minor condition refactor Signed-off-by: Saranya-jena --- .../api/handlers/rest/project_handler.go | 34 +++++++++++++------ .../api/handlers/rest/user_handlers.go | 4 +++ .../authentication/pkg/entities/user.go | 2 +- .../authentication/pkg/project/repository.go | 9 +++-- .../pkg/services/transaction_service.go | 4 +-- .../authentication/pkg/utils/errors.go | 6 ++++ .../authentication/pkg/validations/roles.go | 1 + 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/litmus-portal/authentication/api/handlers/rest/project_handler.go b/litmus-portal/authentication/api/handlers/rest/project_handler.go index 2e8e812b4a2..e7844688d41 100644 --- a/litmus-portal/authentication/api/handlers/rest/project_handler.go +++ b/litmus-portal/authentication/api/handlers/rest/project_handler.go @@ -7,6 +7,7 @@ import ( "litmus/litmus-portal/authentication/pkg/services" "litmus/litmus-portal/authentication/pkg/utils" "litmus/litmus-portal/authentication/pkg/validations" + "net/http" "strconv" "time" @@ -49,6 +50,16 @@ func GetUserWithProject(service services.ApplicationService) gin.HandlerFunc { func GetProject(service services.ApplicationService) gin.HandlerFunc { return func(c *gin.Context) { projectID := c.Param("project_id") + + err := validations.RbacValidator(c.MustGet("uid").(string), projectID, + validations.MutationRbacRules["getProject"], string(entities.AcceptedInvitation), service) + if err != nil { + log.Warn(err) + c.JSON(utils.ErrorStatusCodes[utils.ErrUnauthorized], + presenter.CreateErrorResponse(utils.ErrUnauthorized)) + return + } + project, err := service.GetProjectByProjectID(projectID) if err != nil { log.Error(err) @@ -220,9 +231,9 @@ func CreateProject(service services.ApplicationService) gin.HandlerFunc { c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest)) return } - + // checking if project name is empty if userRequest.ProjectName == "" { - c.JSON(400, gin.H{"message": "project name can't be empty"}) + c.JSON(utils.ErrorStatusCodes[utils.ErrEmptyProjectName], presenter.CreateErrorResponse(utils.ErrEmptyProjectName)) return } @@ -323,13 +334,9 @@ func SendInvitation(service services.ApplicationService) gin.HandlerFunc { presenter.CreateErrorResponse(utils.ErrUnauthorized)) return } - if member.Role == nil { - c.JSON(400, gin.H{"message": "Enter a vaild role"}) - return - } - - if *member.Role != entities.RoleEditor && *member.Role != entities.RoleViewer { - c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest)) + // Validating member role + if member.Role == nil || (*member.Role != entities.RoleEditor && *member.Role != entities.RoleViewer) { + c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRole], presenter.CreateErrorResponse(utils.ErrInvalidRole)) return } @@ -355,7 +362,7 @@ func SendInvitation(service services.ApplicationService) gin.HandlerFunc { } if invitation == entities.AcceptedInvitation { - c.JSON(400, gin.H{"message": "user is already a member of this project"}) + c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], gin.H{"message": "user is already a member of this project"}) return } else if invitation == entities.PendingInvitation || invitation == entities.DeclinedInvitation || invitation == entities.ExitedProject { err = service.UpdateInvite(member.ProjectID, member.UserID, entities.PendingInvitation, member.Role) @@ -364,7 +371,7 @@ func SendInvitation(service services.ApplicationService) gin.HandlerFunc { c.JSON(utils.ErrorStatusCodes[utils.ErrServerError], presenter.CreateErrorResponse(utils.ErrServerError)) return } - c.JSON(200, gin.H{"message": "Invitation sent successfully"}) + c.JSON(http.StatusOK, gin.H{"message": "Invitation sent successfully"}) return } @@ -510,6 +517,11 @@ func RemoveInvitation(service services.ApplicationService) gin.HandlerFunc { c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest)) return } + if member.UserID == "" { + c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest)) + return + } + err = validations.RbacValidator(c.MustGet("uid").(string), member.ProjectID, validations.MutationRbacRules["removeInvitation"], string(entities.AcceptedInvitation), diff --git a/litmus-portal/authentication/api/handlers/rest/user_handlers.go b/litmus-portal/authentication/api/handlers/rest/user_handlers.go index 8e2d341a89e..a3adfcdd2d3 100644 --- a/litmus-portal/authentication/api/handlers/rest/user_handlers.go +++ b/litmus-portal/authentication/api/handlers/rest/user_handlers.go @@ -280,6 +280,10 @@ func UpdateUserState(service services.ApplicationService) gin.HandlerFunc { c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest)) return } + if userRequest.IsDeactivate == nil { + c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest)) + return + } var adminUser entities.User adminUser.UserName = c.MustGet("username").(string) diff --git a/litmus-portal/authentication/pkg/entities/user.go b/litmus-portal/authentication/pkg/entities/user.go index 8b31243845a..4b5b4b5d6a2 100644 --- a/litmus-portal/authentication/pkg/entities/user.go +++ b/litmus-portal/authentication/pkg/entities/user.go @@ -50,7 +50,7 @@ type UserPassword struct { // UpdateUserState defines structure to deactivate or reactivate user type UpdateUserState struct { Username string `json:"username"` - IsDeactivate bool `json:"is_deactivate"` + IsDeactivate *bool `json:"is_deactivate"` } // APIStatus defines structure for APIroute status diff --git a/litmus-portal/authentication/pkg/project/repository.go b/litmus-portal/authentication/pkg/project/repository.go index 92b6ce63c67..885c561343f 100644 --- a/litmus-portal/authentication/pkg/project/repository.go +++ b/litmus-portal/authentication/pkg/project/repository.go @@ -81,8 +81,13 @@ func (r repository) GetProjectsByUserID(userID string, isOwner bool) ([]*entitie {"members", bson.D{ {"$elemMatch", bson.D{ {"user_id", userID}, - {"invitation", bson.D{ - {"$ne", entities.DeclinedInvitation}, + {"$and", bson.A{ + bson.D{{"invitation", bson.D{ + {"$ne", entities.DeclinedInvitation}, + }}}, + bson.D{{"invitation", bson.D{ + {"$ne", entities.ExitedProject}, + }}}, }}, }}, }}} diff --git a/litmus-portal/authentication/pkg/services/transaction_service.go b/litmus-portal/authentication/pkg/services/transaction_service.go index 4823a29b6df..b7891d96b02 100644 --- a/litmus-portal/authentication/pkg/services/transaction_service.go +++ b/litmus-portal/authentication/pkg/services/transaction_service.go @@ -38,7 +38,7 @@ func (a applicationService) UpdateStateTransaction(userRequest entities.UpdateUs var deactivateTime string - if userRequest.IsDeactivate { + if *userRequest.IsDeactivate { deactivateTime = strconv.FormatInt(time.Now().Unix(), 10) // Checking if user is already deactivated @@ -48,7 +48,7 @@ func (a applicationService) UpdateStateTransaction(userRequest entities.UpdateUs } // Updating details in user collection - err = a.UpdateUserState(userRequest.Username, userRequest.IsDeactivate, deactivateTime) + err = a.UpdateUserState(userRequest.Username, *userRequest.IsDeactivate, deactivateTime) if err != nil { log.Info(err) return utils.ErrServerError diff --git a/litmus-portal/authentication/pkg/utils/errors.go b/litmus-portal/authentication/pkg/utils/errors.go index c35948ce116..f415b2e88df 100644 --- a/litmus-portal/authentication/pkg/utils/errors.go +++ b/litmus-portal/authentication/pkg/utils/errors.go @@ -18,6 +18,8 @@ var ( ErrUpdatingAdmin AppError = errors.New("cannot remove admin") ErrUserDeactivated AppError = errors.New("your account has been deactivated") ErrUserAlreadyDeactivated AppError = errors.New("user already deactivated") + ErrEmptyProjectName AppError = errors.New("invalid project name") + ErrInvalidRole AppError = errors.New("invalid role") ) // ErrorStatusCodes holds the http status codes for every AppError @@ -33,6 +35,8 @@ var ErrorStatusCodes = map[AppError]int{ ErrUpdatingAdmin: 400, ErrUserDeactivated: 400, ErrUserAlreadyDeactivated: 400, + ErrEmptyProjectName: 400, + ErrInvalidRole: 400, } // ErrorDescriptions holds detailed error description for every AppError @@ -43,4 +47,6 @@ var ErrorDescriptions = map[AppError]string{ ErrUnauthorized: "The user does not have requested authorization to access this resource", ErrUserExists: "This username is already assigned to another user", ErrStrictPasswordPolicyViolation: "Please ensure the password is 8 characters long and has 1 digit, 1 lowercase alphabet, 1 uppercase alphabet and 1 special character", + ErrEmptyProjectName: "Project name can't be empty", + ErrInvalidRole: "Role is invalid", } diff --git a/litmus-portal/authentication/pkg/validations/roles.go b/litmus-portal/authentication/pkg/validations/roles.go index a31d29c6414..c42fe1a3eb1 100644 --- a/litmus-portal/authentication/pkg/validations/roles.go +++ b/litmus-portal/authentication/pkg/validations/roles.go @@ -10,4 +10,5 @@ var MutationRbacRules = map[string][]string{ "removeInvitation": {string(entities.RoleOwner)}, "leaveProject": {string(entities.RoleViewer), string(entities.RoleEditor)}, "updateProjectName": {string(entities.RoleOwner)}, + "getProject": {string(entities.RoleOwner), string(entities.RoleViewer), string(entities.RoleEditor)}, }