完善登录逻辑,登录接口统一到 /token
This commit is contained in:
@@ -22,6 +22,12 @@
|
|||||||
- [ ] Limiter
|
- [ ] Limiter
|
||||||
- [ ] Compress
|
- [ ] Compress
|
||||||
|
|
||||||
|
使用 fiber 自带 validator 进行参数验证
|
||||||
|
|
||||||
|
增加 domain 层,缓解同包字段过长的问题
|
||||||
|
|
||||||
|
移动端适配
|
||||||
|
|
||||||
授权过期跳转登录,成功后返回原链接
|
授权过期跳转登录,成功后返回原链接
|
||||||
|
|
||||||
错误处理类型转换失败问题
|
错误处理类型转换失败问题
|
||||||
|
|||||||
@@ -179,20 +179,21 @@ comment on column user_role.deleted_at is '删除时间';
|
|||||||
|
|
||||||
drop table if exists client cascade;
|
drop table if exists client cascade;
|
||||||
create table client (
|
create table client (
|
||||||
id serial primary key,
|
id serial primary key,
|
||||||
client_id varchar(255) not null unique,
|
client_id varchar(255) not null unique,
|
||||||
client_secret varchar(255) not null,
|
client_secret varchar(255) not null,
|
||||||
redirect_uri varchar(255),
|
redirect_uri varchar(255),
|
||||||
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,
|
||||||
spec int not null,
|
grant_password bool not null default false,
|
||||||
name varchar(255) not null,
|
spec int not null,
|
||||||
icon varchar(255),
|
name varchar(255) not null,
|
||||||
status int not null default 1,
|
icon varchar(255),
|
||||||
created_at timestamp default current_timestamp,
|
status int not null default 1,
|
||||||
updated_at timestamp default current_timestamp,
|
created_at timestamp default current_timestamp,
|
||||||
deleted_at timestamp
|
updated_at timestamp default current_timestamp,
|
||||||
|
deleted_at timestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
create index client_client_id_index on client (client_id);
|
create index client_client_id_index on client (client_id);
|
||||||
@@ -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-web,1-native,2-browser';
|
comment on column client.spec is '安全规范:0-web,1-native,2-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';
|
||||||
@@ -822,19 +824,19 @@ comment on column bill.deleted_at is '删除时间';
|
|||||||
-- coupon 优惠券
|
-- coupon 优惠券
|
||||||
drop table if exists coupon cascade;
|
drop table if exists coupon cascade;
|
||||||
create table coupon (
|
create table coupon (
|
||||||
id serial primary key,
|
id serial primary key,
|
||||||
user_id int references "user" (id)
|
user_id int references "user" (id)
|
||||||
on update cascade
|
on update cascade
|
||||||
on delete cascade,
|
on delete cascade,
|
||||||
code varchar(255) not null unique,
|
code varchar(255) not null unique,
|
||||||
remark varchar(255),
|
remark varchar(255),
|
||||||
amount decimal(12, 2) not null default 0,
|
amount decimal(12, 2) not null default 0,
|
||||||
min_amount decimal(12, 2) not null default 0,
|
min_amount decimal(12, 2) not null default 0,
|
||||||
status int not null default 0,
|
status int not null default 0,
|
||||||
expire_at timestamp,
|
expire_at timestamp,
|
||||||
created_at timestamp default current_timestamp,
|
created_at timestamp default current_timestamp,
|
||||||
updated_at timestamp default current_timestamp,
|
updated_at timestamp default current_timestamp,
|
||||||
deleted_at timestamp
|
deleted_at timestamp
|
||||||
);
|
);
|
||||||
create index coupon_user_id_index on coupon (user_id);
|
create index coupon_user_id_index on coupon (user_id);
|
||||||
create index coupon_code_index on coupon (code);
|
create index coupon_code_index on coupon (code);
|
||||||
|
|||||||
131
web/auth/auth.go
131
web/auth/auth.go
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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()).
|
||||||
|
|||||||
@@ -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 {
|
||||||
ClientID string `json:"client_id" form:"client_id"`
|
GrantType s.OauthGrantType `json:"grant_type" form:"grant_type"`
|
||||||
ClientSecret string `json:"client_secret" form:"client_secret"`
|
ClientID string `json:"client_id" form:"client_id"`
|
||||||
GrantType TokenGrantType `json:"grant_type" form:"grant_type"`
|
ClientSecret string `json:"client_secret" form:"client_secret"`
|
||||||
Code string `json:"code" form:"code"`
|
Scope string `json:"scope" form:"scope"`
|
||||||
RedirectURI string `json:"redirect_uri" form:"redirect_uri"`
|
TokenReqCode
|
||||||
CodeVerifier string `json:"code_verifier" form:"code_verifier"`
|
TokenReqClient
|
||||||
RefreshToken string `json:"refresh_token" form:"refresh_token"`
|
TokenReqRefresh
|
||||||
Scope string `json:"scope" form:"scope"`
|
TokenReqPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenReqCode struct {
|
||||||
|
Code string `json:"code" form:"code"`
|
||||||
|
RedirectURI string `json:"redirect_uri" form:"redirect_uri"`
|
||||||
|
CodeVerifier string `json:"code_verifier" form:"code_verifier"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenReqClient struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenReqRefresh struct {
|
||||||
|
RefreshToken string `json:"refresh_token" form:"refresh_token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
@@ -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-http,2-https,3-socks5" json:"protocol"` // 协议类型:1-http,2-https,3-socks5
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName Channel's table name
|
// TableName Channel's table name
|
||||||
|
|||||||
@@ -14,20 +14,21 @@ const TableNameClient = "client"
|
|||||||
|
|
||||||
// Client mapped from table <client>
|
// Client mapped from table <client>
|
||||||
type Client struct {
|
type Client struct {
|
||||||
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:客户端ID" json:"id"` // 客户端ID
|
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:客户端ID" json:"id"` // 客户端ID
|
||||||
ClientID string `gorm:"column:client_id;not null;comment:OAuth2客户端标识符" json:"client_id"` // OAuth2客户端标识符
|
ClientID string `gorm:"column:client_id;not null;comment:OAuth2客户端标识符" json:"client_id"` // OAuth2客户端标识符
|
||||||
ClientSecret string `gorm:"column:client_secret;not null;comment:OAuth2客户端密钥" json:"client_secret"` // OAuth2客户端密钥
|
ClientSecret string `gorm:"column:client_secret;not null;comment:OAuth2客户端密钥" json:"client_secret"` // OAuth2客户端密钥
|
||||||
RedirectURI string `gorm:"column:redirect_uri;comment:OAuth2 重定向URI" json:"redirect_uri"` // OAuth2 重定向URI
|
RedirectURI string `gorm:"column:redirect_uri;comment:OAuth2 重定向URI" json:"redirect_uri"` // OAuth2 重定向URI
|
||||||
GrantCode bool `gorm:"column:grant_code;not null;comment:允许授权码授予" json:"grant_code"` // 允许授权码授予
|
GrantCode bool `gorm:"column:grant_code;not null;comment:允许授权码授予" json:"grant_code"` // 允许授权码授予
|
||||||
GrantClient bool `gorm:"column:grant_client;not null;comment:允许客户端凭证授予" json:"grant_client"` // 允许客户端凭证授予
|
GrantClient bool `gorm:"column:grant_client;not null;comment:允许客户端凭证授予" json:"grant_client"` // 允许客户端凭证授予
|
||||||
GrantRefresh bool `gorm:"column:grant_refresh;not null;comment:允许刷新令牌授予" json:"grant_refresh"` // 允许刷新令牌授予
|
GrantRefresh bool `gorm:"column:grant_refresh;not null;comment:允许刷新令牌授予" json:"grant_refresh"` // 允许刷新令牌授予
|
||||||
Spec int32 `gorm:"column:spec;not null;comment:安全规范:0-web,1-native,2-browser" json:"spec"` // 安全规范:0-web,1-native,2-browser
|
Spec int32 `gorm:"column:spec;not null;comment:安全规范:0-web,1-native,2-browser" json:"spec"` // 安全规范:0-web,1-native,2-browser
|
||||||
Name string `gorm:"column:name;not null;comment:名称" json:"name"` // 名称
|
Name string `gorm:"column:name;not null;comment:名称" json:"name"` // 名称
|
||||||
Icon string `gorm:"column:icon;comment:图标URL" json:"icon"` // 图标URL
|
Icon string `gorm:"column:icon;comment:图标URL" json:"icon"` // 图标URL
|
||||||
Status int32 `gorm:"column:status;not null;default:1;comment:状态:1-正常,0-禁用" json:"status"` // 状态:1-正常,0-禁用
|
Status int32 `gorm:"column:status;not null;default:1;comment:状态:1-正常,0-禁用" json:"status"` // 状态:1-正常,0-禁用
|
||||||
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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -71,18 +71,18 @@ type bill struct {
|
|||||||
billDo
|
billDo
|
||||||
|
|
||||||
ALL field.Asterisk
|
ALL field.Asterisk
|
||||||
ID field.Int32 // 账单ID
|
ID field.Int32 // 账单ID
|
||||||
UserID field.Int32 // 用户ID
|
UserID field.Int32 // 用户ID
|
||||||
Info field.String // 产品可读信息
|
Info field.String // 产品可读信息
|
||||||
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
|
||||||
|
|||||||
@@ -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-http,2-https,3-socks5
|
||||||
|
|
||||||
fieldMap map[string]field.Expr
|
fieldMap map[string]field.Expr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
@@ -50,21 +51,22 @@ func newClient(db *gorm.DB, opts ...gen.DOOption) client {
|
|||||||
type client struct {
|
type client struct {
|
||||||
clientDo
|
clientDo
|
||||||
|
|
||||||
ALL field.Asterisk
|
ALL field.Asterisk
|
||||||
ID field.Int32 // 客户端ID
|
ID field.Int32 // 客户端ID
|
||||||
ClientID field.String // OAuth2客户端标识符
|
ClientID field.String // OAuth2客户端标识符
|
||||||
ClientSecret field.String // OAuth2客户端密钥
|
ClientSecret field.String // OAuth2客户端密钥
|
||||||
RedirectURI field.String // OAuth2 重定向URI
|
RedirectURI field.String // OAuth2 重定向URI
|
||||||
GrantCode field.Bool // 允许授权码授予
|
GrantCode field.Bool // 允许授权码授予
|
||||||
GrantClient field.Bool // 允许客户端凭证授予
|
GrantClient field.Bool // 允许客户端凭证授予
|
||||||
GrantRefresh field.Bool // 允许刷新令牌授予
|
GrantRefresh field.Bool // 允许刷新令牌授予
|
||||||
Spec field.Int32 // 安全规范:0-web,1-native,2-browser
|
Spec field.Int32 // 安全规范:0-web,1-native,2-browser
|
||||||
Name field.String // 名称
|
Name field.String // 名称
|
||||||
Icon field.String // 图标URL
|
Icon field.String // 图标URL
|
||||||
Status field.Int32 // 状态:1-正常,0-禁用
|
Status field.Int32 // 状态:1-正常,0-禁用
|
||||||
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 {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,14 +50,14 @@ type resource struct {
|
|||||||
resourceDo
|
resourceDo
|
||||||
|
|
||||||
ALL field.Asterisk
|
ALL field.Asterisk
|
||||||
ID field.Int32 // 套餐ID
|
ID field.Int32 // 套餐ID
|
||||||
UserID field.Int32 // 用户ID
|
UserID field.Int32 // 用户ID
|
||||||
Active field.Bool // 套餐状态
|
Active field.Bool // 套餐状态
|
||||||
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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user