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, User: usr.Username, 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) if err != nil { ClearToken(c) panic(errors.NewError(http.StatusUnauthorized, err)) } server.Res(c, &server.Response{Data: usr}) }