package controllers import ( "errors" "fmt" "html" "log" "net/http" "strings" "smt/models" "smt/utils/token" "github.com/gin-gonic/gin" "golang.org/x/crypto/bcrypt" ) type AddUserInput struct { UserName string `json:"userName" binding:"required"` Password string `json:"password" binding:"required"` GroupId int `json:"groupId"` GroupName string `json:"groupName"` //RoleId int `json:"roleid"` } type LoginInput struct { UserName string `json:"userName" binding:"required"` Password string `json:"password" binding:"required"` } type DeleteInput struct { UserName string `json:"userName" binding:"required"` } type AddRoleInput struct { RoleName string `json:"roleName" binding:"required"` LdapGroup string `json:"ldapGroup"` ReadOnly bool `json:"readOnly"` Admin bool `json:"admin"` } func DeleteUser(c *gin.Context) { var input DeleteInput var RequestingUserId int if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if val, ok := c.Get("user-id"); !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user"}) return } else { RequestingUserId = val.(int) } u := models.User{} u.UserName = input.UserName //remove spaces in username u.UserName = html.EscapeString(strings.TrimSpace(u.UserName)) // Confirm user account exists testUser, _ := models.UserGetByName(u.UserName) log.Printf("DeleteUser confirming user '%s' account exists\n", u.UserName) if (models.User{} == testUser) { err := errors.New("attempt to delete non-existing username '" + u.UserName + "'") log.Printf("Delete User error : '%s'\n", err) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } else { err := u.DeleteUser() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"Error deleting user": err.Error()}) return } // Create audit record a := models.Audit{ UserId: RequestingUserId, EventText: fmt.Sprintf("Deleted User Id %d", testUser.UserId), } a.AuditAdd() c.JSON(http.StatusOK, gin.H{"message": "user deletion success"}) } } func AddUser(c *gin.Context) { var input AddUserInput var RequestingUserId int if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if len(input.UserName) == 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified"}) return } if len(input.Password) == 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "no password specified"}) return } if val, ok := c.Get("user-id"); !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user"}) return } else { RequestingUserId = val.(int) } u := models.User{} u.UserName = input.UserName u.Password = input.Password // Determine which GroupId to save // Can be specified either by GroupName or GroupId in the request if len(input.GroupName) > 0 { g, err := models.GroupGetByName(input.GroupName) if err != nil { errString := fmt.Sprintf("RegisterUser error looking up group by name : '%s'", err) log.Println(errString) c.JSON(http.StatusBadRequest, gin.H{"error": errString}) return } if g == (models.Group{}) { errString := fmt.Sprintf("RegisterUser specified group '%s' not found\n", input.GroupName) log.Println(errString) c.JSON(http.StatusBadRequest, gin.H{"error": errString}) return } else { u.GroupId = g.GroupId } } else if input.GroupId > 0 { u.GroupId = input.GroupId } else { // Default to group Id 2 which is users log.Println("RegisterUser no group id or group name specified, defaulting to built-in group 'Users' ") u.GroupId = 2 } //remove spaces in username u.UserName = html.EscapeString(strings.TrimSpace(u.UserName)) // Check if user already exists testUser, _ := models.UserGetByName(u.UserName) log.Printf("Register checking if user '%s' already exists\n", u.UserName) if (models.User{} == testUser) { log.Printf("Register confirmed no existing username\n") } else { err := errors.New("attempt to register conflicting username '" + u.UserName + "'") log.Printf("Register error : '%s'\n", err) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } //turn password into hash hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"Error hashing password": err.Error()}) return } else { //log.Printf("Register generated hashed password value '%s' from '%s'\n", string(hashedPassword), input.Password) log.Printf("Register generated hashed password value '%s'\n", string(hashedPassword)) } u.Password = string(hashedPassword) _, err = u.SaveUser() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"Error saving user": err.Error()}) return } // Create audit record a := models.Audit{ UserId: RequestingUserId, EventText: fmt.Sprintf("Created User Id %d", u.UserId), } a.AuditAdd() c.JSON(http.StatusOK, gin.H{"message": "user registration success", "data": u}) } func Login(c *gin.Context) { var input LoginInput if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } u := models.User{} u.UserName = input.UserName u.Password = input.Password log.Printf("Login checking username '%s' and password length '%d'\n", u.UserName, len(u.Password)) token, err := models.LoginCheck(u.UserName, u.Password) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "username or password is incorrect."}) return } else { log.Printf("Login verified, returning token '%s'\n", token) } c.JSON(http.StatusOK, gin.H{"access_token": token}) } func CurrentUser(c *gin.Context) { user_id, err := token.ExtractTokenID(c) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } u, err := models.UserGetByID(user_id) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "success", "data": u}) } func GetUsers(c *gin.Context) { users, err := models.UserList() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "success", "data": users}) }