89 lines
2.0 KiB
Go
89 lines
2.0 KiB
Go
package auth
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/rs/zerolog/log"
|
|
"kumoly.io/kumoly/app/errors"
|
|
"kumoly.io/kumoly/app/server"
|
|
)
|
|
|
|
type apiLoginReq struct {
|
|
Name string `json:"username" example:"user" binding:"required"`
|
|
// Email string `json:"email" example:"user@example.com" binding:"required,email"`
|
|
PwdB64 string `json:"password" example:"YWRtaW4=" binding:"required,base64"`
|
|
}
|
|
|
|
func ApiLogin(c *gin.Context) {
|
|
var data apiLoginReq
|
|
if err := c.ShouldBindJSON(&data); err != nil {
|
|
panic(err)
|
|
}
|
|
pwd, err := base64.URLEncoding.DecodeString(data.PwdB64)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
usr := &User{}
|
|
err = DB.Preload("Profile").Preload("Groups").Where("username = ?", data.Name).First(usr).Error
|
|
if err != nil {
|
|
panic(ErrorLoginFailed)
|
|
}
|
|
err = usr.ValidatePassword(string(pwd))
|
|
if err != nil {
|
|
log.Error().Str("mod", "auth").Err(err).Msg("wrong password")
|
|
usr.LoginFailed += 1
|
|
DB.Model(&usr).Update("login_failed", usr.LoginFailed)
|
|
panic(ErrorLoginFailed)
|
|
}
|
|
if usr.SSOEnabled {
|
|
panic(ErrorUserIsSSO)
|
|
}
|
|
if !usr.Activated {
|
|
log.Error().Str("mod", "auth").
|
|
Err(ErrorUserNotActivated).
|
|
Str("user", usr.Username).Str("uid", usr.ID).
|
|
Msg("not activated")
|
|
panic(ErrorUserNotActivated)
|
|
}
|
|
grps := make([]string, len(usr.Groups))
|
|
for i, g := range usr.Groups {
|
|
grps[i] = g.Name
|
|
}
|
|
err = SetClaims(c, &Claims{
|
|
Uid: usr.ID,
|
|
Groups: grps,
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
usr.LastLogin = time.Now()
|
|
usr.LastLoginIP = c.ClientIP()
|
|
usr.LoginFailed = 0
|
|
DB.Model(&usr).Updates(map[string]interface{}{
|
|
"last_login": usr.LastLogin,
|
|
"login_failed": usr.LoginFailed,
|
|
"last_login_ip": usr.LastLoginIP,
|
|
})
|
|
server.Res(c, &server.Response{
|
|
Status: 200,
|
|
Data: usr,
|
|
})
|
|
}
|
|
|
|
func ApiLogout(c *gin.Context) {
|
|
ClearToken(c)
|
|
server.Res(c, &server.Response{Data: "ok"})
|
|
}
|
|
|
|
func ApiMe(c *gin.Context) {
|
|
usr, err := GetUser(c, DB)
|
|
if err != nil {
|
|
ClearToken(c)
|
|
panic(errors.NewError(http.StatusUnauthorized, err))
|
|
}
|
|
server.Res(c, &server.Response{Data: usr})
|
|
}
|