package models import ( "fmt" "github.com/dgrijalva/jwt-go" "github.com/labstack/echo" "golang.org/x/crypto/bcrypt" ) // UserLogin Object to recive user credentials in JSON format type UserLogin struct { Username string `json:"username" form:"username"` Password string `json:"password" form:"password"` } // User holds information about an user type User struct { ID int64 `xorm:"int(11) autoincr not null unique pk"` Name string `xorm:"varchar(250)"` Username string `xorm:"varchar(250) not null unique"` Password string `xorm:"varchar(250) not null"` Email string `xorm:"varchar(250)"` Created int64 `xorm:"created"` Updated int64 `xorm:"updated"` } // UserLog logs user actions type UserLog struct { ID int64 `xorm:"int(11) autoincr not null unique pk"` UserID int64 `xorm:"int(11)"` Log string `xorm:"varchar(250)"` ItemID int64 `xorm:"int(11)"` Time int64 `xorm:"created"` } // TableName returns the table name for users func (User) TableName() string { return "users" } // GetUserByID gets informations about a user by its ID func GetUserByID(id int64) (user User, exists bool, err error) { return GetUser(User{ID: id}) } // GetUser gets a user object func GetUser(user User) (userOut User, exists bool, err error) { userOut = user exists, err = x.Get(&userOut) return userOut, exists, err } // CreateUser creates a new user and inserts it into the database func CreateUser(user User) (newUser User, err error) { newUser = user // Check if we have all needed informations if newUser.Password == "" || newUser.Username == "" { return User{}, fmt.Errorf("you need to specify at least a username and a password") } // Check if the user already existst _, exists, err := GetUser(User{Name: newUser.Name}) if err != nil { return User{}, err } if exists { return User{}, fmt.Errorf("this username is already taken. Please use another") } // Hash the password newUser.Password, err = hashPassword(user.Password) if err != nil { return User{}, err } // Insert it _, err = x.Insert(newUser) if err != nil { return User{}, err } return newUser, nil } // HashPassword hashes a password func hashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) return string(bytes), err } // CheckUserCredentials checks user credentials func CheckUserCredentials(u *UserLogin) (User, error) { // Check if the user exists var user = User{Username: u.Username} exists, err := x.Get(&user) if err != nil { return User{}, err } if !exists { return User{}, fmt.Errorf("user does not exist") } // Check the users password err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(u.Password)) if err != nil { return User{}, err } return user, nil } // GetCurrentUser returns the current user based on its jwt token func GetCurrentUser(c echo.Context) (user User, err error) { jwtinf := c.Get("user").(*jwt.Token) claims := jwtinf.Claims.(jwt.MapClaims) userID, ok := claims["id"].(float64) if !ok { return user, fmt.Errorf("Error getting UserID") } user = User{ ID: int64(userID), Name: claims["name"].(string), Email: claims["email"].(string), Username: claims["username"].(string), } return } // LogAction logs a user action func logAction(action string, user User, itemID int64) (err error) { _, err = x.Insert(UserLog{Log: action, UserID: user.ID, ItemID: itemID}) return } // LogAction logs a user action func LogAction(action string, itemID int64, c echo.Context) (err error) { // Get the user options user, err := GetCurrentUser(c) if err != nil { return err } return logAction(action, user, itemID) }