INFRA-2971 : Add member api segregated (#385)

* INFRA-2971 : Add member api segregated

* INFRA-2971 : pr review changes

* INFRA-2971 : Message updated
This commit is contained in:
Vijay Joshi
2024-03-05 13:03:56 +05:30
committed by GitHub
parent eda6e689e3
commit 8ad6a842f8
11 changed files with 212 additions and 7 deletions

View File

@@ -12,6 +12,7 @@ import (
common "houston/service/response/common"
"houston/service/teamService"
"net/http"
"regexp"
"strconv"
)
@@ -158,6 +159,22 @@ func (handler *TeamHandler) HandleMakeManager(c *gin.Context) {
c.JSON(http.StatusOK, common.SuccessResponse("Team manager updated successfully", http.StatusOK))
}
func (handler *TeamHandler) HandleAddMembers(c *gin.Context, request team.UpdateTeamRequest) {
err := validateAddMemberRequest(request)
if err != nil {
handler.handleErrorResponse(c, err)
return
}
err = handler.service.AddTeamMember(request, c.GetHeader(util.UserEmailHeader))
if err != nil {
handler.handleErrorResponse(c, err)
return
}
c.JSON(http.StatusOK, common.SuccessResponse("Members added successfully", http.StatusOK))
}
func validateAddTeamRequest(request team.AddTeamRequest) error {
teamName := request.Name
minLength := viper.GetInt("TEAM_NAME_MIN_LENGTH")
@@ -193,12 +210,9 @@ func validateUpdateTeamRequest(request team.UpdateTeamRequest) error {
}
if request.Members != nil {
if request.Members.SeverityId == 0 {
return customErrors.NewInvalidInputError("Severity id not provided for members to add")
}
if len(request.Members.UserEmailIds) == 0 {
return customErrors.NewInvalidInputError("No user email ids provided for members to add")
err := validateMembers(request.Members)
if err != nil {
return err
}
}
@@ -241,3 +255,46 @@ func validateGetTeamParams(c *gin.Context) (uint, error) {
return uint(teamId), nil
}
func validateAddMemberRequest(request team.UpdateTeamRequest) error {
if request.Id == 0 {
return customErrors.NewInvalidInputError("Team id not provided")
}
err := validateMembers(request.Members)
if err != nil {
return err
}
return nil
}
func validateMembers(members *team.Members) error {
if members == nil {
return customErrors.NewInvalidInputError("Members not provided")
}
if members.SeverityId == 0 {
return customErrors.NewInvalidInputError("Severity was not selected")
}
if len(members.UserEmailIds) == 0 {
return customErrors.NewInvalidInputError("No email id string entered in input field- Please enter a valid email id.")
}
if err := validateEachMemberEmail(members.UserEmailIds); err != nil {
return err
}
return nil
}
func validateEachMemberEmail(emailIds []string) error {
emailRegex := regexp.MustCompile(util.EMAIL_REGEX)
for _, email := range emailIds {
if !emailRegex.MatchString(email) {
return customErrors.NewInvalidInputError(fmt.Sprintf("Invalid email: %s", email))
}
}
return nil
}

View File

@@ -108,6 +108,7 @@ func (s *Server) teamHandler(houstonGroup *gin.RouterGroup) {
houstonGroup.POST("/teams/add", teamHandler.AddTeam)
houstonGroup.POST("/teams-v2/add", s.authService.IfAdmin(teamHandlerV2.HandleAddTeam))
houstonGroup.POST("/teams-v2", s.authService.IfMemberOrAdmin(teamHandlerV2.HandleUpdateTeam))
houstonGroup.POST("/teams/members", s.authService.IfMemberOrAdmin(teamHandlerV2.HandleAddMembers))
houstonGroup.POST("/teams", teamHandler.UpdateTeam)
houstonGroup.PATCH("/teams/:id/manager/:userId", teamHandler.MakeManager)
houstonGroup.PATCH("/teams-v2/:id/manager/:userId", s.authService.IfManagerOrAdmin(teamHandlerV2.HandleMakeManager))

View File

@@ -121,3 +121,7 @@ const RedColorCode = "#FF0000"
const (
DUPLICATE_KEY_VALUE_MESSAGE = "duplicate key value"
)
const (
EMAIL_REGEX = `^[a-zA-Z]+\.[a-zA-Z]+@navi\.com$`
)

View File

@@ -72,6 +72,20 @@ func (repo *teamUserRepositoryImpl) GetTeamUserByTeamIdAndUserEmailId(teamId uin
return &teamUser, nil
}
func (repo *teamUserRepositoryImpl) GetTeamUsersByTeamIdAndUserEmailIds(teamId uint, userEmailIds []string) ([]teamUser.TeamUserEntity, error) {
var teamUsers []teamUser.TeamUserEntity
if err := repo.gormClient.
Preload("User").
Joins("JOIN houston_user ON houston_user.id = team_user.user_id").
Where("houston_user.email IN (?) AND team_user.team_id = ?", userEmailIds, teamId).
Find(&teamUsers).
Error; err != nil {
return nil, err
}
return teamUsers, nil
}
func (repo *teamUserRepositoryImpl) GetTeamUsersWithMinimumSeverityIdLessThanOrEqualToGivenSeverity(teamId, severityId uint) ([]teamUser.TeamUserEntity, error) {
var teamUsers []teamUser.TeamUserEntity

View File

@@ -12,6 +12,7 @@ type TeamUserRepository interface {
GetTeamsByUserId(userId uint) ([]teamUser.TeamUserEntity, error)
RemoveTeamUserByTeamIdAndUserId(teamId, userId uint) error
GetTeamUserByTeamIdAndUserEmailId(teamId uint, userEmailId string) (*teamUser.TeamUserEntity, error)
GetTeamUsersByTeamIdAndUserEmailIds(teamId uint, userEmailIds []string) ([]teamUser.TeamUserEntity, error)
GetTeamUsersWithMinimumSeverityIdLessThanOrEqualToGivenSeverity(teamId, severityId uint) ([]teamUser.TeamUserEntity, error)
}

View File

@@ -423,8 +423,17 @@ func (teamService *TeamServiceV2) UpdateTeam(request teamRequest.UpdateTeamReque
return err
}
err = teamService.commitTeamDetails(teamEntity, userEmail)
if err != nil {
return err
}
return nil
}
func (teamService *TeamServiceV2) commitTeamDetails(teamEntity *team.TeamEntity, userEmail string) error {
teamEntity.UpdatedBy = userEmail
err = teamService.teamRepository.UpdateTeam(teamEntity)
err := teamService.teamRepository.UpdateTeam(teamEntity)
if err != nil {
logger.Error(fmt.Sprintf("%s could not update team with id: %d : %+v", logTag, teamEntity.ID, err))
return customErrors.NewDataAccessError(fmt.Sprintf("could not update team with id: %d", teamEntity.ID))
@@ -433,6 +442,29 @@ func (teamService *TeamServiceV2) UpdateTeam(request teamRequest.UpdateTeamReque
return nil
}
func (teamService *TeamServiceV2) AddTeamMember(request teamRequest.UpdateTeamRequest, userEmail string) error {
teamEntity, err := teamService.GetTeamById(request.Id)
if err != nil {
return err
}
_, err = teamService.doUsersWithEmailsExistInTeam(request.Id, request.Members.UserEmailIds)
if err != nil {
return err
}
if err := teamService.addMembers(teamEntity, request.Members); err != nil {
return err
}
err = teamService.commitTeamDetails(teamEntity, userEmail)
if err != nil {
return err
}
return nil
}
func (teamService *TeamServiceV2) RemoveTeamMember(teamId, userId uint, requesterEmail string) error {
teamEntity, err := teamService.GetTeamById(teamId)
if err != nil {
@@ -715,6 +747,24 @@ func (teamService *TeamServiceV2) removeUserFromTeamEntity(teamEntity team.TeamE
return customErrors.NewNotFoundError("User not found in team")
}
func (teamService *TeamServiceV2) doUsersWithEmailsExistInTeam(teamId uint, emails []string) (bool, error) {
teamUsers, err := teamService.teamUserService.GetTeamUsersByTeamIdAndUserEmailIds(teamId, emails)
if err != nil {
logger.Error(fmt.Sprintf("%s error in fetching team users for team with id: %d : %+v", logTag, teamId, err))
return false, customErrors.NewDataAccessError("Could not fetch team users for team")
}
if teamUsers != nil && len(teamUsers) > 0 {
var existingEmails []string
for _, teamUser := range teamUsers {
existingEmails = append(existingEmails, teamUser.User.Email)
}
return true, customErrors.NewInvalidInputError("User(s) already exist in the team: " + strings.Join(existingEmails, ", "))
}
return false, nil
}
func findUserInTeam(emailId string, teamUsers []*teamUserModel.TeamUserDTO) *teamUserModel.TeamUserDTO {
for _, teamUserValue := range teamUsers {
if teamUserValue.User.Email == emailId {

View File

@@ -13,6 +13,7 @@ type ITeamServiceV2 interface {
GetExternalTeam(teamId uint, provider string) (*externalTeam.ExternalTeamDTO, error)
AddTeam(request teamRequest.AddTeamRequest, userEmail string) (*service.AddTeamResponse, error)
UpdateTeam(request teamRequest.UpdateTeamRequest, userEmail string) error
AddTeamMember(request teamRequest.UpdateTeamRequest, userEmail string) error
RemoveTeamMember(teamId, userId uint, requesterEmail string) error
MakeManager(teamId, memberToMakeManagerId uint, requesterEmail string) error
GetTeam(teamId uint) (*service.TeamResponseV2, error)

View File

@@ -619,6 +619,56 @@ func (suite *TeamServiceV2Suite) Test_UpdateTeam_AddMembers_Success() {
suite.Nil(err, "error should be nil")
}
func (suite *TeamServiceV2Suite) Test_AddTeamMember_TeamNotFound() {
suite.teamRepository.FindTeamByIdMock.Return(nil, errors.New("error"))
err := suite.teamService.AddTeamMember(teamRequest.UpdateTeamRequest{Id: 1, Members: &teamRequest.Members{
SeverityId: 2,
UserEmailIds: []string{"test1@navi.com", "test2@navi.com"},
}}, "")
suite.NotNil(err, "error should not be nil")
}
func (suite *TeamServiceV2Suite) Test_AddTeamMember_TeamUserError() {
suite.teamRepository.FindTeamByIdMock.Return(GetMockTeamEntity(), nil)
suite.teamUserService.GetTeamUsersByTeamIdAndUserEmailIdsMock.Return(nil, errors.New("error"))
err := suite.teamService.AddTeamMember(teamRequest.UpdateTeamRequest{Id: 1, Members: &teamRequest.Members{
SeverityId: 2,
UserEmailIds: []string{"test1@navi.com", "test2@navi.com"},
}}, "")
suite.NotNil(err, "error should not be nil")
}
func (suite *TeamServiceV2Suite) Test_AddTeamMember_DuplicateUserCase() {
suite.teamRepository.FindTeamByIdMock.Return(GetMockTeamEntity(), nil)
suite.teamUserService.GetTeamUsersByTeamIdAndUserEmailIdsMock.Return(GetMockTeamUsers(), nil)
err := suite.teamService.AddTeamMember(teamRequest.UpdateTeamRequest{Id: 1, Members: &teamRequest.Members{
SeverityId: 2,
UserEmailIds: []string{"test1@navi.com", "test2@navi.com"},
}}, "")
suite.NotNil(err, "error should not be nil")
}
func (suite *TeamServiceV2Suite) Test_AddTeamMember_SuccessCase() {
suite.teamRepository.FindTeamByIdMock.Return(GetMockTeamEntity(), nil)
suite.teamUserService.GetTeamUsersByTeamIdAndUserEmailIdsMock.Return(nil, nil)
suite.teamSeverityService.GetSeveritiesMapForATeamMock.Return(GetMockTeamSeverityMap(), nil)
suite.teamUserService.GetTeamUsersByTeamIdMock.Return(GetMockTeamUsers(), nil)
suite.userService.GetHoustonUserByEmailIdMock.Return(GetMockUserDTO(), nil)
suite.teamUserService.AddTeamUserMock.Return(GetMockTeamUserDTO(), nil)
suite.teamUserSeverityService.AddTeamUserSeverityMock.Return(nil)
suite.teamUserSeverityService.UpdateTeamSeverityForTeamUserMock.Return(nil)
suite.teamRepository.UpdateTeamMock.Return(nil)
err := suite.teamService.AddTeamMember(teamRequest.UpdateTeamRequest{Id: 1, Members: &teamRequest.Members{
SeverityId: 2,
UserEmailIds: []string{"test1@navi.com", "test2@navi.com"},
}}, "")
suite.Nil(err, "error should be nil")
}
func (suite *TeamServiceV2Suite) Test_RemoveTeamMember_TeamNotFound() {
suite.teamRepository.FindTeamByIdMock.Return(nil, errors.New("error"))

View File

@@ -83,6 +83,16 @@ func (service *TeamUserService) GetTeamUserByTeamIdAndUserEmailId(teamId uint, u
return teamUser.ToDTO(), nil
}
func (service *TeamUserService) GetTeamUsersByTeamIdAndUserEmailIds(teamId uint, userEmailIds []string) ([]*teamUserModel.TeamUserDTO, error) {
teamUsers, err := service.teamUserRepository.GetTeamUsersByTeamIdAndUserEmailIds(teamId, userEmailIds)
if err != nil {
logger.Error("error in fetching team users", zap.Error(err))
return nil, err
}
return dtoConverter.TeamUserEntitiesToDTOs(teamUsers), nil
}
func (service *TeamUserService) GetTeamUsersWithMinimumSeverityIdLessThanOrEqualToGivenSeverity(teamId, severityId uint) ([]*teamUserModel.TeamUserDTO, error) {
teamUsers, err := service.teamUserRepository.GetTeamUsersWithMinimumSeverityIdLessThanOrEqualToGivenSeverity(teamId, severityId)
if err != nil {

View File

@@ -112,6 +112,22 @@ func (suite *TeamUserServiceSuite) Test_GetTeamUserByTeamIdAndUserEmailId_Succes
suite.NotNil(teamUser, "teamUser should not be nil")
}
func (suite *TeamUserServiceSuite) Test_GetTeamUsersByTeamIdAndUserEmailIds_RepoFailureCase() {
suite.teamUserRepository.GetTeamUsersByTeamIdAndUserEmailIdsMock.Return(nil, errors.New("error"))
teamUsers, err := suite.teamUserService.GetTeamUsersByTeamIdAndUserEmailIds(1, []string{"email"})
suite.Nil(teamUsers, "teamUsers should be nil")
suite.EqualError(err, "error", "error should be error")
}
func (suite *TeamUserServiceSuite) Test_GetTeamUsersByTeamIdAndUserEmailIds_SuccessCase() {
suite.teamUserRepository.GetTeamUsersByTeamIdAndUserEmailIdsMock.Return(GetMockTeamUserEntities(), nil)
teamUsers, err := suite.teamUserService.GetTeamUsersByTeamIdAndUserEmailIds(1, []string{"email"})
suite.Nil(err, "error should be nil")
suite.NotNil(teamUsers, "teamUsers should not be nil")
}
func (suite *TeamUserServiceSuite) Test_GetTeamUsersWithMinimumSeverityIdLessThanOrEqualToGivenSeverity_RepoFailureCase() {
suite.teamUserRepository.GetTeamUsersWithMinimumSeverityIdLessThanOrEqualToGivenSeverityMock.Return(nil, errors.New("error"))

View File

@@ -9,5 +9,6 @@ type ITeamUserService interface {
GetTeamsByUserId(userId uint) ([]*teamUserModel.TeamUserDTO, error)
RemoveTeamUser(teamId, userId uint) error
GetTeamUserByTeamIdAndUserEmailId(teamId uint, userEmailId string) (*teamUserModel.TeamUserDTO, error)
GetTeamUsersByTeamIdAndUserEmailIds(teamId uint, userEmailIds []string) ([]*teamUserModel.TeamUserDTO, error)
GetTeamUsersWithMinimumSeverityIdLessThanOrEqualToGivenSeverity(teamId, severityId uint) ([]*teamUserModel.TeamUserDTO, error)
}