diff --git a/web/auth/account.go b/web/auth/account.go index 72bfa85..9b193df 100644 --- a/web/auth/account.go +++ b/web/auth/account.go @@ -82,7 +82,7 @@ func authUserBySms(tx *q.Query, username, code string) (*m.User, error) { // 验证验证码 err := s.Verifier.VerifySms(context.Background(), username, code) if err != nil { - return nil, core.NewBizErr("短信认证失败:%w", err) + return nil, core.NewBizErr("短信认证失败", err) } // 查找用户 diff --git a/web/handlers/batch.go b/web/handlers/batch.go index 49ec324..3133a4e 100644 --- a/web/handlers/batch.go +++ b/web/handlers/batch.go @@ -55,3 +55,25 @@ type PageResourceBatchReq struct { TimeStart *time.Time `json:"time_start"` TimeEnd *time.Time `json:"time_end"` } + +// PageBatchByAdmin 分页查询所有提取记录 +func PageBatchByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin() + if err != nil { + return err + } + + req := new(struct{ core.PageReq }) + if err = g.Validator.ParseBody(c, req); err != nil { + return err + } + + list, total, err := q.LogsUserUsage.FindByPage(req.GetOffset(), req.GetLimit()) + + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) +} diff --git a/web/handlers/bill.go b/web/handlers/bill.go index 50d75fb..dc9e6c9 100644 --- a/web/handlers/bill.go +++ b/web/handlers/bill.go @@ -3,20 +3,40 @@ package handlers import ( "platform/web/auth" "platform/web/core" + g "platform/web/globals" q "platform/web/queries" "time" "github.com/gofiber/fiber/v2" ) -// region ListBill +// PageBillByAdmin 分页查询全部账单 +func PageBillByAdmin(c *fiber.Ctx) error { + // 检查权限 + _, err := auth.GetAuthCtx(c).PermitAdmin() + if err != nil { + return err + } -type ListBillReq struct { - core.PageReq - BillNo *string `json:"bill_no"` - Type *int `json:"type"` - CreateAfter *time.Time `json:"create_after"` - CreateBefore *time.Time `json:"create_before"` + // 解析请求参数 + req := new(core.PageReq) + if err := g.Validator.ParseBody(c, req); err != nil { + return err + } + + // 查询用户列表 + list, total, err := q.Bill.FindByPage(req.GetOffset(), req.GetLimit()) + if err != nil { + return err + } + + // 返回结果 + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) } // ListBill 获取账单列表 @@ -79,4 +99,10 @@ func ListBill(c *fiber.Ctx) error { }) } -// endregion +type ListBillReq struct { + core.PageReq + BillNo *string `json:"bill_no"` + Type *int `json:"type"` + CreateAfter *time.Time `json:"create_after"` + CreateBefore *time.Time `json:"create_before"` +} diff --git a/web/handlers/channel.go b/web/handlers/channel.go index 0e3881c..64a5547 100644 --- a/web/handlers/channel.go +++ b/web/handlers/channel.go @@ -14,15 +14,36 @@ import ( "github.com/gofiber/fiber/v2" ) -// region ListChannels +// PageChannelsByAdmin 分页查询所有通道 +func PageChannelsByAdmin(c *fiber.Ctx) error { + // 检查权限 + _, err := auth.GetAuthCtx(c).PermitAdmin() + if err != nil { + return err + } -type ListChannelsReq struct { - core.PageReq - AuthType s.ChannelAuthType `json:"auth_type"` - ExpireAfter *time.Time `json:"expire_after"` - ExpireBefore *time.Time `json:"expire_before"` + // 解析请求参数 + req := new(core.PageReq) + if err := g.Validator.ParseBody(c, req); err != nil { + return err + } + + // 查询通道列表 + list, total, err := q.Channel.FindByPage(req.GetOffset(), req.GetLimit()) + if err != nil { + return err + } + + // 返回结果 + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) } +// 分页查询当前用户通道 func ListChannels(c *fiber.Ctx) error { // 检查权限 authContext, err := auth.GetAuthCtx(c).PermitUser() @@ -86,28 +107,14 @@ func ListChannels(c *fiber.Ctx) error { }) } -// endregion - -// region CreateChannel - -type CreateChannelReq struct { - ResourceId int32 `json:"resource_id" validate:"required"` - AuthType s.ChannelAuthType `json:"auth_type" validate:"required"` - Protocol int `json:"protocol" validate:"required"` - Count int `json:"count" validate:"required"` - Prov *string `json:"prov"` - City *string `json:"city"` - Isp *int `json:"isp"` -} - -type CreateChannelRespItem struct { - Proto int `json:"-"` - Host string `json:"host"` - Port uint16 `json:"port"` - Username *string `json:"username,omitempty"` - Password *string `json:"password,omitempty"` +type ListChannelsReq struct { + core.PageReq + AuthType s.ChannelAuthType `json:"auth_type"` + ExpireAfter *time.Time `json:"expire_after"` + ExpireBefore *time.Time `json:"expire_before"` } +// 创建新通道 func CreateChannel(c *fiber.Ctx) error { // 解析参数 @@ -154,16 +161,25 @@ func CreateChannel(c *fiber.Ctx) error { return c.JSON(resp) } -type CreateChannelResultType string - -// endregion - -// region RemoveChannels - -type RemoveChannelsReq struct { - Batch string `json:"batch" validate:"required"` +type CreateChannelReq struct { + ResourceId int32 `json:"resource_id" validate:"required"` + AuthType s.ChannelAuthType `json:"auth_type" validate:"required"` + Protocol int `json:"protocol" validate:"required"` + Count int `json:"count" validate:"required"` + Prov *string `json:"prov"` + City *string `json:"city"` + Isp *int `json:"isp"` } +type CreateChannelRespItem struct { + Proto int `json:"-"` + Host string `json:"host"` + Port uint16 `json:"port"` + Username *string `json:"username,omitempty"` + Password *string `json:"password,omitempty"` +} + +// RemoveChannels 删除通道 func RemoveChannels(c *fiber.Ctx) error { // 检查权限 _, err := auth.GetAuthCtx(c).PermitOfficialClient() @@ -186,4 +202,6 @@ func RemoveChannels(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) } -// endregion +type RemoveChannelsReq struct { + Batch string `json:"batch" validate:"required"` +} diff --git a/web/handlers/resource.go b/web/handlers/resource.go index f41c49d..17247c3 100644 --- a/web/handlers/resource.go +++ b/web/handlers/resource.go @@ -15,8 +15,8 @@ import ( "github.com/gofiber/fiber/v2" ) -// ListResourceShort 分页短效套餐 -func ListResourceShort(c *fiber.Ctx) error { +// PageResourceShort 分页查询当前用户短效套餐 +func PageResourceShort(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() if err != nil { @@ -24,7 +24,7 @@ func ListResourceShort(c *fiber.Ctx) error { } // 解析请求参数 - req := new(ListResourceShortReq) + req := new(PageResourceShortReq) if err := c.BodyParser(req); err != nil { return err } @@ -86,7 +86,7 @@ func ListResourceShort(c *fiber.Ctx) error { }) } -type ListResourceShortReq struct { +type PageResourceShortReq struct { core.PageReq ResourceNo *string `json:"resource_no"` Active *bool `json:"active"` @@ -97,8 +97,8 @@ type ListResourceShortReq struct { ExpireBefore *time.Time `json:"expire_before"` } -// ListResourceLong 分页长效套餐 -func ListResourceLong(c *fiber.Ctx) error { +// PageResourceLong 分页查询当前用户长效套餐 +func PageResourceLong(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() if err != nil { @@ -106,7 +106,7 @@ func ListResourceLong(c *fiber.Ctx) error { } // 解析请求参数 - req := new(ListResourceLongReq) + req := new(PageResourceLongReq) if err := c.BodyParser(req); err != nil { return err } @@ -168,7 +168,7 @@ func ListResourceLong(c *fiber.Ctx) error { }) } -type ListResourceLongReq struct { +type PageResourceLongReq struct { core.PageReq ResourceNo *string `json:"resource_no"` Active *bool `json:"active"` @@ -179,6 +179,56 @@ type ListResourceLongReq struct { ExpireBefore *time.Time `json:"expire_before"` } +// PageResourceShortByAdmin 分页查询全部短效套餐 +func PageResourceShortByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin() + if err != nil { + return err + } + + req := new(struct{ core.PageReq }) + if err = g.Validator.ParseBody(c, req); err != nil { + return err + } + + list, total, err := q.Resource.Debug(). + LeftJoin(q.ResourceShort, q.ResourceShort.ResourceID.EqCol(q.Resource.ID)). + Where(q.Resource.Type.Eq(int(m.ResourceTypeShort))). + FindByPage(req.GetOffset(), req.GetLimit()) + + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) +} + +// PageResourceLongByAdmin 分页查询全部短效套餐 +func PageResourceLongByAdmin(c *fiber.Ctx) error { + _, err := auth.GetAuthCtx(c).PermitAdmin() + if err != nil { + return err + } + + req := new(struct{ core.PageReq }) + if err = g.Validator.ParseBody(c, req); err != nil { + return err + } + + list, total, err := q.Resource. + LeftJoin(q.ResourceLong, q.ResourceLong.ResourceID.EqCol(q.Resource.ID)). + Where(q.Resource.Type.Eq(int(m.ResourceTypeLong))). + FindByPage(req.GetOffset(), req.GetLimit()) + + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) +} + // AllActiveResource 所有可用套餐 func AllActiveResource(c *fiber.Ctx) error { // 检查权限 diff --git a/web/handlers/trade.go b/web/handlers/trade.go index 1d3b0d7..c8121aa 100644 --- a/web/handlers/trade.go +++ b/web/handlers/trade.go @@ -9,6 +9,7 @@ import ( "platform/web/core" g "platform/web/globals" m "platform/web/models" + q "platform/web/queries" s "platform/web/services" "time" @@ -16,18 +17,36 @@ import ( "github.com/valyala/fasthttp" ) -type TradeCreateReq struct { - s.CreateTradeData - Type m.TradeType `json:"type" validate:"required"` - Resource *s.CreateResourceData `json:"resource,omitempty"` - Recharge *s.RechargeProductInfo `json:"recharge,omitempty"` -} - -type TradeCreateResp struct { - PayUrl string `json:"pay_url"` - TradeNo string `json:"trade_no"` +// PageTradeByAdmin 分页查询所有订单 +func PageTradeByAdmin(c *fiber.Ctx) error { + // 检查权限 + _, err := auth.GetAuthCtx(c).PermitAdmin() + if err != nil { + return err + } + + // 解析请求参数 + req := new(core.PageReq) + if err := g.Validator.ParseBody(c, req); err != nil { + return err + } + + // 查询用户列表 + list, total, err := q.Trade.FindByPage(req.GetOffset(), req.GetLimit()) + if err != nil { + return err + } + + // 返回结果 + return c.JSON(core.PageResp{ + List: list, + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + }) } +// 创建订单 func TradeCreate(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -67,10 +86,19 @@ func TradeCreate(c *fiber.Ctx) error { }) } -type TradeCompleteReq struct { - s.ModifyTradeData +type TradeCreateReq struct { + s.CreateTradeData + Type m.TradeType `json:"type" validate:"required"` + Resource *s.CreateResourceData `json:"resource,omitempty"` + Recharge *s.RechargeProductInfo `json:"recharge,omitempty"` } +type TradeCreateResp struct { + PayUrl string `json:"pay_url"` + TradeNo string `json:"trade_no"` +} + +// 完成订单 func TradeComplete(c *fiber.Ctx) error { // 检查权限 _, err := auth.GetAuthCtx(c).PermitUser() @@ -93,10 +121,11 @@ func TradeComplete(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } -type TradeCancelReq struct { +type TradeCompleteReq struct { s.ModifyTradeData } +// 取消订单 func TradeCancel(c *fiber.Ctx) error { // 检查权限 _, err := auth.GetAuthCtx(c).PermitUser() @@ -120,10 +149,11 @@ func TradeCancel(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } -type TradeCheckReq struct { +type TradeCancelReq struct { s.ModifyTradeData } +// 检查订单 func TradeCheck(c *fiber.Ctx) error { // 解析请求参数 req := new(TradeCheckReq) @@ -170,3 +200,7 @@ func TradeCheck(c *fiber.Ctx) error { return nil } + +type TradeCheckReq struct { + s.ModifyTradeData +} diff --git a/web/handlers/user.go b/web/handlers/user.go index 2577f47..7e7c98f 100644 --- a/web/handlers/user.go +++ b/web/handlers/user.go @@ -2,6 +2,8 @@ package handlers import ( "platform/web/auth" + "platform/web/core" + g "platform/web/globals" m "platform/web/models" q "platform/web/queries" s "platform/web/services" @@ -10,15 +12,38 @@ import ( "golang.org/x/crypto/bcrypt" ) -// region /update +// 分页获取用户 +func PageUserByAdmin(c *fiber.Ctx) error { + // 检查权限 + _, err := auth.GetAuthCtx(c).PermitAdmin() + if err != nil { + return err + } -type UpdateUserReq struct { - Username string `json:"username" validate:"omitempty,min=3,max=20"` - Email string `json:"email" validate:"omitempty,email"` - ContactQQ string `json:"contact_qq" validate:"omitempty,qq"` - ContactWechat string `json:"contact_wechat" validate:"omitempty,wechat"` + // 解析请求参数 + req := new(core.PageReq) + if err := g.Validator.ParseBody(c, req); err != nil { + return err + } + + // 查询用户列表 + users, total, err := q.User. + Omit(q.User.Password). + FindByPage(req.GetOffset(), req.GetLimit()) + if err != nil { + return err + } + + // 返回结果 + return c.JSON(core.PageResp{ + Total: int(total), + Page: req.GetPage(), + Size: req.GetSize(), + List: users, + }) } +// 更新用户 func UpdateUser(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -49,15 +74,14 @@ func UpdateUser(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } -// endregion - -// region /update/account - -type UpdateAccountReq struct { - Username string `json:"username" validate:"omitempty,min=3,max=20"` - Password string `json:"password" validate:"omitempty,min=6,max=20"` +type UpdateUserReq struct { + Username string `json:"username" validate:"omitempty,min=3,max=20"` + Email string `json:"email" validate:"omitempty,email"` + ContactQQ string `json:"contact_qq" validate:"omitempty,qq"` + ContactWechat string `json:"contact_wechat" validate:"omitempty,wechat"` } +// 更新账号信息 func UpdateAccount(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -86,16 +110,12 @@ func UpdateAccount(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } -// endregion - -// region /update/password - -type UpdatePasswordReq struct { - Phone string `json:"phone"` - Code string `json:"code"` - Password string `json:"password"` +type UpdateAccountReq struct { + Username string `json:"username" validate:"omitempty,min=3,max=20"` + Password string `json:"password" validate:"omitempty,min=6,max=20"` } +// 更新账号密码 func UpdatePassword(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -135,4 +155,8 @@ func UpdatePassword(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } -// endregion +type UpdatePasswordReq struct { + Phone string `json:"phone"` + Code string `json:"code"` + Password string `json:"password"` +} diff --git a/web/routes.go b/web/routes.go index cc99ee6..4e4f387 100644 --- a/web/routes.go +++ b/web/routes.go @@ -10,7 +10,23 @@ import ( func ApplyRouters(app *fiber.App) { api := app.Group("/api") + userRouter(api) + adminRouter(api) + // 回调 + callbacks := app.Group("/callback") + callbacks.Get("/identify", handlers.IdentifyCallbackNew) + + // 临时 + if env.RunMode == env.RunModeDev { + debug := app.Group("/debug") + debug.Get("/sms/:phone", handlers.DebugGetSmsCode) + debug.Get("/proxy/register", handlers.DebugRegisterProxyBaiYin) + } +} + +// 用户接口路由 +func userRouter(api fiber.Router) { // 认证 auth := api.Group("/auth") auth.Get("/authorize", auth2.AuthorizeGet) @@ -37,8 +53,8 @@ func ApplyRouters(app *fiber.App) { // 套餐 resource := api.Group("/resource") resource.Post("/all", handlers.AllActiveResource) - resource.Post("/list/short", handlers.ListResourceShort) - resource.Post("/list/long", handlers.ListResourceLong) + resource.Post("/list/short", handlers.PageResourceShort) + resource.Post("/list/long", handlers.PageResourceLong) resource.Post("/create", handlers.CreateResource) resource.Post("/price", handlers.ResourcePrice) resource.Post("/statistics/free", handlers.StatisticResourceFree) @@ -74,7 +90,7 @@ func ApplyRouters(app *fiber.App) { proxy.Post("/online", handlers.ProxyReportOnline) proxy.Post("/offline", handlers.ProxyReportOffline) proxy.Post("/update", handlers.ProxyReportUpdate) - proxy.Post("/register", handlers.ProxyRegisterBaiYin) + proxy.Post("/register/baidyin", handlers.ProxyRegisterBaiYin) // 节点 edge := api.Group("/edge") @@ -84,15 +100,34 @@ func ApplyRouters(app *fiber.App) { // 前台 inquiry := api.Group("/inquiry") inquiry.Post("/create", handlers.CreateInquiry) - - // 回调 - callbacks := app.Group("/callback") - callbacks.Get("/identify", handlers.IdentifyCallbackNew) - - // 临时 - if env.RunMode == env.RunModeDev { - debug := app.Group("/debug") - debug.Get("/sms/:phone", handlers.DebugGetSmsCode) - debug.Get("/proxy/register", handlers.DebugRegisterProxyBaiYin) - } +} + +// 管理员接口路由 +func adminRouter(api fiber.Router) { + api = api.Group("/admin") + + // user 用户 + var user = api.Group("/user") + user.Post("/page", handlers.PageUserByAdmin) + + // resource 套餐 + var resource = api.Group("/resource") + resource.Post("/short/page", handlers.PageResourceShortByAdmin) + resource.Post("/long/page", handlers.PageResourceLongByAdmin) + + // batch 批次 + var usage = api.Group("batch") + usage.Post("/page", handlers.PageBatchByAdmin) + + // channel 通道 + var channel = api.Group("/channel") + channel.Post("/page", handlers.PageChannelsByAdmin) + + // trade 交易 + var trade = api.Group("trade") + trade.Post("/page", handlers.PageTradeByAdmin) + + // bill 账单 + var bill = api.Group("/bill") + bill.Post("/page", handlers.PageBillByAdmin) }