This commit is contained in:
孟帅
2023-05-12 16:20:22 +08:00
parent f30fd885be
commit 9198a53584
52 changed files with 982 additions and 834 deletions

View File

@@ -91,18 +91,12 @@ import (
) )
// RouterPrefix 路由前缀 // RouterPrefix 路由前缀
// 最终效果:/应用名称/插件模块名称/xxx/xxx // 最终效果:/应用名称/插件模块名称/xxx/xxx。如果你不喜欢现在的路由风格,可以自行调整
func RouterPrefix(ctx context.Context, app, name string) string { func RouterPrefix(ctx context.Context, app, name string) string {
var prefix = "/" var prefix = "/"
switch app {
case consts.AppAdmin: if app != "" {
prefix = g.Cfg().MustGet(ctx, "router.admin.prefix", "/admin").String() prefix = g.Cfg().MustGet(ctx, "router."+app+".prefix", "/"+app+"").String()
case consts.AppApi:
prefix = g.Cfg().MustGet(ctx, "router.api.prefix", "/api").String()
case consts.AppHome:
prefix = g.Cfg().MustGet(ctx, "router.home.prefix", "/home").String()
case consts.AppWebSocket:
prefix = g.Cfg().MustGet(ctx, "router.ws.prefix", "/socket").String()
} }
return prefix + "/" + name return prefix + "/" + name

View File

@@ -11,6 +11,13 @@
> 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整 > 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整
### v2.6.10
updated 2023.05.12
- 增加增加jwt+缓存驱动实现的令牌认证,支持自动续约、可控过期失效策略
- 移除移除旧jwt功能库
- 移除:移除`decimal``mahonia` package
### v2.6.7 ### v2.6.7
updated 2023.05.10 updated 2023.05.10
- 增加增加支付网关集成支付宝、微信支付、QQ支付可通过后台直接配置参数 - 增加增加支付网关集成支付宝、微信支付、QQ支付可通过后台直接配置参数

View File

@@ -3,8 +3,8 @@
目录 目录
- 缓存驱动 - 缓存驱动
- 请求上下文(待写) - 请求上下文
- JWT(待写) - JWT
- 地理定位(待写) - 地理定位(待写)
- 通知(待写) - 通知(待写)
@@ -87,8 +87,68 @@ func test(ctx context.Context) {
``` ```
### JWT ### JWT
- 基于jwt+缓存驱动实现的用户登录令牌功能支持自动续约解决了jwt服务端无法退出问题和jwt令牌无法主动失效问题
#### 配置示例
```yaml
# 登录令牌
token:
secretKey: "hotgo123" # 令牌加密秘钥,考虑安全问题生产环境中请修改默认值
expires: 604800 # 令牌有效期单位秒。默认7天
autoRefresh: true # 是否开启自动刷新过期时间, false|true 默认为true
refreshInterval: 86400 # 刷新间隔单位秒。必须小于expires否则无法触发。默认1天内只允许刷新一次
maxRefreshTimes: 30 # 最大允许刷新次数,-1不限制。默认30次
multiLogin: true # 是否允许多端登录, false|true 默认为true
```
```go ```go
// 待写 package admin
import (
"fmt"
"context"
"hotgo/internal/library/token"
"hotgo/internal/model"
)
func test(ctx context.Context) {
// 登录
user := &model.Identity{
Id: mb.Id,
Pid: mb.Pid,
DeptId: mb.DeptId,
RoleId: ro.Id,
RoleKey: ro.Key,
Username: mb.Username,
RealName: mb.RealName,
Avatar: mb.Avatar,
Email: mb.Email,
Mobile: mb.Mobile,
App: consts.AppAdmin,
LoginAt: gtime.Now(),
}
loginToken, expires, err := token.Login(ctx, user)
if err != nil {
return nil, err
}
// gf请求对象
r := *ghttp.Request
// 获取登录用户信息
user, err := token.ParseLoginUser(r)
if err != nil {
return
}
// 注销登录
err = token.Logout(r)
}
``` ```
### 地理定位 ### 地理定位

View File

@@ -25,7 +25,7 @@ func WebSocket(ctx context.Context, group *ghttp.RouterGroup) {
websocket.Index, websocket.Index,
) )
// ws连接中间件 // ws连接中间件
group.Middleware(service.Middleware().WebSocketToken) group.Middleware(service.Middleware().WebSocketAuth)
group.Bind( group.Bind(
// 需要验证的路由 // 需要验证的路由
// .. // ..

View File

@@ -3,7 +3,6 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package common package common
import ( import (
@@ -13,7 +12,7 @@ import (
// LoginLogoutReq 注销登录 // LoginLogoutReq 注销登录
type LoginLogoutReq struct { type LoginLogoutReq struct {
g.Meta `path:"/site/logout" method:"get" tags:"后台基础" summary:"注销登录"` g.Meta `path:"/site/logout" method:"post" tags:"后台基础" summary:"注销登录"`
} }
type LoginLogoutRes struct{} type LoginLogoutRes struct{}
@@ -21,7 +20,6 @@ type LoginLogoutRes struct{}
type LoginCaptchaReq struct { type LoginCaptchaReq struct {
g.Meta `path:"/site/captcha" method:"get" tags:"后台基础" summary:"获取登录验证码"` g.Meta `path:"/site/captcha" method:"get" tags:"后台基础" summary:"获取登录验证码"`
} }
type LoginCaptchaRes struct { type LoginCaptchaRes struct {
Cid string `json:"cid" dc:"验证码ID"` Cid string `json:"cid" dc:"验证码ID"`
Base64 string `json:"base64" dc:"验证码"` Base64 string `json:"base64" dc:"验证码"`

View File

@@ -3,7 +3,6 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package monitor package monitor
import ( import (
@@ -47,13 +46,12 @@ type OnlineModel struct {
Addr string `json:"addr"` // 客户端地址 Addr string `json:"addr"` // 客户端地址
Os string `json:"os"` // 客户端系统名称 Os string `json:"os"` // 客户端系统名称
Browser string `json:"browser"` // 浏览器 Browser string `json:"browser"` // 浏览器
FirstTime uint64 `json:"firstTime"` // 首次连接时间 FirstTime int64 `json:"firstTime"` // 首次连接时间
HeartbeatTime uint64 `json:"heartbeatTime"` // 用户上次心跳时间 HeartbeatTime uint64 `json:"heartbeatTime"` // 用户上次心跳时间
App string `json:"app"` // 应用名称 App string `json:"app"` // 应用名称
UserId int64 `json:"userId"` // 用户ID UserId int64 `json:"userId"` // 用户ID
Username string `json:"username"` // 用户名 Username string `json:"username"` // 用户名
Avatar string `json:"avatar"` // 头像 Avatar string `json:"avatar"` // 头像
ExpTime int64 `json:"expTime"` // 过期时间
} }
type OnlineModels []*OnlineModel type OnlineModels []*OnlineModel

View File

@@ -10,7 +10,6 @@ require (
github.com/alibabacloud-go/tea-utils/v2 v2.0.1 github.com/alibabacloud-go/tea-utils/v2 v2.0.1
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible
github.com/apache/rocketmq-client-go/v2 v2.1.0 github.com/apache/rocketmq-client-go/v2 v2.1.0
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/casbin/casbin/v2 v2.55.0 github.com/casbin/casbin/v2 v2.55.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/forgoer/openssl v1.4.0 github.com/forgoer/openssl v1.4.0
@@ -18,13 +17,13 @@ require (
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.4.1 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.4.1
github.com/gogf/gf/contrib/nosql/redis/v2 v2.4.1 github.com/gogf/gf/contrib/nosql/redis/v2 v2.4.1
github.com/gogf/gf/v2 v2.4.1 github.com/gogf/gf/v2 v2.4.1
github.com/golang-jwt/jwt/v5 v5.0.0
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794 github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794
github.com/mojocn/base64Captcha v1.3.5 github.com/mojocn/base64Captcha v1.3.5
github.com/olekukonko/tablewriter v0.0.5 github.com/olekukonko/tablewriter v0.0.5
github.com/qiniu/go-sdk/v7 v7.14.0 github.com/qiniu/go-sdk/v7 v7.14.0
github.com/shirou/gopsutil/v3 v3.23.3 github.com/shirou/gopsutil/v3 v3.23.3
github.com/shopspring/decimal v1.3.1
github.com/silenceper/wechat/v2 v2.1.4 github.com/silenceper/wechat/v2 v2.1.4
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.633 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.633
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.633 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.633

View File

@@ -81,8 +81,6 @@ github.com/aliyun/credentials-go v1.1.2 h1:qU1vwGIBb3UJ8BwunHDRFtAhS6jnQLnde/yk0
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/apache/rocketmq-client-go/v2 v2.1.0 h1:3eABKfxc1WmS2lLTTbKMe1gZfZV6u1Sx9orFnOfABV0= github.com/apache/rocketmq-client-go/v2 v2.1.0 h1:3eABKfxc1WmS2lLTTbKMe1gZfZV6u1Sx9orFnOfABV0=
github.com/apache/rocketmq-client-go/v2 v2.1.0/go.mod h1:oEZKFDvS7sz/RWU0839+dQBupazyBV7WX5cP6nrio0Q= github.com/apache/rocketmq-client-go/v2 v2.1.0/go.mod h1:oEZKFDvS7sz/RWU0839+dQBupazyBV7WX5cP6nrio0Q=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@@ -179,6 +177,8 @@ github.com/gogf/gf/contrib/nosql/redis/v2 v2.4.1/go.mod h1:0t7pBtXdfuemskzkdxyC2
github.com/gogf/gf/v2 v2.4.1 h1:snsuvDhNFiRoAuWBbKfIIng0KyMaRA87Qr03GLir5j8= github.com/gogf/gf/v2 v2.4.1 h1:snsuvDhNFiRoAuWBbKfIIng0KyMaRA87Qr03GLir5j8=
github.com/gogf/gf/v2 v2.4.1/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y= github.com/gogf/gf/v2 v2.4.1/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -418,8 +418,6 @@ github.com/shoenig/go-m1cpu v0.1.4 h1:SZPIgRM2sEF9NJy50mRHu9PKGwxyyTTJIWvCtgVboz
github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/silenceper/wechat/v2 v2.1.4 h1:X+G9C/EiBET5AK0zhrflX3ESCP/yxhJUvoRoSXHm0js= github.com/silenceper/wechat/v2 v2.1.4 h1:X+G9C/EiBET5AK0zhrflX3ESCP/yxhJUvoRoSXHm0js=
github.com/silenceper/wechat/v2 v2.1.4/go.mod h1:F0PKqImb15THnwoqRNrZO1z3vpwyWuiHr5zzfnjdECY= github.com/silenceper/wechat/v2 v2.1.4/go.mod h1:F0PKqImb15THnwoqRNrZO1z3vpwyWuiHr5zzfnjdECY=

View File

@@ -7,6 +7,6 @@ package consts
// cache // cache
const ( const (
CacheJwtToken = "jwt_token:" // JWT-token CacheToken = "token" // 登录token
CacheJwtUserBind = "jwt_user_bind:" // JWT-用户身份绑定 CacheTokenBind = "token_bind" // 登录用户身份绑定
) )

View File

@@ -5,7 +5,9 @@
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package consts package consts
import "github.com/gogf/gf/v2/text/gstr" import (
"github.com/gogf/gf/v2/text/gstr"
)
// 错误解释 // 错误解释
const ( const (

View File

@@ -7,5 +7,5 @@ package consts
// VersionApp HotGo版本 // VersionApp HotGo版本
const ( const (
VersionApp = "2.6.7" VersionApp = "2.6.10"
) )

View File

@@ -3,13 +3,13 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package admin package admin
import ( import (
"context" "context"
"github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"hotgo/api/admin/monitor" "hotgo/api/admin/monitor"
"hotgo/internal/consts" "hotgo/internal/consts"
@@ -79,13 +79,12 @@ func (c *cMonitor) OnlineList(ctx context.Context, req *monitor.OnlineListReq) (
Addr: conn.Addr, Addr: conn.Addr,
Os: useragent.GetOs(conn.UserAgent), Os: useragent.GetOs(conn.UserAgent),
Browser: useragent.GetBrowser(conn.UserAgent), Browser: useragent.GetBrowser(conn.UserAgent),
FirstTime: conn.FirstTime, FirstTime: gtime.New(conn.User.LoginAt).Unix(),
HeartbeatTime: conn.HeartbeatTime, HeartbeatTime: conn.HeartbeatTime,
App: conn.User.App, App: conn.User.App,
UserId: conn.User.Id, UserId: conn.User.Id,
Username: conn.User.Username, Username: conn.User.Username,
Avatar: conn.User.Avatar, Avatar: conn.User.Avatar,
ExpTime: conn.User.Exp,
}) })
} }

View File

@@ -7,16 +7,14 @@ package common
import ( import (
"context" "context"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
"hotgo/api/admin/common" "hotgo/api/admin/common"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/library/cache"
"hotgo/internal/library/captcha" "hotgo/internal/library/captcha"
"hotgo/internal/library/jwt" "hotgo/internal/library/token"
"hotgo/internal/model/input/adminin" "hotgo/internal/model/input/adminin"
"hotgo/internal/model/input/sysin" "hotgo/internal/model/input/sysin"
"hotgo/internal/service" "hotgo/internal/service"
@@ -112,13 +110,6 @@ func (c *cSite) Login(ctx context.Context, req *common.LoginReq) (res *common.Lo
// Logout 注销登录 // Logout 注销登录
func (c *cSite) Logout(ctx context.Context, req *common.LoginLogoutReq) (res *common.LoginLogoutRes, err error) { func (c *cSite) Logout(ctx context.Context, req *common.LoginLogoutReq) (res *common.LoginLogoutRes, err error) {
token := consts.CacheJwtToken + gmd5.MustEncryptString(jwt.GetAuthorization(ghttp.RequestFromCtx(ctx))) err = token.Logout(ghttp.RequestFromCtx(ctx))
if len(token) == 0 {
err = gerror.New("当前用户未登录!")
return
}
// 删除登录token
_, err = cache.Instance().Remove(ctx, token)
return return
} }

View File

@@ -27,7 +27,6 @@ type AdminMemberColumns struct {
Username string // 帐号 Username string // 帐号
PasswordHash string // 密码 PasswordHash string // 密码
Salt string // 密码盐 Salt string // 密码盐
AuthKey string // 授权令牌
PasswordResetToken string // 密码重置令牌 PasswordResetToken string // 密码重置令牌
Integral string // 积分 Integral string // 积分
Balance string // 余额 Balance string // 余额
@@ -59,7 +58,6 @@ var adminMemberColumns = AdminMemberColumns{
Username: "username", Username: "username",
PasswordHash: "password_hash", PasswordHash: "password_hash",
Salt: "salt", Salt: "salt",
AuthKey: "auth_key",
PasswordResetToken: "password_reset_token", PasswordResetToken: "password_reset_token",
Integral: "integral", Integral: "integral",
Balance: "balance", Balance: "balance",

View File

@@ -35,7 +35,7 @@ type SysLogColumns struct {
ProvinceId string // 省编码 ProvinceId string // 省编码
CityId string // 市编码 CityId string // 市编码
ErrorCode string // 报错code ErrorCode string // 报错code
ErrorMsg string // 报错信息 ErrorMsg string // 对外错误提示
ErrorData string // 报错日志 ErrorData string // 报错日志
UserAgent string // UA信息 UserAgent string // UA信息
TakeUpTime string // 请求耗时 TakeUpTime string // 请求耗时

View File

@@ -23,15 +23,9 @@ func Tpl(name, tpl string) string {
// 最终效果:/应用名称/插件模块名称/xxx/xxx。如果你不喜欢现在的路由风格可以自行调整 // 最终效果:/应用名称/插件模块名称/xxx/xxx。如果你不喜欢现在的路由风格可以自行调整
func RouterPrefix(ctx context.Context, app, name string) string { func RouterPrefix(ctx context.Context, app, name string) string {
var prefix = "/" var prefix = "/"
switch app {
case consts.AppAdmin: if app != "" {
prefix = g.Cfg().MustGet(ctx, "router.admin.prefix", "/admin").String() prefix = g.Cfg().MustGet(ctx, "router."+app+".prefix", "/"+app+"").String()
case consts.AppApi:
prefix = g.Cfg().MustGet(ctx, "router.api.prefix", "/api").String()
case consts.AppHome:
prefix = g.Cfg().MustGet(ctx, "router.home.prefix", "/home").String()
case consts.AppWebSocket:
prefix = g.Cfg().MustGet(ctx, "router.ws.prefix", "/socket").String()
} }
return prefix + "/" + name return prefix + "/" + name

View File

@@ -1,113 +0,0 @@
// Package jwt
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package jwt
import (
"context"
"fmt"
j "github.com/dgrijalva/jwt-go"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/library/cache"
"hotgo/internal/model"
"time"
)
// GenerateLoginToken 为指定用户生成token
func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh bool) (string, error) {
var (
jwtVersion = g.Cfg().MustGet(ctx, "jwt.version", "1.0")
jwtSign = g.Cfg().MustGet(ctx, "jwt.sign", "hotGo")
token = j.NewWithClaims(j.SigningMethodHS256, j.MapClaims{
"id": user.Id,
"pid": user.Pid,
"deptId": user.DeptId,
"roleId": user.RoleId,
"roleKey": user.RoleKey,
"username": user.Username,
"realName": user.RealName,
"avatar": user.Avatar,
"email": user.Email,
"mobile": user.Mobile,
"exp": user.Exp,
"expires": user.Expires,
"app": user.App,
"isRefresh": isRefresh,
"jwtVersion": jwtVersion.String(),
})
)
tokenString, err := token.SignedString(jwtSign.Bytes())
if err != nil {
return "", err
}
var (
tokenStringMd5 = gmd5.MustEncryptString(tokenString)
// 绑定登录token
key = consts.CacheJwtToken + tokenStringMd5
// 将有效期转为持续时间,单位:秒
expires, _ = time.ParseDuration(fmt.Sprintf("+%vs", user.Expires))
)
err = cache.Instance().Set(ctx, key, tokenString, expires)
if err != nil {
return "", err
}
err = cache.Instance().Set(ctx, consts.CacheJwtUserBind+user.App+":"+gconv.String(user.Id), key, expires)
if err != nil {
return "", err
}
return tokenString, err
}
// ParseToken 解析token
func ParseToken(tokenString string, secret []byte) (j.MapClaims, error) {
if tokenString == "" {
err := gerror.New("token 为空")
return nil, err
}
token, err := j.Parse(tokenString, func(token *j.Token) (interface{}, error) {
if _, ok := token.Method.(*j.SigningMethodHMAC); !ok {
return nil, gerror.Newf("unexpected signing method: %v", token.Header["alg"])
}
return secret, nil
})
if token == nil {
err := gerror.New("token不存在")
return nil, err
}
if claims, ok := token.Claims.(j.MapClaims); ok && token.Valid {
return claims, nil
} else {
return nil, err
}
}
// GetAuthorization 获取authorization
func GetAuthorization(r *ghttp.Request) string {
// 默认从请求头获取
var authorization = r.Header.Get("Authorization")
// 如果请求头不存在则从get参数获取
if authorization == "" {
return r.Get("authorization").String()
}
return gstr.Replace(authorization, "Bearer ", "")
}
func GenAuthKey(token string) string {
return gmd5.MustEncryptString(token)
}

View File

@@ -8,8 +8,8 @@ package location
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/axgle/mahonia"
"github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/encoding/gcharset"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
@@ -67,19 +67,18 @@ func WhoisLocation(ctx context.Context, ip string) (*IpLocationData, error) {
defer response.Close() defer response.Close()
var ( str, err := gcharset.ToUTF8("GBK", response.ReadAllString())
whoisData *WhoisRegionData if err != nil {
enc = mahonia.NewDecoder("gbk") return nil, err
data = enc.ConvertString(response.ReadAllString()) }
)
if err = gconv.Struct(data, &whoisData); err != nil { var whoisData *WhoisRegionData
if err = gconv.Struct([]byte(str), &whoisData); err != nil {
return nil, err return nil, err
} }
return &IpLocationData{ return &IpLocationData{
Ip: whoisData.Ip, Ip: whoisData.Ip,
//Country string `json:"country"`
Region: whoisData.Addr, Region: whoisData.Addr,
Province: whoisData.Pro, Province: whoisData.Pro,
ProvinceCode: gconv.Int64(whoisData.ProCode), ProvinceCode: gconv.Int64(whoisData.ProCode),

View File

@@ -0,0 +1,299 @@
package token
import (
"context"
"fmt"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/golang-jwt/jwt/v5"
"hotgo/internal/consts"
"hotgo/internal/library/cache"
"hotgo/internal/library/contexts"
"hotgo/internal/model"
"hotgo/utility/simple"
"time"
)
type Claims struct {
*model.Identity
jwt.RegisteredClaims
}
type Token struct {
ExpireAt int64 `json:"exp"` // token过期时间
RefreshAt int64 `json:"ra"` // 刷新时间
RefreshCount int64 `json:"rc"` // 刷新次数
}
var (
config *model.TokenConfig
errorLogin = gerror.New("登录身份已失效,请重新登录!")
errorMultiLogin = gerror.New("账号存在异地登录,如非本人操作请及时修改登录密码!")
)
func SetConfig(c *model.TokenConfig) {
config = c
}
func GetConfig() *model.TokenConfig {
return config
}
// Login 登录
func Login(ctx context.Context, user *model.Identity) (string, int64, error) {
claims := Claims{
user,
jwt.RegisteredClaims{},
}
header, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(config.SecretKey))
if err != nil {
return "", 0, err
}
var (
now = gtime.Now()
// 认证key
authKey = GetAuthKey(header)
// 登录token
tokenKey = GetTokenKey(user.App, authKey)
// 身份绑定
bindKey = GetBindKey(user.App, user.Id)
// 有效时长
duration = time.Second * gconv.Duration(config.Expires)
)
token := &Token{
ExpireAt: now.Unix() + config.Expires,
RefreshAt: now.Unix(),
RefreshCount: 0,
}
if err = cache.Instance().Set(ctx, tokenKey, token, duration); err != nil {
return "", 0, err
}
if err = cache.Instance().Set(ctx, bindKey, tokenKey, duration); err != nil {
return "", 0, err
}
return header, config.Expires, nil
}
// Logout 注销登录
func Logout(r *ghttp.Request) (err error) {
var (
ctx = r.Context()
header = GetAuthorization(r)
)
if header == "" {
err = errorLogin
return
}
claims, err := parseToken(ctx, header)
if err != nil {
return
}
var (
// 认证key
authKey = GetAuthKey(header)
// 登录token
tokenKey = GetTokenKey(contexts.GetModule(ctx), authKey)
// 身份绑定
bindKey = GetBindKey(contexts.GetModule(ctx), claims.Id)
)
// 删除token
if _, err = cache.Instance().Remove(ctx, tokenKey); err != nil {
return
}
if !config.MultiLogin {
if _, err = cache.Instance().Remove(ctx, bindKey); err != nil {
return
}
}
return
}
// ParseLoginUser 解析登录用户信息
func ParseLoginUser(r *ghttp.Request) (user *model.Identity, err error) {
var (
ctx = r.Context()
header = GetAuthorization(r)
)
if header == "" {
err = errorLogin
return
}
claims, err := parseToken(ctx, header)
if err != nil {
return
}
var (
authKey = GetAuthKey(header)
// 登录token
tokenKey = GetTokenKey(claims.App, authKey)
// 身份绑定
bindKey = GetBindKey(claims.App, claims.Id)
)
// 检查token是否存在
tk, err := cache.Instance().Get(ctx, tokenKey)
if err != nil {
g.Log().Debugf(ctx, "get tokenKey err:%+v", err)
err = errorLogin
return
}
if tk.IsEmpty() {
g.Log().Debug(ctx, "token isEmpty")
err = errorLogin
return
}
var token *Token
if err = tk.Scan(&token); err != nil {
g.Log().Debugf(ctx, "token scan err:%+v", err)
err = errorLogin
return
}
if token == nil {
g.Log().Debugf(ctx, "token = nil")
err = errorLogin
return
}
now := gtime.Now()
if token.ExpireAt < now.Unix() {
g.Log().Debugf(ctx, "token expired.")
err = errorLogin
return
}
// 是否允许多端登录
if !config.MultiLogin {
origin, err := cache.Instance().Get(ctx, bindKey)
if err != nil {
g.Log().Debugf(ctx, "bindKey get err:%+v", err)
err = errorLogin
return nil, err
}
if origin == nil || origin.IsEmpty() {
g.Log().Debug(ctx, "bindKey isEmpty")
err = errorLogin
return nil, err
}
if tokenKey != origin.String() {
g.Log().Debugf(ctx, "bindKey offsite login tokenKey:%v, origin:%v", tokenKey, origin.String())
err = errorMultiLogin
return nil, err
}
}
// 自动刷新token有效期
refreshToken := func() {
// 未开启自动刷新
if !config.AutoRefresh {
return
}
// 刷新次数已达上限
if config.MaxRefreshTimes != -1 && token.RefreshCount >= config.MaxRefreshTimes {
return
}
// 未达到刷新间隔
if gtime.New(token.RefreshAt).Unix()+config.RefreshInterval > now.Unix() {
return
}
// 刷新有效期
token.ExpireAt = now.Unix() + config.Expires
token.RefreshAt = now.Unix()
token.RefreshCount += 1
duration := time.Second * gconv.Duration(config.Expires)
if err = cache.Instance().Set(ctx, tokenKey, token, duration); err != nil {
return
}
if err = cache.Instance().Set(ctx, bindKey, tokenKey, duration); err != nil {
return
}
}
simple.SafeGo(ctx, func(ctx context.Context) {
refreshToken()
})
user = new(model.Identity)
user = claims.Identity
return
}
// parseToken 解析jwt令牌
func parseToken(ctx context.Context, header string) (*Claims, error) {
token, err := jwt.ParseWithClaims(header, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(config.SecretKey), nil
})
if err != nil {
g.Log().Debugf(ctx, "parseToken err:%+v", err)
return nil, err
}
if !token.Valid {
return nil, errorLogin
}
claims, ok := token.Claims.(*Claims)
if !ok {
return nil, errorLogin
}
return claims, nil
}
// GetAuthorization 获取authorization
func GetAuthorization(r *ghttp.Request) string {
// 默认从请求头获取
var authorization = r.Header.Get("Authorization")
// 如果请求头不存在则从get参数获取
if authorization == "" {
return r.Get("authorization").String()
}
return gstr.Replace(authorization, "Bearer ", "")
}
// GetAuthKey 认证key
func GetAuthKey(token string) string {
return gmd5.MustEncryptString(token)
}
// GetTokenKey 令牌缓存key
func GetTokenKey(appName, authKey string) string {
return fmt.Sprintf("%v:%v:%v", consts.CacheToken, appName, authKey)
}
// GetBindKey 令牌身份绑定key
func GetBindKey(appName string, userId int64) string {
return fmt.Sprintf("%v:%v:%v", consts.CacheTokenBind, appName, userId)
}

View File

@@ -21,7 +21,7 @@ import (
"hotgo/internal/library/contexts" "hotgo/internal/library/contexts"
"hotgo/internal/library/hgorm/handler" "hotgo/internal/library/hgorm/handler"
"hotgo/internal/library/hgorm/hook" "hotgo/internal/library/hgorm/hook"
"hotgo/internal/library/jwt" "hotgo/internal/library/token"
"hotgo/internal/model" "hotgo/internal/model"
"hotgo/internal/model/do" "hotgo/internal/model/do"
"hotgo/internal/model/entity" "hotgo/internal/model/entity"
@@ -663,9 +663,8 @@ func (s *sAdminMember) LoginMemberInfo(ctx context.Context) (res *adminin.LoginM
// Login 提交登录 // Login 提交登录
func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (res *adminin.MemberLoginModel, err error) { func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (res *adminin.MemberLoginModel, err error) {
var ( var (
ro *entity.AdminRole ro *entity.AdminRole
mb *entity.AdminMember mb *entity.AdminMember
expires = g.Cfg().MustGet(ctx, "jwt.expires", 1).Int64()
) )
if err = dao.AdminMember.Ctx(ctx).Where("username", in.Username).Scan(&mb); err != nil { if err = dao.AdminMember.Ctx(ctx).Where("username", in.Username).Scan(&mb); err != nil {
@@ -707,7 +706,7 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
return return
} }
identity := &model.Identity{ user := &model.Identity{
Id: mb.Id, Id: mb.Id,
Pid: mb.Pid, Pid: mb.Pid,
DeptId: mb.DeptId, DeptId: mb.DeptId,
@@ -718,20 +717,17 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
Avatar: mb.Avatar, Avatar: mb.Avatar,
Email: mb.Email, Email: mb.Email,
Mobile: mb.Mobile, Mobile: mb.Mobile,
Exp: gtime.Timestamp() + expires,
Expires: expires,
App: consts.AppAdmin, App: consts.AppAdmin,
LoginAt: gtime.Now(),
} }
token, err := jwt.GenerateLoginToken(ctx, identity, false) loginToken, expires, err := token.Login(ctx, user)
if err != nil { if err != nil {
err = gerror.New(err.Error()) return nil, err
return
} }
update := do.AdminMember{ update := do.AdminMember{
AuthKey: jwt.GenAuthKey(token), LastActiveAt: user.LoginAt,
LastActiveAt: gtime.Now(),
} }
// 更新登录信息 // 更新登录信息
@@ -740,8 +736,8 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
} }
res = &adminin.MemberLoginModel{ res = &adminin.MemberLoginModel{
Id: identity.Id, Id: user.Id,
Token: token, Token: loginToken,
Expires: expires, Expires: expires,
} }

View File

@@ -21,7 +21,6 @@ import (
"hotgo/internal/model/input/adminin" "hotgo/internal/model/input/adminin"
"hotgo/internal/model/input/form" "hotgo/internal/model/input/form"
"hotgo/internal/service" "hotgo/internal/service"
"hotgo/utility/auth"
"hotgo/utility/convert" "hotgo/utility/convert"
"hotgo/utility/tree" "hotgo/utility/tree"
"sort" "sort"
@@ -39,10 +38,6 @@ func init() {
// Verify 验证权限 // Verify 验证权限
func (s *sAdminRole) Verify(ctx context.Context, path, method string) bool { func (s *sAdminRole) Verify(ctx context.Context, path, method string) bool {
if auth.IsExceptAuth(ctx, path) {
return true
}
var ( var (
user = contexts.Get(ctx).User user = contexts.Get(ctx).User
superRoleKey = g.Cfg().MustGet(ctx, "hotgo.admin.superRoleKey") superRoleKey = g.Cfg().MustGet(ctx, "hotgo.admin.superRoleKey")
@@ -57,6 +52,7 @@ func (s *sAdminRole) Verify(ctx context.Context, path, method string) bool {
if service.AdminMember().VerifySuperId(ctx, user.Id) || user.RoleKey == superRoleKey.String() { if service.AdminMember().VerifySuperId(ctx, user.Id) || user.RoleKey == superRoleKey.String() {
return true return true
} }
ok, err := casbin.Enforcer.Enforce(user.RoleKey, path, method) ok, err := casbin.Enforcer.Enforce(user.RoleKey, path, method)
if err != nil { if err != nil {
g.Log().Infof(ctx, "admin Verify Enforce err:%+v", err) g.Log().Infof(ctx, "admin Verify Enforce err:%+v", err)

View File

@@ -19,8 +19,8 @@ import (
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/library/cache" "hotgo/internal/library/cache"
"hotgo/internal/library/contexts" "hotgo/internal/library/contexts"
"hotgo/internal/library/jwt"
"hotgo/internal/library/response" "hotgo/internal/library/response"
"hotgo/internal/library/token"
"hotgo/internal/library/wechat" "hotgo/internal/library/wechat"
"hotgo/internal/model/input/commonin" "hotgo/internal/model/input/commonin"
"hotgo/internal/service" "hotgo/internal/service"
@@ -65,7 +65,7 @@ func (s *sCommonWechat) Authorize(ctx context.Context, in commonin.WechatAuthori
path = gmeta.Get(common.WechatAuthorizeCallReq{}, "path").String() path = gmeta.Get(common.WechatAuthorizeCallReq{}, "path").String()
redirectUri = basic.Domain + prefix + path redirectUri = basic.Domain + prefix + path
memberId = contexts.GetUserId(ctx) memberId = contexts.GetUserId(ctx)
state = s.GetCacheKey(in.Type, jwt.GenAuthKey(jwt.GetAuthorization(request))) state = s.GetCacheKey(in.Type, token.GetAuthKey(token.GetAuthorization(request)))
scope string scope string
) )
@@ -109,14 +109,14 @@ func (s *sCommonWechat) AuthorizeCall(ctx context.Context, in commonin.WechatAut
defer delete(s.temp, in.State) defer delete(s.temp, in.State)
token, err := wechat.GetUserAccessToken(ctx, in.Code) tk, err := wechat.GetUserAccessToken(ctx, in.Code)
if err != nil { if err != nil {
return return
} }
switch data.Type { switch data.Type {
case consts.WechatAuthorizeOpenId: // 设置openid case consts.WechatAuthorizeOpenId: // 设置openid
cache.Instance().Set(ctx, data.State, token.OpenID, time.Hour*24*7) cache.Instance().Set(ctx, data.State, tk.OpenID, time.Hour*24*7)
case consts.WechatAuthorizeBindLogin: // 绑定微信登录 case consts.WechatAuthorizeBindLogin: // 绑定微信登录
// ... // ...
default: default:
@@ -131,7 +131,7 @@ func (s *sCommonWechat) AuthorizeCall(ctx context.Context, in commonin.WechatAut
// GetOpenId 从缓存中获取临时openid // GetOpenId 从缓存中获取临时openid
func (s *sCommonWechat) GetOpenId(ctx context.Context) (openId string, err error) { func (s *sCommonWechat) GetOpenId(ctx context.Context) (openId string, err error) {
request := ghttp.RequestFromCtx(ctx) request := ghttp.RequestFromCtx(ctx)
key := s.GetCacheKey(consts.WechatAuthorizeOpenId, jwt.GenAuthKey(jwt.GetAuthorization(request))) key := s.GetCacheKey(consts.WechatAuthorizeOpenId, token.GetAuthKey(token.GetAuthorization(request)))
date, err := cache.Instance().Get(ctx, key) date, err := cache.Instance().Get(ctx, key)
if err != nil { if err != nil {
err = gerror.Newf("GetOpenId err:%+v", err.Error()) err = gerror.Newf("GetOpenId err:%+v", err.Error())

View File

@@ -3,7 +3,6 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package middleware package middleware
import ( import (
@@ -15,27 +14,35 @@ import (
"hotgo/internal/library/contexts" "hotgo/internal/library/contexts"
"hotgo/internal/library/response" "hotgo/internal/library/response"
"hotgo/internal/service" "hotgo/internal/service"
"hotgo/utility/auth"
) )
// AdminAuth 后台鉴权中间件 // AdminAuth 后台鉴权中间件
func (s *sMiddleware) AdminAuth(r *ghttp.Request) { func (s *sMiddleware) AdminAuth(r *ghttp.Request) {
var ctx = r.Context() var (
// 替换掉模块前缀 ctx = r.Context()
routerPrefix := g.Cfg().MustGet(ctx, "router.admin.prefix", "/admin") prefix = g.Cfg().MustGet(ctx, "router.admin.prefix", "/admin").String()
path := gstr.Replace(r.URL.Path, routerPrefix.String(), "", 1) path = gstr.Replace(r.URL.Path, prefix, "", 1)
)
/// 不需要验证登录的路由地址 // 不需要验证登录的路由地址
if auth.IsExceptLogin(ctx, path) { if isExceptLogin(ctx, consts.AppAdmin, path) {
r.Middleware.Next() r.Middleware.Next()
return return
} }
if err := inspectAuth(r, consts.AppAdmin); err != nil { // 将用户信息传递到上下文中
if err := deliverUserContext(r); err != nil {
g.Log().Warningf(ctx, "deliverUserContext err:%+v", err)
response.JsonExit(r, gcode.CodeNotAuthorized.Code(), err.Error()) response.JsonExit(r, gcode.CodeNotAuthorized.Code(), err.Error())
return return
} }
// 不需要验证权限的路由地址
if isExceptAuth(ctx, consts.AppAdmin, path) {
r.Middleware.Next()
return
}
// 验证路由访问权限 // 验证路由访问权限
if !service.AdminRole().Verify(ctx, path, r.Method) { if !service.AdminRole().Verify(ctx, path, r.Method) {
g.Log().Debugf(ctx, "AdminAuth fail path:%+v, GetRoleKey:%+v, r.Method:%+v", path, contexts.GetRoleKey(ctx), r.Method) g.Log().Debugf(ctx, "AdminAuth fail path:%+v, GetRoleKey:%+v, r.Method:%+v", path, contexts.GetRoleKey(ctx), r.Method)

View File

@@ -3,7 +3,6 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package middleware package middleware
import ( import (
@@ -13,34 +12,30 @@ import (
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/library/response" "hotgo/internal/library/response"
"hotgo/utility/auth"
) )
// ApiAuth API鉴权中间件 // ApiAuth API鉴权中间件
func (s *sMiddleware) ApiAuth(r *ghttp.Request) { func (s *sMiddleware) ApiAuth(r *ghttp.Request) {
var ctx = r.Context() var (
ctx = r.Context()
prefix = g.Cfg().MustGet(ctx, "router.api.prefix", "/api").String()
path = gstr.Replace(r.URL.Path, prefix, "", 1)
)
// 替换掉模块前缀 // 不需要验证登录的路由地址
routerPrefix := g.Cfg().MustGet(ctx, "router.api.prefix", "/api") if isExceptLogin(ctx, consts.AppApi, path) {
path := gstr.Replace(r.URL.Path, routerPrefix.String(), "", 1)
/// 不需要验证登录的路由地址
if auth.IsExceptLogin(ctx, path) {
r.Middleware.Next() r.Middleware.Next()
return return
} }
if err := inspectAuth(r, consts.AppAdmin); err != nil { // 将用户信息传递到上下文中
if err := deliverUserContext(r); err != nil {
response.JsonExit(r, gcode.CodeNotAuthorized.Code(), err.Error()) response.JsonExit(r, gcode.CodeNotAuthorized.Code(), err.Error())
return return
} }
//// 验证路由访问权限 // 验证路由访问权限
//verify := service.AdminRole().Verify(ctx, path, r.Method) // ...
//if !verify {
// response.JsonExit(r, consts.CodeSecurityReason, "你没有访问权限!")
// return
//}
r.Middleware.Next() r.Middleware.Next()
} }

View File

@@ -6,22 +6,21 @@
package middleware package middleware
import ( import (
"github.com/gogf/gf/v2/crypto/gmd5" "context"
"fmt"
"github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/library/addons" "hotgo/internal/library/addons"
"hotgo/internal/library/cache"
"hotgo/internal/library/contexts" "hotgo/internal/library/contexts"
"hotgo/internal/library/jwt"
"hotgo/internal/library/response" "hotgo/internal/library/response"
"hotgo/internal/library/token"
"hotgo/internal/model" "hotgo/internal/model"
"hotgo/internal/service" "hotgo/internal/service"
"hotgo/utility/validate"
"net/http" "net/http"
"strings" "strings"
) )
@@ -33,10 +32,10 @@ type sMiddleware struct {
} }
func init() { func init() {
service.RegisterMiddleware(New()) service.RegisterMiddleware(NewMiddleware())
} }
func New() *sMiddleware { func NewMiddleware() *sMiddleware {
return &sMiddleware{ return &sMiddleware{
LoginUrl: "/common", LoginUrl: "/common",
DemoWhiteList: g.Map{ DemoWhiteList: g.Map{
@@ -124,85 +123,38 @@ func (s *sMiddleware) Addon(r *ghttp.Request) {
r.Middleware.Next() r.Middleware.Next()
} }
// inspectAuth 检查并完成身份认证 // deliverUserContext 将用户信息传递到上下文中
func inspectAuth(r *ghttp.Request, appName string) (err error) { func deliverUserContext(r *ghttp.Request) (err error) {
var ( user, err := token.ParseLoginUser(r)
ctx = r.Context() if err != nil {
user = new(model.Identity)
authorization = jwt.GetAuthorization(r)
customCtx = &model.Context{}
)
if authorization == "" {
err = gerror.New("请先登录!")
return return
} }
contexts.SetUser(r.Context(), user)
// 获取jwtToken
jwtToken := consts.CacheJwtToken + gmd5.MustEncryptString(authorization)
jwtSign := g.Cfg().MustGet(ctx, "jwt.sign", "hotgo")
data, parseErr := jwt.ParseToken(authorization, jwtSign.Bytes())
if parseErr != nil {
err = gerror.Newf("token不正确或已过期! err :%+v", parseErr.Error())
return
}
if parseErr = gconv.Struct(data, &user); parseErr != nil {
err = gerror.Newf("登录信息解析异常,请重新登录! err :%+v", parseErr.Error())
return
}
// 判断token跟redis的缓存的token是否一样
isContains, containsErr := cache.Instance().Contains(ctx, jwtToken)
if containsErr != nil {
err = gerror.Newf("token无效 err :%+v", containsErr.Error())
return
}
if !isContains {
err = gerror.Newf("token已过期")
return
}
// 是否开启多端登录
if !g.Cfg().MustGet(ctx, "jwt.multiPort", true).Bool() {
key := consts.CacheJwtUserBind + appName + ":" + gconv.String(user.Id)
originJwtToken, originErr := cache.Instance().Get(ctx, key)
if originErr != nil {
err = gerror.Newf("信息异常,请重新登录! err :%+v", originErr.Error())
return
}
if originJwtToken == nil || originJwtToken.IsEmpty() {
err = gerror.New("token已过期")
return
}
if jwtToken != originJwtToken.String() {
err = gerror.New("账号已在其他地方登录!")
return
}
}
// 保存到上下文
if user != nil {
customCtx.User = &model.Identity{
Id: user.Id,
Pid: user.Pid,
DeptId: user.DeptId,
RoleId: user.RoleId,
RoleKey: user.RoleKey,
Username: user.Username,
RealName: user.RealName,
Avatar: user.Avatar,
Email: user.Email,
Mobile: user.Mobile,
Exp: user.Exp,
Expires: user.Expires,
App: user.App,
}
}
contexts.SetUser(ctx, customCtx.User)
return return
} }
// isExceptAuth 是否是不需要验证权限的路由地址
func isExceptAuth(ctx context.Context, appName, path string) bool {
pathList := g.Cfg().MustGet(ctx, fmt.Sprintf("router.%v.exceptAuth", appName)).Strings()
for i := 0; i < len(pathList); i++ {
if validate.InSliceExistStr(pathList[i], path) {
return true
}
}
return false
}
// isExceptLogin 是否是不需要登录的路由地址
func isExceptLogin(ctx context.Context, appName, path string) bool {
pathList := g.Cfg().MustGet(ctx, fmt.Sprintf("router.%v.exceptLogin", appName)).Strings()
for i := 0; i < len(pathList); i++ {
if validate.InSliceExistStr(pathList[i], path) {
return true
}
}
return false
}

View File

@@ -3,7 +3,6 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package middleware package middleware
import ( import (
@@ -13,24 +12,24 @@ import (
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/library/response" "hotgo/internal/library/response"
"hotgo/utility/auth"
) )
// WebSocketToken 检查ws连接token // WebSocketAuth websocket鉴权中间件
func (s *sMiddleware) WebSocketToken(r *ghttp.Request) { func (s *sMiddleware) WebSocketAuth(r *ghttp.Request) {
var ctx = r.Context() var (
ctx = r.Context()
prefix = g.Cfg().MustGet(ctx, "router.websocket.prefix", "/websocket").String()
path = gstr.Replace(r.URL.Path, prefix, "", 1)
)
// 替换掉模块前缀 // 不需要验证登录的路由地址
routerPrefix := g.Cfg().MustGet(ctx, "router.ws.prefix", "/socket") if isExceptLogin(ctx, consts.AppWebSocket, path) {
path := gstr.Replace(r.URL.Path, routerPrefix.String(), "", 1)
/// 不需要验证登录的路由地址
if auth.IsExceptLogin(ctx, path) {
r.Middleware.Next() r.Middleware.Next()
return return
} }
if err := inspectAuth(r, consts.AppAdmin); err != nil { // 将用户信息传递到上下文中
if err := deliverUserContext(r); err != nil {
response.JsonExit(r, gcode.CodeNotAuthorized.Code(), err.Error()) response.JsonExit(r, gcode.CodeNotAuthorized.Code(), err.Error())
return return
} }

View File

@@ -17,6 +17,7 @@ import (
"hotgo/internal/consts" "hotgo/internal/consts"
"hotgo/internal/dao" "hotgo/internal/dao"
"hotgo/internal/library/payment" "hotgo/internal/library/payment"
"hotgo/internal/library/token"
"hotgo/internal/library/wechat" "hotgo/internal/library/wechat"
"hotgo/internal/model" "hotgo/internal/model"
"hotgo/internal/model/entity" "hotgo/internal/model/entity"
@@ -74,6 +75,12 @@ func (s *sSysConfig) InitConfig(ctx context.Context) {
} }
payment.SetConfig(pay) payment.SetConfig(pay)
tk, err := s.GetLoadToken(ctx)
if err != nil {
g.Log().Fatalf(ctx, "init token conifg fail%+v", err)
}
token.SetConfig(tk)
} }
// GetLoadTCP 获取本地tcp配置 // GetLoadTCP 获取本地tcp配置
@@ -94,6 +101,12 @@ func (s *sSysConfig) GetLoadGenerate(ctx context.Context) (conf *model.GenerateC
return return
} }
// GetLoadToken 获取本地token配置
func (s *sSysConfig) GetLoadToken(ctx context.Context) (conf *model.TokenConfig, err error) {
err = g.Cfg().MustGet(ctx, "token").Scan(&conf)
return
}
// GetWechat 获取微信配置 // GetWechat 获取微信配置
func (s *sSysConfig) GetWechat(ctx context.Context) (conf *model.WechatConfig, err error) { func (s *sSysConfig) GetWechat(ctx context.Context) (conf *model.WechatConfig, err error) {
models, err := s.GetConfigByGroup(ctx, sysin.GetConfigInp{Group: "wechat"}) models, err := s.GetConfigByGroup(ctx, sysin.GetConfigInp{Group: "wechat"})

View File

@@ -261,7 +261,18 @@ type TCPClientConnConfig struct {
SecretKey string `json:"secretKey"` SecretKey string `json:"secretKey"`
} }
// TCPConfig tcp服务器配置
type TCPConfig struct { type TCPConfig struct {
Server *TCPServerConfig `json:"server"` Server *TCPServerConfig `json:"server"`
Client *TCPClientConfig `json:"client"` Client *TCPClientConfig `json:"client"`
} }
// TokenConfig 登录令牌配置
type TokenConfig struct {
SecretKey string `json:"secretKey"`
Expires int64 `json:"expires"`
AutoRefresh bool `json:"autoRefresh"`
RefreshInterval int64 `json:"refreshInterval"`
MaxRefreshTimes int64 `json:"maxRefreshTimes"`
MultiLogin bool `json:"multiLogin"`
}

View File

@@ -7,6 +7,7 @@ package model
import ( import (
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
) )
// Context 请求上下文结构 // Context 请求上下文结构
@@ -20,17 +21,16 @@ type Context struct {
// Identity 通用身份模型 // Identity 通用身份模型
type Identity struct { type Identity struct {
Id int64 `json:"id" description:"用户ID"` Id int64 `json:"id" description:"用户ID"`
Pid int64 `json:"pid" description:"上级ID"` Pid int64 `json:"pid" description:"上级ID"`
DeptId int64 `json:"deptId" description:"部门ID"` DeptId int64 `json:"deptId" description:"部门ID"`
RoleId int64 `json:"roleId" description:"角色ID"` RoleId int64 `json:"roleId" description:"角色ID"`
RoleKey string `json:"roleKey" description:"角色唯一标识符"` RoleKey string `json:"roleKey" description:"角色唯一标识符"`
Username string `json:"username" description:"用户名"` Username string `json:"username" description:"用户名"`
RealName string `json:"realName" description:"姓名"` RealName string `json:"realName" description:"姓名"`
Avatar string `json:"avatar" description:"头像"` Avatar string `json:"avatar" description:"头像"`
Email string `json:"email" description:"邮箱"` Email string `json:"email" description:"邮箱"`
Mobile string `json:"mobile" description:"手机号码"` Mobile string `json:"mobile" description:"手机号码"`
Exp int64 `json:"exp" description:"登录有效期截止时间戳"` App string `json:"app" description:"登录应用"`
Expires int64 `json:"expires" description:"登录有效期"` LoginAt *gtime.Time `json:"loginAt" description:"登录时间"`
App string `json:"app" description:"登录应用"`
} }

View File

@@ -20,7 +20,6 @@ type AdminMember struct {
Username interface{} // 帐号 Username interface{} // 帐号
PasswordHash interface{} // 密码 PasswordHash interface{} // 密码
Salt interface{} // 密码盐 Salt interface{} // 密码盐
AuthKey interface{} // 授权令牌
PasswordResetToken interface{} // 密码重置令牌 PasswordResetToken interface{} // 密码重置令牌
Integral interface{} // 积分 Integral interface{} // 积分
Balance interface{} // 余额 Balance interface{} // 余额

View File

@@ -28,7 +28,7 @@ type SysLog struct {
ProvinceId interface{} // 省编码 ProvinceId interface{} // 省编码
CityId interface{} // 市编码 CityId interface{} // 市编码
ErrorCode interface{} // 报错code ErrorCode interface{} // 报错code
ErrorMsg interface{} // 报错信息 ErrorMsg interface{} // 对外错误提示
ErrorData *gjson.Json // 报错日志 ErrorData *gjson.Json // 报错日志
UserAgent interface{} // UA信息 UserAgent interface{} // UA信息
TakeUpTime interface{} // 请求耗时 TakeUpTime interface{} // 请求耗时

View File

@@ -18,7 +18,6 @@ type AdminMember struct {
Username string `json:"username" description:"帐号"` Username string `json:"username" description:"帐号"`
PasswordHash string `json:"passwordHash" description:"密码"` PasswordHash string `json:"passwordHash" description:"密码"`
Salt string `json:"salt" description:"密码盐"` Salt string `json:"salt" description:"密码盐"`
AuthKey string `json:"authKey" description:"授权令牌"`
PasswordResetToken string `json:"passwordResetToken" description:"密码重置令牌"` PasswordResetToken string `json:"passwordResetToken" description:"密码重置令牌"`
Integral float64 `json:"integral" description:"积分"` Integral float64 `json:"integral" description:"积分"`
Balance float64 `json:"balance" description:"余额"` Balance float64 `json:"balance" description:"余额"`

View File

@@ -26,7 +26,7 @@ type SysLog struct {
ProvinceId int64 `json:"provinceId" description:"省编码"` ProvinceId int64 `json:"provinceId" description:"省编码"`
CityId int64 `json:"cityId" description:"市编码"` CityId int64 `json:"cityId" description:"市编码"`
ErrorCode int `json:"errorCode" description:"报错code"` ErrorCode int `json:"errorCode" description:"报错code"`
ErrorMsg string `json:"errorMsg" description:"报错信息"` ErrorMsg string `json:"errorMsg" description:"对外错误提示"`
ErrorData *gjson.Json `json:"errorData" description:"报错日志"` ErrorData *gjson.Json `json:"errorData" description:"报错日志"`
UserAgent string `json:"userAgent" description:"UA信息"` UserAgent string `json:"userAgent" description:"UA信息"`
TakeUpTime int64 `json:"takeUpTime" description:"请求耗时"` TakeUpTime int64 `json:"takeUpTime" description:"请求耗时"`

View File

@@ -3,7 +3,6 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package router package router
import ( import (
@@ -27,7 +26,7 @@ func WebSocket(ctx context.Context, group *ghttp.RouterGroup) {
) )
// ws连接中间件 // ws连接中间件
group.Middleware(service.Middleware().WebSocketToken) group.Middleware(service.Middleware().WebSocketAuth)
// ws // ws
group.GET("/", websocket.WsPage) group.GET("/", websocket.WsPage)

View File

@@ -19,6 +19,86 @@ import (
) )
type ( type (
IAdminRole interface {
Verify(ctx context.Context, path, method string) bool
List(ctx context.Context, in adminin.RoleListInp) (res *adminin.RoleListModel, totalCount int, err error)
GetName(ctx context.Context, RoleId int64) (name string, err error)
GetMemberList(ctx context.Context, RoleId int64) (list []*adminin.RoleListModel, err error)
GetPermissions(ctx context.Context, reqInfo *role.GetPermissionsReq) (MenuIds []int64, err error)
UpdatePermissions(ctx context.Context, reqInfo *role.UpdatePermissionsReq) (err error)
Edit(ctx context.Context, in *role.EditReq) (err error)
Delete(ctx context.Context, in *role.DeleteReq) (err error)
DataScopeSelect(ctx context.Context) (res form.Selects)
DataScopeEdit(ctx context.Context, in *adminin.DataScopeEditInp) (err error)
}
IAdminNotice interface {
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
Delete(ctx context.Context, in adminin.NoticeDeleteInp) (err error)
Edit(ctx context.Context, in adminin.NoticeEditInp) (err error)
Status(ctx context.Context, in adminin.NoticeStatusInp) (err error)
MaxSort(ctx context.Context, in adminin.NoticeMaxSortInp) (res *adminin.NoticeMaxSortModel, err error)
View(ctx context.Context, in adminin.NoticeViewInp) (res *adminin.NoticeViewModel, err error)
List(ctx context.Context, in adminin.NoticeListInp) (list []*adminin.NoticeListModel, totalCount int, err error)
PullMessages(ctx context.Context, in adminin.PullMessagesInp) (res *adminin.PullMessagesModel, err error)
UnreadCount(ctx context.Context, in adminin.NoticeUnreadCountInp) (res *adminin.NoticeUnreadCountModel, err error)
UpRead(ctx context.Context, in adminin.NoticeUpReadInp) (err error)
ReadAll(ctx context.Context, in adminin.NoticeReadAllInp) (err error)
MessageList(ctx context.Context, in adminin.NoticeMessageListInp) (list []*adminin.NoticeMessageListModel, totalCount int, err error)
}
IAdminCash interface {
View(ctx context.Context, in adminin.CashViewInp) (res *adminin.CashViewModel, err error)
List(ctx context.Context, in adminin.CashListInp) (list []*adminin.CashListModel, totalCount int, err error)
Apply(ctx context.Context, in adminin.CashApplyInp) (err error)
Payment(ctx context.Context, in adminin.CashPaymentInp) (err error)
}
IAdminCreditsLog interface {
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
SaveBalance(ctx context.Context, in adminin.CreditsLogSaveBalanceInp) (res *adminin.CreditsLogSaveBalanceModel, err error)
SaveIntegral(ctx context.Context, in adminin.CreditsLogSaveIntegralInp) (res *adminin.CreditsLogSaveIntegralModel, err error)
List(ctx context.Context, in adminin.CreditsLogListInp) (list []*adminin.CreditsLogListModel, totalCount int, err error)
Export(ctx context.Context, in adminin.CreditsLogListInp) (err error)
}
IAdminDept interface {
NameUnique(ctx context.Context, in adminin.DeptNameUniqueInp) (res *adminin.DeptNameUniqueModel, err error)
Delete(ctx context.Context, in adminin.DeptDeleteInp) (err error)
Edit(ctx context.Context, in adminin.DeptEditInp) (err error)
Status(ctx context.Context, in adminin.DeptStatusInp) (err error)
MaxSort(ctx context.Context, in adminin.DeptMaxSortInp) (res *adminin.DeptMaxSortModel, err error)
View(ctx context.Context, in adminin.DeptViewInp) (res *adminin.DeptViewModel, err error)
Option(ctx context.Context, in adminin.DeptOptionInp) (res *adminin.DeptOptionModel, totalCount int, err error)
List(ctx context.Context, in adminin.DeptListInp) (res *adminin.DeptListModel, err error)
GetName(ctx context.Context, id int64) (name string, err error)
}
IAdminMember interface {
AddBalance(ctx context.Context, in adminin.MemberAddBalanceInp) (err error)
AddIntegral(ctx context.Context, in adminin.MemberAddIntegralInp) (err error)
UpdateCash(ctx context.Context, in adminin.MemberUpdateCashInp) (err error)
UpdateEmail(ctx context.Context, in adminin.MemberUpdateEmailInp) (err error)
UpdateMobile(ctx context.Context, in adminin.MemberUpdateMobileInp) (err error)
UpdateProfile(ctx context.Context, in adminin.MemberUpdateProfileInp) (err error)
UpdatePwd(ctx context.Context, in adminin.MemberUpdatePwdInp) (err error)
ResetPwd(ctx context.Context, in adminin.MemberResetPwdInp) (err error)
EmailUnique(ctx context.Context, in adminin.MemberEmailUniqueInp) (res *adminin.MemberEmailUniqueModel, err error)
MobileUnique(ctx context.Context, in adminin.MemberMobileUniqueInp) (res *adminin.MemberMobileUniqueModel, err error)
NameUnique(ctx context.Context, in adminin.MemberNameUniqueInp) (res *adminin.MemberNameUniqueModel, err error)
VerifySuperId(ctx context.Context, verifyId int64) bool
Delete(ctx context.Context, in adminin.MemberDeleteInp) (err error)
Edit(ctx context.Context, in adminin.MemberEditInp) (err error)
View(ctx context.Context, in adminin.MemberViewInp) (res *adminin.MemberViewModel, err error)
List(ctx context.Context, in adminin.MemberListInp) (list []*adminin.MemberListModel, totalCount int, err error)
LoginMemberInfo(ctx context.Context) (res *adminin.LoginMemberInfoModel, err error)
Login(ctx context.Context, in adminin.MemberLoginInp) (res *adminin.MemberLoginModel, err error)
RoleMemberList(ctx context.Context, in adminin.RoleMemberListInp) (list []*adminin.MemberListModel, totalCount int, err error)
Status(ctx context.Context, in adminin.MemberStatusInp) (err error)
GetIdByCode(ctx context.Context, in adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error)
Select(ctx context.Context, in adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error)
FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model
MemberLoginStat(ctx context.Context, in adminin.MemberLoginStatInp) (res *adminin.MemberLoginStatModel, err error)
}
IAdminMemberPost interface {
UpdatePostIds(ctx context.Context, memberId int64, postIds []int64) (err error)
GetMemberByIds(ctx context.Context, memberId int64) (postIds []int64, err error)
}
IAdminMenu interface { IAdminMenu interface {
MaxSort(ctx context.Context, req *menu.MaxSortReq) (res *menu.MaxSortRes, err error) MaxSort(ctx context.Context, req *menu.MaxSortReq) (res *menu.MaxSortRes, err error)
NameUnique(ctx context.Context, req *menu.NameUniqueReq) (res *menu.NameUniqueRes, err error) NameUnique(ctx context.Context, req *menu.NameUniqueReq) (res *menu.NameUniqueRes, err error)
@@ -47,69 +127,6 @@ type (
View(ctx context.Context, in adminin.OrderViewInp) (res *adminin.OrderViewModel, err error) View(ctx context.Context, in adminin.OrderViewInp) (res *adminin.OrderViewModel, err error)
Status(ctx context.Context, in adminin.OrderStatusInp) (err error) Status(ctx context.Context, in adminin.OrderStatusInp) (err error)
} }
IAdminRole interface {
Verify(ctx context.Context, path, method string) bool
List(ctx context.Context, in adminin.RoleListInp) (res *adminin.RoleListModel, totalCount int, err error)
GetName(ctx context.Context, RoleId int64) (name string, err error)
GetMemberList(ctx context.Context, RoleId int64) (list []*adminin.RoleListModel, err error)
GetPermissions(ctx context.Context, reqInfo *role.GetPermissionsReq) (MenuIds []int64, err error)
UpdatePermissions(ctx context.Context, reqInfo *role.UpdatePermissionsReq) (err error)
Edit(ctx context.Context, in *role.EditReq) (err error)
Delete(ctx context.Context, in *role.DeleteReq) (err error)
DataScopeSelect(ctx context.Context) (res form.Selects)
DataScopeEdit(ctx context.Context, in *adminin.DataScopeEditInp) (err error)
}
IAdminCreditsLog interface {
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
SaveBalance(ctx context.Context, in adminin.CreditsLogSaveBalanceInp) (res *adminin.CreditsLogSaveBalanceModel, err error)
SaveIntegral(ctx context.Context, in adminin.CreditsLogSaveIntegralInp) (res *adminin.CreditsLogSaveIntegralModel, err error)
List(ctx context.Context, in adminin.CreditsLogListInp) (list []*adminin.CreditsLogListModel, totalCount int, err error)
Export(ctx context.Context, in adminin.CreditsLogListInp) (err error)
}
IAdminMemberPost interface {
UpdatePostIds(ctx context.Context, memberId int64, postIds []int64) (err error)
GetMemberByIds(ctx context.Context, memberId int64) (postIds []int64, err error)
}
IAdminMember interface {
AddBalance(ctx context.Context, in adminin.MemberAddBalanceInp) (err error)
AddIntegral(ctx context.Context, in adminin.MemberAddIntegralInp) (err error)
UpdateCash(ctx context.Context, in adminin.MemberUpdateCashInp) (err error)
UpdateEmail(ctx context.Context, in adminin.MemberUpdateEmailInp) (err error)
UpdateMobile(ctx context.Context, in adminin.MemberUpdateMobileInp) (err error)
UpdateProfile(ctx context.Context, in adminin.MemberUpdateProfileInp) (err error)
UpdatePwd(ctx context.Context, in adminin.MemberUpdatePwdInp) (err error)
ResetPwd(ctx context.Context, in adminin.MemberResetPwdInp) (err error)
EmailUnique(ctx context.Context, in adminin.MemberEmailUniqueInp) (res *adminin.MemberEmailUniqueModel, err error)
MobileUnique(ctx context.Context, in adminin.MemberMobileUniqueInp) (res *adminin.MemberMobileUniqueModel, err error)
NameUnique(ctx context.Context, in adminin.MemberNameUniqueInp) (res *adminin.MemberNameUniqueModel, err error)
VerifySuperId(ctx context.Context, verifyId int64) bool
Delete(ctx context.Context, in adminin.MemberDeleteInp) (err error)
Edit(ctx context.Context, in adminin.MemberEditInp) (err error)
View(ctx context.Context, in adminin.MemberViewInp) (res *adminin.MemberViewModel, err error)
List(ctx context.Context, in adminin.MemberListInp) (list []*adminin.MemberListModel, totalCount int, err error)
LoginMemberInfo(ctx context.Context) (res *adminin.LoginMemberInfoModel, err error)
Login(ctx context.Context, in adminin.MemberLoginInp) (res *adminin.MemberLoginModel, err error)
RoleMemberList(ctx context.Context, in adminin.RoleMemberListInp) (list []*adminin.MemberListModel, totalCount int, err error)
Status(ctx context.Context, in adminin.MemberStatusInp) (err error)
GetIdByCode(ctx context.Context, in adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error)
Select(ctx context.Context, in adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error)
FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model
MemberLoginStat(ctx context.Context, in adminin.MemberLoginStatInp) (res *adminin.MemberLoginStatModel, err error)
}
IAdminNotice interface {
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
Delete(ctx context.Context, in adminin.NoticeDeleteInp) (err error)
Edit(ctx context.Context, in adminin.NoticeEditInp) (err error)
Status(ctx context.Context, in adminin.NoticeStatusInp) (err error)
MaxSort(ctx context.Context, in adminin.NoticeMaxSortInp) (res *adminin.NoticeMaxSortModel, err error)
View(ctx context.Context, in adminin.NoticeViewInp) (res *adminin.NoticeViewModel, err error)
List(ctx context.Context, in adminin.NoticeListInp) (list []*adminin.NoticeListModel, totalCount int, err error)
PullMessages(ctx context.Context, in adminin.PullMessagesInp) (res *adminin.PullMessagesModel, err error)
UnreadCount(ctx context.Context, in adminin.NoticeUnreadCountInp) (res *adminin.NoticeUnreadCountModel, err error)
UpRead(ctx context.Context, in adminin.NoticeUpReadInp) (err error)
ReadAll(ctx context.Context, in adminin.NoticeReadAllInp) (err error)
MessageList(ctx context.Context, in adminin.NoticeMessageListInp) (list []*adminin.NoticeMessageListModel, totalCount int, err error)
}
IAdminPost interface { IAdminPost interface {
Delete(ctx context.Context, in adminin.PostDeleteInp) (err error) Delete(ctx context.Context, in adminin.PostDeleteInp) (err error)
Edit(ctx context.Context, in adminin.PostEditInp) (err error) Edit(ctx context.Context, in adminin.PostEditInp) (err error)
@@ -121,61 +138,22 @@ type (
GetMemberByStartName(ctx context.Context, memberId int64) (name string, err error) GetMemberByStartName(ctx context.Context, memberId int64) (name string, err error)
Status(ctx context.Context, in adminin.PostStatusInp) (err error) Status(ctx context.Context, in adminin.PostStatusInp) (err error)
} }
IAdminCash interface {
View(ctx context.Context, in adminin.CashViewInp) (res *adminin.CashViewModel, err error)
List(ctx context.Context, in adminin.CashListInp) (list []*adminin.CashListModel, totalCount int, err error)
Apply(ctx context.Context, in adminin.CashApplyInp) (err error)
Payment(ctx context.Context, in adminin.CashPaymentInp) (err error)
}
IAdminDept interface {
NameUnique(ctx context.Context, in adminin.DeptNameUniqueInp) (res *adminin.DeptNameUniqueModel, err error)
Delete(ctx context.Context, in adminin.DeptDeleteInp) (err error)
Edit(ctx context.Context, in adminin.DeptEditInp) (err error)
Status(ctx context.Context, in adminin.DeptStatusInp) (err error)
MaxSort(ctx context.Context, in adminin.DeptMaxSortInp) (res *adminin.DeptMaxSortModel, err error)
View(ctx context.Context, in adminin.DeptViewInp) (res *adminin.DeptViewModel, err error)
Option(ctx context.Context, in adminin.DeptOptionInp) (res *adminin.DeptOptionModel, totalCount int, err error)
List(ctx context.Context, in adminin.DeptListInp) (res *adminin.DeptListModel, err error)
GetName(ctx context.Context, id int64) (name string, err error)
}
) )
var ( var (
localAdminCash IAdminCash localAdminCash IAdminCash
localAdminCreditsLog IAdminCreditsLog
localAdminDept IAdminDept localAdminDept IAdminDept
localAdminMember IAdminMember localAdminMember IAdminMember
localAdminNotice IAdminNotice
localAdminPost IAdminPost
localAdminRole IAdminRole
localAdminCreditsLog IAdminCreditsLog
localAdminMemberPost IAdminMemberPost localAdminMemberPost IAdminMemberPost
localAdminMenu IAdminMenu localAdminMenu IAdminMenu
localAdminMonitor IAdminMonitor localAdminMonitor IAdminMonitor
localAdminNotice IAdminNotice
localAdminOrder IAdminOrder localAdminOrder IAdminOrder
localAdminPost IAdminPost
localAdminRole IAdminRole
) )
func AdminCreditsLog() IAdminCreditsLog {
if localAdminCreditsLog == nil {
panic("implement not found for interface IAdminCreditsLog, forgot register?")
}
return localAdminCreditsLog
}
func RegisterAdminCreditsLog(i IAdminCreditsLog) {
localAdminCreditsLog = i
}
func AdminMemberPost() IAdminMemberPost {
if localAdminMemberPost == nil {
panic("implement not found for interface IAdminMemberPost, forgot register?")
}
return localAdminMemberPost
}
func RegisterAdminMemberPost(i IAdminMemberPost) {
localAdminMemberPost = i
}
func AdminMenu() IAdminMenu { func AdminMenu() IAdminMenu {
if localAdminMenu == nil { if localAdminMenu == nil {
panic("implement not found for interface IAdminMenu, forgot register?") panic("implement not found for interface IAdminMenu, forgot register?")
@@ -198,26 +176,15 @@ func RegisterAdminMonitor(i IAdminMonitor) {
localAdminMonitor = i localAdminMonitor = i
} }
func AdminOrder() IAdminOrder { func AdminNotice() IAdminNotice {
if localAdminOrder == nil { if localAdminNotice == nil {
panic("implement not found for interface IAdminOrder, forgot register?") panic("implement not found for interface IAdminNotice, forgot register?")
} }
return localAdminOrder return localAdminNotice
} }
func RegisterAdminOrder(i IAdminOrder) { func RegisterAdminNotice(i IAdminNotice) {
localAdminOrder = i localAdminNotice = i
}
func AdminRole() IAdminRole {
if localAdminRole == nil {
panic("implement not found for interface IAdminRole, forgot register?")
}
return localAdminRole
}
func RegisterAdminRole(i IAdminRole) {
localAdminRole = i
} }
func AdminCash() IAdminCash { func AdminCash() IAdminCash {
@@ -231,6 +198,17 @@ func RegisterAdminCash(i IAdminCash) {
localAdminCash = i localAdminCash = i
} }
func AdminCreditsLog() IAdminCreditsLog {
if localAdminCreditsLog == nil {
panic("implement not found for interface IAdminCreditsLog, forgot register?")
}
return localAdminCreditsLog
}
func RegisterAdminCreditsLog(i IAdminCreditsLog) {
localAdminCreditsLog = i
}
func AdminDept() IAdminDept { func AdminDept() IAdminDept {
if localAdminDept == nil { if localAdminDept == nil {
panic("implement not found for interface IAdminDept, forgot register?") panic("implement not found for interface IAdminDept, forgot register?")
@@ -253,15 +231,26 @@ func RegisterAdminMember(i IAdminMember) {
localAdminMember = i localAdminMember = i
} }
func AdminNotice() IAdminNotice { func AdminMemberPost() IAdminMemberPost {
if localAdminNotice == nil { if localAdminMemberPost == nil {
panic("implement not found for interface IAdminNotice, forgot register?") panic("implement not found for interface IAdminMemberPost, forgot register?")
} }
return localAdminNotice return localAdminMemberPost
} }
func RegisterAdminNotice(i IAdminNotice) { func RegisterAdminMemberPost(i IAdminMemberPost) {
localAdminNotice = i localAdminMemberPost = i
}
func AdminOrder() IAdminOrder {
if localAdminOrder == nil {
panic("implement not found for interface IAdminOrder, forgot register?")
}
return localAdminOrder
}
func RegisterAdminOrder(i IAdminOrder) {
localAdminOrder = i
} }
func AdminPost() IAdminPost { func AdminPost() IAdminPost {
@@ -274,3 +263,14 @@ func AdminPost() IAdminPost {
func RegisterAdminPost(i IAdminPost) { func RegisterAdminPost(i IAdminPost) {
localAdminPost = i localAdminPost = i
} }
func AdminRole() IAdminRole {
if localAdminRole == nil {
panic("implement not found for interface IAdminRole, forgot register?")
}
return localAdminRole
}
func RegisterAdminRole(i IAdminRole) {
localAdminRole = i
}

View File

@@ -20,7 +20,7 @@ type (
Blacklist(r *ghttp.Request) Blacklist(r *ghttp.Request)
Develop(r *ghttp.Request) Develop(r *ghttp.Request)
ResponseHandler(r *ghttp.Request) ResponseHandler(r *ghttp.Request)
WebSocketToken(r *ghttp.Request) WebSocketAuth(r *ghttp.Request)
} }
) )

View File

@@ -17,6 +17,11 @@ import (
) )
type ( type (
ISysAddonsConfig interface {
GetConfigByGroup(ctx context.Context, in sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error)
ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error)
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateAddonsConfigInp) (err error)
}
ISysCron interface { ISysCron interface {
StartCron(ctx context.Context) StartCron(ctx context.Context)
Delete(ctx context.Context, in sysin.CronDeleteInp) (err error) Delete(ctx context.Context, in sysin.CronDeleteInp) (err error)
@@ -27,123 +32,6 @@ type (
List(ctx context.Context, in sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error) List(ctx context.Context, in sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error)
OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err error) OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err error)
} }
ISysBlacklist interface {
Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error)
Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error)
Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.BlacklistMaxSortInp) (res *sysin.BlacklistMaxSortModel, err error)
View(ctx context.Context, in sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error)
List(ctx context.Context, in sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error)
VariableLoad(ctx context.Context, err error)
Load(ctx context.Context)
}
ISysDictData interface {
Delete(ctx context.Context, in sysin.DictDataDeleteInp) error
Edit(ctx context.Context, in sysin.DictDataEditInp) (err error)
List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
}
ISysLog interface {
Export(ctx context.Context, in sysin.LogListInp) (err error)
RealWrite(ctx context.Context, log entity.SysLog) (err error)
AutoLog(ctx context.Context) error
AnalysisLog(ctx context.Context) entity.SysLog
View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error)
Delete(ctx context.Context, in sysin.LogDeleteInp) (err error)
List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
}
ISysLoginLog interface {
Model(ctx context.Context) *gdb.Model
List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
Export(ctx context.Context, in sysin.LoginLogListInp) (err error)
Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error)
View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
Push(ctx context.Context, in sysin.LoginLogPushInp)
RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
}
ISysAddons interface {
List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
Build(ctx context.Context, in sysin.AddonsBuildInp) (err error)
Install(ctx context.Context, in sysin.AddonsInstallInp) (err error)
Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error)
UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error)
}
ISysConfig interface {
InitConfig(ctx context.Context)
GetLoadTCP(ctx context.Context) (conf *model.TCPConfig, err error)
GetLoadCache(ctx context.Context) (conf *model.CacheConfig, err error)
GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
GetWechat(ctx context.Context) (conf *model.WechatConfig, err error)
GetPay(ctx context.Context) (conf *model.PayConfig, err error)
GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error)
GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (res *sysin.GetConfigModel, err error)
ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) (err error)
}
ISysEmsLog interface {
Delete(ctx context.Context, in sysin.EmsLogDeleteInp) (err error)
Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error)
Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error)
View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
Send(ctx context.Context, in sysin.SendEmsInp) (err error)
GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error)
}
ISysGenCodes interface {
Delete(ctx context.Context, in sysin.GenCodesDeleteInp) (err error)
Edit(ctx context.Context, in sysin.GenCodesEditInp) (res *sysin.GenCodesEditModel, err error)
Status(ctx context.Context, in sysin.GenCodesStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.GenCodesMaxSortInp) (res *sysin.GenCodesMaxSortModel, err error)
View(ctx context.Context, in sysin.GenCodesViewInp) (res *sysin.GenCodesViewModel, err error)
List(ctx context.Context, in sysin.GenCodesListInp) (list []*sysin.GenCodesListModel, totalCount int, err error)
Selects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error)
TableSelect(ctx context.Context, in sysin.GenCodesTableSelectInp) (res []*sysin.GenCodesTableSelectModel, err error)
ColumnSelect(ctx context.Context, in sysin.GenCodesColumnSelectInp) (res []*sysin.GenCodesColumnSelectModel, err error)
ColumnList(ctx context.Context, in sysin.GenCodesColumnListInp) (res []*sysin.GenCodesColumnListModel, err error)
Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error)
Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error)
}
ISysProvinces interface {
Tree(ctx context.Context) (list []g.Map, err error)
Delete(ctx context.Context, in sysin.ProvincesDeleteInp) (err error)
Edit(ctx context.Context, in sysin.ProvincesEditInp) (err error)
Status(ctx context.Context, in sysin.ProvincesStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error)
View(ctx context.Context, in sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error)
List(ctx context.Context, in sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error)
ChildrenList(ctx context.Context, in sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error)
UniqueId(ctx context.Context, in sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error)
Select(ctx context.Context, in sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error)
}
ISysAttachment interface {
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
Delete(ctx context.Context, in sysin.AttachmentDeleteInp) (err error)
Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error)
Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (res *sysin.AttachmentMaxSortModel, err error)
View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (models *entity.SysAttachment, err error)
}
ISysCronGroup interface {
Delete(ctx context.Context, in sysin.CronGroupDeleteInp) (err error)
Edit(ctx context.Context, in sysin.CronGroupEditInp) (err error)
Status(ctx context.Context, in sysin.CronGroupStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.CronGroupMaxSortInp) (res *sysin.CronGroupMaxSortModel, err error)
View(ctx context.Context, in sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error)
List(ctx context.Context, in sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error)
Select(ctx context.Context, in sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error)
}
ISysCurdDemo interface { ISysCurdDemo interface {
Model(ctx context.Context, option ...*handler.Option) *gdb.Model Model(ctx context.Context, option ...*handler.Option) *gdb.Model
List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error) List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error)
@@ -161,13 +49,40 @@ type (
Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error) Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error)
TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error) TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error)
} }
ISysServeLog interface { ISysCronGroup interface {
Model(ctx context.Context) *gdb.Model Delete(ctx context.Context, in sysin.CronGroupDeleteInp) (err error)
List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error) Edit(ctx context.Context, in sysin.CronGroupEditInp) (err error)
Export(ctx context.Context, in sysin.ServeLogListInp) (err error) Status(ctx context.Context, in sysin.CronGroupStatusInp) (err error)
Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error) MaxSort(ctx context.Context, in sysin.CronGroupMaxSortInp) (res *sysin.CronGroupMaxSortModel, err error)
View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error) View(ctx context.Context, in sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error)
RealWrite(ctx context.Context, models entity.SysServeLog) (err error) List(ctx context.Context, in sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error)
Select(ctx context.Context, in sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error)
}
ISysDictData interface {
Delete(ctx context.Context, in sysin.DictDataDeleteInp) error
Edit(ctx context.Context, in sysin.DictDataEditInp) (err error)
List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
}
ISysEmsLog interface {
Delete(ctx context.Context, in sysin.EmsLogDeleteInp) (err error)
Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error)
Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error)
View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
Send(ctx context.Context, in sysin.SendEmsInp) (err error)
GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error)
}
ISysLog interface {
Export(ctx context.Context, in sysin.LogListInp) (err error)
RealWrite(ctx context.Context, log entity.SysLog) (err error)
AutoLog(ctx context.Context) error
AnalysisLog(ctx context.Context) entity.SysLog
View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error)
Delete(ctx context.Context, in sysin.LogDeleteInp) (err error)
List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
} }
ISysSmsLog interface { ISysSmsLog interface {
Delete(ctx context.Context, in sysin.SmsLogDeleteInp) (err error) Delete(ctx context.Context, in sysin.SmsLogDeleteInp) (err error)
@@ -181,88 +96,119 @@ type (
AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error) AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error) VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error)
} }
ISysAddonsConfig interface { ISysAddons interface {
GetConfigByGroup(ctx context.Context, in sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error) List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error) Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateAddonsConfigInp) (err error) Build(ctx context.Context, in sysin.AddonsBuildInp) (err error)
Install(ctx context.Context, in sysin.AddonsInstallInp) (err error)
Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error)
UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error)
}
ISysConfig interface {
InitConfig(ctx context.Context)
GetLoadTCP(ctx context.Context) (conf *model.TCPConfig, err error)
GetLoadCache(ctx context.Context) (conf *model.CacheConfig, err error)
GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
GetLoadToken(ctx context.Context) (conf *model.TokenConfig, err error)
GetWechat(ctx context.Context) (conf *model.WechatConfig, err error)
GetPay(ctx context.Context) (conf *model.PayConfig, err error)
GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error)
GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (res *sysin.GetConfigModel, err error)
ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) (err error)
}
ISysLoginLog interface {
Model(ctx context.Context) *gdb.Model
List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
Export(ctx context.Context, in sysin.LoginLogListInp) (err error)
Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error)
View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
Push(ctx context.Context, in sysin.LoginLogPushInp)
RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
}
ISysProvinces interface {
Tree(ctx context.Context) (list []g.Map, err error)
Delete(ctx context.Context, in sysin.ProvincesDeleteInp) (err error)
Edit(ctx context.Context, in sysin.ProvincesEditInp) (err error)
Status(ctx context.Context, in sysin.ProvincesStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error)
View(ctx context.Context, in sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error)
List(ctx context.Context, in sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error)
ChildrenList(ctx context.Context, in sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error)
UniqueId(ctx context.Context, in sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error)
Select(ctx context.Context, in sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error)
}
ISysServeLog interface {
Model(ctx context.Context) *gdb.Model
List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error)
Export(ctx context.Context, in sysin.ServeLogListInp) (err error)
Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error)
View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error)
RealWrite(ctx context.Context, models entity.SysServeLog) (err error)
}
ISysAttachment interface {
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
Delete(ctx context.Context, in sysin.AttachmentDeleteInp) (err error)
Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error)
Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (res *sysin.AttachmentMaxSortModel, err error)
View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (models *entity.SysAttachment, err error)
}
ISysBlacklist interface {
Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error)
Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error)
Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.BlacklistMaxSortInp) (res *sysin.BlacklistMaxSortModel, err error)
View(ctx context.Context, in sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error)
List(ctx context.Context, in sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error)
VariableLoad(ctx context.Context, err error)
Load(ctx context.Context)
}
ISysGenCodes interface {
Delete(ctx context.Context, in sysin.GenCodesDeleteInp) (err error)
Edit(ctx context.Context, in sysin.GenCodesEditInp) (res *sysin.GenCodesEditModel, err error)
Status(ctx context.Context, in sysin.GenCodesStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.GenCodesMaxSortInp) (res *sysin.GenCodesMaxSortModel, err error)
View(ctx context.Context, in sysin.GenCodesViewInp) (res *sysin.GenCodesViewModel, err error)
List(ctx context.Context, in sysin.GenCodesListInp) (list []*sysin.GenCodesListModel, totalCount int, err error)
Selects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error)
TableSelect(ctx context.Context, in sysin.GenCodesTableSelectInp) (res []*sysin.GenCodesTableSelectModel, err error)
ColumnSelect(ctx context.Context, in sysin.GenCodesColumnSelectInp) (res []*sysin.GenCodesColumnSelectModel, err error)
ColumnList(ctx context.Context, in sysin.GenCodesColumnListInp) (res []*sysin.GenCodesColumnListModel, err error)
Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error)
Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error)
} }
) )
var ( var (
localSysProvinces ISysProvinces
localSysAttachment ISysAttachment
localSysConfig ISysConfig
localSysEmsLog ISysEmsLog localSysEmsLog ISysEmsLog
localSysGenCodes ISysGenCodes localSysLog ISysLog
localSysServeLog ISysServeLog
localSysSmsLog ISysSmsLog localSysSmsLog ISysSmsLog
localSysAddonsConfig ISysAddonsConfig
localSysCronGroup ISysCronGroup localSysCronGroup ISysCronGroup
localSysDictData ISysDictData
localSysLoginLog ISysLoginLog
localSysProvinces ISysProvinces
localSysServeLog ISysServeLog
localSysAddons ISysAddons
localSysConfig ISysConfig
localSysGenCodes ISysGenCodes
localSysAttachment ISysAttachment
localSysBlacklist ISysBlacklist
localSysCurdDemo ISysCurdDemo localSysCurdDemo ISysCurdDemo
localSysDictType ISysDictType localSysDictType ISysDictType
localSysAddonsConfig ISysAddonsConfig
localSysCron ISysCron localSysCron ISysCron
localSysLoginLog ISysLoginLog
localSysAddons ISysAddons
localSysBlacklist ISysBlacklist
localSysDictData ISysDictData
localSysLog ISysLog
) )
func SysAttachment() ISysAttachment {
if localSysAttachment == nil {
panic("implement not found for interface ISysAttachment, forgot register?")
}
return localSysAttachment
}
func RegisterSysAttachment(i ISysAttachment) {
localSysAttachment = i
}
func SysConfig() ISysConfig {
if localSysConfig == nil {
panic("implement not found for interface ISysConfig, forgot register?")
}
return localSysConfig
}
func RegisterSysConfig(i ISysConfig) {
localSysConfig = i
}
func SysEmsLog() ISysEmsLog {
if localSysEmsLog == nil {
panic("implement not found for interface ISysEmsLog, forgot register?")
}
return localSysEmsLog
}
func RegisterSysEmsLog(i ISysEmsLog) {
localSysEmsLog = i
}
func SysGenCodes() ISysGenCodes {
if localSysGenCodes == nil {
panic("implement not found for interface ISysGenCodes, forgot register?")
}
return localSysGenCodes
}
func RegisterSysGenCodes(i ISysGenCodes) {
localSysGenCodes = i
}
func SysProvinces() ISysProvinces {
if localSysProvinces == nil {
panic("implement not found for interface ISysProvinces, forgot register?")
}
return localSysProvinces
}
func RegisterSysProvinces(i ISysProvinces) {
localSysProvinces = i
}
func SysAddonsConfig() ISysAddonsConfig { func SysAddonsConfig() ISysAddonsConfig {
if localSysAddonsConfig == nil { if localSysAddonsConfig == nil {
panic("implement not found for interface ISysAddonsConfig, forgot register?") panic("implement not found for interface ISysAddonsConfig, forgot register?")
@@ -274,15 +220,15 @@ func RegisterSysAddonsConfig(i ISysAddonsConfig) {
localSysAddonsConfig = i localSysAddonsConfig = i
} }
func SysCronGroup() ISysCronGroup { func SysCron() ISysCron {
if localSysCronGroup == nil { if localSysCron == nil {
panic("implement not found for interface ISysCronGroup, forgot register?") panic("implement not found for interface ISysCron, forgot register?")
} }
return localSysCronGroup return localSysCron
} }
func RegisterSysCronGroup(i ISysCronGroup) { func RegisterSysCron(i ISysCron) {
localSysCronGroup = i localSysCron = i
} }
func SysCurdDemo() ISysCurdDemo { func SysCurdDemo() ISysCurdDemo {
@@ -307,59 +253,15 @@ func RegisterSysDictType(i ISysDictType) {
localSysDictType = i localSysDictType = i
} }
func SysServeLog() ISysServeLog { func SysCronGroup() ISysCronGroup {
if localSysServeLog == nil { if localSysCronGroup == nil {
panic("implement not found for interface ISysServeLog, forgot register?") panic("implement not found for interface ISysCronGroup, forgot register?")
} }
return localSysServeLog return localSysCronGroup
} }
func RegisterSysServeLog(i ISysServeLog) { func RegisterSysCronGroup(i ISysCronGroup) {
localSysServeLog = i localSysCronGroup = i
}
func SysSmsLog() ISysSmsLog {
if localSysSmsLog == nil {
panic("implement not found for interface ISysSmsLog, forgot register?")
}
return localSysSmsLog
}
func RegisterSysSmsLog(i ISysSmsLog) {
localSysSmsLog = i
}
func SysCron() ISysCron {
if localSysCron == nil {
panic("implement not found for interface ISysCron, forgot register?")
}
return localSysCron
}
func RegisterSysCron(i ISysCron) {
localSysCron = i
}
func SysAddons() ISysAddons {
if localSysAddons == nil {
panic("implement not found for interface ISysAddons, forgot register?")
}
return localSysAddons
}
func RegisterSysAddons(i ISysAddons) {
localSysAddons = i
}
func SysBlacklist() ISysBlacklist {
if localSysBlacklist == nil {
panic("implement not found for interface ISysBlacklist, forgot register?")
}
return localSysBlacklist
}
func RegisterSysBlacklist(i ISysBlacklist) {
localSysBlacklist = i
} }
func SysDictData() ISysDictData { func SysDictData() ISysDictData {
@@ -373,6 +275,17 @@ func RegisterSysDictData(i ISysDictData) {
localSysDictData = i localSysDictData = i
} }
func SysEmsLog() ISysEmsLog {
if localSysEmsLog == nil {
panic("implement not found for interface ISysEmsLog, forgot register?")
}
return localSysEmsLog
}
func RegisterSysEmsLog(i ISysEmsLog) {
localSysEmsLog = i
}
func SysLog() ISysLog { func SysLog() ISysLog {
if localSysLog == nil { if localSysLog == nil {
panic("implement not found for interface ISysLog, forgot register?") panic("implement not found for interface ISysLog, forgot register?")
@@ -384,6 +297,39 @@ func RegisterSysLog(i ISysLog) {
localSysLog = i localSysLog = i
} }
func SysSmsLog() ISysSmsLog {
if localSysSmsLog == nil {
panic("implement not found for interface ISysSmsLog, forgot register?")
}
return localSysSmsLog
}
func RegisterSysSmsLog(i ISysSmsLog) {
localSysSmsLog = i
}
func SysAddons() ISysAddons {
if localSysAddons == nil {
panic("implement not found for interface ISysAddons, forgot register?")
}
return localSysAddons
}
func RegisterSysAddons(i ISysAddons) {
localSysAddons = i
}
func SysConfig() ISysConfig {
if localSysConfig == nil {
panic("implement not found for interface ISysConfig, forgot register?")
}
return localSysConfig
}
func RegisterSysConfig(i ISysConfig) {
localSysConfig = i
}
func SysLoginLog() ISysLoginLog { func SysLoginLog() ISysLoginLog {
if localSysLoginLog == nil { if localSysLoginLog == nil {
panic("implement not found for interface ISysLoginLog, forgot register?") panic("implement not found for interface ISysLoginLog, forgot register?")
@@ -394,3 +340,58 @@ func SysLoginLog() ISysLoginLog {
func RegisterSysLoginLog(i ISysLoginLog) { func RegisterSysLoginLog(i ISysLoginLog) {
localSysLoginLog = i localSysLoginLog = i
} }
func SysProvinces() ISysProvinces {
if localSysProvinces == nil {
panic("implement not found for interface ISysProvinces, forgot register?")
}
return localSysProvinces
}
func RegisterSysProvinces(i ISysProvinces) {
localSysProvinces = i
}
func SysServeLog() ISysServeLog {
if localSysServeLog == nil {
panic("implement not found for interface ISysServeLog, forgot register?")
}
return localSysServeLog
}
func RegisterSysServeLog(i ISysServeLog) {
localSysServeLog = i
}
func SysAttachment() ISysAttachment {
if localSysAttachment == nil {
panic("implement not found for interface ISysAttachment, forgot register?")
}
return localSysAttachment
}
func RegisterSysAttachment(i ISysAttachment) {
localSysAttachment = i
}
func SysBlacklist() ISysBlacklist {
if localSysBlacklist == nil {
panic("implement not found for interface ISysBlacklist, forgot register?")
}
return localSysBlacklist
}
func RegisterSysBlacklist(i ISysBlacklist) {
localSysBlacklist = i
}
func SysGenCodes() ISysGenCodes {
if localSysGenCodes == nil {
panic("implement not found for interface ISysGenCodes, forgot register?")
}
return localSysGenCodes
}
func RegisterSysGenCodes(i ISysGenCodes) {
localSysGenCodes = i
}

View File

@@ -153,12 +153,14 @@ cache:
fileDir: "./storage/cache" # 文件缓存路径adapter=file时必填 fileDir: "./storage/cache" # 文件缓存路径adapter=file时必填
#JWT # 登录令牌
jwt: token:
version: "1.0" # 版本号 secretKey: "hotgo123" # 令牌加密秘钥考虑安全问题生产环境中请修改默认值
expires: "864000" # 有效期单位 expires: 604800 # 令牌有效期单位默认7天
sign: "hotgo" # 秘钥考虑安全问题请修改默认值 autoRefresh: true # 是否开启自动刷新过期时间 false|true 默认为true
multiPort: true # 是否允许多端登录默认为true refreshInterval: 86400 # 刷新间隔单位必须小于expires否则无法触发默认1天内只允许刷新一次
maxRefreshTimes: 30 # 最大允许刷新次数-1不限制默认30次
multiLogin: true # 是否允许多端登录 false|true 默认为true
#消息队列 #消息队列

View File

@@ -25,7 +25,7 @@ func WebSocket(ctx context.Context, group *ghttp.RouterGroup) {
websocket.Index, websocket.Index,
) )
// ws连接中间件 // ws连接中间件
group.Middleware(service.Middleware().WebSocketToken) group.Middleware(service.Middleware().WebSocketAuth)
group.Bind( group.Bind(
// 需要验证的路由 // 需要验证的路由
// .. // ..

View File

@@ -3,7 +3,7 @@
-- https://www.phpmyadmin.net/ -- https://www.phpmyadmin.net/
-- --
-- 主机 localhost:3306 -- 主机 localhost:3306
-- 生成日期 2023-05-11 15:56:13 -- 生成日期 2023-05-12 15:45:52
-- 服务器版本 5.7.38-log -- 服务器版本 5.7.38-log
-- PHP 版本 5.6.40 -- PHP 版本 5.6.40
@@ -171,7 +171,6 @@ CREATE TABLE `hg_admin_member` (
`username` varchar(20) NOT NULL DEFAULT '' COMMENT '帐号', `username` varchar(20) NOT NULL DEFAULT '' COMMENT '帐号',
`password_hash` char(32) NOT NULL DEFAULT '' COMMENT '密码', `password_hash` char(32) NOT NULL DEFAULT '' COMMENT '密码',
`salt` char(16) NOT NULL COMMENT '密码盐', `salt` char(16) NOT NULL COMMENT '密码盐',
`auth_key` char(32) NOT NULL DEFAULT '' COMMENT '授权令牌',
`password_reset_token` varchar(150) DEFAULT '' COMMENT '密码重置令牌', `password_reset_token` varchar(150) DEFAULT '' COMMENT '密码重置令牌',
`integral` decimal(10,2) UNSIGNED DEFAULT '0.00' COMMENT '积分', `integral` decimal(10,2) UNSIGNED DEFAULT '0.00' COMMENT '积分',
`balance` decimal(10,2) UNSIGNED DEFAULT '0.00' COMMENT '余额', `balance` decimal(10,2) UNSIGNED DEFAULT '0.00' COMMENT '余额',
@@ -198,10 +197,10 @@ CREATE TABLE `hg_admin_member` (
-- 转存表中的数据 `hg_admin_member` -- 转存表中的数据 `hg_admin_member`
-- --
INSERT INTO `hg_admin_member` (`id`, `dept_id`, `role_id`, `real_name`, `username`, `password_hash`, `salt`, `auth_key`, `password_reset_token`, `integral`, `balance`, `avatar`, `sex`, `qq`, `email`, `mobile`, `birthday`, `city_id`, `address`, `pid`, `level`, `tree`, `cash`, `last_active_at`, `remark`, `status`, `created_at`, `updated_at`) VALUES INSERT INTO `hg_admin_member` (`id`, `dept_id`, `role_id`, `real_name`, `username`, `password_hash`, `salt`, `password_reset_token`, `integral`, `balance`, `avatar`, `sex`, `qq`, `email`, `mobile`, `birthday`, `city_id`, `address`, `pid`, `level`, `tree`, `cash`, `last_active_at`, `remark`, `status`, `created_at`, `updated_at`) VALUES
(1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '72c79855b0e94d4503e80a9fe064c645', '', '89.00', '99391.78', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号', 0, 1, '', '{\"name\": \"孟帅\", \"account\": \"15303830571\", \"payeeCode\": \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg\"}', '2023-05-11 15:52:51', NULL, 1, '2021-02-12 17:59:45', '2023-05-11 15:52:51'), (1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '89.00', '99391.78', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号', 0, 1, '', '{\"name\": \"孟帅\", \"account\": \"15303830571\", \"payeeCode\": \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg\"}', '2023-05-12 15:44:12', NULL, 1, '2021-02-12 17:59:45', '2023-05-12 15:44:12'),
(3, 100, 2, '测试账号', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '33db4202dd10e2c670bfdfb16cd2ecd5', '', '0.00', '4.00', 'http://alioss.qvnidaye.com//images/2021/03/12/image_1615529198_vMK4kwq2.jpg', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', NULL, '2023-04-29 10:20:16', '', 1, '2022-02-11 17:59:45', '2023-04-29 10:20:16'), (3, 100, 2, '测试账号', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '0.00', '4.00', 'http://alioss.qvnidaye.com//images/2021/03/12/image_1615529198_vMK4kwq2.jpg', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', NULL, '2023-04-29 10:20:16', '', 1, '2022-02-11 17:59:45', '2023-04-29 10:20:16'),
(8, 101, 200, 'ameng', 'ameng', '382df3b083a27886edb94e669a857c33', 'hfuUEb', 'a3197f39fae36471b2be8f2e86d8a91e', '', '11.00', '3.22', '', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', NULL, '2023-04-30 20:04:06', '', 1, '2023-02-03 17:34:31', '2023-04-30 20:04:06'); (8, 101, 200, 'ameng', 'ameng', '382df3b083a27886edb94e669a857c33', 'hfuUEb', '', '11.00', '3.22', '', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', NULL, '2023-04-30 20:04:06', '', 1, '2023-02-03 17:34:31', '2023-04-30 20:04:06');
-- -------------------------------------------------------- -- --------------------------------------------------------

View File

@@ -1,45 +0,0 @@
// Package auth
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package auth
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"hotgo/utility/validate"
)
// IsExceptAuth 是否是不需要验证权限的路由地址
func IsExceptAuth(ctx context.Context, path string) bool {
var pathList []string
except := g.Cfg().MustGet(ctx, "router.admin.exceptAuth")
pathList = except.Strings()
for i := 0; i < len(pathList); i++ {
if validate.InSliceExistStr(pathList[i], path) {
return true
}
}
return false
}
// IsExceptLogin 是否是不需要登录的路由地址
func IsExceptLogin(ctx context.Context, path string) bool {
var pathList []string
except := g.Cfg().MustGet(ctx, "router.admin.exceptLogin")
pathList = except.Strings()
for i := 0; i < len(pathList); i++ {
if validate.InSliceExistStr(pathList[i], path) {
return true
}
}
return false
}

View File

@@ -3,13 +3,13 @@
// @Copyright Copyright (c) 2023 HotGo CLI // @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com> // @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package format package format
import ( import (
"fmt" "fmt"
"github.com/shopspring/decimal" "github.com/gogf/gf/v2/util/gconv"
"math" "math"
"strconv"
) )
// RoundInt64 四舍五入 // RoundInt64 四舍五入
@@ -19,22 +19,19 @@ func RoundInt64(x float64) int64 {
// Round2String 四舍五入保留小数默认2位 // Round2String 四舍五入保留小数默认2位
func Round2String(value float64, args ...interface{}) (v string) { func Round2String(value float64, args ...interface{}) (v string) {
var places int32 = 2 var places = 2
if len(args) > 0 { if len(args) > 0 {
places = args[0].(int32) places = gconv.Int(args[0])
} }
return decimal.NewFromFloat(value).Round(places).String() cDig := strconv.Itoa(places)
val := fmt.Sprintf("%0."+cDig+"f", value)
return val
} }
// Round2Float64 四舍五入保留小数默认2位 // Round2Float64 四舍五入保留小数默认2位
func Round2Float64(value float64, args ...interface{}) (v float64) { func Round2Float64(value float64, args ...interface{}) (v float64) {
var places int32 = 2 return gconv.Float64(Round2String(value, args...))
if len(args) > 0 {
places = args[0].(int32)
}
return decimal.NewFromFloat(value).Round(places).InexactFloat64()
} }
// FileSize 字节的单位转换 保留两位小数 // FileSize 字节的单位转换 保留两位小数

View File

@@ -1,6 +1,6 @@
{ {
"name": "hotgo", "name": "hotgo",
"version": "2.6.7", "version": "2.6.10",
"author": { "author": {
"name": "MengShuai", "name": "MengShuai",
"email": "133814250@qq.com", "email": "133814250@qq.com",

View File

@@ -24,7 +24,7 @@
import { useLockscreenStore } from '@/store/modules/lockscreen'; import { useLockscreenStore } from '@/store/modules/lockscreen';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useDesignSettingStore } from '@/store/modules/designSetting'; import { useDesignSettingStore } from '@/store/modules/designSetting';
import { lighten } from '@/utils/index'; import { lighten } from '@/utils';
const route = useRoute(); const route = useRoute();
const useLockscreen = useLockscreenStore(); const useLockscreen = useLockscreenStore();

View File

@@ -101,6 +101,21 @@ export function login(params) {
); );
} }
/**
* @description: 用户注销
*/
export function logout() {
return http.request<BasicResponseModel>(
{
url: ApiEnum.SiteLogout,
method: 'POST',
},
{
isTransformResponse: false,
}
);
}
/** /**
* @description: 用户修改密码 * @description: 用户修改密码
*/ */
@@ -116,14 +131,3 @@ export function changePassword(params, uid) {
} }
); );
} }
/**
* @description: 用户登出
*/
export function logout(params) {
return http.request({
url: '/login/logout',
method: 'POST',
params,
});
}

View File

@@ -4,6 +4,7 @@ export enum ApiEnum {
// 基础 // 基础
SiteLogin = '/site/login', // 登录 SiteLogin = '/site/login', // 登录
SiteLogout = '/site/logout', // 注销
SiteConfig = '/site/config', // 配置信息 SiteConfig = '/site/config', // 配置信息
// 用户 // 用户

View File

@@ -301,16 +301,16 @@
}); });
}; };
// 退出登录 // 注销登录
const doLogout = () => { const doLogout = () => {
dialog.info({ dialog.info({
title: '提示', title: '提示',
content: '您确定要退出登录吗', content: '您确定要注销登录吗',
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
userStore.logout().then(() => { userStore.logout().then(() => {
message.success('成功退出登录'); message.success('成功注销登录');
// 移除标签页 // 移除标签页
localStorage.removeItem(TABS_ROUTES); localStorage.removeItem(TABS_ROUTES);
router router
@@ -377,7 +377,7 @@
key: 1, key: 1,
}, },
{ {
label: '退出登录', label: '注销登录',
key: 2, key: 2,
}, },
]; ];

View File

@@ -3,7 +3,7 @@ import { createStorage, storage } from '@/utils/Storage';
import { store } from '@/store'; import { store } from '@/store';
import { ACCESS_TOKEN, CURRENT_CONFIG, CURRENT_USER, IS_LOCKSCREEN } from '@/store/mutation-types'; import { ACCESS_TOKEN, CURRENT_CONFIG, CURRENT_USER, IS_LOCKSCREEN } from '@/store/mutation-types';
import { ResultEnum } from '@/enums/httpEnum'; import { ResultEnum } from '@/enums/httpEnum';
import { getConfig, getUserInfo, login } from '@/api/system/user'; import { getConfig, getUserInfo, login, logout } from '@/api/system/user';
const Storage = createStorage({ storage: localStorage }); const Storage = createStorage({ storage: localStorage });
export interface UserInfoState { export interface UserInfoState {
@@ -114,7 +114,7 @@ export const useUserStore = defineStore({
const response = await login(userInfo); const response = await login(userInfo);
const { data, code } = response; const { data, code } = response;
if (code === ResultEnum.SUCCESS) { if (code === ResultEnum.SUCCESS) {
const ex = 7 * 24 * 60 * 60 * 1000; const ex = 30 * 24 * 60 * 60 * 1000;
storage.set(ACCESS_TOKEN, data.token, ex); storage.set(ACCESS_TOKEN, data.token, ex);
storage.set(CURRENT_USER, data, ex); storage.set(CURRENT_USER, data, ex);
storage.set(IS_LOCKSCREEN, false); storage.set(IS_LOCKSCREEN, false);
@@ -168,11 +168,19 @@ export const useUserStore = defineStore({
}, },
// 登出 // 登出
async logout() { async logout() {
this.setPermissions([]); try {
this.setUserInfo(null); const response = await logout();
storage.remove(ACCESS_TOKEN); const { code } = response;
storage.remove(CURRENT_USER); if (code === ResultEnum.SUCCESS) {
return Promise.resolve(''); this.setPermissions([]);
this.setUserInfo(null);
storage.remove(ACCESS_TOKEN);
storage.remove(CURRENT_USER);
}
return Promise.resolve(response);
} catch (e) {
return Promise.reject(e);
}
}, },
}, },
}); });

View File

@@ -105,10 +105,10 @@ const transform: AxiosTransform = {
const LoginPath = PageEnum.BASE_LOGIN; const LoginPath = PageEnum.BASE_LOGIN;
if (router.currentRoute.value?.name === LoginName) return; if (router.currentRoute.value?.name === LoginName) return;
// 到登录页 // 到登录页
errorMsg = '登录超时,请重新登录!'; errorMsg = message ?? '登录超时,请重新登录!';
$dialog.warning({ $dialog.warning({
title: '提示', title: '提示',
content: '登录身份已失效,请重新登录!', content: errorMsg, // '登录身份已失效,请重新登录!',
positiveText: '确定', positiveText: '确定',
//negativeText: '取消', //negativeText: '取消',
closable: false, closable: false,

View File

@@ -203,7 +203,7 @@
message.success('更新成功'); message.success('更新成功');
userStore.logout().then(() => { userStore.logout().then(() => {
message.success('成功退出登录'); message.success('成功注销登录');
// 移除标签页 // 移除标签页
localStorage.removeItem(TABS_ROUTES); localStorage.removeItem(TABS_ROUTES);
router router

View File

@@ -193,7 +193,7 @@
message.success('更新成功'); message.success('更新成功');
userStore.logout().then(() => { userStore.logout().then(() => {
message.success('成功退出登录'); message.success('成功注销登录');
// 移除标签页 // 移除标签页
localStorage.removeItem(TABS_ROUTES); localStorage.removeItem(TABS_ROUTES);
router router

View File

@@ -1,6 +1,6 @@
import { h } from 'vue'; import { h } from 'vue';
import { NAvatar, NTag } from 'naive-ui'; import { NAvatar, NTag } from 'naive-ui';
import { timestampToTime, formatBefore, formatAfter } from '@/utils/dateUtil'; import { timestampToTime, formatBefore } from '@/utils/dateUtil';
export const columns = [ export const columns = [
{ {
@@ -31,11 +31,11 @@ export const columns = [
return row.app; return row.app;
}, },
}, },
// { {
// title: '用户ID', title: '用户ID',
// key: 'userId', key: 'userId',
// width: 100, width: 100,
// }, },
{ {
title: '用户名', title: '用户名',
key: 'username', key: 'username',
@@ -90,14 +90,6 @@ export const columns = [
return row.os; return row.os;
}, },
}, },
{
title: '授权过期',
key: 'expTime',
width: 80,
render: (rows, _) => {
return formatAfter(new Date(rows.expTime * 1000));
},
},
{ {
title: '最后活跃', title: '最后活跃',
key: 'heartbeatTime', key: 'heartbeatTime',