From 2c37dcc2be689bcc051207a60832ab8c4a77ad6a Mon Sep 17 00:00:00 2001 From: luorijun Date: Mon, 12 May 2025 10:07:12 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E8=AE=A4=E8=AF=81=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E9=80=BB=E8=BE=91=EF=BC=8C=E9=9B=86=E4=B8=AD=E5=88=B0?= =?UTF-8?q?=20auth=20=E5=8C=85=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 +- scripts/sql/init.sql | 46 +++ web/auth/authenticate.go | 2 +- web/auth/authorize.go | 40 ++ web/auth/context.go | 53 ++- web/auth/session.go | 176 ++++++++- web/handlers/auth.go | 6 +- web/handlers/channel.go | 5 +- web/handlers/verifier.go | 4 +- web/models/admin.gen.go | 18 +- web/models/admin_role.gen.go | 4 +- web/models/admin_role_link.gen.go | 6 +- web/models/admin_role_permission_link.gen.go | 6 +- web/models/announcement.gen.go | 6 +- web/models/bill.gen.go | 16 +- web/models/channel.gen.go | 14 +- web/models/client.gen.go | 22 +- web/models/client_permission_link.gen.go | 6 +- web/models/coupon.gen.go | 22 +- web/models/logs_request.gen.go | 24 +- web/models/node.gen.go | 16 +- web/models/permission.gen.go | 4 +- web/models/product.gen.go | 6 +- web/models/proxy.gen.go | 10 +- web/models/refund.gen.go | 18 +- web/models/resource.gen.go | 6 +- web/models/resource_psr.gen.go | 16 +- web/models/resource_pss.gen.go | 22 +- web/models/session.gen.go | 36 ++ web/models/trade.gen.go | 34 +- web/models/user.gen.go | 32 +- web/models/user_role.gen.go | 4 +- web/models/user_role_link.gen.go | 6 +- web/models/user_role_permission_link.gen.go | 6 +- web/models/whitelist.gen.go | 8 +- web/queries/gen.go | 8 + web/queries/session.gen.go | 371 +++++++++++++++++++ web/services/auth.go | 24 +- web/services/channel.go | 4 +- web/services/session.go | 226 ----------- 40 files changed, 905 insertions(+), 455 deletions(-) create mode 100644 web/models/session.gen.go create mode 100644 web/queries/session.gen.go delete mode 100644 web/services/session.go diff --git a/README.md b/README.md index 70383f8..712e5bc 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,29 @@ ## todo -- 长效业务接入 - 页面 账户总览 - 页面 提取记录 - 页面 使用记录 -- 公众号的到期提示 -- 支付回调处理 - 保存 session 到数据库 +- 移除 PayloadType,使用 Grant_Type -### 下阶段 +### 长效业务 -- 代理数据表的 secret 字段 aes 加密存储 -- 扩展 device 权限验证方式,提供一种方法区分内部和外部服务 -- 废弃 password 授权模式,迁移到 authorization code 授权模式 -- oauth token 验证授权范围 -- 实现白银节点的 warp 服务,用来去重与端口分配,保证测试与生产环境不会产生端口竞争 -- callback 结果直接由 api 端提供,不通过前端转发 -- debug:白银节点提供一些工具接口,方便快速操作 - - 批量下线端口 -- 统一使用 validator 进行参数验证 +- 支付回调处理 +- 公众号的到期提示 ### 长期 +- 修改日志输出提高可读性 +- 用户最后登录的数据可以通过 session 表进行查询,不再保存在 user 表里 +- callback 结果直接由 api 端提供,不通过前端转发 +- debug:白银节点提供一些工具接口,方便快速操作 + - 批量下线端口 +- 代理数据表的 secret 字段 aes 加密存储 +- 废弃 password 授权模式,迁移到 authorization code 授权模式 +- oauth token 验证授权范围 +- 实现白银节点的 warp 服务,用来去重与端口分配,保证测试与生产环境不会产生端口竞争 +- 统一使用 validator 进行参数验证 - 分离项目脚手架(env,logs,Server 结构体) - 业务代码和测试代码共用的控制变量可以优化为环境变量 - 考虑统计接口调用频率并通过接口展示 diff --git a/scripts/sql/init.sql b/scripts/sql/init.sql index ef108bf..5f24e0e 100644 --- a/scripts/sql/init.sql +++ b/scripts/sql/init.sql @@ -295,6 +295,52 @@ comment on column client.deleted_at is '删除时间'; -- region 权限信息 -- ==================== +-- session +drop table if exists session cascade; +create table session ( + id serial primary key, + user_id int references "user" (id) + on update cascade + on delete cascade, + client_id int references client (id) + on update cascade + on delete cascade, + ip varchar(45), + ua varchar(255), + grant_type varchar(255) not null default 0, + access_token varchar(255) not null unique, + access_token_expires timestamp not null, + refresh_token varchar(255) unique, + refresh_token_expires timestamp, + scopes varchar(255), + created_at timestamp default current_timestamp, + updated_at timestamp default current_timestamp, + deleted_at timestamp +); +create index session_user_id_index on session (user_id); +create index session_client_id_index on session (client_id); +create index session_access_token_index on session (access_token); +create index session_refresh_token_index on session (refresh_token); +create index session_created_at_index on session (created_at); +create index session_deleted_at_index on session (deleted_at); + +-- session表字段注释 +comment on table session is '会话表'; +comment on column session.id is '会话ID'; +comment on column session.user_id is '用户ID'; +comment on column session.client_id is '客户端ID'; +comment on column session.ip is 'IP地址'; +comment on column session.ua is '用户代理'; +comment on column session.grant_type is '授权类型:authorization_code-授权码模式,client_credentials-客户端凭证模式,refresh_token-刷新令牌模式,password-密码模式'; +comment on column session.access_token is '访问令牌'; +comment on column session.access_token_expires is '访问令牌过期时间'; +comment on column session.refresh_token is '刷新令牌'; +comment on column session.refresh_token_expires is '刷新令牌过期时间'; +comment on column session.scopes is '权限范围'; +comment on column session.created_at is '创建时间'; +comment on column session.updated_at is '更新时间'; +comment on column session.deleted_at is '删除时间'; + -- permission drop table if exists permission cascade; create table permission ( diff --git a/web/auth/authenticate.go b/web/auth/authenticate.go index f90d9f7..2df1cd8 100644 --- a/web/auth/authenticate.go +++ b/web/auth/authenticate.go @@ -77,7 +77,7 @@ func Locals(c *fiber.Ctx, auth *Context) { } func authBearer(ctx context.Context, token string) (*Context, error) { - auth, err := find(ctx, token) + auth, err := FindSession(ctx, token) if err != nil { slog.Debug(err.Error()) return nil, err diff --git a/web/auth/authorize.go b/web/auth/authorize.go index cdcd3db..eb97056 100644 --- a/web/auth/authorize.go +++ b/web/auth/authorize.go @@ -16,3 +16,43 @@ const ( GrantPasswordPhone = PasswordGrantType("phone_code") // 手机号模式 GrantPasswordEmail = PasswordGrantType("email_code") // 邮箱模式 ) + +func Token(grant GrantType) error { + return nil +} + +func authAuthorizationCode() { + +} + +func authClientCredential() { + +} + +func authRefreshToken() { + +} + +func authPassword() { + +} + +func authPasswordSecret() { + +} + +func authPasswordPhone() { + +} + +func authPasswordEmail() { + +} + +func Revoke() error { + return nil +} + +func Introspect() error { + return nil +} diff --git a/web/auth/context.go b/web/auth/context.go index 6ae4857..7bb2067 100644 --- a/web/auth/context.go +++ b/web/auth/context.go @@ -1,13 +1,28 @@ package auth +import ( + client2 "platform/web/domains/client" +) + // Context 定义认证信息 type Context struct { Payload Payload `json:"payload"` - Agent Agent `json:"agent,omitempty"` Permissions map[string]struct{} `json:"permissions,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` } +func (a *Context) AnyType(types ...PayloadType) bool { + if a == nil { + return false + } + for _, t := range types { + if a.Payload.Type == t { + return true + } + } + return false +} + // AnyPermission 检查认证是否包含指定权限 func (a *Context) AnyPermission(requiredPermission ...string) bool { if a == nil || a.Permissions == nil { @@ -29,26 +44,15 @@ type Payload struct { Avatar string `json:"avatar,omitempty"` } -type Agent struct { - Id int32 `json:"id,omitempty"` - Addr string `json:"addr,omitempty"` -} - type PayloadType int const ( - // PayloadNone 游客 - PayloadNone PayloadType = iota - // PayloadUser 用户 - PayloadUser - // PayloadAdmin 管理员 - PayloadAdmin - // PayloadPublicServer 公共服务(public_client) - PayloadPublicServer - // PayloadSecuredServer 安全服务(credential_client) - PayloadSecuredServer - // PayloadInternalServer 内部服务 - PayloadInternalServer + PayloadNone PayloadType = iota // 游客 + PayloadUser // 用户 + PayloadAdmin // 管理员 + PayloadPublicServer // 公共服务(public_client) + PayloadSecuredServer // 安全服务(credential_client) + PayloadInternalServer // 内部服务 ) func (t PayloadType) ToStr() string { @@ -80,3 +84,16 @@ func PayloadTypeFromStr(name string) PayloadType { return PayloadNone } } + +func PayloadTypeFromClientSpec(spec client2.Spec) PayloadType { + var clientType PayloadType + switch spec { + case client2.SpecNative, client2.SpecBrowser: + clientType = PayloadPublicServer + case client2.SpecWeb: + clientType = PayloadSecuredServer + case client2.SpecTrusted: + clientType = PayloadInternalServer + } + return clientType +} diff --git a/web/auth/session.go b/web/auth/session.go index bee8a1f..32f4f78 100644 --- a/web/auth/session.go +++ b/web/auth/session.go @@ -5,11 +5,21 @@ import ( "encoding/json" "errors" "fmt" + "github.com/google/uuid" "github.com/redis/go-redis/v9" + "platform/pkg/env" g "platform/web/globals" + "time" ) -func find(ctx context.Context, token string) (*Context, error) { +type Session struct { + // 认证主体 + Payload *Payload + // 令牌信息 + TokenDetails *TokenDetails +} + +func FindSession(ctx context.Context, token string) (*Context, error) { // 读取认证数据 authJSON, err := g.Redis.Get(ctx, accessKey(token)).Result() @@ -29,6 +39,170 @@ func find(ctx context.Context, token string) (*Context, error) { return auth, nil } +func CreateSession(ctx context.Context, authCtx *Context, remember bool) (*TokenDetails, error) { + var now = time.Now() + + // 生成令牌组 + accessToken := genToken() + refreshToken := genToken() + + // 序列化认证数据 + authData, err := json.Marshal(authCtx) + if err != nil { + return nil, err + } + + // 序列化刷新令牌数据 + refreshData, err := json.Marshal(RefreshData{ + AuthContext: authCtx, + AccessToken: accessToken, + }) + if err != nil { + return nil, err + } + + // 事务保存数据到 Redis + var accessExpire = time.Duration(env.SessionAccessExpire) * time.Second + var refreshExpire = time.Duration(env.SessionRefreshExpire) * time.Second + + pipe := g.Redis.TxPipeline() + pipe.Set(ctx, accessKey(accessToken), authData, accessExpire) + if remember { + pipe.Set(ctx, refreshKey(refreshToken), refreshData, refreshExpire) + } + _, err = pipe.Exec(ctx) + if err != nil { + return nil, err + } + + return &TokenDetails{ + AccessToken: accessToken, + AccessTokenExpires: now.Add(accessExpire), + RefreshToken: refreshToken, + RefreshTokenExpires: now.Add(refreshExpire), + Auth: authCtx, + }, nil +} + +func RefreshSession(ctx context.Context, refreshToken string, renew bool) (*TokenDetails, error) { + var now = time.Now() + + rKey := refreshKey(refreshToken) + var tokenDetails *TokenDetails + + // 刷新令牌 + err := g.Redis.Watch(ctx, func(tx *redis.Tx) error { + + // 先获取刷新令牌数据 + refreshJson, err := tx.Get(ctx, rKey).Result() + if err != nil { + if errors.Is(err, redis.Nil) { + return ErrInvalidRefreshToken + } + return err + } + + // 解析刷新令牌数据 + refreshData := new(RefreshData) + if err := json.Unmarshal([]byte(refreshJson), refreshData); err != nil { + return err + } + + // 生成新的令牌 + newAccessToken := genToken() + newRefreshToken := genToken() + + authData, err := json.Marshal(refreshData.AuthContext) + if err != nil { + return err + } + newRefreshData, err := json.Marshal(RefreshData{ + AuthContext: refreshData.AuthContext, + AccessToken: newAccessToken, + }) + if err != nil { + return err + } + + pipeline := tx.Pipeline() + + // 保存新的令牌 + var accessExpire = time.Duration(env.SessionAccessExpire) * time.Second + var refreshExpire = time.Duration(env.SessionRefreshExpire) * time.Second + + pipeline.Set(ctx, accessKey(newAccessToken), authData, accessExpire) + pipeline.Set(ctx, refreshKey(newRefreshToken), newRefreshData, refreshExpire) + + // 删除旧的令牌 + pipeline.Del(ctx, accessKey(refreshData.AccessToken)) + pipeline.Del(ctx, refreshKey(refreshToken)) + + _, err = pipeline.Exec(ctx) + if err != nil { + return err + } + + tokenDetails = &TokenDetails{ + AccessToken: newAccessToken, + RefreshToken: newRefreshToken, + AccessTokenExpires: now.Add(accessExpire), + RefreshTokenExpires: now.Add(refreshExpire), + Auth: refreshData.AuthContext, + } + return nil + }, rKey) + if err != nil { + return nil, fmt.Errorf("刷新令牌失败: %w", err) + } + + return tokenDetails, nil +} + +func RemoveSession(ctx context.Context, accessToken string, refreshToken string) error { + g.Redis.Del(ctx, accessKey(accessToken), refreshKey(refreshToken)) + return nil +} + +// 生成一个新的令牌 +func genToken() string { + return uuid.NewString() +} + +// 令牌键的格式为 "session:" func accessKey(token string) string { return fmt.Sprintf("session:%s", token) } + +// 刷新令牌键的格式为 "session:refreshKey:" +func refreshKey(token string) string { + return fmt.Sprintf("session:refresh:%s", token) +} + +// TokenDetails 存储令牌详细信息 +type TokenDetails struct { + // 访问令牌 + AccessToken string + // 刷新令牌 + RefreshToken string + // 访问令牌过期时间 + AccessTokenExpires time.Time + // 刷新令牌过期时间 + RefreshTokenExpires time.Time + // 认证信息 + Auth *Context +} + +type RefreshData struct { + AuthContext *Context + AccessToken string +} + +type SessionErr string + +func (e SessionErr) Error() string { + return string(e) +} + +const ( + ErrInvalidRefreshToken = SessionErr("无效的刷新令牌") +) diff --git a/web/handlers/auth.go b/web/handlers/auth.go index 64b3b49..c61744b 100644 --- a/web/handlers/auth.go +++ b/web/handlers/auth.go @@ -110,7 +110,7 @@ func Token(c *fiber.Ctx) error { scope := strings.Split(req.Scope, ",") token, err := s.Auth.OauthRefreshToken(c.Context(), client, req.RefreshToken, scope) if err != nil { - if errors.Is(err, s.ErrInvalidToken) { + if errors.Is(err, auth2.ErrInvalidRefreshToken) { return sendError(c, s.ErrOauthInvalidGrant) } return sendError(c, err) @@ -226,7 +226,7 @@ func protect(c *fiber.Ctx, grant auth2.GrantType, clientId, clientSecret string) } // 发送成功响应 -func sendSuccess(c *fiber.Ctx, details *s.TokenDetails) error { +func sendSuccess(c *fiber.Ctx, details *auth2.TokenDetails) error { return c.JSON(TokenResp{ AccessToken: details.AccessToken, TokenType: "Bearer", @@ -292,7 +292,7 @@ func Revoke(c *fiber.Ctx) error { } // 删除会话 - err = s.Session.Remove(c.Context(), req.AccessToken, req.RefreshToken) + err = auth2.RemoveSession(c.Context(), req.AccessToken, req.RefreshToken) if err != nil { return err } diff --git a/web/handlers/channel.go b/web/handlers/channel.go index 7351463..948780c 100644 --- a/web/handlers/channel.go +++ b/web/handlers/channel.go @@ -198,10 +198,7 @@ type RemoveChannelsReq struct { func RemoveChannels(c *fiber.Ctx) error { // 检查权限 - authCtx, err := auth.Protect(c, []auth.PayloadType{ - auth.PayloadUser, - auth.PayloadSecuredServer, - }, []string{}) + authCtx, err := auth.Protect(c, []auth.PayloadType{auth.PayloadUser, auth.PayloadInternalServer}, []string{}) if err != nil { return err } diff --git a/web/handlers/verifier.go b/web/handlers/verifier.go index a1953e9..04b0406 100644 --- a/web/handlers/verifier.go +++ b/web/handlers/verifier.go @@ -17,9 +17,7 @@ type VerifierReq struct { func SmsCode(c *fiber.Ctx) error { - _, err := auth.Protect(c, []auth.PayloadType{ - auth.PayloadSecuredServer, - }, []string{}) + _, err := auth.Protect(c, []auth.PayloadType{auth.PayloadSecuredServer}, []string{}) if err != nil { return err } diff --git a/web/models/admin.gen.go b/web/models/admin.gen.go index 95bb6df..fc75726 100644 --- a/web/models/admin.gen.go +++ b/web/models/admin.gen.go @@ -14,17 +14,17 @@ const TableNameAdmin = "admin" // Admin mapped from table type Admin struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:管理员ID" json:"id"` // 管理员ID - Username string `gorm:"column:username;not null;comment:用户名" json:"username"` // 用户名 - Password string `gorm:"column:password;not null;comment:密码" json:"password"` // 密码 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:管理员ID" json:"id"` // 管理员ID + Username string `gorm:"column:username;not null;comment:用户名" json:"username"` // 用户名 + Password string `gorm:"column:password;not null;comment:密码" json:"password"` // 密码 Name string `gorm:"column:name;comment:真实姓名" json:"name"` // 真实姓名 - Avatar string `gorm:"column:avatar;comment:头像URL" json:"avatar"` // 头像URL + Avatar string `gorm:"column:avatar;comment:头像URL" json:"avatar"` // 头像URL Phone string `gorm:"column:phone;comment:手机号码" json:"phone"` // 手机号码 - Email string `gorm:"column:email;comment:邮箱" json:"email"` // 邮箱 - Status int32 `gorm:"column:status;not null;default:1;comment:状态:0-禁用,1-正常" json:"status"` // 状态:0-禁用,1-正常 - LastLogin orm.LocalDateTime `gorm:"column:last_login;comment:最后登录时间" json:"last_login"` // 最后登录时间 - LastLoginHost string `gorm:"column:last_login_host;comment:最后登录地址" json:"last_login_host"` // 最后登录地址 - LastLoginAgent string `gorm:"column:last_login_agent;comment:最后登录代理" json:"last_login_agent"` // 最后登录代理 + Email string `gorm:"column:email;comment:邮箱" json:"email"` // 邮箱 + Status int32 `gorm:"column:status;not null;default:1;comment:状态:0-禁用,1-正常" json:"status"` // 状态:0-禁用,1-正常 + LastLogin orm.LocalDateTime `gorm:"column:last_login;comment:最后登录时间" json:"last_login"` // 最后登录时间 + LastLoginHost string `gorm:"column:last_login_host;comment:最后登录地址" json:"last_login_host"` // 最后登录地址 + LastLoginAgent string `gorm:"column:last_login_agent;comment:最后登录代理" json:"last_login_agent"` // 最后登录代理 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/admin_role.gen.go b/web/models/admin_role.gen.go index d3e5e57..2ed90ed 100644 --- a/web/models/admin_role.gen.go +++ b/web/models/admin_role.gen.go @@ -14,11 +14,11 @@ const TableNameAdminRole = "admin_role" // AdminRole mapped from table type AdminRole 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 Name string `gorm:"column:name;not null;comment:角色名称" json:"name"` // 角色名称 Description string `gorm:"column:description;comment:角色描述" json:"description"` // 角色描述 Active bool `gorm:"column:active;default:true;comment:是否激活" json:"active"` // 是否激活 - Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序 + Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/admin_role_link.gen.go b/web/models/admin_role_link.gen.go index 33b888c..c98622e 100644 --- a/web/models/admin_role_link.gen.go +++ b/web/models/admin_role_link.gen.go @@ -14,9 +14,9 @@ const TableNameAdminRoleLink = "admin_role_link" // AdminRoleLink mapped from table type AdminRoleLink struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID - AdminID int32 `gorm:"column:admin_id;not null;comment:管理员ID" json:"admin_id"` // 管理员ID - RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID + AdminID int32 `gorm:"column:admin_id;not null;comment:管理员ID" json:"admin_id"` // 管理员ID + RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/admin_role_permission_link.gen.go b/web/models/admin_role_permission_link.gen.go index e93423d..e03cdd1 100644 --- a/web/models/admin_role_permission_link.gen.go +++ b/web/models/admin_role_permission_link.gen.go @@ -14,9 +14,9 @@ const TableNameAdminRolePermissionLink = "admin_role_permission_link" // AdminRolePermissionLink mapped from table type AdminRolePermissionLink struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID - RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID - PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID + RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID + PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/announcement.gen.go b/web/models/announcement.gen.go index 5103658..7ffe45f 100644 --- a/web/models/announcement.gen.go +++ b/web/models/announcement.gen.go @@ -14,12 +14,12 @@ const TableNameAnnouncement = "announcement" // Announcement mapped from table type Announcement 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 Title string `gorm:"column:title;not null;comment:公告标题" json:"title"` // 公告标题 Content string `gorm:"column:content;comment:公告内容" json:"content"` // 公告内容 - Type int32 `gorm:"column:type;not null;default:1;comment:公告类型:1-普通公告" json:"type"` // 公告类型:1-普通公告 + Type int32 `gorm:"column:type;not null;default:1;comment:公告类型:1-普通公告" json:"type"` // 公告类型:1-普通公告 Pin bool `gorm:"column:pin;not null;comment:是否置顶" json:"pin"` // 是否置顶 - Status int32 `gorm:"column:status;not null;default:1;comment:公告状态:0-禁用,1-正常" json:"status"` // 公告状态:0-禁用,1-正常 + Status int32 `gorm:"column:status;not null;default:1;comment:公告状态:0-禁用,1-正常" json:"status"` // 公告状态:0-禁用,1-正常 Sort int32 `gorm:"column:sort;not null;comment:公告排序" json:"sort"` // 公告排序 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 diff --git a/web/models/bill.gen.go b/web/models/bill.gen.go index ef14b8f..284251e 100644 --- a/web/models/bill.gen.go +++ b/web/models/bill.gen.go @@ -14,14 +14,14 @@ const TableNameBill = "bill" // Bill mapped from table type Bill struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:账单ID" json:"id"` // 账单ID - UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID - TradeID int32 `gorm:"column:trade_id;comment:订单ID" json:"trade_id"` // 订单ID - ResourceID int32 `gorm:"column:resource_id;comment:套餐ID" json:"resource_id"` // 套餐ID - RefundID int32 `gorm:"column:refund_id;comment:退款ID" json:"refund_id"` // 退款ID - BillNo string `gorm:"column:bill_no;not null;comment:易读账单号" json:"bill_no"` // 易读账单号 - Info string `gorm:"column:info;comment:产品可读信息" json:"info"` // 产品可读信息 - Type int32 `gorm:"column:type;not null;comment:账单类型:1-消费,2-退款,3-充值" json:"type"` // 账单类型:1-消费,2-退款,3-充值 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:账单ID" json:"id"` // 账单ID + UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID + TradeID int32 `gorm:"column:trade_id;comment:订单ID" json:"trade_id"` // 订单ID + ResourceID int32 `gorm:"column:resource_id;comment:套餐ID" json:"resource_id"` // 套餐ID + RefundID int32 `gorm:"column:refund_id;comment:退款ID" json:"refund_id"` // 退款ID + BillNo string `gorm:"column:bill_no;not null;comment:易读账单号" json:"bill_no"` // 易读账单号 + Info string `gorm:"column:info;comment:产品可读信息" json:"info"` // 产品可读信息 + Type int32 `gorm:"column:type;not null;comment:账单类型:1-消费,2-退款,3-充值" json:"type"` // 账单类型:1-消费,2-退款,3-充值 Amount float64 `gorm:"column:amount;not null;comment:账单金额" json:"amount"` // 账单金额 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 diff --git a/web/models/channel.gen.go b/web/models/channel.gen.go index 68c5099..dbf7bc0 100644 --- a/web/models/channel.gen.go +++ b/web/models/channel.gen.go @@ -14,19 +14,19 @@ const TableNameChannel = "channel" // Channel mapped from table type Channel struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:通道ID" json:"id"` // 通道ID - UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID - ProxyID int32 `gorm:"column:proxy_id;not null;comment:代理ID" json:"proxy_id"` // 代理ID - NodeID int32 `gorm:"column:node_id;comment:节点ID" json:"node_id"` // 节点ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:通道ID" json:"id"` // 通道ID + UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID + ProxyID int32 `gorm:"column:proxy_id;not null;comment:代理ID" json:"proxy_id"` // 代理ID + NodeID int32 `gorm:"column:node_id;comment:节点ID" json:"node_id"` // 节点ID ProxyHost string `gorm:"column:proxy_host;not null;comment:代理地址" json:"proxy_host"` // 代理地址 ProxyPort int32 `gorm:"column:proxy_port;not null;comment:转发端口" json:"proxy_port"` // 转发端口 NodeHost string `gorm:"column:node_host;comment:节点地址" json:"node_host"` // 节点地址 Protocol int32 `gorm:"column:protocol;comment:协议类型:1-http,2-https,3-socks5" json:"protocol"` // 协议类型:1-http,2-https,3-socks5 - AuthIP bool `gorm:"column:auth_ip;not null;comment:IP认证" json:"auth_ip"` // IP认证 + AuthIP bool `gorm:"column:auth_ip;not null;comment:IP认证" json:"auth_ip"` // IP认证 UserHost string `gorm:"column:user_host;comment:用户地址" json:"user_host"` // 用户地址 AuthPass bool `gorm:"column:auth_pass;not null;comment:密码认证" json:"auth_pass"` // 密码认证 - Username string `gorm:"column:username;comment:用户名" json:"username"` // 用户名 - Password string `gorm:"column:password;comment:密码" json:"password"` // 密码 + Username string `gorm:"column:username;comment:用户名" json:"username"` // 用户名 + Password string `gorm:"column:password;comment:密码" json:"password"` // 密码 Expiration orm.LocalDateTime `gorm:"column:expiration;not null;comment:过期时间" json:"expiration"` // 过期时间 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 diff --git a/web/models/client.gen.go b/web/models/client.gen.go index e19a9df..2e71d70 100644 --- a/web/models/client.gen.go +++ b/web/models/client.gen.go @@ -14,18 +14,18 @@ const TableNameClient = "client" // Client mapped from table type Client struct { - 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客户端标识符 - 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 - GrantCode bool `gorm:"column:grant_code;not null;comment:允许授权码授予" json:"grant_code"` // 允许授权码授予 - GrantClient bool `gorm:"column:grant_client;not null;comment:允许客户端凭证授予" json:"grant_client"` // 允许客户端凭证授予 - GrantRefresh bool `gorm:"column:grant_refresh;not null;comment:允许刷新令牌授予" json:"grant_refresh"` // 允许刷新令牌授予 - GrantPassword bool `gorm:"column:grant_password;not null;comment:允许密码授予" json:"grant_password"` // 允许密码授予 + 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客户端标识符 + 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 + GrantCode bool `gorm:"column:grant_code;not null;comment:允许授权码授予" json:"grant_code"` // 允许授权码授予 + GrantClient bool `gorm:"column:grant_client;not null;comment:允许客户端凭证授予" json:"grant_client"` // 允许客户端凭证授予 + GrantRefresh bool `gorm:"column:grant_refresh;not null;comment:允许刷新令牌授予" json:"grant_refresh"` // 允许刷新令牌授予 + GrantPassword bool `gorm:"column:grant_password;not null;comment:允许密码授予" json:"grant_password"` // 允许密码授予 Spec int32 `gorm:"column:spec;not null;comment:安全规范:1-native,2-browser,3-web,4-trusted" json:"spec"` // 安全规范:1-native,2-browser,3-web,4-trusted - Name string `gorm:"column:name;not null;comment:名称" json:"name"` // 名称 - Icon string `gorm:"column:icon;comment:图标URL" json:"icon"` // 图标URL - Status int32 `gorm:"column:status;not null;default:1;comment:状态:0-禁用,1-正常" json:"status"` // 状态:0-禁用,1-正常 + Name string `gorm:"column:name;not null;comment:名称" json:"name"` // 名称 + Icon string `gorm:"column:icon;comment:图标URL" json:"icon"` // 图标URL + Status int32 `gorm:"column:status;not null;default:1;comment:状态:0-禁用,1-正常" json:"status"` // 状态:0-禁用,1-正常 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/client_permission_link.gen.go b/web/models/client_permission_link.gen.go index bbea687..ce4c955 100644 --- a/web/models/client_permission_link.gen.go +++ b/web/models/client_permission_link.gen.go @@ -14,9 +14,9 @@ const TableNameClientPermissionLink = "client_permission_link" // ClientPermissionLink mapped from table type ClientPermissionLink struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID - ClientID int32 `gorm:"column:client_id;not null;comment:客户端ID" json:"client_id"` // 客户端ID - PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID + ClientID int32 `gorm:"column:client_id;not null;comment:客户端ID" json:"client_id"` // 客户端ID + PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/coupon.gen.go b/web/models/coupon.gen.go index 192903f..c1c0a3d 100644 --- a/web/models/coupon.gen.go +++ b/web/models/coupon.gen.go @@ -14,17 +14,17 @@ const TableNameCoupon = "coupon" // Coupon mapped from table type Coupon struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:优惠券ID" json:"id"` // 优惠券ID - UserID int32 `gorm:"column:user_id;comment:用户ID" json:"user_id"` // 用户ID - Code string `gorm:"column:code;not null;comment:优惠券代码" json:"code"` // 优惠券代码 - Remark string `gorm:"column:remark;comment:优惠券备注" json:"remark"` // 优惠券备注 - Amount float64 `gorm:"column:amount;not null;comment:优惠券金额" json:"amount"` // 优惠券金额 - MinAmount float64 `gorm:"column:min_amount;not null;comment:最低消费金额" json:"min_amount"` // 最低消费金额 - Status int32 `gorm:"column:status;not null;comment:优惠券状态:0-未使用,1-已使用,2-已过期" json:"status"` // 优惠券状态:0-未使用,1-已使用,2-已过期 - ExpireAt orm.LocalDateTime `gorm:"column:expire_at;comment:过期时间" json:"expire_at"` // 过期时间 - CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 - DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:优惠券ID" json:"id"` // 优惠券ID + UserID int32 `gorm:"column:user_id;comment:用户ID" json:"user_id"` // 用户ID + Code string `gorm:"column:code;not null;comment:优惠券代码" json:"code"` // 优惠券代码 + Remark string `gorm:"column:remark;comment:优惠券备注" json:"remark"` // 优惠券备注 + Amount float64 `gorm:"column:amount;not null;comment:优惠券金额" json:"amount"` // 优惠券金额 + MinAmount float64 `gorm:"column:min_amount;not null;comment:最低消费金额" json:"min_amount"` // 最低消费金额 + Status int32 `gorm:"column:status;not null;comment:优惠券状态:0-未使用,1-已使用,2-已过期" json:"status"` // 优惠券状态:0-未使用,1-已使用,2-已过期 + ExpireAt orm.LocalDateTime `gorm:"column:expire_at;comment:过期时间" json:"expire_at"` // 过期时间 + CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 } // TableName Coupon's table name diff --git a/web/models/logs_request.gen.go b/web/models/logs_request.gen.go index e12c48f..747b509 100644 --- a/web/models/logs_request.gen.go +++ b/web/models/logs_request.gen.go @@ -4,25 +4,23 @@ package models -import ( - "platform/web/globals/orm" -) +import "platform/web/globals/orm" const TableNameLogsRequest = "logs_request" // LogsRequest mapped from table type LogsRequest 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 Identity int32 `gorm:"column:identity;comment:访客身份:0-游客,1-用户,2-管理员,3-公共服务,4-安全服务,5-内部服务" json:"identity"` // 访客身份:0-游客,1-用户,2-管理员,3-公共服务,4-安全服务,5-内部服务 - Visitor int32 `gorm:"column:visitor;comment:访客ID" json:"visitor"` // 访客ID - IP string `gorm:"column:ip;not null;comment:IP地址" json:"ip"` // IP地址 - Ua string `gorm:"column:ua;comment:用户代理" json:"ua"` // 用户代理 - Method string `gorm:"column:method;not null;comment:请求方法" json:"method"` // 请求方法 - Path string `gorm:"column:path;not null;comment:请求路径" json:"path"` // 请求路径 - Latency string `gorm:"column:latency;comment:请求延迟" json:"latency"` // 请求延迟 - Status int32 `gorm:"column:status;not null;comment:响应状态码" json:"status"` // 响应状态码 - Error string `gorm:"column:error;comment:错误信息" json:"error"` // 错误信息 - Time orm.LocalDateTime `gorm:"column:time;default:CURRENT_TIMESTAMP;comment:请求时间" json:"time"` // 请求时间 + Visitor int32 `gorm:"column:visitor;comment:访客ID" json:"visitor"` // 访客ID + IP string `gorm:"column:ip;not null;comment:IP地址" json:"ip"` // IP地址 + Ua string `gorm:"column:ua;comment:用户代理" json:"ua"` // 用户代理 + Method string `gorm:"column:method;not null;comment:请求方法" json:"method"` // 请求方法 + Path string `gorm:"column:path;not null;comment:请求路径" json:"path"` // 请求路径 + Latency string `gorm:"column:latency;comment:请求延迟" json:"latency"` // 请求延迟 + Status int32 `gorm:"column:status;not null;comment:响应状态码" json:"status"` // 响应状态码 + Error string `gorm:"column:error;comment:错误信息" json:"error"` // 错误信息 + Time orm.LocalDateTime `gorm:"column:time;default:CURRENT_TIMESTAMP;comment:请求时间" json:"time"` // 请求时间 } // TableName LogsRequest's table name diff --git a/web/models/node.gen.go b/web/models/node.gen.go index 86fa5fe..dff83fd 100644 --- a/web/models/node.gen.go +++ b/web/models/node.gen.go @@ -14,18 +14,18 @@ const TableNameNode = "node" // Node mapped from table type Node struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:节点ID" json:"id"` // 节点ID - ProxyID int32 `gorm:"column:proxy_id;comment:代理ID" json:"proxy_id"` // 代理ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:节点ID" json:"id"` // 节点ID + ProxyID int32 `gorm:"column:proxy_id;comment:代理ID" json:"proxy_id"` // 代理ID Version int32 `gorm:"column:version;not null;comment:节点版本" json:"version"` // 节点版本 Name string `gorm:"column:name;not null;comment:节点名称" json:"name"` // 节点名称 Host string `gorm:"column:host;not null;comment:节点地址" json:"host"` // 节点地址 - Isp int32 `gorm:"column:isp;not null;comment:运营商:0-未知,1-电信,2-联通,3-移动" json:"isp"` // 运营商:0-未知,1-电信,2-联通,3-移动 - Prov string `gorm:"column:prov;not null;comment:省份" json:"prov"` // 省份 - City string `gorm:"column:city;not null;comment:城市" json:"city"` // 城市 + Isp int32 `gorm:"column:isp;not null;comment:运营商:0-未知,1-电信,2-联通,3-移动" json:"isp"` // 运营商:0-未知,1-电信,2-联通,3-移动 + Prov string `gorm:"column:prov;not null;comment:省份" json:"prov"` // 省份 + City string `gorm:"column:city;not null;comment:城市" json:"city"` // 城市 ProxyPort int32 `gorm:"column:proxy_port;comment:代理端口" json:"proxy_port"` // 代理端口 - Status int32 `gorm:"column:status;not null;comment:节点状态:0-离线,1-正常" json:"status"` // 节点状态:0-离线,1-正常 - Rtt int32 `gorm:"column:rtt;comment:延迟" json:"rtt"` // 延迟 - Loss int32 `gorm:"column:loss;comment:丢包率" json:"loss"` // 丢包率 + Status int32 `gorm:"column:status;not null;comment:节点状态:0-离线,1-正常" json:"status"` // 节点状态:0-离线,1-正常 + Rtt int32 `gorm:"column:rtt;comment:延迟" json:"rtt"` // 延迟 + Loss int32 `gorm:"column:loss;comment:丢包率" json:"loss"` // 丢包率 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/permission.gen.go b/web/models/permission.gen.go index 0f55286..20c40e1 100644 --- a/web/models/permission.gen.go +++ b/web/models/permission.gen.go @@ -14,8 +14,8 @@ const TableNamePermission = "permission" // Permission mapped from table type Permission struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:权限ID" json:"id"` // 权限ID - ParentID int32 `gorm:"column:parent_id;comment:父权限ID" json:"parent_id"` // 父权限ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:权限ID" json:"id"` // 权限ID + ParentID int32 `gorm:"column:parent_id;comment:父权限ID" json:"parent_id"` // 父权限ID Name string `gorm:"column:name;not null;comment:权限名称" json:"name"` // 权限名称 Description string `gorm:"column:description;comment:权限描述" json:"description"` // 权限描述 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 diff --git a/web/models/product.gen.go b/web/models/product.gen.go index db2475c..8f1fa16 100644 --- a/web/models/product.gen.go +++ b/web/models/product.gen.go @@ -14,12 +14,12 @@ const TableNameProduct = "product" // Product mapped from table type Product 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 Code string `gorm:"column:code;not null;comment:产品代码" json:"code"` // 产品代码 Name string `gorm:"column:name;not null;comment:产品名称" json:"name"` // 产品名称 Description string `gorm:"column:description;comment:产品描述" json:"description"` // 产品描述 - Sort int32 `gorm:"column:sort;not null;comment:排序" json:"sort"` // 排序 - Status int32 `gorm:"column:status;not null;default:1;comment:产品状态:0-禁用,1-正常" json:"status"` // 产品状态:0-禁用,1-正常 + Sort int32 `gorm:"column:sort;not null;comment:排序" json:"sort"` // 排序 + Status int32 `gorm:"column:status;not null;default:1;comment:产品状态:0-禁用,1-正常" json:"status"` // 产品状态:0-禁用,1-正常 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/proxy.gen.go b/web/models/proxy.gen.go index a436790..6bb5e0a 100644 --- a/web/models/proxy.gen.go +++ b/web/models/proxy.gen.go @@ -15,11 +15,11 @@ const TableNameProxy = "proxy" // Proxy mapped from table type Proxy struct { ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:代理服务ID" json:"id"` // 代理服务ID - Version int32 `gorm:"column:version;not null;comment:代理服务版本" json:"version"` // 代理服务版本 - Name string `gorm:"column:name;not null;comment:代理服务名称" json:"name"` // 代理服务名称 - Host string `gorm:"column:host;not null;comment:代理服务地址" json:"host"` // 代理服务地址 - Type int32 `gorm:"column:type;not null;comment:代理服务类型:1-三方,2-自有" json:"type"` // 代理服务类型:1-三方,2-自有 - Secret string `gorm:"column:secret;comment:代理服务密钥" json:"secret"` // 代理服务密钥 + Version int32 `gorm:"column:version;not null;comment:代理服务版本" json:"version"` // 代理服务版本 + Name string `gorm:"column:name;not null;comment:代理服务名称" json:"name"` // 代理服务名称 + Host string `gorm:"column:host;not null;comment:代理服务地址" json:"host"` // 代理服务地址 + Type int32 `gorm:"column:type;not null;comment:代理服务类型:1-三方,2-自有" json:"type"` // 代理服务类型:1-三方,2-自有 + Secret string `gorm:"column:secret;comment:代理服务密钥" json:"secret"` // 代理服务密钥 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/refund.gen.go b/web/models/refund.gen.go index 3a00869..fcdf4ea 100644 --- a/web/models/refund.gen.go +++ b/web/models/refund.gen.go @@ -14,15 +14,15 @@ const TableNameRefund = "refund" // Refund mapped from table type Refund struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:退款ID" json:"id"` // 退款ID - TradeID int32 `gorm:"column:trade_id;not null;comment:订单ID" json:"trade_id"` // 订单ID - ProductID int32 `gorm:"column:product_id;comment:产品ID" json:"product_id"` // 产品ID - Amount float64 `gorm:"column:amount;not null;comment:退款金额" json:"amount"` // 退款金额 - Reason string `gorm:"column:reason;comment:退款原因" json:"reason"` // 退款原因 - Status int32 `gorm:"column:status;not null;comment:退款状态:0-待处理,1-已退款,2-已拒绝" json:"status"` // 退款状态:0-待处理,1-已退款,2-已拒绝 - CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 - DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:退款ID" json:"id"` // 退款ID + TradeID int32 `gorm:"column:trade_id;not null;comment:订单ID" json:"trade_id"` // 订单ID + ProductID int32 `gorm:"column:product_id;comment:产品ID" json:"product_id"` // 产品ID + Amount float64 `gorm:"column:amount;not null;comment:退款金额" json:"amount"` // 退款金额 + Reason string `gorm:"column:reason;comment:退款原因" json:"reason"` // 退款原因 + Status int32 `gorm:"column:status;not null;comment:退款状态:0-待处理,1-已退款,2-已拒绝" json:"status"` // 退款状态:0-待处理,1-已退款,2-已拒绝 + CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 } // TableName Refund's table name diff --git a/web/models/resource.gen.go b/web/models/resource.gen.go index 2cce3e8..5639499 100644 --- a/web/models/resource.gen.go +++ b/web/models/resource.gen.go @@ -14,11 +14,11 @@ const TableNameResource = "resource" // Resource mapped from table type Resource struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:套餐ID" json:"id"` // 套餐ID - UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:套餐ID" json:"id"` // 套餐ID + UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID ResourceNo string `gorm:"column:resource_no;comment:套餐编号" json:"resource_no"` // 套餐编号 Active bool `gorm:"column:active;not null;default:true;comment:套餐状态" json:"active"` // 套餐状态 - Type int32 `gorm:"column:type;not null;comment:套餐类型:1-动态,2-隧道,3-独享" json:"type"` // 套餐类型:1-动态,2-隧道,3-独享 + Type int32 `gorm:"column:type;not null;comment:套餐类型:1-动态,2-隧道,3-独享" json:"type"` // 套餐类型:1-动态,2-隧道,3-独享 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/resource_psr.gen.go b/web/models/resource_psr.gen.go index 061453a..9b17cd5 100644 --- a/web/models/resource_psr.gen.go +++ b/web/models/resource_psr.gen.go @@ -4,20 +4,18 @@ package models -import ( - "platform/web/globals/orm" -) +import "platform/web/globals/orm" const TableNameResourcePsr = "resource_psr" // ResourcePsr mapped from table type ResourcePsr struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID - ResourceID int32 `gorm:"column:resource_id;not null;comment:套餐ID" json:"resource_id"` // 套餐ID - Live int32 `gorm:"column:live;comment:轮换周期(秒)" json:"live"` // 轮换周期(秒) - Conn int32 `gorm:"column:conn;comment:最大连接数" json:"conn"` // 最大连接数 - Expire orm.LocalDateTime `gorm:"column:expire;comment:过期时间" json:"expire"` // 过期时间 - Used bool `gorm:"column:used;comment:是否已使用" json:"used"` // 是否已使用 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID + ResourceID int32 `gorm:"column:resource_id;not null;comment:套餐ID" json:"resource_id"` // 套餐ID + Live int32 `gorm:"column:live;comment:轮换周期(秒)" json:"live"` // 轮换周期(秒) + Conn int32 `gorm:"column:conn;comment:最大连接数" json:"conn"` // 最大连接数 + Expire orm.LocalDateTime `gorm:"column:expire;comment:过期时间" json:"expire"` // 过期时间 + Used bool `gorm:"column:used;comment:是否已使用" json:"used"` // 是否已使用 } // TableName ResourcePsr's table name diff --git a/web/models/resource_pss.gen.go b/web/models/resource_pss.gen.go index 8850de8..0effc0b 100644 --- a/web/models/resource_pss.gen.go +++ b/web/models/resource_pss.gen.go @@ -4,24 +4,22 @@ package models -import ( - "platform/web/globals/orm" -) +import "platform/web/globals/orm" const TableNameResourcePss = "resource_pss" // ResourcePss mapped from table type ResourcePss struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID - ResourceID int32 `gorm:"column:resource_id;not null;comment:套餐ID" json:"resource_id"` // 套餐ID - Type int32 `gorm:"column:type;comment:套餐类型:1-包时,2-包量" json:"type"` // 套餐类型:1-包时,2-包量 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID + ResourceID int32 `gorm:"column:resource_id;not null;comment:套餐ID" json:"resource_id"` // 套餐ID + Type int32 `gorm:"column:type;comment:套餐类型:1-包时,2-包量" json:"type"` // 套餐类型:1-包时,2-包量 Live int32 `gorm:"column:live;comment:可用时长(秒)" json:"live"` // 可用时长(秒) - Expire orm.LocalDateTime `gorm:"column:expire;comment:过期时间" json:"expire"` // 过期时间 - Quota int32 `gorm:"column:quota;comment:配额数量" json:"quota"` // 配额数量 - Used int32 `gorm:"column:used;not null;comment:已用数量" json:"used"` // 已用数量 - DailyLimit int32 `gorm:"column:daily_limit;not null;comment:每日限制" json:"daily_limit"` // 每日限制 - DailyUsed int32 `gorm:"column:daily_used;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量 - DailyLast orm.LocalDateTime `gorm:"column:daily_last;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间 + Expire orm.LocalDateTime `gorm:"column:expire;comment:过期时间" json:"expire"` // 过期时间 + Quota int32 `gorm:"column:quota;comment:配额数量" json:"quota"` // 配额数量 + Used int32 `gorm:"column:used;not null;comment:已用数量" json:"used"` // 已用数量 + DailyLimit int32 `gorm:"column:daily_limit;not null;comment:每日限制" json:"daily_limit"` // 每日限制 + DailyUsed int32 `gorm:"column:daily_used;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量 + DailyLast orm.LocalDateTime `gorm:"column:daily_last;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间 } // TableName ResourcePss's table name diff --git a/web/models/session.gen.go b/web/models/session.gen.go new file mode 100644 index 0000000..cace446 --- /dev/null +++ b/web/models/session.gen.go @@ -0,0 +1,36 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package models + +import ( + "platform/web/globals/orm" + + "gorm.io/gorm" +) + +const TableNameSession = "session" + +// Session mapped from table +type Session struct { + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:会话ID" json:"id"` // 会话ID + UserID int32 `gorm:"column:user_id;comment:用户ID" json:"user_id"` // 用户ID + ClientID int32 `gorm:"column:client_id;comment:客户端ID" json:"client_id"` // 客户端ID + IP string `gorm:"column:ip;comment:IP地址" json:"ip"` // IP地址 + Ua string `gorm:"column:ua;comment:用户代理" json:"ua"` // 用户代理 + GrantType string `gorm:"column:grant_type;not null;default:0;comment:授权类型:authorization_code-授权码模式,client_credentials-客户端凭证模式,refresh_token-刷新令牌模式,password-密码模式" json:"grant_type"` // 授权类型:authorization_code-授权码模式,client_credentials-客户端凭证模式,refresh_token-刷新令牌模式,password-密码模式 + AccessToken string `gorm:"column:access_token;not null;comment:访问令牌" json:"access_token"` // 访问令牌 + AccessTokenExpires orm.LocalDateTime `gorm:"column:access_token_expires;not null;comment:访问令牌过期时间" json:"access_token_expires"` // 访问令牌过期时间 + RefreshToken string `gorm:"column:refresh_token;comment:刷新令牌" json:"refresh_token"` // 刷新令牌 + RefreshTokenExpires orm.LocalDateTime `gorm:"column:refresh_token_expires;comment:刷新令牌过期时间" json:"refresh_token_expires"` // 刷新令牌过期时间 + Scopes_ string `gorm:"column:scopes;comment:权限范围" json:"scopes"` // 权限范围 + CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 +} + +// TableName Session's table name +func (*Session) TableName() string { + return TableNameSession +} diff --git a/web/models/trade.gen.go b/web/models/trade.gen.go index f5a7d70..695fa50 100644 --- a/web/models/trade.gen.go +++ b/web/models/trade.gen.go @@ -14,23 +14,23 @@ const TableNameTrade = "trade" // Trade mapped from table type Trade struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:订单ID" json:"id"` // 订单ID - UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID - InnerNo string `gorm:"column:inner_no;not null;comment:内部订单号" json:"inner_no"` // 内部订单号 - OuterNo string `gorm:"column:outer_no;comment:外部订单号" json:"outer_no"` // 外部订单号 - Type int32 `gorm:"column:type;not null;comment:订单类型:1-购买产品,2-充值余额" json:"type"` // 订单类型:1-购买产品,2-充值余额 - Subject string `gorm:"column:subject;not null;comment:订单主题" json:"subject"` // 订单主题 - Remark string `gorm:"column:remark;comment:订单备注" json:"remark"` // 订单备注 - Amount float64 `gorm:"column:amount;not null;comment:订单总金额" json:"amount"` // 订单总金额 - Payment float64 `gorm:"column:payment;not null;comment:支付金额" json:"payment"` // 支付金额 - Method int32 `gorm:"column:method;not null;comment:支付方式:1-支付宝,2-微信" json:"method"` // 支付方式:1-支付宝,2-微信 - Status int32 `gorm:"column:status;not null;comment:订单状态:0-待支付,1-已支付,2-已取消,3-已退款" json:"status"` // 订单状态:0-待支付,1-已支付,2-已取消,3-已退款 - PayURL string `gorm:"column:pay_url;comment:支付链接" json:"pay_url"` // 支付链接 - PaidAt orm.LocalDateTime `gorm:"column:paid_at;comment:支付时间" json:"paid_at"` // 支付时间 - CancelAt orm.LocalDateTime `gorm:"column:cancel_at;comment:取消时间" json:"cancel_at"` // 取消时间 - CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 - DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:订单ID" json:"id"` // 订单ID + UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID + InnerNo string `gorm:"column:inner_no;not null;comment:内部订单号" json:"inner_no"` // 内部订单号 + OuterNo string `gorm:"column:outer_no;comment:外部订单号" json:"outer_no"` // 外部订单号 + Type int32 `gorm:"column:type;not null;comment:订单类型:1-购买产品,2-充值余额" json:"type"` // 订单类型:1-购买产品,2-充值余额 + Subject string `gorm:"column:subject;not null;comment:订单主题" json:"subject"` // 订单主题 + Remark string `gorm:"column:remark;comment:订单备注" json:"remark"` // 订单备注 + Amount float64 `gorm:"column:amount;not null;comment:订单总金额" json:"amount"` // 订单总金额 + Payment float64 `gorm:"column:payment;not null;comment:支付金额" json:"payment"` // 支付金额 + Method int32 `gorm:"column:method;not null;comment:支付方式:1-支付宝,2-微信" json:"method"` // 支付方式:1-支付宝,2-微信 + Status int32 `gorm:"column:status;not null;comment:订单状态:0-待支付,1-已支付,2-已取消,3-已退款" json:"status"` // 订单状态:0-待支付,1-已支付,2-已取消,3-已退款 + PayURL string `gorm:"column:pay_url;comment:支付链接" json:"pay_url"` // 支付链接 + PaidAt orm.LocalDateTime `gorm:"column:paid_at;comment:支付时间" json:"paid_at"` // 支付时间 + CancelAt orm.LocalDateTime `gorm:"column:cancel_at;comment:取消时间" json:"cancel_at"` // 取消时间 + CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 } // TableName Trade's table name diff --git a/web/models/user.gen.go b/web/models/user.gen.go index 194a4bb..6ef1ad6 100644 --- a/web/models/user.gen.go +++ b/web/models/user.gen.go @@ -19,22 +19,22 @@ type User struct { Phone string `gorm:"column:phone;not null;comment:手机号码" json:"phone"` // 手机号码 Username string `gorm:"column:username;comment:用户名" json:"username"` // 用户名 Email string `gorm:"column:email" json:"email"` - Password string `gorm:"column:password;comment:用户密码" json:"password"` // 用户密码 - Name string `gorm:"column:name;comment:真实姓名" json:"name"` // 真实姓名 - Avatar string `gorm:"column:avatar;comment:头像URL" json:"avatar"` // 头像URL - Status int32 `gorm:"column:status;not null;default:1;comment:用户状态:0-禁用,1-正常" json:"status"` // 用户状态:0-禁用,1-正常 - Balance float64 `gorm:"column:balance;not null;comment:账户余额" json:"balance"` // 账户余额 - IDType int32 `gorm:"column:id_type;not null;comment:认证类型:0-未认证,1-个人认证,2-企业认证" json:"id_type"` // 认证类型:0-未认证,1-个人认证,2-企业认证 - IDNo string `gorm:"column:id_no;comment:身份证号或营业执照号" json:"id_no"` // 身份证号或营业执照号 - IDToken string `gorm:"column:id_token;comment:身份验证标识" json:"id_token"` // 身份验证标识 - ContactQQ string `gorm:"column:contact_qq;comment:QQ联系方式" json:"contact_qq"` // QQ联系方式 - ContactWechat string `gorm:"column:contact_wechat;comment:微信联系方式" json:"contact_wechat"` // 微信联系方式 - LastLogin orm.LocalDateTime `gorm:"column:last_login;comment:最后登录时间" json:"last_login"` // 最后登录时间 - LastLoginHost string `gorm:"column:last_login_host;comment:最后登录地址" json:"last_login_host"` // 最后登录地址 - LastLoginAgent string `gorm:"column:last_login_agent;comment:最后登录代理" json:"last_login_agent"` // 最后登录代理 - CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 - DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 + Password string `gorm:"column:password;comment:用户密码" json:"password"` // 用户密码 + Name string `gorm:"column:name;comment:真实姓名" json:"name"` // 真实姓名 + Avatar string `gorm:"column:avatar;comment:头像URL" json:"avatar"` // 头像URL + Status int32 `gorm:"column:status;not null;default:1;comment:用户状态:0-禁用,1-正常" json:"status"` // 用户状态:0-禁用,1-正常 + Balance float64 `gorm:"column:balance;not null;comment:账户余额" json:"balance"` // 账户余额 + IDType int32 `gorm:"column:id_type;not null;comment:认证类型:0-未认证,1-个人认证,2-企业认证" json:"id_type"` // 认证类型:0-未认证,1-个人认证,2-企业认证 + IDNo string `gorm:"column:id_no;comment:身份证号或营业执照号" json:"id_no"` // 身份证号或营业执照号 + IDToken string `gorm:"column:id_token;comment:身份验证标识" json:"id_token"` // 身份验证标识 + ContactQQ string `gorm:"column:contact_qq;comment:QQ联系方式" json:"contact_qq"` // QQ联系方式 + ContactWechat string `gorm:"column:contact_wechat;comment:微信联系方式" json:"contact_wechat"` // 微信联系方式 + LastLogin orm.LocalDateTime `gorm:"column:last_login;comment:最后登录时间" json:"last_login"` // 最后登录时间 + LastLoginHost string `gorm:"column:last_login_host;comment:最后登录地址" json:"last_login_host"` // 最后登录地址 + LastLoginAgent string `gorm:"column:last_login_agent;comment:最后登录代理" json:"last_login_agent"` // 最后登录代理 + CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 } // TableName User's table name diff --git a/web/models/user_role.gen.go b/web/models/user_role.gen.go index f788515..578ab67 100644 --- a/web/models/user_role.gen.go +++ b/web/models/user_role.gen.go @@ -14,11 +14,11 @@ const TableNameUserRole = "user_role" // UserRole mapped from table type UserRole 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 Name string `gorm:"column:name;not null;comment:角色名称" json:"name"` // 角色名称 Description string `gorm:"column:description;comment:角色描述" json:"description"` // 角色描述 Active bool `gorm:"column:active;default:true;comment:是否激活" json:"active"` // 是否激活 - Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序 + Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/user_role_link.gen.go b/web/models/user_role_link.gen.go index 6069002..b6ea6d7 100644 --- a/web/models/user_role_link.gen.go +++ b/web/models/user_role_link.gen.go @@ -14,9 +14,9 @@ const TableNameUserRoleLink = "user_role_link" // UserRoleLink mapped from table type UserRoleLink struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID - UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID - RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID + UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID + RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/user_role_permission_link.gen.go b/web/models/user_role_permission_link.gen.go index 91fcfd7..34ad610 100644 --- a/web/models/user_role_permission_link.gen.go +++ b/web/models/user_role_permission_link.gen.go @@ -14,9 +14,9 @@ const TableNameUserRolePermissionLink = "user_role_permission_link" // UserRolePermissionLink mapped from table type UserRolePermissionLink struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID - RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID - PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID + RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID + PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/models/whitelist.gen.go b/web/models/whitelist.gen.go index 27f80bf..55c08c6 100644 --- a/web/models/whitelist.gen.go +++ b/web/models/whitelist.gen.go @@ -14,10 +14,10 @@ const TableNameWhitelist = "whitelist" // Whitelist mapped from table type Whitelist struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:白名单ID" json:"id"` // 白名单ID - UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID - Host string `gorm:"column:host;not null;comment:IP地址" json:"host"` // IP地址 - Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 + ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:白名单ID" json:"id"` // 白名单ID + UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID + Host string `gorm:"column:host;not null;comment:IP地址" json:"host"` // IP地址 + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间 diff --git a/web/queries/gen.go b/web/queries/gen.go index 095a6a0..5b4db66 100644 --- a/web/queries/gen.go +++ b/web/queries/gen.go @@ -37,6 +37,7 @@ var ( ResourcePps *resourcePps ResourcePsr *resourcePsr ResourcePss *resourcePss + Session *session Trade *trade User *user UserRole *userRole @@ -67,6 +68,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) { ResourcePps = &Q.ResourcePps ResourcePsr = &Q.ResourcePsr ResourcePss = &Q.ResourcePss + Session = &Q.Session Trade = &Q.Trade User = &Q.User UserRole = &Q.UserRole @@ -98,6 +100,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query { ResourcePps: newResourcePps(db, opts...), ResourcePsr: newResourcePsr(db, opts...), ResourcePss: newResourcePss(db, opts...), + Session: newSession(db, opts...), Trade: newTrade(db, opts...), User: newUser(db, opts...), UserRole: newUserRole(db, opts...), @@ -130,6 +133,7 @@ type Query struct { ResourcePps resourcePps ResourcePsr resourcePsr ResourcePss resourcePss + Session session Trade trade User user UserRole userRole @@ -163,6 +167,7 @@ func (q *Query) clone(db *gorm.DB) *Query { ResourcePps: q.ResourcePps.clone(db), ResourcePsr: q.ResourcePsr.clone(db), ResourcePss: q.ResourcePss.clone(db), + Session: q.Session.clone(db), Trade: q.Trade.clone(db), User: q.User.clone(db), UserRole: q.UserRole.clone(db), @@ -203,6 +208,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query { ResourcePps: q.ResourcePps.replaceDB(db), ResourcePsr: q.ResourcePsr.replaceDB(db), ResourcePss: q.ResourcePss.replaceDB(db), + Session: q.Session.replaceDB(db), Trade: q.Trade.replaceDB(db), User: q.User.replaceDB(db), UserRole: q.UserRole.replaceDB(db), @@ -233,6 +239,7 @@ type queryCtx struct { ResourcePps *resourcePpsDo ResourcePsr *resourcePsrDo ResourcePss *resourcePssDo + Session *sessionDo Trade *tradeDo User *userDo UserRole *userRoleDo @@ -263,6 +270,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx { ResourcePps: q.ResourcePps.WithContext(ctx), ResourcePsr: q.ResourcePsr.WithContext(ctx), ResourcePss: q.ResourcePss.WithContext(ctx), + Session: q.Session.WithContext(ctx), Trade: q.Trade.WithContext(ctx), User: q.User.WithContext(ctx), UserRole: q.UserRole.WithContext(ctx), diff --git a/web/queries/session.gen.go b/web/queries/session.gen.go new file mode 100644 index 0000000..b432344 --- /dev/null +++ b/web/queries/session.gen.go @@ -0,0 +1,371 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package queries + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "platform/web/models" +) + +func newSession(db *gorm.DB, opts ...gen.DOOption) session { + _session := session{} + + _session.sessionDo.UseDB(db, opts...) + _session.sessionDo.UseModel(&models.Session{}) + + tableName := _session.sessionDo.TableName() + _session.ALL = field.NewAsterisk(tableName) + _session.ID = field.NewInt32(tableName, "id") + _session.UserID = field.NewInt32(tableName, "user_id") + _session.ClientID = field.NewInt32(tableName, "client_id") + _session.IP = field.NewString(tableName, "ip") + _session.Ua = field.NewString(tableName, "ua") + _session.GrantType = field.NewString(tableName, "grant_type") + _session.AccessToken = field.NewString(tableName, "access_token") + _session.AccessTokenExpires = field.NewField(tableName, "access_token_expires") + _session.RefreshToken = field.NewString(tableName, "refresh_token") + _session.RefreshTokenExpires = field.NewField(tableName, "refresh_token_expires") + _session.Scopes_ = field.NewString(tableName, "scopes") + _session.CreatedAt = field.NewField(tableName, "created_at") + _session.UpdatedAt = field.NewField(tableName, "updated_at") + _session.DeletedAt = field.NewField(tableName, "deleted_at") + + _session.fillFieldMap() + + return _session +} + +type session struct { + sessionDo + + ALL field.Asterisk + ID field.Int32 // 会话ID + UserID field.Int32 // 用户ID + ClientID field.Int32 // 客户端ID + IP field.String // IP地址 + Ua field.String // 用户代理 + GrantType field.String // 授权类型:authorization_code-授权码模式,client_credentials-客户端凭证模式,refresh_token-刷新令牌模式,password-密码模式 + AccessToken field.String // 访问令牌 + AccessTokenExpires field.Field // 访问令牌过期时间 + RefreshToken field.String // 刷新令牌 + RefreshTokenExpires field.Field // 刷新令牌过期时间 + Scopes_ field.String // 权限范围 + CreatedAt field.Field // 创建时间 + UpdatedAt field.Field // 更新时间 + DeletedAt field.Field // 删除时间 + + fieldMap map[string]field.Expr +} + +func (s session) Table(newTableName string) *session { + s.sessionDo.UseTable(newTableName) + return s.updateTableName(newTableName) +} + +func (s session) As(alias string) *session { + s.sessionDo.DO = *(s.sessionDo.As(alias).(*gen.DO)) + return s.updateTableName(alias) +} + +func (s *session) updateTableName(table string) *session { + s.ALL = field.NewAsterisk(table) + s.ID = field.NewInt32(table, "id") + s.UserID = field.NewInt32(table, "user_id") + s.ClientID = field.NewInt32(table, "client_id") + s.IP = field.NewString(table, "ip") + s.Ua = field.NewString(table, "ua") + s.GrantType = field.NewString(table, "grant_type") + s.AccessToken = field.NewString(table, "access_token") + s.AccessTokenExpires = field.NewField(table, "access_token_expires") + s.RefreshToken = field.NewString(table, "refresh_token") + s.RefreshTokenExpires = field.NewField(table, "refresh_token_expires") + s.Scopes_ = field.NewString(table, "scopes") + s.CreatedAt = field.NewField(table, "created_at") + s.UpdatedAt = field.NewField(table, "updated_at") + s.DeletedAt = field.NewField(table, "deleted_at") + + s.fillFieldMap() + + return s +} + +func (s *session) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := s.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (s *session) fillFieldMap() { + s.fieldMap = make(map[string]field.Expr, 14) + s.fieldMap["id"] = s.ID + s.fieldMap["user_id"] = s.UserID + s.fieldMap["client_id"] = s.ClientID + s.fieldMap["ip"] = s.IP + s.fieldMap["ua"] = s.Ua + s.fieldMap["grant_type"] = s.GrantType + s.fieldMap["access_token"] = s.AccessToken + s.fieldMap["access_token_expires"] = s.AccessTokenExpires + s.fieldMap["refresh_token"] = s.RefreshToken + s.fieldMap["refresh_token_expires"] = s.RefreshTokenExpires + s.fieldMap["scopes"] = s.Scopes_ + s.fieldMap["created_at"] = s.CreatedAt + s.fieldMap["updated_at"] = s.UpdatedAt + s.fieldMap["deleted_at"] = s.DeletedAt +} + +func (s session) clone(db *gorm.DB) session { + s.sessionDo.ReplaceConnPool(db.Statement.ConnPool) + return s +} + +func (s session) replaceDB(db *gorm.DB) session { + s.sessionDo.ReplaceDB(db) + return s +} + +type sessionDo struct{ gen.DO } + +func (s sessionDo) Debug() *sessionDo { + return s.withDO(s.DO.Debug()) +} + +func (s sessionDo) WithContext(ctx context.Context) *sessionDo { + return s.withDO(s.DO.WithContext(ctx)) +} + +func (s sessionDo) ReadDB() *sessionDo { + return s.Clauses(dbresolver.Read) +} + +func (s sessionDo) WriteDB() *sessionDo { + return s.Clauses(dbresolver.Write) +} + +func (s sessionDo) Session(config *gorm.Session) *sessionDo { + return s.withDO(s.DO.Session(config)) +} + +func (s sessionDo) Clauses(conds ...clause.Expression) *sessionDo { + return s.withDO(s.DO.Clauses(conds...)) +} + +func (s sessionDo) Returning(value interface{}, columns ...string) *sessionDo { + return s.withDO(s.DO.Returning(value, columns...)) +} + +func (s sessionDo) Not(conds ...gen.Condition) *sessionDo { + return s.withDO(s.DO.Not(conds...)) +} + +func (s sessionDo) Or(conds ...gen.Condition) *sessionDo { + return s.withDO(s.DO.Or(conds...)) +} + +func (s sessionDo) Select(conds ...field.Expr) *sessionDo { + return s.withDO(s.DO.Select(conds...)) +} + +func (s sessionDo) Where(conds ...gen.Condition) *sessionDo { + return s.withDO(s.DO.Where(conds...)) +} + +func (s sessionDo) Order(conds ...field.Expr) *sessionDo { + return s.withDO(s.DO.Order(conds...)) +} + +func (s sessionDo) Distinct(cols ...field.Expr) *sessionDo { + return s.withDO(s.DO.Distinct(cols...)) +} + +func (s sessionDo) Omit(cols ...field.Expr) *sessionDo { + return s.withDO(s.DO.Omit(cols...)) +} + +func (s sessionDo) Join(table schema.Tabler, on ...field.Expr) *sessionDo { + return s.withDO(s.DO.Join(table, on...)) +} + +func (s sessionDo) LeftJoin(table schema.Tabler, on ...field.Expr) *sessionDo { + return s.withDO(s.DO.LeftJoin(table, on...)) +} + +func (s sessionDo) RightJoin(table schema.Tabler, on ...field.Expr) *sessionDo { + return s.withDO(s.DO.RightJoin(table, on...)) +} + +func (s sessionDo) Group(cols ...field.Expr) *sessionDo { + return s.withDO(s.DO.Group(cols...)) +} + +func (s sessionDo) Having(conds ...gen.Condition) *sessionDo { + return s.withDO(s.DO.Having(conds...)) +} + +func (s sessionDo) Limit(limit int) *sessionDo { + return s.withDO(s.DO.Limit(limit)) +} + +func (s sessionDo) Offset(offset int) *sessionDo { + return s.withDO(s.DO.Offset(offset)) +} + +func (s sessionDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *sessionDo { + return s.withDO(s.DO.Scopes(funcs...)) +} + +func (s sessionDo) Unscoped() *sessionDo { + return s.withDO(s.DO.Unscoped()) +} + +func (s sessionDo) Create(values ...*models.Session) error { + if len(values) == 0 { + return nil + } + return s.DO.Create(values) +} + +func (s sessionDo) CreateInBatches(values []*models.Session, batchSize int) error { + return s.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (s sessionDo) Save(values ...*models.Session) error { + if len(values) == 0 { + return nil + } + return s.DO.Save(values) +} + +func (s sessionDo) First() (*models.Session, error) { + if result, err := s.DO.First(); err != nil { + return nil, err + } else { + return result.(*models.Session), nil + } +} + +func (s sessionDo) Take() (*models.Session, error) { + if result, err := s.DO.Take(); err != nil { + return nil, err + } else { + return result.(*models.Session), nil + } +} + +func (s sessionDo) Last() (*models.Session, error) { + if result, err := s.DO.Last(); err != nil { + return nil, err + } else { + return result.(*models.Session), nil + } +} + +func (s sessionDo) Find() ([]*models.Session, error) { + result, err := s.DO.Find() + return result.([]*models.Session), err +} + +func (s sessionDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Session, err error) { + buf := make([]*models.Session, 0, batchSize) + err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (s sessionDo) FindInBatches(result *[]*models.Session, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return s.DO.FindInBatches(result, batchSize, fc) +} + +func (s sessionDo) Attrs(attrs ...field.AssignExpr) *sessionDo { + return s.withDO(s.DO.Attrs(attrs...)) +} + +func (s sessionDo) Assign(attrs ...field.AssignExpr) *sessionDo { + return s.withDO(s.DO.Assign(attrs...)) +} + +func (s sessionDo) Joins(fields ...field.RelationField) *sessionDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Joins(_f)) + } + return &s +} + +func (s sessionDo) Preload(fields ...field.RelationField) *sessionDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Preload(_f)) + } + return &s +} + +func (s sessionDo) FirstOrInit() (*models.Session, error) { + if result, err := s.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*models.Session), nil + } +} + +func (s sessionDo) FirstOrCreate() (*models.Session, error) { + if result, err := s.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*models.Session), nil + } +} + +func (s sessionDo) FindByPage(offset int, limit int) (result []*models.Session, count int64, err error) { + result, err = s.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = s.Offset(-1).Limit(-1).Count() + return +} + +func (s sessionDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = s.Count() + if err != nil { + return + } + + err = s.Offset(offset).Limit(limit).Scan(result) + return +} + +func (s sessionDo) Scan(result interface{}) (err error) { + return s.DO.Scan(result) +} + +func (s sessionDo) Delete(models ...*models.Session) (result gen.ResultInfo, err error) { + return s.DO.Delete(models) +} + +func (s *sessionDo) withDO(do gen.Dao) *sessionDo { + s.DO = *do.(*gen.DO) + return s +} diff --git a/web/services/auth.go b/web/services/auth.go index f7d7b37..4da3433 100644 --- a/web/services/auth.go +++ b/web/services/auth.go @@ -18,21 +18,15 @@ var Auth = &authService{} type authService struct{} // OauthAuthorizationCode 验证授权码 -func (s *authService) OauthAuthorizationCode(ctx context.Context, client *m.Client, code, redirectURI, codeVerifier string) (*TokenDetails, error) { +func (s *authService) OauthAuthorizationCode(ctx context.Context, client *m.Client, code, redirectURI, codeVerifier string) (*auth2.TokenDetails, error) { // TODO: 从数据库验证授权码 return nil, errors.New("TODO") } // OauthClientCredentials 验证客户端凭证 -func (s *authService) OauthClientCredentials(ctx context.Context, client *m.Client, scope ...string) (*TokenDetails, error) { +func (s *authService) OauthClientCredentials(ctx context.Context, client *m.Client, scope ...string) (*auth2.TokenDetails, error) { - var clientType auth2.PayloadType - switch client2.Spec(client.Spec) { - case client2.SpecNative, client2.SpecBrowser: - clientType = auth2.PayloadPublicServer - case client2.SpecWeb, client2.SpecTrusted: - clientType = auth2.PayloadSecuredServer - } + var clientType = auth2.PayloadTypeFromClientSpec(client2.Spec(client.Spec)) var permissions = make(map[string]struct{}, len(scope)) for _, item := range scope { @@ -50,7 +44,7 @@ func (s *authService) OauthClientCredentials(ctx context.Context, client *m.Clie } // todo 数据库定义会话持续时间 - token, err := Session.Create(ctx, authCtx, false) + token, err := auth2.CreateSession(ctx, &authCtx, false) if err != nil { return nil, err } @@ -59,9 +53,9 @@ func (s *authService) OauthClientCredentials(ctx context.Context, client *m.Clie } // OauthRefreshToken 验证刷新令牌 -func (s *authService) OauthRefreshToken(ctx context.Context, _ *m.Client, refreshToken string, scope ...[]string) (*TokenDetails, error) { +func (s *authService) OauthRefreshToken(ctx context.Context, _ *m.Client, refreshToken string, scope ...[]string) (*auth2.TokenDetails, error) { // TODO: 从数据库验证刷新令牌 - details, err := Session.Refresh(ctx, refreshToken) + details, err := auth2.RefreshSession(ctx, refreshToken, true) if err != nil { return nil, err } @@ -70,7 +64,7 @@ func (s *authService) OauthRefreshToken(ctx context.Context, _ *m.Client, refres } // OauthPassword 验证密码 -func (s *authService) OauthPassword(ctx context.Context, _ *m.Client, data *GrantPasswordData, ip, agent string) (*TokenDetails, error) { +func (s *authService) OauthPassword(ctx context.Context, _ *m.Client, data *GrantPasswordData, ip, agent string) (*auth2.TokenDetails, error) { var user *m.User err := q.Q.Transaction(func(tx *q.Query) error { @@ -145,7 +139,7 @@ func (s *authService) OauthPassword(ctx context.Context, _ *m.Client, data *Gran }, } - token, err := Session.Create(ctx, authCtx, data.Remember) + token, err := auth2.CreateSession(ctx, &authCtx, data.Remember) if err != nil { return nil, err } @@ -179,7 +173,7 @@ func (e AuthServiceError) Error() string { return string(e) } -var ( +const ( ErrOauthInvalidRequest = AuthServiceError("invalid_request") ErrOauthInvalidClient = AuthServiceError("invalid_client") ErrOauthInvalidGrant = AuthServiceError("invalid_grant") diff --git a/web/services/channel.go b/web/services/channel.go index 87f61b4..637f23a 100644 --- a/web/services/channel.go +++ b/web/services/channel.go @@ -443,7 +443,7 @@ func calcChannels( } if env.DebugExternalChange && next > count { - step = time.Now() + var step = time.Now() var multiple float64 = 2 // 扩张倍数 var newConfig = g.AutoConfig{ @@ -550,7 +550,7 @@ func calcChannels( // 提交端口配置并更新节点列表 if env.DebugExternalChange { - step = time.Now() + var step = time.Now() var secret = strings.Split(proxy.Secret, ":") gateway := g.NewGateway( diff --git a/web/services/session.go b/web/services/session.go deleted file mode 100644 index b880287..0000000 --- a/web/services/session.go +++ /dev/null @@ -1,226 +0,0 @@ -package services - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "platform/pkg/env" - "platform/web/auth" - g "platform/web/globals" - "time" - - "github.com/google/uuid" - "github.com/redis/go-redis/v9" -) - -// region SessionService - -var Session SessionServiceInter = &sessionService{} - -type SessionServiceInter interface { - // Find 通过访问令牌获取会话信息 - Find(ctx context.Context, token string) (*auth.Context, error) - // Create 创建一个新的会话 - Create(ctx context.Context, authCtx auth.Context, remember bool) (*TokenDetails, error) - // Refresh 刷新一个会话 - Refresh(ctx context.Context, refreshToken string) (*TokenDetails, error) - // Remove 删除会话 - Remove(ctx context.Context, accessToken, refreshToken string) error -} - -type SessionServiceError string - -func (e SessionServiceError) Error() string { - return string(e) -} - -var ( - ErrInvalidToken = SessionServiceError("invalid_token") -) - -type sessionService struct{} - -// Find 通过访问令牌获取会话信息 -func (s *sessionService) Find(ctx context.Context, token string) (*auth.Context, error) { - - // 读取认证数据 - authJSON, err := g.Redis.Get(ctx, accessKey(token)).Result() - if err != nil { - if errors.Is(err, redis.Nil) { - return nil, ErrInvalidToken - } - return nil, err - } - - // 反序列化 - authCtx := new(auth.Context) - if err := json.Unmarshal([]byte(authJSON), authCtx); err != nil { - return nil, err - } - - return authCtx, nil -} - -// Create 创建一个新的会话 -func (s *sessionService) Create(ctx context.Context, authCtx auth.Context, remember bool) (*TokenDetails, error) { - var now = time.Now() - - // 生成令牌组 - accessToken := genToken() - refreshToken := genToken() - - // 序列化认证数据 - authData, err := json.Marshal(authCtx) - if err != nil { - return nil, err - } - - // 序列化刷新令牌数据 - refreshData, err := json.Marshal(RefreshData{ - AuthContext: authCtx, - AccessToken: accessToken, - }) - if err != nil { - return nil, err - } - - // 事务保存数据到 Redis - var accessExpire = time.Duration(env.SessionAccessExpire) * time.Second - var refreshExpire = time.Duration(env.SessionRefreshExpire) * time.Second - - pipe := g.Redis.TxPipeline() - pipe.Set(ctx, accessKey(accessToken), authData, accessExpire) - if remember { - pipe.Set(ctx, refreshKey(refreshToken), refreshData, refreshExpire) - } - _, err = pipe.Exec(ctx) - if err != nil { - return nil, err - } - - return &TokenDetails{ - AccessToken: accessToken, - AccessTokenExpires: now.Add(accessExpire), - RefreshToken: refreshToken, - RefreshTokenExpires: now.Add(refreshExpire), - Auth: authCtx, - }, nil -} - -// Refresh 刷新一个会话 -func (s *sessionService) Refresh(ctx context.Context, refreshToken string) (*TokenDetails, error) { - var now = time.Now() - - rKey := refreshKey(refreshToken) - var tokenDetails *TokenDetails - - // 刷新令牌 - err := g.Redis.Watch(ctx, func(tx *redis.Tx) error { - - // 先获取刷新令牌数据 - refreshJson, err := tx.Get(ctx, rKey).Result() - if err != nil { - if errors.Is(err, redis.Nil) { - return ErrInvalidToken - } - return err - } - - // 解析刷新令牌数据 - refreshData := new(RefreshData) - if err := json.Unmarshal([]byte(refreshJson), refreshData); err != nil { - return err - } - - // 生成新的令牌 - newAccessToken := genToken() - newRefreshToken := genToken() - - authData, err := json.Marshal(refreshData.AuthContext) - if err != nil { - return err - } - newRefreshData, err := json.Marshal(RefreshData{ - AuthContext: refreshData.AuthContext, - AccessToken: newAccessToken, - }) - if err != nil { - return err - } - - pipeline := tx.Pipeline() - - // 保存新的令牌 - var accessExpire = time.Duration(env.SessionAccessExpire) * time.Second - var refreshExpire = time.Duration(env.SessionRefreshExpire) * time.Second - - pipeline.Set(ctx, accessKey(newAccessToken), authData, accessExpire) - pipeline.Set(ctx, refreshKey(newRefreshToken), newRefreshData, refreshExpire) - - // 删除旧的令牌 - pipeline.Del(ctx, accessKey(refreshData.AccessToken)) - pipeline.Del(ctx, refreshKey(refreshToken)) - - _, err = pipeline.Exec(ctx) - if err != nil { - return err - } - - tokenDetails = &TokenDetails{ - AccessToken: newAccessToken, - RefreshToken: newRefreshToken, - AccessTokenExpires: now.Add(accessExpire), - RefreshTokenExpires: now.Add(refreshExpire), - Auth: refreshData.AuthContext, - } - return nil - }, rKey) - if err != nil { - return nil, fmt.Errorf("刷新令牌失败: %w", err) - } - - return tokenDetails, nil -} - -// Remove 删除会话 -func (s *sessionService) Remove(ctx context.Context, accessToken, refreshToken string) error { - g.Redis.Del(ctx, accessKey(accessToken), refreshKey(refreshToken)) - return nil -} - -// 生成一个新的令牌 -func genToken() string { - return uuid.NewString() -} - -// 令牌键的格式为 "session:" -func accessKey(token string) string { - return fmt.Sprintf("session:%s", token) -} - -// 刷新令牌键的格式为 "session:refreshKey:" -func refreshKey(token string) string { - return fmt.Sprintf("session:refresh:%s", token) -} - -// endregion - -type RefreshData struct { - AuthContext auth.Context - AccessToken string -} - -// TokenDetails 存储令牌详细信息 -type TokenDetails struct { - // 访问令牌 - AccessToken string - // 刷新令牌 - RefreshToken string - // 访问令牌过期时间 - AccessTokenExpires time.Time - // 刷新令牌过期时间 - RefreshTokenExpires time.Time - // 认证信息 - Auth auth.Context -}