vikunja-api/pkg/models/user.go

121 lines
3.1 KiB
Go
Raw Permalink Normal View History

2018-06-10 11:11:41 +02:00
package models
import (
"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" json:"id"`
Username string `xorm:"varchar(250) not null unique" json:"username"`
Password string `xorm:"varchar(250) not null" json:"-"`
2018-06-10 11:11:41 +02:00
Email string `xorm:"varchar(250)" json:"email"`
IsActive bool `json:"-"`
2018-10-27 11:33:28 +02:00
PasswordResetToken string `xorm:"varchar(450)" json:"-"`
EmailConfirmToken string `xorm:"varchar(450)" json:"-"`
2018-10-27 11:33:28 +02:00
Created int64 `xorm:"created" json:"-"`
Updated int64 `xorm:"updated" json:"-"`
2018-06-10 11:11:41 +02:00
}
// TableName returns the table name for users
func (User) TableName() string {
return "users"
}
2018-07-10 14:02:23 +02:00
// APIUserPassword represents a user object without timestamps and a json password field.
type APIUserPassword struct {
2018-06-13 13:45:22 +02:00
ID int64 `json:"id"`
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
}
2018-07-10 14:02:23 +02:00
// APIFormat formats an API User into a normal user struct
func (apiUser *APIUserPassword) APIFormat() User {
2018-06-13 13:45:22 +02:00
return User{
ID: apiUser.ID,
Username: apiUser.Username,
Password: apiUser.Password,
Email: apiUser.Email,
}
}
2018-06-10 11:11:41 +02:00
// GetUserByID gets informations about a user by its ID
2018-08-30 19:14:02 +02:00
func GetUserByID(id int64) (user User, err error) {
2018-06-10 11:11:41 +02:00
// Apparently xorm does otherwise look for all users but return only one, which leads to returing one even if the ID is 0
if id < 1 {
return User{}, ErrUserDoesNotExist{}
2018-06-10 11:11:41 +02:00
}
return GetUser(User{ID: id})
}
// GetUser gets a user object
2018-08-30 19:14:02 +02:00
func GetUser(user User) (userOut User, err error) {
2018-06-10 11:11:41 +02:00
userOut = user
2018-08-30 19:14:02 +02:00
exists, err := x.Get(&userOut)
2018-06-10 11:11:41 +02:00
if !exists {
2018-10-27 11:33:28 +02:00
return User{}, ErrUserDoesNotExist{UserID: user.ID}
2018-06-10 11:11:41 +02:00
}
2018-08-30 19:14:02 +02:00
return userOut, err
2018-06-10 11:11:41 +02:00
}
// CheckUserCredentials checks user credentials
func CheckUserCredentials(u *UserLogin) (User, error) {
// Check if we have any credentials
if u.Password == "" || u.Username == "" {
return User{}, ErrNoUsernamePassword{}
}
2018-06-10 11:11:41 +02:00
// Check if the user exists
2018-08-30 19:14:02 +02:00
user, err := GetUser(User{Username: u.Username})
2018-06-10 11:11:41 +02:00
if err != nil {
return User{}, err
}
// User is invalid if it needs to verify its email address
if !user.IsActive {
return User{}, ErrEmailNotConfirmed{UserID: user.ID}
}
2018-06-10 11:11:41 +02:00
// Check the users password
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(u.Password))
if err != nil {
if err == bcrypt.ErrMismatchedHashAndPassword {
return User{}, ErrWrongUsernameOrPassword{}
}
2018-06-10 11:11:41 +02:00
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, ErrCouldNotGetUserID{}
}
user = User{
ID: int64(userID),
Email: claims["email"].(string),
Username: claims["username"].(string),
}
return
}