Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package models
- import (
- "errors"
- "mmt/services/crm/config"
- "time"
- jwt "github.com/dgrijalva/jwt-go"
- "github.com/gofrs/uuid"
- "golang.org/x/crypto/bcrypt"
- )
- // TODO: вынести в конфиг
- // const tokenExpiredTime = 1440
- // const refreshTokenExpiredMinutes = 201600
- // Sessions godoc
- type Sessions struct {
- tableName struct{} `sql:"crm_sessions"`
- ID int `json:"id" sql:",pk"`
- UserID int `json:"user_id"`
- RefreshToken string `json:"refresh_token" description:"Токен для обновления"`
- SessionEnd time.Time `json:"session_end" description:"Дата когда токен отозван"`
- RefreshTokenUsed time.Time `json:"refresh_token_used" description:"Дата использования токена"`
- RefreshTokenExpired time.Time `json:"refrash_expired" description:"Дата протухания токена"`
- CreatedAt time.Time `sql:"default:now()" json:"created_at" description:"Дата создания"`
- }
- type (
- // LoginRequest requested data when logging in
- LoginRequest struct {
- Login string `json:"login"`
- Password string `json:"password"`
- }
- // LoginRefreshRequest godoc
- LoginRefreshRequest struct {
- RefreshToken string `json:"refresh"`
- }
- // TokenClaim JWT token structure
- TokenClaim struct {
- Role string `json:"role"`
- UserID int `json:"user_id"`
- Login string `json:"login"`
- jwt.StandardClaims
- }
- // LoginResponse responsed when requesting token
- LoginResponse struct {
- UserID int `json:"user_id"`
- Token string `json:"token"`
- RefreshToken string `json:"refresh_token"`
- RefreshTokenExpiration time.Time `json:"refresh_expiration"`
- }
- )
- // NewRefrashToken generate new session ID
- func (logResp *LoginResponse) newRefreshToken(userID int) error {
- newToken, err := uuid.NewV4()
- if err != nil {
- return err
- }
- logResp.UserID = userID
- logResp.RefreshToken = newToken.String()
- dur := time.Minute * time.Duration(config.St.Application.RefreshTokenExpiredM)
- logResp.RefreshTokenExpiration = time.Now().Add(dur)
- err = logResp.saveTokenData(newToken.String())
- if err != nil {
- return err
- }
- return nil
- }
- // saveTokenData expired existing and create new token for user
- func (logResp *LoginResponse) saveTokenData(uuid string) error {
- var sessNew Sessions
- sessNew.UserID = logResp.UserID
- sessNew.RefreshToken = uuid
- sessNew.RefreshTokenExpired = logResp.RefreshTokenExpiration
- _, err := db.Model(&sessNew).Returning("*").Insert()
- if err != nil {
- return errors.New("Ошибка сохранения новой сессии")
- }
- return nil
- }
- // GenerateJWT generates new token
- func (logResp *LoginResponse) GenerateJWT(user UsersCRM) error {
- jwtSec := config.JWTSecret()
- mySigningKey := []byte(jwtSec)
- claims := TokenClaim{
- UserID: user.ID,
- Role: user.Role,
- Login: user.Login,
- }
- claims.IssuedAt = time.Now().Unix()
- dur := time.Minute * time.Duration(config.St.Application.TokenExpiredM)
- claims.ExpiresAt = time.Now().Add(dur).Unix()
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- ss, err := token.SignedString(mySigningKey)
- if err != nil {
- return err
- }
- logResp.Token = ss
- return nil
- }
- // AuthenticateUser godoc
- func AuthenticateUser(data LoginRequest) (LoginResponse, error) {
- var oper UsersCRM
- var login LoginResponse
- err := db.Model(&oper).
- Where("deleted = false AND Login = ?", data.Login).
- First()
- if err != nil {
- return login, err
- }
- // Comparing the password with the hash
- err = bcrypt.CompareHashAndPassword([]byte(oper.Password), []byte(data.Password))
- if err != nil {
- return login, err
- }
- err = expireUserTokens(oper.ID)
- if err != nil {
- return login, err
- }
- err = login.newRefreshToken(oper.ID)
- if err != nil {
- return login, err
- }
- err = login.GenerateJWT(oper)
- if err != nil {
- return login, err
- }
- return login, nil
- }
- func expireUserTokens(userID int) error {
- var sessOld Sessions
- _, err := db.Model(&sessOld).
- Set("refresh_token_used = ?", time.Now()).
- Where("user_id = ?", userID).
- Update()
- if err != nil {
- return err
- }
- return nil
- }
- func expireToken(token string) (UsersCRM, error) {
- var oper UsersCRM
- var sessOld Sessions
- _, err := db.Model(&sessOld).
- Set("refresh_token_used = ?", time.Now()).
- Where("refresh_token = ? AND CURRENT_TIMESTAMP < refresh_token_expired AND refresh_token_used is NULL", token).
- Returning("*").
- Update(&sessOld)
- if err != nil {
- return oper, errors.New("Refresh token not found")
- }
- err = db.Model(&oper).
- Where("deleted = false AND ID = ?", sessOld.UserID).
- First()
- if err != nil {
- return oper, err
- }
- return oper, nil
- }
- // RefreshJWTToken godoc
- func RefreshJWTToken(token string) (LoginResponse, error) {
- var newLogin LoginResponse
- User, err := expireToken(token)
- if err != nil {
- return newLogin, err
- }
- err = newLogin.newRefreshToken(User.ID)
- if err != nil {
- return newLogin, err
- }
- err = newLogin.GenerateJWT(User)
- if err != nil {
- return newLogin, err
- }
- return newLogin, nil
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement