补全权限数据 & 优化 router 代码结构

This commit is contained in:
2026-06-01 16:08:58 +08:00
parent 0dfbbe5939
commit 7f30b6be4e
4 changed files with 72 additions and 204 deletions

View File

@@ -7,6 +7,7 @@
交易信息持久化
订单关闭问题,在前端关闭窗口后直接调用了全部订单接口,应改成先确认再关闭
- 取消订单接口改成只允许管理员调用
- 新增关闭订单接口,关闭订单的逻辑是先尝试完成,如果订单未支付则取消订单
@@ -18,27 +19,33 @@
冷数据迁移方案
## 开发环境
## 开发流程
### 更新表结构的流程
### 新建数据表流程
1. 编辑 `scripts/sql/init.sql` 文件,参照原有格式,需要注意:
1. 创建 model 文件
2. 将 model 按照格式添加声明到 `cmd/gen/main.go`
3. 编辑 `scripts/sql/init.sql` 文件,参照原有格式,需要注意:
- 先写 drop table if exists 语句,确保脚本可以幂等执行
- 编写 create table 语句,按需添加审计字段和软删除字段 (created_at, updated_at, deleted_at)
- 为有必要的字段添加索引
- 为数据表及其字段添加注释
- 在文件末尾创建数据表流程全部结束后,为字段添加外键
2. 建议用数据库工具检查差异并增量更新,或者手动增量更新
3. 创建 model 文件,并将其添加到 gen 代码中
4. 生成查询文件
4. 调用 `go run ./cmd/gen/main.go` 生成查询文件
### 权限管理
### 更新数据表流程
`web/core/scopes.go` 下定义了系统所有静态权限
1. 更新 model 文件
2. 编辑 `scripts/sql/init.sql` 文件,参照原有格式,需要注意:
- 先写 drop table if exists 语句,确保脚本可以幂等执行
- 为有必要的字段添加索引
- 为数据表及其字段添加注释
- 在文件末尾创建数据表流程全部结束后,为字段添加外键
3. 调用 `go run ./cmd/gen/main.go` 更新查询文件
新增系统权限需要在数据库中配套添加权限
### 新增接口或修改接口权限
前端也需要新增配套权限定义
1.`web/core/scopes.go` 下声明权限常量。通常格式为 `Model:Action:SubAction`,例如 `User:Create``User:Delete``User:Update:Password`
2.`scripts/sql/fill.sql` 文件的权限区域添加或修改权限条目
## 业务逻辑

View File

@@ -239,6 +239,10 @@ insert into permission (parent_id, name, description, sort) values
insert into permission (parent_id, name, description, sort) values
((select id from permission where name = 'proxy:write' and deleted_at is null), 'proxy:write:status', '更改代理状态', 1);
-- channel:write 子权限
insert into permission (parent_id, name, description, sort) values
((select id from permission where name = 'channel:write' and deleted_at is null), 'channel:write:clear_expired', '清理过期 IP', 1);
-- resource:short 子权限
insert into permission (parent_id, name, description, sort) values
((select id from permission where name = 'resource:short' and deleted_at is null), 'resource:short:read', '读取用户短效动态套餐列表', 1);
@@ -285,6 +289,10 @@ insert into permission (parent_id, name, description, sort) values
insert into permission (parent_id, name, description, sort) values
((select id from permission where name = 'coupon_user:read' and deleted_at is null), 'coupon_user:read:of_user', '读取指定用户的已发放优惠券列表', 1);
-- trade:write 子权限
insert into permission (parent_id, name, description, sort) values
((select id from permission where name = 'trade:write' and deleted_at is null), 'trade:write:complete', '完成交易', 1);
-- --------------------------
-- level 4
-- --------------------------

View File

@@ -1,149 +0,0 @@
package handlers
import (
s "platform/web/services"
"github.com/gofiber/fiber/v2"
)
type RegisterEdgeReq struct {
Name string `json:"name" validate:"required"`
Version int `json:"version" validate:"required"`
}
type RegisterEdgeResp struct {
Id int32 `json:"id"`
Host string `json:"host"`
}
func AssignEdge(c *fiber.Ctx) (err error) {
return c.JSON(map[string]any{
"error": "接口暂不可用",
})
// // 验证请求参数
// var req = new(RegisterEdgeReq)
// err = g.Validator.Validate(c, req)
// if err != nil {
// return err
// }
// // 全局锁,防止并发注册
// var mutex = g.Redsync.NewMutex("edge:discovery")
// if err := mutex.Lock(); err != nil {
// return errors.New("服务繁忙,请稍后重试")
// }
// defer func() {
// if ok, err := mutex.Unlock(); err != nil {
// slog.Error("解锁失败", slog.Bool("ok", ok), slog.Any("err", err))
// }
// }()
// // 检查节点
// var fwd *m.Proxy
// var edge *m.Edge
// edge, err = q.Edge.
// Where(q.Edge.Mac.Eq(req.Name)).
// Take()
// if errors.Is(err, gorm.ErrRecordNotFound) {
// // 挑选合适的转发服务
// fwd, err = q.Proxy.
// LeftJoin(q.Edge, q.Edge.ProxyID.EqCol(q.Proxy.ID), q.Edge.Status.Eq(1)).
// Select(q.Proxy.ALL, q.Edge.ALL.Count().As("count")).
// Where(q.Proxy.Type.Eq(int32(proxy2.TypeSelfHosted))).
// Group(q.Proxy.ID).
// Order(field.NewField("", "count").Desc()).
// First()
// if err != nil {
// return err
// }
// // 保存节点信息
// edge = &m.Edge{
// Name: req.Name,
// Version: int32(req.Version),
// Type: int32(edge2.TypeSelfHosted),
// ProxyID: &fwd.ID,
// }
// err = q.Edge.Create(edge)
// if err != nil {
// return err
// }
// } else if err == nil {
// // 获取已配置的转发服务
// fwd, err = q.Proxy.
// Where(q.Proxy.ID.Eq(*edge.ProxyID)).
// Take()
// if err != nil {
// return err
// }
// // 节点已存在,更新版本号
// if edge.Version < int32(req.Version) {
// _, err = q.Edge.
// Where(q.Edge.ID.Eq(edge.ID)).
// UpdateSimple(q.Edge.Version.Value(int32(req.Version)))
// if err != nil {
// return err
// }
// }
// } else {
// return err
// }
// // 返回服务地址
// return c.JSON(RegisterEdgeResp{
// Id: edge.ID,
// Host: fwd.Host,
// })
}
type AllEdgesAvailableReq struct {
s.EdgeFilter
Count int `json:"count"`
}
type AllEdgesAvailableRespItem struct {
Ip string `json:"ip"` // 节点地址
Port int32 `json:"port"` // 代理服务端口
Isp string `json:"isp"` // 运营商
Prov string `json:"prov"` // 省份
City string `json:"city"` // 城市
Status int32 `json:"status"` // 节点状态0-离线1-正常
}
func AllEdgesAvailable(c *fiber.Ctx) (err error) {
return c.JSON(map[string]any{
"error": "接口暂不可用",
})
// // 检查权限
// _, err = auth.GetAuthCtx(c).PermitSecretClient()
// if err != nil {
// return err
// }
// // 验证请求参数
// var req = new(AllEdgesAvailableReq)
// err = g.Validator.Validate(c, req)
// if err != nil {
// return err
// }
// // 获取可用的转发服务
// infos, err := s.Edge.AllEdges(req.Count, req.EdgeFilter)
// if err != nil {
// return err
// }
// // 返回结果
// var edges = make([]AllEdgesAvailableRespItem, len(infos))
// for i, info := range infos {
// edges[i] = AllEdgesAvailableRespItem{
// Ip: info.Host,
// Port: u.Z(info.ProxyPort),
// Isp: edge2.ISP(info.Isp).String(),
// Prov: info.Prov,
// City: info.City,
// Status: info.Status,
// }
// }
// return c.JSON(edges)
}

View File

@@ -15,9 +15,10 @@ import (
func ApplyRouters(app *fiber.App) {
api := app.Group("/api")
publicRouter(api)
clientRouter(api)
userRouter(api)
adminRouter(api)
clientRouter(api)
// 回调
callbacks := app.Group("/callback")
@@ -52,8 +53,8 @@ func ApplyRouters(app *fiber.App) {
}
}
// 用户接口路由
func userRouter(api fiber.Router) {
// 公开接口路由
func publicRouter(api fiber.Router) {
// 认证
auth := api.Group("/auth")
auth.Get("/authorize", auth2.AuthorizeGet)
@@ -62,6 +63,48 @@ func userRouter(api fiber.Router) {
auth.Post("/revoke", auth2.Revoke)
auth.Post("/introspect", auth2.Introspect)
// 套餐
resource := api.Group("/resource")
resource.Post("/price", handlers.ResourcePrice)
// 交易
trade := api.Group("/trade")
trade.Get("/check", handlers.TradeCheck)
// 前台
inquiry := api.Group("/inquiry")
inquiry.Post("/create", handlers.CreateInquiry)
// 产品
product := api.Group("/product")
product.Post("/list", handlers.AllProduct)
}
// 客户端接口路由
func clientRouter(api fiber.Router) {
client := api
// 验证短信令牌
client.Post("/verify/sms", handlers.SendSmsCode)
// 网关
proxy := client.Group("/proxy")
proxy.Post("/online", handlers.ProxyReportOnline)
proxy.Post("/offline", handlers.ProxyReportOffline)
proxy.Post("/update", handlers.ProxyReportUpdate)
// 通道管理
channel := client.Group("/channel")
channel.Post("/remove", handlers.RemoveChannels)
// 文章查看
article := api.Group("/article")
article.Post("/nav", handlers.NavArticle)
article.Post("/get", handlers.GetArticle)
}
// 用户接口路由
func userRouter(api fiber.Router) {
// 用户
user := api.Group("/user")
user.Post("/update", handlers.UpdateUser)
@@ -102,7 +145,6 @@ func userRouter(api fiber.Router) {
trade.Post("/create", handlers.TradeCreate)
trade.Post("/complete", handlers.TradeComplete)
trade.Post("/cancel", handlers.TradeCancel)
trade.Get("/check", handlers.TradeCheck)
// 账单
bill := api.Group("/bill")
@@ -121,51 +163,11 @@ func userRouter(api fiber.Router) {
announcement := api.Group("/announcement")
announcement.Post("/list", handlers.ListAnnouncements)
// 网关
proxy := api.Group("/proxy")
proxy.Post("/online", handlers.ProxyReportOnline)
proxy.Post("/offline", handlers.ProxyReportOffline)
proxy.Post("/update", handlers.ProxyReportUpdate)
// 节点
edge := api.Group("/edge")
edge.Post("/assign", handlers.AssignEdge)
edge.Post("/all", handlers.AllEdgesAvailable)
// 前台
inquiry := api.Group("/inquiry")
inquiry.Post("/create", handlers.CreateInquiry)
// 产品
product := api.Group("/product")
product.Post("/list", handlers.AllProduct)
// 认证
verify := api.Group("/verify")
verify.Post("/sms/password", handlers.SendSmsCodeForPassword)
}
// 客户端接口路由
func clientRouter(api fiber.Router) {
client := api
// 验证短信令牌
client.Post("/verify/sms", handlers.SendSmsCode)
// 套餐定价查询
resource := client.Group("/resource")
resource.Post("/price", handlers.ResourcePrice)
// 通道管理
channel := client.Group("/channel")
channel.Post("/remove", handlers.RemoveChannels)
// 文章查看
article := api.Group("/article")
article.Post("/nav", handlers.NavArticle)
article.Post("/get", handlers.GetArticle)
}
// 管理员接口路由
func adminRouter(api fiber.Router) {
api = api.Group("/admin")