Advertisement
Guest User

Untitled

a guest
Apr 24th, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.00 KB | None | 0 0
  1. package models
  2.  
  3. import (
  4. "errors"
  5. "mmt/services/crm/config"
  6. "time"
  7.  
  8. jwt "github.com/dgrijalva/jwt-go"
  9. "github.com/gofrs/uuid"
  10. "golang.org/x/crypto/bcrypt"
  11. )
  12.  
  13. // TODO: вынести в конфиг
  14. // const tokenExpiredTime = 1440
  15. // const refreshTokenExpiredMinutes = 201600
  16.  
  17. // Sessions godoc
  18. type Sessions struct {
  19. tableName struct{} `sql:"crm_sessions"`
  20. ID int `json:"id" sql:",pk"`
  21. UserID int `json:"user_id"`
  22. RefreshToken string `json:"refresh_token" description:"Токен для обновления"`
  23. SessionEnd time.Time `json:"session_end" description:"Дата когда токен отозван"`
  24. RefreshTokenUsed time.Time `json:"refresh_token_used" description:"Дата использования токена"`
  25. RefreshTokenExpired time.Time `json:"refrash_expired" description:"Дата протухания токена"`
  26. CreatedAt time.Time `sql:"default:now()" json:"created_at" description:"Дата создания"`
  27. }
  28.  
  29. type (
  30. // LoginRequest requested data when logging in
  31. LoginRequest struct {
  32. Login string `json:"login"`
  33. Password string `json:"password"`
  34. }
  35.  
  36. // LoginRefreshRequest godoc
  37. LoginRefreshRequest struct {
  38. RefreshToken string `json:"refresh"`
  39. }
  40.  
  41. // TokenClaim JWT token structure
  42. TokenClaim struct {
  43. Role string `json:"role"`
  44. UserID int `json:"user_id"`
  45. Login string `json:"login"`
  46. jwt.StandardClaims
  47. }
  48.  
  49. // LoginResponse responsed when requesting token
  50. LoginResponse struct {
  51. UserID int `json:"user_id"`
  52. Token string `json:"token"`
  53. RefreshToken string `json:"refresh_token"`
  54. RefreshTokenExpiration time.Time `json:"refresh_expiration"`
  55. }
  56. )
  57.  
  58. // NewRefrashToken generate new session ID
  59. func (logResp *LoginResponse) newRefreshToken(userID int) error {
  60.  
  61. newToken, err := uuid.NewV4()
  62. if err != nil {
  63. return err
  64. }
  65.  
  66. logResp.UserID = userID
  67. logResp.RefreshToken = newToken.String()
  68.  
  69. dur := time.Minute * time.Duration(config.St.Application.RefreshTokenExpiredM)
  70. logResp.RefreshTokenExpiration = time.Now().Add(dur)
  71.  
  72. err = logResp.saveTokenData(newToken.String())
  73. if err != nil {
  74. return err
  75. }
  76. return nil
  77. }
  78.  
  79. // saveTokenData expired existing and create new token for user
  80. func (logResp *LoginResponse) saveTokenData(uuid string) error {
  81.  
  82. var sessNew Sessions
  83.  
  84. sessNew.UserID = logResp.UserID
  85. sessNew.RefreshToken = uuid
  86. sessNew.RefreshTokenExpired = logResp.RefreshTokenExpiration
  87.  
  88. _, err := db.Model(&sessNew).Returning("*").Insert()
  89. if err != nil {
  90. return errors.New("Ошибка сохранения новой сессии")
  91. }
  92.  
  93. return nil
  94. }
  95.  
  96. // GenerateJWT generates new token
  97. func (logResp *LoginResponse) GenerateJWT(user UsersCRM) error {
  98.  
  99. jwtSec := config.JWTSecret()
  100. mySigningKey := []byte(jwtSec)
  101.  
  102. claims := TokenClaim{
  103. UserID: user.ID,
  104. Role: user.Role,
  105. Login: user.Login,
  106. }
  107. claims.IssuedAt = time.Now().Unix()
  108.  
  109. dur := time.Minute * time.Duration(config.St.Application.TokenExpiredM)
  110. claims.ExpiresAt = time.Now().Add(dur).Unix()
  111.  
  112. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  113.  
  114. ss, err := token.SignedString(mySigningKey)
  115. if err != nil {
  116. return err
  117. }
  118. logResp.Token = ss
  119.  
  120. return nil
  121. }
  122.  
  123. // AuthenticateUser godoc
  124. func AuthenticateUser(data LoginRequest) (LoginResponse, error) {
  125.  
  126. var oper UsersCRM
  127. var login LoginResponse
  128. err := db.Model(&oper).
  129. Where("deleted = false AND Login = ?", data.Login).
  130. First()
  131. if err != nil {
  132. return login, err
  133. }
  134.  
  135. // Comparing the password with the hash
  136. err = bcrypt.CompareHashAndPassword([]byte(oper.Password), []byte(data.Password))
  137. if err != nil {
  138. return login, err
  139. }
  140.  
  141. err = expireUserTokens(oper.ID)
  142. if err != nil {
  143. return login, err
  144. }
  145.  
  146. err = login.newRefreshToken(oper.ID)
  147. if err != nil {
  148. return login, err
  149. }
  150.  
  151. err = login.GenerateJWT(oper)
  152. if err != nil {
  153. return login, err
  154. }
  155.  
  156. return login, nil
  157. }
  158.  
  159. func expireUserTokens(userID int) error {
  160.  
  161. var sessOld Sessions
  162.  
  163. _, err := db.Model(&sessOld).
  164. Set("refresh_token_used = ?", time.Now()).
  165. Where("user_id = ?", userID).
  166. Update()
  167.  
  168. if err != nil {
  169. return err
  170. }
  171. return nil
  172. }
  173.  
  174. func expireToken(token string) (UsersCRM, error) {
  175.  
  176. var oper UsersCRM
  177. var sessOld Sessions
  178.  
  179. _, err := db.Model(&sessOld).
  180. Set("refresh_token_used = ?", time.Now()).
  181. Where("refresh_token = ? AND CURRENT_TIMESTAMP < refresh_token_expired AND refresh_token_used is NULL", token).
  182. Returning("*").
  183. Update(&sessOld)
  184.  
  185. if err != nil {
  186. return oper, errors.New("Refresh token not found")
  187. }
  188.  
  189. err = db.Model(&oper).
  190. Where("deleted = false AND ID = ?", sessOld.UserID).
  191. First()
  192. if err != nil {
  193. return oper, err
  194. }
  195. return oper, nil
  196. }
  197.  
  198. // RefreshJWTToken godoc
  199. func RefreshJWTToken(token string) (LoginResponse, error) {
  200.  
  201. var newLogin LoginResponse
  202.  
  203. User, err := expireToken(token)
  204. if err != nil {
  205. return newLogin, err
  206. }
  207.  
  208. err = newLogin.newRefreshToken(User.ID)
  209. if err != nil {
  210. return newLogin, err
  211. }
  212.  
  213. err = newLogin.GenerateJWT(User)
  214. if err != nil {
  215. return newLogin, err
  216. }
  217.  
  218. return newLogin, nil
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement