2025-05-31 12:03:22 +08:00
|
|
|
package impl
|
2025-05-31 16:14:34 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
// }
|