165 lines
4.3 KiB
Go
165 lines
4.3 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"ultone/internal/database/cache"
|
|
"ultone/internal/database/db"
|
|
"ultone/internal/log"
|
|
"ultone/internal/model"
|
|
"ultone/internal/opt"
|
|
"ultone/internal/tool"
|
|
|
|
"github.com/loveuer/nf/nft/resp"
|
|
"github.com/spf13/cast"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type userController interface {
|
|
GetUser(ctx context.Context, id uint64) (*model.User, error)
|
|
GetUserByToken(ctx context.Context, token string) (*model.User, error)
|
|
CacheUser(ctx context.Context, user *model.User) error
|
|
CacheToken(ctx context.Context, token string, user *model.User) error
|
|
RmToken(ctx context.Context, token string) error
|
|
RmUserCache(ctx context.Context, id uint64) error
|
|
DeleteUser(ctx context.Context, target *model.User) error
|
|
}
|
|
|
|
type uc struct{}
|
|
|
|
var _ userController = (*uc)(nil)
|
|
|
|
func (u uc) GetUser(ctx context.Context, id uint64) (*model.User, error) {
|
|
var (
|
|
err error
|
|
target = new(model.User)
|
|
key = fmt.Sprintf("%s:user:id:%d", opt.CachePrefix, id)
|
|
bs []byte
|
|
)
|
|
|
|
if opt.EnableUserCache {
|
|
if bs, err = cache.Client.Get(tool.Timeout(3), key); err != nil {
|
|
log.Warn(ctx, "controller.GetUser: get user by cache key=%s err=%v", key, err)
|
|
goto ByDB
|
|
}
|
|
|
|
if err = json.Unmarshal(bs, target); err != nil {
|
|
log.Warn(ctx, "controller.GetUser: json unmarshal key=%s by=%s err=%v", key, string(bs), err)
|
|
goto ByDB
|
|
}
|
|
|
|
return target, nil
|
|
}
|
|
|
|
ByDB:
|
|
if err = db.Default.Session(tool.Timeout(3)).
|
|
Model(&model.User{}).
|
|
Where("id = ?", id).
|
|
Take(target).
|
|
Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
// tips: 公开项目需要考虑击穿处理
|
|
return target, resp.NewError(400, "目标不存在", err, nil)
|
|
}
|
|
|
|
return target, resp.NewError(500, "", err, nil)
|
|
}
|
|
|
|
if opt.EnableUserCache {
|
|
if err = u.CacheUser(ctx, target); err != nil {
|
|
log.Warn(ctx, "controller.GetUser: cache user key=%s err=%v", key, err)
|
|
}
|
|
}
|
|
|
|
return target, nil
|
|
}
|
|
|
|
func (u uc) GetUserByToken(ctx context.Context, token string) (*model.User, error) {
|
|
strs := strings.Split(token, ".")
|
|
if len(strs) != 3 {
|
|
return nil, fmt.Errorf("controller.GetUserByToken: jwt token invalid, token=%s", token)
|
|
}
|
|
|
|
key := fmt.Sprintf("%s:user:token:%s", opt.CachePrefix, strs[2])
|
|
bs, err := cache.Client.Get(tool.Timeout(3), key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
log.Debug(ctx, "controller.GetUserByToken: key=%s cache bytes=%s", key, string(bs))
|
|
|
|
userId := cast.ToUint64(string(bs))
|
|
if userId == 0 {
|
|
return nil, fmt.Errorf("controller.GetUserByToken: bs=%s cast to uint64 err", string(bs))
|
|
}
|
|
|
|
var op *model.User
|
|
|
|
if op, err = u.GetUser(ctx, userId); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return op, nil
|
|
}
|
|
|
|
func (u uc) CacheUser(ctx context.Context, target *model.User) error {
|
|
key := fmt.Sprintf("%s:user:id:%d", opt.CachePrefix, target.Id)
|
|
return cache.Client.Set(tool.Timeout(3), key, target)
|
|
}
|
|
|
|
func (u uc) CacheToken(ctx context.Context, token string, user *model.User) error {
|
|
strs := strings.Split(token, ".")
|
|
if len(strs) != 3 {
|
|
return fmt.Errorf("controller.CacheToken: jwt token invalid")
|
|
}
|
|
|
|
key := fmt.Sprintf("%s:user:token:%s", opt.CachePrefix, strs[2])
|
|
return cache.Client.SetEx(tool.Timeout(3), key, user.Id, opt.TokenTimeout)
|
|
}
|
|
|
|
func (u uc) RmToken(ctx context.Context, token string) error {
|
|
strs := strings.Split(token, ".")
|
|
if len(strs) != 3 {
|
|
return fmt.Errorf("controller.CacheToken: jwt token invalid")
|
|
}
|
|
|
|
key := fmt.Sprintf("%s:user:token:%s", opt.CachePrefix, strs[2])
|
|
return cache.Client.Del(tool.Timeout(3), key)
|
|
}
|
|
|
|
func (u uc) RmUserCache(ctx context.Context, id uint64) error {
|
|
key := fmt.Sprintf("%s:user:id:%d", opt.CachePrefix, id)
|
|
return cache.Client.Del(tool.Timeout(3), key)
|
|
}
|
|
|
|
func (u uc) DeleteUser(ctx context.Context, target *model.User) error {
|
|
var (
|
|
err error
|
|
now = time.Now()
|
|
username = fmt.Sprintf("%s@%d", target.Username, now.UnixMilli())
|
|
)
|
|
|
|
if err = db.Default.Session(tool.Timeout(5)).
|
|
Model(&model.User{}).
|
|
Where("id = ?", target.Id).
|
|
Updates(map[string]any{
|
|
"deleted_at": now.UnixMilli(),
|
|
"username": username,
|
|
}).Error; err != nil {
|
|
return resp.NewError(500, "", err, nil)
|
|
}
|
|
|
|
if opt.EnableUserCache {
|
|
if err = u.RmUserCache(ctx, target.Id); err != nil {
|
|
log.Warn(ctx, "controller.DeleteUser: rm user=%d cache err=%v", target.Id, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|