2025-05-31 16:14:34 +08:00

202 lines
5.3 KiB
Go

package impl
import (
"context"
"time"
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/token"
"github.com/infraboard/mcube/v2/desense"
"github.com/infraboard/mcube/v2/exception"
"github.com/infraboard/mcube/v2/ioc/config/datasource"
"github.com/infraboard/mcube/v2/types"
)
// 登录接口(颁发Token)
func (i *TokenServiceImpl) IssueToken(ctx context.Context, in *token.IssueTokenRequest) (*token.Token, error) {
// 颁发Token
// user/password
// ldap
// 飞书,企业微信 ...
issuer := token.GetIssuer(in.Issuer)
if issuer == nil {
return nil, exception.NewBadRequest("issuer %s no support", in.Issuer)
}
tk, err := issuer.IssueToken(ctx, in.Parameter)
if err != nil {
return nil, err
}
tk.SetIssuer(in.Issuer).SetSource(in.Source)
// 判断当前数据库有没有已经存在的Token
activeTokenQueryReq := token.NewQueryTokenRequest().
AddUserId(tk.UserId).
SetSource(in.Source).
SetActive(true)
tks, err := i.QueryToken(ctx, activeTokenQueryReq)
if err != nil {
return nil, err
}
switch in.Source {
// 每个端只能有1个活跃登录
case token.SOURCE_WEB, token.SOURCE_IOS, token.SOURCE_ANDROID, token.SOURCE_PC:
if tks.Len() > 0 {
i.log.Debug().Msgf("use exist active token: %s", desense.Default().DeSense(tk.AccessToken, "4", "3"))
return tks.Items[0], nil
}
case token.SOURCE_API:
if tks.Len() > int(i.MaxActiveApiToken) {
return nil, exception.NewBadRequest("max active api token overflow")
}
}
// 保持Token
if err := datasource.DBFromCtx(ctx).
Create(tk).
Error; err != nil {
return nil, err
}
return tk, nil
}
// 校验Token 是给内部中间层使用 身份校验层
func (i *TokenServiceImpl) ValiateToken(ctx context.Context, req *token.ValiateTokenRequest) (*token.Token, error) {
// 1. 查询Token (是不是我们这个系统颁发的)
tk := token.NewToken()
err := datasource.DBFromCtx(ctx).
Where("access_token = ?", req.AccessToken).
First(tk).
Error
if err != nil {
return nil, err
}
// 2.1 判断Ak是否过期
if err := tk.IsAccessTokenExpired(); err != nil {
// 判断刷新Token是否过期
if err := tk.IsRreshTokenExpired(); err != nil {
return nil, err
}
// 如果开启了自动刷新
if i.AutoRefresh {
tk.SetRefreshAt(time.Now())
tk.SetExpiredAtByDuration(i.refreshDuration, 4)
if err := datasource.DBFromCtx(ctx).Save(tk); err != nil {
i.log.Error().Msgf("auto refresh token error, %s", err.Error)
}
}
return nil, err
}
return tk, nil
}
func (i *TokenServiceImpl) DescribeToken(ctx context.Context, in *token.DescribeTokenRequest) (*token.Token, error) {
query := datasource.DBFromCtx(ctx)
switch in.DescribeBy {
case token.DESCRIBE_BY_ACCESS_TOKEN:
query = query.Where("access_token = ?", in.DescribeValue)
default:
return nil, exception.NewBadRequest("unspport describe type %s", in.DescribeValue)
}
tk := token.NewToken()
if err := query.First(tk).Error; err != nil {
return nil, err
}
return tk, nil
}
// 退出接口(销毁Token)
func (i *TokenServiceImpl) RevolkToken(ctx context.Context, in *token.RevolkTokenRequest) (*token.Token, error) {
tk, err := i.DescribeToken(ctx, token.NewDescribeTokenRequest(in.AccessToken))
if err != nil {
return nil, err
}
if err := tk.CheckRefreshToken(in.RefreshToken); err != nil {
return nil, err
}
tk.Lock(token.LOCK_TYPE_REVOLK, "user revolk token")
err = datasource.DBFromCtx(ctx).Model(&token.Token{}).
Where("access_token = ?", in.AccessToken).
Where("refresh_token = ?", in.RefreshToken).
Updates(tk.Status.ToMap()).
Error
if err != nil {
return nil, err
}
return tk, err
}
// 查询已经颁发出去的Token
func (i *TokenServiceImpl) QueryToken(ctx context.Context, in *token.QueryTokenRequest) (*types.Set[*token.Token], error) {
set := types.New[*token.Token]()
query := datasource.DBFromCtx(ctx).Model(&token.Token{})
if in.Active != nil {
if *in.Active {
query = query.
Where("lock_at IS NULL AND refresh_token_expired_at > ?", time.Now())
} else {
query = query.
Where("lock_at IS NOT NULL OR refresh_token_expired_at <= ?", time.Now())
}
}
if in.Source != nil {
query = query.Where("source = ?", *in.Source)
}
if len(in.UserIds) > 0 {
query = query.Where("user_id IN ?", in.UserIds)
}
// 查询总量
err := query.Count(&set.Total).Error
if err != nil {
return nil, err
}
err = query.
Order("issue_at desc").
Offset(int(in.ComputeOffset())).
Limit(int(in.PageSize)).
Find(&set.Items).
Error
if err != nil {
return nil, err
}
return set, nil
}
// 用户切换空间
// func (i *TokenServiceImpl) ChangeNamespce(ctx context.Context, in *token.ChangeNamespceRequest) (*token.Token, error) {
// set, err := i.policy.QueryNamespace(ctx, policy.NewQueryNamespaceRequest().SetUserId(in.UserId).SetNamespaceId(in.NamespaceId))
// if err != nil {
// return nil, err
// }
// ns := set.First()
// if ns == nil {
// return nil, exception.NewPermissionDeny("你没有该空间访问权限")
// }
// // 更新Token
// tk, err := i.DescribeToken(ctx, token.NewDescribeTokenRequest(in.AccessToken))
// if err != nil {
// return nil, err
// }
// tk.NamespaceId = ns.Id
// tk.NamespaceName = ns.Name
// // 保存状态
// if err := datasource.DBFromCtx(ctx).
// Updates(tk).
// Error; err != nil {
// return nil, err
// }
// return tk, nil
// }