Skip to content

Commit

Permalink
create user validation (#1074)
Browse files Browse the repository at this point in the history
* create user validation

* move validateUsername

* move funcs

* move validatePassword
  • Loading branch information
shay23b committed Jul 5, 2023
1 parent 4c5fe65 commit 170be00
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 60 deletions.
58 changes: 36 additions & 22 deletions server/memphis_cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"memphis/models"
"memphis/utils"
"net/http"
"regexp"
"runtime"
"sort"
"strconv"
Expand Down Expand Up @@ -1215,10 +1214,34 @@ func (umh UserMgmtHandler) AddUser(c *gin.Context) {

var subscription, pending bool
team := strings.ToLower(body.Team)
teamError := validateUserTeam(team)
if teamError != nil {
serv.Warnf("[tenant: %v][user: %v]AddUser at validateUserTeam: %v", user.TenantName, user.Username, teamError.Error())
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": teamError.Error()})
return
}
position := strings.ToLower(body.Position)
positionError := validateUserPosition(position)
if positionError != nil {
serv.Warnf("[tenant: %v][user: %v]AddUser at validateUserPosition: %v", user.TenantName, user.Username, positionError.Error())
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": positionError.Error()})
return
}
fullName := strings.ToLower(body.FullName)
fullNameError := validateUserFullName(fullName)
if fullNameError != nil {
serv.Warnf("[tenant: %v][user: %v]AddUser at validateUserFullName: %v", user.TenantName, user.Username, fullNameError.Error())
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": fullNameError.Error()})
return
}
owner := user.Username
description := strings.ToLower(body.Description)
descriptionError := validateUserDescription(description)
if descriptionError != nil {
serv.Warnf("[tenant: %v][user: %v]AddUser at validateUserDescription: %v", user.TenantName, user.Username, descriptionError.Error())
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": descriptionError.Error()})
return
}

user.TenantName = strings.ToLower(user.TenantName)
username := strings.ToLower(body.Username)
Expand Down Expand Up @@ -1254,13 +1277,20 @@ func (umh UserMgmtHandler) AddUser(c *gin.Context) {
avatarId = body.AvatarId
}

if body.Password == "" {
serv.Warnf("[tenant: %v][user: %v]AddUser: Password was not provided for user %v", user.TenantName, user.Username, username)
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": "Password was not provided"})
return
}
passwordErr := validatePassword(body.Password)
if passwordErr != nil {
serv.Warnf("[tenant: %v][user: %v]AddUser validate password : User %v: %v", user.TenantName, user.Username, body.Username, passwordErr.Error())
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": passwordErr.Error()})
return
}

var password string
if userType == "management" {
if body.Password == "" {
serv.Warnf("[tenant: %v][user: %v]AddUser: Password was not provided for user %v", user.TenantName, user.Username, username)
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": "Password was not provided"})
return
}

hashedPwd, err := bcrypt.GenerateFromPassword([]byte(body.Password), bcrypt.MinCost)
if err != nil {
Expand All @@ -1282,12 +1312,6 @@ func (umh UserMgmtHandler) AddUser(c *gin.Context) {
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": "Password was not provided"})
return
}
err = validatePassword(body.Password)
if err != nil {
serv.Warnf("[tenant: %v][user: %v]AddUser validate password : User %v: %v", user.TenantName, user.Username, body.Username, err.Error())
c.AbortWithStatusJSON(SHOWABLE_ERROR_STATUS_CODE, gin.H{"message": err.Error()})
return
}
password, err = EncryptAES([]byte(body.Password))
if err != nil {
serv.Errorf("[tenant: %v][user: %v]AddUser at EncryptAES: User %v: %v", user.TenantName, user.Username, body.Username, err.Error())
Expand Down Expand Up @@ -1413,16 +1437,6 @@ func (umh UserMgmtHandler) RemoveUser(c *gin.Context) {
c.IndentedJSON(200, gin.H{})
}

func validateUsername(username string) error {
re := regexp.MustCompile("^[a-z0-9_.-]*$")

validName := re.MatchString(username)
if !validName || len(username) == 0 {
return errors.New("username has to include only letters/numbers/./_/- ")
}
return nil
}

func (umh UserMgmtHandler) RemoveMyUser(c *gin.Context) {
user, err := getUserDetailsFromMiddleware(c)
if err != nil {
Expand Down
80 changes: 80 additions & 0 deletions server/memphis_handlers_user_mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strconv"
"strings"
"time"
"unicode"

"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
Expand Down Expand Up @@ -777,3 +778,82 @@ func (umh UserMgmtHandler) GetFilterDetails(c *gin.Context) {
return
}
}

func validateUsername(username string) error {
if len(username) > 20 {
return errors.New("username exceeds the maximum allowed length of 20 characters")
}
re := regexp.MustCompile("^[a-z0-9_.-]*$")
validName := re.MatchString(username)
if !validName || len(username) == 0 {
return errors.New("username has to include only letters/numbers/./_/- ")
}
return nil
}

func validateUserDescription(description string) error {
if len(description) > 100 {
return errors.New("description exceeds the maximum allowed length of 100 characters")
}
return nil
}

func validateUserTeam(team string) error {
if len(team) > 20 {
return errors.New("team exceeds the maximum allowed length of 20 characters")
}
return nil
}

func validateUserPosition(position string) error {
if len(position) > 30 {
return errors.New("position exceeds the maximum allowed length of 30 characters")
}
return nil
}

func validateUserFullName(fullName string) error {
if len(fullName) > 30 {
return errors.New("full name exceeds the maximum allowed length of 30 characters")
}
return nil
}

func validatePassword(password string) error {
if len(password) > 20 {
return errors.New("password exceeds the maximum allowed length of 20 characters")
}
pattern := `^[A-Za-z0-9!?\-@#$%]+$`
match, _ := regexp.MatchString(pattern, password)
if !match {
return errors.New("Password must be at least 8 characters long, contain both uppercase and lowercase, and at least one number and one special character")
}
if len(password) < 8 {
return errors.New("Password must be at least 8 characters long, contain both uppercase and lowercase, and at least one number and one special character")
}
var (
hasUppercase bool
hasLowercase bool
hasDigit bool
hasSpecialChar bool
)

for _, char := range password {
switch {
case unicode.IsUpper(char):
hasUppercase = true
case unicode.IsLower(char):
hasLowercase = true
case unicode.IsDigit(char):
hasDigit = true
case char == '!' || char == '?' || char == '-' || char == '@' || char == '#' || char == '$' || char == '%':
hasSpecialChar = true
}
}

if hasUppercase && hasLowercase && hasDigit && hasSpecialChar {
return nil
}

return errors.New("Password must be at least 8 characters long, contain both uppercase and lowercase, and at least one number and one special character")
}
38 changes: 0 additions & 38 deletions server/memphis_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,10 @@ import (
"memphis/models"
"net/textproto"
"os"
"regexp"
"sort"
"strconv"
"strings"
"time"
"unicode"

"github.com/gofrs/uuid"
"github.com/nats-io/nuid"
Expand Down Expand Up @@ -1455,39 +1453,3 @@ func (s *Server) MoveResourcesFromOldToNewDefaultAcc() error {
}
return nil
}

func validatePassword(password string) error {
pattern := `^[A-Za-z0-9!?\-@#$%]+$`
match, _ := regexp.MatchString(pattern, password)
if !match {
return errors.New("Password must be at least 8 characters long, contain both uppercase and lowercase, and at least one number and one special character")
}
if len(password) < 8 {
return errors.New("Password must be at least 8 characters long, contain both uppercase and lowercase, and at least one number and one special character")
}
var (
hasUppercase bool
hasLowercase bool
hasDigit bool
hasSpecialChar bool
)

for _, char := range password {
switch {
case unicode.IsUpper(char):
hasUppercase = true
case unicode.IsLower(char):
hasLowercase = true
case unicode.IsDigit(char):
hasDigit = true
case char == '!' || char == '?' || char == '-' || char == '@' || char == '#' || char == '$' || char == '%':
hasSpecialChar = true
}
}

if hasUppercase && hasLowercase && hasDigit && hasSpecialChar {
return nil
}

return errors.New("Password must be at least 8 characters long, contain both uppercase and lowercase, and at least one number and one special character")
}
7 changes: 7 additions & 0 deletions ui_src/src/domain/users/createUserDetails/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ const CreateUserDetails = ({ createUserRef, closeModal, handleLoader }) => {
placeholder={userType === 'management' && isCloud() ? 'Type email' : 'Type username'}
type="text"
radiusType="semi-round"
maxLength={20}
colorType="black"
backgroundColorType="none"
borderColorType="gray"
Expand Down Expand Up @@ -175,6 +176,7 @@ const CreateUserDetails = ({ createUserRef, closeModal, handleLoader }) => {
<Input
placeholder="Type full name"
type="text"
maxLength={30}
radiusType="semi-round"
colorType="black"
backgroundColorType="none"
Expand All @@ -194,6 +196,7 @@ const CreateUserDetails = ({ createUserRef, closeModal, handleLoader }) => {
<Input
placeholder="Type your team"
type="text"
maxLength={20}
radiusType="semi-round"
colorType="black"
backgroundColorType="none"
Expand All @@ -212,6 +215,7 @@ const CreateUserDetails = ({ createUserRef, closeModal, handleLoader }) => {
<Input
placeholder="Type your position"
type="text"
maxLength={30}
radiusType="semi-round"
colorType="black"
backgroundColorType="none"
Expand All @@ -235,6 +239,7 @@ const CreateUserDetails = ({ createUserRef, closeModal, handleLoader }) => {
<Input
placeholder="Type your description"
type="text"
maxLength={100}
radiusType="semi-round"
colorType="black"
backgroundColorType="none"
Expand Down Expand Up @@ -307,6 +312,7 @@ const CreateUserDetails = ({ createUserRef, closeModal, handleLoader }) => {
<Input
placeholder="Type Password"
type="password"
maxLength={20}
radiusType="semi-round"
colorType="black"
backgroundColorType="none"
Expand Down Expand Up @@ -341,6 +347,7 @@ const CreateUserDetails = ({ createUserRef, closeModal, handleLoader }) => {
<Input
placeholder="Type Password"
type="password"
maxLength={20}
radiusType="semi-round"
colorType="black"
backgroundColorType="none"
Expand Down

0 comments on commit 170be00

Please sign in to comment.