273 lines
8.1 KiB
Go
273 lines
8.1 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"time"
|
|
|
|
"lone-services/pkg/redis"
|
|
"lone-services/pkg/utils"
|
|
user "lone-services/rpc/user/pb"
|
|
"lone-services/services/user/internal/config"
|
|
"lone-services/services/user/internal/dao"
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
|
)
|
|
|
|
func okResponse(data any) *user.Response {
|
|
buf, _ := jsoniter.Marshal(data)
|
|
return &user.Response{
|
|
Code: utils.Ok.Code,
|
|
Msg: utils.Ok.Msg,
|
|
Data: string(buf),
|
|
}
|
|
}
|
|
|
|
func failResponse(status utils.Status) *user.Response {
|
|
return &user.Response{
|
|
Code: status.Code,
|
|
Msg: status.Msg,
|
|
}
|
|
}
|
|
|
|
func outResponse(status utils.Status, msg string) *user.Response {
|
|
return &user.Response{
|
|
Code: status.Code,
|
|
Msg: msg,
|
|
}
|
|
}
|
|
|
|
func toSession(info dao.UserRow, mobilePlain string, client *dao.Client) dao.UserLoginSession {
|
|
return dao.UserLoginSession{
|
|
Id: info.Id,
|
|
Name: info.Name,
|
|
Avatar: info.Avatar,
|
|
Mobile: mobilePlain,
|
|
Gender: info.Gender,
|
|
Birthday: info.Birthday.DateString(),
|
|
Type: client.Type,
|
|
ClientCode: client.Code,
|
|
}
|
|
}
|
|
|
|
func sessionClaims(session dao.UserLoginSession, tokenType string) utils.Claims {
|
|
return utils.Claims{
|
|
UserID: session.Id,
|
|
Name: session.Name,
|
|
Avatar: session.Avatar,
|
|
Mobile: session.Mobile,
|
|
Gender: session.Gender,
|
|
Birthday: session.Birthday,
|
|
Type: session.Type,
|
|
ClientCode: session.ClientCode,
|
|
BizId: session.BizId,
|
|
TokenType: tokenType,
|
|
}
|
|
}
|
|
|
|
func buildJwtToken(jwtAuth *config.JWTAuth, session dao.UserLoginSession) (dao.Token, error) {
|
|
accessToken, err := jwtAuth.Access.Sign(sessionClaims(session, utils.TokenTypeAccess))
|
|
if err != nil {
|
|
return dao.Token{}, err
|
|
}
|
|
refreshToken, err := jwtAuth.Refresh.Sign(sessionClaims(session, utils.TokenTypeRefresh))
|
|
if err != nil {
|
|
return dao.Token{}, err
|
|
}
|
|
return dao.Token{
|
|
AccessToken: accessToken,
|
|
RefreshToken: refreshToken,
|
|
Info: session,
|
|
}, nil
|
|
}
|
|
|
|
func loginCacheType(client *dao.Client) string {
|
|
if client == nil {
|
|
return utils.LoginTypeUser
|
|
}
|
|
switch client.SubjectType {
|
|
case dao.SubjectTypeSale:
|
|
return utils.LoginTypeSale
|
|
case dao.SubjectTypeStore:
|
|
return utils.LoginTypeStore
|
|
case dao.SubjectTypeUser:
|
|
return utils.LoginTypeUser
|
|
}
|
|
switch client.Type {
|
|
case dao.TypeSale:
|
|
return utils.LoginTypeSale
|
|
case dao.TypeStore:
|
|
return utils.LoginTypeStore
|
|
default:
|
|
return utils.LoginTypeUser
|
|
}
|
|
}
|
|
|
|
func setLogin(jwtAuth *config.JWTAuth, accessToken, refreshToken string, session dao.UserLoginSession, client *dao.Client) utils.Status {
|
|
accessExpire := time.Duration(jwtAuth.Access.TTL) * time.Second
|
|
refreshExpire := time.Duration(jwtAuth.Refresh.TTL) * time.Second
|
|
loginType := loginCacheType(client)
|
|
|
|
ctx := context.Background()
|
|
userStr, _ := jsoniter.Marshal(session)
|
|
|
|
redisKey := utils.GetLoginKey(loginType, accessToken)
|
|
if err := redis.Client.Set(ctx, redisKey, userStr, accessExpire).Err(); err != nil {
|
|
return utils.Fail
|
|
}
|
|
|
|
redisKeysKey := utils.GetLoginKeysKey(loginType, strconv.FormatInt(session.Id, utils.NumberTen))
|
|
var loginInfo utils.LoginRedis
|
|
if oldAuth, err := redis.Client.Get(ctx, redisKeysKey).Result(); err == nil {
|
|
_ = jsoniter.Unmarshal([]byte(oldAuth), &loginInfo)
|
|
if len(loginInfo.Token) > utils.NumberOne {
|
|
redis.Client.Del(ctx, utils.GetLoginKey(loginType, loginInfo.Token))
|
|
}
|
|
if len(loginInfo.Refresh) > utils.NumberOne {
|
|
redis.Client.Del(ctx, utils.GetLoginRefreshKey(loginType, loginInfo.Refresh))
|
|
}
|
|
}
|
|
|
|
loginInfo.Token = accessToken
|
|
loginInfo.Refresh = refreshToken
|
|
loginInfo.Info = userStr
|
|
newStr, _ := jsoniter.Marshal(loginInfo)
|
|
if err := redis.Client.Set(ctx, redisKeysKey, newStr, refreshExpire).Err(); err != nil {
|
|
return utils.Fail
|
|
}
|
|
refreshKey := utils.GetLoginRefreshKey(loginType, refreshToken)
|
|
if err := redis.Client.Set(ctx, refreshKey, strconv.FormatInt(session.Id, utils.NumberTen), refreshExpire).Err(); err != nil {
|
|
return utils.Fail
|
|
}
|
|
return utils.Ok
|
|
}
|
|
|
|
// tryRenewUserLogin 仅对 C 端(subject_type=user)复用已有 token 并续期;
|
|
// 门店/销售不走此逻辑。成功时更新会话中的 client_code/biz_id 等字段。
|
|
func tryRenewUserLogin(jwtAuth *config.JWTAuth, session dao.UserLoginSession, client *dao.Client) (*dao.Token, bool) {
|
|
if jwtAuth == nil || jwtAuth.Access == nil || jwtAuth.Refresh == nil {
|
|
return nil, false
|
|
}
|
|
if loginCacheType(client) != utils.LoginTypeUser {
|
|
return nil, false
|
|
}
|
|
if redis.Client == nil || session.Id < utils.NumberOne {
|
|
return nil, false
|
|
}
|
|
|
|
ctx := context.Background()
|
|
loginType := utils.LoginTypeUser
|
|
infoKey := utils.GetLoginKeysKey(loginType, strconv.FormatInt(session.Id, utils.NumberTen))
|
|
|
|
oldAuth, err := redis.Client.Get(ctx, infoKey).Result()
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
var loginInfo utils.LoginRedis
|
|
if err := jsoniter.Unmarshal([]byte(oldAuth), &loginInfo); err != nil {
|
|
return nil, false
|
|
}
|
|
if len(loginInfo.Token) <= utils.NumberOne || len(loginInfo.Refresh) <= utils.NumberOne {
|
|
return nil, false
|
|
}
|
|
|
|
tokenKey := utils.GetLoginKey(loginType, loginInfo.Token)
|
|
if _, err := redis.Client.Get(ctx, tokenKey).Result(); err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
accessExpire := time.Duration(jwtAuth.Access.TTL) * time.Second
|
|
refreshExpire := time.Duration(jwtAuth.Refresh.TTL) * time.Second
|
|
userStr, _ := jsoniter.Marshal(session)
|
|
|
|
if err := redis.Client.Set(ctx, tokenKey, userStr, accessExpire).Err(); err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
loginInfo.Info = userStr
|
|
newStr, _ := jsoniter.Marshal(loginInfo)
|
|
if err := redis.Client.Set(ctx, infoKey, newStr, refreshExpire).Err(); err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
refreshKey := utils.GetLoginRefreshKey(loginType, loginInfo.Refresh)
|
|
if err := redis.Client.Set(ctx, refreshKey, strconv.FormatInt(session.Id, utils.NumberTen), refreshExpire).Err(); err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
return &dao.Token{
|
|
AccessToken: loginInfo.Token,
|
|
RefreshToken: loginInfo.Refresh,
|
|
Info: session,
|
|
}, true
|
|
}
|
|
|
|
func remaponUserLoginAfterMerge(jwtAuth *config.JWTAuth, fromUserId, toUserId int64, session dao.UserLoginSession) error {
|
|
if jwtAuth == nil || jwtAuth.Access == nil || jwtAuth.Refresh == nil {
|
|
return nil
|
|
}
|
|
if redis.Client == nil || fromUserId < utils.NumberOne || toUserId < utils.NumberOne {
|
|
return nil
|
|
}
|
|
if session.Id != toUserId {
|
|
session.Id = toUserId
|
|
}
|
|
|
|
ctx := context.Background()
|
|
loginType := utils.LoginTypeUser
|
|
fromInfoKey := utils.GetLoginKeysKey(loginType, strconv.FormatInt(fromUserId, utils.NumberTen))
|
|
|
|
oldAuth, err := redis.Client.Get(ctx, fromInfoKey).Result()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
var loginInfo utils.LoginRedis
|
|
if err := jsoniter.Unmarshal([]byte(oldAuth), &loginInfo); err != nil {
|
|
return err
|
|
}
|
|
if len(loginInfo.Token) <= utils.NumberOne {
|
|
return nil
|
|
}
|
|
|
|
accessExpire := time.Duration(jwtAuth.Access.TTL) * time.Second
|
|
refreshExpire := time.Duration(jwtAuth.Refresh.TTL) * time.Second
|
|
userStr, _ := jsoniter.Marshal(session)
|
|
|
|
tokenKey := utils.GetLoginKey(loginType, loginInfo.Token)
|
|
if err := redis.Client.Set(ctx, tokenKey, userStr, accessExpire).Err(); err != nil {
|
|
return err
|
|
}
|
|
|
|
toInfoKey := utils.GetLoginKeysKey(loginType, strconv.FormatInt(toUserId, utils.NumberTen))
|
|
if oldTo, err := redis.Client.Get(ctx, toInfoKey).Result(); err == nil {
|
|
var toLogin utils.LoginRedis
|
|
if uErr := jsoniter.Unmarshal([]byte(oldTo), &toLogin); uErr == nil {
|
|
if len(toLogin.Token) > utils.NumberOne && toLogin.Token != loginInfo.Token {
|
|
_ = redis.Client.Del(ctx, utils.GetLoginKey(loginType, toLogin.Token)).Err()
|
|
}
|
|
if len(toLogin.Refresh) > utils.NumberOne && toLogin.Refresh != loginInfo.Refresh {
|
|
_ = redis.Client.Del(ctx, utils.GetLoginRefreshKey(loginType, toLogin.Refresh)).Err()
|
|
}
|
|
}
|
|
}
|
|
|
|
loginInfo.Info = userStr
|
|
newStr, _ := jsoniter.Marshal(loginInfo)
|
|
if err := redis.Client.Set(ctx, toInfoKey, newStr, refreshExpire).Err(); err != nil {
|
|
return err
|
|
}
|
|
if fromUserId != toUserId {
|
|
_ = redis.Client.Del(ctx, fromInfoKey).Err()
|
|
}
|
|
|
|
if len(loginInfo.Refresh) > utils.NumberOne {
|
|
refreshKey := utils.GetLoginRefreshKey(loginType, loginInfo.Refresh)
|
|
if err := redis.Client.Set(ctx, refreshKey, strconv.FormatInt(toUserId, utils.NumberTen), refreshExpire).Err(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|