完善登录逻辑,登录接口统一到 /token

This commit is contained in:
2025-04-23 19:01:08 +08:00
parent b181864a2f
commit 1374757eab
28 changed files with 404 additions and 266 deletions

View File

@@ -22,6 +22,12 @@
- [ ] Limiter - [ ] Limiter
- [ ] Compress - [ ] Compress
使用 fiber 自带 validator 进行参数验证
增加 domain 层,缓解同包字段过长的问题
移动端适配
授权过期跳转登录,成功后返回原链接 授权过期跳转登录,成功后返回原链接
错误处理类型转换失败问题 错误处理类型转换失败问题

View File

@@ -186,6 +186,7 @@ create table client (
grant_code bool not null default false, grant_code bool not null default false,
grant_client bool not null default false, grant_client bool not null default false,
grant_refresh bool not null default false, grant_refresh bool not null default false,
grant_password bool not null default false,
spec int not null, spec int not null,
name varchar(255) not null, name varchar(255) not null,
icon varchar(255), icon varchar(255),
@@ -209,6 +210,7 @@ comment on column client.redirect_uri is 'OAuth2 重定向URI';
comment on column client.grant_code is '允许授权码授予'; comment on column client.grant_code is '允许授权码授予';
comment on column client.grant_client is '允许客户端凭证授予'; comment on column client.grant_client is '允许客户端凭证授予';
comment on column client.grant_refresh is '允许刷新令牌授予'; comment on column client.grant_refresh is '允许刷新令牌授予';
comment on column client.grant_password is '允许密码授予';
comment on column client.spec is '安全规范0-web1-native2-browser'; comment on column client.spec is '安全规范0-web1-native2-browser';
comment on column client.name is '名称'; comment on column client.name is '名称';
comment on column client.icon is '图标URL'; comment on column client.icon is '图标URL';

View File

@@ -76,7 +76,6 @@ func Permit(types []services.PayloadType, permissions ...string) fiber.Handler {
return c.Next() return c.Next()
} }
} }
func PermitAll(permissions ...string) fiber.Handler { func PermitAll(permissions ...string) fiber.Handler {
@@ -88,14 +87,6 @@ func PermitAll(permissions ...string) fiber.Handler {
}, permissions...) }, permissions...)
} }
// PermitUser 创建针对单个路由的鉴权中间件
func PermitUser(permissions ...string) fiber.Handler {
return Permit([]services.PayloadType{
services.PayloadUser,
services.PayloadAdmin,
}, permissions...)
}
func PermitDevice(permissions ...string) fiber.Handler { func PermitDevice(permissions ...string) fiber.Handler {
return Permit([]services.PayloadType{ return Permit([]services.PayloadType{
services.PayloadClientPublic, services.PayloadClientPublic,
@@ -104,74 +95,6 @@ func PermitDevice(permissions ...string) fiber.Handler {
}, permissions...) }, permissions...)
} }
func PermitPublic(permissions ...string) fiber.Handler {
return Permit([]services.PayloadType{
services.PayloadClientPublic,
services.PayloadAdmin,
}, permissions...)
}
func PermitConfidential(permissions ...string) fiber.Handler {
return Permit([]services.PayloadType{
services.PayloadClientConfidential,
services.PayloadAdmin,
}, permissions...)
}
func authBearer(ctx context.Context, token string) (*services.AuthContext, error) {
auth, err := services.Session.Find(ctx, token)
if err != nil {
slog.Debug(err.Error())
return nil, err
}
return auth, nil
}
func authBasic(ctx context.Context, token string) (*services.AuthContext, error) {
// 解析 Basic 认证信息
var base, err = base64.URLEncoding.DecodeString(token)
if err != nil {
slog.Debug(err.Error())
return nil, err
}
var split = strings.Split(string(base), ":")
if len(split) != 2 {
msg := "无法解析 Basic 认证信息"
slog.Debug(msg)
return nil, errors.New(msg)
}
var clientID = split[0]
// 获取客户端信息
client, err := q.Client.
Where(
q.Client.ClientID.Eq(clientID),
q.Client.Spec.Eq(0),
q.Client.GrantClient.Is(true),
q.Client.Status.Eq(1)).
Take()
if err != nil {
return nil, err
}
// todo 查询客户端关联权限
// 组织授权信息(一次性请求)
return &services.AuthContext{
Payload: services.Payload{
Id: client.ID,
Type: services.PayloadClientConfidential,
Name: client.Name,
Avatar: client.Icon,
},
Permissions: nil,
Metadata: nil,
}, nil
}
func Protect(c *fiber.Ctx, types []services.PayloadType, permissions []string) (*services.AuthContext, error) { func Protect(c *fiber.Ctx, types []services.PayloadType, permissions []string) (*services.AuthContext, error) {
// 获取令牌 // 获取令牌
var header = c.Get("Authorization") var header = c.Get("Authorization")
@@ -216,3 +139,57 @@ func Protect(c *fiber.Ctx, types []services.PayloadType, permissions []string) (
return auth, nil return auth, nil
} }
func authBearer(ctx context.Context, token string) (*services.AuthContext, error) {
auth, err := services.Session.Find(ctx, token)
if err != nil {
slog.Debug(err.Error())
return nil, err
}
return auth, nil
}
func authBasic(_ context.Context, token string) (*services.AuthContext, error) {
// 解析 Basic 认证信息
var base, err = base64.URLEncoding.DecodeString(token)
if err != nil {
slog.Debug(err.Error())
return nil, err
}
var split = strings.Split(string(base), ":")
if len(split) != 2 {
msg := "无法解析 Basic 认证信息"
slog.Debug(msg)
return nil, errors.New(msg)
}
var clientID = split[0]
// 获取客户端信息
client, err := q.Client.
Where(
q.Client.ClientID.Eq(clientID),
q.Client.Spec.Eq(0),
q.Client.GrantClient.Is(true),
q.Client.Status.Eq(1)).
Take()
if err != nil {
return nil, err
}
// todo 查询客户端关联权限
// 组织授权信息(一次性请求)
return &services.AuthContext{
Payload: services.Payload{
Id: client.ID,
Type: services.PayloadClientConfidential,
Name: client.Name,
Avatar: client.Icon,
},
Permissions: nil,
Metadata: nil,
}, nil
}

View File

@@ -51,7 +51,7 @@ func ListBill(c *fiber.Ctx) error {
do = do.Where(q.Bill.BillNo.Eq(*req.BillNo)) do = do.Where(q.Bill.BillNo.Eq(*req.BillNo))
} }
bills, err := do.Debug(). bills, err := do.
Preload(q.Bill.Resource, q.Bill.Trade, q.Bill.Refund). Preload(q.Bill.Resource, q.Bill.Trade, q.Bill.Refund).
Preload(q.Bill.Resource.Pss). Preload(q.Bill.Resource.Pss).
Order(q.Bill.CreatedAt.Desc()). Order(q.Bill.CreatedAt.Desc()).

View File

@@ -3,9 +3,10 @@ package handlers
import ( import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"platform/web/models" "log/slog"
m "platform/web/models"
q "platform/web/queries" q "platform/web/queries"
"platform/web/services" s "platform/web/services"
"strings" "strings"
"time" "time"
@@ -17,22 +18,42 @@ import (
// region Token // region Token
type TokenReq struct { type TokenReq struct {
GrantType s.OauthGrantType `json:"grant_type" form:"grant_type"`
ClientID string `json:"client_id" form:"client_id"` ClientID string `json:"client_id" form:"client_id"`
ClientSecret string `json:"client_secret" form:"client_secret"` ClientSecret string `json:"client_secret" form:"client_secret"`
GrantType TokenGrantType `json:"grant_type" form:"grant_type"` Scope string `json:"scope" form:"scope"`
TokenReqCode
TokenReqClient
TokenReqRefresh
TokenReqPassword
}
type TokenReqCode struct {
Code string `json:"code" form:"code"` Code string `json:"code" form:"code"`
RedirectURI string `json:"redirect_uri" form:"redirect_uri"` RedirectURI string `json:"redirect_uri" form:"redirect_uri"`
CodeVerifier string `json:"code_verifier" form:"code_verifier"` CodeVerifier string `json:"code_verifier" form:"code_verifier"`
}
type TokenReqClient struct {
}
type TokenReqRefresh struct {
RefreshToken string `json:"refresh_token" form:"refresh_token"` RefreshToken string `json:"refresh_token" form:"refresh_token"`
Scope string `json:"scope" form:"scope"` }
type TokenReqPassword struct {
LoginType s.OauthGrantLoginType `json:"login_type" form:"login_type"`
Username string `json:"username" form:"username"`
Password string `json:"password" form:"password"`
Remember bool `json:"remember" form:"remember"`
} }
type TokenResp struct { type TokenResp struct {
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token,omitempty"` RefreshToken string `json:"refresh_token,omitempty"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"` TokenType string `json:"token_type"`
Scope string `json:"scope,omitempty"` Scope string `json:"scope,omitempty"`
ExpiresIn int `json:"expires_in"`
} }
type TokenErrResp struct { type TokenErrResp struct {
@@ -40,57 +61,57 @@ type TokenErrResp struct {
Description string `json:"error_description,omitempty"` Description string `json:"error_description,omitempty"`
} }
type TokenGrantType string
const (
AuthorizationCode = TokenGrantType("authorization_code")
ClientCredentials = TokenGrantType("client_credentials")
RefreshToken = TokenGrantType("refresh_token")
)
// Token 处理 OAuth2.0 授权请求 // Token 处理 OAuth2.0 授权请求
func Token(c *fiber.Ctx) error { func Token(c *fiber.Ctx) error {
// 验证请求参数 // 验证请求参数
req := new(TokenReq) req := new(TokenReq)
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {
return sendError(c, services.ErrOauthInvalidRequest, "无法解析请求参数") return sendError(c, s.ErrOauthInvalidRequest, "无法解析请求参数")
} }
if req.GrantType == "" { if req.GrantType == "" {
return sendError(c, services.ErrOauthInvalidRequest, "缺少必要参数grant_type") return sendError(c, s.ErrOauthInvalidRequest, "缺少必要参数grant_type")
} }
slog.Debug("oauth token", slog.String("grant_type",
string(req.GrantType)),
slog.String("client_id", req.ClientID),
)
// 基于授权类型处理请求 // 基于授权类型处理请求
switch req.GrantType { switch req.GrantType {
case AuthorizationCode: case s.OauthGrantTypeAuthorizationCode:
return authorizationCode(c, req) return authorizationCode(c, req)
case ClientCredentials: case s.OauthGrantTypeClientCredentials:
return clientCredentials(c, req) return clientCredentials(c, req)
case RefreshToken: case s.OauthGrantTypeRefreshToken:
return refreshToken(c, req) return refreshToken(c, req)
case s.OauthGrantTypePassword:
return password(c, req)
default: default:
return sendError(c, services.ErrOauthUnsupportedGrantType) return sendError(c, s.ErrOauthUnsupportedGrantType)
} }
} }
// 授权码 // 授权码
func authorizationCode(c *fiber.Ctx, req *TokenReq) error { func authorizationCode(c *fiber.Ctx, req *TokenReq) error {
if req.Code == "" { if req.Code == "" {
return sendError(c, services.ErrOauthInvalidRequest, "缺少必要参数code") return sendError(c, s.ErrOauthInvalidRequest, "缺少必要参数code")
} }
client, err := protect(c, services.GrantTypeAuthorizationCode, req.ClientID, req.ClientSecret) client, err := protect(c, s.OauthGrantTypeAuthorizationCode, req.ClientID, req.ClientSecret)
if err != nil { if err != nil {
return sendError(c, err) return sendError(c, err)
} }
token, err := services.Auth.OauthAuthorizationCode(c.Context(), client, req.Code, req.RedirectURI, req.CodeVerifier) token, err := s.Auth.OauthAuthorizationCode(c.Context(), client, req.Code, req.RedirectURI, req.CodeVerifier)
if err != nil { if err != nil {
return sendError(c, err.(services.AuthServiceOauthError)) return sendError(c, err.(s.AuthServiceOauthError))
} }
return sendSuccess(c, token) return sendSuccess(c, token)
@@ -98,15 +119,15 @@ func authorizationCode(c *fiber.Ctx, req *TokenReq) error {
// 客户端凭证 // 客户端凭证
func clientCredentials(c *fiber.Ctx, req *TokenReq) error { func clientCredentials(c *fiber.Ctx, req *TokenReq) error {
client, err := protect(c, services.GrantTypeClientCredentials, req.ClientID, req.ClientSecret) client, err := protect(c, s.OauthGrantTypeClientCredentials, req.ClientID, req.ClientSecret)
if err != nil { if err != nil {
return sendError(c, err) return sendError(c, err)
} }
scope := strings.Split(req.Scope, ",") scope := strings.Split(req.Scope, ",")
token, err := services.Auth.OauthClientCredentials(c.Context(), client, scope...) token, err := s.Auth.OauthClientCredentials(c.Context(), client, scope...)
if err != nil { if err != nil {
return sendError(c, err.(services.AuthServiceOauthError)) return sendError(c, err.(s.AuthServiceOauthError))
} }
return sendSuccess(c, token) return sendSuccess(c, token)
@@ -115,19 +136,19 @@ func clientCredentials(c *fiber.Ctx, req *TokenReq) error {
// 刷新令牌 // 刷新令牌
func refreshToken(c *fiber.Ctx, req *TokenReq) error { func refreshToken(c *fiber.Ctx, req *TokenReq) error {
if req.RefreshToken == "" { if req.RefreshToken == "" {
return sendError(c, services.ErrOauthInvalidRequest, "缺少必要参数refresh_token") return sendError(c, s.ErrOauthInvalidRequest, "缺少必要参数refresh_token")
} }
client, err := protect(c, services.GrantTypeRefreshToken, req.ClientID, req.ClientSecret) client, err := protect(c, s.OauthGrantTypeRefreshToken, req.ClientID, req.ClientSecret)
if err != nil { if err != nil {
return sendError(c, err) return sendError(c, err)
} }
scope := strings.Split(req.Scope, ",") scope := strings.Split(req.Scope, ",")
token, err := services.Auth.OauthRefreshToken(c.Context(), client, req.RefreshToken, scope) token, err := s.Auth.OauthRefreshToken(c.Context(), client, req.RefreshToken, scope)
if err != nil { if err != nil {
if errors.Is(err, services.ErrInvalidToken) { if errors.Is(err, s.ErrInvalidToken) {
return sendError(c, services.ErrOauthInvalidGrant) return sendError(c, s.ErrOauthInvalidGrant)
} }
return sendError(c, err) return sendError(c, err)
} }
@@ -135,8 +156,108 @@ func refreshToken(c *fiber.Ctx, req *TokenReq) error {
return sendSuccess(c, token) return sendSuccess(c, token)
} }
func password(c *fiber.Ctx, req *TokenReq) error {
if req.LoginType == "" {
return sendError(c, s.ErrOauthInvalidRequest, "缺少必要参数password_type")
}
if req.Username == "" {
return sendError(c, s.ErrOauthInvalidRequest, "缺少必要参数username")
}
if req.Password == "" {
return sendError(c, s.ErrOauthInvalidRequest, "缺少必要参数password")
}
// 验证客户端凭证
_, err := protect(c, s.OauthGrantTypePassword, req.ClientID, req.ClientSecret)
if err != nil {
return sendError(c, err)
}
// 验证验证码
err = s.Verifier.VerifySms(c.Context(), req.Username, req.Password)
if err != nil {
if errors.Is(err, s.ErrVerifierServiceInvalid) {
return fiber.NewError(fiber.StatusBadRequest, "验证码错误")
}
return err
}
// 查找用户
var user *m.User
err = q.Q.Transaction(func(tx *q.Query) error {
switch req.LoginType {
case s.OauthGrantPasswordTypePhoneCode:
user, err = tx.User.Where(tx.User.Phone.Eq(req.Username)).Take()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
case s.OauthGrantPasswordTypeEmailCode:
user, err = tx.User.Where(tx.User.Email.Eq(req.Username)).Take()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
case s.OauthGrantPasswordTypePassword:
user, err = tx.User.
Where(tx.User.Or(
tx.User.Phone.Eq(req.Username),
tx.User.Email.Eq(req.Username),
tx.User.Username.Eq(req.Username),
)).
Take()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
default:
return sendError(c, s.ErrOauthInvalidRequest, "无效的登录类型")
}
// 如果用户不存在,初始化用户 todo 初始化默认权限信息
if user == nil {
user = &m.User{
Phone: req.Username,
Username: req.Username,
}
}
// 更新用户的登录时间
user.LastLogin = time.Now()
user.LastLoginHost = c.IP()
user.LastLoginAgent = c.Get("User-Agent")
if err := tx.User.Omit(q.User.AdminID).Save(user); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
// 保存到会话
auth := s.AuthContext{
Payload: s.Payload{
Id: user.ID,
Type: s.PayloadUser,
Name: user.Name,
Avatar: user.Avatar,
},
}
duration := s.DefaultSessionConfig
if !req.Remember {
duration.RefreshTokenDuration = 0
}
token, err := s.Session.Create(c.Context(), auth)
if err != nil {
return err
}
return sendSuccess(c, token)
}
// 检查客户端凭证 // 检查客户端凭证
func protect(c *fiber.Ctx, grant services.GrantType, clientId, clientSecret string) (*models.Client, error) { func protect(c *fiber.Ctx, grant s.OauthGrantType, clientId, clientSecret string) (*m.Client, error) {
header := c.Get("Authorization") header := c.Get("Authorization")
if header != "" { if header != "" {
basic := strings.TrimPrefix(header, "Basic ") basic := strings.TrimPrefix(header, "Basic ")
@@ -155,44 +276,48 @@ func protect(c *fiber.Ctx, grant services.GrantType, clientId, clientSecret stri
// 查找客户端 // 查找客户端
if clientId == "" { if clientId == "" {
return nil, services.ErrOauthInvalidRequest return nil, s.ErrOauthInvalidRequest
} }
client, err := q.Client.Where(q.Client.ClientID.Eq(clientId)).Take() client, err := q.Client.Where(q.Client.ClientID.Eq(clientId)).Take()
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, services.ErrOauthInvalidClient return nil, s.ErrOauthInvalidClient
} }
return nil, err return nil, err
} }
// 验证客户端状态 // 验证客户端状态
if client.Status != 1 { if client.Status != 1 {
return nil, services.ErrOauthUnauthorizedClient return nil, s.ErrOauthUnauthorizedClient
} }
// 验证授权类型 // 验证授权类型
switch grant { switch grant {
case services.GrantTypeAuthorizationCode: case s.OauthGrantTypeAuthorizationCode:
if !client.GrantCode { if !client.GrantCode {
return nil, services.ErrOauthUnauthorizedClient return nil, s.ErrOauthUnauthorizedClient
} }
case services.GrantTypeClientCredentials: case s.OauthGrantTypeClientCredentials:
if !client.GrantClient || client.Spec != 0 { if !client.GrantClient || client.Spec != 0 {
return nil, services.ErrOauthUnauthorizedClient return nil, s.ErrOauthUnauthorizedClient
} }
case services.GrantTypeRefreshToken: case s.OauthGrantTypeRefreshToken:
if !client.GrantRefresh { if !client.GrantRefresh {
return nil, services.ErrOauthUnauthorizedClient return nil, s.ErrOauthUnauthorizedClient
}
case s.OauthGrantTypePassword:
if !client.GrantPassword {
return nil, s.ErrOauthUnauthorizedClient
} }
} }
// 如果客户端是 confidential验证 client_secret失败返回错误 // 如果客户端是 confidential验证 client_secret失败返回错误
if client.Spec == 0 { if client.Spec == 0 {
if clientSecret == "" { if clientSecret == "" {
return nil, services.ErrOauthInvalidRequest return nil, s.ErrOauthInvalidRequest
} }
if bcrypt.CompareHashAndPassword([]byte(client.ClientSecret), []byte(clientSecret)) != nil { if bcrypt.CompareHashAndPassword([]byte(client.ClientSecret), []byte(clientSecret)) != nil {
return nil, services.ErrOauthInvalidClient return nil, s.ErrOauthInvalidClient
} }
} }
@@ -200,7 +325,7 @@ func protect(c *fiber.Ctx, grant services.GrantType, clientId, clientSecret stri
} }
// 发送成功响应 // 发送成功响应
func sendSuccess(c *fiber.Ctx, details *services.TokenDetails) error { func sendSuccess(c *fiber.Ctx, details *s.TokenDetails) error {
return c.JSON(TokenResp{ return c.JSON(TokenResp{
AccessToken: details.AccessToken, AccessToken: details.AccessToken,
TokenType: "Bearer", TokenType: "Bearer",
@@ -211,23 +336,23 @@ func sendSuccess(c *fiber.Ctx, details *services.TokenDetails) error {
// 发送错误响应 // 发送错误响应
func sendError(c *fiber.Ctx, err error, description ...string) error { func sendError(c *fiber.Ctx, err error, description ...string) error {
var sErr services.AuthServiceOauthError var sErr s.AuthServiceOauthError
if errors.As(err, &sErr) { if errors.As(err, &sErr) {
status := fiber.StatusBadRequest status := fiber.StatusBadRequest
var desc string var desc string
switch { switch {
case errors.Is(sErr, services.ErrOauthInvalidRequest): case errors.Is(sErr, s.ErrOauthInvalidRequest):
desc = "无效的请求" desc = "无效的请求"
case errors.Is(sErr, services.ErrOauthInvalidClient): case errors.Is(sErr, s.ErrOauthInvalidClient):
status = fiber.StatusUnauthorized status = fiber.StatusUnauthorized
desc = "无效的客户端凭证" desc = "无效的客户端凭证"
case errors.Is(sErr, services.ErrOauthInvalidGrant): case errors.Is(sErr, s.ErrOauthInvalidGrant):
desc = "无效的授权凭证" desc = "无效的授权凭证"
case errors.Is(sErr, services.ErrOauthInvalidScope): case errors.Is(sErr, s.ErrOauthInvalidScope):
desc = "无效的授权范围" desc = "无效的授权范围"
case errors.Is(sErr, services.ErrOauthUnauthorizedClient): case errors.Is(sErr, s.ErrOauthUnauthorizedClient):
desc = "未授权的客户端" desc = "未授权的客户端"
case errors.Is(sErr, services.ErrOauthUnsupportedGrantType): case errors.Is(sErr, s.ErrOauthUnsupportedGrantType):
desc = "不支持的授权类型" desc = "不支持的授权类型"
} }
if len(description) > 0 { if len(description) > 0 {

View File

@@ -2,6 +2,7 @@ package handlers
import ( import (
"errors" "errors"
"platform/web/auth"
"platform/web/services" "platform/web/services"
"regexp" "regexp"
"strconv" "strconv"
@@ -16,6 +17,13 @@ type VerifierReq struct {
func SmsCode(c *fiber.Ctx) error { func SmsCode(c *fiber.Ctx) error {
_, err := auth.Protect(c, []services.PayloadType{
services.PayloadClientConfidential,
}, []string{})
if err != nil {
return err
}
// 解析请求参数 // 解析请求参数
req := new(VerifierReq) req := new(VerifierReq)
if err := c.BodyParser(req); err != nil { if err := c.BodyParser(req); err != nil {

View File

@@ -20,12 +20,12 @@ type Bill struct {
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
TradeID int32 `gorm:"column:trade_id" json:"trade_id"` TradeID int32 `gorm:"column:trade_id;comment:订单ID" json:"trade_id"` // 订单ID
ResourceID int32 `gorm:"column:resource_id" json:"resource_id"` ResourceID int32 `gorm:"column:resource_id;comment:套餐ID" json:"resource_id"` // 套餐ID
Type int32 `gorm:"column:type;not null" json:"type"` Type int32 `gorm:"column:type;not null;comment:账单类型0-充值1-消费2-退款" json:"type"` // 账单类型0-充值1-消费2-退款
BillNo string `gorm:"column:bill_no;not null" json:"bill_no"` BillNo string `gorm:"column:bill_no;not null;comment:易读账单号" json:"bill_no"` // 易读账单号
RefundID int32 `gorm:"column:refund_id" json:"refund_id"` RefundID int32 `gorm:"column:refund_id;comment:退款ID" json:"refund_id"` // 退款ID
Amount float64 `gorm:"column:amount;not null" json:"amount"` Amount float64 `gorm:"column:amount;not null;comment:账单金额" json:"amount"` // 账单金额
Trade *Trade `gorm:"foreignKey:TradeID" json:"trade"` Trade *Trade `gorm:"foreignKey:TradeID" json:"trade"`
Refund *Refund `gorm:"foreignKey:RefundID" json:"refund"` Refund *Refund `gorm:"foreignKey:RefundID" json:"refund"`
Resource *Resource `gorm:"foreignKey:ResourceID" json:"resource"` Resource *Resource `gorm:"foreignKey:ResourceID" json:"resource"`

View File

@@ -31,7 +31,7 @@ type Channel struct {
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ProxyHost string `gorm:"column:proxy_host;not null" json:"proxy_host"` ProxyHost string `gorm:"column:proxy_host;not null" json:"proxy_host"`
Protocol int32 `gorm:"column:protocol" json:"protocol"` Protocol int32 `gorm:"column:protocol;comment:协议类型1-http2-https3-socks5" json:"protocol"` // 协议类型1-http2-https3-socks5
} }
// TableName Channel's table name // TableName Channel's table name

View File

@@ -28,6 +28,7 @@ type Client struct {
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
GrantPassword bool `gorm:"column:grant_password;not null" json:"grant_password"`
} }
// TableName Client's table name // TableName Client's table name

View File

@@ -15,17 +15,17 @@ const TableNameCoupon = "coupon"
// Coupon mapped from table <coupon> // Coupon mapped from table <coupon>
type Coupon struct { type Coupon struct {
ExpireAt time.Time `gorm:"column:expire_at" json:"expire_at"` ExpireAt time.Time `gorm:"column:expire_at;comment:过期时间" json:"expire_at"` // 过期时间
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP" json:"created_at"` CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP" json:"updated_at"` UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at" json:"deleted_at"` DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:优惠券ID" json:"id"` // 优惠券ID
UserID int32 `gorm:"column:user_id" json:"user_id"` UserID int32 `gorm:"column:user_id;comment:用户ID" json:"user_id"` // 用户ID
Status int32 `gorm:"column:status;not null" json:"status"` Status int32 `gorm:"column:status;not null;comment:优惠券状态0-未使用1-已使用2-已过期" json:"status"` // 优惠券状态0-未使用1-已使用2-已过期
Code string `gorm:"column:code;not null" json:"code"` Code string `gorm:"column:code;not null;comment:优惠券代码" json:"code"` // 优惠券代码
Remark string `gorm:"column:remark" json:"remark"` Remark string `gorm:"column:remark;comment:优惠券备注" json:"remark"` // 优惠券备注
Amount float64 `gorm:"column:amount;not null" json:"amount"` Amount float64 `gorm:"column:amount;not null;comment:优惠券金额" json:"amount"` // 优惠券金额
MinAmount float64 `gorm:"column:min_amount;not null" json:"min_amount"` MinAmount float64 `gorm:"column:min_amount;not null;comment:最低消费金额" json:"min_amount"` // 最低消费金额
} }
// TableName Coupon's table name // TableName Coupon's table name

View File

@@ -22,13 +22,13 @@ type Node struct {
City string `gorm:"column:city;not null;comment:城市" json:"city"` // 城市 City string `gorm:"column:city;not null;comment:城市" json:"city"` // 城市
ProxyID int32 `gorm:"column:proxy_id;comment:代理ID" json:"proxy_id"` // 代理ID ProxyID int32 `gorm:"column:proxy_id;comment:代理ID" json:"proxy_id"` // 代理ID
ProxyPort int32 `gorm:"column:proxy_port;comment:代理端口" json:"proxy_port"` // 代理端口 ProxyPort int32 `gorm:"column:proxy_port;comment:代理端口" json:"proxy_port"` // 代理端口
Status int32 `gorm:"column:status;not null;comment:节点状态:1-正常,0-离线" json:"status"` // 节点状态:1-正常,0-离线 Status int32 `gorm:"column:status;not null;comment:节点状态0-离线1-正常" json:"status"` // 节点状态0-离线1-正常
Rtt int32 `gorm:"column:rtt;comment:延迟" json:"rtt"` // 延迟 Rtt int32 `gorm:"column:rtt;comment:延迟" json:"rtt"` // 延迟
Loss int32 `gorm:"column:loss;comment:丢包率" json:"loss"` // 丢包率 Loss int32 `gorm:"column:loss;comment:丢包率" json:"loss"` // 丢包率
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
Isp int32 `gorm:"column:isp;not null" json:"isp"` Isp int32 `gorm:"column:isp;not null;comment:运营商0-其他1-电信2-联通3-移动" json:"isp"` // 运营商0-其他1-电信2-联通3-移动
} }
// TableName Node's table name // TableName Node's table name

View File

@@ -20,9 +20,9 @@ type Refund struct {
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
TradeID int32 `gorm:"column:trade_id;not null" json:"trade_id"` TradeID int32 `gorm:"column:trade_id;not null;comment:订单ID" json:"trade_id"` // 订单ID
Reason string `gorm:"column:reason" json:"reason"` Reason string `gorm:"column:reason;comment:退款原因" json:"reason"` // 退款原因
Status int32 `gorm:"column:status;not null" json:"status"` Status int32 `gorm:"column:status;not null;comment:退款状态0-待处理1-已退款2-已拒绝" json:"status"` // 退款状态0-待处理1-已退款2-已拒绝
} }
// TableName Refund's table name // TableName Refund's table name

View File

@@ -20,8 +20,8 @@ type Resource struct {
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ResourceNo string `gorm:"column:resource_no" json:"resource_no"` ResourceNo string `gorm:"column:resource_no;comment:套餐编号" json:"resource_no"` // 套餐编号
Type int32 `gorm:"column:type;not null" json:"type"` Type int32 `gorm:"column:type;not null;comment:套餐类型1-动态2-隧道3-独享" json:"type"` // 套餐类型1-动态2-隧道3-独享
Pss *ResourcePss `gorm:"foreignKey:ResourceID;references:ID" json:"pss"` Pss *ResourcePss `gorm:"foreignKey:ResourceID;references:ID" json:"pss"`
} }

View File

@@ -27,10 +27,10 @@ type Trade struct {
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
Type int32 `gorm:"column:type;not null" json:"type"` Type int32 `gorm:"column:type;not null;comment:订单类型0-充值余额1-购买产品" json:"type"` // 订单类型0-充值余额1-购买产品
CancelAt common.LocalDateTime `gorm:"column:cancel_at" json:"cancel_at"` CancelAt common.LocalDateTime `gorm:"column:cancel_at;comment:取消时间" json:"cancel_at"` // 取消时间
PaidAt common.LocalDateTime `gorm:"column:paid_at" json:"paid_at"` PaidAt common.LocalDateTime `gorm:"column:paid_at;comment:支付时间" json:"paid_at"` // 支付时间
PayURL string `gorm:"column:pay_url" json:"pay_url"` PayURL string `gorm:"column:pay_url;comment:支付链接" json:"pay_url"` // 支付链接
} }
// TableName Trade's table name // TableName Trade's table name

View File

@@ -20,7 +20,7 @@ type Whitelist struct {
CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 CreatedAt common.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 UpdatedAt common.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
Remark string `gorm:"column:remark" json:"remark"` Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注
} }
// TableName Whitelist's table name // TableName Whitelist's table name

View File

@@ -77,12 +77,12 @@ type bill struct {
CreatedAt field.Field // 创建时间 CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
TradeID field.Int32 TradeID field.Int32 // 订单ID
ResourceID field.Int32 ResourceID field.Int32 // 套餐ID
Type field.Int32 Type field.Int32 // 账单类型0-充值1-消费2-退款
BillNo field.String BillNo field.String // 易读账单号
RefundID field.Int32 RefundID field.Int32 // 退款ID
Amount field.Float64 Amount field.Float64 // 账单金额
Trade billBelongsToTrade Trade billBelongsToTrade
Refund billBelongsToRefund Refund billBelongsToRefund

View File

@@ -70,7 +70,7 @@ type channel struct {
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
ProxyHost field.String ProxyHost field.String
Protocol field.Int32 Protocol field.Int32 // 协议类型1-http2-https3-socks5
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }

View File

@@ -41,6 +41,7 @@ func newClient(db *gorm.DB, opts ...gen.DOOption) client {
_client.CreatedAt = field.NewField(tableName, "created_at") _client.CreatedAt = field.NewField(tableName, "created_at")
_client.UpdatedAt = field.NewField(tableName, "updated_at") _client.UpdatedAt = field.NewField(tableName, "updated_at")
_client.DeletedAt = field.NewField(tableName, "deleted_at") _client.DeletedAt = field.NewField(tableName, "deleted_at")
_client.GrantPassword = field.NewBool(tableName, "grant_password")
_client.fillFieldMap() _client.fillFieldMap()
@@ -65,6 +66,7 @@ type client struct {
CreatedAt field.Field // 创建时间 CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
GrantPassword field.Bool
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }
@@ -95,6 +97,7 @@ func (c *client) updateTableName(table string) *client {
c.CreatedAt = field.NewField(table, "created_at") c.CreatedAt = field.NewField(table, "created_at")
c.UpdatedAt = field.NewField(table, "updated_at") c.UpdatedAt = field.NewField(table, "updated_at")
c.DeletedAt = field.NewField(table, "deleted_at") c.DeletedAt = field.NewField(table, "deleted_at")
c.GrantPassword = field.NewBool(table, "grant_password")
c.fillFieldMap() c.fillFieldMap()
@@ -111,7 +114,7 @@ func (c *client) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
} }
func (c *client) fillFieldMap() { func (c *client) fillFieldMap() {
c.fieldMap = make(map[string]field.Expr, 14) c.fieldMap = make(map[string]field.Expr, 15)
c.fieldMap["id"] = c.ID c.fieldMap["id"] = c.ID
c.fieldMap["client_id"] = c.ClientID c.fieldMap["client_id"] = c.ClientID
c.fieldMap["client_secret"] = c.ClientSecret c.fieldMap["client_secret"] = c.ClientSecret
@@ -126,6 +129,7 @@ func (c *client) fillFieldMap() {
c.fieldMap["created_at"] = c.CreatedAt c.fieldMap["created_at"] = c.CreatedAt
c.fieldMap["updated_at"] = c.UpdatedAt c.fieldMap["updated_at"] = c.UpdatedAt
c.fieldMap["deleted_at"] = c.DeletedAt c.fieldMap["deleted_at"] = c.DeletedAt
c.fieldMap["grant_password"] = c.GrantPassword
} }
func (c client) clone(db *gorm.DB) client { func (c client) clone(db *gorm.DB) client {

View File

@@ -48,17 +48,17 @@ type coupon struct {
couponDo couponDo
ALL field.Asterisk ALL field.Asterisk
ExpireAt field.Time ExpireAt field.Time // 过期时间
CreatedAt field.Field CreatedAt field.Field // 创建时间
UpdatedAt field.Field UpdatedAt field.Field // 更新时间
DeletedAt field.Field DeletedAt field.Field // 删除时间
ID field.Int32 ID field.Int32 // 优惠券ID
UserID field.Int32 UserID field.Int32 // 用户ID
Status field.Int32 Status field.Int32 // 优惠券状态0-未使用1-已使用2-已过期
Code field.String Code field.String // 优惠券代码
Remark field.String Remark field.String // 优惠券备注
Amount field.Float64 Amount field.Float64 // 优惠券金额
MinAmount field.Float64 MinAmount field.Float64 // 最低消费金额
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }

View File

@@ -60,13 +60,13 @@ type node struct {
City field.String // 城市 City field.String // 城市
ProxyID field.Int32 // 代理ID ProxyID field.Int32 // 代理ID
ProxyPort field.Int32 // 代理端口 ProxyPort field.Int32 // 代理端口
Status field.Int32 // 节点状态:1-正常,0-离线 Status field.Int32 // 节点状态0-离线1-正常
Rtt field.Int32 // 延迟 Rtt field.Int32 // 延迟
Loss field.Int32 // 丢包率 Loss field.Int32 // 丢包率
CreatedAt field.Field // 创建时间 CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
Isp field.Int32 Isp field.Int32 // 运营商0-其他1-电信2-联通3-移动
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }

View File

@@ -52,9 +52,9 @@ type refund struct {
CreatedAt field.Field // 创建时间 CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
TradeID field.Int32 TradeID field.Int32 // 订单ID
Reason field.String Reason field.String // 退款原因
Status field.Int32 Status field.Int32 // 退款状态0-待处理1-已退款2-已拒绝
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }

View File

@@ -56,8 +56,8 @@ type resource struct {
CreatedAt field.Field // 创建时间 CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
ResourceNo field.String ResourceNo field.String // 套餐编号
Type field.Int32 Type field.Int32 // 套餐类型1-动态2-隧道3-独享
Pss resourceHasOnePss Pss resourceHasOnePss
fieldMap map[string]field.Expr fieldMap map[string]field.Expr

View File

@@ -67,10 +67,10 @@ type trade struct {
CreatedAt field.Field // 创建时间 CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
Type field.Int32 Type field.Int32 // 订单类型0-充值余额1-购买产品
CancelAt field.Field CancelAt field.Field // 取消时间
PaidAt field.Field PaidAt field.Field // 支付时间
PayURL field.String PayURL field.String // 支付链接
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }

View File

@@ -50,7 +50,7 @@ type whitelist struct {
CreatedAt field.Field // 创建时间 CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间 UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间 DeletedAt field.Field // 删除时间
Remark field.String Remark field.String // 备注
fieldMap map[string]field.Expr fieldMap map[string]field.Expr
} }

View File

@@ -12,7 +12,7 @@ func ApplyRouters(app *fiber.App) {
// 认证 // 认证
auth := api.Group("/auth") auth := api.Group("/auth")
auth.Post("/verify/sms", auth2.PermitDevice(), handlers.SmsCode) auth.Post("/verify/sms", handlers.SmsCode)
auth.Post("/login/sms", auth2.PermitDevice(), handlers.Login) auth.Post("/login/sms", auth2.PermitDevice(), handlers.Login)
auth.Post("/logout", handlers.Logout) auth.Post("/logout", handlers.Logout)
auth.Post("/token", handlers.Token) auth.Post("/token", handlers.Token)

View File

@@ -85,10 +85,19 @@ func (s *authService) OauthRefreshToken(ctx context.Context, client *models.Clie
return details, nil return details, nil
} }
type GrantType int type OauthGrantType string
const ( const (
GrantTypeAuthorizationCode GrantType = iota OauthGrantTypeAuthorizationCode = OauthGrantType("authorization_code")
GrantTypeClientCredentials OauthGrantTypeClientCredentials = OauthGrantType("client_credentials")
GrantTypeRefreshToken OauthGrantTypeRefreshToken = OauthGrantType("refresh_token")
OauthGrantTypePassword = OauthGrantType("password")
)
type OauthGrantLoginType string
const (
OauthGrantPasswordTypePassword = OauthGrantLoginType("password")
OauthGrantPasswordTypePhoneCode = OauthGrantLoginType("phone_code")
OauthGrantPasswordTypeEmailCode = OauthGrantLoginType("email_code")
) )

View File

@@ -239,6 +239,7 @@ func mergeConfig(defaultCfg SessionConfig, customCfg SessionConfig) SessionConfi
// AuthContext 定义认证信息 // AuthContext 定义认证信息
type AuthContext struct { type AuthContext struct {
Payload Payload `json:"payload"` Payload Payload `json:"payload"`
Agent Agent `json:"agent,omitempty"`
Permissions map[string]struct{} `json:"permissions,omitempty"` Permissions map[string]struct{} `json:"permissions,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"`
} }
@@ -265,6 +266,11 @@ const (
PayloadClientConfidential PayloadClientConfidential
) )
type Agent struct {
Id int32 `json:"id,omitempty"`
Addr string `json:"addr,omitempty"`
}
// AnyPermission 检查认证是否包含指定权限 // AnyPermission 检查认证是否包含指定权限
func (a *AuthContext) AnyPermission(requiredPermission ...string) bool { func (a *AuthContext) AnyPermission(requiredPermission ...string) bool {
if a == nil || a.Permissions == nil { if a == nil || a.Permissions == nil {