feat: update template
This commit is contained in:
@@ -2,10 +2,13 @@ package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"server/internal/config"
|
||||
"server/internal/db"
|
||||
"server/internal/db/sqlc"
|
||||
"server/internal/middleware"
|
||||
"server/internal/model/auth"
|
||||
"server/internal/model/enum"
|
||||
"server/internal/model/request"
|
||||
"server/internal/model/response"
|
||||
"server/internal/pkg/cache"
|
||||
@@ -13,6 +16,7 @@ import (
|
||||
"server/internal/pkg/errs"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
@@ -46,15 +50,31 @@ func comparePasswordHash(passwordHash, inputPassword string) error {
|
||||
return bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(inputPassword))
|
||||
}
|
||||
|
||||
func (s *AuthService) GetAuthState(ctx context.Context, userID int32) (*sqlc.GetUserAuthStateRow, error) {
|
||||
// 过期时间使用最短窗口的那个 也就是access_token的过期时间
|
||||
return cache.GetOrSetJSON[*sqlc.GetUserAuthStateRow](ctx, s.cache, cachekey.UserAuthState(userID), s.cfg.JWTConfig.Expire, func() (*sqlc.GetUserAuthStateRow, error) {
|
||||
state, err := s.store.GetUserAuthState(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &state, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AuthService) discardRefreshToken(ctx context.Context, userID int32, hash string) {
|
||||
_ = s.cache.Del(ctx, cachekey.AuthRefresh(hash))
|
||||
_ = s.cache.SRem(ctx, cachekey.AuthRefreshUser(userID), hash)
|
||||
}
|
||||
|
||||
func (s *AuthService) Login(ctx context.Context, req request.LoginRequest) (*response.LoginResponse, error) {
|
||||
user, err := s.store.GetUserByAccount(ctx, req.Account)
|
||||
user, err := s.store.GetUser(ctx, sqlc.GetUserParams{Account: req.Account})
|
||||
|
||||
if err != nil {
|
||||
return nil, errs.ErrInvalidCredentials
|
||||
}
|
||||
|
||||
// 此处判断如果用户id不为1 且状态为0表示用户已被禁用
|
||||
if user.ID != 1 && user.Status == 0 {
|
||||
// 判断用户不为超管 且状态为0表示用户已被禁用
|
||||
if !auth.IsAdmin(user.ID) && user.Status == 0 {
|
||||
return nil, errs.ErrUserDisabled
|
||||
}
|
||||
|
||||
@@ -62,14 +82,14 @@ func (s *AuthService) Login(ctx context.Context, req request.LoginRequest) (*res
|
||||
return nil, errs.ErrInvalidCredentials
|
||||
}
|
||||
|
||||
accessToken, accessTokenExp, err := s.jwt.GenerateAccessToken(user.ID)
|
||||
accessToken, accessTokenExp, err := s.jwt.GenerateAccessToken(user.ID, user.TokenVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
refreshToken, err := s.jwt.GenerateRefreshToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
// 哈希
|
||||
@@ -79,28 +99,29 @@ func (s *AuthService) Login(ctx context.Context, req request.LoginRequest) (*res
|
||||
|
||||
refreshTokenExp := now.Add(s.cfg.JWTConfig.RefreshExpire)
|
||||
refreshTokenRecord := &auth.RefreshTokenRecord{
|
||||
UserID: user.ID,
|
||||
CreatedAt: now,
|
||||
ExpiresAt: refreshTokenExp,
|
||||
UserID: user.ID,
|
||||
TokenVersion: user.TokenVersion,
|
||||
CreatedAt: now,
|
||||
ExpiresAt: refreshTokenExp,
|
||||
}
|
||||
|
||||
// 存入redis
|
||||
err = s.cache.SetJSON(ctx, cachekey.AuthRefresh(hash), refreshTokenRecord, s.cfg.JWTConfig.RefreshExpire)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
// 反向索引
|
||||
err = s.cache.SAdd(ctx, cachekey.AuthRefreshUser(user.ID), hash)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
// 给反向索引设置过期时间 这个过期时间需要覆盖最后一个token的过期时间 所以用最新的就行了
|
||||
if err = s.cache.Expire(ctx, cachekey.AuthRefreshUser(user.ID), s.cfg.JWTConfig.RefreshExpire); err != nil {
|
||||
return nil, err
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
return &response.LoginResponse{
|
||||
@@ -121,26 +142,7 @@ func (s *AuthService) Logout(ctx context.Context, refreshToken string) error {
|
||||
}
|
||||
|
||||
if ok {
|
||||
// 清理反向索引
|
||||
if err = s.cache.SRem(ctx, cachekey.AuthRefreshUser(user.UserID), hash); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 清理当前登录的token
|
||||
if err = s.cache.Del(ctx, cachekey.AuthRefresh(hash)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *AuthService) GetActiveSysUser(ctx context.Context, id int32) error {
|
||||
var err error
|
||||
|
||||
_, err = s.store.GetActiveUserByID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
s.discardRefreshToken(ctx, user.UserID, hash)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -152,25 +154,45 @@ func (s *AuthService) RefreshToken(ctx context.Context, refreshToken string) (*r
|
||||
// 从redis中获取数据
|
||||
record, ok, err := cache.GetJSON[auth.RefreshTokenRecord](ctx, s.cache, cachekey.AuthRefresh(hash))
|
||||
if err != nil {
|
||||
return nil, errs.ErrInvalidRefreshToken
|
||||
// redis 错误返回500
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return nil, errs.ErrInvalidRefreshToken
|
||||
}
|
||||
|
||||
// 拿到用户信息
|
||||
authState, err := s.GetAuthState(ctx, record.UserID)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
// 用户已被删除 惰性清理
|
||||
s.discardRefreshToken(ctx, record.UserID, hash)
|
||||
return nil, errs.ErrInvalidRefreshToken
|
||||
}
|
||||
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
// 如果不是超级用户 需要判断用户状态
|
||||
if record.UserID != 1 {
|
||||
err = s.GetActiveSysUser(ctx, record.UserID)
|
||||
if err != nil {
|
||||
if !auth.IsAdmin(record.UserID) {
|
||||
if enum.Status(authState.Status) == enum.StatusDisabled {
|
||||
// 用户被禁用 清理redis缓存
|
||||
s.discardRefreshToken(ctx, record.UserID, hash)
|
||||
return nil, errs.ErrInvalidRefreshToken
|
||||
}
|
||||
}
|
||||
|
||||
// 比对token version 如果不相等 此时 惰性清理掉redis中的缓存
|
||||
if authState.TokenVersion != record.TokenVersion {
|
||||
s.discardRefreshToken(ctx, record.UserID, hash)
|
||||
return nil, errs.ErrInvalidRefreshToken
|
||||
}
|
||||
|
||||
// 获取新的access token
|
||||
accessToken, accessTokenExp, err := s.jwt.GenerateAccessToken(record.UserID)
|
||||
accessToken, accessTokenExp, err := s.jwt.GenerateAccessToken(record.UserID, authState.TokenVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errs.ErrInternalServer
|
||||
}
|
||||
|
||||
return &response.LoginResponse{
|
||||
|
||||
Reference in New Issue
Block a user