|
- package endpoints
-
- import (
- "encoding/json"
- "net/http"
- "time"
-
- "github.com/golang-jwt/jwt/v4"
- "github.com/imosed/signet/auth"
- . "github.com/imosed/signet/data"
- "github.com/rs/zerolog/log"
- "github.com/spf13/viper"
- )
-
- type LoginResponse struct {
- Token *string `json:"token"`
- LastLogin *time.Time `json:"lastLogin"`
- }
-
- func Login(w http.ResponseWriter, r *http.Request) {
- var req AuthenticationRequest
- err := json.NewDecoder(r.Body).Decode(&req)
- if err != nil {
- log.Error().Err(err).Msg("Failed to decode body in login attempt")
- return
- }
-
- var userData User
-
- var loginTime = time.Now()
-
- var resp LoginResponse
- Db.Table("users").Select("id, password, privileges, last_login").
- Where("username = ?", req.Username).First(&userData)
- var passwordMatches bool
- passwordMatches, err = ComparePasswordAndHash(req.Password, userData.Password)
- if err != nil {
- log.Error().Err(err).Msg("Could not compare password to hash in login attempt")
- return
- }
- if !passwordMatches {
- err = json.NewEncoder(w).Encode(resp)
- if err != nil {
- log.Error().Err(err).Msg("Failed to deliver failed login attempt response")
- }
- return
- }
-
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, &auth.Claims{
- ID: userData.ID,
- Username: req.Username,
- Privileges: userData.Privileges,
- RegisteredClaims: jwt.RegisteredClaims{
- ExpiresAt: jwt.NewNumericDate(loginTime.Add(10 * time.Hour)),
- },
- })
-
- secret := viper.GetString("app.secretKey")
- tokenString, err := token.SignedString([]byte(secret))
- if err != nil {
- log.Error().Err(err).Msg("Could not generate JWT token")
- return
- }
- resp.Token = &tokenString
- resp.LastLogin = userData.LastLogin
-
- if userData.LastLogin != nil {
- // need to set this after the user changes their password
- Db.Table("users").Where("id = ?", userData.ID).Update("last_login", loginTime)
- }
-
- err = json.NewEncoder(w).Encode(resp)
- if err != nil {
- log.Error().Err(err).Msg("Could not deliver response in Login call")
- }
- }
|