diff --git a/README.md b/README.md index 6d7db7b4e963665e15da122972bb2b2ab1d1638d..ee2a1106381e0fb135216b2e0f70ffdebecaf072 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ - - # ubdframe ## 介绍 @@ -49,7 +47,7 @@ http://localhost:8080/swagger/ ## 主要功能模块 ### AdminApp(管理后台) -- �18n 支持(多语言) +- i18n 支持(多语言) - 权限管理(RBAC) - 日志记录 - 用户管理 @@ -61,10 +59,14 @@ http://localhost:8080/swagger/ - 用户信息管理 - 验证码发送/校验 -### BlockApp(内容块管理) -- 内容块的增删改查 -- 支持文本、图片、代码、链接等类型 -- 缓存机制支持快速访问 +### CmsApp(CMS内容管理) +- 内容块 + - 支持文本、图片、代码、链接等类型 +- 专栏管理 +- 内容模型 + - 产品模型 + - 文章模型 +- 通用渲染内容 ### IotApp(物联网服务) - 支持 MQTT 设备连接 @@ -125,6 +127,7 @@ src/apps/adminapp/docs/adminservice_swagger.json src/apps/adminapp/docs/adminservice_swagger.yaml ``` + ## 开发与测试 - 单元测试位于各模块的 `_test.go` 文件中 - 使用 `go test` 运行测试 diff --git a/cmd/microdocs/README.md b/cmd/microdocs/README.md new file mode 100644 index 0000000000000000000000000000000000000000..569f15b3bd911d008e40f6249b85b28aaf4dcd0c --- /dev/null +++ b/cmd/microdocs/README.md @@ -0,0 +1,20 @@ + +# microdocs (微swagger文档) + +## 1、安装 + +``` +go install gitee.com/captials-team/ubdframe/cmd/microdocs@latest +``` + + +## 2、运行 + +``` +./microdocs + +``` + + + +运行后浏览器访问查看: **http://127.0.0.1:8080/swagger/index.html** diff --git a/cmd/randstr/README.md b/cmd/randstr/README.md new file mode 100644 index 0000000000000000000000000000000000000000..37ab4df9eedab22d8e94c5e88b929f40322ef816 --- /dev/null +++ b/cmd/randstr/README.md @@ -0,0 +1,19 @@ + +# randstr (生成随机字符串) + +## 1、安装 + +``` +go install gitee.com/captials-team/ubdframe/cmd/randstr@latest +``` + + +## 2、运行 + +生成50个长度为10的随机字符串 +``` +randstr -l 10 -n 50 +``` + + + diff --git a/cmd/randstr/main.go b/cmd/randstr/main.go new file mode 100644 index 0000000000000000000000000000000000000000..4e6081b1afbfafd942be81be5224fd2798924e73 --- /dev/null +++ b/cmd/randstr/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "flag" + "fmt" + "gitee.com/captials-team/ubdframe/src/common/utils" +) + +var len = flag.Int("l", 10, "指定随机字符串长度") +var num = flag.Int("n", 1, "指定生成数量") +var prefix = flag.String("p", "", "指定前缀") + +func main() { + flag.Parse() + + for i := 1; i <= (*num); i++ { + fmt.Println(*prefix + utils.RandLetterFigureCode(*len)) + } +} diff --git a/cmd/timeclock/README.md b/cmd/timeclock/README.md new file mode 100644 index 0000000000000000000000000000000000000000..71761c82a6ed6d157965eaab2185ceb827fb4ef0 --- /dev/null +++ b/cmd/timeclock/README.md @@ -0,0 +1,23 @@ +# timeclock (时间时钟) + +## 1、安装 + +``` +go install gitee.com/captials-team/ubdframe/cmd/timeclock@latest +``` + +## 2、运行 + +控制台运行 + +``` +timeclock +``` + +控件UI运行 + +``` +timeclock -ui +``` + + diff --git a/cmd/timeclock/main.go b/cmd/timeclock/main.go new file mode 100644 index 0000000000000000000000000000000000000000..abeef9c133024007013d981714e5ea2828939bbc --- /dev/null +++ b/cmd/timeclock/main.go @@ -0,0 +1,80 @@ +package main + +import ( + "context" + "flag" + "fmt" + "gitee.com/captials-team/ubdframe/src/common" + "github.com/gonutz/wui" + "os" + "strings" + "time" +) + +var ui = flag.Bool("ui", false, "以控件UI展示") + +func main() { + flag.Parse() + + format := "2006-01-02 15:04:05.000" + + ch := make(chan string, 64) + ctx := context.Background() + if *ui { + go runAsWindows(ctx, ch) + } else { + go runAsConsole(ctx, ch) + } + + for { + ch <- time.Now().Format(format) + time.Sleep(time.Millisecond * 20) + } +} + +func runAsConsole(ctx context.Context, ch chan string) { + fmt.Printf("%s\n\n", strings.Repeat("=", 50)) + for s := range ch { + fmt.Printf("\r%s%s", s, strings.Repeat(" ", 20)) + } +} + +func runAsWindows(ctx context.Context, ch chan string) { + w := wui.NewWindow() + w.SetTitle("TimeClock") + w.SetSize(300, 200) + + label := wui.NewLabel() + label.SetWidth(w.Width()) + label.SetHeight(w.Height()) + label.SetCenterAlign() + label.SetVisible(true) + label.SetText("-") + label.SetEnabled(true) + label.SetPos(0, 0) + + f, _ := wui.NewFont(wui.FontDesc{ + Name: "微软雅黑", + Height: 24, + }) + label.SetFont(f) + + w.Add(label) + w.SetOnResize(func() { + label.SetWidth(w.Width()) + label.SetHeight(w.Height()) + }) + + w.SetOnClose(func() { + os.Exit(1) + }) + w.SetOnShow(func() { + go func() { + for s := range ch { + label.SetText(s) + } + }() + }) + common.ErrPanic(w.Show()) + +} diff --git a/go.mod b/go.mod index 045da7eeede358207ddf8e70200e299d940e3ba2..71602ccd732c90007373e9625330f959b484f3af 100644 --- a/go.mod +++ b/go.mod @@ -6,19 +6,23 @@ toolchain go1.22.0 require ( github.com/BurntSushi/toml v1.4.0 + github.com/Jeffail/tunny v0.1.4 github.com/Knetic/govaluate v3.0.0+incompatible github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.0 github.com/alibabacloud-go/tea-utils/v2 v2.0.7 + github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-contrib/cors v1.7.2 github.com/gin-contrib/multitemplate v1.0.1 github.com/gin-contrib/static v1.1.2 github.com/gin-gonic/gin v1.10.0 + github.com/go-openapi/spec v0.20.4 github.com/go-playground/assert/v2 v2.2.0 github.com/go-redis/redis/v7 v7.4.1 github.com/go-redis/redis/v8 v8.11.5 github.com/go-sql-driver/mysql v1.7.0 + github.com/gonutz/wui v1.0.0 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 github.com/jinzhu/copier v0.4.0 @@ -27,7 +31,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 github.com/mojocn/base64Captcha v1.3.6 github.com/natefinch/lumberjack v2.0.0+incompatible - github.com/nicksnyder/go-i18n/v2 v2.4.1 + github.com/nicksnyder/go-i18n/v2 v2.5.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/prometheus/client_golang v1.19.0 github.com/rfyiamcool/backoff v1.1.0 @@ -45,8 +49,8 @@ require ( go.etcd.io/etcd/client/v3 v3.5.17 go.uber.org/dig v1.18.0 go.uber.org/zap v1.24.0 - golang.org/x/net v0.33.0 - golang.org/x/text v0.21.0 + golang.org/x/net v0.35.0 + golang.org/x/text v0.22.0 golang.org/x/time v0.8.0 google.golang.org/grpc v1.68.1 google.golang.org/protobuf v1.34.2 @@ -83,12 +87,12 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/structs v1.1.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.19.6 // indirect - github.com/go-openapi/spec v0.20.4 // indirect github.com/go-openapi/swag v0.19.15 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -97,6 +101,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/gonutz/w32 v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -127,10 +132,10 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/image v0.13.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/image v0.24.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/tools v0.24.1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect diff --git a/go.sum b/go.sum index 9bc2f52efe661f11d4518ec20bc3642f24dcda59..4f431b729c9c157597e4923b4af1f39f756f8ef1 100644 --- a/go.sum +++ b/go.sum @@ -600,6 +600,8 @@ github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Jeffail/tunny v0.1.4 h1:chtpdz+nUtaYQeCKlNBg6GycFF/kGVHOr6A3cmzTJXs= +github.com/Jeffail/tunny v0.1.4/go.mod h1:P8xAx4XQl0xsuhjX1DtfaMDCSuavzdb2rwbd0lk+fvo= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -673,6 +675,8 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef h1:2JGTg6JapxP9/R33ZaagQtAM4EkkSYnIAlOG5EI8gkM= +github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -760,8 +764,9 @@ github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzP github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -864,6 +869,10 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gonutz/w32 v1.0.0 h1:3t1z6ZfkFvirjFYBx9pHeHBuKoN/VBVk9yHb/m2Ll/k= +github.com/gonutz/w32 v1.0.0/go.mod h1:Rc/YP5K9gv0FW4p6X9qL3E7Y56lfMflEol1fLElfMW4= +github.com/gonutz/wui v1.0.0 h1:kXv6iHawOtz8g6qK4K29rs8KClHo1yYrrYddHArxpcY= +github.com/gonutz/wui v1.0.0/go.mod h1:cpEPmIh19mpxkcho2qMHLX16gVteB1aee8g11887kyE= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= @@ -1025,8 +1034,8 @@ github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DG github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= -github.com/nicksnyder/go-i18n/v2 v2.4.1 h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3YPrr0g= -github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk= +github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk= +github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -1210,8 +1219,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1240,8 +1249,9 @@ golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeap golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= +golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= +golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1271,8 +1281,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1343,8 +1353,8 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1390,8 +1400,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1484,8 +1494,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1517,8 +1527,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1593,8 +1603,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.24.1 h1:vxuHLTNS3Np5zrYoPRpcheASHX/7KiGo+8Y4ZM1J2O8= +golang.org/x/tools v0.24.1/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/apps/README.md b/src/apps/README.md deleted file mode 100644 index e7e4dfa73224d2a77fbe483e14e75af1dd37bb76..0000000000000000000000000000000000000000 --- a/src/apps/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# App说明 - -app是用于快速构建整体应用而分割的各类app独立模块 - -可独立使用或可作为插件使用,也可只使用其部分功能或能力 - - - -## UserApp - -提供用户相关的基础功能 - -见 [文档 ](./userapp/README.md) - - - -## AdminApp - -提供后台管理站用户相关的基础功能 - -见 [文档 ](./adminapp/README.md) - - - -## WebApp - -支持web渲染功能,代理转发功能 - -见 [文档 ](./webapp/README.md) - - - -## 通用说明 - - - -### Swagger-API文档生成 - -各应用下相应存在 gen_docs.sh 脚本,用于生成各个app的api文档 - -若无该脚本则说明该app无api应用,如web应用 \ No newline at end of file diff --git a/src/apps/adminapp/README.md b/src/apps/adminapp/README.md deleted file mode 100644 index 209b9e9b64428415ed8ef6c87e4ee00f4c26c96f..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/README.md +++ /dev/null @@ -1,40 +0,0 @@ - - -# AdminApp - -提供后台管理站用户相关的基础功能 - - - -### 支持功能 - -目前支持功能: - -- 授权登录 -- 管理员管理 -- 权限管理(RBAC) - - - -### Swagger-API - -API文档地址: http://127.0.0.1:40103/swagger/adminservice/doc.json - - - -### 使用说明 - - - -#### 用户AuthHandler - -可通过userapp/App下的AuthOption选项获取userApp的C端用户AuthHandler - -``` -xxAdmin.AuthOption.AuthHandler=userApp.ApiServer.AuthOption.OptAuthHandler() - -``` - - - - diff --git a/src/apps/adminapp/api_server.go b/src/apps/adminapp/api_server.go deleted file mode 100644 index e1a2da971d90e15028ea793a592f0b1d5a2672b8..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/api_server.go +++ /dev/null @@ -1,183 +0,0 @@ -package adminapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/adminapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/apps/adminapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - *apps.ApiServer - - di *dig.Scope - conf *configstc.AdminAppConfig - - gin_http.AuthOption //认证相关选项配置 - gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - gin_http.OperateLogOption //操作日志 - gin_http.AuthExtendInfoOption //认证扩展信息选项配置 - gin_http.AccreditOption //授权选项 -} - -func (s *ApiServer) Name() string { - return "admin_api" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - authGroup := g.Group("", s.OptAuthHandler(), s.OptAccreditHandler()) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminAuthController, captcha interfaces.ItfCaptchaController) { - if d, ok := ctr.(*httpController.AuthController); ok { - d.AuthExtendInfoOption = s.AuthExtendInfoOption - } - })) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminAuthController, captcha interfaces.ItfCaptchaController) { - //验证码 - g.POST("/mag/captcha/get", captcha.GetCaptcha) //图片验证码 - - //登陆相关 - g.POST("/mag/auth/login", captcha.VerifyHandler(), ctr.AuthLogin, s.RecordLog("登录")) //不需要授权 - authGroup.POST("/mag/auth/check", ctr.AuthCheck) - authGroup.POST("/mag/auth/info", ctr.AuthInfo) - authGroup.POST("/mag/auth/logout", ctr.AuthLogout, s.RecordLog("登出")) - authGroup.POST("/mag/auth/fresh_token", ctr.AuthFreshToken) - })) - - //个人中心 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminCenterController) { - authGroup.POST("/mag/u_center/info", ctr.UserInfo) //个人信息 - authGroup.POST("/mag/u_center/modify_pwd", ctr.ModifyPassword, s.RecordLog("修改密码")) //修改密码(登录情况下) - authGroup.POST("/mag/u_center/modify_info", ctr.ModifyInfo, s.RecordLog("修改个人信息")) - })) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAccreditController) { - authGroup.POST("/mag/u_center/accredit_info", ctr.AccreditInfo) - })) - - //管理员管理 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminManageController) { - //管理员管理 - authGroup.POST("/mag/admin/search", ctr.SearchAdmin, s.RecordLog("进入管理员管理")) - authGroup.POST("/mag/admin/detail", ctr.QueryAdmin, s.RecordLog("查看管理员")) - authGroup.POST("/mag/admin/save", ctr.SaveAdmin, s.RecordLog("创建/更新管理员")) - authGroup.POST("/mag/admin/disable", ctr.DisableAdmin, s.RecordLog("禁用管理员")) - authGroup.POST("/mag/admin/delete", ctr.DeleteAdmin, s.RecordLog("删除管理员")) - })) - - //管理员日志 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminLogController) { - //管理员管理 - authGroup.POST("/mag/admin_log/search", ctr.SearchAdminLog, s.RecordLog("进入日志管理")) - })) - - //权限管理(RBAC) - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfRbacManageController) { - //rbac-用户角色信息 - authGroup.POST("/mag/rbac/user/role/search", ctr.SearchUserRoles) - authGroup.POST("/mag/rbac/user/role/bind", ctr.BindUserRoles, s.RecordLog("绑定用户角色")) - - //rbac-角色 - authGroup.POST("/mag/rbac/role/search", ctr.SearchRoles, s.RecordLog("进入角色管理")) - authGroup.POST("/mag/rbac/role/simples", ctr.SimpleRoles) //简易返回所有角色 - authGroup.POST("/mag/rbac/role/detail", ctr.QueryRole, s.RecordLog("查看角色详情")) - authGroup.POST("/mag/rbac/role/save", ctr.SaveRole, s.RecordLog("新增/更新角色信息")) - authGroup.POST("/mag/rbac/role/disable", ctr.DisableRole, s.RecordLog("启用/禁用角色")) - authGroup.POST("/mag/rbac/role/delete", ctr.DeleteRole, s.RecordLog("删除角色")) - authGroup.POST("/mag/rbac/role/permissions", ctr.SearchRolePermissions) - authGroup.POST("/mag/rbac/role/permission/save", ctr.SaveRolePermissions, s.RecordLog("更新角色权限")) - - //rbac-权限 - authGroup.POST("/mag/rbac/permission/search", ctr.SearchPermissions, s.RecordLog("进入权限树管理")) - authGroup.POST("/mag/rbac/permission/save", ctr.SavePermission, s.RecordLog("新增/更新权限树节点")) - authGroup.POST("/mag/rbac/permission/delete", ctr.DeletePermission, s.RecordLog("删除权限树节点")) - })) - //组织管理 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfOrganizeManageController) { - authGroup.POST("/mag/organize/search", ctr.SearchOrganize, s.RecordLog("进入组织管理")) - authGroup.POST("/mag/organize/tree", ctr.TreeOrganize) //简易返回组织树 - authGroup.POST("/mag/organize/detail", ctr.QueryOrganize, s.RecordLog("查看组织详情")) - authGroup.POST("/mag/organize/save", ctr.SaveOrganize, s.RecordLog("新增/更新组织信息")) - authGroup.POST("/mag/organize/disable", ctr.DisableOrganize, s.RecordLog("启用/禁用组织")) - authGroup.POST("/mag/organize/delete", ctr.DeleteOrganize, s.RecordLog("删除组织")) - })) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Scope, conf *configstc.AdminAppConfig, logger v1log.ILog) *ApiServer { - - //swagger配置,取值后取指针是为了实现复用(多App) - swaggerDocs := *docs.SwaggerInfoadminservice - swaggerDocs.Host = conf.ApiServer.HostAddr() + utils.KeepHasPrefix(conf.RoutePrefix, "/") - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: swaggerDocs.InstanceName(), - Swagger: &swaggerDocs, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - s.WithName(conf.Name) - s.WithCors() //开启跨域设置 - - s.AuthOption.AuthHandler = gin_http.AuthHandler(jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey)) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAdminLogController) { - s.OperateLogOption.OperateLogHandler = ctr.LogHandler() - })) - - return s -} diff --git a/src/apps/adminapp/app.go b/src/apps/adminapp/app.go deleted file mode 100644 index 2c3e2f1ce2c0a18118de17fa3711b1682a9d20a1..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/app.go +++ /dev/null @@ -1,150 +0,0 @@ -// @title Admin模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey AdminKeyAuth -// @in header -// @name Authorization -// @description 管理站用Admin-Token, Header: Authorization -// @scope.write Grants write access - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package adminapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/adminapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/services" - "gitee.com/captials-team/ubdframe/src/infrastructure/caches" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "go.uber.org/dig" - "time" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Scope - ApiServer *ApiServer -} - -func (app *App) initDao(conf *configstc.AdminAppConfig) { - common.ErrPanic(app.di.Provide(func() (interfaces.ItfAdminDao, interfaces.ItfAdminLog) { - var err error - - admin := mysqlDao.NewAdminDao(conf.DBConfig) - adminLog := mysqlDao.NewAdminLogDao(conf.DBConfig) - - _, err = admin.Migrate() - common.ErrPanic(err) - - _, err = adminLog.Migrate() - common.ErrPanic(err) - - app.l.Info("migrate success") - - return admin, adminLog - })) - - common.ErrPanic(app.di.Provide(func() (interfaces.ItfOrganize, interfaces.ItfOrganizeRelate) { - var err error - - organizeDao := mysqlDao.NewOrganizeDao(conf.DBConfig) - relateDao := mysqlDao.NewOrganizeRelateDao(conf.DBConfig) - - _, err = organizeDao.Migrate() - common.ErrPanic(err) - - _, err = relateDao.Migrate() - common.ErrPanic(err) - - app.l.Info("migrate success") - - return organizeDao, relateDao - })) - - app.l.Info("provide dao success") - -} - -func (app *App) initCaches(conf *configstc.AdminAppConfig) { - common.ErrPanic(app.di.Provide(func() caches.ItfCache { - return caches.NewMemoryStore(time.Minute * 10) - }), uber_help.ErrAlreadyProvided) - - app.l.Info("provide cache success") -} - -func (app *App) initService() { - common.ErrPanic(app.di.Provide(services.NewAdminService, dig.As(new(interfaces.ItfAdminService)))) - common.ErrPanic(app.di.Provide(services.NewOrganizeService, dig.As(new(interfaces.ItfOrganizeService)))) - - app.l.Info("init service success") -} - -func (app *App) initController() { - common.ErrPanic(app.di.Provide(gin_http.NewCaptchaController, dig.As(new(interfaces.ItfCaptchaController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewAuthController, dig.As(new(interfaces.ItfAdminAuthController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewAdminController, dig.As(new(interfaces.ItfAdminManageController)), dig.As(new(interfaces.ItfAdminCenterController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewRbacController, dig.As(new(interfaces.ItfRbacManageController)), dig.As(new(interfaces.ItfAccreditController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewAdminLogController, dig.As(new(interfaces.ItfAdminLogController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewOrganizeManageController, dig.As(new(interfaces.ItfOrganizeManageController))), uber_help.ErrAlreadyProvided) -} - -func NewApp(di *dig.Container, conf *configstc.AdminAppConfig, logger v1log.ILog) *App { - scope := di.Scope("admin") - - common.ErrPanic(scope.Provide(func() *dig.Scope { - return scope - }), uber_help.ErrAlreadyProvided) - common.ErrPanic(scope.Provide(func() *configstc.AdminAppConfig { - return conf - }), uber_help.ErrAlreadyProvided) - - app := &App{ - di: scope, - l: logger, - App: apps.NewApp(di, "admin_app"), - } - - app.WithModule(conf.ModuleMode) - - //db初始化 - common.ErrPanic(scope.Invoke(app.initCaches)) - common.ErrPanic(scope.Invoke(app.initDao)) - common.ErrPanic(scope.Invoke(app.initService)) - common.ErrPanic(scope.Invoke(app.initController)) - - if conf.ApiServer.Enable { - common.ErrPanic(scope.Provide(NewApiServer)) - common.ErrPanic(scope.Invoke(func(api *ApiServer) { - app.WithApiServer(api) - app.ApiServer = api - })) - } - - return app -} diff --git a/src/apps/adminapp/app_test.go b/src/apps/adminapp/app_test.go deleted file mode 100644 index c5bdb4bebc82ff171b174221962c1ae23713637a..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/app_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package adminapp - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/tests" - "go.uber.org/dig" - "testing" - "time" -) - -func TestAppStart(t *testing.T) { - di := testDi(t) - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - return app.Start() - })) - - time.Sleep(time.Hour) -} - -func testDi(t *testing.T) *dig.Container { - di := tests.NewDi(t) - - common.ErrPanic(di.Provide(func() *configstc.AdminAppConfig { - return &configstc.AdminAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_ubd_frame", - TablePrefix: "test_", - }, - DocsEnable: true, - AutoCreateAdmin: true, - } - })) - - return di -} diff --git a/src/apps/adminapp/config.go b/src/apps/adminapp/config.go deleted file mode 100644 index 8d60a5c6cfda22727945ae497d1825bac420847d..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/config.go +++ /dev/null @@ -1,16 +0,0 @@ -package adminapp - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" -) - -// NewConfig godoc -// @Summary CONFIG-配置 -// @Description CONFIG-配置内容 -// @Tags admin -// @Produce json -// @Success 200 {array} configstc.AdminAppConfig -// @Router /-admin-config [post] -func NewConfig() *configstc.AdminAppConfig { - return configstc.LoadConfig(new(configstc.AdminAppConfig)) -} diff --git a/src/apps/adminapp/controllers/http/ctr_admin.go b/src/apps/adminapp/controllers/http/ctr_admin.go deleted file mode 100644 index 03a664a830fa447fbf36b685260f2379c547d885..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_admin.go +++ /dev/null @@ -1,506 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/i18n" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/passwd" - "gitee.com/captials-team/ubdframe/src/resource" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "golang.org/x/text/language" - "net/http" -) - -type AdminController struct { - l v1log.ILog - - adminModel interfaces.ItfAdminDao - adminLogModel interfaces.ItfAdminLog - - conf *configstc.AdminAppConfig - - *gin_http.I18nController - passwd.SaltMd5Password - passwd.StrongPasswordChecker -} - -func NewAdminController(di *dig.Scope, l v1log.ILog, conf *configstc.AdminAppConfig) *AdminController { - ctr := &AdminController{ - l: l, - - conf: conf, - } - - common.ErrPanic(di.Invoke(func(admin interfaces.ItfAdminDao, adminLog interfaces.ItfAdminLog) { - ctr.adminModel = admin - ctr.adminLogModel = adminLog - })) - - //i18n - ctr.initI18n() - - //初始化账户 - ctr.initAccount() - - return ctr -} - -func (ctr *AdminController) initI18n() { - parser := i18n.NewParser() - - //从本地加载指定的i18n文件 - common.ErrPanic(utils.ScanEmbedFsDo(resource.I18nFs, func(file string, path string) error { - content, err := resource.I18nFs.ReadFile(path) - common.ErrPanic(err) - - parser.Bundle().MustParseMessageFileBytes(content, file) - - //file文件名必须对应上 language.English.String() - //ctr.l.Info("File=%s", file) - //ctr.l.Info("English=%s", language.English.String()) - //ctr.l.Info("Chinese=%s", language.Chinese.String()) - - return nil - })) - - //parser.Bundle().MustParseMessageFileBytes([]byte(``), language.Chinese.String()+".toml") - - for name, path := range ctr.conf.I18nFiles { - parser.Load(path, name+".toml") - //ctr.l.Info("load i18n path %s: %s, %s", name, path, parser.Lang(name).ParseMsg("Hello")) - } - parser.SetLanguage(language.Chinese) - parser.CacheLanguages() - ctr.I18nController = &gin_http.I18nController{ - Parser: parser, - } -} - -func (ctr *AdminController) initAccount() { - var err error - //自动创建admin账户 - if ctr.conf.AutoCreateAdmin { - salt := utils.RandLetterFigureCode(16) - _, err = ctr.adminModel.AddCheckAccount(&models.Admin{ - Id: 0, - Account: "admin", - Password: passwd.GenSaltPasswordByMd5("123456", salt), - Salt: salt, - Nickname: "超级管理员", - Avatar: "", - Email: "system@system.com", - IsRoot: consts.StatusTrue, - Status: consts.StatusEnable, - }) - common.ErrPanic(err) - ctr.l.Info("add SuperAdmin success") - } -} - -// SearchAdmin godoc -// @Summary 管理员管理-搜索列表 -// @Description 搜索管理员列表 -// @Tags admin -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.SearchAdminReq true "搜索参数集" -// @success 0 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.Admin}} "获取成功" -// @Router /mag/admin/search [post] -func (ctr *AdminController) SearchAdmin(ctx *gin.Context) { - auth := gin_http.GetAuth(ctx) - - var req reqdata.SearchAdminReq - ctx.ShouldBind(&req) - - params := &dto.SearchAdminParams{ - Keywords: req.Keywords, - Status: req.Status, - } - - if configstc.CommonExtendParams(auth.Extends).ExtendParamByBool("is_root") { - params.IsRoot = -1 - } - - list, pager, err := ctr.adminModel.Search(params, &paginate.Pager{ - Page: req.Page, - Size: req.Size, - }) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: utils.CopyMoreTo(list, []*respdata.AdminListItemResp{}), - Paginate: *pager, - })) -} - -// QueryAdmin godoc -// @Summary 管理员管理-查看详请 -// @Description 获取管理员详细信息 -// @Security AdminKeyAuth -// @Tags admin -// @Accept json -// @Produce json -// @Param param body reqdata.DetailReq true "查询指定id详情" -// @success 0 {object} respdata.ResponseData{data=respdata.AdminDetailResp} "获取成功" -// @failure 2 {object} respdata.ResponseData{} "系统错误" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @failure 8 {object} respdata.ResponseData{} "操作失败" -// @Router /mag/admin/detail [post] -func (ctr *AdminController) QueryAdmin(ctx *gin.Context) { - var req reqdata.DetailReq - - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - data, err := ctr.adminModel.Query(req.Id) - if err != nil { - ctr.Response(ctx, respdata.CSysBusy) - return - } - if data == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(data, new(respdata.AdminDetailResp)))) -} - -// SaveAdmin godoc -// @Summary 管理员管理-新增/更新 -// @Description 新增管理员,编辑提交管理员 -// @Security AdminKeyAuth -// @Tags admin -// @Accept json -// @Produce json -// @Param param body reqdata.AddEditAdminReq true "新增/编辑信息" -// @success 0 {object} respdata.ResponseData{data=models.Admin} "处理成功" -// @failure 2 {object} respdata.ResponseData{} "系统错误" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @failure 8 {object} respdata.ResponseData{} "操作失败" -// @Router /mag/admin/save [post] -func (ctr *AdminController) SaveAdmin(ctx *gin.Context) { - var req reqdata.AddEditAdminReq - - ctx.ShouldBind(&req) - - if req.Nickname == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - if req.Id == 0 && (req.Account == "" || req.Password == "") { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - //新增时进行账户检查 - if req.Id == 0 { - ctr.createAdmin(ctx, req) - } else { - ctr.updateAdmin(ctx, req) - } -} - -func (ctr *AdminController) createAdmin(ctx *gin.Context, req reqdata.AddEditAdminReq) { - if req.Account == "" || req.Password == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - find, err := ctr.adminModel.QueryByAccount(req.Account) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if find != nil { - ctr.Response(ctx, respdata.CError.MMsg("AccountExist")) - return - } - - if ok, s := ctr.CheckPassword(req.Password); !ok { - ctr.Response(ctx, respdata.CError.MMsg(s)) - return - } - - var salt = utils.RandLetterFigureCode(16) - req.Password = ctr.GenPassword(req.Password, salt) - - data := models.Admin{ - Account: req.Account, - Password: req.Password, - Salt: salt, - - Nickname: req.Nickname, - Avatar: req.Avatar, - Email: req.Email, - Phone: req.Phone, - Status: req.Status, - Remark: req.Remark, - ExpiredAt: req.ExpiredAt, - } - - _, err = ctr.adminModel.Add(&data) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CFail) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(&data, new(respdata.AdminDetailResp)))) -} - -func (ctr *AdminController) updateAdmin(ctx *gin.Context, req reqdata.AddEditAdminReq) { - find, err := ctr.adminModel.Query(req.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if find == nil { - ctr.Response(ctx, respdata.CError.MMsg("AccountNotExist")) - return - } - - if req.Password != "" { - if ok, s := ctr.CheckPassword(req.Password); !ok { - ctr.Response(ctx, respdata.CError.MMsg(s)) - return - } - req.Password = passwd.GenSaltPasswordByMd5(req.Password, find.Salt) - } - - data := models.Admin{ - Password: req.Password, - - Nickname: req.Nickname, - Avatar: req.Avatar, - Email: req.Email, - Phone: req.Phone, - Status: req.Status, - Remark: req.Remark, - ExpiredAt: req.ExpiredAt, - } - _, err = ctr.adminModel.Update(req.Id, &data) - - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CFail) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(&data, new(respdata.AdminDetailResp)))) -} - -// DisableAdmin godoc -// @Summary 管理员管理-启用/禁用 -// @Description 操作启用/禁用管理员 -// @Security AdminKeyAuth -// @Tags admin -// @Accept json -// @Produce json -// @Param param body reqdata.SetStatusReq true "状态设置请求" -// @success 200 {object} respdata.ResponseData{} "设置成功" -// @Router /mag/admin/disable [post] -func (ctr *AdminController) DisableAdmin(ctx *gin.Context) { - var req reqdata.SetStatusReq - - ctx.ShouldBind(&req) - - if req.Status != consts.StatusEnable && req.Status != consts.StatusDisable { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - admin, err := ctr.adminModel.Query(req.Id) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if admin == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - if admin.IsRoot > 0 { - ctr.Response(ctx, respdata.CError.MMsg("无法被修改")) - return - } - _, err = ctr.adminModel.ResetStatus(req.Id, req.Status) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) - return -} - -// DeleteAdmin godoc -// @Summary 管理员管理-删除管理员 -// @Description 删除管理员 -// @Security AdminKeyAuth -// @Tags admin -// @Accept json -// @Produce json -// @Param param body reqdata.DetailReq true "指定管理员id" -// @success 200 {object} respdata.ResponseData{} "操作成功" -// @Router /mag/admin/delete [post] -func (ctr *AdminController) DeleteAdmin(ctx *gin.Context) { - var req reqdata.DetailReq - - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - data, err := ctr.adminModel.Query(req.Id) - if err != nil { - ctr.Response(ctx, respdata.CSysBusy) - return - } - if data == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - - if _, err := ctr.adminModel.Delete(data.Id); err != nil { - ctr.l.Error("delete admin fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(data)) -} - -// ModifyInfo godoc -// @Summary 账户中心-修改个人信息 -// @Description 修改个人信息 -// @Tags admin.center -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.ModifyInfoReq false "用户信息" -// @success 0 {object} respdata.ResponseData{} "成功" -// @failure 2 {object} respdata.ResponseData{} "修改失败" -// @Router /mag/u_center/modify_info [post] -func (ctr *AdminController) ModifyInfo(ctx *gin.Context) { - var req reqdata.ModifyInfoReq - ctx.ShouldBind(&req) - - if req.Nickname == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - auth := gin_http.GetAuth(ctx) - if _, err := ctr.adminModel.UpdateProInfo(auth.Id, &models.Admin{ - Avatar: req.Avatar, - Nickname: req.Nickname, - }); err != nil { - ctr.l.Error("modify err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -// ModifyPassword godoc -// @Summary 账户中心-修改密码 -// @Description 修改密码 -// @Tags admin.center -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.ModifyPasswordReq false "提价" -// @success 0 {object} respdata.ResponseData{} "成功" -// @failure 2 {object} respdata.ResponseData{} "修改失败" -// @Router /mag/u_center/modify_pwd [post] -func (ctr *AdminController) ModifyPassword(ctx *gin.Context) { - var req reqdata.ModifyPasswordReq - ctx.ShouldBind(&req) - - if req.OldPassword == "" || req.Password == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - if ok, s := ctr.CheckPassword(req.Password); !ok { - ctr.Response(ctx, respdata.CError.MMsg(s)) - return - } - - auth := gin_http.GetAuth(ctx) - password, salt, err := ctr.adminModel.QueryPassword(auth.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CError) - return - } - - if password != passwd.GenSaltPasswordByMd5(req.OldPassword, salt) { - ctr.Response(ctx, respdata.CError.MMsg("PasswordWrong")) - return - } - - isRoot := configstc.CommonExtendParams(auth.Extends).ExtendParamByBool("is_root") - if _, err := ctr.adminModel.ResetPassword(auth.Id, passwd.GenSaltPasswordByMd5(req.Password, salt), isRoot); err != nil { - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -func (ctr *AdminController) ResetPassword(ctx *gin.Context) { - ctr.Response(ctx, respdata.CNotSupport) -} //重置密码 - -func (ctr *AdminController) BindEmailPhone(ctx *gin.Context) { - ctr.Response(ctx, respdata.CNotSupport) -} //绑定邮箱 - -func (ctr *AdminController) LoginRecord(ctx *gin.Context) { - ctr.Response(ctx, respdata.CNotSupport) -} //登录记录 - -// UserInfo godoc -// @Summary 用户信息 -// @Description 用户信息,比AuthInfo提供信息更详细 -// @Tags admin.center -// @Produce json -// @Security ApiKeyAuth -// @success 0 {object} respdata.ResponseData{data=respdata.AdminDetailResp} "获取成功" -// @success 0 {object} respdata.ResponseData{} "重置成功" -// @fail 1 {object} respdata.ResponseData{} "重置失败" -// @Router /mag/u_center/info [post] -func (ctr *AdminController) UserInfo(ctx *gin.Context) { - auth := gin_http.GetAuth(ctx) - user, err := ctr.adminModel.Query(auth.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("query err")) - return - } - if user == nil { - ctx.JSON(http.StatusOK, respdata.CNotFound) - return - } - - resp := utils.CopyTo(user, new(respdata.AdminDetailResp)) - ctr.Response(ctx, respdata.CSuccess.MData(resp)) -} diff --git a/src/apps/adminapp/controllers/http/ctr_admin_log.go b/src/apps/adminapp/controllers/http/ctr_admin_log.go deleted file mode 100644 index 72a0a90bd94849bfd418ffa519397581e2e8f53d..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_admin_log.go +++ /dev/null @@ -1,146 +0,0 @@ -package http - -import ( - "fmt" - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - gocache "github.com/patrickmn/go-cache" - "go.uber.org/dig" - "time" -) - -type AdminLogController struct { - l v1log.ILog - - adminModel interfaces.ItfAdminDao - adminLogModel interfaces.ItfAdminLog - - conf *configstc.AdminAppConfig - - gin_http.ResponseController - cache *gocache.Cache -} - -func NewAdminLogController(di *dig.Scope, l v1log.ILog, conf *configstc.AdminAppConfig) *AdminLogController { - ctr := &AdminLogController{ - l: l, - adminModel: mysqlDao.NewAdminDao(conf.DBConfig), - adminLogModel: mysqlDao.NewAdminLogDao(conf.DBConfig), - - conf: conf, - - cache: gocache.New(time.Minute, time.Minute), - } - - return ctr -} - -// SearchAdminLog godoc -// @Summary 管理员日志 -// @Description 返回管理员操作日志 -// @Security AdminKeyAuth -// @Tags admin.log -// @Accept json -// @Produce json -// @Param param body reqdata.SearchAdminLogReq true "搜索参数集" -// @success 200 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.AdminLog}} "获取成功" -// @Router /mag/admin_log/search [post] -func (ctr *AdminLogController) SearchAdminLog(ctx *gin.Context) { - var req reqdata.SearchAdminLogReq - ctx.ShouldBind(&req) - - params := &dto.SearchAdminLogParams{ - Keywords: req.Keywords, - Uid: req.AdminId, - } - - list, pager, err := ctr.adminLogModel.Search(params, &paginate.Pager{ - Page: req.Page, - Size: req.Size, - }) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pager, - })) -} - -// CreateLog godoc -// @Summary 日志创建 -// @Description 创建操作日志,可根据页面访问内容创建 -// @Security AdminKeyAuth -// @Tags admin.log -// @Accept json -// @Produce json -// @Param param body reqdata.SearchAdminLogReq true "搜索参数集" -// @success 200 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.AdminLog}} "获取成功" -// @Router /mag/admin_log/create [post] -func (ctr *AdminLogController) CreateLog(ctx *gin.Context) { - var req reqdata.CreateLogReq - ctx.ShouldBind(&req) - - ctr.logRecord(ctx, req.Content) - - ctr.Response(ctx, respdata.CSuccess) -} - -// LogRecord 日志记录 -func (ctr *AdminLogController) logRecord(ctx *gin.Context, log string) { - //不记录日志 - if len(log) == 0 { - return - } - //对应用户 - auth := gin_http.GetAuth(ctx) - - //同一用户,1分钟内与上次操作内容一致则不记录 - key := fmt.Sprintf("operate_log_%d", auth.Id) - if pre, exist := ctr.cache.Get(key); exist && pre == log { - ctr.l.Debug("operate log[%d] %s", auth.Id, log) - return - } - ctr.cache.SetDefault(key, log) - - //登录记录 - go func(p *dto.LoginInfoParam) { - ctr.adminLogModel.Add(&models.AdminLog{ - AdminId: auth.Id, - Nickname: auth.Nickname, - Account: auth.Account, - Device: p.Device, - Log: log, - Ip: p.Ip, - }) - }(&dto.LoginInfoParam{ - Time: time.Now(), - Ip: utils.GetRequestIp(ctx.Request), - Device: ctx.Request.Header.Get("User-Agent"), - }) -} - -// LogHandler 记录log(默认的log存储handler) -func (ctr *AdminLogController) LogHandler() gin.HandlerFunc { - return func(ctx *gin.Context) { - ctx.Next() - - if log, exist := ctx.Get(consts.OperateLogContextKey); exist && log != nil { - ctr.logRecord(ctx, log.(string)) - } - } -} diff --git a/src/apps/adminapp/controllers/http/ctr_admin_test.go b/src/apps/adminapp/controllers/http/ctr_admin_test.go deleted file mode 100644 index 637115516998a989d18b0d820e114daec70aea9b..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_admin_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package http - -import ( - "bytes" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/stretchr/testify/assert" - "go.uber.org/dig" - "io/ioutil" - "net/http" - "os" - "testing" -) - -func TestSearchAdmin(t *testing.T) { - - ctx, w := gin_http.NewTestAuthContext() - - ctx.Request.Body = ioutil.NopCloser(bytes.NewBufferString("{}")) - - di := newDi() - err := di.Invoke(func(ctr *AdminController) { - ctr.SearchAdmin(ctx) - - assert.Equal(t, http.StatusOK, ctx.Writer.Status()) - assert.IsType(t, "", w.Body.String()) - assert.Contains(t, w.Body.String(), "code") - assert.Contains(t, w.Body.String(), "msg") - assert.Contains(t, w.Body.String(), "list") - assert.Contains(t, w.Body.String(), "paginate") - - t.Logf("%s", w.Body.String()) - }) - assert.Equal(t, nil, err) -} - -func TestAuthCopy(t *testing.T) { - type A1 struct { - Id int64 - Name string - } - - type A2 struct { - Auth struct { - Id int64 - Name string - } - Token string - Extends map[string]string - } - type B1 struct { - Auth A1 - Token string - Extends map[string]string - } - - val := B1{ - Auth: A1{ - Id: 3, - Name: "name_111", - }, - Token: "abcd", - Extends: map[string]string{"status": "13"}, - } - - valCopy := utils.CopyTo(&val, new(A2)) - t.Logf("%+v", valCopy) - - t.Logf("root= %t", configstc.CommonExtendParams(valCopy.Extends).ExtendParamByBool("is_root")) - t.Logf("status= %d", configstc.CommonExtendParams(valCopy.Extends).ExtendParamByInt("status")) -} - -func newDi() *dig.Container { - di := dig.New() - di.Provide(func() *dig.Container { - return di - }) - di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, 0) - }) - di.Provide(func() *configstc.AdminAppConfig { - return &configstc.AdminAppConfig{ - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbName: "db_microservice", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - }, - AuthConfig: configstc.AuthConfig{ - SecretKey: "xjsajdad", - AuthExpired: 3600, - }, - } - }) - di.Provide(func(conf *configstc.AdminAppConfig) interfaces.ItfJwtParser { - return jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey) - }) - di.Provide(NewAdminController) - return di -} diff --git a/src/apps/adminapp/controllers/http/ctr_auth.go b/src/apps/adminapp/controllers/http/ctr_auth.go deleted file mode 100644 index 69446294abbd85df758ce4c6eb073f7c17c374d2..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_auth.go +++ /dev/null @@ -1,219 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/converts" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/i18n" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/passwd" - "github.com/gin-gonic/gin" - "github.com/gin-gonic/gin/binding" - "go.uber.org/dig" - "golang.org/x/text/language" - "net/http" - "time" -) - -type AuthController struct { - l v1log.ILog - - jwtAuth interfaces.ItfJwtParser - conf *configstc.AdminAppConfig - - adminModel interfaces.ItfAdminDao - - *gin_http.I18nController - passwd.SaltMd5Password - - gin_http.AuthExtendInfoOption -} - -func NewAuthController(di *dig.Scope, l v1log.ILog, conf *configstc.AdminAppConfig) *AuthController { - ctr := &AuthController{ - l: l, - adminModel: mysqlDao.NewAdminDao(conf.DBConfig), - - jwtAuth: jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey), - conf: conf, - - SaltMd5Password: passwd.SaltMd5Password{Salt: conf.PasswordSalt}, - } - - //i18n - { - parser := i18n.NewParser() - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nEn), language.English.String()+".toml") - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nZh), language.Chinese.String()+".toml") - //for name, path := range conf.I18nFiles { - // parser.Load(path, name+".toml") - // l.Info("load i18n path %s: %s, %s", name, path, parser.Lang(name).ParseMsg("Hello")) - //} - parser.SetLanguage(language.Chinese) - parser.CacheLanguages() - ctr.I18nController = &gin_http.I18nController{ - Parser: i18n.NewParser(), - } - } - - return ctr -} - -// AuthLogin 授权登录 godoc -// @Summary Auth-登录 -// @Description 登录 -// @Tags admin.auth -// @Produce json -// @Param param body reqdata.AuthReq true "账户信息" -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /mag/auth/login [post] -// @x-response-apikey-token-set {"tokenKey":"response.data.token","apiKey":"AdminKeyAuth"} -func (ctr *AuthController) AuthLogin(ctx *gin.Context) { - var req reqdata.AuthReq - - ctx.ShouldBindBodyWith(&req, binding.JSON) - //ctr.l.Info("req %+v", req) - - if req.Account == "" || req.Password == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - //查询表 - data, err := ctr.adminModel.QueryByAccount(req.Account) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CError) - return - } - if data == nil { - ctr.Response(ctx, respdata.CError.MMsg("PasswordWrong")) - return - } - password, salt, err := ctr.adminModel.QueryPassword(data.Id) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CError) - return - } - if password != passwd.GenSaltPasswordByMd5(req.Password, salt) { - ctr.Response(ctx, respdata.CError.MMsg("PasswordWrong")) - return - } - - //禁用用户 - if data.Status != consts.StatusEnable { - ctr.Response(ctx, respdata.CError.MMsg("AccountDisable")) - return - } - - //有效期 - if data.ExpiredAt > 0 && data.ExpiredAt < time.Now().Unix() { - ctr.Response(ctx, respdata.CError.MMsg("AccountExpired")) - return - } - - if data.LastLogin == nil { - t := time.Now() - data.LastLogin = &(t) - } - - authInfo := converts.AdminConvertAuthInfo(data) - - if ctr.AuthExtendInfoOption.ExtendInfoFunc != nil { - extends := ctr.AuthExtendInfoOption.ExtendInfoFunc(data.Id) - authInfo.Extends = utils.MergeMap(authInfo.Extends, extends) - } - - packet, err := converts.AuthToDataPacket(authInfo, time.Duration(ctr.conf.AuthConfig.AuthExpired)*time.Second, ctr.jwtAuth) - if err != nil { - ctr.l.Error("token fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.loginRecord(ctx, packet.Auth) - - gin_http.SetAuth(ctx, packet) - - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(&packet, new(respdata.AuthResp)))) -} - -// AuthLogout godoc -// @Summary Auth-取消授权 -// @Description 取消授权 -// @Tags admin.auth -// @Produce json -// @Security AdminKeyAuth -// @success 200 {object} respdata.ResponseData{} "取消成功" -// @success 500 {object} respdata.ResponseData{} "取消失败" -// @Router /mag/auth/logout [post] -func (ctr *AuthController) AuthLogout(ctx *gin.Context) { - ctx.JSON(http.StatusOK, respdata.CSuccess) -} - -// AuthInfo 登录信息 godoc -// @Summary Auth-登录信息 -// @Description 获取登录信息 -// @Tags admin.auth -// @Security AdminKeyAuth -// @Produce json -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "授权成功" -// @Router /mag/auth/info [post] -func (ctr *AuthController) AuthInfo(ctx *gin.Context) { - auth := gin_http.GetAuthDataPacket(ctx) - - //ctr.l.Debug("auth %d-%s", auth.Auth.Id, auth.Auth.Nickname) - auth.Token = "" - - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(&auth, new(respdata.AuthResp)))) -} - -// AuthCheck godoc -// @Summary Auth-登录校验 -// @Description 登录校验ok正常返回,不通过返回99 -// @Tags user.auth -// @Security ApiKeyAuth -// @Produce json -// @success 200 {object} respdata.ResponseData{} "返回结果" -// @Router /mag/auth/check [post] -func (ctr *AuthController) AuthCheck(ctx *gin.Context) { - ctr.Response(ctx, respdata.CSuccess) -} - -// AuthFreshToken godoc -// @Summary Auth-刷新授权 -// @Description 刷新授权token -// @Tags admin.auth -// @Produce json -// @Security AdminKeyAuth -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "刷新成功" -// @success 500 {object} respdata.ResponseData{} "刷新失败" -// @Router /mag/auth/fresh_token [post] -// @x-response-apikey-token-set {"tokenKey":"response.data.token","apiKey":"ApiKeyAuth"} -func (ctr *AuthController) AuthFreshToken(ctx *gin.Context) { - auth := gin_http.GetAuthDataPacket(ctx) - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(&auth, new(respdata.AuthResp)))) -} - -// loginRecord 登录记录 -func (ctr *AuthController) loginRecord(ctx *gin.Context, auth dto.AuthInfo) { - - //登录记录 - go func(p *dto.LoginInfoParam) { - ctr.adminModel.LoginNote(auth.Id, p) - }(&dto.LoginInfoParam{ - Time: time.Now(), - Ip: ctx.ClientIP(), - Device: ctx.Request.Header.Get("User-Agent"), - }) -} diff --git a/src/apps/adminapp/controllers/http/ctr_auth_test.go b/src/apps/adminapp/controllers/http/ctr_auth_test.go deleted file mode 100644 index 0783aa019b9f13d9a9a15c454c5621bda501ade6..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_auth_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package http - -import ( - "bytes" - "fmt" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/stretchr/testify/assert" - "go.uber.org/dig" - "io/ioutil" - "net/http" - "os" - "testing" -) - -func TestAuth(t *testing.T) { - - di := newDi1() - err := di.Invoke(func(ctr *AuthController) { - //不传参数 - ctx, w := gin_http.NewTestAuthContext() - ctx.Request.Body = ioutil.NopCloser(bytes.NewBufferString(` -{"account":"","password":""} -`)) - ctr.AuthLogin(ctx) - - assert.Equal(t, http.StatusOK, ctx.Writer.Status()) - assert.Contains(t, w.Body.String(), fmt.Sprintf("\"code\":%d,", respdata.CParamsInvalid.Code)) - assert.Contains(t, w.Body.String(), respdata.CParamsInvalid.Msg) - - //验证码 - ctx, w = gin_http.NewTestAuthContext() - ctx.Request.Body = ioutil.NopCloser(bytes.NewBufferString(` -{"account":"123","password":"123","captcha_key":"xxxx","captcha_code":"123456"} -`)) - ctr.AuthLogin(ctx) - - assert.Equal(t, http.StatusOK, ctx.Writer.Status()) - assert.Contains(t, w.Body.String(), fmt.Sprintf("\"code\":%d,", respdata.CVtCodeInvalid.Code)) - assert.Contains(t, w.Body.String(), respdata.CVtCodeInvalid.Msg) - - //账户/密码错误 - ctx, w = gin_http.NewTestAuthContext() - ctx.Request.Body = ioutil.NopCloser(bytes.NewBufferString(` -{"account":"123","password":"123","captcha_key":"vt_key","captcha_code":"12345678"} -`)) - ctr.AuthLogin(ctx) - assert.Equal(t, http.StatusOK, ctx.Writer.Status()) - assert.Contains(t, w.Body.String(), "\"code\":1,") - assert.Contains(t, w.Body.String(), "\"msg\":\"account/password wrong\",") - - //账户/密码正确 - - ctx, w = gin_http.NewTestAuthContext() - ctx.Request.Body = ioutil.NopCloser(bytes.NewBufferString(` -{"account":"demo","password":"123456","captcha_key":"vt_key","captcha_code":"123456"} -`)) - ctr.AuthLogin(ctx) - assert.Equal(t, http.StatusOK, ctx.Writer.Status()) - assert.Contains(t, w.Body.String(), "\"code\":0,") - assert.Contains(t, w.Body.String(), "auth") - assert.Contains(t, w.Body.String(), "expired_at") - assert.Contains(t, w.Body.String(), "\"id\":") - assert.Contains(t, w.Body.String(), "\"account\":\"demo\",") - }) - assert.Equal(t, nil, err) -} - -func TestAuthInfo(t *testing.T) { - - ctx, w := gin_http.NewTestAuthContext() - ctx.Request.Body = ioutil.NopCloser(bytes.NewBufferString("{}")) - - di := newDi1() - err := di.Invoke(func(ctr *AuthController) { - ctr.AuthInfo(ctx) - - assert.Equal(t, http.StatusOK, ctx.Writer.Status()) - assert.Contains(t, w.Body.String(), "\"code\":0,") - assert.Contains(t, w.Body.String(), "auth") - assert.Contains(t, w.Body.String(), "expired_at") - assert.Contains(t, w.Body.String(), "\"id\":1,") - assert.Contains(t, w.Body.String(), "\"account\":\"demo\",") - - t.Logf("STATUS %d", ctx.Writer.Status()) - }) - assert.Equal(t, nil, err) -} - -func newDi1() *dig.Container { - di := dig.New() - di.Provide(func() *dig.Container { - return di - }) - di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, 0) - }) - di.Provide(func() *configstc.AdminAppConfig { - return &configstc.AdminAppConfig{ - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbName: "db_microservice", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - }, - AuthConfig: configstc.AuthConfig{ - SecretKey: "xjsajdad", - AuthExpired: 3600, - }, - } - }) - di.Provide(func(conf *configstc.AdminAppConfig) interfaces.ItfJwtParser { - return jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey) - }) - di.Provide(NewAdminController) - return di -} diff --git a/src/apps/adminapp/controllers/http/ctr_captcha.go b/src/apps/adminapp/controllers/http/ctr_captcha.go deleted file mode 100644 index febf9acede1618873762eb02f30c168606342ae1..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_captcha.go +++ /dev/null @@ -1,17 +0,0 @@ -package http - -import ( - "github.com/gin-gonic/gin" -) - -// GetCaptcha godoc -// @Summary 验证码图片 -// @Description 验证码生成图片 -// @Tags admin.other -// @Produce json -// @success 0 {object} respdata.ResponseData{data=respdata.CaptchaResponse} "获取成功" -// @failure 1 {object} respdata.ResponseData{code=int} "获取失败" -// @Router /mag/captcha/get [post] -func GetCaptcha(ctx *gin.Context) { - //该代码用来生成captcha api的swagger用 -} diff --git a/src/apps/adminapp/controllers/http/ctr_organize.go b/src/apps/adminapp/controllers/http/ctr_organize.go deleted file mode 100644 index ac77e59638fed78c37bdc541734b3488a257eaf4..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_organize.go +++ /dev/null @@ -1,220 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type OrganizeManageController struct { - l v1log.ILog - conf *configstc.AdminAppConfig - - orgSrv interfaces.ItfOrganizeService - - gin_http.ResponseController -} - -func NewOrganizeManageController(di *dig.Scope, l v1log.ILog, conf *configstc.AdminAppConfig, orgSrv interfaces.ItfOrganizeService) *OrganizeManageController { - ctr := &OrganizeManageController{ - l: l, - conf: conf, - orgSrv: orgSrv, - } - - return ctr -} - -// SearchOrganize godoc -// @Summary 组织列表 -// @Description 搜索组织列表 -// @Tags admin.organize -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.SearchOrganizeReq true "搜索参数集" -// @success 0 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.Organize}} "获取成功" -// @Router /mag/organize/search [post] -func (ctr *OrganizeManageController) SearchOrganize(ctx *gin.Context) { - var req reqdata.SearchOrganizeReq - ctx.ShouldBind(&req) - - params := dto.SearchOrganizeParams{ - Keywords: req.Keywords, - Pid: req.Pid, - PType: req.PType, - Status: req.Status, - } - list, pa, err := ctr.orgSrv.Search(params, paginate.NewPager(req.Page, req.Size)) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pa, - })) -} - -// TreeOrganize godoc -// @Summary 组织树 -// @Description 搜索组织树 -// @Tags admin.organize -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.TreeOrganizeReq true "搜索参数集" -// @success 0 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]dto.SwaggerTreeNode}} "获取成功" -// @Router /mag/organize/tree [post] -func (ctr *OrganizeManageController) TreeOrganize(ctx *gin.Context) { - var req reqdata.TreeOrganizeReq - ctx.ShouldBind(&req) - - params := dto.TreeOrganizeParams{ - Pid: req.Pid, - PType: req.PType, - } - tree, err := ctr.orgSrv.Tree(params) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.Response(ctx, respdata.CSuccess.MData(tree)) -} - -// QueryOrganize godoc -// @Summary 查看详请 -// @Description 获取组织详细信息 -// @Security AdminKeyAuth -// @Tags admin.organize -// @Accept json -// @Produce json -// @Param param body reqdata.DetailReq true "查询指定id详情" -// @success 0 {object} respdata.ResponseData{data=respdata.OrganizeDetail} "获取成功" -// @failure 2 {object} respdata.ResponseData{} "系统错误" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @failure 8 {object} respdata.ResponseData{} "操作失败" -// @Router /mag/organize/detail [post] -func (ctr *OrganizeManageController) QueryOrganize(ctx *gin.Context) { - var req reqdata.DetailReq - - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - info, err := ctr.orgSrv.Query(req.Id) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(info)) -} - -// SaveOrganize godoc -// @Summary 组织新增/更新 -// @Description 新增组织,编辑提交组织 -// @Security AdminKeyAuth -// @Tags admin.organize -// @Accept json -// @Produce json -// @Param param body reqdata.AddEditOrganizeReq true "新增/编辑信息" -// @success 0 {object} respdata.ResponseData{data=models.Organize} "处理成功" -// @failure 2 {object} respdata.ResponseData{} "系统错误" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @failure 8 {object} respdata.ResponseData{} "操作失败" -// @Router /mag/organize/save [post] -func (ctr *OrganizeManageController) SaveOrganize(ctx *gin.Context) { - var req reqdata.AddEditOrganizeReq - ctx.ShouldBind(&req) - - data := models.Organize{ - Name: req.Name, - Description: req.Describe, - Type: "", - Pid: req.Pid, - Status: req.Status, - } - - var err error - if req.Id > 0 { - _, err = ctr.orgSrv.Update(req.Id, data) - } else { - _, err = ctr.orgSrv.Add(data) - } - - if err != nil { - ctr.l.Error("save err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -// DisableOrganize godoc -// @Summary 启用/禁用 -// @Description 操作启用/禁用指定组织 -// @Security AdminKeyAuth -// @Tags admin.organize -// @Accept json -// @Produce json -// @Param param body reqdata.SetStatusReq true "状态设置请求" -// @success 200 {object} respdata.ResponseData{} "设置成功" -// @Router /mag/organize/disable [post] -func (ctr *OrganizeManageController) DisableOrganize(ctx *gin.Context) { - var req reqdata.SetStatusReq - ctx.ShouldBind(&req) - if req.Id == 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - _, err := ctr.orgSrv.Enable(req.Id, req.Status) - if err != nil { - ctr.l.Error("set err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.Response(ctx, respdata.CSuccess) - return -} - -// DeleteOrganize godoc -// @Summary 删除组织 -// @Description 删除指定组织 -// @Security AdminKeyAuth -// @Tags admin.organize -// @Accept json -// @Produce json -// @Param param body reqdata.DetailReq true "指定管理员id" -// @success 200 {object} respdata.ResponseData{} "操作成功" -// @Router /mag/organize/delete [post] -func (ctr *OrganizeManageController) DeleteOrganize(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - _, err := ctr.orgSrv.Delete(req.Id) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} diff --git a/src/apps/adminapp/controllers/http/ctr_rbac.go b/src/apps/adminapp/controllers/http/ctr_rbac.go deleted file mode 100644 index d50b55d2db78c67060ccbe0726ef13e93c0e9be5..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_rbac.go +++ /dev/null @@ -1,620 +0,0 @@ -package http - -import ( - "encoding/json" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/converts" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "gorm.io/gorm" - "os" - "strings" -) - -type RbacController struct { - l v1log.ILog - conf *configstc.AdminAppConfig - rbacModel interfaces.ItfRbac - - //权限列表 - permissions []*dto.PermissionItem - - gin_http.ResponseController -} - -func NewRbacController(di *dig.Scope, l v1log.ILog, conf *configstc.AdminAppConfig) *RbacController { - ctr := &RbacController{ - l: l, - rbacModel: mysqlDao.NewRbacDao(conf.DBConfig), - conf: conf, - } - - { - var err error - _, err = ctr.rbacModel.Migrate() - common.ErrPanic(err) - } - - ctr.initPermission() - - return ctr -} - -func (ctr *RbacController) initPermission() { - var perms = []*dto.PermissionItem{ - {Id: 1, Name: "所有权限"}, - } - if ctr.conf.PermissionFile != "" { - perms = ctr.loadPermissionFromFile(ctr.conf.PermissionFile) - } - - //空权限且配置了权限文件则进行初始化 - if list, _ := ctr.rbacModel.Perms(); len(list) == 0 && len(perms) > 0 { - addPerms := utils.CopyMoreTo(perms, []*models.RbacPermission{}) - - err := ctr.rbacModel.DB().Transaction(func(tx *gorm.DB) error { - _, err := ctr.rbacModel.Use(tx).BatchAddPerm(addPerms...) - return err - }) - common.ErrPanic(err) - } - ctr.l.Info("load permissions num=%d", len(perms)) - ctr.permissions = perms -} - -func (ctr *RbacController) loadPermissionFromFile(file string) []*dto.PermissionItem { - var perms = []*dto.PermissionItem{} - s, err := os.ReadFile(file) - common.ErrPanic(err) - err = json.Unmarshal(s, &perms) - common.ErrPanic(err) - return perms -} - -// AccreditInfo godoc -// @Summary 账户中心-授权信息 -// @Description 返回授权权限清单 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @success 200 {object} respdata.ResponseData{data=[]dto.RbacPermissionSimple{}} "返回数据" -// @response 500 {object} respdata.ResponseData{} "查询失败" -// @Router /mag/u_center/accredit_info [post] -func (ctr *RbacController) AccreditInfo(ctx *gin.Context) { - auth := gin_http.GetAuth(ctx) - - var hasPerms []*dto.RbacPermissionSimple - //针对超级管理员返回所有 - if configstc.CommonExtendParams(auth.Extends).ExtendParamByBool("is_root") { - for _, v := range ctr.permissions { - hasPerms = append(hasPerms, utils.CopyTo(v, new(dto.RbacPermissionSimple))) - } - ctr.Response(ctx, respdata.CSuccess.MData(hasPerms)) - return - } - - //查询对应用户权限节点 - permIds, err := ctr.rbacModel.UserPermIds(auth.Id) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CError) - return - } - m := utils.SliceInt64ToMap(permIds) - - for _, v := range ctr.permissions { - if _, exist := m[v.Id]; exist { - hasPerms = append(hasPerms, utils.CopyTo(v, new(dto.RbacPermissionSimple))) - } - } - - ctr.Response(ctx, respdata.CSuccess.MData(hasPerms)) -} - -// SearchUserRoles godoc -// @Summary 角色管理-用户关联角色列表 -// @Description 修改个人信息 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.DetailReq false "指定用户id" -// @success 200 {object} respdata.ResponseData{data=[]int64{}} "返回数据" -// @success 500 {object} respdata.ResponseData{} "查询失败" -// @Router /mag/rbac/user/role/search [post] -func (ctr *RbacController) SearchUserRoles(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - list, err := ctr.rbacModel.UserRoleIds(req.Id) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(list)) -} - -// BindUserRoles godoc -// @Summary 角色管理-用户绑定关联角色 -// @Description 修改个人信息 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.SaveUserBindRoleReq false "提交参数" -// @success 200 {object} respdata.ResponseData{data=[]models.RbacRole{}} "返回数据" -// @success 500 {object} respdata.ResponseData{} "查询失败" -// @Router /mag/rbac/user/role/bind [post] -func (ctr *RbacController) BindUserRoles(ctx *gin.Context) { - var req reqdata.SaveUserBindRoleReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - err := ctr.rbacModel.UserRelateRoles(req.Id, req.Roles) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -// SearchRoles godoc -// @Summary 角色管理-角色列表 -// @Description 修改个人信息 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.SearchRolesReq false "查询参数,is_tree暂不支持" -// @success 200 {object} respdata.ResponseData{data=respdata.SearchListResponse{}} "返回数据" -// @success 200 {object} respdata.ResponseData{data=[]models.RbacRole{}} "List返回数据" -// @failure 500 {object} respdata.ResponseData{} "返回失败" -// @Router /mag/rbac/role/search [post] -func (ctr *RbacController) SearchRoles(ctx *gin.Context) { - var req reqdata.SearchRolesReq - ctx.ShouldBind(&req) - - params := &dto.SearchRbacRoleParams{ - Keywords: req.Keywords, - Status: req.Status, - } - roles, pa, err := ctr.rbacModel.SearchRoles(params, &paginate.Pager{ - Page: req.Page, - Size: req.Size, - }) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.l.Info("PA= %+v,%+v", pa, roles) - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: roles, - Paginate: *pa, - })) -} - -// SimpleRoles godoc -// @Summary 角色管理-角色列表(简易+全部返回) -// @Description 修改个人信息 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.ListOptionReq false "查询参数,is_tree暂不支持" -// @success 201 {object} respdata.ResponseData{data=[]dto.RbacRoleSimple{}} "返回数据,is_simple=true" -// @failure 500 {object} respdata.ResponseData{} "返回失败" -// @Router /mag/rbac/role/simples [post] -func (ctr *RbacController) SimpleRoles(ctx *gin.Context) { - var req reqdata.ListOptionReq - ctx.ShouldBind(&req) - roles, err := ctr.rbacModel.Roles() - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - //简易返回 - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyMoreTo(roles, []*dto.RbacRoleSimple{}))) -} - -// SearchRolePermissions godoc -// @Summary 角色管理-角色权限列表 -// @Description 修改个人信息 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.DetailReq false "指定role id" -// @success 200 {object} respdata.ResponseData{data=[]int64{}} "获取成功" -// @failure 500 {object} respdata.ResponseData{} "获取失败" -// @Router /mag/rbac/role/permissions [post] -func (ctr *RbacController) SearchRolePermissions(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 && len(req.Ids) == 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - permIds, err := ctr.rbacModel.RolePermIds(req.Id, req.Ids...) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(permIds)) -} - -// SaveRolePermissions godoc -// @Summary 角色管理-保存角色权限 -// @Description 角色关联权限保存 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.SaveRolePermissionReq false "保存信息" -// @success 200 {object} respdata.ResponseData{data=[]int64{}} "操作成功" -// @failure 500 {object} respdata.ResponseData{} "获取失败" -// @Router /mag/rbac/role/permission/save [post] -func (ctr *RbacController) SaveRolePermissions(ctx *gin.Context) { - var req reqdata.SaveRolePermissionReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - err := ctr.rbacModel.DB().Transaction(func(tx *gorm.DB) error { - return ctr.rbacModel.RoleRelatePerms(req.Id, req.Permissions) - }) - if err != nil { - ctr.l.Error("relate err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -// QueryRole godoc -// @Summary 角色管理-角色详情 -// @Description 角色基本信息详情 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.DetailReq false "指定role id" -// @success 0 {object} respdata.ResponseData{data=models.RbacRole} "查询成功" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @Router /mag/rbac/role/detail [post] -func (ctr *RbacController) QueryRole(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - role, err := ctr.rbacModel.QueryRole(req.Id) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.customizeLog(ctx, "查看角色-"+role.Name) - - ctr.Response(ctx, respdata.CSuccess.MData(role)) -} - -// SaveRole godoc -// @Summary 角色管理-角色新增/更新 -// @Description 新增/更新角色 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.AddEditRoleReq false "指定role id" -// @success 0 {object} respdata.ResponseData{data=respdata.DetailResp} "操作成功" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @Router /mag/rbac/role/save [post] -func (ctr *RbacController) SaveRole(ctx *gin.Context) { - var req reqdata.AddEditRoleReq - ctx.ShouldBind(&req) - if req.Id <= 0 && (req.Name == "") { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - role := models.RbacRole{ - Id: req.Id, - Name: req.Name, - Describe: req.Describe, - Sort: req.Sort, - Status: req.Status, - } - - var err error - if req.Id > 0 { - _, err = ctr.rbacModel.UpdateRole(req.Id, &role) - } else { - role.Id = 0 - _, err = ctr.rbacModel.AddRole(&role) - } - if err != nil { - ctr.l.Error("add err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if req.Id > 0 { - ctr.customizeLog(ctx, "更新角色-"+role.Name) - } else { - ctr.customizeLog(ctx, "新增角色-"+role.Name) - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.DetailResp{Id: role.Id})) -} - -// DisableRole godoc -// @Summary 角色管理-角色启用/禁用 -// @Description 操作启用/禁用角色 -// @Security AdminKeyAuth -// @Tags admin.rbac -// @Accept json -// @Produce json -// @Param param body reqdata.SetStatusReq true "状态设置请求" -// @success 200 {object} respdata.ResponseData{} "设置成功" -// @Router /mag/rbac/role/disable [post] -func (ctr *RbacController) DisableRole(ctx *gin.Context) { - var req reqdata.SetStatusReq - - ctx.ShouldBind(&req) - - if req.Status != consts.StatusEnable && req.Status != consts.StatusDisable { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - role, err := ctr.rbacModel.QueryRole(req.Id) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if role == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - _, err = ctr.rbacModel.ResetRoleStatus(req.Id, req.Status) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if req.Status == consts.StatusEnable { - ctr.customizeLog(ctx, "启用角色-"+role.Name) - } else { - ctr.customizeLog(ctx, "禁用角色-"+role.Name) - } - - ctr.Response(ctx, respdata.CSuccess) - return -} - -// DeleteRole godoc -// @Summary 角色管理-角色删除 -// @Description 操作删除角色 -// @Security AdminKeyAuth -// @Tags admin.rbac -// @Accept json -// @Produce json -// @Param param body reqdata.DetailReq false "指定role id" -// @success 200 {object} respdata.ResponseData{} "设置成功" -// @Router /mag/rbac/role/delete [post] -func (ctr *RbacController) DeleteRole(ctx *gin.Context) { - var req reqdata.DetailReq - - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - role, err := ctr.rbacModel.QueryRole(req.Id) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if role == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - err = ctr.rbacModel.DeleteRole(req.Id) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.customizeLog(ctx, "删除角色-"+role.Name) - - ctr.Response(ctx, respdata.CSuccess) - return -} - -// SearchPermissions godoc -// @Summary 权限管理-权限树 -// @Description 返回所有可操作的权限树 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.ListOptionReq false "查询参数" -// @success 0 {object} respdata.ResponseData{data=[]models.RbacPermission} "获取成功" -// @success 1 {object} respdata.ResponseData{data=[]dto.RbacPermissionSimple} "返回数据,is_simple=true" -// @success 2 {object} respdata.ResponseData{data=[]dto.RbacPermissionSimple} "返回树型数据,is_tree=true" -// @failure 100 {object} respdata.ResponseData{} "获取失败" -// @Router /mag/rbac/permission/search [post] -func (ctr *RbacController) SearchPermissions(ctx *gin.Context) { - var req reqdata.ListOptionReq - ctx.ShouldBind(&req) - list, err := ctr.rbacModel.Perms() - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if req.IsSimple { - ctr.customizeLog(ctx, "") - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyMoreTo(list, []*dto.RbacPermissionSimple{}))) - return - } - if req.IsTree { - ctr.customizeLog(ctx, "") - tree := converts.PermissionSimpleToTree(utils.CopyMoreTo(list, []*dto.RbacPermissionSimple{})) - ctr.Response(ctx, respdata.CSuccess.MData(tree)) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(list)) -} - -// SavePermission godoc -// @Summary 权限管理-权限节点新增/更新 -// @Description 权限节点新增/更新 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.AddEditPermissionReq false "提交信息" -// @success 200 {object} respdata.ResponseData{data=respdata.DetailResp} "操作成功" -// @success 500 {object} respdata.ResponseData{} "操作失败" -// @Router /mag/rbac/permission/save [post] -func (ctr *RbacController) SavePermission(ctx *gin.Context) { - var req reqdata.AddEditPermissionReq - ctx.ShouldBind(&req) - if req.Id <= 0 && (req.Name == "") { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - perm := models.RbacPermission{ - Id: req.Id, - Name: req.Name, - Describe: req.Describe, - Icon: req.Icon, - Type: req.Type, - Path: req.Path, - Sort: req.Sort, - Pid: req.Pid, - Status: req.Status, - Remark: "", - } - - var err error - if req.Id > 0 { - _, err = ctr.rbacModel.UpdatePerm(req.Id, &perm) - } else { - perm.Id = 0 - _, err = ctr.rbacModel.AddPerm(&perm) - } - if err != nil { - ctr.l.Error("add err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.DetailResp{Id: perm.Id})) -} - -// DeletePermission godoc -// @Summary 权限管理-删除权限节点 -// @Description 删除权限节点 -// @Tags admin.rbac -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.DetailReq true "删除请求" -// @success 200 {object} respdata.ResponseData{} "返回数据" -// @success 500 {object} respdata.ResponseData{} "返回失败" -// @Router /mag/rbac/permission/delete [post] -func (ctr *RbacController) DeletePermission(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - if err := ctr.rbacModel.DeletePerm(req.Id); err != nil { - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.Response(ctx, respdata.CSuccess) -} - -// CheckAccreditHandler 权限检查handler -func (ctr *RbacController) CheckAccreditHandler() gin.HandlerFunc { - //生成权限map - m := map[string]*dto.PermissionItem{} - for _, v := range ctr.permissions { - m[v.Path] = v - for _, vv := range v.Paths { - m[vv] = v - } - } - //根据不同模式(mode)判断授权 - accredit := func(ctx *gin.Context, mode consts.AccreditMode) bool { - auth := gin_http.GetAuth(ctx) - //root用户不限权限 - - if configstc.CommonExtendParams(auth.Extends).ExtendParamByBool("is_root") { - return true - } - list, _ := ctr.rbacModel.UserPermIds(auth.Id) //用户权限 - path := "api:" + strings.TrimPrefix(ctx.Request.URL.Path, ctr.conf.RoutePrefix) - //ctr.l.Info("Accredit %s", path) - if find, exist := m[path]; exist { - for _, v := range list { - if v == find.Id { - return true - } - } - } else { - return mode == consts.AccreditAllowWithIn - } - return false - } - return func(ctx *gin.Context) { - if !accredit(ctx, consts.AccreditAllowWithIn) { - ctr.Response(ctx, respdata.CPermissionDeny) - ctx.Abort() - return - } - ctx.Next() - } -} - -func (ctr *RbacController) Permissions() []*dto.PermissionItem { - return ctr.permissions -} - -// customizeLog 指定记录操作日志 -func (ctr *RbacController) customizeLog(ctx *gin.Context, log string) { - ctx.Set(consts.OperateLogContextKey, log) -} diff --git a/src/apps/adminapp/controllers/http/ctr_rbac_casbin.go.bak b/src/apps/adminapp/controllers/http/ctr_rbac_casbin.go.bak deleted file mode 100644 index 81a40ef500f7d287c2dd175a6378077927bd8ac9..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/controllers/http/ctr_rbac_casbin.go.bak +++ /dev/null @@ -1,583 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/converts" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/casbin/casbin/v2" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "os" -) - -import ( - _ "embed" - "encoding/json" -) - -// RbacCasbinController rbac(基于casbin实现) -type RbacCasbinController struct { - l v1log.ILog - conf *configstc.AdminAppConfig - cas *casbin.Enforcer - - roleDao interfaces.ItfRbacRole - //权限列表 - permissions []*dto.PermissionItem - - gin_http.ResponseController -} - -func NewRbacCasbinController(di *dig.Container, l v1log.ILog, cas *casbin.Enforcer, conf *configstc.AdminAppConfig) *RbacCasbinController { - ctr := &RbacCasbinController{ - l: l, - cas: cas, - conf: conf, - } - - common.ErrPanic(di.Invoke(func(roleDao interfaces.ItfRbacRole) { - ctr.roleDao = roleDao - })) - - ctr.initPermission() - - return ctr -} - -func (ctr *RbacCasbinController) initPermission() { - var perms = []*dto.PermissionItem{ - {Id: 1, Name: "所有权限"}, - } - if ctr.conf.PermissionFile != "" { - s, err := os.ReadFile(ctr.conf.PermissionFile) - common.ErrPanic(err) - err = json.Unmarshal(s, &perms) - common.ErrPanic(err) - } - - ctr.l.Info("load permissions num=%d", len(perms)) - ctr.permissions = perms -} - -// AccreditInfo godoc -// @Summary 账户中心-授权信息 -// @Description 返回授权权限清单 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @success 200 {object} respdata.ResponseData{data=[]dto.RbacPermissionSimple{}} "返回数据" -// @response 500 {object} respdata.ResponseData{} "查询失败" -// @Router /mag/u_center/accredit_info [post] -func (ctr *RbacCasbinController) AccreditInfo(ctx *gin.Context) { - auth := gin_http.GetAuth(ctx) - var hasPerms []string - - if configstc.CommonExtendParams(auth.Extends).ExtendParamByBool("is_root") { - for _, v := range ctr.permissions { - hasPerms = append(hasPerms, v.Path) - } - ctr.Response(ctx, respdata.CSuccess.MData(hasPerms)) - return - } - - userId := models.CasbinUserConvertStr(auth.Id, models.UserIdStrPrefix) - permIds, err := ctr.cas.GetImplicitPermissionsForUser(userId) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CError) - return - } - //ctr.l.Info("admin accredit %v %d", permIds, auth.Id) - - for _, v := range permIds { - hasPerms = append(hasPerms, v[2]) - } - - ctr.Response(ctx, respdata.CSuccess.MData(hasPerms)) -} - -// SearchUserRoles godoc -// @Summary 角色管理-用户关联角色列表 -// @Description 修改个人信息 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.DetailReq false "指定用户id" -// @success 200 {object} respdata.ResponseData{data=[]int64{}} "返回数据" -// @success 500 {object} respdata.ResponseData{} "查询失败" -// @Router /mag/rbac/user/role/search [post] -func (ctr *RbacCasbinController) SearchUserRoles(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - userId := models.CasbinUserConvertStr(req.Id, models.UserIdStrPrefix) - list, err := ctr.cas.GetRolesForUser(userId) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(models.CasbinUsersConvertId(list, models.RoleIdStrPrefix))) -} - -// BindUserRoles godoc -// @Summary 角色管理-用户绑定关联角色 -// @Description 修改个人信息 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body SaveUserBindRoleReq false "提交参数" -// @success 200 {object} respdata.ResponseData{data=[]models.RbacRole{}} "返回数据" -// @success 500 {object} respdata.ResponseData{} "查询失败" -// @Router /mag/rbac/user/role/bind [post] -func (ctr *RbacCasbinController) BindUserRoles(ctx *gin.Context) { - var req SaveUserBindRoleReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - userId := models.CasbinUserConvertStr(req.Id, models.UserIdStrPrefix) - _, err := ctr.cas.DeleteRolesForUser(userId) - if err != nil { - ctr.l.Error("delete err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - _, err = ctr.cas.AddRolesForUser(userId, models.CasbinUsersConvertStr(req.Roles, models.RoleIdStrPrefix)) - if err != nil { - ctr.l.Error("add roles err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -type SearchRoleReq struct { - Keywords string `json:"keywords" example:"d"` //关键字搜索 - Status int `json:"status" example:"0"` //状态,0:全部,1:启用,2:禁用 - Page int `json:"page" example:"1"` //分页-页码 - Size int `json:"size" example:"20"` //分页-条数 - - IsAll bool `json:"is_all"` -} - -// SearchRoles godoc -// @Summary 角色管理-角色列表 -// @Description 修改个人信息 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body SearchRoleReq false "查询参数" -// @success 200 {object} respdata.ResponseData{data=[]models.RbacRole{}} "返回数据" -// @success 201 {object} respdata.ResponseData{data=[]dto.RbacRoleSimple{}} "返回数据,is_simple=true" -// @failure 500 {object} respdata.ResponseData{} "返回失败" -// @Router /mag/rbac/role/search [post] -func (ctr *RbacCasbinController) SearchRoles(ctx *gin.Context) { - var req SearchRoleReq - ctx.ShouldBind(&req) - - params := &dto.SearchRbacRoleParams{ - Keywords: req.Keywords, - Status: req.Status, - IsAll: req.IsAll, - } - - list, pager, err := ctr.roleDao.Search(params, &paginate.Pager{ - Page: req.Page, - Size: req.Size, - }) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if req.IsAll { - ctr.Response(ctx, respdata.CSuccess.MData(list)) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pager, - })) -} - -// SearchRolePermissions godoc -// @Summary 角色管理-角色权限列表 -// @Description 修改个人信息 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.DetailReq false "指定role id" -// @success 200 {object} respdata.ResponseData{data=[]int64{}} "获取成功" -// @failure 500 {object} respdata.ResponseData{} "获取失败" -// @Router /mag/rbac/role/permissions [post] -func (ctr *RbacCasbinController) SearchRolePermissions(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - - var permIds []int64 - if req.Id > 0 { - req.Ids = append(req.Ids, req.Id) - } - for _, id := range req.Ids { - if id <= 0 { - continue - } - roleId := models.CasbinUserConvertStr(id, models.RoleIdStrPrefix) - roles, err := ctr.cas.GetPermissionsForUser(roleId) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - for _, v := range roles { - permIds = append(permIds, models.CasbinUserConvertId(v[1], "")) - } - } - - ctr.Response(ctx, respdata.CSuccess.MData(permIds)) -} - -// SaveRolePermissions godoc -// @Summary 角色管理-保存角色权限 -// @Description 角色关联权限保存 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body SaveRolePermissionReq false "保存信息" -// @success 200 {object} respdata.ResponseData{data=[]int64{}} "操作成功" -// @failure 500 {object} respdata.ResponseData{} "获取失败" -// @Router /mag/rbac/role/permission/save [post] -func (ctr *RbacCasbinController) SaveRolePermissions(ctx *gin.Context) { - var req SaveRolePermissionReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - roleId := models.CasbinUserConvertStr(req.Id, models.RoleIdStrPrefix) - - //先删除 - _, err := ctr.cas.DeletePermissionsForUser(roleId) - if err != nil { - ctr.l.Error("relate err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - //再添加 - var policies [][]string - for _, v := range req.Permissions { - - var perm *dto.PermissionItem - var exist bool - //查找对应节点 - for _, vv := range ctr.permissions { - if vv.Id == v { - perm = vv - exist = true - break - } - } - - if !exist { - ctr.l.Error("permission not found %d", v) - ctr.Response(ctx, respdata.CNotFound) - return - } - //path - policies = append(policies, []string{ - roleId, models.CasbinUserConvertStr(perm.Id, ""), perm.Path, - }) - //paths - for _, path := range perm.Paths { - policies = append(policies, []string{ - roleId, models.CasbinUserConvertStr(perm.Id, ""), path, - }) - } - } - _, err = ctr.cas.AddPolicies(policies) - if err != nil { - ctr.l.Error("relate err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -// QueryRole godoc -// @Summary 角色管理-角色详情 -// @Description 角色基本信息详情 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.DetailReq false "指定role id" -// @success 0 {object} respdata.ResponseData{data=models.RbacRole} "查询成功" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @Router /mag/rbac/role/detail [post] -func (ctr *RbacCasbinController) QueryRole(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - role, err := ctr.roleDao.Query(req.Id) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(role)) -} - -// SaveRole godoc -// @Summary 角色管理-角色新增/更新 -// @Description 新增/更新角色 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body addEditRoleReq false "指定role id" -// @success 0 {object} respdata.ResponseData{data=respdata.DetailResp} "操作成功" -// @failure 4 {object} respdata.ResponseData{} "参数错误" -// @Router /mag/rbac/role/save [post] -func (ctr *RbacCasbinController) SaveRole(ctx *gin.Context) { - var req addEditRoleReq - ctx.ShouldBind(&req) - if req.Id <= 0 && (req.Name == "") { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - role := models.RbacRole{ - Id: req.Id, - Name: req.Name, - Describe: req.Describe, - Sort: req.Sort, - Status: req.Status, - } - - var err error - if req.Id > 0 { - _, err = ctr.roleDao.Update(req.Id, &role) - } else { - role.Id = 0 - _, err = ctr.roleDao.Add(&role) - } - if err != nil { - ctr.l.Error("add err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.DetailResp{Id: role.Id})) -} - -// DisableRole godoc -// @Summary 角色管理-角色启用/禁用 -// @Description 操作启用/禁用角色 -// @Security AdminKeyAuth -// @Tags admin -// @Accept json -// @Produce json -// @Param param body reqdata.SetStatusReq true "状态设置请求" -// @success 200 {object} respdata.ResponseData{} "设置成功" -// @Router /mag/rbac/role/disable [post] -func (ctr *RbacCasbinController) DisableRole(ctx *gin.Context) { - var req reqdata.SetStatusReq - - ctx.ShouldBind(&req) - - if req.Status != consts.StatusEnable && req.Status != consts.StatusDisable { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - role, err := ctr.roleDao.Query(req.Id) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if role == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - _, err = ctr.roleDao.ResetStatus(req.Id, req.Status) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) - return -} - -// DeleteRole godoc -// @Summary 角色管理-角色删除 -// @Description 操作删除角色 -// @Security AdminKeyAuth -// @Tags admin -// @Accept json -// @Produce json -// @Param param body reqdata.DetailReq false "指定role id" -// @success 200 {object} respdata.ResponseData{} "设置成功" -// @Router /mag/rbac/role/delete [post] -func (ctr *RbacCasbinController) DeleteRole(ctx *gin.Context) { - var req reqdata.DetailReq - - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - role, err := ctr.roleDao.Query(req.Id) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if role == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - err = ctr.roleDao.Delete(req.Id) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -// SearchPermissions godoc -// @Summary 权限管理-权限树 -// @Description 返回所有可操作的权限树 -// @Tags admin -// @Produce json -// @Security AdminKeyAuth -// @Param param body treeReq false "查询参数" -// @success 0 {object} respdata.ResponseData{data=[]models.RbacPermission} "获取成功" -// @success 1 {object} respdata.ResponseData{data=[]dto.RbacPermissionSimple} "返回数据,is_simple=true" -// @success 2 {object} respdata.ResponseData{data=[]dto.RbacPermissionSimple} "返回树型数据,is_tree=true" -// @failure 100 {object} respdata.ResponseData{} "获取失败" -// @Router /mag/rbac/permission/search [post] -func (ctr *RbacCasbinController) SearchPermissions(ctx *gin.Context) { - var req treeReq - ctx.ShouldBind(&req) - if req.IsTree { - - list := converts.PermissionSimpleToTree(utils.CopyMoreTo(ctr.permissions, []*dto.RbacPermissionSimple{})) - ctr.Response(ctx, respdata.CSuccess.MData(list)) - return - } - ctr.Response(ctx, respdata.CSuccess.MData(ctr.permissions)) -} - -// AccreditHandler 权限检查handler -func (ctr *RbacCasbinController) AccreditHandler() gin.HandlerFunc { - ////生成权限map - //m := map[string]*models.RbacPermission{} - //for _, v := range ctr.permissions { - // m[v.Path] = v - // for _, vv := range v.Paths { - // m[vv] = v - // } - //} - ////根据不同模式(mode)判断授权 - //accredit := func(ctx *gin.Context, mode models.AccreditMode) bool { - // auth := ctr.auth(ctx) - // //root用户不限权限 - // if auth.IsRoot == 1 { - // return true - // } - // list, _ := ctr.roleDao.UserPermIds(auth.Id) //用户权限 - // path := "api:" + strings.TrimPrefix(ctx.Request.URL.Path, ctr.conf.RoutePrefix) - // //ctr.l.Info("Accredit %s", path) - // if find, exist := m[path]; exist { - // for _, v := range list { - // if v == find.Id { - // return true - // } - // } - // } else { - // return mode == models.AccreditAllowWithIn - // } - // return false - //} - return func(ctx *gin.Context) { - //if !accredit(ctx, models.AccreditAllowWithIn) { - // ctr.Response(ctx, respdata.CPermissionDeny) - // ctx.Abort() - // return - //} - ctx.Next() - } -} - -// addEditRoleReq 添加编辑请求 -type addEditRoleReq struct { - Id int64 `json:"id" example:"0"` //id,>0为编辑对应,=0为新增 - Name string `json:"name" example:"role1"` //名称 - Describe string `json:"describe" example:"this a role"` //描述 - Sort int `json:"sort" example:"0"` //排序值 - - Status int `json:"status" example:"1"` //状态 -} - -// SaveRolePermissionReq 关联role权限请求 -type SaveRolePermissionReq struct { - Id int64 `json:"id" example:"1"` //对应角色id - Permissions []int64 `json:"permissions"` //关联的权限节点id列表 -} - -// SaveUserBindRoleReq 关联role权限请求 -type SaveUserBindRoleReq struct { - Id int64 `json:"id" example:"1"` //对应用户id - Roles []int64 `json:"roles"` //关联的角色id列表 -} - -// addEditRoleReq 添加编辑请求 -type addEditPermissionReq struct { - Id int64 `json:"id" example:"0"` //id,>0为编辑对应,=0为新增 - - Name string `json:"name" example:"系统设置"` //权限名称 - Describe string `json:"describe" example:"系统设置菜单"` //描述信息 - Path string `json:"path" example:"/page/setting"` //对应权限路径:页面路径/api路径 - Type string `json:"type" example:"menu"` //类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量 - Icon string `json:"icon" example:"setting"` //icon地址 - Sort int `json:"sort" example:"1"` //排序值 - Pid int64 `json:"pid" example:"0"` //上级id - Remark string `json:"remark" example:""` //备注 - Status int `json:"status" example:"1"` //状态 -} - -// treeReq 列表相关选项请求 -type treeReq struct { - IsTree bool `json:"is_tree"` //是否树型返回 -} diff --git a/src/apps/adminapp/docs/adminservice_docs.go b/src/apps/adminapp/docs/adminservice_docs.go deleted file mode 100644 index d0e4a79ec83c28a4eba59ebe20b1beffb6941322..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/docs/adminservice_docs.go +++ /dev/null @@ -1,3092 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplateadminservice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/-admin-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.AdminAppConfig" - } - } - } - } - } - }, - "/mag/admin/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除管理员", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-删除管理员", - "parameters": [ - { - "description": "指定管理员id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取管理员详细信息", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-查看详请", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AdminDetailResp" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用管理员", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "新增管理员,编辑提交管理员", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-新增/更新", - "parameters": [ - { - "description": "新增/编辑信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AddEditAdminReq" - } - } - ], - "responses": { - "0": { - "description": "处理成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.Admin" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "搜索管理员列表", - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-搜索列表", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchAdminReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Admin" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/admin_log/create": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "创建操作日志,可根据页面访问内容创建", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.log" - ], - "summary": "日志创建", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchAdminLogReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.AdminLog" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/admin_log/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "返回管理员操作日志", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.log" - ], - "summary": "管理员日志", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchAdminLogReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.AdminLog" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/auth/fresh_token": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "刷新授权token", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-刷新授权", - "responses": { - "200": { - "description": "刷新成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "刷新失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/mag/auth/info": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取登录信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-登录信息", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - } - } - } - }, - "/mag/auth/login": { - "post": { - "description": "登录", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-登录", - "parameters": [ - { - "description": "账户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "AdminKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/mag/auth/logout": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "取消授权", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-取消授权", - "responses": { - "200": { - "description": "取消成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "取消失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/captcha/get": { - "post": { - "description": "验证码生成图片", - "produces": [ - "application/json" - ], - "tags": [ - "admin.other" - ], - "summary": "验证码图片", - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.CaptchaResponse" - } - } - } - ] - } - }, - "1": { - "description": "获取失败", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "code": { - "type": "integer" - } - } - } - ] - } - } - } - } - }, - "/mag/organize/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除指定组织", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "删除组织", - "parameters": [ - { - "description": "指定管理员id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取组织详细信息", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "查看详请", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.OrganizeDetail" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用指定组织", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "新增组织,编辑提交组织", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "组织新增/更新", - "parameters": [ - { - "description": "新增/编辑信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AddEditOrganizeReq" - } - } - ], - "responses": { - "0": { - "description": "处理成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.Organize" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "搜索组织列表", - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "组织列表", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchOrganizeReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Organize" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/organize/tree": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "搜索组织树", - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "组织树", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.TreeOrganizeReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SwaggerTreeNode" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/rbac/permission/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除权限节点", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "权限管理-删除权限节点", - "parameters": [ - { - "description": "删除请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "返回数据", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "返回失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/permission/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "权限节点新增/更新", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "权限管理-权限节点新增/更新", - "parameters": [ - { - "description": "提交信息", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.AddEditPermissionReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.DetailResp" - } - } - } - ] - } - }, - "500": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/permission/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "返回所有可操作的权限树", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "权限管理-权限树", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ListOptionReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.RbacPermission" - } - } - } - } - ] - } - }, - "1": { - "description": "返回数据,is_simple=true", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - } - } - } - ] - } - }, - "100": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "返回树型数据,is_tree=true", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - } - } - } - ] - } - } - } - } - }, - "/mag/rbac/role/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作删除角色", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色删除", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "角色基本信息详情", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色详情", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "查询成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.RbacRole" - } - } - } - ] - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用角色", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/permission/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "角色关联权限保存", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-保存角色权限", - "parameters": [ - { - "description": "保存信息", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.SaveRolePermissionReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "integer" - } - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/permissions": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色权限列表", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "integer" - } - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "新增/更新角色", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色新增/更新", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.AddEditRoleReq" - } - } - ], - "responses": { - "0": { - "description": "操作成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.DetailResp" - } - } - } - ] - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色列表", - "parameters": [ - { - "description": "查询参数,is_tree暂不支持", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.SearchRolesReq" - } - } - ], - "responses": { - "200": { - "description": "List返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.RbacRole" - } - } - } - } - ] - } - }, - "500": { - "description": "返回失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/simples": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色列表(简易+全部返回)", - "parameters": [ - { - "description": "查询参数,is_tree暂不支持", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ListOptionReq" - } - } - ], - "responses": { - "201": { - "description": "返回数据,is_simple=true", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacRoleSimple" - } - } - } - } - ] - } - }, - "500": { - "description": "返回失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/user/role/bind": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-用户绑定关联角色", - "parameters": [ - { - "description": "提交参数", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.SaveUserBindRoleReq" - } - } - ], - "responses": { - "200": { - "description": "返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.RbacRole" - } - } - } - } - ] - } - }, - "500": { - "description": "查询失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/user/role/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-用户关联角色列表", - "parameters": [ - { - "description": "指定用户id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "integer" - } - } - } - } - ] - } - }, - "500": { - "description": "查询失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/accredit_info": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "返回授权权限清单", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "账户中心-授权信息", - "responses": { - "200": { - "description": "返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - } - } - } - ] - } - }, - "500": { - "description": "查询失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "用户信息,比AuthInfo提供信息更详细", - "produces": [ - "application/json" - ], - "tags": [ - "admin.center" - ], - "summary": "用户信息", - "responses": { - "0": { - "description": "重置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/modify_info": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.center" - ], - "summary": "账户中心-修改个人信息", - "parameters": [ - { - "description": "用户信息", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ModifyInfoReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "修改失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/modify_pwd": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改密码", - "produces": [ - "application/json" - ], - "tags": [ - "admin.center" - ], - "summary": "账户中心-修改密码", - "parameters": [ - { - "description": "提价", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ModifyPasswordReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "修改失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.AdminAppConfig": { - "type": "object", - "properties": { - "ApiServer": { - "$ref": "#/definitions/configstc.ServerConfig" - }, - "AuthConfig": { - "$ref": "#/definitions/configstc.AuthConfig" - }, - "AutoCreateAdmin": { - "description": "是否自动创建admin账户", - "type": "boolean" - }, - "DBConfig": { - "$ref": "#/definitions/configstc.DBConfig" - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "DocsEnable": { - "description": "是否启用文档", - "type": "boolean" - }, - "I18nFiles": { - "description": "多语言配置:key=language,value=path", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "LimitingApi": { - "description": "api限流", - "allOf": [ - { - "$ref": "#/definitions/configstc.LimitingConfig" - } - ] - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "ModuleMode": { - "description": "模块模式,作为module使用", - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "PProfEnable": { - "description": "是否启用pprof", - "type": "boolean" - }, - "PasswordSalt": { - "description": "密码salt", - "type": "string" - }, - "PermissionFile": { - "description": "权限文件json", - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - }, - "UserPasswordSalt": { - "description": "用户-密码salt", - "type": "string" - } - } - }, - "configstc.AuthConfig": { - "type": "object", - "properties": { - "AuthExpired": { - "description": "授权失效时间,单位:秒", - "type": "integer" - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "SecretKey": { - "description": "加密秘钥,如JWT", - "type": "string" - } - } - }, - "configstc.DBConfig": { - "type": "object", - "properties": { - "ConnMaxIdleTime": { - "description": "每个链接最大空闲时间", - "type": "integer", - "default": 0 - }, - "ConnMaxLifeTime": { - "description": "每个链接最大生存时间", - "type": "integer", - "default": 0 - }, - "DbConn": { - "description": "数据库类型,如mysql", - "type": "string" - }, - "DbDsn": { - "description": "数据库dsn", - "type": "string" - }, - "DbHost": { - "description": "数据库地址", - "type": "string" - }, - "DbName": { - "description": "数据库", - "type": "string" - }, - "DbPassword": { - "description": "密码", - "type": "string" - }, - "DbPort": { - "description": "端口", - "type": "string" - }, - "DbUser": { - "description": "用户名", - "type": "string" - }, - "MaxConcatLen": { - "type": "string" - }, - "MaxIdleConn": { - "description": "预留并发链接数", - "type": "integer", - "default": 0 - }, - "MaxOpenConn": { - "description": "最大支持链接", - "type": "integer", - "default": 0 - }, - "TablePrefix": { - "description": "表前缀", - "type": "string" - }, - "TimeZone": { - "description": "时区设置", - "type": "string" - } - } - }, - "configstc.LimitingConfig": { - "type": "object", - "properties": { - "MaxRate": { - "description": "允许的最大速率", - "type": "integer" - }, - "PerRate": { - "description": "每次(秒)速率", - "type": "integer" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "EndpointAddr": { - "description": "对外访问地址", - "type": "string" - }, - "EndpointPort": { - "description": "对外访问端口", - "type": "integer" - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "dto.RbacPermissionSimple": { - "type": "object", - "properties": { - "children": { - "description": "子权限节点列表", - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "path": { - "description": "对应权限路径:页面路径/api路径", - "type": "string" - }, - "pid": { - "type": "integer" - }, - "sort": { - "type": "integer" - }, - "status": { - "type": "integer" - }, - "type": { - "description": "类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量", - "type": "string" - } - } - }, - "dto.RbacRoleSimple": { - "type": "object", - "properties": { - "domain": { - "description": "所在域(命名空间)", - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "status": { - "description": "0:未知,1:可用,2:禁用", - "type": "integer" - } - } - }, - "dto.SwaggerTreeNode": { - "type": "object", - "properties": { - "children": { - "description": "子节点", - "type": "array", - "items": { - "$ref": "#/definitions/dto.SwaggerTreeNode" - } - }, - "data": { - "description": "节点数据" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "pid": { - "description": "pid", - "type": "string" - } - } - }, - "models.Admin": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "email": { - "type": "string" - }, - "expired_at": { - "description": "过期时间,为0不过期,\u003e0为过期时间的秒级时间戳", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "is_root": { - "description": "1:是root,0:非root", - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "remark": { - "description": "备注", - "type": "string" - }, - "salt": { - "description": "密码盐", - "type": "string" - }, - "status": { - "description": "0:无,1:可用,2:禁用", - "type": "integer" - }, - "tenant_id": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.AdminLog": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "admin_id": { - "type": "integer" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "device": { - "description": "操作设备", - "type": "string" - }, - "id": { - "type": "integer" - }, - "ip": { - "description": "操作ip", - "type": "string" - }, - "log": { - "description": "日志内容", - "type": "string" - }, - "nickname": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.Organize": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "pid": { - "type": "integer" - }, - "status": { - "description": "组织状态,0:无,1:正常,2:禁用,其他自行定义", - "type": "integer" - }, - "tenant_id": { - "type": "integer" - }, - "type": { - "description": "组织类型,自行定义,用于不同类型的组织区分", - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.RbacPermission": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "describe": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "path": { - "description": "对应权限路径:页面路径/api路径", - "type": "string" - }, - "paths": { - "description": "对应的权限路径集合", - "type": "array", - "items": { - "type": "string" - } - }, - "pid": { - "type": "integer" - }, - "remark": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "status": { - "type": "integer" - }, - "type": { - "description": "类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量", - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.RbacRole": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "describe": { - "type": "string" - }, - "domain": { - "description": "所在域(命名空间)", - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "status": { - "description": "0:未知,1:可用,2:禁用", - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.AddEditAdminReq": { - "type": "object", - "properties": { - "account": { - "description": "账户名(创建后无法更改)", - "type": "string", - "example": "demo" - }, - "avatar": { - "description": "头像", - "type": "string", - "example": "https://img2.baidu.com/it/u=1978192862,2048448374\u0026fm=253\u0026fmt=auto\u0026app=138\u0026f=JPEG?w=504\u0026h=500" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "1000000@qq.com" - }, - "expired_at": { - "description": "过期时间,为0为永不过期,\u003e0的秒级时间戳", - "type": "integer", - "example": 0 - }, - "id": { - "description": "id,\u003e0为编辑对应数据,=0为新增", - "type": "integer", - "example": 0 - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo_1" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13612348888" - }, - "remark": { - "description": "备注", - "type": "string", - "example": "test add" - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AddEditOrganizeReq": { - "type": "object", - "properties": { - "describe": { - "description": "备注", - "type": "string", - "example": "备注" - }, - "id": { - "description": "id,\u003e0为编辑对应数据,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "description": "名称", - "type": "string", - "example": "demo_1" - }, - "pid": { - "description": "上级id", - "type": "integer", - "example": 0 - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AddEditPermissionReq": { - "type": "object", - "properties": { - "describe": { - "description": "描述信息", - "type": "string", - "example": "系统设置菜单" - }, - "icon": { - "description": "icon地址", - "type": "string", - "example": "setting" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "description": "权限名称", - "type": "string", - "example": "系统设置" - }, - "path": { - "description": "对应权限路径:页面路径/api路径", - "type": "string", - "example": "/page/setting" - }, - "pid": { - "description": "上级id", - "type": "integer", - "example": 0 - }, - "remark": { - "description": "备注", - "type": "string", - "example": "" - }, - "sort": { - "description": "排序值", - "type": "integer", - "example": 1 - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - }, - "type": { - "description": "类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量", - "type": "string", - "example": "menu" - } - } - }, - "reqdata.AddEditRoleReq": { - "type": "object", - "properties": { - "describe": { - "description": "描述", - "type": "string", - "example": "this a role" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "description": "名称", - "type": "string", - "example": "role1" - }, - "sort": { - "description": "排序值", - "type": "integer", - "example": 0 - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AuthReq": { - "type": "object", - "properties": { - "account": { - "description": "账户名", - "type": "string", - "example": "13488886666" - }, - "captcha_code": { - "description": "验证码", - "type": "string", - "example": "123456" - }, - "captcha_key": { - "description": "验证码key", - "type": "string", - "example": "xxxx" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.DetailReq": { - "type": "object", - "properties": { - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - }, - "ids": { - "description": "多个数据id", - "type": "array", - "items": { - "type": "integer" - }, - "example": [ - 1, - 2 - ] - } - } - }, - "reqdata.ListOptionReq": { - "type": "object", - "properties": { - "is_simple": { - "description": "是否简易返回,false:正常返回,true:simple返回", - "type": "boolean" - }, - "is_tree": { - "description": "是否树型返回", - "type": "boolean" - } - } - }, - "reqdata.ModifyInfoReq": { - "type": "object", - "properties": { - "avatar": { - "description": "头像", - "type": "string", - "example": "xxx" - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo" - }, - "sex": { - "description": "性别", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.ModifyPasswordReq": { - "type": "object", - "properties": { - "old_password": { - "description": "旧密码", - "type": "string", - "example": "123456" - }, - "password": { - "description": "新密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.SaveRolePermissionReq": { - "type": "object", - "properties": { - "id": { - "description": "对应角色id", - "type": "integer", - "example": 1 - }, - "permissions": { - "description": "关联的权限节点id列表", - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "reqdata.SaveUserBindRoleReq": { - "type": "object", - "properties": { - "id": { - "description": "对应用户id", - "type": "integer", - "example": 1 - }, - "roles": { - "description": "关联的角色id列表", - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "reqdata.SearchAdminLogReq": { - "type": "object", - "properties": { - "admin_id": { - "description": "指定管理员id", - "type": "integer", - "example": 0 - }, - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "a" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - } - } - }, - "reqdata.SearchAdminReq": { - "type": "object", - "properties": { - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "d" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "status": { - "description": "状态,0:全部,1:启用,2:禁用", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SearchOrganizeReq": { - "type": "object", - "properties": { - "keywords": { - "type": "string" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "pid": { - "type": "integer" - }, - "pid_type": { - "description": "pid查询类型,0:所有子child,1:只查一级", - "type": "integer" - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "status": { - "description": "状态,0:全部", - "type": "integer" - } - } - }, - "reqdata.SearchRolesReq": { - "type": "object", - "properties": { - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "d" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "status": { - "description": "状态,0:全部,1:启用,2:禁用", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SetStatusReq": { - "type": "object", - "properties": { - "id": { - "description": "id", - "type": "integer" - }, - "status": { - "description": "状态", - "type": "integer" - } - } - }, - "reqdata.TreeOrganizeReq": { - "type": "object", - "properties": { - "pid": { - "type": "integer" - }, - "pid_type": { - "description": "pid查询类型,0:所有子child,1:只查一级", - "type": "integer" - } - } - }, - "respdata.AdminDetailResp": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "email": { - "type": "string" - }, - "expired_at": { - "description": "过期时间", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "is_root": { - "description": "1:是root,0:非root", - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "remark": { - "description": "备注", - "type": "string" - }, - "status": { - "description": "0:无,1:可用,2:禁用", - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "respdata.AuthResp": { - "type": "object", - "properties": { - "auth": { - "description": "授权信息", - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "extends": { - "description": "额外信息", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "nickname": { - "type": "string" - }, - "saas_id": { - "description": "saas模式下用到的归属租户id", - "type": "integer" - }, - "saas_name": { - "description": "saas模式下用到的归属租户的名称", - "type": "string" - }, - "status": { - "type": "integer" - } - } - }, - "expired_at": { - "description": "过期时间戳,秒级", - "type": "integer" - }, - "token": { - "description": "授权凭证", - "type": "string" - } - } - }, - "respdata.CaptchaResponse": { - "type": "object", - "properties": { - "img": { - "type": "string" - }, - "key": { - "type": "string" - } - } - }, - "respdata.DetailResp": { - "type": "object", - "properties": { - "id": { - "description": "指定编辑的对象id", - "type": "integer" - } - } - }, - "respdata.OrganizeDetail": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "parent_name": { - "description": "上级组织名称", - "type": "string" - }, - "pid": { - "type": "integer" - }, - "status": { - "description": "组织状态,0:无,1:正常,2:禁用,其他自行定义", - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfoadminservice holds exported Swagger Info so clients can modify it -var SwaggerInfoadminservice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "Admin模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "adminservice", - SwaggerTemplate: docTemplateadminservice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfoadminservice.InstanceName(), SwaggerInfoadminservice) -} diff --git a/src/apps/adminapp/docs/adminservice_swagger.json b/src/apps/adminapp/docs/adminservice_swagger.json deleted file mode 100644 index 33d207ad5e193832b45c50a37c1e863ef170cca8..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/docs/adminservice_swagger.json +++ /dev/null @@ -1,3072 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "Admin模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": { - "/-admin-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.AdminAppConfig" - } - } - } - } - } - }, - "/mag/admin/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除管理员", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-删除管理员", - "parameters": [ - { - "description": "指定管理员id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取管理员详细信息", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-查看详请", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AdminDetailResp" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用管理员", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "新增管理员,编辑提交管理员", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-新增/更新", - "parameters": [ - { - "description": "新增/编辑信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AddEditAdminReq" - } - } - ], - "responses": { - "0": { - "description": "处理成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.Admin" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/admin/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "搜索管理员列表", - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "管理员管理-搜索列表", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchAdminReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Admin" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/admin_log/create": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "创建操作日志,可根据页面访问内容创建", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.log" - ], - "summary": "日志创建", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchAdminLogReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.AdminLog" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/admin_log/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "返回管理员操作日志", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.log" - ], - "summary": "管理员日志", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchAdminLogReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.AdminLog" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/auth/fresh_token": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "刷新授权token", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-刷新授权", - "responses": { - "200": { - "description": "刷新成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "刷新失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/mag/auth/info": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取登录信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-登录信息", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - } - } - } - }, - "/mag/auth/login": { - "post": { - "description": "登录", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-登录", - "parameters": [ - { - "description": "账户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "AdminKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/mag/auth/logout": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "取消授权", - "produces": [ - "application/json" - ], - "tags": [ - "admin.auth" - ], - "summary": "Auth-取消授权", - "responses": { - "200": { - "description": "取消成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "取消失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/captcha/get": { - "post": { - "description": "验证码生成图片", - "produces": [ - "application/json" - ], - "tags": [ - "admin.other" - ], - "summary": "验证码图片", - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.CaptchaResponse" - } - } - } - ] - } - }, - "1": { - "description": "获取失败", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "code": { - "type": "integer" - } - } - } - ] - } - } - } - } - }, - "/mag/organize/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除指定组织", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "删除组织", - "parameters": [ - { - "description": "指定管理员id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取组织详细信息", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "查看详请", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.OrganizeDetail" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用指定组织", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "新增组织,编辑提交组织", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "组织新增/更新", - "parameters": [ - { - "description": "新增/编辑信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AddEditOrganizeReq" - } - } - ], - "responses": { - "0": { - "description": "处理成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.Organize" - } - } - } - ] - } - }, - "2": { - "description": "系统错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "8": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/organize/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "搜索组织列表", - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "组织列表", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchOrganizeReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Organize" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/organize/tree": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "搜索组织树", - "produces": [ - "application/json" - ], - "tags": [ - "admin.organize" - ], - "summary": "组织树", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.TreeOrganizeReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.SwaggerTreeNode" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/mag/rbac/permission/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除权限节点", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "权限管理-删除权限节点", - "parameters": [ - { - "description": "删除请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "返回数据", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "返回失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/permission/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "权限节点新增/更新", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "权限管理-权限节点新增/更新", - "parameters": [ - { - "description": "提交信息", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.AddEditPermissionReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.DetailResp" - } - } - } - ] - } - }, - "500": { - "description": "操作失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/permission/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "返回所有可操作的权限树", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "权限管理-权限树", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ListOptionReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.RbacPermission" - } - } - } - } - ] - } - }, - "1": { - "description": "返回数据,is_simple=true", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - } - } - } - ] - } - }, - "100": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "返回树型数据,is_tree=true", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - } - } - } - ] - } - } - } - } - }, - "/mag/rbac/role/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作删除角色", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色删除", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "角色基本信息详情", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色详情", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "查询成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.RbacRole" - } - } - } - ] - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用角色", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/permission/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "角色关联权限保存", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-保存角色权限", - "parameters": [ - { - "description": "保存信息", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.SaveRolePermissionReq" - } - } - ], - "responses": { - "200": { - "description": "操作成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "integer" - } - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/permissions": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色权限列表", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "integer" - } - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "新增/更新角色", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色新增/更新", - "parameters": [ - { - "description": "指定role id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.AddEditRoleReq" - } - } - ], - "responses": { - "0": { - "description": "操作成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.DetailResp" - } - } - } - ] - } - }, - "4": { - "description": "参数错误", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色列表", - "parameters": [ - { - "description": "查询参数,is_tree暂不支持", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.SearchRolesReq" - } - } - ], - "responses": { - "200": { - "description": "List返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.RbacRole" - } - } - } - } - ] - } - }, - "500": { - "description": "返回失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/role/simples": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-角色列表(简易+全部返回)", - "parameters": [ - { - "description": "查询参数,is_tree暂不支持", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ListOptionReq" - } - } - ], - "responses": { - "201": { - "description": "返回数据,is_simple=true", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacRoleSimple" - } - } - } - } - ] - } - }, - "500": { - "description": "返回失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/user/role/bind": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-用户绑定关联角色", - "parameters": [ - { - "description": "提交参数", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.SaveUserBindRoleReq" - } - } - ], - "responses": { - "200": { - "description": "返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.RbacRole" - } - } - } - } - ] - } - }, - "500": { - "description": "查询失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rbac/user/role/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "角色管理-用户关联角色列表", - "parameters": [ - { - "description": "指定用户id", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "200": { - "description": "返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "integer" - } - } - } - } - ] - } - }, - "500": { - "description": "查询失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/accredit_info": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "返回授权权限清单", - "produces": [ - "application/json" - ], - "tags": [ - "admin.rbac" - ], - "summary": "账户中心-授权信息", - "responses": { - "200": { - "description": "返回数据", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - } - } - } - ] - } - }, - "500": { - "description": "查询失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "用户信息,比AuthInfo提供信息更详细", - "produces": [ - "application/json" - ], - "tags": [ - "admin.center" - ], - "summary": "用户信息", - "responses": { - "0": { - "description": "重置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/modify_info": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.center" - ], - "summary": "账户中心-修改个人信息", - "parameters": [ - { - "description": "用户信息", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ModifyInfoReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "修改失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/u_center/modify_pwd": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "修改密码", - "produces": [ - "application/json" - ], - "tags": [ - "admin.center" - ], - "summary": "账户中心-修改密码", - "parameters": [ - { - "description": "提价", - "name": "param", - "in": "body", - "schema": { - "$ref": "#/definitions/reqdata.ModifyPasswordReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "修改失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.AdminAppConfig": { - "type": "object", - "properties": { - "ApiServer": { - "$ref": "#/definitions/configstc.ServerConfig" - }, - "AuthConfig": { - "$ref": "#/definitions/configstc.AuthConfig" - }, - "AutoCreateAdmin": { - "description": "是否自动创建admin账户", - "type": "boolean" - }, - "DBConfig": { - "$ref": "#/definitions/configstc.DBConfig" - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "DocsEnable": { - "description": "是否启用文档", - "type": "boolean" - }, - "I18nFiles": { - "description": "多语言配置:key=language,value=path", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "LimitingApi": { - "description": "api限流", - "allOf": [ - { - "$ref": "#/definitions/configstc.LimitingConfig" - } - ] - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "ModuleMode": { - "description": "模块模式,作为module使用", - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "PProfEnable": { - "description": "是否启用pprof", - "type": "boolean" - }, - "PasswordSalt": { - "description": "密码salt", - "type": "string" - }, - "PermissionFile": { - "description": "权限文件json", - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - }, - "UserPasswordSalt": { - "description": "用户-密码salt", - "type": "string" - } - } - }, - "configstc.AuthConfig": { - "type": "object", - "properties": { - "AuthExpired": { - "description": "授权失效时间,单位:秒", - "type": "integer" - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "SecretKey": { - "description": "加密秘钥,如JWT", - "type": "string" - } - } - }, - "configstc.DBConfig": { - "type": "object", - "properties": { - "ConnMaxIdleTime": { - "description": "每个链接最大空闲时间", - "type": "integer", - "default": 0 - }, - "ConnMaxLifeTime": { - "description": "每个链接最大生存时间", - "type": "integer", - "default": 0 - }, - "DbConn": { - "description": "数据库类型,如mysql", - "type": "string" - }, - "DbDsn": { - "description": "数据库dsn", - "type": "string" - }, - "DbHost": { - "description": "数据库地址", - "type": "string" - }, - "DbName": { - "description": "数据库", - "type": "string" - }, - "DbPassword": { - "description": "密码", - "type": "string" - }, - "DbPort": { - "description": "端口", - "type": "string" - }, - "DbUser": { - "description": "用户名", - "type": "string" - }, - "MaxConcatLen": { - "type": "string" - }, - "MaxIdleConn": { - "description": "预留并发链接数", - "type": "integer", - "default": 0 - }, - "MaxOpenConn": { - "description": "最大支持链接", - "type": "integer", - "default": 0 - }, - "TablePrefix": { - "description": "表前缀", - "type": "string" - }, - "TimeZone": { - "description": "时区设置", - "type": "string" - } - } - }, - "configstc.LimitingConfig": { - "type": "object", - "properties": { - "MaxRate": { - "description": "允许的最大速率", - "type": "integer" - }, - "PerRate": { - "description": "每次(秒)速率", - "type": "integer" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "EndpointAddr": { - "description": "对外访问地址", - "type": "string" - }, - "EndpointPort": { - "description": "对外访问端口", - "type": "integer" - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "dto.RbacPermissionSimple": { - "type": "object", - "properties": { - "children": { - "description": "子权限节点列表", - "type": "array", - "items": { - "$ref": "#/definitions/dto.RbacPermissionSimple" - } - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "path": { - "description": "对应权限路径:页面路径/api路径", - "type": "string" - }, - "pid": { - "type": "integer" - }, - "sort": { - "type": "integer" - }, - "status": { - "type": "integer" - }, - "type": { - "description": "类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量", - "type": "string" - } - } - }, - "dto.RbacRoleSimple": { - "type": "object", - "properties": { - "domain": { - "description": "所在域(命名空间)", - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "status": { - "description": "0:未知,1:可用,2:禁用", - "type": "integer" - } - } - }, - "dto.SwaggerTreeNode": { - "type": "object", - "properties": { - "children": { - "description": "子节点", - "type": "array", - "items": { - "$ref": "#/definitions/dto.SwaggerTreeNode" - } - }, - "data": { - "description": "节点数据" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "pid": { - "description": "pid", - "type": "string" - } - } - }, - "models.Admin": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "email": { - "type": "string" - }, - "expired_at": { - "description": "过期时间,为0不过期,\u003e0为过期时间的秒级时间戳", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "is_root": { - "description": "1:是root,0:非root", - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "remark": { - "description": "备注", - "type": "string" - }, - "salt": { - "description": "密码盐", - "type": "string" - }, - "status": { - "description": "0:无,1:可用,2:禁用", - "type": "integer" - }, - "tenant_id": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.AdminLog": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "admin_id": { - "type": "integer" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "device": { - "description": "操作设备", - "type": "string" - }, - "id": { - "type": "integer" - }, - "ip": { - "description": "操作ip", - "type": "string" - }, - "log": { - "description": "日志内容", - "type": "string" - }, - "nickname": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.Organize": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "pid": { - "type": "integer" - }, - "status": { - "description": "组织状态,0:无,1:正常,2:禁用,其他自行定义", - "type": "integer" - }, - "tenant_id": { - "type": "integer" - }, - "type": { - "description": "组织类型,自行定义,用于不同类型的组织区分", - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.RbacPermission": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "describe": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "path": { - "description": "对应权限路径:页面路径/api路径", - "type": "string" - }, - "paths": { - "description": "对应的权限路径集合", - "type": "array", - "items": { - "type": "string" - } - }, - "pid": { - "type": "integer" - }, - "remark": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "status": { - "type": "integer" - }, - "type": { - "description": "类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量", - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.RbacRole": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "describe": { - "type": "string" - }, - "domain": { - "description": "所在域(命名空间)", - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "sort": { - "type": "integer" - }, - "status": { - "description": "0:未知,1:可用,2:禁用", - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.AddEditAdminReq": { - "type": "object", - "properties": { - "account": { - "description": "账户名(创建后无法更改)", - "type": "string", - "example": "demo" - }, - "avatar": { - "description": "头像", - "type": "string", - "example": "https://img2.baidu.com/it/u=1978192862,2048448374\u0026fm=253\u0026fmt=auto\u0026app=138\u0026f=JPEG?w=504\u0026h=500" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "1000000@qq.com" - }, - "expired_at": { - "description": "过期时间,为0为永不过期,\u003e0的秒级时间戳", - "type": "integer", - "example": 0 - }, - "id": { - "description": "id,\u003e0为编辑对应数据,=0为新增", - "type": "integer", - "example": 0 - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo_1" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13612348888" - }, - "remark": { - "description": "备注", - "type": "string", - "example": "test add" - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AddEditOrganizeReq": { - "type": "object", - "properties": { - "describe": { - "description": "备注", - "type": "string", - "example": "备注" - }, - "id": { - "description": "id,\u003e0为编辑对应数据,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "description": "名称", - "type": "string", - "example": "demo_1" - }, - "pid": { - "description": "上级id", - "type": "integer", - "example": 0 - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AddEditPermissionReq": { - "type": "object", - "properties": { - "describe": { - "description": "描述信息", - "type": "string", - "example": "系统设置菜单" - }, - "icon": { - "description": "icon地址", - "type": "string", - "example": "setting" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "description": "权限名称", - "type": "string", - "example": "系统设置" - }, - "path": { - "description": "对应权限路径:页面路径/api路径", - "type": "string", - "example": "/page/setting" - }, - "pid": { - "description": "上级id", - "type": "integer", - "example": 0 - }, - "remark": { - "description": "备注", - "type": "string", - "example": "" - }, - "sort": { - "description": "排序值", - "type": "integer", - "example": 1 - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - }, - "type": { - "description": "类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量", - "type": "string", - "example": "menu" - } - } - }, - "reqdata.AddEditRoleReq": { - "type": "object", - "properties": { - "describe": { - "description": "描述", - "type": "string", - "example": "this a role" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "description": "名称", - "type": "string", - "example": "role1" - }, - "sort": { - "description": "排序值", - "type": "integer", - "example": 0 - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AuthReq": { - "type": "object", - "properties": { - "account": { - "description": "账户名", - "type": "string", - "example": "13488886666" - }, - "captcha_code": { - "description": "验证码", - "type": "string", - "example": "123456" - }, - "captcha_key": { - "description": "验证码key", - "type": "string", - "example": "xxxx" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.DetailReq": { - "type": "object", - "properties": { - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - }, - "ids": { - "description": "多个数据id", - "type": "array", - "items": { - "type": "integer" - }, - "example": [ - 1, - 2 - ] - } - } - }, - "reqdata.ListOptionReq": { - "type": "object", - "properties": { - "is_simple": { - "description": "是否简易返回,false:正常返回,true:simple返回", - "type": "boolean" - }, - "is_tree": { - "description": "是否树型返回", - "type": "boolean" - } - } - }, - "reqdata.ModifyInfoReq": { - "type": "object", - "properties": { - "avatar": { - "description": "头像", - "type": "string", - "example": "xxx" - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo" - }, - "sex": { - "description": "性别", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.ModifyPasswordReq": { - "type": "object", - "properties": { - "old_password": { - "description": "旧密码", - "type": "string", - "example": "123456" - }, - "password": { - "description": "新密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.SaveRolePermissionReq": { - "type": "object", - "properties": { - "id": { - "description": "对应角色id", - "type": "integer", - "example": 1 - }, - "permissions": { - "description": "关联的权限节点id列表", - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "reqdata.SaveUserBindRoleReq": { - "type": "object", - "properties": { - "id": { - "description": "对应用户id", - "type": "integer", - "example": 1 - }, - "roles": { - "description": "关联的角色id列表", - "type": "array", - "items": { - "type": "integer" - } - } - } - }, - "reqdata.SearchAdminLogReq": { - "type": "object", - "properties": { - "admin_id": { - "description": "指定管理员id", - "type": "integer", - "example": 0 - }, - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "a" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - } - } - }, - "reqdata.SearchAdminReq": { - "type": "object", - "properties": { - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "d" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "status": { - "description": "状态,0:全部,1:启用,2:禁用", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SearchOrganizeReq": { - "type": "object", - "properties": { - "keywords": { - "type": "string" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "pid": { - "type": "integer" - }, - "pid_type": { - "description": "pid查询类型,0:所有子child,1:只查一级", - "type": "integer" - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "status": { - "description": "状态,0:全部", - "type": "integer" - } - } - }, - "reqdata.SearchRolesReq": { - "type": "object", - "properties": { - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "d" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "status": { - "description": "状态,0:全部,1:启用,2:禁用", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SetStatusReq": { - "type": "object", - "properties": { - "id": { - "description": "id", - "type": "integer" - }, - "status": { - "description": "状态", - "type": "integer" - } - } - }, - "reqdata.TreeOrganizeReq": { - "type": "object", - "properties": { - "pid": { - "type": "integer" - }, - "pid_type": { - "description": "pid查询类型,0:所有子child,1:只查一级", - "type": "integer" - } - } - }, - "respdata.AdminDetailResp": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "email": { - "type": "string" - }, - "expired_at": { - "description": "过期时间", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "is_root": { - "description": "1:是root,0:非root", - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "remark": { - "description": "备注", - "type": "string" - }, - "status": { - "description": "0:无,1:可用,2:禁用", - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "respdata.AuthResp": { - "type": "object", - "properties": { - "auth": { - "description": "授权信息", - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "extends": { - "description": "额外信息", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "nickname": { - "type": "string" - }, - "saas_id": { - "description": "saas模式下用到的归属租户id", - "type": "integer" - }, - "saas_name": { - "description": "saas模式下用到的归属租户的名称", - "type": "string" - }, - "status": { - "type": "integer" - } - } - }, - "expired_at": { - "description": "过期时间戳,秒级", - "type": "integer" - }, - "token": { - "description": "授权凭证", - "type": "string" - } - } - }, - "respdata.CaptchaResponse": { - "type": "object", - "properties": { - "img": { - "type": "string" - }, - "key": { - "type": "string" - } - } - }, - "respdata.DetailResp": { - "type": "object", - "properties": { - "id": { - "description": "指定编辑的对象id", - "type": "integer" - } - } - }, - "respdata.OrganizeDetail": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "parent_name": { - "description": "上级组织名称", - "type": "string" - }, - "pid": { - "type": "integer" - }, - "status": { - "description": "组织状态,0:无,1:正常,2:禁用,其他自行定义", - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/adminapp/docs/adminservice_swagger.yaml b/src/apps/adminapp/docs/adminservice_swagger.yaml deleted file mode 100644 index 1ce5054870380350111989561b74aad23c21e4d8..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/docs/adminservice_swagger.yaml +++ /dev/null @@ -1,1942 +0,0 @@ -basePath: / -definitions: - configstc.AdminAppConfig: - properties: - ApiServer: - $ref: '#/definitions/configstc.ServerConfig' - AuthConfig: - $ref: '#/definitions/configstc.AuthConfig' - AutoCreateAdmin: - description: 是否自动创建admin账户 - type: boolean - DBConfig: - $ref: '#/definitions/configstc.DBConfig' - Debug: - description: debug开关 - type: boolean - DocsEnable: - description: 是否启用文档 - type: boolean - I18nFiles: - additionalProperties: - type: string - description: 多语言配置:key=language,value=path - type: object - LimitingApi: - allOf: - - $ref: '#/definitions/configstc.LimitingConfig' - description: api限流 - LogLevel: - type: string - LogPath: - description: 日志路径 - type: string - ModuleMode: - description: 模块模式,作为module使用 - type: boolean - Name: - type: string - PProfEnable: - description: 是否启用pprof - type: boolean - PasswordSalt: - description: 密码salt - type: string - PermissionFile: - description: 权限文件json - type: string - RoutePrefix: - description: 路由前缀 - type: string - UserPasswordSalt: - description: 用户-密码salt - type: string - type: object - configstc.AuthConfig: - properties: - AuthExpired: - description: 授权失效时间,单位:秒 - type: integer - Enable: - description: 是否启用 - type: boolean - SecretKey: - description: 加密秘钥,如JWT - type: string - type: object - configstc.DBConfig: - properties: - ConnMaxIdleTime: - default: 0 - description: 每个链接最大空闲时间 - type: integer - ConnMaxLifeTime: - default: 0 - description: 每个链接最大生存时间 - type: integer - DbConn: - description: 数据库类型,如mysql - type: string - DbDsn: - description: 数据库dsn - type: string - DbHost: - description: 数据库地址 - type: string - DbName: - description: 数据库 - type: string - DbPassword: - description: 密码 - type: string - DbPort: - description: 端口 - type: string - DbUser: - description: 用户名 - type: string - MaxConcatLen: - type: string - MaxIdleConn: - default: 0 - description: 预留并发链接数 - type: integer - MaxOpenConn: - default: 0 - description: 最大支持链接 - type: integer - TablePrefix: - description: 表前缀 - type: string - TimeZone: - description: 时区设置 - type: string - type: object - configstc.LimitingConfig: - properties: - MaxRate: - description: 允许的最大速率 - type: integer - PerRate: - description: 每次(秒)速率 - type: integer - type: object - configstc.ServerConfig: - properties: - AllowOrigins: - description: 指定跨域允许访问源,空则为不限制访问 - items: - type: string - type: array - Enable: - description: 是否启用 - type: boolean - EndpointAddr: - description: 对外访问地址 - type: string - EndpointPort: - description: 对外访问端口 - type: integer - Host: - description: Host is the hostname or IP address of the service. - type: string - Port: - description: 端口 - type: integer - ServerBindAddr: - description: ListenAndServe to bind to, such as 0.0.0.0 - type: string - Timeout: - description: Timeout specifies a timeout (in milliseconds) - type: integer - type: object - dto.RbacPermissionSimple: - properties: - children: - description: 子权限节点列表 - items: - $ref: '#/definitions/dto.RbacPermissionSimple' - type: array - icon: - type: string - id: - type: integer - name: - type: string - path: - description: 对应权限路径:页面路径/api路径 - type: string - pid: - type: integer - sort: - type: integer - status: - type: integer - type: - description: 类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量 - type: string - type: object - dto.RbacRoleSimple: - properties: - domain: - description: 所在域(命名空间) - type: string - id: - type: integer - name: - type: string - sort: - type: integer - status: - description: 0:未知,1:可用,2:禁用 - type: integer - type: object - dto.SwaggerTreeNode: - properties: - children: - description: 子节点 - items: - $ref: '#/definitions/dto.SwaggerTreeNode' - type: array - data: - description: 节点数据 - id: - type: string - name: - type: string - pid: - description: pid - type: string - type: object - models.Admin: - properties: - account: - type: string - avatar: - type: string - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - email: - type: string - expired_at: - description: 过期时间,为0不过期,>0为过期时间的秒级时间戳 - type: integer - id: - type: integer - is_root: - description: 1:是root,0:非root - type: integer - last_ip: - description: 上次登录ip - type: string - last_login: - description: 上次登录时间 - type: string - nickname: - type: string - password: - type: string - phone: - description: 手机号 - type: string - remark: - description: 备注 - type: string - salt: - description: 密码盐 - type: string - status: - description: 0:无,1:可用,2:禁用 - type: integer - tenant_id: - type: integer - updated_at: - type: string - type: object - models.AdminLog: - properties: - account: - type: string - admin_id: - type: integer - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - device: - description: 操作设备 - type: string - id: - type: integer - ip: - description: 操作ip - type: string - log: - description: 日志内容 - type: string - nickname: - type: string - updated_at: - type: string - type: object - models.Organize: - properties: - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - description: - type: string - id: - type: integer - name: - type: string - pid: - type: integer - status: - description: 组织状态,0:无,1:正常,2:禁用,其他自行定义 - type: integer - tenant_id: - type: integer - type: - description: 组织类型,自行定义,用于不同类型的组织区分 - type: string - updated_at: - type: string - type: object - models.RbacPermission: - properties: - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - describe: - type: string - icon: - type: string - id: - type: integer - name: - type: string - path: - description: 对应权限路径:页面路径/api路径 - type: string - paths: - description: 对应的权限路径集合 - items: - type: string - type: array - pid: - type: integer - remark: - type: string - sort: - type: integer - status: - type: integer - type: - description: 类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量 - type: string - updated_at: - type: string - type: object - models.RbacRole: - properties: - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - describe: - type: string - domain: - description: 所在域(命名空间) - type: string - id: - type: integer - name: - type: string - sort: - type: integer - status: - description: 0:未知,1:可用,2:禁用 - type: integer - updated_at: - type: string - type: object - paginate.Pager: - properties: - page: - description: 当前页码 - type: integer - page_count: - description: 总页数 - type: integer - paging_id: - description: 分页用id,用于辅助分页用,可为主键id值 - type: integer - size: - description: 单页数量 - type: integer - total: - description: 总条数 - type: integer - type: object - reqdata.AddEditAdminReq: - properties: - account: - description: 账户名(创建后无法更改) - example: demo - type: string - avatar: - description: 头像 - example: https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500 - type: string - email: - description: 邮箱 - example: 1000000@qq.com - type: string - expired_at: - description: 过期时间,为0为永不过期,>0的秒级时间戳 - example: 0 - type: integer - id: - description: id,>0为编辑对应数据,=0为新增 - example: 0 - type: integer - nickname: - description: 昵称 - example: demo_1 - type: string - password: - description: 密码 - example: "123456" - type: string - phone: - description: 手机号 - example: "13612348888" - type: string - remark: - description: 备注 - example: test add - type: string - status: - description: 状态 - example: 1 - type: integer - type: object - reqdata.AddEditOrganizeReq: - properties: - describe: - description: 备注 - example: 备注 - type: string - id: - description: id,>0为编辑对应数据,=0为新增 - example: 0 - type: integer - name: - description: 名称 - example: demo_1 - type: string - pid: - description: 上级id - example: 0 - type: integer - status: - description: 状态 - example: 1 - type: integer - type: object - reqdata.AddEditPermissionReq: - properties: - describe: - description: 描述信息 - example: 系统设置菜单 - type: string - icon: - description: icon地址 - example: setting - type: string - id: - description: id,>0为编辑对应,=0为新增 - example: 0 - type: integer - name: - description: 权限名称 - example: 系统设置 - type: string - path: - description: 对应权限路径:页面路径/api路径 - example: /page/setting - type: string - pid: - description: 上级id - example: 0 - type: integer - remark: - description: 备注 - example: "" - type: string - sort: - description: 排序值 - example: 1 - type: integer - status: - description: 状态 - example: 1 - type: integer - type: - description: 类型, 枚举: menu/action/api,可参考下面的 PermissionType前缀的常量 - example: menu - type: string - type: object - reqdata.AddEditRoleReq: - properties: - describe: - description: 描述 - example: this a role - type: string - id: - description: id,>0为编辑对应,=0为新增 - example: 0 - type: integer - name: - description: 名称 - example: role1 - type: string - sort: - description: 排序值 - example: 0 - type: integer - status: - description: 状态 - example: 1 - type: integer - type: object - reqdata.AuthReq: - properties: - account: - description: 账户名 - example: "13488886666" - type: string - captcha_code: - description: 验证码 - example: "123456" - type: string - captcha_key: - description: 验证码key - example: xxxx - type: string - password: - description: 密码 - example: "123456" - type: string - type: object - reqdata.DetailReq: - properties: - id: - description: 数据id - example: 0 - type: integer - ids: - description: 多个数据id - example: - - 1 - - 2 - items: - type: integer - type: array - type: object - reqdata.ListOptionReq: - properties: - is_simple: - description: 是否简易返回,false:正常返回,true:simple返回 - type: boolean - is_tree: - description: 是否树型返回 - type: boolean - type: object - reqdata.ModifyInfoReq: - properties: - avatar: - description: 头像 - example: xxx - type: string - nickname: - description: 昵称 - example: demo - type: string - sex: - description: 性别 - example: 0 - type: integer - type: object - reqdata.ModifyPasswordReq: - properties: - old_password: - description: 旧密码 - example: "123456" - type: string - password: - description: 新密码 - example: "123456" - type: string - type: object - reqdata.SaveRolePermissionReq: - properties: - id: - description: 对应角色id - example: 1 - type: integer - permissions: - description: 关联的权限节点id列表 - items: - type: integer - type: array - type: object - reqdata.SaveUserBindRoleReq: - properties: - id: - description: 对应用户id - example: 1 - type: integer - roles: - description: 关联的角色id列表 - items: - type: integer - type: array - type: object - reqdata.SearchAdminLogReq: - properties: - admin_id: - description: 指定管理员id - example: 0 - type: integer - keywords: - description: 关键字搜索 - example: a - type: string - page: - description: 分页-页码 - example: 1 - type: integer - size: - description: 分页-条数 - example: 20 - type: integer - type: object - reqdata.SearchAdminReq: - properties: - keywords: - description: 关键字搜索 - example: d - type: string - page: - description: 分页-页码 - example: 1 - type: integer - size: - description: 分页-条数 - example: 20 - type: integer - status: - description: 状态,0:全部,1:启用,2:禁用 - example: 0 - type: integer - type: object - reqdata.SearchOrganizeReq: - properties: - keywords: - type: string - page: - description: 分页-页码 - example: 1 - type: integer - pid: - type: integer - pid_type: - description: pid查询类型,0:所有子child,1:只查一级 - type: integer - size: - description: 分页-条数 - example: 20 - type: integer - status: - description: 状态,0:全部 - type: integer - type: object - reqdata.SearchRolesReq: - properties: - keywords: - description: 关键字搜索 - example: d - type: string - page: - description: 分页-页码 - example: 1 - type: integer - size: - description: 分页-条数 - example: 20 - type: integer - status: - description: 状态,0:全部,1:启用,2:禁用 - example: 0 - type: integer - type: object - reqdata.SetStatusReq: - properties: - id: - description: id - type: integer - status: - description: 状态 - type: integer - type: object - reqdata.TreeOrganizeReq: - properties: - pid: - type: integer - pid_type: - description: pid查询类型,0:所有子child,1:只查一级 - type: integer - type: object - respdata.AdminDetailResp: - properties: - account: - type: string - avatar: - type: string - created_at: - type: string - email: - type: string - expired_at: - description: 过期时间 - type: integer - id: - type: integer - is_root: - description: 1:是root,0:非root - type: integer - last_ip: - description: 上次登录ip - type: string - last_login: - description: 上次登录时间 - type: string - nickname: - type: string - phone: - description: 手机号 - type: string - remark: - description: 备注 - type: string - status: - description: 0:无,1:可用,2:禁用 - type: integer - updated_at: - type: string - type: object - respdata.AuthResp: - properties: - auth: - description: 授权信息 - properties: - account: - type: string - avatar: - type: string - extends: - additionalProperties: - type: string - description: 额外信息 - type: object - id: - type: integer - nickname: - type: string - saas_id: - description: saas模式下用到的归属租户id - type: integer - saas_name: - description: saas模式下用到的归属租户的名称 - type: string - status: - type: integer - type: object - expired_at: - description: 过期时间戳,秒级 - type: integer - token: - description: 授权凭证 - type: string - type: object - respdata.CaptchaResponse: - properties: - img: - type: string - key: - type: string - type: object - respdata.DetailResp: - properties: - id: - description: 指定编辑的对象id - type: integer - type: object - respdata.OrganizeDetail: - properties: - created_at: - type: string - description: - type: string - id: - type: integer - name: - type: string - parent_name: - description: 上级组织名称 - type: string - pid: - type: integer - status: - description: 组织状态,0:无,1:正常,2:禁用,其他自行定义 - type: integer - updated_at: - type: string - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object - respdata.SearchListResponse: - properties: - list: - description: 列表 - paginate: - allOf: - - $ref: '#/definitions/paginate.Pager' - description: 分页信息 - type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Admin模块API - version: "1.0" -paths: - /-admin-config: - post: - description: CONFIG-配置内容 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/configstc.AdminAppConfig' - type: array - summary: CONFIG-配置 - tags: - - admin - /mag/admin/delete: - post: - consumes: - - application/json - description: 删除管理员 - parameters: - - description: 指定管理员id - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "200": - description: 操作成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 管理员管理-删除管理员 - tags: - - admin - /mag/admin/detail: - post: - consumes: - - application/json - description: 获取管理员详细信息 - parameters: - - description: 查询指定id详情 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AdminDetailResp' - type: object - "2": - description: 系统错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "8": - description: 操作失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 管理员管理-查看详请 - tags: - - admin - /mag/admin/disable: - post: - consumes: - - application/json - description: 操作启用/禁用管理员 - parameters: - - description: 状态设置请求 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SetStatusReq' - produces: - - application/json - responses: - "200": - description: 设置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 管理员管理-启用/禁用 - tags: - - admin - /mag/admin/save: - post: - consumes: - - application/json - description: 新增管理员,编辑提交管理员 - parameters: - - description: 新增/编辑信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.AddEditAdminReq' - produces: - - application/json - responses: - "0": - description: 处理成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/models.Admin' - type: object - "2": - description: 系统错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "8": - description: 操作失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 管理员管理-新增/更新 - tags: - - admin - /mag/admin/search: - post: - description: 搜索管理员列表 - parameters: - - description: 搜索参数集 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchAdminReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/models.Admin' - type: array - type: object - type: object - security: - - AdminKeyAuth: [] - summary: 管理员管理-搜索列表 - tags: - - admin - /mag/admin_log/create: - post: - consumes: - - application/json - description: 创建操作日志,可根据页面访问内容创建 - parameters: - - description: 搜索参数集 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchAdminLogReq' - produces: - - application/json - responses: - "200": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/models.AdminLog' - type: array - type: object - type: object - security: - - AdminKeyAuth: [] - summary: 日志创建 - tags: - - admin.log - /mag/admin_log/search: - post: - consumes: - - application/json - description: 返回管理员操作日志 - parameters: - - description: 搜索参数集 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchAdminLogReq' - produces: - - application/json - responses: - "200": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/models.AdminLog' - type: array - type: object - type: object - security: - - AdminKeyAuth: [] - summary: 管理员日志 - tags: - - admin.log - /mag/auth/fresh_token: - post: - description: 刷新授权token - produces: - - application/json - responses: - "200": - description: 刷新成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - "500": - description: 刷新失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: Auth-刷新授权 - tags: - - admin.auth - x-response-apikey-token-set: - apiKey: ApiKeyAuth - tokenKey: response.data.token - /mag/auth/info: - post: - description: 获取登录信息 - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - security: - - AdminKeyAuth: [] - summary: Auth-登录信息 - tags: - - admin.auth - /mag/auth/login: - post: - description: 登录 - parameters: - - description: 账户信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.AuthReq' - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: Auth-登录 - tags: - - admin.auth - x-response-apikey-token-set: - apiKey: AdminKeyAuth - tokenKey: response.data.token - /mag/auth/logout: - post: - description: 取消授权 - produces: - - application/json - responses: - "200": - description: 取消成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 取消失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: Auth-取消授权 - tags: - - admin.auth - /mag/captcha/get: - post: - description: 验证码生成图片 - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.CaptchaResponse' - type: object - "1": - description: 获取失败 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - code: - type: integer - type: object - summary: 验证码图片 - tags: - - admin.other - /mag/organize/delete: - post: - consumes: - - application/json - description: 删除指定组织 - parameters: - - description: 指定管理员id - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "200": - description: 操作成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 删除组织 - tags: - - admin.organize - /mag/organize/detail: - post: - consumes: - - application/json - description: 获取组织详细信息 - parameters: - - description: 查询指定id详情 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.OrganizeDetail' - type: object - "2": - description: 系统错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "8": - description: 操作失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 查看详请 - tags: - - admin.organize - /mag/organize/disable: - post: - consumes: - - application/json - description: 操作启用/禁用指定组织 - parameters: - - description: 状态设置请求 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SetStatusReq' - produces: - - application/json - responses: - "200": - description: 设置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 启用/禁用 - tags: - - admin.organize - /mag/organize/save: - post: - consumes: - - application/json - description: 新增组织,编辑提交组织 - parameters: - - description: 新增/编辑信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.AddEditOrganizeReq' - produces: - - application/json - responses: - "0": - description: 处理成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/models.Organize' - type: object - "2": - description: 系统错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - "8": - description: 操作失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 组织新增/更新 - tags: - - admin.organize - /mag/organize/search: - post: - description: 搜索组织列表 - parameters: - - description: 搜索参数集 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchOrganizeReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/models.Organize' - type: array - type: object - type: object - security: - - AdminKeyAuth: [] - summary: 组织列表 - tags: - - admin.organize - /mag/organize/tree: - post: - description: 搜索组织树 - parameters: - - description: 搜索参数集 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.TreeOrganizeReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/dto.SwaggerTreeNode' - type: array - type: object - type: object - security: - - AdminKeyAuth: [] - summary: 组织树 - tags: - - admin.organize - /mag/rbac/permission/delete: - post: - description: 删除权限节点 - parameters: - - description: 删除请求 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "200": - description: 返回数据 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 返回失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 权限管理-删除权限节点 - tags: - - admin.rbac - /mag/rbac/permission/save: - post: - description: 权限节点新增/更新 - parameters: - - description: 提交信息 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.AddEditPermissionReq' - produces: - - application/json - responses: - "200": - description: 操作成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.DetailResp' - type: object - "500": - description: 操作失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 权限管理-权限节点新增/更新 - tags: - - admin.rbac - /mag/rbac/permission/search: - post: - description: 返回所有可操作的权限树 - parameters: - - description: 查询参数 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.ListOptionReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/models.RbacPermission' - type: array - type: object - "1": - description: 返回数据,is_simple=true - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/dto.RbacPermissionSimple' - type: array - type: object - "2": - description: 返回树型数据,is_tree=true - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/dto.RbacPermissionSimple' - type: array - type: object - "100": - description: 获取失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 权限管理-权限树 - tags: - - admin.rbac - /mag/rbac/role/delete: - post: - consumes: - - application/json - description: 操作删除角色 - parameters: - - description: 指定role id - in: body - name: param - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "200": - description: 设置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-角色删除 - tags: - - admin.rbac - /mag/rbac/role/detail: - post: - description: 角色基本信息详情 - parameters: - - description: 指定role id - in: body - name: param - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "0": - description: 查询成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/models.RbacRole' - type: object - "4": - description: 参数错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-角色详情 - tags: - - admin.rbac - /mag/rbac/role/disable: - post: - consumes: - - application/json - description: 操作启用/禁用角色 - parameters: - - description: 状态设置请求 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SetStatusReq' - produces: - - application/json - responses: - "200": - description: 设置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-角色启用/禁用 - tags: - - admin.rbac - /mag/rbac/role/permission/save: - post: - description: 角色关联权限保存 - parameters: - - description: 保存信息 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.SaveRolePermissionReq' - produces: - - application/json - responses: - "200": - description: 操作成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - type: integer - type: array - type: object - "500": - description: 获取失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-保存角色权限 - tags: - - admin.rbac - /mag/rbac/role/permissions: - post: - description: 修改个人信息 - parameters: - - description: 指定role id - in: body - name: param - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "200": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - type: integer - type: array - type: object - "500": - description: 获取失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-角色权限列表 - tags: - - admin.rbac - /mag/rbac/role/save: - post: - description: 新增/更新角色 - parameters: - - description: 指定role id - in: body - name: param - schema: - $ref: '#/definitions/reqdata.AddEditRoleReq' - produces: - - application/json - responses: - "0": - description: 操作成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.DetailResp' - type: object - "4": - description: 参数错误 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-角色新增/更新 - tags: - - admin.rbac - /mag/rbac/role/search: - post: - description: 修改个人信息 - parameters: - - description: 查询参数,is_tree暂不支持 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.SearchRolesReq' - produces: - - application/json - responses: - "200": - description: List返回数据 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/models.RbacRole' - type: array - type: object - "500": - description: 返回失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-角色列表 - tags: - - admin.rbac - /mag/rbac/role/simples: - post: - description: 修改个人信息 - parameters: - - description: 查询参数,is_tree暂不支持 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.ListOptionReq' - produces: - - application/json - responses: - "201": - description: 返回数据,is_simple=true - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/dto.RbacRoleSimple' - type: array - type: object - "500": - description: 返回失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-角色列表(简易+全部返回) - tags: - - admin.rbac - /mag/rbac/user/role/bind: - post: - description: 修改个人信息 - parameters: - - description: 提交参数 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.SaveUserBindRoleReq' - produces: - - application/json - responses: - "200": - description: 返回数据 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/models.RbacRole' - type: array - type: object - "500": - description: 查询失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-用户绑定关联角色 - tags: - - admin.rbac - /mag/rbac/user/role/search: - post: - description: 修改个人信息 - parameters: - - description: 指定用户id - in: body - name: param - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "200": - description: 返回数据 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - type: integer - type: array - type: object - "500": - description: 查询失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 角色管理-用户关联角色列表 - tags: - - admin.rbac - /mag/u_center/accredit_info: - post: - description: 返回授权权限清单 - produces: - - application/json - responses: - "200": - description: 返回数据 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/dto.RbacPermissionSimple' - type: array - type: object - "500": - description: 查询失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 账户中心-授权信息 - tags: - - admin.rbac - /mag/u_center/info: - post: - description: 用户信息,比AuthInfo提供信息更详细 - produces: - - application/json - responses: - "0": - description: 重置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 用户信息 - tags: - - admin.center - /mag/u_center/modify_info: - post: - description: 修改个人信息 - parameters: - - description: 用户信息 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.ModifyInfoReq' - produces: - - application/json - responses: - "0": - description: 成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "2": - description: 修改失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 账户中心-修改个人信息 - tags: - - admin.center - /mag/u_center/modify_pwd: - post: - description: 修改密码 - parameters: - - description: 提价 - in: body - name: param - schema: - $ref: '#/definitions/reqdata.ModifyPasswordReq' - produces: - - application/json - responses: - "0": - description: 成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "2": - description: 修改失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 账户中心-修改密码 - tags: - - admin.center -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - AdminKeyAuth: - description: '管理站用Admin-Token, Header: Authorization' - in: header - name: Authorization - scopes: - write: Grants write access - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/adminapp/gen_docs.sh b/src/apps/adminapp/gen_docs.sh deleted file mode 100644 index 4784e09c21db8ece5d2a6fc724899be51fbce5af..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName adminservice - - - - - - - - diff --git a/src/apps/adminapp/i18n/en.go b/src/apps/adminapp/i18n/en.go deleted file mode 100644 index c32b716ec411f9201ace621ff01347ad3593dcf8..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/i18n/en.go +++ /dev/null @@ -1,23 +0,0 @@ -package i18n - -// En 英文 -const En = ` -SUCCESS="success" -ERROR="error" -PERMISSION_DENY="deny" -TRY_AGAIN="please try again" -SYSTEM_BUSY="system busy" -PARAMS_INVALID="invalid parameter" -OPERATE_FAIL="operate fail" - -Hello="Halo" -OperateFail="operate fail" -AccountExist="account has exist" -AccountDisable="account has disable" -PasswordWrong="password wrong" - -[user] -Exists="has exists" - -AccountWrong="account {{.Name}} wrong" -` diff --git a/src/apps/adminapp/i18n/zh.go b/src/apps/adminapp/i18n/zh.go deleted file mode 100644 index 8195b0de48a6be8ec14a33a1ebd01b4d12d28fa4..0000000000000000000000000000000000000000 --- a/src/apps/adminapp/i18n/zh.go +++ /dev/null @@ -1,23 +0,0 @@ -package i18n - -// Zh 中文 -const Zh = ` -SUCCESS="成功" -ERROR="错误" -PERMISSION_DENY="无权限" -TRY_AGAIN="请重试" -SYSTEM_BUSY="系统繁忙" -PARAMS_INVALID="无效参数" -OPERATE_FAIL="操作失败" - -Hello="你好" -OperateFail="操作失败" -AccountExist = "账户已存在" -AccountDisable="账户已禁用" -PasswordWrong="密码错误" - -[user] -Exists = "已存在" - -AccountWrong = "账户{{.Name}}错误" -` diff --git a/src/apps/app.go b/src/apps/app.go deleted file mode 100644 index 9660a64a6b13191a88dd3c55a42968e7486508dc..0000000000000000000000000000000000000000 --- a/src/apps/app.go +++ /dev/null @@ -1,103 +0,0 @@ -package apps - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" - "sync" -) - -type App struct { - name string - servers []interfaces.ItfApiServer - worker []interfaces.ItfWorker - - module bool -} - -func (app *App) Name() string { - return app.name -} - -func (app *App) Start() error { - var wg sync.WaitGroup - - for index, v := range app.servers { - wg.Add(1) - server := v - - //对模块支持进行处理 - if s, ok := server.(interfaces.ItfSupportModule); ok && s != nil { - //设置了module才是开启模块 - if app.module { - s.WithModule(app.module) - } - } - - logs.Out.Info("====== App[%s] START[%d/%d]", app.Name(), index+1, len(app.servers)) - go func() { - defer wg.Done() - - err := server.Start() - if err != nil { - logs.Out.Error("====== App[%s] START FAIL %s", app.Name(), err) - return - } - }() - } - wg.Wait() - - return nil -} - -func (app *App) Stop() error { - var wg sync.WaitGroup - - for _, v := range app.servers { - wg.Add(1) - server := v - go func() { - defer wg.Done() - err := server.Stop() - common.ErrPanic(err) - }() - } - wg.Wait() - return nil -} - -func (app *App) WithName(name string) *App { - app.name = name - return app -} - -// WithModule 是否以模块处理 -func (app *App) WithModule(t bool) *App { - app.module = t - return app -} - -// WithServer 指定任意Server -func (app *App) WithServer(s interfaces.ItfApiServer) *App { - app.servers = append(app.servers, s) - return app -} - -// WithApiServer 指定apiServer -func (app *App) WithApiServer(s interfaces.ItfApiServer) *App { - app.servers = append(app.servers, s) - return app -} - -// WithWorker 指定worker -func (app *App) WithWorker(s interfaces.ItfWorker) *App { - app.servers = append(app.servers, s) - return app -} - -func NewApp(di *dig.Container, name string) *App { - return &App{ - name: name, - } -} diff --git a/src/apps/basedataapp/api_server.go b/src/apps/basedataapp/api_server.go deleted file mode 100644 index 31324cbc5f8035f1e68ceb76960669baabf3207a..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/api_server.go +++ /dev/null @@ -1,94 +0,0 @@ -package basedataapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/basedataapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/apps/basedataapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - *apps.ApiServer - - di *dig.Container - conf *configstc.BaseDataAppConfig - - gin_http.SwaggerOption //swagger相关选项配置 - -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s._regRouter(s.Engine()) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - s._regRouter(engine) -} - -// regRouter 注册路由 -func (s *ApiServer) _regRouter(engine *gin.Engine) { - var g = engine.Group("/") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - s.router(g) - - return -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - - //验证码 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfBaseDataController) { - g.POST("/data/regions", ctr.Regions) - })) -} - -func NewApiServer(di *dig.Container, conf *configstc.BaseDataAppConfig, logger v1log.ILog) *ApiServer { - logger.Info("HELLO %s", conf.Name) - - common.ErrPanic(di.Provide(httpController.NewBaseDataController, dig.As(new(interfaces.ItfBaseDataController)))) - - //重置swagger的api host - docs.SwaggerInfobasedataservice.Host = conf.ApiServer.HostAddr() + conf.RoutePrefix - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: docs.SwaggerInfobasedataservice.InstanceName(), - Swagger: docs.SwaggerInfobasedataservice, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - s.ApiServer.WithName("baseData") - s.ApiServer.WithCors() - return s -} diff --git a/src/apps/basedataapp/app.go b/src/apps/basedataapp/app.go deleted file mode 100644 index 922274bdc55b4d84e59f123eb05f2b7627234082..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/app.go +++ /dev/null @@ -1,67 +0,0 @@ -// @title BaseData模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey ApiKeyAuth -// @in header -// @name Authorization -// @description Api-Token, Header: Authorization - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package basedataapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/services" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Container - ApiServer *ApiServer -} - -func (app *App) initService() { - common.ErrPanic(app.di.Provide(services.NewDistrictRegionService, dig.As(new(interfaces.ItfRegionDistrict)))) - - app.l.Info("init service success") -} - -func NewApp(di *dig.Container, conf *configstc.BaseDataAppConfig, logger v1log.ILog) *App { - app := &App{ - di: di, - l: logger, - App: apps.NewApp(di, "baseData_app"), - } - common.ErrPanic(di.Invoke(app.initService)) - common.ErrPanic(di.Provide(NewApiServer)) - common.ErrPanic(di.Invoke(func(api *ApiServer) { - app.App.WithApiServer(api) - app.ApiServer = api - })) - - return app -} diff --git a/src/apps/basedataapp/app_test.go b/src/apps/basedataapp/app_test.go deleted file mode 100644 index 2c473ec977315dc02631eea355403ddfe4a507f8..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/app_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package basedataapp - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/tests" - "go.uber.org/dig" - "testing" - "time" -) - -func TestAppStart(t *testing.T) { - di := testDi(t) - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - return app.Start() - })) - - time.Sleep(time.Hour) -} - -func testDi(t *testing.T) *dig.Container { - di := tests.NewDi(t) - - common.ErrPanic(di.Provide(func() *configstc.BaseDataAppConfig { - return &configstc.BaseDataAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DocsEnable: true, - } - })) - - return di -} diff --git a/src/apps/basedataapp/config.go b/src/apps/basedataapp/config.go deleted file mode 100644 index 7b12dd57519b0f6881504a78eb156651310c56ea..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/config.go +++ /dev/null @@ -1,16 +0,0 @@ -package basedataapp - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" -) - -// NewConfig godoc -// @Summary CONFIG-配置 -// @Description CONFIG-配置内容 -// @Tags baseData -// @Produce json -// @Success 200 {array} configstc.BaseDataAppConfig -// @Router /-baseData-config [post] -func NewConfig() *configstc.BaseDataAppConfig { - return configstc.LoadConfig(new(configstc.BaseDataAppConfig)) -} diff --git a/src/apps/basedataapp/controllers/grpc/g.go b/src/apps/basedataapp/controllers/grpc/g.go deleted file mode 100644 index 21e034e4c0fa360df99ffcad729fa166d205b87f..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/controllers/grpc/g.go +++ /dev/null @@ -1 +0,0 @@ -package grpc diff --git a/src/apps/basedataapp/controllers/http/ctr_basedata.go b/src/apps/basedataapp/controllers/http/ctr_basedata.go deleted file mode 100644 index 933ce44e3d7e52882aa7595024f7fecad0982448..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/controllers/http/ctr_basedata.go +++ /dev/null @@ -1,68 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/i18n" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "golang.org/x/text/language" -) - -type BaseDataController struct { - l v1log.ILog - regionSrv interfaces.ItfRegionDistrict - - *gin_http.I18nController -} - -func NewBaseDataController(di *dig.Container, l v1log.ILog, regionSrv interfaces.ItfRegionDistrict) *BaseDataController { - ctr := &BaseDataController{ - l: l, - regionSrv: regionSrv, - } - - //i18n - { - parser := i18n.NewParser() - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nEn), language.English.String()+".toml") - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nZh), language.Chinese.String()+".toml") - //for name, path := range conf.I18nFiles { - // parser.Load(path, name+".toml") - // l.Info("load i18n path %s: %s, %s", name, path, parser.Lang(name).ParseMsg("Hello")) - //} - parser.SetLanguage(language.Chinese) - parser.CacheLanguages() - ctr.I18nController = &gin_http.I18nController{ - Parser: i18n.NewParser(), - } - } - - return ctr -} - -// Regions godoc -// @Summary 行政区域查询 -// @Description 行政区域查询 -// @Tags baseData -// @Accept json -// @Produce json -// @Param param body reqdata.QueryRegionReq true "参数" -// @success 0 {object} respdata.ResponseData{data=[]dto.RegionItem} "返回成功" -// @Router /data/regions [post] -func (ctr *BaseDataController) Regions(ctx *gin.Context) { - var query reqdata.QueryRegionReq - ctx.ShouldBindJSON(&query) - - regions, err := ctr.regionSrv.Districts(query.Parent) - if err != nil { - ctr.Response(ctx, respdata.CError.MData(err.Error())) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(regions)) - return -} diff --git a/src/apps/basedataapp/docs/basedataservice_docs.go b/src/apps/basedataapp/docs/basedataservice_docs.go deleted file mode 100644 index aa4af366b642eb3be446e0e69e57539757e511c9..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/docs/basedataservice_docs.go +++ /dev/null @@ -1,200 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplatebasedataservice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/-baseData-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "baseData" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.BaseDataAppConfig" - } - } - } - } - } - }, - "/data/regions": { - "post": { - "description": "行政区域查询", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "baseData" - ], - "summary": "行政区域查询", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QueryRegionReq" - } - } - ], - "responses": { - "0": { - "description": "返回成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.BaseDataAppConfig": { - "type": "object", - "properties": { - "ApiServer": { - "$ref": "#/definitions/configstc.ServerConfig" - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "Name": { - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "reqdata.QueryRegionReq": { - "type": "object", - "properties": { - "parent": { - "description": "上级区域code", - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfobasedataservice holds exported Swagger Info so clients can modify it -var SwaggerInfobasedataservice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "BaseData模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "basedataservice", - SwaggerTemplate: docTemplatebasedataservice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfobasedataservice.InstanceName(), SwaggerInfobasedataservice) -} diff --git a/src/apps/basedataapp/docs/basedataservice_swagger.json b/src/apps/basedataapp/docs/basedataservice_swagger.json deleted file mode 100644 index e6bd21ffb1aa6c84b9926c6e4b7812fac78160f4..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/docs/basedataservice_swagger.json +++ /dev/null @@ -1,180 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "BaseData模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": { - "/-baseData-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "baseData" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.BaseDataAppConfig" - } - } - } - } - } - }, - "/data/regions": { - "post": { - "description": "行政区域查询", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "baseData" - ], - "summary": "行政区域查询", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QueryRegionReq" - } - } - ], - "responses": { - "0": { - "description": "返回成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.BaseDataAppConfig": { - "type": "object", - "properties": { - "ApiServer": { - "$ref": "#/definitions/configstc.ServerConfig" - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "Name": { - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "reqdata.QueryRegionReq": { - "type": "object", - "properties": { - "parent": { - "description": "上级区域code", - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/basedataapp/docs/basedataservice_swagger.yaml b/src/apps/basedataapp/docs/basedataservice_swagger.yaml deleted file mode 100644 index 20f7c933ef42058f96d4af122253136e530c9ec6..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/docs/basedataservice_swagger.yaml +++ /dev/null @@ -1,124 +0,0 @@ -basePath: / -definitions: - configstc.BaseDataAppConfig: - properties: - ApiServer: - $ref: '#/definitions/configstc.ServerConfig' - Debug: - description: debug开关 - type: boolean - LogLevel: - type: string - LogPath: - description: 日志路径 - type: string - Name: - type: string - RoutePrefix: - description: 路由前缀 - type: string - type: object - configstc.ServerConfig: - properties: - AllowOrigins: - description: 指定跨域允许访问源,空则为不限制访问 - items: - type: string - type: array - Host: - description: Host is the hostname or IP address of the service. - type: string - Port: - description: 端口 - type: integer - ServerBindAddr: - description: ListenAndServe to bind to, such as 0.0.0.0 - type: string - Timeout: - description: Timeout specifies a timeout (in milliseconds) - type: integer - type: object - reqdata.QueryRegionReq: - properties: - parent: - description: 上级区域code - type: string - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: BaseData模块API - version: "1.0" -paths: - /-baseData-config: - post: - description: CONFIG-配置内容 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/configstc.BaseDataAppConfig' - type: array - summary: CONFIG-配置 - tags: - - baseData - /data/regions: - post: - consumes: - - application/json - description: 行政区域查询 - parameters: - - description: 参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.QueryRegionReq' - produces: - - application/json - responses: - "0": - description: 返回成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: 行政区域查询 - tags: - - baseData -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - ApiKeyAuth: - description: 'Api-Token, Header: Authorization' - in: header - name: Authorization - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/basedataapp/gen_docs.sh b/src/apps/basedataapp/gen_docs.sh deleted file mode 100644 index 8fab4fe85e71899d3061a467b5c47d3a2eb877a6..0000000000000000000000000000000000000000 --- a/src/apps/basedataapp/gen_docs.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName basedataservice - - - - - - - diff --git a/src/apps/blockapp/README.md b/src/apps/blockapp/README.md deleted file mode 100644 index e6cca2c31fb9d60f5cc751c2e412e171c7b72417..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# 块服务(block-app) -提供块内容相关的服务,包括管理站管理块、门户网站获取块内容 - - - - -## 概念 -块内容指某一类型的指定内容的一块内容 - -块类型包含: -- 文字 -- 富文本 -- 图片 -- 开关 - -不同类型的块返回内容视情况返回的内容会不一样 - - - - diff --git a/src/apps/blockapp/api_server.go b/src/apps/blockapp/api_server.go deleted file mode 100644 index a7b9a1edb2c00546ab7d15919b3ec5c74cdbb01e..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/api_server.go +++ /dev/null @@ -1,107 +0,0 @@ -package blockapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/blockapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/apps/blockapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - *apps.ApiServer - - di *dig.Container - conf *configstc.BlockAppConfig - - gin_http.AuthOption //认证相关选项配置 - gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - gin_http.OperateLogOption //操作日志 - gin_http.AuthExtendInfoOption //认证扩展信息选项配置 - gin_http.AccreditOption //授权选项 -} - -func (s *ApiServer) Name() string { - return "setting_api" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - adminGroup := g.Group("", s.OptAuthHandler(), s.OptAccreditHandler()) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfBlockContentController) { - adminGroup.POST("/mag/block/search", ctr.SearchBlock) - adminGroup.POST("/mag/block/detail", ctr.QueryBlock) - adminGroup.POST("/mag/block/save", ctr.SaveBlock) - adminGroup.POST("/mag/block/disable", ctr.DisableBlock) - adminGroup.POST("/mag/block/delete", ctr.DeleteBlock) - - })) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Container, conf *configstc.BlockAppConfig, logger v1log.ILog) *ApiServer { - common.ErrPanic(di.Provide(httpController.NewBlockManageController, dig.As(new(interfaces.ItfBlockContentController))), uber_help.ErrAlreadyProvided) - - docs.SwaggerInfoblockservice.Host = conf.ApiServer.HostAddr() + conf.RoutePrefix - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: docs.SwaggerInfoblockservice.InstanceName(), - Swagger: docs.SwaggerInfoblockservice, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - s.ApiServer.WithCors() - - return s -} diff --git a/src/apps/blockapp/app.go b/src/apps/blockapp/app.go deleted file mode 100644 index 0be5dec0fbe3eef19a7e63dd6bf429a6cbc38c3a..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/app.go +++ /dev/null @@ -1,100 +0,0 @@ -// @title Block模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey AdminKeyAuth -// @in header -// @name Authorization -// @description 管理站用Admin-Token, Header: Authorization -// @scope.write Grants write access - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package blockapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/services" - "gitee.com/captials-team/ubdframe/src/infrastructure/caches" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "go.uber.org/dig" - "time" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Container - ApiServer *ApiServer -} - -func (app *App) initCaches(conf *configstc.BlockAppConfig) { - common.ErrPanic(app.di.Provide(func() caches.ItfCache { - return caches.NewMemoryStore(time.Minute * 10) - }), uber_help.ErrAlreadyProvided) - - app.l.Info("provide cache success") -} - -func (app *App) initDao(conf *configstc.BlockAppConfig) { - common.ErrPanic(app.di.Provide(func() interfaces.ItfBlockContentDao { - dao := mysqlDao.NewBlockContentDao(conf.DBConfig) - - _, err := dao.Migrate() - common.ErrPanic(err) - - app.l.Info("migrate success") - - return dao - })) - - app.l.Info("provide dao success") -} - -func (app *App) initService() { - common.ErrPanic(app.di.Provide(services.NewBlockService, dig.As(new(interfaces.ItfBlockContentService)))) - - app.l.Info("provide service success") -} - -func NewApp(di *dig.Container, conf *configstc.BlockAppConfig, logger v1log.ILog) *App { - app := &App{ - di: di, - l: logger, - App: apps.NewApp(di, "admin_app"), - } - - //db初始化 - common.ErrPanic(di.Invoke(app.initCaches)) - common.ErrPanic(di.Invoke(app.initDao)) - common.ErrPanic(di.Invoke(app.initService)) - common.ErrPanic(di.Provide(NewApiServer)) - - common.ErrPanic(di.Invoke(func(api *ApiServer) { - app.WithApiServer(api) - app.ApiServer = api - })) - - return app -} diff --git a/src/apps/blockapp/app_test.go b/src/apps/blockapp/app_test.go deleted file mode 100644 index 69d90a614f2213db6f0e5261103ff2dada2492d8..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/app_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package blockapp - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/tests" - "go.uber.org/dig" - "os" - "testing" -) - -func TestAppStart(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - return app.Start() - })) -} - -func testDi() *dig.Container { - di := dig.New() - common.ErrPanic(di.Provide(func() *dig.Container { - return di - })) - common.ErrPanic(di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, v1log.DebugLog) - })) - - common.ErrPanic(di.Provide(func() *configstc.BlockAppConfig { - return &configstc.BlockAppConfig{ - ApiServer: tests.TestingApiServer, - DBConfig: tests.TestingDBConfig, - DocsEnable: true, - } - })) - - return di -} diff --git a/src/apps/blockapp/controllers/http/ctr_block.go b/src/apps/blockapp/controllers/http/ctr_block.go deleted file mode 100644 index 156ff86d998255f117cfab31f99ee372608ad9a3..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/controllers/http/ctr_block.go +++ /dev/null @@ -1,170 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type BlockManageController struct { - l v1log.ILog - - conf *configstc.BlockAppConfig - - blockSvc interfaces.ItfBlockContentService - - gin_http.ResponseController -} - -func NewBlockManageController(di *dig.Container, l v1log.ILog, conf *configstc.BlockAppConfig, svc interfaces.ItfBlockContentService) *BlockManageController { - ctr := &BlockManageController{ - l: l, - conf: conf, - } - - ctr.blockSvc = svc - - return ctr -} - -// SearchBlock 块列表 godoc -// @Summary 获取块列表 -// @Description 获取块列表 -// @Tags block -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.SearchBlockContentParam true "参数" -// @success 0 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.BlockContent}} "获取成功" -// @success 500 {object} respdata.ResponseData{} "获取失败" -// @Router /mag/block/search [post] -func (ctr *BlockManageController) SearchBlock(ctx *gin.Context) { - var req reqdata.SearchBlockContentParam - ctx.ShouldBind(&req) - - params := &dto.SearchBlockContentParams{ - Keywords: req.Keywords, - Status: req.Status, - Code: req.Code, - Type: req.Type, - } - - list, pager, err := ctr.blockSvc.Search(params, &paginate.Pager{ - Page: req.Page, - Size: req.Size, - }) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CError) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pager, - })) -} - -// QueryBlock godoc -// @Summary 查询指定块 -// @Description 查询指定单个块内容 -// @Tags block -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.QueryBlockReq true "查询指定id详情" -// @success 0 {object} respdata.ResponseData{data=models.BlockContent} "获取成功" -// @success 2 {object} respdata.ResponseData{} "系统繁忙" -// @success 4 {object} respdata.ResponseData{} "参数无效" -// @success 10 {object} respdata.ResponseData{} "未查询到" -// @Router /mag/block/detail [post] -func (ctr *BlockManageController) QueryBlock(ctx *gin.Context) { - var req reqdata.QueryBlockReq - ctx.ShouldBind(&req) - - detail, err := ctr.blockSvc.Query(req.Id, req.Code) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(detail)) -} - -// SaveBlock godoc -// @Summary 创建或编辑块 -// @Description 创建或编辑块 -// @Tags block -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.SaveBlockReq true "提交用户信息" -// @success 0 {object} respdata.ResponseData{} "保存成功" -// @success 2 {object} respdata.ResponseData{} "系统繁忙" -// @success 4 {object} respdata.ResponseData{} "参数无效" -// @success 10 {object} respdata.ResponseData{} "未查询到" -// @Router /mag/block/save [post] -func (ctr *BlockManageController) SaveBlock(ctx *gin.Context) { - var req reqdata.SaveBlockReq - ctx.ShouldBind(&req) - _, err := ctr.blockSvc.Save(req.Id, &models.BlockContent{ - Code: req.Code, - Name: req.Name, - Type: req.Type, - Content: req.Content, - }) - if err != nil { - ctr.l.Error("save fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.Response(ctx, respdata.CSuccess) - return -} - -// DeleteBlock godoc -// @Summary 删除指定块 -// @Description 删除指定块 -// @Tags block -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.DetailReq true "指定用户id" -// @success 0 {object} respdata.ResponseData{} "成功" -// @Router /mag/block/delete [post] -func (ctr *BlockManageController) DeleteBlock(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - _, err := ctr.blockSvc.Delete(req.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess) -} - -// DisableBlock godoc -// @Summary 启用/禁用块 -// @Description 启用/禁用块 -// @Tags block -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.DetailReq true "指定用户id" -// @success 0 {object} respdata.ResponseData{} "成功" -// @Router /mag/block/disable [post] -func (ctr *BlockManageController) DisableBlock(ctx *gin.Context) { - ctr.Response(ctx, respdata.CSuccess) - return -} diff --git a/src/apps/blockapp/controllers/http/ctr_block_test.go b/src/apps/blockapp/controllers/http/ctr_block_test.go deleted file mode 100644 index 28c17d4a73c92de01693d760c11fa5991f9db464..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/controllers/http/ctr_block_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/tests" - "github.com/stretchr/testify/assert" - "go.uber.org/dig" - "testing" -) - -func TestNewSettingController(t *testing.T) { - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) -} - -func TestNewSettingController_PutSetting(t *testing.T) { - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.PutSettingReq{ - Key: "site_status", - Value: "1", - }) - ctr.PutSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_GetSetting(t *testing.T) { - TestNewSettingController_PutSetting(t) - - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.QuerySettingReq{ - Key: "site_status", - }) - ctr.GetSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_PutMultiSetting(t *testing.T) { - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.PutMultiSettingReq{ - Data: testSettings, - }) - ctr.PutMultiSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_GetMultiSetting(t *testing.T) { - TestNewSettingController_PutMultiSetting(t) - - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.QueryMultiSettingReq{ - Keys: utils.MapKeys(testSettings), - }) - ctr.GetMultiSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_GetMultiSetting_Clear(t *testing.T) { - for k, _ := range testSettings { - testSettings[k] = "" - } - TestNewSettingController_GetMultiSetting(t) -} - -var testSettings = map[string]string{ - "site_status": "1", - "site_name": "云深不知处平台", - "copyright": "copyright @2024", -} - -func testSettingController() *SettingController { - di := dig.New() - dao := mysql.NewSettingDao(tests.TestingDBConfig) - dao.Migrate() - return NewSettingController(di, logs.Out, &configstc.SettingAppConfig{}, dao) -} diff --git a/src/apps/blockapp/docs/blockservice_docs.go b/src/apps/blockapp/docs/blockservice_docs.go deleted file mode 100644 index 6dd3d7495eb70e1a1a1fc2383efe98b0536790c1..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/docs/blockservice_docs.go +++ /dev/null @@ -1,474 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplateblockservice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/mag/block/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除指定块", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "删除指定块", - "parameters": [ - { - "description": "指定用户id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/block/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "查询指定单个块内容", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "查询指定块", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QueryBlockReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.BlockContent" - } - } - } - ] - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/block/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "创建或编辑块", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "创建或编辑块", - "parameters": [ - { - "description": "提交用户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SaveBlockReq" - } - } - ], - "responses": { - "0": { - "description": "保存成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/block/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取块列表", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "获取块列表", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchBlockContentParam" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.BlockContent" - } - } - } - } - ] - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "models.BlockContent": { - "type": "object", - "properties": { - "code": { - "description": "块内容唯一标识,可重复,重复的视为多个", - "type": "string" - }, - "content": { - "description": "块展示内容,最多1000,如更长推荐存oss等", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "description": "块名称", - "type": "string" - }, - "type": { - "description": "类型,字符串形式,见下面的枚举", - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.DetailReq": { - "type": "object", - "properties": { - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - }, - "ids": { - "description": "多个数据id", - "type": "array", - "items": { - "type": "integer" - }, - "example": [ - 1, - 2 - ] - } - } - }, - "reqdata.QueryBlockReq": { - "type": "object", - "properties": { - "code": { - "description": "指定code", - "type": "string", - "example": "name" - }, - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SaveBlockReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "phone" - }, - "content": { - "type": "string", - "example": "123456789" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "type": "string", - "example": "联系方式" - }, - "type": { - "type": "string", - "example": "text" - } - } - }, - "reqdata.SearchBlockContentParam": { - "type": "object", - "properties": { - "code": { - "description": "对应块代码", - "type": "string" - }, - "keywords": { - "description": "关键字", - "type": "string" - }, - "page": { - "type": "integer", - "example": 1 - }, - "size": { - "type": "integer", - "example": 10 - }, - "status": { - "type": "integer", - "example": 0 - }, - "type": { - "description": "块类型", - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfoblockservice holds exported Swagger Info so clients can modify it -var SwaggerInfoblockservice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "Block模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "blockservice", - SwaggerTemplate: docTemplateblockservice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfoblockservice.InstanceName(), SwaggerInfoblockservice) -} diff --git a/src/apps/blockapp/docs/blockservice_swagger.json b/src/apps/blockapp/docs/blockservice_swagger.json deleted file mode 100644 index a00de7a1c231f7d2c3436e7d5222af58646e977d..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/docs/blockservice_swagger.json +++ /dev/null @@ -1,454 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "Block模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": { - "/mag/block/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除指定块", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "删除指定块", - "parameters": [ - { - "description": "指定用户id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/block/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "查询指定单个块内容", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "查询指定块", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QueryBlockReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.BlockContent" - } - } - } - ] - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/block/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "创建或编辑块", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "创建或编辑块", - "parameters": [ - { - "description": "提交用户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SaveBlockReq" - } - } - ], - "responses": { - "0": { - "description": "保存成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/block/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取块列表", - "produces": [ - "application/json" - ], - "tags": [ - "block" - ], - "summary": "获取块列表", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchBlockContentParam" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.BlockContent" - } - } - } - } - ] - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "models.BlockContent": { - "type": "object", - "properties": { - "code": { - "description": "块内容唯一标识,可重复,重复的视为多个", - "type": "string" - }, - "content": { - "description": "块展示内容,最多1000,如更长推荐存oss等", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "name": { - "description": "块名称", - "type": "string" - }, - "type": { - "description": "类型,字符串形式,见下面的枚举", - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.DetailReq": { - "type": "object", - "properties": { - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - }, - "ids": { - "description": "多个数据id", - "type": "array", - "items": { - "type": "integer" - }, - "example": [ - 1, - 2 - ] - } - } - }, - "reqdata.QueryBlockReq": { - "type": "object", - "properties": { - "code": { - "description": "指定code", - "type": "string", - "example": "name" - }, - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SaveBlockReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "phone" - }, - "content": { - "type": "string", - "example": "123456789" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "name": { - "type": "string", - "example": "联系方式" - }, - "type": { - "type": "string", - "example": "text" - } - } - }, - "reqdata.SearchBlockContentParam": { - "type": "object", - "properties": { - "code": { - "description": "对应块代码", - "type": "string" - }, - "keywords": { - "description": "关键字", - "type": "string" - }, - "page": { - "type": "integer", - "example": 1 - }, - "size": { - "type": "integer", - "example": 10 - }, - "status": { - "type": "integer", - "example": 0 - }, - "type": { - "description": "块类型", - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/blockapp/docs/blockservice_swagger.yaml b/src/apps/blockapp/docs/blockservice_swagger.yaml deleted file mode 100644 index 8159ab102fe61fd807ee1e87400e595130db2618..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/docs/blockservice_swagger.yaml +++ /dev/null @@ -1,295 +0,0 @@ -basePath: / -definitions: - models.BlockContent: - properties: - code: - description: 块内容唯一标识,可重复,重复的视为多个 - type: string - content: - description: 块展示内容,最多1000,如更长推荐存oss等 - type: string - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - id: - type: integer - name: - description: 块名称 - type: string - type: - description: 类型,字符串形式,见下面的枚举 - type: string - updated_at: - type: string - type: object - paginate.Pager: - properties: - page: - description: 当前页码 - type: integer - page_count: - description: 总页数 - type: integer - paging_id: - description: 分页用id,用于辅助分页用,可为主键id值 - type: integer - size: - description: 单页数量 - type: integer - total: - description: 总条数 - type: integer - type: object - reqdata.DetailReq: - properties: - id: - description: 数据id - example: 0 - type: integer - ids: - description: 多个数据id - example: - - 1 - - 2 - items: - type: integer - type: array - type: object - reqdata.QueryBlockReq: - properties: - code: - description: 指定code - example: name - type: string - id: - description: 数据id - example: 0 - type: integer - type: object - reqdata.SaveBlockReq: - properties: - code: - example: phone - type: string - content: - example: "123456789" - type: string - id: - description: id,>0为编辑对应,=0为新增 - example: 0 - type: integer - name: - example: 联系方式 - type: string - type: - example: text - type: string - type: object - reqdata.SearchBlockContentParam: - properties: - code: - description: 对应块代码 - type: string - keywords: - description: 关键字 - type: string - page: - example: 1 - type: integer - size: - example: 10 - type: integer - status: - example: 0 - type: integer - type: - description: 块类型 - type: string - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object - respdata.SearchListResponse: - properties: - list: - description: 列表 - paginate: - allOf: - - $ref: '#/definitions/paginate.Pager' - description: 分页信息 - type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Block模块API - version: "1.0" -paths: - /mag/block/delete: - post: - description: 删除指定块 - parameters: - - description: 指定用户id - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "0": - description: 成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 删除指定块 - tags: - - block - /mag/block/detail: - post: - description: 查询指定单个块内容 - parameters: - - description: 查询指定id详情 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.QueryBlockReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/models.BlockContent' - type: object - "2": - description: 系统繁忙 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数无效 - schema: - $ref: '#/definitions/respdata.ResponseData' - "10": - description: 未查询到 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 查询指定块 - tags: - - block - /mag/block/save: - post: - description: 创建或编辑块 - parameters: - - description: 提交用户信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SaveBlockReq' - produces: - - application/json - responses: - "0": - description: 保存成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "2": - description: 系统繁忙 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数无效 - schema: - $ref: '#/definitions/respdata.ResponseData' - "10": - description: 未查询到 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 创建或编辑块 - tags: - - block - /mag/block/search: - post: - description: 获取块列表 - parameters: - - description: 参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchBlockContentParam' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/models.BlockContent' - type: array - type: object - type: object - "500": - description: 获取失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 获取块列表 - tags: - - block -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - AdminKeyAuth: - description: '管理站用Admin-Token, Header: Authorization' - in: header - name: Authorization - scopes: - write: Grants write access - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/blockapp/gen_docs.sh b/src/apps/blockapp/gen_docs.sh deleted file mode 100644 index 5cc2e1407486a62193b1fdcce35c0ff1a420cbc2..0000000000000000000000000000000000000000 --- a/src/apps/blockapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName blockservice - - - - - - - - diff --git a/src/apps/iotapp/README.md b/src/apps/iotapp/README.md deleted file mode 100644 index 2a0f2f581b97d9a796fce8f926bf9c5c45c13a39..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/README.md +++ /dev/null @@ -1,31 +0,0 @@ - - -## TelemetryApp - -提供遥测相关的基础功能 - - - -### 支持功能 - -目前支持功能: - -- 遥测-测点数据存储 -- 遥测-测点数据查询 - - - -### Swagger-API - -API文档地址: http://127.0.0.1:40101/swagger/telemetryservice/doc.json - - - -### 使用说明 - - - - - - - diff --git a/src/apps/iotapp/api_server.go b/src/apps/iotapp/api_server.go deleted file mode 100644 index 55f90aa6d0568bc04d2241a2ff0df80030300677..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/api_server.go +++ /dev/null @@ -1,106 +0,0 @@ -package iotapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/iotapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/apps/iotapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - di *dig.Container - conf *configstc.IotAppConfig - *apps.ApiServer - - gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - - AdminAuthOption gin_http.AuthOption //auth相关选项配置 -} - -func (s *ApiServer) Name() string { - return "user_api" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - adminGroup := g.Group("", s.AdminAuthOption.OptAuthHandler()) - - //后台模块 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfTelemetryController) { - adminGroup.POST("/mag/telemetry/latest", ctr.GetLatest) //最新测点数据 - adminGroup.POST("/mag/telemetry/history", ctr.SearchHistory) //历史数据 - adminGroup.POST("/mag/telemetry/stats", ctr.SearchStats) //统计数据 - })) -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Container, conf *configstc.IotAppConfig, logger v1log.ILog) *ApiServer { - common.ErrPanic(di.Provide(httpController.NewTelemetryController, dig.As(new(interfaces.ItfTelemetryController))), uber_help.ErrAlreadyProvided) - - docs.SwaggerInfoiotserevice.Host = conf.ApiServer.HostAddr() + conf.RoutePrefix - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: docs.SwaggerInfoiotserevice.InstanceName(), - Swagger: docs.SwaggerInfoiotserevice, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - s.ApiServer.WithCors() - - //管理端auth - s.AdminAuthOption.AuthHandler = gin_http.AuthHandler(jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey)) - - return s -} diff --git a/src/apps/iotapp/app.go b/src/apps/iotapp/app.go deleted file mode 100644 index a680683909227066a27608aeca0c558088d8a173..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/app.go +++ /dev/null @@ -1,114 +0,0 @@ -// @title Iot模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey ApiKeyAuth -// @in header -// @name Authorization -// @description Api-Token, Header: Authorization - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package iotapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/services" - "gitee.com/captials-team/ubdframe/src/infrastructure/caches" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "go.uber.org/dig" - "time" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Container - ApiServer *ApiServer -} - -func (app *App) initDao() { - common.ErrPanic(app.di.Provide(func(conf *configstc.IotAppConfig) (metaDao interfaces.ItfMetricMetaDao, dataDao interfaces.ItfMetricDataDao, latestDao interfaces.ItfMetricLatestDataDao, statDao interfaces.ItfMetricStatDataDao) { - var err error - - metaDao = mysqlDao.NewMetricsDao(conf.DBConfig) - dataDao = mysqlDao.NewMetricDataDao(conf.DBConfig) - latestDao = mysqlDao.NewMetricLatestDataDao(conf.DBConfig) - statDao = mysqlDao.NewMetricStatDataDao(conf.DBConfig) - - _, err = metaDao.Migrate() - common.ErrPanic(err) - - _, err = dataDao.Migrate() - common.ErrPanic(err) - - _, err = latestDao.Migrate() - common.ErrPanic(err) - - _, err = statDao.Migrate() - common.ErrPanic(err) - - return - })) - - app.l.Info("provide dao success") -} - -func (app *App) initCaches(conf *configstc.IotAppConfig) { - common.ErrPanic(app.di.Provide(func() caches.ItfCache { - return caches.NewMemoryStore(time.Minute * 10) - }), uber_help.ErrAlreadyProvided) - - app.l.Info("provide cache success") -} - -func (app *App) initService() { - common.ErrPanic(app.di.Provide(services.NewTelemetryService, dig.As(new(interfaces.ItfTelemetryService)))) - - app.l.Info("init service success") -} - -func NewApp(di *dig.Container, conf *configstc.IotAppConfig, logger v1log.ILog) *App { - app := &App{ - di: di, - App: apps.NewApp(di, "user_app"), - l: logger, - } - - //初始化 - common.ErrPanic(di.Invoke(app.initCaches)) - common.ErrPanic(di.Invoke(app.initDao)) - common.ErrPanic(di.Invoke(app.initService)) - - //http api - if conf.ApiServer.Enable { - common.ErrPanic(di.Provide(NewApiServer)) - common.ErrPanic(di.Invoke(func(api *ApiServer) { - app.App.WithApiServer(api) - app.ApiServer = api - })) - } - - return app -} diff --git a/src/apps/iotapp/app_test.go b/src/apps/iotapp/app_test.go deleted file mode 100644 index adf784d813abd9b32e2c7d8dca8cdf7e2b928746..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/app_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package iotapp - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" - "os" - "testing" - "time" -) - -func TestAppStart(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - go func() { - time.Sleep(time.Hour) - app.Stop() - }() - - return app.Start() - })) - -} - -func testDi() *dig.Container { - di := dig.New() - common.ErrPanic(di.Provide(func() *dig.Container { - return di - })) - common.ErrPanic(di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, v1log.DebugLog) - })) - - common.ErrPanic(di.Provide(func() *configstc.IotAppConfig { - return &configstc.IotAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_ubd_frame", - TablePrefix: "test", - }, - DocsEnable: true, - } - })) - - return di -} diff --git a/src/apps/iotapp/controllers/http/ctr_metric.go b/src/apps/iotapp/controllers/http/ctr_metric.go deleted file mode 100644 index 0f8335c04e9230ebfbd9b989ededa20c2365fb80..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/controllers/http/ctr_metric.go +++ /dev/null @@ -1,119 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type TelemetryController struct { - l v1log.ILog - conf *configstc.IotAppConfig - srv interfaces.ItfTelemetryService - - gin_http.ResponseController -} - -func NewTelemetryController(di *dig.Container, l v1log.ILog, conf *configstc.IotAppConfig, srv interfaces.ItfTelemetryService) *TelemetryController { - ctr := &TelemetryController{ - l: l, - conf: conf, - srv: srv, - } - - return ctr -} - -// GetLatest godoc -// @Summary 获取测点最新数据 -// @Description 获取测点最新数据 -// @Tags user -// @Produce json -// @Param param body reqdata.MetricDataReq true "查询参数" -// @fail 1 {object} respdata.ResponseData{} "重置失败" -// @success 200 {object} respdata.ResponseData{data=models.MetricData} "重置成功" -// @Router /mag/telemetry/latest [post] -func (ctr *TelemetryController) GetLatest(ctx *gin.Context) { - var req reqdata.MetricDataReq - ctx.ShouldBind(&req) - - data, err := ctr.srv.QueryLatestData(req.MetricId) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(data)) -} - -// SearchHistory godoc -// @Summary 测点历史数据 -// @Description 测点历史数据 -// @Tags user -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.SearchMetricDataReq true "查询参数" -// @success 200 {object} respdata.SearchListResponse{data=[]models.MetricData} "绑定成功" -// @success 201 {object} models.MetricData{} "具体子项数据" -// @Router /mag/telemetry/history [post] -func (ctr *TelemetryController) SearchHistory(ctx *gin.Context) { - var req reqdata.SearchMetricDataReq - ctx.ShouldBind(&req) - - list, pa, err := ctr.srv.SearchHistoryData(&dto.SearchMetricDataDto{ - MetricId: req.MetricId, - StartTime: req.StartTime, - EndTime: req.EndTime, - }, paginate.NewPager(req.Page, req.Size)) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pa, - })) -} - -// SearchStats godoc -// @Summary 测点统计数据 -// @Description 测点统计数据 -// @Tags user -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.SearchMetricStatReq true "查询参数" -// @success 200 {object} respdata.SearchListResponse{data=[]models.MetricStatValueData} "绑定成功" -// @success 201 {object} models.MetricData{} "具体子项数据" -// @Router /mag/telemetry/stats [post] -func (ctr *TelemetryController) SearchStats(ctx *gin.Context) { - var req reqdata.SearchMetricStatReq - ctx.ShouldBind(&req) - - list, pa, err := ctr.srv.SearchStatData(&dto.SearchMetricStatDto{ - MetricId: req.MetricId, - StatType: req.StatType, - DataType: req.DataType, - StartTime: req.StartTime, - EndTime: req.EndTime, - }, paginate.NewPager(req.Page, req.Size)) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pa, - })) -} diff --git a/src/apps/iotapp/docs/iotserevice_docs.go b/src/apps/iotapp/docs/iotserevice_docs.go deleted file mode 100644 index d7087853751deee67ad9035e3a9933b8f41b0746..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/docs/iotserevice_docs.go +++ /dev/null @@ -1,393 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplateiotserevice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/mag/telemetry/history": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测点历史数据", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "测点历史数据", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchMetricDataReq" - } - } - ], - "responses": { - "200": { - "description": "绑定成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.MetricData" - } - } - } - } - ] - } - }, - "201": { - "description": "具体子项数据", - "schema": { - "$ref": "#/definitions/models.MetricData" - } - } - } - } - }, - "/mag/telemetry/latest": { - "post": { - "description": "获取测点最新数据", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "获取测点最新数据", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.MetricDataReq" - } - } - ], - "responses": { - "200": { - "description": "重置成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.MetricData" - } - } - } - ] - } - } - } - } - }, - "/mag/telemetry/stats": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测点统计数据", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "测点统计数据", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchMetricStatReq" - } - } - ], - "responses": { - "200": { - "description": "绑定成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.MetricStatValueData" - } - } - } - } - ] - } - }, - "201": { - "description": "具体子项数据", - "schema": { - "$ref": "#/definitions/models.MetricData" - } - } - } - } - } - }, - "definitions": { - "models.MetricData": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "metric_id": { - "type": "integer" - }, - "timestamp": { - "type": "integer" - }, - "updated_at": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "models.MetricStatValueData": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "metric_id": { - "type": "integer" - }, - "stat_type": { - "description": "统计类型,类似:1m,1h,1d", - "type": "string" - }, - "timestamp": { - "type": "integer" - }, - "value": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.MetricDataReq": { - "type": "object", - "properties": { - "metric_id": { - "description": "测点id", - "type": "integer" - } - } - }, - "reqdata.SearchMetricDataReq": { - "type": "object", - "properties": { - "end_time": { - "description": "结束时间,单位:毫秒", - "type": "integer" - }, - "metric_id": { - "description": "测点id", - "type": "integer" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "start_time": { - "description": "开始时间,单位:毫秒", - "type": "integer" - } - } - }, - "reqdata.SearchMetricStatReq": { - "type": "object", - "properties": { - "data_type": { - "description": "数据类型,last/avg/min/max/sum/add(增量)", - "type": "string" - }, - "end_time": { - "description": "结束时间,单位:毫秒", - "type": "integer" - }, - "metric_id": { - "description": "测点id", - "type": "integer" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "start_time": { - "description": "开始时间,单位:毫秒", - "type": "integer" - }, - "stat_type": { - "description": "统计类型,类似:1m,1h,1d", - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - } - }, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfoiotserevice holds exported Swagger Info so clients can modify it -var SwaggerInfoiotserevice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "Iot模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "iotserevice", - SwaggerTemplate: docTemplateiotserevice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfoiotserevice.InstanceName(), SwaggerInfoiotserevice) -} diff --git a/src/apps/iotapp/docs/iotserevice_swagger.json b/src/apps/iotapp/docs/iotserevice_swagger.json deleted file mode 100644 index 5b2498e0db946745f08eb1a03c18d501f4292e0f..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/docs/iotserevice_swagger.json +++ /dev/null @@ -1,373 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "Iot模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": { - "/mag/telemetry/history": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测点历史数据", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "测点历史数据", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchMetricDataReq" - } - } - ], - "responses": { - "200": { - "description": "绑定成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.MetricData" - } - } - } - } - ] - } - }, - "201": { - "description": "具体子项数据", - "schema": { - "$ref": "#/definitions/models.MetricData" - } - } - } - } - }, - "/mag/telemetry/latest": { - "post": { - "description": "获取测点最新数据", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "获取测点最新数据", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.MetricDataReq" - } - } - ], - "responses": { - "200": { - "description": "重置成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/models.MetricData" - } - } - } - ] - } - } - } - } - }, - "/mag/telemetry/stats": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "测点统计数据", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "测点统计数据", - "parameters": [ - { - "description": "查询参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchMetricStatReq" - } - } - ], - "responses": { - "200": { - "description": "绑定成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/models.MetricStatValueData" - } - } - } - } - ] - } - }, - "201": { - "description": "具体子项数据", - "schema": { - "$ref": "#/definitions/models.MetricData" - } - } - } - } - } - }, - "definitions": { - "models.MetricData": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "metric_id": { - "type": "integer" - }, - "timestamp": { - "type": "integer" - }, - "updated_at": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "models.MetricStatValueData": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "metric_id": { - "type": "integer" - }, - "stat_type": { - "description": "统计类型,类似:1m,1h,1d", - "type": "string" - }, - "timestamp": { - "type": "integer" - }, - "value": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.MetricDataReq": { - "type": "object", - "properties": { - "metric_id": { - "description": "测点id", - "type": "integer" - } - } - }, - "reqdata.SearchMetricDataReq": { - "type": "object", - "properties": { - "end_time": { - "description": "结束时间,单位:毫秒", - "type": "integer" - }, - "metric_id": { - "description": "测点id", - "type": "integer" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "start_time": { - "description": "开始时间,单位:毫秒", - "type": "integer" - } - } - }, - "reqdata.SearchMetricStatReq": { - "type": "object", - "properties": { - "data_type": { - "description": "数据类型,last/avg/min/max/sum/add(增量)", - "type": "string" - }, - "end_time": { - "description": "结束时间,单位:毫秒", - "type": "integer" - }, - "metric_id": { - "description": "测点id", - "type": "integer" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - }, - "start_time": { - "description": "开始时间,单位:毫秒", - "type": "integer" - }, - "stat_type": { - "description": "统计类型,类似:1m,1h,1d", - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - } - }, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/iotapp/docs/iotserevice_swagger.yaml b/src/apps/iotapp/docs/iotserevice_swagger.yaml deleted file mode 100644 index df56fd4e2c27e3fe44115ea9fcee406eab9845e2..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/docs/iotserevice_swagger.yaml +++ /dev/null @@ -1,242 +0,0 @@ -basePath: / -definitions: - models.MetricData: - properties: - created_at: - type: string - id: - type: integer - metric_id: - type: integer - timestamp: - type: integer - updated_at: - type: string - value: - type: string - type: object - models.MetricStatValueData: - properties: - id: - type: integer - metric_id: - type: integer - stat_type: - description: 统计类型,类似:1m,1h,1d - type: string - timestamp: - type: integer - value: - type: string - type: object - paginate.Pager: - properties: - page: - description: 当前页码 - type: integer - page_count: - description: 总页数 - type: integer - paging_id: - description: 分页用id,用于辅助分页用,可为主键id值 - type: integer - size: - description: 单页数量 - type: integer - total: - description: 总条数 - type: integer - type: object - reqdata.MetricDataReq: - properties: - metric_id: - description: 测点id - type: integer - type: object - reqdata.SearchMetricDataReq: - properties: - end_time: - description: 结束时间,单位:毫秒 - type: integer - metric_id: - description: 测点id - type: integer - page: - description: 分页-页码 - example: 1 - type: integer - size: - description: 分页-条数 - example: 20 - type: integer - start_time: - description: 开始时间,单位:毫秒 - type: integer - type: object - reqdata.SearchMetricStatReq: - properties: - data_type: - description: 数据类型,last/avg/min/max/sum/add(增量) - type: string - end_time: - description: 结束时间,单位:毫秒 - type: integer - metric_id: - description: 测点id - type: integer - page: - description: 分页-页码 - example: 1 - type: integer - size: - description: 分页-条数 - example: 20 - type: integer - start_time: - description: 开始时间,单位:毫秒 - type: integer - stat_type: - description: 统计类型,类似:1m,1h,1d - type: string - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object - respdata.SearchListResponse: - properties: - list: - description: 列表 - paginate: - allOf: - - $ref: '#/definitions/paginate.Pager' - description: 分页信息 - type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Iot模块API - version: "1.0" -paths: - /mag/telemetry/history: - post: - description: 测点历史数据 - parameters: - - description: 查询参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchMetricDataReq' - produces: - - application/json - responses: - "200": - description: 绑定成功 - schema: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - data: - items: - $ref: '#/definitions/models.MetricData' - type: array - type: object - "201": - description: 具体子项数据 - schema: - $ref: '#/definitions/models.MetricData' - security: - - ApiKeyAuth: [] - summary: 测点历史数据 - tags: - - user - /mag/telemetry/latest: - post: - description: 获取测点最新数据 - parameters: - - description: 查询参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.MetricDataReq' - produces: - - application/json - responses: - "200": - description: 重置成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/models.MetricData' - type: object - summary: 获取测点最新数据 - tags: - - user - /mag/telemetry/stats: - post: - description: 测点统计数据 - parameters: - - description: 查询参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchMetricStatReq' - produces: - - application/json - responses: - "200": - description: 绑定成功 - schema: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - data: - items: - $ref: '#/definitions/models.MetricStatValueData' - type: array - type: object - "201": - description: 具体子项数据 - schema: - $ref: '#/definitions/models.MetricData' - security: - - ApiKeyAuth: [] - summary: 测点统计数据 - tags: - - user -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - ApiKeyAuth: - description: 'Api-Token, Header: Authorization' - in: header - name: Authorization - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/iotapp/gen_docs.sh b/src/apps/iotapp/gen_docs.sh deleted file mode 100644 index f53af0154ecacd9238950baa63a2a161e63d7da3..0000000000000000000000000000000000000000 --- a/src/apps/iotapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName iotserevice - - - - - - - - diff --git a/src/apps/jobapp/README.md b/src/apps/jobapp/README.md deleted file mode 100644 index 050001563168df9d81ad2541ba15c5259a3b67b8..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/README.md +++ /dev/null @@ -1,31 +0,0 @@ - - -## JobApp - -提供运行任务相关的功能 - - - -### 支持功能 - -目前支持功能: - -- 注册指定job worker -- 运行指定job worker -- 通过api动态操作job worker(待实现) - - -### Swagger-API - -API文档地址: http://127.0.0.1:40102/swagger/jobservice/doc.json - - - -### 使用说明 - - - - - - - diff --git a/src/apps/jobapp/api_server.go b/src/apps/jobapp/api_server.go deleted file mode 100644 index dbe3b45a68247e5c2a35aa42de17a119f0ff8fee..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/api_server.go +++ /dev/null @@ -1,105 +0,0 @@ -package jobapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/jobapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/apps/jobapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - di *dig.Container - conf *configstc.JobAppConfig - *apps.ApiServer - - gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - - AdminAuthOption gin_http.AuthOption //auth相关选项配置 -} - -func (s *ApiServer) Name() string { - return "job_api" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) router(g gin.IRouter) { - - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - adminGroup := g.Group("", s.AdminAuthOption.OptAuthHandler()) - - //后台模块 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfJobController) { - adminGroup.POST("/mag/jobs/search", ctr.SearchJobs) //job搜索 - })) -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Container, conf *configstc.JobAppConfig, logger v1log.ILog) *ApiServer { - common.ErrPanic(di.Provide(httpController.NewJobController, dig.As(new(interfaces.ItfJobController))), uber_help.ErrAlreadyProvided) - - docs.SwaggerInfojobserevice.Host = conf.ApiServer.HostAddr() + conf.RoutePrefix - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: docs.SwaggerInfojobserevice.InstanceName(), - Swagger: docs.SwaggerInfojobserevice, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - s.ApiServer.WithCors() - - //管理端auth - s.AdminAuthOption.AuthHandler = gin_http.AuthHandler(jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey)) - - return s -} diff --git a/src/apps/jobapp/app.go b/src/apps/jobapp/app.go deleted file mode 100644 index 9d98a7d6bcf5920a9a5f94c35d618ce058a5bede..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/app.go +++ /dev/null @@ -1,73 +0,0 @@ -// @title Job模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey ApiKeyAuth -// @in header -// @name Authorization -// @description Api-Token, Header: Authorization - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package jobapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/pkg/jobworker" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Container - ApiServer *ApiServer - WorkerMgr *jobworker.WorkerMgr -} - -func NewApp(di *dig.Container, conf *configstc.JobAppConfig, logger v1log.ILog) *App { - app := &App{ - di: di, - App: apps.NewApp(di, "job_app"), - l: logger, - } - - //http api - if conf.ApiServer.Enable { - common.ErrPanic(di.Provide(NewApiServer)) - common.ErrPanic(di.Invoke(func(api *ApiServer) { - app.App.WithApiServer(api) - app.ApiServer = api - })) - } - common.ErrPanic(di.Provide(NewWorkerMgr)) - common.ErrPanic(di.Invoke(func(mgr *jobworker.WorkerMgr) { - app.App.WithServer(mgr) - app.WorkerMgr = mgr - })) - - return app -} - -func NewWorkerMgr(di *dig.Container, conf *configstc.JobAppConfig, logger v1log.ILog) *jobworker.WorkerMgr { - return jobworker.NewWorkerMgr(di, &conf.JobConfig, logger) -} diff --git a/src/apps/jobapp/app_test.go b/src/apps/jobapp/app_test.go deleted file mode 100644 index cdd9ab2fcd0bb2eb36c2af269498a67be715784f..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/app_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package jobapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps/jobapp/workers" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" - "os" - "testing" - "time" -) - -func TestAppStart(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - go func() { - time.Sleep(time.Hour) - app.Stop() - }() - - app.Start() - return nil - })) - - time.Sleep(time.Hour) -} - -func TestAppStart_WorkerMgrRun(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) { - app.WorkerMgr.Reg(workers.NewDemoWorker) - - app.WorkerMgr.RunOnce(10) - app.WorkerMgr.Start() - })) - - time.Sleep(time.Hour) -} - -func TestAppStart_WorkerMgr_StartAction(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) { - app.WorkerMgr.Reg(workers.NewDemoWorker) - - app.WorkerMgr.RunOnce(10) - app.WorkerMgr.StartAction(configstc.MultiActionItem{ - Actions: "demo.echo", - Count: 1, - OpInterval: 2000, - ExtendParams: map[string]string{ - "title": "this is title", - }, - }) - })) - - time.Sleep(time.Hour) -} - -func testDi() *dig.Container { - di := dig.New() - common.ErrPanic(di.Provide(func() *dig.Container { - return di - })) - common.ErrPanic(di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, v1log.DebugLog) - })) - - common.ErrPanic(di.Provide(func() *configstc.JobAppConfig { - return &configstc.JobAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_ubd_frame", - TablePrefix: "test", - }, - DocsEnable: true, - JobConfig: configstc.JobConfig{ - MultiFiles: nil, - MultiActions: []configstc.MultiActionItem{ - { - Actions: "demo", - Count: 1, - OpInterval: 5000, - ExtendParams: nil, - }, - }, - GlobalParams: nil, - }, - } - })) - - return di -} diff --git a/src/apps/jobapp/controllers/http/ctr_job.go b/src/apps/jobapp/controllers/http/ctr_job.go deleted file mode 100644 index ce92ea5b8b667d1996a8f3bc96ba6c300da7217f..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/controllers/http/ctr_job.go +++ /dev/null @@ -1,41 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type JobController struct { - l v1log.ILog - conf *configstc.JobAppConfig - mgr interfaces.ItfWorker - - gin_http.ResponseController -} - -func NewJobController(di *dig.Container, l v1log.ILog, conf *configstc.JobAppConfig, mgr interfaces.ItfWorker) *JobController { - ctr := &JobController{ - l: l, - conf: conf, - mgr: mgr, - } - - return ctr -} - -// SearchJobs godoc -// @Summary 当前job列表 -// @Description 当前job列表 -// @Tags admin -// @Produce json -// @Param param body reqdata.MetricDataReq true "查询参数" -// @fail 1 {object} respdata.ResponseData{} "重置失败" -// @success 200 {object} respdata.ResponseData{data=models.MetricData} "重置成功" -// @Router /mag/jobs/search [post] -func (ctr *JobController) SearchJobs(ctx *gin.Context) { - return -} diff --git a/src/apps/jobapp/docs/jobserevice_docs.go b/src/apps/jobapp/docs/jobserevice_docs.go deleted file mode 100644 index a22a1a02d68f67f56871f51bdcbd707ce9e7df6c..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/docs/jobserevice_docs.go +++ /dev/null @@ -1,64 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplatejobserevice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": {}, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfojobserevice holds exported Swagger Info so clients can modify it -var SwaggerInfojobserevice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "Job模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "jobserevice", - SwaggerTemplate: docTemplatejobserevice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfojobserevice.InstanceName(), SwaggerInfojobserevice) -} diff --git a/src/apps/jobapp/docs/jobserevice_swagger.json b/src/apps/jobapp/docs/jobserevice_swagger.json deleted file mode 100644 index fa72f11937b0faffc08a494fe80dccbeb5382136..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/docs/jobserevice_swagger.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "Job模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": {}, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/jobapp/docs/jobserevice_swagger.yaml b/src/apps/jobapp/docs/jobserevice_swagger.yaml deleted file mode 100644 index f6868bd172331381fbefaecdb18ef0e2fc541271..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/docs/jobserevice_swagger.yaml +++ /dev/null @@ -1,33 +0,0 @@ -basePath: / -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Job模块API - version: "1.0" -paths: {} -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - ApiKeyAuth: - description: 'Api-Token, Header: Authorization' - in: header - name: Authorization - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/jobapp/gen_docs.sh b/src/apps/jobapp/gen_docs.sh deleted file mode 100644 index 9d9921247eff61feb573e9265b2122b2fe91e92f..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName jobserevice - - - - - - - - diff --git a/src/apps/jobapp/workers/worker_demo.go b/src/apps/jobapp/workers/worker_demo.go deleted file mode 100644 index 75aed575aa83e71068d849ce8b91e7cd04cb92d9..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/workers/worker_demo.go +++ /dev/null @@ -1,149 +0,0 @@ -package workers - -import ( - "context" - "fmt" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/pkg/contexts" - "gitee.com/captials-team/ubdframe/src/pkg/jobworker" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/metrics" - "go.uber.org/dig" - "os" - "time" -) - -type DemoWorker struct { - di *dig.Container - op *jobworker.JobParam - l v1log.ILog - monitorCh chan metrics.IndicData - ctx *contexts.AdvancedContext -} - -func NewDemoWorker(di *dig.Container, op *jobworker.JobParam) jobworker.IWorker { - w := &DemoWorker{ - di: di, - op: op, - l: v1log.NewWriterLog(os.Stdout, 0), - ctx: contexts.NewCancelAdvancedContext(context.Background()), - } - if di != nil { - common.ErrPanic(di.Invoke(func(l v1log.ILog) { - w.l = l - })) - } - - return w -} - -func (w *DemoWorker) Name() string { - return w.op.Action -} - -func (w *DemoWorker) Op() *jobworker.JobParam { - return w.op -} - -func (w *DemoWorker) Actions() []string { - return []string{ - "demo", - "demo.echo", - } -} - -func (w *DemoWorker) Params() map[string]string { - return map[string]string{ - "title": "default title", - } -} - -func (w *DemoWorker) Start() { - w.TimedStart(func() (goon bool) { - title := w.op.ExtendParams.ExtendParamValue("title") - - w.l.Info(" %s running\t%s", w.op.OpId, title) - - return true - }) -} - -// TimedStart 定时执行开始 -func (w *DemoWorker) TimedStart(f func() (goon bool)) { - w.ctx.Wait.Add(1) - defer w.ctx.Wait.Done() - - if w.op == nil { - panic(fmt.Sprintf("%s op nil", w.Name())) - } - - ti := time.NewTicker(time.Second) - if w.op.Interval > 0 { - ti = time.NewTicker(w.op.Interval) - } - i := 0 - - for { - i++ - select { - case <-w.ctx.Done(): - return - case <-ti.C: - if !f() { - return - } - } - } -} - -// Run 运行指定次数 -func (w *DemoWorker) Run(count int64) { - w.l.Warn("not support run [%s] times %d", w.Op().Action, count) - - for i := 1; i <= int(count); i++ { - w.l.Info("demo run %d", i) - time.Sleep(time.Second) - } -} - -func (w *DemoWorker) Stop() { - w.ctx.Cancel(nil) - w.ctx.Wait.Wait() -} - -func (w *DemoWorker) Interval() time.Duration { //设置运行的间隔 - if w.op.Interval > 0 { - return w.op.Interval - } - return time.Second -} - -func (w *DemoWorker) GetRunInterval() time.Duration { //实际运行的间隔 - return time.Second -} - -// Tps 总tps -func (w *DemoWorker) Tps() float64 { - return 0 -} - -// Log 提供的日志 -func (w *DemoWorker) Log() v1log.ILog { - return w.l -} - -func (w *DemoWorker) Debug() { - -} - -func (w *DemoWorker) SetMonitor(ch chan metrics.IndicData) { - w.monitorCh = ch -} - -func (w *DemoWorker) monitor(data metrics.IndicData) { - if w.monitorCh != nil { - w.monitorCh <- data - } else { - w.l.Info("monitor ch is nil") - } -} diff --git a/src/apps/jobapp/workers/worker_fastuse.go b/src/apps/jobapp/workers/worker_fastuse.go deleted file mode 100644 index 4a47e1af640a9b5262683f5f9e1bfc99c1d87b01..0000000000000000000000000000000000000000 --- a/src/apps/jobapp/workers/worker_fastuse.go +++ /dev/null @@ -1,150 +0,0 @@ -package workers - -import ( - "context" - "fmt" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/pkg/contexts" - "gitee.com/captials-team/ubdframe/src/pkg/jobworker" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/metrics" - "go.uber.org/dig" - "os" - "time" -) - -// FastUseWorker 快速上手使用的worker -type FastUseWorker struct { - di *dig.Container - op *jobworker.JobParam - l v1log.ILog - monitorCh chan metrics.IndicData - ctx *contexts.AdvancedContext -} - -func NewFastUseWorker(di *dig.Container, op *jobworker.JobParam) jobworker.IWorker { - w := &FastUseWorker{ - di: di, - op: op, - l: v1log.NewWriterLog(os.Stdout, 0), - ctx: contexts.NewCancelAdvancedContext(context.Background()), - } - if di != nil { - common.ErrPanic(di.Invoke(func(l v1log.ILog) { - w.l = l - })) - } - - return w -} - -func (w *FastUseWorker) Name() string { - return w.op.Action -} - -func (w *FastUseWorker) Op() *jobworker.JobParam { - return w.op -} - -func (w *FastUseWorker) Actions() []string { - return []string{} -} - -func (w *FastUseWorker) Params() map[string]string { - return nil -} - -func (w *FastUseWorker) Start() { - w.TimedStart(func() (goon bool) { - w.l.Info(" %s running", w.op.OpId) - - return true - }) -} - -// Run 运行指定次数 -func (w *FastUseWorker) Run(count int64) { - w.l.Warn("not support run [%s] times %d", w.Op().Action, count) -} - -func (w *FastUseWorker) Stop() { - w.ctx.Cancel(nil) - w.ctx.Wait.Wait() -} - -func (w *FastUseWorker) Interval() time.Duration { //设置运行的间隔 - if w.op.Interval > 0 { - return w.op.Interval - } - return time.Second -} - -func (w *FastUseWorker) GetRunInterval() time.Duration { //实际运行的间隔 - return time.Second -} - -// Tps 总tps -func (w *FastUseWorker) Tps() float64 { - return 0 -} - -// Log 提供的日志 -func (w *FastUseWorker) Log() v1log.ILog { - return w.l -} - -func (w *FastUseWorker) Debug() { - -} - -// TimedStart 定时执行开始 -func (w *FastUseWorker) TimedStart(f func() (goon bool)) { - w.ctx.Wait.Add(1) - defer w.ctx.Wait.Done() - - if w.op == nil { - panic(fmt.Sprintf("%s op nil", w.Name())) - } - - ti := time.NewTicker(time.Second) - if w.op.Interval > 0 { - ti = time.NewTicker(w.op.Interval) - } - i := 0 - - for { - i++ - select { - case <-w.ctx.Done(): - return - case <-ti.C: - if !f() { - return - } - } - } -} - -func (w *FastUseWorker) Monitor(data metrics.IndicData) { - if w.monitorCh != nil { - w.monitorCh <- data - } else { - w.l.Info("monitor ch is nil") - } -} - -func (w *FastUseWorker) monitor(data metrics.IndicData) { - if w.monitorCh != nil { - w.monitorCh <- data - } else { - w.l.Info("monitor ch is nil") - } -} - -func (w *FastUseWorker) SetMonitor(ch chan metrics.IndicData) { - w.monitorCh = ch -} - -func (w *FastUseWorker) Ctx() *contexts.AdvancedContext { - return w.ctx -} diff --git a/src/apps/ossapp/api_server.go b/src/apps/ossapp/api_server.go deleted file mode 100644 index 02db1cc7eedfb93fc4b38ac982c2458becae02f6..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/api_server.go +++ /dev/null @@ -1,106 +0,0 @@ -package ossapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/ossapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/apps/ossapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - *apps.ApiServer - - di *dig.Container - conf *configstc.OssAppConfig - - gin_http.AuthOption //认证相关选项配置 - gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - gin_http.OperateLogOption //操作日志 - gin_http.AuthExtendInfoOption //认证扩展信息选项配置 - gin_http.AccreditOption //授权选项 -} - -func (s *ApiServer) Name() string { - return "oss_api" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - authGroup := g.Group("", s.OptAuthHandler(), s.OptAccreditHandler()) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfOssController) { - authGroup.POST("/oss/config", ctr.ConfigOss) //配置oss - })) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfOssController) { - g.POST("/oss/upload", ctr.DoUpload) //配置oss - })) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Container, conf *configstc.OssAppConfig, logger v1log.ILog) *ApiServer { - common.ErrPanic(di.Provide(httpController.NewUploadController, dig.As(new(interfaces.ItfOssController))), uber_help.ErrAlreadyProvided) - - docs.SwaggerInfoossservice.Host = conf.ApiServer.HostAddr() + conf.RoutePrefix - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: docs.SwaggerInfoossservice.InstanceName(), - Swagger: docs.SwaggerInfoossservice, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - s.ApiServer.WithCors() - - return s -} diff --git a/src/apps/ossapp/app.go b/src/apps/ossapp/app.go deleted file mode 100644 index ca499e5f48df86358ca9a7d68eb33d61a57ae0ba..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/app.go +++ /dev/null @@ -1,83 +0,0 @@ -// @title Oss模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey AdminKeyAuth -// @in header -// @name Authorization -// @description 管理站用Admin-Token, Header: Authorization -// @scope.write Grants write access - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package ossapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Container - ApiServer *ApiServer -} - -func (app *App) initDao(conf *configstc.OssAppConfig) interfaces.ItfSettingDao { - var err error - - if conf.ConfigSource == consts.ConfigFromDB { - setting := mysqlDao.NewSettingDao(conf.DBConfig) - - _, err = setting.Migrate() - common.ErrPanic(err) - - app.l.Info("migrate success") - - return setting - } - - return nil -} - -func NewApp(di *dig.Container, conf *configstc.OssAppConfig, logger v1log.ILog) *App { - app := &App{ - di: di, - l: logger, - App: apps.NewApp(di, "admin_app"), - } - - //db初始化 - common.ErrPanic(di.Provide(NewApiServer)) - common.ErrPanic(di.Provide(app.initDao)) - - common.ErrPanic(di.Invoke(func(api *ApiServer) { - app.WithApiServer(api) - app.ApiServer = api - })) - - return app -} diff --git a/src/apps/ossapp/app_test.go b/src/apps/ossapp/app_test.go deleted file mode 100644 index 4a9cbe6f0a0ecc88bd4010e69f289b4c5af49795..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/app_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package ossapp - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/ossadaptor" - "go.uber.org/dig" - "os" - "testing" -) - -func TestAppStart(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - return app.Start() - })) -} - -func testDi() *dig.Container { - di := dig.New() - common.ErrPanic(di.Provide(func() *dig.Container { - return di - })) - common.ErrPanic(di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, v1log.DebugLog) - })) - - common.ErrPanic(di.Provide(func() *configstc.OssAppConfig { - return &configstc.OssAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_ubd_frame", - TablePrefix: "test", - }, - DocsEnable: true, - ConfigSource: consts.ConfigFromFile, - UploadType: ossadaptor.UploadByAliyunOss, - UploadConfig: map[string]map[string]string{ - ossadaptor.UploadByLocal: { - "bind_domain": "", - "storage_path": "", - }, - ossadaptor.UploadByAliyunOss: { - "bind_domain": "", - "access_key": "", - "secret_key": "", - }, - ossadaptor.UploadByQiniuOss: { - "bind_domain": "", - "access_key": "", - "secret_key": "", - }, - ossadaptor.UploadByMinioOss: { - "bind_domain": "", - "access_key": "", - "secret_key": "", - "endpoint": "", - "bucket": "", - "sub_path": "", - }, - }, - } - })) - - return di -} diff --git a/src/apps/ossapp/controllers/http/ctr_upload.go b/src/apps/ossapp/controllers/http/ctr_upload.go deleted file mode 100644 index 596af3e1f060c789bfeaaa145d051a95c01c2006..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/controllers/http/ctr_upload.go +++ /dev/null @@ -1,308 +0,0 @@ -package http - -import ( - "bufio" - "encoding/json" - "fmt" - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/ossadaptor" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "gorm.io/gorm" - "io" - "mime/multipart" - "os" - "path" - "time" -) - -type UploadController struct { - l v1log.ILog - - conf *configstc.OssAppConfig - - settingDao interfaces.ItfSettingDao - - gin_http.ResponseController -} - -func NewUploadController(di *dig.Container, l v1log.ILog, conf *configstc.OssAppConfig) *UploadController { - ctr := &UploadController{ - l: l, - conf: conf, - } - - di.Invoke(func(dao interfaces.ItfSettingDao) { - ctr.settingDao = dao - }) - - return ctr -} - -// ConfigOss 上传 godoc -// @Summary OSS配置 -// @Description 上传图片/文件等 -// @Tags upload -// @Produce json -// @Param param body reqdata.OssSettingReq true "参数" -// @success 200 {object} respdata.ResponseData{} "配置成功" -// @success 500 {object} respdata.ResponseData{} "配置失败" -// @Router /oss/config [post] -func (ctr *UploadController) ConfigOss(ctx *gin.Context) { - var req reqdata.OssSettingReq - ctx.ShouldBindJSON(&req) - - upType := req.UploadType - - if _, exist := ossadaptor.SupportUploadTypes[upType]; !exist { - ctr.Response(ctx, respdata.CError.MMsg("不支持的OSS配置类型")) - return - } - upConfig := req.UploadConfig[upType] - - ctr.settingDao.DB().Transaction(func(tx *gorm.DB) error { - dao := ctr.settingDao.Use(tx) - err := dao.Set(UploadTypeKey, req.UploadType) - if err != nil { - return err - } - - upConfigStr, _ := json.Marshal(upConfig) - err = dao.Set(fmt.Sprintf(UploadConfigKey, upType), string(upConfigStr)) - if err != nil { - return err - } - return nil - }) - - ctr.Response(ctx, respdata.CSuccess) -} - -// DoUpload 上传 godoc -// @Summary 上传 -// @Description 上传图片/文件等 -// @Tags upload -// @Produce mpfd -// @Param param formData file true "上传文件" -// @success 200 {object} respdata.ResponseData{} "上传成功" -// @success 500 {object} respdata.ResponseData{} "上传失败" -// @Router /oss/upload [post] -func (ctr *UploadController) DoUpload(ctx *gin.Context) { - upType, upConfig := ctr.getUploadConfig() - ossHandler, err := ossadaptor.NewOssUploader(upType, upConfig) - if err != nil { - ctr.Response(ctx, respdata.CError.MMsg(err.Error())) - return - } - - _, files, err := ctr.ParseMultipartForm(ctx) - if err != nil { - ctr.l.Error("multipart form err: %s", err) - ctr.Response(ctx, respdata.CError.MMsg("multipart form err: "+err.Error())) - return - } - if files["file"] == nil && len(files["file"]) <= 0 { - ctr.Response(ctx, respdata.CError.MMsg("请先上传文件")) - return - } - - file := files["file"][0] - - maxSize := ctr.conf.UploadMaxSize - if file.Size > maxSize { - ctr.Response(ctx, respdata.CError.MMsg(fmt.Sprintf("文件大小不可超过 %d b", maxSize))) - return - } - //logger.Infof("fileSize:%d b", file.Size) - - //转存 - arFile, err := ctr.archivedFile(file) - if err != nil { - ctr.l.Error("upload fail: %s", err) - ctr.Response(ctx, respdata.CError.MMsg("upload fail: "+err.Error())) - return - } - - //do upload - tgName := ctr.objFileName(arFile) - ret, err := ossHandler.Put(arFile, tgName) - if err != nil { - ctr.l.Error("upload fail: %s", err) - ctr.Response(ctx, respdata.CError.MMsg("upload fail: "+err.Error())) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(map[string]interface{}{ - "url": ret.Url, - })) - return -} - -func (ctr *UploadController) ParseMultipartForm(ctx *gin.Context) (map[string][]string, map[string][]*multipart.FileHeader, error) { - r := ctx.Request - err := r.ParseMultipartForm(128) - if err != nil { - return nil, nil, err - } - - return r.MultipartForm.Value, r.MultipartForm.File, nil -} - -func (ctr *UploadController) objFileName(file string) string { - fSuffix := utils.FileExt(file) - return fmt.Sprintf("%s.%s", - utils.Md5Sum(time.Now().Format(time.DateTime)+utils.RandFigureCode(6)), - fSuffix) -} - -// 转存文件 -func (ctr *UploadController) archivedFile(file *multipart.FileHeader) (string, error) { - - f, err := file.Open() - defer func() { - f.Close() - }() - if err != nil { - return "", err - } - - //临时存放目录 - tmpDir := path.Join(ctr.conf.StoragePath, "tmp") - err = utils.EnsureDir(tmpDir) - if err != nil { - ctr.l.Error("create tmp dir err:%s", err) - return "", err - } - - // - arName := fmt.Sprintf("%d_%s.%s", - time.Now().UnixNano(), utils.RandFigureCode(4), - utils.FileExt(file.Filename)) - arPath := path.Join(tmpDir, arName) - - fAr, err := os.OpenFile(arPath, os.O_CREATE|os.O_RDWR, 0755) - if err != nil { - return "", err - } - defer func() { - fAr.Close() - }() - - buf := bufio.NewReader(f) - s := make([]byte, 4096) - eof := false - for !eof { - n, err := buf.Read(s) - if err == io.EOF { - eof = true - } else if err != nil { - return "", err - } - - if n <= 0 { - continue - } - - _, err = fAr.Write(s) - if err != nil { - return "", err - } - } - - return arPath, nil -} - -// todo 优化 -func (ctr *UploadController) readInputFile(f io.Reader, ch chan []byte) { - defer close(ch) - - buf := bufio.NewReader(f) - s := make([]byte, 4096) - eof := false - for !eof { - n, err := buf.Read(s) - if err == io.EOF { - eof = true - } else if err != nil { - return - } - - if n <= 0 { - continue - } - - ch <- s - } - return -} - -// todo 优化 -func (ctr *UploadController) writeOutFile(f io.Writer, ch chan []byte) { - for s := range ch { - _, err := f.Write(s) - if err != nil { - continue - } - } - return -} - -func (ctr *UploadController) getUploadConfig() (string, map[string]string) { - c := ctr.conf - switch c.ConfigSource { - case consts.ConfigFromFile: - return ctr.getUploadConfigFromFile() - case consts.ConfigFromDB: - return ctr.getUploadConfigFromDB() - } - - return "", nil -} - -// getUploadConfigFromFile 从配置文件取 -func (ctr *UploadController) getUploadConfigFromFile() (string, map[string]string) { - c := ctr.conf - - upType := c.UploadType - upConfig := c.UploadConfig - - if upOss, exist := upConfig[upType]; exist { - return upType, upOss - } - - return upType, map[string]string{} -} - -// getUploadConfigFromDB 从数据库取配置 -func (ctr *UploadController) getUploadConfigFromDB() (string, map[string]string) { - upConfig := map[string]string{} - upType, err := ctr.settingDao.Get(UploadTypeKey) - if err != nil { - ctr.l.Error("get upload type from db err:%s", err) - return upType, upConfig - } - - if upType == "" { - return upType, upConfig - } - // - upConfigStr, err := ctr.settingDao.Get(fmt.Sprintf(UploadConfigKey, upType)) - if err != nil { - ctr.l.Error("get upload config from db err:%s", err) - return "", upConfig - } - - json.Unmarshal([]byte(upConfigStr), &upConfig) - - return upType, upConfig -} - -const UploadTypeKey = "oss_type" -const UploadConfigKey = "oss_config_%s" diff --git a/src/apps/ossapp/docs/ossservice_docs.go b/src/apps/ossapp/docs/ossservice_docs.go deleted file mode 100644 index 5874ab64ef53e6bb3975d6d3590a43fc4c0a6b18..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/docs/ossservice_docs.go +++ /dev/null @@ -1,172 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplateossservice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/oss/config": { - "post": { - "description": "上传图片/文件等", - "produces": [ - "application/json" - ], - "tags": [ - "upload" - ], - "summary": "OSS配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.OssSettingReq" - } - } - ], - "responses": { - "200": { - "description": "配置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "配置失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/oss/upload": { - "post": { - "description": "上传图片/文件等", - "produces": [ - "multipart/form-data" - ], - "tags": [ - "upload" - ], - "summary": "上传", - "parameters": [ - { - "type": "file", - "description": "上传文件", - "name": "param", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "上传成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "上传失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "reqdata.OssSettingReq": { - "type": "object", - "properties": { - "upload_config": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "upload_type": { - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfoossservice holds exported Swagger Info so clients can modify it -var SwaggerInfoossservice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "Oss模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "ossservice", - SwaggerTemplate: docTemplateossservice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfoossservice.InstanceName(), SwaggerInfoossservice) -} diff --git a/src/apps/ossapp/docs/ossservice_swagger.json b/src/apps/ossapp/docs/ossservice_swagger.json deleted file mode 100644 index fdfe17a4e641fa3fc110b56bc1b92a518b6442ea..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/docs/ossservice_swagger.json +++ /dev/null @@ -1,152 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "Oss模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": { - "/oss/config": { - "post": { - "description": "上传图片/文件等", - "produces": [ - "application/json" - ], - "tags": [ - "upload" - ], - "summary": "OSS配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.OssSettingReq" - } - } - ], - "responses": { - "200": { - "description": "配置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "配置失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/oss/upload": { - "post": { - "description": "上传图片/文件等", - "produces": [ - "multipart/form-data" - ], - "tags": [ - "upload" - ], - "summary": "上传", - "parameters": [ - { - "type": "file", - "description": "上传文件", - "name": "param", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "上传成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "上传失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "reqdata.OssSettingReq": { - "type": "object", - "properties": { - "upload_config": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "upload_type": { - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/ossapp/docs/ossservice_swagger.yaml b/src/apps/ossapp/docs/ossservice_swagger.yaml deleted file mode 100644 index 97d1fe909f807ef3db7ee8abdb70d0d0195e1da5..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/docs/ossservice_swagger.yaml +++ /dev/null @@ -1,103 +0,0 @@ -basePath: / -definitions: - reqdata.OssSettingReq: - properties: - upload_config: - additionalProperties: - additionalProperties: - type: string - type: object - type: object - upload_type: - type: string - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Oss模块API - version: "1.0" -paths: - /oss/config: - post: - description: 上传图片/文件等 - parameters: - - description: 参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.OssSettingReq' - produces: - - application/json - responses: - "200": - description: 配置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 配置失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: OSS配置 - tags: - - upload - /oss/upload: - post: - description: 上传图片/文件等 - parameters: - - description: 上传文件 - in: formData - name: param - required: true - type: file - produces: - - multipart/form-data - responses: - "200": - description: 上传成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 上传失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: 上传 - tags: - - upload -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - AdminKeyAuth: - description: '管理站用Admin-Token, Header: Authorization' - in: header - name: Authorization - scopes: - write: Grants write access - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/ossapp/gen_docs.sh b/src/apps/ossapp/gen_docs.sh deleted file mode 100644 index 9a2d65afc3e4b76d4504ae6b5af09afa7f425d6c..0000000000000000000000000000000000000000 --- a/src/apps/ossapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName ossservice - - - - - - - - diff --git a/src/apps/rssapp/api_server.go b/src/apps/rssapp/api_server.go deleted file mode 100644 index 8f2bf2c0940fe2fae26bd83d8608306372d54558..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/api_server.go +++ /dev/null @@ -1,118 +0,0 @@ -package rssapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/apps/rssapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - *apps.ApiServer - - di *dig.Scope - conf *configstc.RssAppConfig - - gin_http.AuthOption //认证相关选项配置 - gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - gin_http.OperateLogOption //操作日志 - gin_http.AuthExtendInfoOption //认证扩展信息选项配置 - gin_http.AccreditOption //授权选项 - - AdminAuth gin_http.AuthOption //管理站认证相关选项配置 -} - -func (s *ApiServer) Name() string { - return "rss_api" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - - //用于客户端 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfRssController) { - g.POST("/rss/items", ctr.RssCacheItems) - })) - - authGroup := g.Group("", s.OptAuthHandler(), s.OptAccreditHandler()) - //管理站 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfRssManageController) { - //rss原数据 - authGroup.POST("/mag/rss/sources", ctr.RssSourceList) - authGroup.POST("/mag/rss/source/items", ctr.RssSourceItems) - })) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Scope, conf *configstc.RssAppConfig, logger v1log.ILog) *ApiServer { - - //swagger配置,取值后取指针是为了实现复用(多App) - swaggerDocs := *docs.SwaggerInforssservice - swaggerDocs.Host = conf.ApiServer.HostAddr() + utils.KeepHasPrefix(conf.RoutePrefix, "/") - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: swaggerDocs.InstanceName(), - Swagger: &swaggerDocs, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - //开启跨域设置 - s.ApiServer.WithCors() - - if conf.AuthConfig.Enable { - s.AuthOption.AuthHandler = gin_http.AuthHandler(jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey)) - } - - return s -} diff --git a/src/apps/rssapp/app.go b/src/apps/rssapp/app.go deleted file mode 100644 index 3cec70a0725668578bf569f12943712ba1bc28c7..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/app.go +++ /dev/null @@ -1,110 +0,0 @@ -package rssapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/rssapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/services" - "gitee.com/captials-team/ubdframe/src/domain/vo" - "gitee.com/captials-team/ubdframe/src/infrastructure/caches" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/rsshelp" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "github.com/robfig/cron/v3" - "go.uber.org/dig" - "time" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Scope - ApiServer *ApiServer - RssFetcher *rsshelp.RssFetcher -} - -func (app *App) initCaches(conf *configstc.RssAppConfig) { - common.ErrPanic(app.di.Provide(func() caches.ItfCache { - return caches.NewMemoryStore(time.Minute * 10) - }), uber_help.ErrAlreadyProvided) - - common.ErrPanic(app.di.Provide(func(cache caches.ItfCache) services.RssCache { - return caches.NewCacheFacade[string, *vo.RssBody](cache) - }), uber_help.ErrAlreadyProvided) - - app.l.Info("provide cache success") -} - -func (app *App) startCron(f *rsshelp.RssFetcher, conf *configstc.RssAppConfig) { - //异步初始化 - if conf.AsyncInit { - go f.Fetch() - } else { - f.Fetch() - } - - //每30分钟获取一次 - c := cron.New() - c.AddFunc("@every 30m", f.Fetch) - c.Start() -} - -func (app *App) initRss(f *rsshelp.RssFetcher, ca services.RssCache, logger v1log.ILog, conf *configstc.RssAppConfig) { - app.RssFetcher = f - - for _, v := range conf.RssConfig { - if v.Enable { - f.AddRss(v.Name, v.Rss) - } - } - - f.AddHandler(func(meta *vo.RssMeta, body *vo.RssBody) { - err := ca.SetDefault(meta.Name, body) - logger.Ctl(err != nil).Error("%s", err) - }) -} - -func (app *App) initController() { - common.ErrPanic(app.di.Provide(httpController.NewRssController, dig.As(new(interfaces.ItfRssController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewRssManagerController, dig.As(new(interfaces.ItfRssManageController))), uber_help.ErrAlreadyProvided) -} - -func NewApp(di *dig.Container, conf *configstc.RssAppConfig, logger v1log.ILog) *App { - scope := di.Scope("admin") - - common.ErrPanic(scope.Provide(func() *dig.Scope { - return scope - }), uber_help.ErrAlreadyProvided) - common.ErrPanic(scope.Provide(func() *configstc.RssAppConfig { - return conf - }), uber_help.ErrAlreadyProvided) - - app := &App{ - di: scope, - l: logger, - App: apps.NewApp(di, "rss_app"), - } - - app.WithModule(conf.ModuleMode) - - //db初始化 - common.ErrPanic(scope.Provide(rsshelp.NewRssFetcher)) - - common.ErrPanic(scope.Invoke(app.initCaches)) - common.ErrPanic(scope.Invoke(app.initRss)) - common.ErrPanic(scope.Invoke(app.initController)) - common.ErrPanic(scope.Invoke(app.startCron)) - - if conf.ApiServer.Enable { - common.ErrPanic(scope.Provide(NewApiServer)) - common.ErrPanic(scope.Invoke(func(api *ApiServer) { - app.WithApiServer(api) - app.ApiServer = api - })) - } - - return app -} diff --git a/src/apps/rssapp/app_test.go b/src/apps/rssapp/app_test.go deleted file mode 100644 index a21fcf39366338083da41404c9f8b8ffc5f4da8a..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/app_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package rssapp - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/tests" - "go.uber.org/dig" - "testing" - "time" -) - -func TestAppStart(t *testing.T) { - di := testDi(t) - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - return app.Start() - })) - - time.Sleep(time.Hour) -} - -func testDi(t *testing.T) *dig.Container { - di := tests.NewDi(t) - - common.ErrPanic(di.Provide(func() *configstc.RssAppConfig { - return &configstc.RssAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_ubd_frame", - TablePrefix: "test_", - }, - DocsEnable: true, - RssConfig: []configstc.RssMetaConfig{ - { - Enable: true, - Name: "百度焦点", - Rss: "https://news.baidu.com/n?cmd=1&class=civilnews&tn=rss&sub=0", - }, - }, - AsyncInit: false, - } - })) - - return di -} diff --git a/src/apps/rssapp/config.go b/src/apps/rssapp/config.go deleted file mode 100644 index a677e9a1474071f9fca1bf7cee9119976327854d..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/config.go +++ /dev/null @@ -1,14 +0,0 @@ -package rssapp - -import "gitee.com/captials-team/ubdframe/src/domain/configstc" - -// NewConfig godoc -// @Summary CONFIG-配置 -// @Description CONFIG-配置内容 -// @Tags admin -// @Produce json -// @Success 200 {array} configstc.AdminAppConfig -// @Router /-admin-config [post] -func NewConfig() *configstc.RssAppConfig { - return configstc.LoadConfig(new(configstc.RssAppConfig)) -} diff --git a/src/apps/rssapp/controllers/http/ctr_rss.go b/src/apps/rssapp/controllers/http/ctr_rss.go deleted file mode 100644 index c337c85b7e0f382a90773c0441c21fe8bb4b98b4..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/controllers/http/ctr_rss.go +++ /dev/null @@ -1,56 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/services" - "gitee.com/captials-team/ubdframe/src/domain/vo" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" -) - -type RssController struct { - l v1log.ILog - cache services.RssCache - conf *configstc.RssAppConfig - - gin_http.ResponseController -} - -func NewRssController(l v1log.ILog, conf *configstc.RssAppConfig, cache services.RssCache) *RssController { - ctr := &RssController{ - l: l, - cache: cache, - conf: conf, - } - - return ctr -} - -// RssCacheItems godoc -// @Summary RSS文章列表(缓存) -// @Description rss内容列表(缓存) -// @Tags rss -// @Produce json -// @success 200 {object} respdata.ResponseData{data=[]vo.RssItems} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /rss/items [post] -func (ctr *RssController) RssCacheItems(ctx *gin.Context) { - var list []*vo.RssItems - - for _, v := range ctr.conf.RssConfig { - body, err := ctr.cache.Get(v.Name) - if err != nil { - ctr.l.Error("cache get err %s,%s", err, v.Name) - ctr.Response(ctx, respdata.CError) - return - } - for _, item := range body.Channel.Items { - item.Author = v.Name //修改作者 - list = append(list, item) - } - } - - ctr.Response(ctx, respdata.CSuccess.MData(list)) -} diff --git a/src/apps/rssapp/controllers/http/ctr_rss_mag.go b/src/apps/rssapp/controllers/http/ctr_rss_mag.go deleted file mode 100644 index 4385d56e01ebcce3ae215751f680835fa84eb2a8..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/controllers/http/ctr_rss_mag.go +++ /dev/null @@ -1,74 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/vo" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/rsshelp" - "github.com/gin-gonic/gin" -) - -type RssManagerController struct { - l v1log.ILog - fetcher *rsshelp.RssFetcher - conf *configstc.RssAppConfig - - gin_http.ResponseController -} - -func NewRssManagerController(l v1log.ILog, conf *configstc.RssAppConfig, fetcher *rsshelp.RssFetcher) *RssManagerController { - ctr := &RssManagerController{ - l: l, - fetcher: fetcher, - conf: conf, - } - - return ctr -} - -// RssSourceList godoc -// @Summary RSS源列表 -// @Description rss源列表 -// @Tags rss-manager -// @Produce json -// @Security AdminKeyAuth -// @success 200 {object} respdata.ResponseData{data=configstc.RssMetaConfig} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /mag/rss/sources [post] -func (ctr *RssManagerController) RssSourceList(ctx *gin.Context) { - ctr.Response(ctx, respdata.CSuccess.MData(ctr.conf.RssConfig)) -} - -// RssSourceItems godoc -// @Summary RSS源文章列表 -// @Description rss源内容列表 -// @Tags rss-manager -// @Produce json -// @Security AdminKeyAuth -// @Param param body dto.SearchRssContentReq true "验证信息" -// @success 200 {object} respdata.ResponseData{data=vo.RssItems} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /mag/rss/source/items [post] -func (ctr *RssManagerController) RssSourceItems(ctx *gin.Context) { - var req dto.SearchRssContentReq - ctx.ShouldBindJSON(&req) - - var fetcher = ctr.fetcher - if req.Rss != "" { - //指定rss - fetcher = rsshelp.NewRssFetcher(ctr.l) - fetcher.AddRss("tmp", req.Rss) - } - - var list []*vo.RssItems - fetcher.FetchHandler(func(meta *vo.RssMeta, body *vo.RssBody) { - for _, item := range body.Channel.Items { - item.Author = meta.Name //修改作者 - list = append(list, item) - } - }) - ctr.Response(ctx, respdata.CSuccess.MData(list)) -} diff --git a/src/apps/rssapp/docs/rssservice_docs.go b/src/apps/rssapp/docs/rssservice_docs.go deleted file mode 100644 index 567d77445c3ddcdac26032a00262a69f1801006f..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/docs/rssservice_docs.go +++ /dev/null @@ -1,472 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplaterssservice = `{ - "schemes": {{ marshal .Schemes }}, - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "contact": {}, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/-admin-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.AdminAppConfig" - } - } - } - } - } - }, - "/mag/rss/source/items": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "rss源内容列表", - "produces": [ - "application/json" - ], - "tags": [ - "rss-manager" - ], - "summary": "RSS源文章列表", - "parameters": [ - { - "description": "验证信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchRssContentReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/vo.RssItems" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rss/sources": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "rss源列表", - "produces": [ - "application/json" - ], - "tags": [ - "rss-manager" - ], - "summary": "RSS源列表", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/configstc.RssMetaConfig" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/rss/items": { - "post": { - "description": "rss内容列表(缓存)", - "produces": [ - "application/json" - ], - "tags": [ - "rss" - ], - "summary": "RSS文章列表(缓存)", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/vo.RssItems" - } - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.AdminAppConfig": { - "type": "object", - "properties": { - "ApiServer": { - "$ref": "#/definitions/configstc.ServerConfig" - }, - "AuthConfig": { - "$ref": "#/definitions/configstc.AuthConfig" - }, - "AutoCreateAdmin": { - "description": "是否自动创建admin账户", - "type": "boolean" - }, - "DBConfig": { - "$ref": "#/definitions/configstc.DBConfig" - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "DocsEnable": { - "description": "是否启用文档", - "type": "boolean" - }, - "I18nFiles": { - "description": "多语言配置:key=language,value=path", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "LimitingApi": { - "description": "api限流", - "allOf": [ - { - "$ref": "#/definitions/configstc.LimitingConfig" - } - ] - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "ModuleMode": { - "description": "模块模式,作为module使用", - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "PProfEnable": { - "description": "是否启用pprof", - "type": "boolean" - }, - "PasswordSalt": { - "description": "密码salt", - "type": "string" - }, - "PermissionFile": { - "description": "权限文件json", - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - }, - "UserPasswordSalt": { - "description": "用户-密码salt", - "type": "string" - } - } - }, - "configstc.AuthConfig": { - "type": "object", - "properties": { - "AuthExpired": { - "description": "授权失效时间,单位:秒", - "type": "integer" - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "SecretKey": { - "description": "加密秘钥,如JWT", - "type": "string" - } - } - }, - "configstc.DBConfig": { - "type": "object", - "properties": { - "ConnMaxIdleTime": { - "description": "每个链接最大空闲时间", - "type": "integer", - "default": 0 - }, - "ConnMaxLifeTime": { - "description": "每个链接最大生存时间", - "type": "integer", - "default": 0 - }, - "DbConn": { - "description": "数据库类型,如mysql", - "type": "string" - }, - "DbDsn": { - "description": "数据库dsn", - "type": "string" - }, - "DbHost": { - "description": "数据库地址", - "type": "string" - }, - "DbName": { - "description": "数据库", - "type": "string" - }, - "DbPassword": { - "description": "密码", - "type": "string" - }, - "DbPort": { - "description": "端口", - "type": "string" - }, - "DbUser": { - "description": "用户名", - "type": "string" - }, - "MaxConcatLen": { - "type": "string" - }, - "MaxIdleConn": { - "description": "预留并发链接数", - "type": "integer", - "default": 0 - }, - "MaxOpenConn": { - "description": "最大支持链接", - "type": "integer", - "default": 0 - }, - "TablePrefix": { - "description": "表前缀", - "type": "string" - }, - "TimeZone": { - "description": "时区设置", - "type": "string" - } - } - }, - "configstc.LimitingConfig": { - "type": "object", - "properties": { - "MaxRate": { - "description": "允许的最大速率", - "type": "integer" - }, - "PerRate": { - "description": "每次(秒)速率", - "type": "integer" - } - } - }, - "configstc.RssMetaConfig": { - "type": "object", - "properties": { - "Enable": { - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "Rss": { - "type": "string" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "EndpointAddr": { - "description": "对外访问地址", - "type": "string" - }, - "EndpointPort": { - "description": "对外访问端口", - "type": "integer" - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "dto.SearchRssContentReq": { - "type": "object", - "properties": { - "rss": { - "description": "指定rss地址", - "type": "string", - "x-nullable": true, - "example": "" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "vo.RssItems": { - "type": "object", - "properties": { - "author": { - "description": "作者", - "type": "string" - }, - "description": { - "description": "描述信息", - "type": "string" - }, - "link": { - "description": "连接", - "type": "string" - }, - "pubDate": { - "description": "发布日期/时间", - "type": "string" - }, - "title": { - "description": "新闻标题", - "type": "string" - } - } - } - } -}` - -// SwaggerInforssservice holds exported Swagger Info so clients can modify it -var SwaggerInforssservice = &swag.Spec{ - Version: "", - Host: "", - BasePath: "", - Schemes: []string{}, - Title: "", - Description: "", - InfoInstanceName: "rssservice", - SwaggerTemplate: docTemplaterssservice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInforssservice.InstanceName(), SwaggerInforssservice) -} diff --git a/src/apps/rssapp/docs/rssservice_swagger.json b/src/apps/rssapp/docs/rssservice_swagger.json deleted file mode 100644 index 525809b5b3f80a45529152a34474db5e4f649ab6..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/docs/rssservice_swagger.json +++ /dev/null @@ -1,443 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "contact": {} - }, - "paths": { - "/-admin-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.AdminAppConfig" - } - } - } - } - } - }, - "/mag/rss/source/items": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "rss源内容列表", - "produces": [ - "application/json" - ], - "tags": [ - "rss-manager" - ], - "summary": "RSS源文章列表", - "parameters": [ - { - "description": "验证信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SearchRssContentReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/vo.RssItems" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/rss/sources": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "rss源列表", - "produces": [ - "application/json" - ], - "tags": [ - "rss-manager" - ], - "summary": "RSS源列表", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/configstc.RssMetaConfig" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/rss/items": { - "post": { - "description": "rss内容列表(缓存)", - "produces": [ - "application/json" - ], - "tags": [ - "rss" - ], - "summary": "RSS文章列表(缓存)", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/definitions/vo.RssItems" - } - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.AdminAppConfig": { - "type": "object", - "properties": { - "ApiServer": { - "$ref": "#/definitions/configstc.ServerConfig" - }, - "AuthConfig": { - "$ref": "#/definitions/configstc.AuthConfig" - }, - "AutoCreateAdmin": { - "description": "是否自动创建admin账户", - "type": "boolean" - }, - "DBConfig": { - "$ref": "#/definitions/configstc.DBConfig" - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "DocsEnable": { - "description": "是否启用文档", - "type": "boolean" - }, - "I18nFiles": { - "description": "多语言配置:key=language,value=path", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "LimitingApi": { - "description": "api限流", - "allOf": [ - { - "$ref": "#/definitions/configstc.LimitingConfig" - } - ] - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "ModuleMode": { - "description": "模块模式,作为module使用", - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "PProfEnable": { - "description": "是否启用pprof", - "type": "boolean" - }, - "PasswordSalt": { - "description": "密码salt", - "type": "string" - }, - "PermissionFile": { - "description": "权限文件json", - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - }, - "UserPasswordSalt": { - "description": "用户-密码salt", - "type": "string" - } - } - }, - "configstc.AuthConfig": { - "type": "object", - "properties": { - "AuthExpired": { - "description": "授权失效时间,单位:秒", - "type": "integer" - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "SecretKey": { - "description": "加密秘钥,如JWT", - "type": "string" - } - } - }, - "configstc.DBConfig": { - "type": "object", - "properties": { - "ConnMaxIdleTime": { - "description": "每个链接最大空闲时间", - "type": "integer", - "default": 0 - }, - "ConnMaxLifeTime": { - "description": "每个链接最大生存时间", - "type": "integer", - "default": 0 - }, - "DbConn": { - "description": "数据库类型,如mysql", - "type": "string" - }, - "DbDsn": { - "description": "数据库dsn", - "type": "string" - }, - "DbHost": { - "description": "数据库地址", - "type": "string" - }, - "DbName": { - "description": "数据库", - "type": "string" - }, - "DbPassword": { - "description": "密码", - "type": "string" - }, - "DbPort": { - "description": "端口", - "type": "string" - }, - "DbUser": { - "description": "用户名", - "type": "string" - }, - "MaxConcatLen": { - "type": "string" - }, - "MaxIdleConn": { - "description": "预留并发链接数", - "type": "integer", - "default": 0 - }, - "MaxOpenConn": { - "description": "最大支持链接", - "type": "integer", - "default": 0 - }, - "TablePrefix": { - "description": "表前缀", - "type": "string" - }, - "TimeZone": { - "description": "时区设置", - "type": "string" - } - } - }, - "configstc.LimitingConfig": { - "type": "object", - "properties": { - "MaxRate": { - "description": "允许的最大速率", - "type": "integer" - }, - "PerRate": { - "description": "每次(秒)速率", - "type": "integer" - } - } - }, - "configstc.RssMetaConfig": { - "type": "object", - "properties": { - "Enable": { - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "Rss": { - "type": "string" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "EndpointAddr": { - "description": "对外访问地址", - "type": "string" - }, - "EndpointPort": { - "description": "对外访问端口", - "type": "integer" - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "dto.SearchRssContentReq": { - "type": "object", - "properties": { - "rss": { - "description": "指定rss地址", - "type": "string", - "x-nullable": true, - "example": "" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "vo.RssItems": { - "type": "object", - "properties": { - "author": { - "description": "作者", - "type": "string" - }, - "description": { - "description": "描述信息", - "type": "string" - }, - "link": { - "description": "连接", - "type": "string" - }, - "pubDate": { - "description": "发布日期/时间", - "type": "string" - }, - "title": { - "description": "新闻标题", - "type": "string" - } - } - } - } -} \ No newline at end of file diff --git a/src/apps/rssapp/docs/rssservice_swagger.yaml b/src/apps/rssapp/docs/rssservice_swagger.yaml deleted file mode 100644 index 0f68e0eb09caecbf619d7ed339390b840e26bd79..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/docs/rssservice_swagger.yaml +++ /dev/null @@ -1,293 +0,0 @@ -definitions: - configstc.AdminAppConfig: - properties: - ApiServer: - $ref: '#/definitions/configstc.ServerConfig' - AuthConfig: - $ref: '#/definitions/configstc.AuthConfig' - AutoCreateAdmin: - description: 是否自动创建admin账户 - type: boolean - DBConfig: - $ref: '#/definitions/configstc.DBConfig' - Debug: - description: debug开关 - type: boolean - DocsEnable: - description: 是否启用文档 - type: boolean - I18nFiles: - additionalProperties: - type: string - description: 多语言配置:key=language,value=path - type: object - LimitingApi: - allOf: - - $ref: '#/definitions/configstc.LimitingConfig' - description: api限流 - LogLevel: - type: string - LogPath: - description: 日志路径 - type: string - ModuleMode: - description: 模块模式,作为module使用 - type: boolean - Name: - type: string - PProfEnable: - description: 是否启用pprof - type: boolean - PasswordSalt: - description: 密码salt - type: string - PermissionFile: - description: 权限文件json - type: string - RoutePrefix: - description: 路由前缀 - type: string - UserPasswordSalt: - description: 用户-密码salt - type: string - type: object - configstc.AuthConfig: - properties: - AuthExpired: - description: 授权失效时间,单位:秒 - type: integer - Enable: - description: 是否启用 - type: boolean - SecretKey: - description: 加密秘钥,如JWT - type: string - type: object - configstc.DBConfig: - properties: - ConnMaxIdleTime: - default: 0 - description: 每个链接最大空闲时间 - type: integer - ConnMaxLifeTime: - default: 0 - description: 每个链接最大生存时间 - type: integer - DbConn: - description: 数据库类型,如mysql - type: string - DbDsn: - description: 数据库dsn - type: string - DbHost: - description: 数据库地址 - type: string - DbName: - description: 数据库 - type: string - DbPassword: - description: 密码 - type: string - DbPort: - description: 端口 - type: string - DbUser: - description: 用户名 - type: string - MaxConcatLen: - type: string - MaxIdleConn: - default: 0 - description: 预留并发链接数 - type: integer - MaxOpenConn: - default: 0 - description: 最大支持链接 - type: integer - TablePrefix: - description: 表前缀 - type: string - TimeZone: - description: 时区设置 - type: string - type: object - configstc.LimitingConfig: - properties: - MaxRate: - description: 允许的最大速率 - type: integer - PerRate: - description: 每次(秒)速率 - type: integer - type: object - configstc.RssMetaConfig: - properties: - Enable: - type: boolean - Name: - type: string - Rss: - type: string - type: object - configstc.ServerConfig: - properties: - AllowOrigins: - description: 指定跨域允许访问源,空则为不限制访问 - items: - type: string - type: array - Enable: - description: 是否启用 - type: boolean - EndpointAddr: - description: 对外访问地址 - type: string - EndpointPort: - description: 对外访问端口 - type: integer - Host: - description: Host is the hostname or IP address of the service. - type: string - Port: - description: 端口 - type: integer - ServerBindAddr: - description: ListenAndServe to bind to, such as 0.0.0.0 - type: string - Timeout: - description: Timeout specifies a timeout (in milliseconds) - type: integer - type: object - dto.SearchRssContentReq: - properties: - rss: - description: 指定rss地址 - example: "" - type: string - x-nullable: true - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object - vo.RssItems: - properties: - author: - description: 作者 - type: string - description: - description: 描述信息 - type: string - link: - description: 连接 - type: string - pubDate: - description: 发布日期/时间 - type: string - title: - description: 新闻标题 - type: string - type: object -info: - contact: {} -paths: - /-admin-config: - post: - description: CONFIG-配置内容 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/configstc.AdminAppConfig' - type: array - summary: CONFIG-配置 - tags: - - admin - /mag/rss/source/items: - post: - description: rss源内容列表 - parameters: - - description: 验证信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/dto.SearchRssContentReq' - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/vo.RssItems' - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: RSS源文章列表 - tags: - - rss-manager - /mag/rss/sources: - post: - description: rss源列表 - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/configstc.RssMetaConfig' - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: RSS源列表 - tags: - - rss-manager - /rss/items: - post: - description: rss内容列表(缓存) - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - items: - $ref: '#/definitions/vo.RssItems' - type: array - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: RSS文章列表(缓存) - tags: - - rss -swagger: "2.0" diff --git a/src/apps/rssapp/gen_docs.sh b/src/apps/rssapp/gen_docs.sh deleted file mode 100644 index 86921a93520db8625e33463c9009af159e884d12..0000000000000000000000000000000000000000 --- a/src/apps/rssapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName rssservice - - - - - - - - diff --git a/src/apps/settingapp/api_server.go b/src/apps/settingapp/api_server.go deleted file mode 100644 index 588fa46061998c80ada1dec82b21ab73c8d58d77..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/api_server.go +++ /dev/null @@ -1,112 +0,0 @@ -package settingapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/settingapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/apps/settingapp/docs" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - *apps.ApiServer - - di *dig.Container - conf *configstc.SettingAppConfig - - gin_http.AuthOption //认证相关选项配置 - gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - gin_http.OperateLogOption //操作日志 - gin_http.AuthExtendInfoOption //认证扩展信息选项配置 - gin_http.AccreditOption //授权选项 -} - -func (s *ApiServer) Name() string { - return "setting_api" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - authGroup := g.Group("", s.OptAuthHandler(), s.OptAccreditHandler()) - - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfSettingController) { - authGroup.POST("/setting/get", ctr.GetSetting) //获取单个配置 - authGroup.POST("/setting/put", ctr.PutSetting) //保存单个配置 - - authGroup.POST("/setting/multi/get", ctr.GetMultiSetting) //获取多个配置 - authGroup.POST("/setting/multi/put", ctr.PutMultiSetting) //保存多个配置 - })) - - //对外的获取配置 - common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfSettingController) { - //g.POST( "/setting/get", ctr.GetSetting) - //g.POST( "/setting/multi/get", ctr.GetMultiSetting) - })) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Container, conf *configstc.SettingAppConfig, logger v1log.ILog) *ApiServer { - common.ErrPanic(di.Provide(httpController.NewSettingController, dig.As(new(interfaces.ItfSettingController))), uber_help.ErrAlreadyProvided) - - docs.SwaggerInfosettingservice.Host = conf.ApiServer.HostAddr() + conf.RoutePrefix - - s := &ApiServer{ - di: di, - conf: conf, - SwaggerOption: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: docs.SwaggerInfosettingservice.InstanceName(), - Swagger: docs.SwaggerInfosettingservice, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - s.ApiServer.WithCors() - - return s -} diff --git a/src/apps/settingapp/app.go b/src/apps/settingapp/app.go deleted file mode 100644 index 37e8f9674f1cff8b9479efda73f535401cb9b686..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/app.go +++ /dev/null @@ -1,102 +0,0 @@ -// @title Setting模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey AdminKeyAuth -// @in header -// @name Authorization -// @description 管理站用Admin-Token, Header: Authorization -// @scope.write Grants write access - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package settingapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/services" - "gitee.com/captials-team/ubdframe/src/infrastructure/caches" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "go.uber.org/dig" - "time" -) - -type App struct { - *apps.App - - l v1log.ILog - di *dig.Container - ApiServer *ApiServer -} - -func (app *App) initCaches(conf *configstc.SettingAppConfig) { - common.ErrPanic(app.di.Provide(func() caches.ItfCache { - return caches.NewMemoryStore(time.Minute * 10) - }), uber_help.ErrAlreadyProvided) - - app.l.Info("provide cache success") -} - -func (app *App) initDao(conf *configstc.SettingAppConfig) { - common.ErrPanic(app.di.Provide(func() interfaces.ItfSettingDao { - settingDao := mysqlDao.NewSettingDao(conf.DBConfig) - - _, err := settingDao.Migrate() - common.ErrPanic(err) - - app.l.Info("migrate success") - - return settingDao - })) - - app.l.Info("provide dao success") -} - -func (app *App) initService() { - common.ErrPanic(app.di.Provide(services.NewSettingService, dig.As(new(interfaces.ItfSettingService)))) - - app.l.Info("provide service success") -} - -func NewApp(di *dig.Container, conf *configstc.SettingAppConfig, logger v1log.ILog) *App { - app := &App{ - di: di, - l: logger, - App: apps.NewApp(di, "admin_app"), - } - - //初始化 - common.ErrPanic(di.Invoke(app.initCaches)) - common.ErrPanic(di.Invoke(app.initDao)) - common.ErrPanic(di.Invoke(app.initService)) - - if conf.ApiServer.Enable { - common.ErrPanic(di.Provide(NewApiServer)) - common.ErrPanic(di.Invoke(func(api *ApiServer) { - app.WithApiServer(api) - app.ApiServer = api - })) - } - - return app -} diff --git a/src/apps/settingapp/app_test.go b/src/apps/settingapp/app_test.go deleted file mode 100644 index ddea439fae3c25e12bef3cc098fd64fc8d997727..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/app_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package settingapp - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/tests" - "go.uber.org/dig" - "os" - "testing" -) - -func TestAppStart(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - return app.Start() - })) -} - -func testDi() *dig.Container { - di := dig.New() - common.ErrPanic(di.Provide(func() *dig.Container { - return di - })) - common.ErrPanic(di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, v1log.DebugLog) - })) - - common.ErrPanic(di.Provide(func() *configstc.SettingAppConfig { - return &configstc.SettingAppConfig{ - ApiServer: tests.TestingApiServer, - DBConfig: tests.TestingDBConfig, - DocsEnable: true, - } - })) - - return di -} diff --git a/src/apps/settingapp/controllers/http/ctr_setting.go b/src/apps/settingapp/controllers/http/ctr_setting.go deleted file mode 100644 index 86c26f833d5a84fd56dab0f5a87268d120169107..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/controllers/http/ctr_setting.go +++ /dev/null @@ -1,135 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type SettingController struct { - l v1log.ILog - - conf *configstc.SettingAppConfig - - settingSvc interfaces.ItfSettingService - - gin_http.ResponseController -} - -func NewSettingController(di *dig.Container, l v1log.ILog, conf *configstc.SettingAppConfig, svc interfaces.ItfSettingService) *SettingController { - ctr := &SettingController{ - l: l, - conf: conf, - } - - ctr.settingSvc = svc - - return ctr -} - -// GetSetting 获取配置 godoc -// @Summary 获取单个配置 -// @Description 获取单个配置 -// @Tags setting -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.QuerySettingReq true "参数" -// @success 200 {object} respdata.ResponseData{data=respdata.QuerySettingResp} "获取成功" -// @success 500 {object} respdata.ResponseData{} "获取失败" -// @Router /setting/get [post] -func (ctr *SettingController) GetSetting(ctx *gin.Context) { - var req reqdata.QuerySettingReq - ctx.ShouldBindJSON(&req) - if req.Key == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - value, err := ctr.settingSvc.Get(req.Key) - if err != nil { - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.QuerySettingResp{req.Key: value})) - return -} - -// PutSetting 提交配置 godoc -// @Summary 提交单个配置 -// @Description 提交单个配置 -// @Tags setting -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.PutSettingReq true "参数" -// @success 200 {object} respdata.ResponseData{} "配置成功" -// @success 500 {object} respdata.ResponseData{} "配置失败" -// @Router /setting/put [post] -func (ctr *SettingController) PutSetting(ctx *gin.Context) { - var req reqdata.PutSettingReq - ctx.ShouldBindJSON(&req) - - err := ctr.settingSvc.Set(req.Key, req.Value) - if err != nil { - ctr.l.Error("setting save %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.Response(ctx, respdata.CSuccess) -} - -// GetMultiSetting 获取配置 godoc -// @Summary 批量获取配置 -// @Description 批量获取多个配置 -// @Tags setting-multi -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.QueryMultiSettingReq true "参数" -// @success 200 {object} respdata.ResponseData{data=respdata.QuerySettingResp} "获取成功" -// @success 500 {object} respdata.ResponseData{} "获取失败" -// @Router /setting/multi/get [post] -func (ctr *SettingController) GetMultiSetting(ctx *gin.Context) { - var req reqdata.QueryMultiSettingReq - ctx.ShouldBindJSON(&req) - if len(req.Keys) == 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - data, err := ctr.settingSvc.GetMulti(req.Keys...) - if err != nil { - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.QuerySettingResp(data))) - return -} - -// PutMultiSetting 提交配置 godoc -// @Summary 批量提交配置 -// @Description 批量提交多个配置 -// @Tags setting-multi -// @Produce json -// @Security AdminKeyAuth -// @Param param body reqdata.PutMultiSettingReq true "参数" -// @success 200 {object} respdata.ResponseData{} "配置成功" -// @success 500 {object} respdata.ResponseData{} "配置失败" -// @Router /setting/multi/put [post] -func (ctr *SettingController) PutMultiSetting(ctx *gin.Context) { - var req reqdata.PutMultiSettingReq - ctx.ShouldBindJSON(&req) - - err := ctr.settingSvc.SetMulti(req.Data) - if err != nil { - ctr.l.Error("setting save %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.Response(ctx, respdata.CSuccess) -} diff --git a/src/apps/settingapp/controllers/http/ctr_setting_test.go b/src/apps/settingapp/controllers/http/ctr_setting_test.go deleted file mode 100644 index 28c17d4a73c92de01693d760c11fa5991f9db464..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/controllers/http/ctr_setting_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/tests" - "github.com/stretchr/testify/assert" - "go.uber.org/dig" - "testing" -) - -func TestNewSettingController(t *testing.T) { - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) -} - -func TestNewSettingController_PutSetting(t *testing.T) { - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.PutSettingReq{ - Key: "site_status", - Value: "1", - }) - ctr.PutSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_GetSetting(t *testing.T) { - TestNewSettingController_PutSetting(t) - - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.QuerySettingReq{ - Key: "site_status", - }) - ctr.GetSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_PutMultiSetting(t *testing.T) { - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.PutMultiSettingReq{ - Data: testSettings, - }) - ctr.PutMultiSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_GetMultiSetting(t *testing.T) { - TestNewSettingController_PutMultiSetting(t) - - ctr := testSettingController() - assert.NotEqual(t, nil, ctr) - - ctx, resp := gin_http.NewTestContext() - - //ctx.Request.Body = - utils.SetRequestBodyJson(ctx.Request, reqdata.QueryMultiSettingReq{ - Keys: utils.MapKeys(testSettings), - }) - ctr.GetMultiSetting(ctx) - - data, err := respdata.ReaderToResponseData(resp.Body) - common.ErrPanic(err) - - assert.Equal(t, data.Code, int64(0)) - t.Logf("MSG= %+v", data.Msg) - t.Logf("DATA= %+v", data.Data) -} - -func TestNewSettingController_GetMultiSetting_Clear(t *testing.T) { - for k, _ := range testSettings { - testSettings[k] = "" - } - TestNewSettingController_GetMultiSetting(t) -} - -var testSettings = map[string]string{ - "site_status": "1", - "site_name": "云深不知处平台", - "copyright": "copyright @2024", -} - -func testSettingController() *SettingController { - di := dig.New() - dao := mysql.NewSettingDao(tests.TestingDBConfig) - dao.Migrate() - return NewSettingController(di, logs.Out, &configstc.SettingAppConfig{}, dao) -} diff --git a/src/apps/settingapp/docs/settingservice_docs.go b/src/apps/settingapp/docs/settingservice_docs.go deleted file mode 100644 index 6934c95c737eb503ba977a63e20cd09a9af4a9a8..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/docs/settingservice_docs.go +++ /dev/null @@ -1,329 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplatesettingservice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/setting/get": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取单个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting" - ], - "summary": "获取单个配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QuerySettingReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.QuerySettingResp" - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/setting/multi/get": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "批量获取多个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting-multi" - ], - "summary": "批量获取配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QueryMultiSettingReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.QuerySettingResp" - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/setting/multi/put": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "批量提交多个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting-multi" - ], - "summary": "批量提交配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PutMultiSettingReq" - } - } - ], - "responses": { - "200": { - "description": "配置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "配置失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/setting/put": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "提交单个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting" - ], - "summary": "提交单个配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PutSettingReq" - } - } - ], - "responses": { - "200": { - "description": "配置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "配置失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "reqdata.PutMultiSettingReq": { - "type": "object", - "properties": { - "data": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - }, - "reqdata.PutSettingReq": { - "type": "object", - "properties": { - "key": { - "type": "string", - "example": "site_title" - }, - "value": { - "type": "string", - "example": "linux" - } - } - }, - "reqdata.QueryMultiSettingReq": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "site_title", - "site_status" - ] - } - } - }, - "reqdata.QuerySettingReq": { - "type": "object", - "properties": { - "key": { - "type": "string", - "example": "site_title" - } - } - }, - "respdata.QuerySettingResp": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfosettingservice holds exported Swagger Info so clients can modify it -var SwaggerInfosettingservice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "Setting模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "settingservice", - SwaggerTemplate: docTemplatesettingservice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfosettingservice.InstanceName(), SwaggerInfosettingservice) -} diff --git a/src/apps/settingapp/docs/settingservice_swagger.json b/src/apps/settingapp/docs/settingservice_swagger.json deleted file mode 100644 index 45b704dd6cc7f0c8a5bf2c61b940dcf780375711..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/docs/settingservice_swagger.json +++ /dev/null @@ -1,309 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "Setting模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": { - "/setting/get": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "获取单个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting" - ], - "summary": "获取单个配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QuerySettingReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.QuerySettingResp" - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/setting/multi/get": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "批量获取多个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting-multi" - ], - "summary": "批量获取配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.QueryMultiSettingReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.QuerySettingResp" - } - } - } - ] - } - }, - "500": { - "description": "获取失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/setting/multi/put": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "批量提交多个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting-multi" - ], - "summary": "批量提交配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PutMultiSettingReq" - } - } - ], - "responses": { - "200": { - "description": "配置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "配置失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/setting/put": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "提交单个配置", - "produces": [ - "application/json" - ], - "tags": [ - "setting" - ], - "summary": "提交单个配置", - "parameters": [ - { - "description": "参数", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PutSettingReq" - } - } - ], - "responses": { - "200": { - "description": "配置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "配置失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "reqdata.PutMultiSettingReq": { - "type": "object", - "properties": { - "data": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - }, - "reqdata.PutSettingReq": { - "type": "object", - "properties": { - "key": { - "type": "string", - "example": "site_title" - }, - "value": { - "type": "string", - "example": "linux" - } - } - }, - "reqdata.QueryMultiSettingReq": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "site_title", - "site_status" - ] - } - } - }, - "reqdata.QuerySettingReq": { - "type": "object", - "properties": { - "key": { - "type": "string", - "example": "site_title" - } - } - }, - "respdata.QuerySettingResp": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "AdminKeyAuth": { - "description": "管理站用Admin-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header", - "scopes": { - "write": "Grants write access" - } - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/settingapp/docs/settingservice_swagger.yaml b/src/apps/settingapp/docs/settingservice_swagger.yaml deleted file mode 100644 index 3d71c473fac0e02d913fb203d1709003bf6f146b..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/docs/settingservice_swagger.yaml +++ /dev/null @@ -1,195 +0,0 @@ -basePath: / -definitions: - reqdata.PutMultiSettingReq: - properties: - data: - additionalProperties: - type: string - type: object - type: object - reqdata.PutSettingReq: - properties: - key: - example: site_title - type: string - value: - example: linux - type: string - type: object - reqdata.QueryMultiSettingReq: - properties: - keys: - example: - - site_title - - site_status - items: - type: string - type: array - type: object - reqdata.QuerySettingReq: - properties: - key: - example: site_title - type: string - type: object - respdata.QuerySettingResp: - additionalProperties: - type: string - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Setting模块API - version: "1.0" -paths: - /setting/get: - post: - description: 获取单个配置 - parameters: - - description: 参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.QuerySettingReq' - produces: - - application/json - responses: - "200": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.QuerySettingResp' - type: object - "500": - description: 获取失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 获取单个配置 - tags: - - setting - /setting/multi/get: - post: - description: 批量获取多个配置 - parameters: - - description: 参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.QueryMultiSettingReq' - produces: - - application/json - responses: - "200": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.QuerySettingResp' - type: object - "500": - description: 获取失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 批量获取配置 - tags: - - setting-multi - /setting/multi/put: - post: - description: 批量提交多个配置 - parameters: - - description: 参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.PutMultiSettingReq' - produces: - - application/json - responses: - "200": - description: 配置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 配置失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 批量提交配置 - tags: - - setting-multi - /setting/put: - post: - description: 提交单个配置 - parameters: - - description: 参数 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.PutSettingReq' - produces: - - application/json - responses: - "200": - description: 配置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 配置失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 提交单个配置 - tags: - - setting -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - AdminKeyAuth: - description: '管理站用Admin-Token, Header: Authorization' - in: header - name: Authorization - scopes: - write: Grants write access - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/settingapp/gen_docs.sh b/src/apps/settingapp/gen_docs.sh deleted file mode 100644 index 0c76f97e765cb3370ec82464284e98a48762bd7f..0000000000000000000000000000000000000000 --- a/src/apps/settingapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName settingservice - - - - - - - - diff --git a/src/apps/userapp/README.md b/src/apps/userapp/README.md deleted file mode 100644 index e3b0bc94538be14b03d49a77ea65a820def85f90..0000000000000000000000000000000000000000 --- a/src/apps/userapp/README.md +++ /dev/null @@ -1,82 +0,0 @@ - - -## UserApp - -提供用户相关的基础功能 - - - -### 支持功能 - -目前支持功能: - -- 注册/登录 -- 登录日志查看 -- 手机/邮箱验证码发送 -- 第三方登录,如wechat/qq等 -- 用户管理的功能 - - - -### Swagger-API - -API文档地址: http://127.0.0.1:40101/swagger/userservice/doc.json - - - -### 使用说明 - - - - - -#### 用户管理站AuthHandler - -主要用于实现对接其他系统的授权体系 - -可通过userapp/App下的AdminAuthOption选项配置对应的授权检查handler - -示例: - -设置为adminApp模块提供的AuthHandler - -``` - -userApp.ApiServer.AdminAuthOption.AuthHandler = adminApp.ApiServer.OptAuthHandler() - -``` - -自定义授权handler - -``` - -userApp.ApiServer.AdminAuthOption.AuthHandler = func(ctx *gin.Context) { - d, _ := ctx.Get(consts.AuthInfoContextKey) - logger.Info("%+v", d) - - token:=ctx.GetHeader("x-token") - if token!="xxx"{ - ctx.AbortWithStatusJSON(http.StatusOK, respdata.CAuthDenied) - return - } - - gin_http.SetAuth(ctx,&dto.AuthDataPacket{Auth: dto.AuthInfo{Id: 2,}}) - } -``` - - - - - -#### 用户AuthHandler - -可通过userapp/App下的AuthOption选项获取userApp的C端用户AuthHandler - -``` -xxAdmin.AuthOption.AuthHandler=userApp.ApiServer.AuthOption.OptAuthHandler() - -``` - - - - diff --git a/src/apps/userapp/api_server.go b/src/apps/userapp/api_server.go deleted file mode 100644 index 1ac38f883075267119d2539ede5d9e7e2f01d707..0000000000000000000000000000000000000000 --- a/src/apps/userapp/api_server.go +++ /dev/null @@ -1,170 +0,0 @@ -package userapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/apps/userapp/docs" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" -) - -type ApiServer struct { - *apps.ApiServer - - di *dig.Scope - conf *configstc.UserAppConfig - - gin_http.AuthOption //auth相关选项配置 - Swagger gin_http.SwaggerOption //swagger相关选项配置 - gin_http.PProfOption //pprof选项配置 - gin_http.OperateLogOption - - AdminAuthOption gin_http.AuthOption //auth相关选项配置 - - //依赖的controller - captchaCtr interfaces.ItfCaptchaController - verifyCodeCtr interfaces.ItfVerifyCodeController - authCtr interfaces.ItfUserAuthController - userCtr interfaces.ItfUserCenterController - userManageCtr interfaces.ItfUserManageController -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - //注册swagger - s.Swagger.SwaggerRouter(g) - - //注册pprof - s.PProfRouter(engine) - - s.router(g) - - return -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - authGroup := g.Group("", s.OptAuthHandler()) - adminGroup := g.Group("", s.AdminAuthOption.OptAuthHandler()) - - //验证码相关 - { - g.POST("/captcha/get", s.captchaCtr.GetCaptcha) // 图片验证码 - g.POST("/verify_code/send", s.verifyCodeCtr.SendCode) //短信验证码等 - } - - //授权模块 - { - //注册/登录相关 - g.POST("/auth/register", s.authCtr.SignUp) - g.POST("/auth/login", s.captchaCtr.VerifyHandler(), s.authCtr.AuthLogin) - g.POST("/auth/wechat_code", s.authCtr.AuthByWxCode) //微信code第三方登录 - - authGroup.POST("/auth/check", s.authCtr.AuthCheck) //校验登录状态 - authGroup.POST("/auth/info", s.authCtr.AuthInfo) //获取授权信息(通用授权) - authGroup.POST("/auth/logout", s.authCtr.AuthLogout) - authGroup.POST("/auth/fresh_token", s.authCtr.AuthFreshToken) //授权刷新token - } - - //debug开启的 - if s.conf.Debug { - g.POST("/debug/auth/third", s.authCtr.DebugAuthByThird) //debug auth用 - } - - //用户相关 - { - g.POST("/u_center/reset_pwd", s.userCtr.ResetPassword) //重置密码(忘记密码情况下) - authGroup.POST("/u_center/info", s.userCtr.UserInfo) //详细的账户信息 - authGroup.POST("/u_center/bind", s.userCtr.BindEmailPhone) //绑定信息 - authGroup.POST("/u_center/login_record", s.userCtr.LoginRecord) - authGroup.POST("/u_center/modify_pwd", s.userCtr.ModifyPassword) //修改密码(登录情况下) - authGroup.POST("/u_center/modify_info", s.userCtr.ModifyInfo) - } - - //用户权限 - //todo 待添加用户权限模块 - //common.ErrPanic(s.di.Invoke(func(ctr interfaces.ItfAccreditController) { - // authGroup.POST("/mag/u_center/accredit_info", ctr.AccreditInfo) - //})) - - //用户admin模块 - { - adminGroup.POST("/mag/user/search", s.userManageCtr.SearchUser) - adminGroup.POST("/mag/user/save", s.userManageCtr.SaveUser) - adminGroup.POST("/mag/user/detail", s.userManageCtr.QueryUser) - adminGroup.POST("/mag/user/disable", s.userManageCtr.DisableUser) - adminGroup.POST("/mag/user/delete", s.userManageCtr.DeleteUser) - adminGroup.POST("/mag/user/reset_password", s.userManageCtr.ResetUserPassword) - - //todo 添加用户日志查看功能 - //adminGroup.POST("/mag/user/log", ctr.SearchUserLog) - } -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(conf *configstc.UserAppConfig, logger v1log.ILog, - captchaCtr interfaces.ItfCaptchaController, - verifyCodeCtr interfaces.ItfVerifyCodeController, - authCtr interfaces.ItfUserAuthController, - userCtr interfaces.ItfUserCenterController, - userManageCtr interfaces.ItfUserManageController) *ApiServer { - - //swagger配置,取值后取指针是为了实现复用(多App) - swaggerDocs := *docs.SwaggerInfouserservice - swaggerDocs.Host = conf.ApiServer.HostAddr() + utils.KeepHasPrefix(conf.RoutePrefix, "/") - - s := &ApiServer{ - conf: conf, - Swagger: gin_http.SwaggerOption{ - Enable: conf.DocsEnable, - Name: swaggerDocs.InstanceName(), - Swagger: &swaggerDocs, - }, - PProfOption: gin_http.PProfOption{ - Enable: conf.PProfEnable, - }, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - //依赖的controller - captchaCtr: captchaCtr, - verifyCodeCtr: verifyCodeCtr, - authCtr: authCtr, - userCtr: userCtr, - userManageCtr: userManageCtr, - } - - s.WithName(conf.Name) - s.WithCors() //开启跨域设置 - - //用户端auth - s.AuthOption.AuthHandler = gin_http.AuthHandler(jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey)) - s.AdminAuthOption.AuthHandler = gin_http.AuthHandler(jwtauth.NewJwtTokenHandler(conf.AdminAuthConfig.SecretKey)) - - return s -} diff --git a/src/apps/userapp/app.go b/src/apps/userapp/app.go deleted file mode 100644 index 5386c8d1b54bd77672300fa28dc3ef64190e5d6f..0000000000000000000000000000000000000000 --- a/src/apps/userapp/app.go +++ /dev/null @@ -1,143 +0,0 @@ -// @title User模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey ApiKeyAuth -// @in header -// @name Authorization -// @description Api-Token, Header: Authorization - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package userapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - httpController "gitee.com/captials-team/ubdframe/src/apps/userapp/controllers/http" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/services" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - "go.uber.org/dig" -) - -type App struct { - *apps.App - - di *dig.Scope - - //rpc和api根据启动情况会有一个为空 - ApiServer *ApiServer - RpcServer *RpcServer -} - -func (app *App) initDao() { - common.ErrPanic(app.di.Provide(func(conf *configstc.UserAppConfig) (user interfaces.ItfUser, userThird interfaces.ItfUserThird, vtCode interfaces.ItfVerifyCode, loginRecord interfaces.ItfUserLoginRecord) { - var err error - user = mysqlDao.NewUserDao(conf.DBConfig) - userThird = mysqlDao.NewUserThirdDao(conf.DBConfig) - vtCode = mysqlDao.NewVerifyCodeDao(conf.DBConfig) - loginRecord = mysqlDao.NewUserLoginRecordDao(conf.DBConfig) - - _, err = user.Migrate() - common.ErrPanic(err) - - _, err = userThird.Migrate() - common.ErrPanic(err) - - _, err = vtCode.Migrate() - common.ErrPanic(err) - - _, err = loginRecord.Migrate() - common.ErrPanic(err) - - return - })) - -} - -func (app *App) initController() { - common.ErrPanic(app.di.Provide(gin_http.NewCaptchaController, dig.As(new(interfaces.ItfCaptchaController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewUserController, dig.As(new(interfaces.ItfUserCenterController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewAuthController, dig.As(new(interfaces.ItfUserAuthController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewVerifyCodeController, dig.As(new(interfaces.ItfVerifyCodeController))), uber_help.ErrAlreadyProvided) - common.ErrPanic(app.di.Provide(httpController.NewUserManageController, dig.As(new(interfaces.ItfUserManageController))), uber_help.ErrAlreadyProvided) -} - -func (app *App) initService(conf *configstc.UserAppConfig) { - common.ErrPanic(app.di.Provide(services.NewUserService, dig.As(new(interfaces.ItfUserService)))) -} - -// initUser 初始化用户 -func (app *App) initUser(conf *configstc.UserAppConfig, s interfaces.ItfUserService) { - for _, u := range conf.AutoCreateUser { - common.ErrPanic(s.AutoCreateUser(u.UserName, u.Account, u.Password)) - } -} - -// NewApp 初始化app -func NewApp(di *dig.Container, conf *configstc.UserAppConfig) *App { - scope := di.Scope("user") - - common.ErrPanic(scope.Provide(func() *dig.Scope { - return scope - }), uber_help.ErrAlreadyProvided) - - common.ErrPanic(scope.Provide(func() *configstc.UserAppConfig { - return conf - }), uber_help.ErrAlreadyProvided) - - app := &App{ - di: scope, - App: apps.NewApp(di, "user_app"), - } - app.WithName(conf.Name) - app.WithModule(conf.ModuleMode) - - common.ErrPanic(scope.Invoke(app.initDao)) - common.ErrPanic(scope.Invoke(app.initService)) - common.ErrPanic(scope.Invoke(app.initController)) - common.ErrPanic(scope.Invoke(app.initUser)) //初始化用户 - - //http api - if conf.ApiServer.Enable { - common.ErrPanic(scope.Provide(NewApiServer)) - common.ErrPanic(scope.Invoke(func(api *ApiServer) { - api.WithModule(conf.ModuleMode) - - app.WithApiServer(api) - app.ApiServer = api - })) - } - - //rpc - if conf.RpcServer.Enable { - common.ErrPanic(scope.Provide(NewRpcServer)) - common.ErrPanic(scope.Invoke(func(server *RpcServer) { - server.WithModule(conf.ModuleMode) - - app.App.WithApiServer(server) - app.RpcServer = server - })) - } - - return app -} diff --git a/src/apps/userapp/app_test.go b/src/apps/userapp/app_test.go deleted file mode 100644 index 52ac9abf11cb56cb1f800e26475a047830a87e93..0000000000000000000000000000000000000000 --- a/src/apps/userapp/app_test.go +++ /dev/null @@ -1,171 +0,0 @@ -package userapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/tests" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "testing" - "time" -) - -func TestAppStart(t *testing.T) { - di := testDi(t) - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - return app.Start() - })) - - time.Sleep(time.Hour) -} - -func TestMultiUserApp(t *testing.T) { - di := tests.NewDi(t) - - common.ErrPanic(di.Provide(apps.NewAppManager)) - - common.ErrPanic(di.Invoke(func(mgr *apps.AppManager) error { - userConfig := configstc.UserAppConfig{ - Name: "user", - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_test", - TablePrefix: "test_user_", - }, - DocsEnable: true, - ModuleMode: true, - } - userConfig.AutoCreateUser = []configstc.CreateUserConfig{ - {"体验用户", "demo", "123456"}, - } - - adminConfig := userConfig - adminConfig.DBConfig.TablePrefix = "test_admin_" - adminConfig.RoutePrefix = "/admin" - adminConfig.Name = "admin" - adminConfig.AutoCreateUser = []configstc.CreateUserConfig{ - {"超级管理员", "superadmin", "123456"}, - {"管理员", "admin", "123456"}, - } - - userApp := NewApp(di, &userConfig) - adminApp := NewApp(di, &adminConfig) - - api := apps.NewApiServer(gin.New(), userConfig.ApiServer) - api.WithName("MAIN") - api.InitRouterForServer(userApp.ApiServer, adminApp.ApiServer) - - mgr.WithApp(api) - - return mgr.Start() - })) - - time.Sleep(time.Hour) -} - -func TestMultiUserApp_di_in(t *testing.T) { - di := tests.NewDi(t) - - common.ErrPanic(di.Provide(apps.NewAppManager)) - - type MainApp struct { - dig.In - UserApp *App `name:"UserApp"` - AdminApp *App `name:"AdminApp"` - } - - apiServer := configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - } - common.ErrPanic(di.Provide(func() *App { - return NewApp(di, &configstc.UserAppConfig{ - Name: "user", - ApiServer: apiServer, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_test", - TablePrefix: "test_user_", - }, - DocsEnable: true, - ModuleMode: true, - AutoCreateUser: []configstc.CreateUserConfig{ - {"体验用户", "demo", "123456"}, - }, - }) - }, dig.Name("UserApp"))) - - common.ErrPanic(di.Provide(func() *App { - return NewApp(di, &configstc.UserAppConfig{ - Name: "admin", - ApiServer: apiServer, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_test", - TablePrefix: "test_admin_", - }, - DocsEnable: true, - ModuleMode: true, - RoutePrefix: "/admin", - AutoCreateUser: []configstc.CreateUserConfig{ - {"超级管理员", "superadmin", "123456"}, - {"管理员", "admin", "123456"}, - }, - }) - }, dig.Name("AdminApp"))) - - common.ErrPanic(di.Invoke(func(mgr *apps.AppManager, main MainApp) error { - api := apps.NewApiServer(gin.New(), apiServer) - api.WithName("MAIN") - api.InitRouterForServer(main.UserApp.ApiServer, main.AdminApp.ApiServer) - - mgr.WithApp(api) - - return mgr.Start() - })) - - time.Sleep(time.Hour) -} - -func testDi(t *testing.T) *dig.Container { - di := tests.NewDi(t) - - common.ErrPanic(di.Provide(func() *configstc.UserAppConfig { - return &configstc.UserAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - DBConfig: configstc.DBConfig{ - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_ubd_frame", - TablePrefix: "test_", - }, - DocsEnable: true, - } - })) - - return di -} diff --git a/src/apps/userapp/config.go b/src/apps/userapp/config.go deleted file mode 100644 index 566052e4375b37c17db0eccd9fb6697b24d4a63a..0000000000000000000000000000000000000000 --- a/src/apps/userapp/config.go +++ /dev/null @@ -1,16 +0,0 @@ -package userapp - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" -) - -// NewConfig godoc -// @Summary CONFIG-配置 -// @Description CONFIG-配置内容 -// @Tags user -// @Produce json -// @Success 200 {array} configstc.UserAppConfig -// @Router /-user-config [post] -func NewConfig() *configstc.UserAppConfig { - return configstc.LoadConfig(new(configstc.UserAppConfig)) -} diff --git a/src/apps/userapp/controllers/grpc/ctr_auth.go b/src/apps/userapp/controllers/grpc/ctr_auth.go deleted file mode 100644 index 8124815edbfea09a0c9da7c821f4c81e1de9b3cf..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/grpc/ctr_auth.go +++ /dev/null @@ -1,102 +0,0 @@ -package grpc - -import ( - "context" - "fmt" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/converts" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/passwd" - pbService "gitee.com/captials-team/ubdframe/src/protobufs/pb/service" - "go.uber.org/dig" - "time" -) - -type AuthServiceServer struct { - pbService.UnimplementedUserServiceServer - - jwtAuth interfaces.ItfJwtParser - - userDao interfaces.ItfUser - loginRecordDao interfaces.ItfUserLoginRecord - l v1log.ILog -} - -func (s *AuthServiceServer) DoAuth(ctx context.Context, req *pbService.DoAuthRequest) (*pbService.AuthResponse, error) { - var resp pbService.AuthResponse - if req.Account == "" || req.Password == "" { - utils.CopyTo(&respdata.CParamsInvalid, &resp) - return &resp, nil - } - //ctr.l.Debug("auth req %v", req) - - user, err := s.userDao.QueryByAccount(req.Account) - if err != nil { - return nil, fmt.Errorf("query err %s", err) - } - if user == nil { - resp.Code = -1 - resp.Message = "account wrong" - return &resp, nil - } - if user.Password != passwd.GenSaltPasswordByMd5(req.Password, user.Salt) { - resp.Code = -1 - resp.Message = "password wrong" - return &resp, nil - } - - //登录 - packet, err := converts.AuthToDataPacket(converts.UserConvertAuthInfo(user), time.Hour*4, s.jwtAuth) - if err != nil { - return nil, err - } - utils.CopyTo(&packet.Auth, &resp.Data) - - return &resp, nil -} - -func (s *AuthServiceServer) CheckAuth(ctx context.Context, req *pbService.CheckAuthRequest) (*pbService.AuthResponse, error) { - var resp pbService.AuthResponse - if req.Token == "" { - return &resp, fmt.Errorf("token invalid") - } - - packet, err := converts.TokenToAuthDataPacket(req.Token, s.jwtAuth) - if err != nil { - return nil, err - } - - if err := packet.Valid(); err != nil { - return nil, err - } - - utils.CopyTo(&packet.Auth, &(resp.Data)) - - s.l.Info("%+v", resp.Data) - - return &resp, nil -} - -func (s *AuthServiceServer) AddLog(ctx context.Context, req *pbService.AddLogRequest) (*pbService.AddLogResponse, error) { - var resp pbService.AddLogResponse - resp.Message = "add success" - return &resp, nil -} - -func NewAuthServiceServer(di *dig.Container, logger v1log.ILog, conf *configstc.UserAppConfig) *AuthServiceServer { - server := &AuthServiceServer{ - jwtAuth: jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey), - l: logger, - } - common.ErrPanic(di.Invoke(func(userDao interfaces.ItfUser, userThirdDao interfaces.ItfUserThird, loginRecordDao interfaces.ItfUserLoginRecord, verifyCodeDao interfaces.ItfVerifyCode) { - server.userDao = userDao - server.loginRecordDao = loginRecordDao - })) - - return server -} diff --git a/src/apps/userapp/controllers/grpc/g.go b/src/apps/userapp/controllers/grpc/g.go deleted file mode 100644 index 21e034e4c0fa360df99ffcad729fa166d205b87f..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/grpc/g.go +++ /dev/null @@ -1 +0,0 @@ -package grpc diff --git a/src/apps/userapp/controllers/http/base.go b/src/apps/userapp/controllers/http/base.go deleted file mode 100644 index d02cfda642c35bda7612cc799cd3c0a9c9acc6d4..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/http/base.go +++ /dev/null @@ -1 +0,0 @@ -package http diff --git a/src/apps/userapp/controllers/http/ctr_auth.go b/src/apps/userapp/controllers/http/ctr_auth.go deleted file mode 100644 index b97c8679fcab532f2651b9261f7b889d78158b4a..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/http/ctr_auth.go +++ /dev/null @@ -1,453 +0,0 @@ -package http - -import ( - "fmt" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/converts" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/i18n" - "gitee.com/captials-team/ubdframe/src/pkg/jwtauth" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/passwd" - "github.com/gin-gonic/gin" - "github.com/gin-gonic/gin/binding" - "github.com/silenceper/wechat/v2" - "github.com/silenceper/wechat/v2/cache" - "github.com/silenceper/wechat/v2/miniprogram" - miniConfig "github.com/silenceper/wechat/v2/miniprogram/config" - "golang.org/x/text/language" - "gorm.io/gorm" - "net/http" - "time" -) - -type AuthController struct { - l v1log.ILog - userDao interfaces.ItfUser - userThirdDao interfaces.ItfUserThird - loginRecordDao interfaces.ItfUserLoginRecord - verifyCodeDao interfaces.ItfVerifyCode - - jwtAuth interfaces.ItfJwtParser - - conf *configstc.UserAppConfig - - wxMiniProg *miniprogram.MiniProgram //微信miniProg支持 - - *gin_http.I18nController - passwd.SaltMd5Password -} - -func NewAuthController(conf *configstc.UserAppConfig, l v1log.ILog, userDao interfaces.ItfUser, userThirdDao interfaces.ItfUserThird, loginRecordDao interfaces.ItfUserLoginRecord, verifyCodeDao interfaces.ItfVerifyCode) *AuthController { - ctr := &AuthController{ - l: l, - conf: conf, - jwtAuth: jwtauth.NewJwtTokenHandler(conf.AuthConfig.SecretKey), - SaltMd5Password: passwd.SaltMd5Password{Salt: conf.PasswordSalt}, - } - //i18n - { - parser := i18n.NewParser() - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nEn), language.English.String()+".toml") - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nZh), language.Chinese.String()+".toml") - //for name, path := range conf.I18nFiles { - // parser.Load(path, name+".toml") - // l.Info("load i18n path %s: %s, %s", name, path, parser.Lang(name).ParseMsg("Hello")) - //} - parser.SetLanguage(language.Chinese) - parser.CacheLanguages() - ctr.I18nController = &gin_http.I18nController{ - Parser: i18n.NewParser(), - } - } - - //support we chat - if conf.WechatAuth.Enable { - wc := wechat.NewWechat() - memory := cache.NewMemory() - cfg := &miniConfig.Config{ - AppID: conf.WechatAuth.AppKey, - AppSecret: conf.WechatAuth.AppSecret, - Cache: memory, - } - ctr.wxMiniProg = wc.GetMiniProgram(cfg) - } - - ctr.userDao = userDao - ctr.userThirdDao = userThirdDao - ctr.loginRecordDao = loginRecordDao - ctr.verifyCodeDao = verifyCodeDao - - return ctr -} - -// SignUp godoc -// @Summary 注册账户 -// @Description 注册账户(账户/密码) -// @Tags user.auth -// @Accept json -// @Produce json -// @Param param body reqdata.RegisterReq true "注册信息" -// @success 0 {object} respdata.ResponseData{} "注册成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /auth/register [post] -func (ctr *AuthController) SignUp(ctx *gin.Context) { - if !ctr.conf.AuthRegister { - ctx.JSON(http.StatusOK, respdata.CNotSupport) - return - } - var req reqdata.RegisterReq - ctx.ShouldBindJSON(&req) - - if req.Account == "" || req.Password == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - //验证码为手机号/邮箱发送的验证码 - if req.Target() == "" || req.Code == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - //校验验证码 - ok, err := ctr.verifyCodeDao.Verify(req.Target(), req.Code) - if err != nil || !ok { - ctr.l.Ctl(err != nil).Error("verify err %s", err) - ctx.JSON(http.StatusOK, respdata.CVtCodeInvalid) - return - } - if req.Nickname == "" { - req.Nickname = utils.RandNickname() - } - - salt := utils.RandLetterFigureCode(12) - user := &models.User{ - Account: req.Account, - Password: ctr.GenPassword(req.Password, salt), - Salt: salt, - Nickname: req.Nickname, - Email: req.Email, - Phone: req.Phone, - LastLogin: nil, - LastIp: "", - Status: 1, - } - - //检查账户是否存在 - if find, _ := ctr.userDao.QueryByAccount(user.Account); find != nil { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("account_exists")) - return - } - - _, err = ctr.userDao.Add(user) - if err != nil { - ctr.l.Ctl(err != nil).Error("add new user err %s", err) - ctr.Response(ctx, respdata.CTryAgain) - return - } - - ctx.JSON(http.StatusOK, respdata.CSuccess.MData(respdata.RegisterResp{ - Account: user.Account, - Nickname: user.Nickname, - Sex: user.Sex, - Avatar: user.Avatar, - Email: user.Email, - Phone: user.Phone, - })) - return -} - -// AuthLogin godoc -// @Summary Auth-授权登录 -// @Description 登录 -// @Tags user.auth -// @Produce json -// @Param param body reqdata.AuthReq true "账户信息" -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /auth/login [post] -// @x-response-apikey-token-set {"tokenKey":"response.data.token","apiKey":"ApiKeyAuth"} -func (ctr *AuthController) AuthLogin(ctx *gin.Context) { - var req reqdata.AuthReq - - ctx.ShouldBindBodyWith(&req, binding.JSON) - if req.Account == "" || req.Password == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - if req.CaptchaKey == "" || req.CaptchaCode == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - //ctr.l.Debug("auth req %v", req) - - user, err := ctr.userDao.QueryByAccount(req.Account) - if err != nil { - ctr.l.Error("query err %s", err) - ctx.JSON(http.StatusOK, respdata.CError) - return - } - if user == nil || user.Password != ctr.GenPassword(req.Password, user.Salt) { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("account/password wrong")) - return - } - - //登录记录 - ctr.loginRecord(ctx, ctr.user2Auth(user)) - - ctr.authResponse(ctx, ctr.user2Auth(user)) -} - -// AuthLogout godoc -// @Summary Auth-取消授权 -// @Description 取消授权 -// @Tags user.auth -// @Produce json -// @Security ApiKeyAuth -// @success 200 {object} respdata.ResponseData{} "取消成功" -// @success 500 {object} respdata.ResponseData{} "取消失败" -// @Router /auth/logout [post] -func (ctr *AuthController) AuthLogout(ctx *gin.Context) { - ctx.JSON(http.StatusOK, respdata.CSuccess) -} - -// AuthFreshToken godoc -// @Summary Auth-刷新授权 -// @Description 刷新授权token -// @Tags user.auth -// @Produce json -// @Security ApiKeyAuth -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "刷新成功" -// @success 500 {object} respdata.ResponseData{} "刷新失败" -// @Router /auth/fresh_token [post] -// @x-response-apikey-token-set {"tokenKey":"response.data.token","apiKey":"ApiKeyAuth"} -func (ctr *AuthController) AuthFreshToken(ctx *gin.Context) { - auth := gin_http.GetAuth(ctx) - ctr.authResponse(ctx, auth) -} - -// AuthByWxCode godoc -// @Summary Auth-微信code授权 -// @Description 第三方登录-微信 -// @Tags user.auth -// @Produce json -// @Param param body reqdata.ThirdAuthReq true "第三方授权码" -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /auth/wechat_code [post] -// @x-response-apikey-token-set {"tokenKey":"response.data.token","apiKey":"ApiKeyAuth"} -func (ctr *AuthController) AuthByWxCode(ctx *gin.Context) { - if ctr.wxMiniProg == nil { - ctx.JSON(http.StatusOK, respdata.CNotSupport) - return - } - var req reqdata.ThirdAuthReq - - ctx.ShouldBind(&req) - if req.Code == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid.MMsg("code is empty")) - return - } - - //mini program授权码授权 - authSession, err := ctr.wxMiniProg.GetAuth().Code2Session(req.Code) - if err != nil { - ctr.l.Error("wechat err: %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("AUTH_FAIL")) - return - } - - thirdInfo := &models.UserThird{ - ThirdId: authSession.OpenID, - ThirdUnionId: authSession.UnionID, - ThirdType: models.ThirdWechat, - } - ctr.thirdAuth(ctx, thirdInfo) -} - -// AuthByQQ godoc -// @Summary Auth-QQ授权登录 -// @Description 第三方登录-QQ -// @Tags user.auth -// @Produce json -// @Param param body reqdata.ThirdAuthReq true "第三方授权码" -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /auth/qq_code [post] -// @x-response-apikey-token-set {"tokenKey":"response.data.token","apiKey":"ApiKeyAuth"} -func (ctr *AuthController) AuthByQQ(ctx *gin.Context) { - ctr.Response(ctx, respdata.CNotSupport) -} - -// AuthInfo godoc -// @Summary Auth-登录信息 -// @Description 获取登录信息 -// @Tags user.auth -// @Security ApiKeyAuth -// @Produce json -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "授权信息" -// @Router /auth/info [post] -func (ctr *AuthController) AuthInfo(ctx *gin.Context) { - auth := gin_http.GetAuthDataPacket(ctx) - ctr.l.Debug("auth %d-%s", auth.Auth.Id, auth.Auth.Nickname) - - auth.Token = "" - - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(&auth, new(respdata.AuthResp)))) -} - -// AuthCheck godoc -// @Summary Auth-登录校验 -// @Description 登录校验ok正常返回,不通过返回99 -// @Tags user.auth -// @Security ApiKeyAuth -// @Produce json -// @success 200 {object} respdata.ResponseData{} "返回结果" -// @Router /auth/check [post] -func (ctr *AuthController) AuthCheck(ctx *gin.Context) { - ctr.Response(ctx, respdata.CSuccess) -} - -// DebugAuthByThird godoc -// @Summary [DEBUG]第三方授权 -// @Description 第三方登录-微信 -// @Tags user.auth -// @Produce json -// @success 200 {object} respdata.ResponseData{data=respdata.AuthResp} "授权成功" -// @success 500 {object} respdata.ResponseData{code} "授权失败" -// @Router /debug/auth/third [post] -// @x-response-apikey-token-set {"tokenKey":"response.data.token","apiKey":"ApiKeyAuth"} -func (ctr *AuthController) DebugAuthByThird(ctx *gin.Context) { - ctr.l.Debug("debug auth third") - - thirdInfo := &models.UserThird{ - ThirdId: fmt.Sprintf("debug_user_%s", time.Now().Format("200601021504")), - ThirdType: models.ThirdWechat, - Nickname: utils.RandNickname(), - Phone: fmt.Sprintf("1%d%s", utils.TrueScopeRand(33, 88), utils.RandFigureCode(8)), - Email: fmt.Sprintf("%s@qq%s.com", utils.RandFigureCode(6), utils.RandFigureCode(3)), - } - thirdInfo.ThirdUnionId = thirdInfo.ThirdId - - ctr.thirdAuth(ctx, thirdInfo) -} - -// thirdAuth 第三方授权处理 -func (ctr *AuthController) thirdAuth(ctx *gin.Context, thirdInfo *models.UserThird) { - var user *models.User - - //先查询用户 - userWe, err := ctr.userThirdDao.QueryByThirdId(thirdInfo.ThirdType, thirdInfo.ThirdId) - if err != nil { - ctr.l.Error("query err: %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - //已存在则查询用户 - if userWe != nil { - user, err = ctr.userDao.Query(userWe.UId) - if err != nil { - ctr.l.Error("query err: %s", err) - ctx.JSON(http.StatusOK, respdata.CSysBusy) - return - } - if user != nil { - ctr.authResponse(ctx, ctr.user2Auth(user)) - return - } - //对应用户不存在则重新删除后进行重新创建的流程 - ctr.userThirdDao.Delete(userWe.Id) - } - - //创建新用户 - db := ctr.userDao.DB() - err = db.Transaction(func(tx *gorm.DB) error { - //创建新用户 - user = thirdInfo.ConvertUser() - - uid, err := ctr.userDao.Use(tx).Add(user) - if err != nil { - return err - } - thirdInfo.UId = uid - _, err = ctr.userThirdDao.Use(tx).Add(thirdInfo) - if err != nil { - return err - } - return nil - }) - if err != nil { - ctr.l.Error("new user fail err: %s", err) - ctx.JSON(http.StatusOK, respdata.CSysBusy) - return - } - - ctr.authResponse(ctx, ctr.user2Auth(user)) -} - -// authResponse 授权返回 -func (ctr *AuthController) authResponse(ctx *gin.Context, auth dto.AuthInfo) { - if auth.Id <= 0 { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("auth err")) - return - } - - authData, err := converts.AuthToDataPacket(auth, time.Duration(ctr.conf.AuthConfig.AuthExpired)*time.Second, ctr.jwtAuth) - if err != nil { - ctr.l.Error("token fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("token err")) - return - } - - ctr.loginRecord(ctx, auth) - - ctr.Response(ctx, respdata.CSuccess.MData(utils.CopyTo(&authData, new(respdata.AuthResp)))) -} - -// user2Auth 用户转为model数据 -func (ctr *AuthController) user2Auth(data *models.User) dto.AuthInfo { - if data == nil { - return dto.AuthInfo{} - } - if data.LastLogin == nil { - t := time.Now() - data.LastLogin = &t - } - return dto.AuthInfo{ - Id: data.Id, - Nickname: data.Nickname, - Account: data.Account, - //Avatar: data.Avatar, - Status: data.Status, - //Email: data.Email, - //Phone: data.Phone, - //LastLogin: data.LastLogin.Format(time.RFC3339), - //LastIp: data.LastIp, - SaasId: 0, - } -} - -// loginRecord 登录记录 -func (ctr *AuthController) loginRecord(ctx *gin.Context, auth dto.AuthInfo) { - //登录记录 - go func(p *dto.LoginInfoParam) { - ctr.userDao.LoginNote(auth.Id, p) - ctr.loginRecordDao.Add(&models.UserLoginRecord{ - Uid: auth.Id, - LastDevice: p.Device, - LastLogin: &p.Time, - LastLocate: "", - LastIp: p.Ip, - Remark: "", - }) - }(&dto.LoginInfoParam{ - Time: time.Now(), - Ip: ctx.ClientIP(), - Device: ctx.Request.Header.Get("User-Agent"), - }) -} diff --git a/src/apps/userapp/controllers/http/ctr_captcha.go b/src/apps/userapp/controllers/http/ctr_captcha.go deleted file mode 100644 index ac72acfe5fc6bf0f172db947ae598a88ec30302e..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/http/ctr_captcha.go +++ /dev/null @@ -1,17 +0,0 @@ -package http - -import ( - "github.com/gin-gonic/gin" -) - -// GetCaptcha godoc -// @Summary 验证码图片 -// @Description 验证码生成图片 -// @Tags user.other -// @Produce json -// @success 0 {object} respdata.ResponseData{data=respdata.CaptchaResponse} "获取成功" -// @failure 1 {object} respdata.ResponseData{code=int} "获取失败" -// @Router /captcha/get [post] -func GetCaptcha(ctx *gin.Context) { - //该代码用来生成captcha api的swagger用 -} diff --git a/src/apps/userapp/controllers/http/ctr_user.go b/src/apps/userapp/controllers/http/ctr_user.go deleted file mode 100644 index c6d649fc5860fb832d1455185e6a405b0451221b..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/http/ctr_user.go +++ /dev/null @@ -1,313 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - "gitee.com/captials-team/ubdframe/src/pkg/i18n" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/passwd" - "github.com/gin-gonic/gin" - "golang.org/x/text/language" - "net/http" -) - -type UserController struct { - l v1log.ILog - userDao interfaces.ItfUser - loginRecordDao interfaces.ItfUserLoginRecord - verifyCodeDao interfaces.ItfVerifyCode - - conf *configstc.UserAppConfig - - *gin_http.CaptchaController - *gin_http.I18nController - passwd.SaltMd5Password -} - -func NewUserController(l v1log.ILog, conf *configstc.UserAppConfig, userDao interfaces.ItfUser, loginRecordDao interfaces.ItfUserLoginRecord, verifyCodeDao interfaces.ItfVerifyCode) *UserController { - ctr := &UserController{ - l: l, - conf: conf, - SaltMd5Password: passwd.SaltMd5Password{Salt: conf.PasswordSalt}, - } - //i18n - { - parser := i18n.NewParser() - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nEn), language.English.String()+".toml") - //parser.Bundle().MustParseMessageFileBytes([]byte(I18nZh), language.Chinese.String()+".toml") - //for name, path := range conf.I18nFiles { - // parser.Load(path, name+".toml") - // l.Info("load i18n path %s: %s, %s", name, path, parser.Lang(name).ParseMsg("Hello")) - //} - parser.SetLanguage(language.Chinese) - parser.CacheLanguages() - ctr.I18nController = &gin_http.I18nController{ - Parser: i18n.NewParser(), - } - } - ctr.userDao = userDao - ctr.loginRecordDao = loginRecordDao - ctr.verifyCodeDao = verifyCodeDao - - return ctr -} - -// UserInfo godoc -// @Summary 用户信息 -// @Description 用户信息,比AuthInfo提供信息更详细 -// @Tags user -// @Produce json -// @Security ApiKeyAuth -// @success 0 {object} respdata.ResponseData{data=respdata.QueryUserResp} "获取成功" -// @success 0 {object} respdata.ResponseData{} "重置成功" -// @fail 1 {object} respdata.ResponseData{} "重置失败" -// @Router /u_center/info [post] -func (ctr *UserController) UserInfo(ctx *gin.Context) { - auth := gin_http.GetAuth(ctx) - user, err := ctr.userDao.Query(auth.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("query err")) - return - } - if user == nil { - ctx.JSON(http.StatusOK, respdata.CNotFound) - return - } - - resp := utils.CopyTo(user, new(respdata.QueryUserResp)) - ctr.Response(ctx, respdata.CSuccess.MData(resp)) -} - -// ResetPassword godoc -// @Summary 忘记密码 -// @Description 忘记密码场景下重置密码 -// @Tags user -// @Produce json -// @Param param body reqdata.ResetPasswordReq true "重置密码" -// @success 0 {object} respdata.ResponseData{} "重置成功" -// @fail 1 {object} respdata.ResponseData{} "重置失败" -// @Router /u_center/reset_pwd [post] -func (ctr *UserController) ResetPassword(ctx *gin.Context) { - var req reqdata.ResetPasswordReq - ctx.ShouldBind(&req) - - if req.Target() == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - - //校验验证码 - ok, err := ctr.verifyCodeDao.Verify(req.Target(), req.Code) - if err != nil || !ok { - ctr.l.Ctl(err != nil).Error("verify err %s", err) - ctx.JSON(http.StatusOK, respdata.CVtCodeInvalid) - return - } - - //通过后进行重置 - var user *models.User - if req.Phone != "" { - user, err = ctr.userDao.QueryByPhone(req.Phone) - } else if req.Email != "" { - user, err = ctr.userDao.QueryByEmail(req.Email) - } - if err != nil { - ctr.l.Error("query fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("user not exist")) - return - } - - if user == nil { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("user not exist")) - return - } - - //重置账户密码 - if _, err := ctr.userDao.ResetPassword(user.Id, ctr.GenPassword(req.Password)); err != nil { - ctr.l.Error("reset fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("reset fail")) - return - } - - ctx.JSON(http.StatusOK, respdata.CSuccess) -} - -// BindEmailPhone godoc -// @Summary 用户中心-绑定邮箱/手机 -// @Description 绑定邮箱/手机 -// @Tags user -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.PhoneEmailVerifyReq true "验证信息" -// @success 200 {object} respdata.ResponseData{} "绑定成功" -// @success 500 {object} respdata.ResponseData{} "绑定失败" -// @Router /u_center/bind [post] -func (ctr *UserController) BindEmailPhone(ctx *gin.Context) { - var req reqdata.PhoneEmailVerifyReq - ctx.ShouldBind(&req) - - if req.Email == "" || req.Phone == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - - //校验验证码 - ok, err := ctr.verifyCodeDao.Verify(req.Target(), req.Code) - if err != nil || !ok { - ctr.l.Ctl(err != nil).Error("verify err %s", err) - ctx.JSON(http.StatusOK, respdata.CVtCodeInvalid) - return - } - //通过后进行修改 - var user *models.User - if req.Phone != "" { - user, err = ctr.userDao.QueryByPhone(req.Phone) - } else if req.Email != "" { - user, err = ctr.userDao.QueryByEmail(req.Email) - } - if err != nil { - ctr.l.Error("query fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("user not exist")) - return - } - - if user == nil { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("user not exist")) - return - } - if req.Phone != "" { - user.Phone = req.Phone - } else if req.Email != "" { - user.Email = req.Email - } - - //重置账户密码 - if _, err := ctr.userDao.UpdateProInfo(user.Id, &models.User{ - Email: user.Email, - Phone: user.Phone, - }); err != nil { - ctr.l.Error("reset fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("reset fail")) - return - } - - ctx.JSON(http.StatusOK, respdata.CNotSupport) -} - -// LoginRecord godoc -// @Summary 用户中心-历史登录记录 -// @Description 登录历史记录 -// @Tags user -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.SearchLoginRecordReq true "搜索参数集" -// @success 200 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.UserLoginRecord}} "获取成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /u_center/login_record [post] -func (ctr *UserController) LoginRecord(ctx *gin.Context) { - var req reqdata.SearchLoginRecordReq - ctx.ShouldBind(&req) - - auth := gin_http.GetAuth(ctx) - list, pager, err := ctr.loginRecordDao.Search(&dto.SearchLoginRecordParams{ - Keywords: req.Keywords, - Uid: auth.Id, - }, &paginate.Pager{ - Page: req.Page, - Size: req.Size, - }) - if err != nil { - ctr.l.Error("search err %s", err) - ctx.JSON(http.StatusOK, respdata.CError.MMsg("search fail")) - return - } - - ctx.JSON(http.StatusOK, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pager, - })) -} - -// ModifyPassword godoc -// @Summary 用户中心-修改密码 -// @Description 授权登录后修改密码 -// @Tags user -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.ModifyPasswordReq true "修改密码" -// @success 0 {object} respdata.ResponseData{} "修改成功" -// @fail 1 {object} respdata.ResponseData{} "修改失败" -// @Router /u_center/modify_pwd [post] -func (ctr *UserController) ModifyPassword(ctx *gin.Context) { - var req reqdata.ModifyPasswordReq - ctx.ShouldBind(&req) - - if req.OldPassword == "" || req.Password == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - - auth := gin_http.GetAuth(ctx) - user, err := ctr.userDao.Query(auth.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError) - return - } - - //旧密码验证 - if user.Password != ctr.GenPassword(req.OldPassword, user.Salt) { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("password wrong")) - return - } - - //重置密码 - if _, err := ctr.userDao.ResetPassword(auth.Id, ctr.GenPassword(req.Password)); err != nil { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("password reset fail")) - return - } - - ctx.JSON(http.StatusOK, respdata.CSuccess) -} - -// ModifyInfo godoc -// @Summary 用户中心-修改个人信息 -// @Description 修改个人信息 -// @Tags user -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.ModifyInfoReq true "账户信息" -// @success 200 {object} respdata.ResponseData{} "授权成功" -// @success 500 {object} respdata.ResponseData{} "授权失败" -// @Router /u_center/modify_info [post] -func (ctr *UserController) ModifyInfo(ctx *gin.Context) { - var req reqdata.ModifyInfoReq - ctx.ShouldBind(&req) - - if req.Nickname == "" || req.Avatar == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - - auth := gin_http.GetAuth(ctx) - _, err := ctr.userDao.UpdateProInfo(auth.Id, &models.User{ - Nickname: req.Nickname, - Sex: req.Sex, - Avatar: req.Avatar, - }) - if err != nil { - ctr.l.Error("update fail %s", err) - ctx.JSON(http.StatusOK, respdata.CError) - return - } - - ctx.JSON(http.StatusOK, respdata.CSuccess) -} diff --git a/src/apps/userapp/controllers/http/ctr_user_manage.go b/src/apps/userapp/controllers/http/ctr_user_manage.go deleted file mode 100644 index 658c2aee1e9639bcdde95b4139b1bde4a07c3f97..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/http/ctr_user_manage.go +++ /dev/null @@ -1,357 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common/consts" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto" - "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/passwd" - "github.com/gin-gonic/gin" -) - -type UserManageController struct { - l v1log.ILog - conf *configstc.UserAppConfig - userModel interfaces.ItfUser - userThirdModel interfaces.ItfUserThird - - passwd.SaltMd5Password - gin_http.ResponseController - gin_http.OperateLogController -} - -func NewUserManageController(l v1log.ILog, conf *configstc.UserAppConfig) *UserManageController { - ctr := &UserManageController{ - l: l, - userModel: mysqlDao.NewUserDao(conf.DBConfig), - userThirdModel: mysqlDao.NewUserThirdDao(conf.DBConfig), - conf: conf, - SaltMd5Password: passwd.SaltMd5Password{Salt: conf.PasswordSalt}, - } - - return ctr -} - -// SearchUser 用户列表 godoc -// @Summary 用户管理-列表 -// @Description 用户列表展示和搜索 -// @Tags admin.user -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.SearchUserParam true "搜索参数集" -// @success 0 {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.User}} "获取成功" -// @Router /mag/user/search [post] -func (ctr *UserManageController) SearchUser(ctx *gin.Context) { - var req reqdata.SearchUserParam - ctx.ShouldBind(&req) - - params := &dto.SearchUserParams{ - Keywords: req.Keywords, - Status: req.Status, - } - - list, pager, err := ctr.userModel.Search(params, &paginate.Pager{ - Page: req.Page, - Size: req.Size, - }) - if err != nil { - ctr.l.Error("search err %s", err) - ctr.Response(ctx, respdata.CError) - return - } - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{ - List: list, - Paginate: *pager, - })) -} - -// SaveUser godoc -// @Summary 用户管理-保存 -// @Description 创建或编辑用户 -// @Tags admin.user -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.AddEditUserReq true "提交用户信息" -// @success 0 {object} respdata.ResponseData{data=respdata.DetailResp} "保存成功" -// @success 2 {object} respdata.ResponseData{} "系统繁忙" -// @success 4 {object} respdata.ResponseData{} "参数无效" -// @success 10 {object} respdata.ResponseData{} "未查询到" -// @Router /mag/user/save [post] -func (ctr *UserManageController) SaveUser(ctx *gin.Context) { - var req reqdata.AddEditUserReq - - ctx.ShouldBind(&req) - - if req.Id <= 0 { - ctr.createUser(ctx, req) - } else { - ctr.updateUser(ctx, req) - } -} - -func (ctr *UserManageController) createUser(ctx *gin.Context, req reqdata.AddEditUserReq) { - if req.Nickname == "" || req.Account == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - salt := utils.RandLetterFigureCode(12) - user := models.User{ - Account: req.Account, - Password: ctr.GenPassword(req.Password, salt), - Nickname: req.Nickname, - Phone: req.Phone, - Email: req.Email, - Status: req.Status, - Salt: salt, - } - - find, err := ctr.userModel.QueryByAccount(user.Account) - if err != nil { - ctr.l.Error("query err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if find != nil { - ctr.Response(ctx, respdata.CError.MMsg("用户名已存在")) - return - } - _, err = ctr.userModel.Add(&user) - if err != nil { - ctr.l.Error("add user err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.CustomizeLog(ctx, "新增用户-"+user.Nickname) - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.DetailResp{Id: user.Id})) -} - -func (ctr *UserManageController) updateUser(ctx *gin.Context, req reqdata.AddEditUserReq) { - if req.Nickname == "" || req.Account == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - user := models.User{ - Account: req.Account, - Password: req.Password, - Nickname: req.Nickname, - Phone: req.Phone, - Email: req.Email, - Status: req.Status, - } - - find, err := ctr.userModel.Query(req.Id) - if err != nil { - ctr.l.Error("query err %s,uid=%d", err, req.Id) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if find == nil { - ctr.Response(ctx, respdata.CError.MMsg("用户不存在")) - return - } - _, err = ctr.userModel.Update(req.Id, &user) - if err != nil { - ctr.l.Error("update err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if req.Password != "" { - _, err = ctr.userModel.ResetPassword(req.Id, ctr.GenPassword(req.Password, find.Salt)) - } - if err != nil { - ctr.l.Error("update user err %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.CustomizeLog(ctx, "更新用户-"+user.Nickname) - - ctr.Response(ctx, respdata.CSuccess.MData(respdata.DetailResp{Id: user.Id})) -} - -// QueryUser godoc -// @Summary 用户管理-详情 -// @Description 查询单个用户的详细信息 -// @Tags admin.user -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.DetailReq true "查询指定id详情" -// @success 0 {object} respdata.ResponseData{data=respdata.QueryUserResp} "获取成功" -// @success 2 {object} respdata.ResponseData{} "系统繁忙" -// @success 4 {object} respdata.ResponseData{} "参数无效" -// @success 10 {object} respdata.ResponseData{} "未查询到" -// @Router /mag/user/detail [post] -func (ctr *UserManageController) QueryUser(ctx *gin.Context) { - var req reqdata.DetailReq - - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - user, err := ctr.userModel.Query(req.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if user == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - user.Password = "" - - thirds, _, err := ctr.userThirdModel.Search(&dto.SearchUserThirdParams{ - Uid: user.Id, - }, &paginate.Pager{Size: 100}) - if err != nil { - ctr.l.Error("get thirds fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.CustomizeLog(ctx, "查看用户-"+user.Nickname) - - resp := utils.CopyTo(user, new(respdata.QueryUserResp)) - resp.Thirds = utils.CopyMoreTo(thirds, []*respdata.UserThirdInfo{}) - - ctr.Response(ctx, respdata.CSuccess.MData(resp)) -} - -// DisableUser godoc -// @Summary 用户管理-启用/禁用 -// @Description 操作启用/禁用用户 -// @Security AdminKeyAuth -// @Tags admin.user -// @Accept json -// @Produce json -// @Param param body reqdata.SetStatusReq true "状态设置请求" -// @success 200 {object} respdata.ResponseData{} "设置成功" -// @Router /mag/user/disable [post] -func (ctr *UserManageController) DisableUser(ctx *gin.Context) { - var req reqdata.SetStatusReq - - ctx.ShouldBind(&req) - - if req.Status != consts.StatusEnable && req.Status != consts.StatusDisable { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - user, err := ctr.userModel.Query(req.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if user == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - _, err = ctr.userModel.ResetStatus(req.Id, req.Status) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if req.Status == consts.StatusEnable { - ctr.CustomizeLog(ctx, "启用用户-"+user.Nickname) - } else { - ctr.CustomizeLog(ctx, "禁用用户-"+user.Nickname) - } - ctr.Response(ctx, respdata.CSuccess) - return -} - -// DeleteUser godoc -// @Summary 用户管理-删除用户 -// @Description 删除指定用户 -// @Tags admin.user -// @Security AdminKeyAuth -// @Produce json -// @Param param body reqdata.DetailReq true "指定用户id" -// @success 0 {object} respdata.ResponseData{} "成功" -// @Router /mag/user/delete [post] -func (ctr *UserManageController) DeleteUser(ctx *gin.Context) { - var req reqdata.DetailReq - ctx.ShouldBind(&req) - if req.Id <= 0 { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - user, err := ctr.userModel.Query(req.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if user == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - - if _, err := ctr.userModel.Delete(user.Id); err != nil { - ctr.l.Error("delete user fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - - ctr.CustomizeLog(ctx, "删除用户-"+user.Nickname) - - ctr.Response(ctx, respdata.CSuccess) -} - -// ResetUserPassword godoc -// @Summary 用户管理-重置密码 -// @Description 密码重置 -// @Security AdminKeyAuth -// @Tags admin.user -// @Accept json -// @Produce json -// @Param param body reqdata.ResetUserPasswdReq true "重置密码请求" -// @success 200 {object} respdata.ResponseData{} "成功" -// @Router /mag/user/reset_password [post] -func (ctr *UserManageController) ResetUserPassword(ctx *gin.Context) { - var req reqdata.ResetUserPasswdReq - ctx.ShouldBind(&req) - - if req.Password == "" { - ctr.Response(ctx, respdata.CParamsInvalid) - return - } - - user, err := ctr.userModel.Query(req.Id) - if err != nil { - ctr.l.Error("query fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - if user == nil { - ctr.Response(ctx, respdata.CNotFound) - return - } - - _, err = ctr.userModel.ResetPassword(req.Id, ctr.GenPassword(req.Password, user.Salt)) - if err != nil { - ctr.l.Error("operate fail %s", err) - ctr.Response(ctx, respdata.CSysBusy) - return - } - ctr.CustomizeLog(ctx, "重置用户密码-"+user.Nickname) - - ctr.Response(ctx, respdata.CSuccess) -} diff --git a/src/apps/userapp/controllers/http/ctr_verifycode.go b/src/apps/userapp/controllers/http/ctr_verifycode.go deleted file mode 100644 index 5dc788441e8134b7870d8cf3c584f55287cf243c..0000000000000000000000000000000000000000 --- a/src/apps/userapp/controllers/http/ctr_verifycode.go +++ /dev/null @@ -1,167 +0,0 @@ -package http - -import ( - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" - "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - "gitee.com/captials-team/ubdframe/src/domain/models" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/messages" - "github.com/gin-gonic/gin" - "net/http" - "time" -) - -type VerifyCodeController struct { - l v1log.ILog - - phoneSender messages.MessageSender - emailSender messages.MessageSender - - verifyCodeDao interfaces.ItfVerifyCode - - codeExpireTime time.Duration //过期时间 -} - -// SendCode godoc -// @Summary 短信验证码-发送 -// @Description 发送短信验证码 -// @Tags user.other -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.PhoneEmailSendReq true "发送对象信息" -// @success 200 {object} respdata.ResponseData{data=respdata.SmsCodeSendResp} "发送成功" -// @success 500 {object} respdata.ResponseData{} "发送失败" -// @Router /verify_code/send [post] -func (ctr *VerifyCodeController) SendCode(ctx *gin.Context) { - var req reqdata.PhoneEmailSendReq - ctx.ShouldBind(&req) - - //发送 - var sender messages.MessageSender - var target string - if req.Phone != "" { - sender = ctr.phoneSender - target = req.Phone - } else if req.Email != "" { - //邮箱验证码 - sender = ctr.emailSender - target = req.Email - } - if sender == nil { - ctx.JSON(http.StatusOK, respdata.CNotSupport) - return - } - if !sender.Allow(target) { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("wait for seconds send")) - return - } - expireTime := ctr.codeExpireTime - expiredAt := time.Now().Add(expireTime) - code := utils.RandFigureCode(6) - - ctr.l.Info("code send: %s,%s", target, code) - - go func() { - codeInfo := &models.VerifyCode{ - Target: target, - Code: code, - ExpiredAt: &expiredAt, - } - //存dao - if _, err := ctr.verifyCodeDao.Add(codeInfo); err != nil { - ctx.JSON(http.StatusOK, respdata.CError.MMsg("wait for seconds send")) - return - } - //发送实际处理 - if err := sender.Send(target, code); err != nil { - ctr.l.Error("send code err: %s,%s", target, err) - } - ctr.l.Info("code-%s send success", target) - }() - - ctx.JSON(http.StatusOK, respdata.CSuccess.MData(respdata.SmsCodeSendResp{ - ValidMinute: int64(expireTime / time.Second), - Target: target, - })) -} - -// VerifyCode godoc -// @Summary 短信验证码-校验 -// @Description 校验短信验证码 -// @Tags user.other -// @Produce json -// @Security ApiKeyAuth -// @Param param body reqdata.PhoneEmailVerifyReq true "验证信息" -// @success 0 {object} respdata.ResponseData{data=respdata.SmsCodeVerifyResp} "验证成功" -// @success 5 {object} respdata.ResponseData{} "验证失败" -// @Router /verify_code/verify [post] -func (ctr *VerifyCodeController) VerifyCode(ctx *gin.Context) { - var req reqdata.PhoneEmailVerifyReq - - ctx.ShouldBindBodyWithJSON(&req) - - if req.Target() == "" || req.Code == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - - //校验验证码 - ok, err := ctr.verifyCodeDao.Verify(req.Target(), req.Code) - if err != nil || !ok { - ctr.l.Ctl(err != nil).Error("verify err %s", err) - ctx.JSON(http.StatusOK, respdata.CVtCodeInvalid) - return - } - - ctx.JSON(http.StatusOK, respdata.CSuccess.MData(respdata.SmsCodeVerifyResp{ - Target: req.Target(), - Success: true, - })) -} - -func (ctr *VerifyCodeController) VerifyHandler() gin.HandlerFunc { - return func(ctx *gin.Context) { - var req reqdata.PhoneEmailVerifyReq - - ctx.ShouldBindBodyWithJSON(&req) - - if req.Target() == "" || req.Code == "" { - ctx.JSON(http.StatusOK, respdata.CParamsInvalid) - return - } - - //校验验证码 - ok, err := ctr.verifyCodeDao.Verify(req.Target(), req.Code) - if err != nil || !ok { - ctr.l.Ctl(err != nil).Error("verify err %s", err) - ctx.AbortWithStatusJSON(http.StatusOK, respdata.CVtCodeInvalid) - return - } - } -} - -func NewVerifyCodeController(conf *configstc.UserAppConfig, l v1log.ILog, verifyCodeDao interfaces.ItfVerifyCode) *VerifyCodeController { - ctr := &VerifyCodeController{ - l: l, - - phoneSender: messages.NewNoneSender(), - emailSender: messages.NewNoneSender(), - - codeExpireTime: time.Minute * 5, - } - //sms - if conf.SmsConfig.Enable { - ctr.phoneSender = messages.NewAliCloudCodeSMS(conf.SmsConfig) - } - //邮箱 - if conf.EmailConfig.Enable { - ctr.emailSender = messages.NewEmailVerifyCodeSender(&conf.EmailConfig).WithCodeExpired(ctr.codeExpireTime) - } - - ctr.verifyCodeDao = verifyCodeDao - - return ctr -} diff --git a/src/apps/userapp/docs/userservice_docs.go b/src/apps/userapp/docs/userservice_docs.go deleted file mode 100644 index ea823e39935ccf6318a51c85fbfb2a934aae81aa..0000000000000000000000000000000000000000 --- a/src/apps/userapp/docs/userservice_docs.go +++ /dev/null @@ -1,2143 +0,0 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs - -import "github.com/swaggo/swag" - -const docTemplateuserservice = `{ - "schemes": {{ marshal .Schemes }}, - "produces": [ - "application/json", - "text/html" - ], - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/-user-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.UserAppConfig" - } - } - } - } - } - }, - "/auth/fresh_token": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "刷新授权token", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-刷新授权", - "responses": { - "200": { - "description": "刷新成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "刷新失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/auth/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取登录信息", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-登录信息", - "responses": { - "200": { - "description": "授权信息", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - } - } - } - }, - "/auth/login": { - "post": { - "description": "登录", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-授权登录", - "parameters": [ - { - "description": "账户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/auth/logout": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "取消授权", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-取消授权", - "responses": { - "200": { - "description": "取消成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "取消失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/auth/qq_code": { - "post": { - "description": "第三方登录-QQ", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-QQ授权登录", - "parameters": [ - { - "description": "第三方授权码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ThirdAuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/auth/register": { - "post": { - "description": "注册账户(账户/密码)", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "注册账户", - "parameters": [ - { - "description": "注册信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.RegisterReq" - } - } - ], - "responses": { - "0": { - "description": "注册成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/auth/wechat_code": { - "post": { - "description": "第三方登录-微信", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-微信code授权", - "parameters": [ - { - "description": "第三方授权码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ThirdAuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/captcha/get": { - "post": { - "description": "验证码生成图片", - "produces": [ - "application/json" - ], - "tags": [ - "user.other" - ], - "summary": "验证码图片", - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.CaptchaResponse" - } - } - } - ] - } - }, - "1": { - "description": "获取失败", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "code": { - "type": "integer" - } - } - } - ] - } - } - } - } - }, - "/debug/auth/third": { - "post": { - "description": "第三方登录-微信", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "[DEBUG]第三方授权", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/mag/user/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除指定用户", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-删除用户", - "parameters": [ - { - "description": "指定用户id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "查询单个用户的详细信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-详情", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.QueryUserResp" - } - } - } - ] - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用用户", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/reset_password": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "密码重置", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-重置密码", - "parameters": [ - { - "description": "重置密码请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ResetUserPasswdReq" - } - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "创建或编辑用户", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-保存", - "parameters": [ - { - "description": "提交用户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AddEditUserReq" - } - } - ], - "responses": { - "0": { - "description": "保存成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.DetailResp" - } - } - } - ] - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "用户列表展示和搜索", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-列表", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchUserParam" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.User" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/u_center/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "绑定邮箱/手机", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-绑定邮箱/手机", - "parameters": [ - { - "description": "验证信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PhoneEmailVerifyReq" - } - } - ], - "responses": { - "200": { - "description": "绑定成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "绑定失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "用户信息,比AuthInfo提供信息更详细", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户信息", - "responses": { - "0": { - "description": "重置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/login_record": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "登录历史记录", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-历史登录记录", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchLoginRecordReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.UserLoginRecord" - } - } - } - } - ] - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/modify_info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-修改个人信息", - "parameters": [ - { - "description": "账户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ModifyInfoReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/modify_pwd": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "授权登录后修改密码", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-修改密码", - "parameters": [ - { - "description": "修改密码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ModifyPasswordReq" - } - } - ], - "responses": { - "0": { - "description": "修改成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/reset_pwd": { - "post": { - "description": "忘记密码场景下重置密码", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "忘记密码", - "parameters": [ - { - "description": "重置密码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ResetPasswordReq" - } - } - ], - "responses": { - "0": { - "description": "重置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/verify_code/send": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "发送短信验证码", - "produces": [ - "application/json" - ], - "tags": [ - "user.other" - ], - "summary": "短信验证码-发送", - "parameters": [ - { - "description": "发送对象信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PhoneEmailSendReq" - } - } - ], - "responses": { - "200": { - "description": "发送成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.SmsCodeSendResp" - } - } - } - ] - } - }, - "500": { - "description": "发送失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/verify_code/verify": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "校验短信验证码", - "produces": [ - "application/json" - ], - "tags": [ - "user.other" - ], - "summary": "短信验证码-校验", - "parameters": [ - { - "description": "验证信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PhoneEmailVerifyReq" - } - } - ], - "responses": { - "0": { - "description": "验证成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.SmsCodeVerifyResp" - } - } - } - ] - } - }, - "5": { - "description": "验证失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.AuthConfig": { - "type": "object", - "properties": { - "AuthExpired": { - "description": "授权失效时间,单位:秒", - "type": "integer" - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "SecretKey": { - "description": "加密秘钥,如JWT", - "type": "string" - } - } - }, - "configstc.CommonExtendParams": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "configstc.CreateUserConfig": { - "type": "object", - "properties": { - "Account": { - "description": "账户", - "type": "string" - }, - "Password": { - "description": "密码", - "type": "string" - }, - "UserName": { - "description": "用户名", - "type": "string" - } - } - }, - "configstc.DBConfig": { - "type": "object", - "properties": { - "ConnMaxIdleTime": { - "description": "每个链接最大空闲时间", - "type": "integer", - "default": 0 - }, - "ConnMaxLifeTime": { - "description": "每个链接最大生存时间", - "type": "integer", - "default": 0 - }, - "DbConn": { - "description": "数据库类型,如mysql", - "type": "string" - }, - "DbDsn": { - "description": "数据库dsn", - "type": "string" - }, - "DbHost": { - "description": "数据库地址", - "type": "string" - }, - "DbName": { - "description": "数据库", - "type": "string" - }, - "DbPassword": { - "description": "密码", - "type": "string" - }, - "DbPort": { - "description": "端口", - "type": "string" - }, - "DbUser": { - "description": "用户名", - "type": "string" - }, - "MaxConcatLen": { - "type": "string" - }, - "MaxIdleConn": { - "description": "预留并发链接数", - "type": "integer", - "default": 0 - }, - "MaxOpenConn": { - "description": "最大支持链接", - "type": "integer", - "default": 0 - }, - "TablePrefix": { - "description": "表前缀", - "type": "string" - }, - "TimeZone": { - "description": "时区设置", - "type": "string" - } - } - }, - "configstc.EmailConfig": { - "type": "object", - "properties": { - "Enable": { - "type": "boolean" - }, - "SmtpHost": { - "description": "smtp服务host", - "type": "string" - }, - "SmtpName": { - "description": "smtp 发送名称", - "type": "string" - }, - "SmtpPassword": { - "description": "smtp密码", - "type": "string" - }, - "SmtpPort": { - "description": "smtp服务端口", - "type": "integer" - }, - "SmtpUserName": { - "description": "smtp用户名", - "type": "string" - } - } - }, - "configstc.LimitingConfig": { - "type": "object", - "properties": { - "MaxRate": { - "description": "允许的最大速率", - "type": "integer" - }, - "PerRate": { - "description": "每次(秒)速率", - "type": "integer" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "EndpointAddr": { - "description": "对外访问地址", - "type": "string" - }, - "EndpointPort": { - "description": "对外访问端口", - "type": "integer" - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "configstc.ThirdConfig": { - "type": "object", - "properties": { - "AppKey": { - "description": "app id/key", - "type": "string" - }, - "AppSecret": { - "description": "appSecret", - "type": "string" - }, - "Enable": { - "description": "是否启用第三方", - "type": "boolean" - }, - "ExtendParams": { - "description": "扩展参数,微信: EncodingAESKey", - "allOf": [ - { - "$ref": "#/definitions/configstc.CommonExtendParams" - } - ] - } - } - }, - "configstc.UserAppConfig": { - "type": "object", - "properties": { - "AdminAuthConfig": { - "description": "授权配置(管理站)", - "allOf": [ - { - "$ref": "#/definitions/configstc.AuthConfig" - } - ] - }, - "ApiServer": { - "description": "作为api服务器", - "allOf": [ - { - "$ref": "#/definitions/configstc.ServerConfig" - } - ] - }, - "AuthConfig": { - "description": "授权配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.AuthConfig" - } - ] - }, - "AuthRegister": { - "description": "是否支持注册", - "type": "boolean" - }, - "AutoCreateUser": { - "description": "自动创建用户列表", - "type": "array", - "items": { - "$ref": "#/definitions/configstc.CreateUserConfig" - } - }, - "DBConfig": { - "description": "数据库配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.DBConfig" - } - ] - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "DocsEnable": { - "description": "是否启用文档", - "type": "boolean" - }, - "EmailConfig": { - "description": "邮件配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.EmailConfig" - } - ] - }, - "LimitingApi": { - "description": "api限流", - "allOf": [ - { - "$ref": "#/definitions/configstc.LimitingConfig" - } - ] - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "ModuleMode": { - "description": "模块模式,作为module使用", - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "PProfEnable": { - "description": "是否启用pprof", - "type": "boolean" - }, - "PasswordSalt": { - "description": "密码salt", - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - }, - "RpcServer": { - "description": "作为rpc服务器", - "allOf": [ - { - "$ref": "#/definitions/configstc.ServerConfig" - } - ] - }, - "SmsConfig": { - "description": "短信配置,目前使用阿里云", - "allOf": [ - { - "$ref": "#/definitions/configstc.ThirdConfig" - } - ] - }, - "WechatAuth": { - "description": "微信配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.ThirdConfig" - } - ] - } - } - }, - "models.User": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "email": { - "description": "email", - "type": "string" - }, - "id": { - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "description": "昵称", - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "salt": { - "description": "密码盐", - "type": "string" - }, - "sex": { - "description": "性别,0:未知,1:男,2:女", - "type": "integer" - }, - "status": { - "type": "integer" - }, - "tenant_id": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.UserLoginRecord": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "last_device": { - "description": "操作设备", - "type": "string" - }, - "last_ip": { - "type": "string" - }, - "last_locate": { - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "remark": { - "type": "string" - }, - "uid": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.AddEditUserReq": { - "type": "object", - "properties": { - "account": { - "description": "账户", - "type": "string", - "example": "demo" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "user123" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13699991234" - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AuthReq": { - "type": "object", - "properties": { - "account": { - "description": "账户名", - "type": "string", - "example": "13488886666" - }, - "captcha_code": { - "description": "验证码", - "type": "string", - "example": "123456" - }, - "captcha_key": { - "description": "验证码key", - "type": "string", - "example": "xxxx" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.DetailReq": { - "type": "object", - "properties": { - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - }, - "ids": { - "description": "多个数据id", - "type": "array", - "items": { - "type": "integer" - }, - "example": [ - 1, - 2 - ] - } - } - }, - "reqdata.ModifyInfoReq": { - "type": "object", - "properties": { - "avatar": { - "description": "头像", - "type": "string", - "example": "xxx" - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo" - }, - "sex": { - "description": "性别", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.ModifyPasswordReq": { - "type": "object", - "properties": { - "old_password": { - "description": "旧密码", - "type": "string", - "example": "123456" - }, - "password": { - "description": "新密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.PhoneEmailSendReq": { - "type": "object", - "properties": { - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - } - } - }, - "reqdata.PhoneEmailVerifyReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "123456" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - } - } - }, - "reqdata.RegisterReq": { - "type": "object", - "properties": { - "account": { - "description": "账户密码", - "type": "string", - "example": "13488886666" - }, - "avatar": { - "description": "头像", - "type": "string", - "example": "xxx" - }, - "code": { - "type": "string", - "example": "123456" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - }, - "sex": { - "description": "性别", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.ResetPasswordReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "123456" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "password": { - "description": "新密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - } - } - }, - "reqdata.ResetUserPasswdReq": { - "type": "object", - "properties": { - "admin_password": { - "description": "当前管理员密码,可不填", - "type": "string", - "example": "123456" - }, - "id": { - "description": "指定用户id", - "type": "integer", - "example": 0 - }, - "password": { - "description": "重置的新密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.SearchLoginRecordReq": { - "type": "object", - "properties": { - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "m" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - } - } - }, - "reqdata.SearchUserParam": { - "type": "object", - "properties": { - "keywords": { - "type": "string", - "example": "d" - }, - "page": { - "type": "integer", - "example": 1 - }, - "size": { - "type": "integer", - "example": 10 - }, - "status": { - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SetStatusReq": { - "type": "object", - "properties": { - "id": { - "description": "id", - "type": "integer" - }, - "status": { - "description": "状态", - "type": "integer" - } - } - }, - "reqdata.ThirdAuthReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "123456" - } - } - }, - "respdata.AuthResp": { - "type": "object", - "properties": { - "auth": { - "description": "授权信息", - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "extends": { - "description": "额外信息", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "nickname": { - "type": "string" - }, - "saas_id": { - "description": "saas模式下用到的归属租户id", - "type": "integer" - }, - "saas_name": { - "description": "saas模式下用到的归属租户的名称", - "type": "string" - }, - "status": { - "type": "integer" - } - } - }, - "expired_at": { - "description": "过期时间戳,秒级", - "type": "integer" - }, - "token": { - "description": "授权凭证", - "type": "string" - } - } - }, - "respdata.CaptchaResponse": { - "type": "object", - "properties": { - "img": { - "type": "string" - }, - "key": { - "type": "string" - } - } - }, - "respdata.DetailResp": { - "type": "object", - "properties": { - "id": { - "description": "指定编辑的对象id", - "type": "integer" - } - } - }, - "respdata.QueryUserResp": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "email": { - "description": "email", - "type": "string" - }, - "id": { - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "description": "昵称", - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "sex": { - "description": "性别,0:未知,1:男,2:女", - "type": "integer" - }, - "status": { - "type": "integer" - }, - "third_binds": { - "description": "第三方绑定列表", - "type": "array", - "items": { - "$ref": "#/definitions/respdata.UserThirdInfo" - } - }, - "updated_at": { - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - }, - "respdata.SmsCodeSendResp": { - "type": "object", - "properties": { - "target": { - "description": "发送目标,可为手机号/邮箱", - "type": "string", - "example": "13488886666" - }, - "valid_minute": { - "description": "有效分钟数,单位:分钟", - "type": "integer", - "example": 33 - } - } - }, - "respdata.SmsCodeVerifyResp": { - "type": "object", - "properties": { - "success": { - "description": "是否验证成功", - "type": "boolean" - }, - "target": { - "description": "发送目标,可为手机号/邮箱", - "type": "string", - "example": "13488886666" - } - } - }, - "respdata.UserThirdInfo": { - "type": "object", - "properties": { - "avatar": { - "type": "string" - }, - "email": { - "type": "string" - }, - "extend_info": { - "description": "拓展信息,可以存json", - "type": "string" - }, - "id": { - "type": "integer" - }, - "nickname": { - "type": "string" - }, - "phone": { - "description": "额外可获取的用户信息", - "type": "string" - }, - "third_id": { - "description": "第三方id", - "type": "string" - }, - "third_type": { - "description": "第三方类型", - "type": "string" - }, - "third_union_id": { - "description": "第三方union id", - "type": "string" - }, - "uid": { - "type": "integer" - } - } - } - }, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -}` - -// SwaggerInfouserservice holds exported Swagger Info so clients can modify it -var SwaggerInfouserservice = &swag.Spec{ - Version: "1.0", - Host: "localhost:8080", - BasePath: "/", - Schemes: []string{"http", "https"}, - Title: "User模块API", - Description: "This is a sample server celler server.", - InfoInstanceName: "userservice", - SwaggerTemplate: docTemplateuserservice, - LeftDelim: "{{", - RightDelim: "}}", -} - -func init() { - swag.Register(SwaggerInfouserservice.InstanceName(), SwaggerInfouserservice) -} diff --git a/src/apps/userapp/docs/userservice_swagger.json b/src/apps/userapp/docs/userservice_swagger.json deleted file mode 100644 index c4a2bf09e07cb7c7c57b5cef8f8a46bbf859e62c..0000000000000000000000000000000000000000 --- a/src/apps/userapp/docs/userservice_swagger.json +++ /dev/null @@ -1,2123 +0,0 @@ -{ - "produces": [ - "application/json", - "text/html" - ], - "schemes": [ - "http", - "https" - ], - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "User模块API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "sage12345678@qq.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/", - "paths": { - "/-user-config": { - "post": { - "description": "CONFIG-配置内容", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "CONFIG-配置", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/configstc.UserAppConfig" - } - } - } - } - } - }, - "/auth/fresh_token": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "刷新授权token", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-刷新授权", - "responses": { - "200": { - "description": "刷新成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "刷新失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/auth/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取登录信息", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-登录信息", - "responses": { - "200": { - "description": "授权信息", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - } - } - } - }, - "/auth/login": { - "post": { - "description": "登录", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-授权登录", - "parameters": [ - { - "description": "账户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/auth/logout": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "取消授权", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-取消授权", - "responses": { - "200": { - "description": "取消成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "取消失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/auth/qq_code": { - "post": { - "description": "第三方登录-QQ", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-QQ授权登录", - "parameters": [ - { - "description": "第三方授权码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ThirdAuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/auth/register": { - "post": { - "description": "注册账户(账户/密码)", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "注册账户", - "parameters": [ - { - "description": "注册信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.RegisterReq" - } - } - ], - "responses": { - "0": { - "description": "注册成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/auth/wechat_code": { - "post": { - "description": "第三方登录-微信", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "Auth-微信code授权", - "parameters": [ - { - "description": "第三方授权码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ThirdAuthReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/captcha/get": { - "post": { - "description": "验证码生成图片", - "produces": [ - "application/json" - ], - "tags": [ - "user.other" - ], - "summary": "验证码图片", - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.CaptchaResponse" - } - } - } - ] - } - }, - "1": { - "description": "获取失败", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "code": { - "type": "integer" - } - } - } - ] - } - } - } - } - }, - "/debug/auth/third": { - "post": { - "description": "第三方登录-微信", - "produces": [ - "application/json" - ], - "tags": [ - "user.auth" - ], - "summary": "[DEBUG]第三方授权", - "responses": { - "200": { - "description": "授权成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.AuthResp" - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - }, - "x-response-apikey-token-set": { - "apiKey": "ApiKeyAuth", - "tokenKey": "response.data.token" - } - } - }, - "/mag/user/delete": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "删除指定用户", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-删除用户", - "parameters": [ - { - "description": "指定用户id", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/detail": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "查询单个用户的详细信息", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-详情", - "parameters": [ - { - "description": "查询指定id详情", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.DetailReq" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.QueryUserResp" - } - } - } - ] - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/disable": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "操作启用/禁用用户", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-启用/禁用", - "parameters": [ - { - "description": "状态设置请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SetStatusReq" - } - } - ], - "responses": { - "200": { - "description": "设置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/reset_password": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "密码重置", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-重置密码", - "parameters": [ - { - "description": "重置密码请求", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ResetUserPasswdReq" - } - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/save": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "创建或编辑用户", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-保存", - "parameters": [ - { - "description": "提交用户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.AddEditUserReq" - } - } - ], - "responses": { - "0": { - "description": "保存成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.DetailResp" - } - } - } - ] - } - }, - "10": { - "description": "未查询到", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "2": { - "description": "系统繁忙", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "4": { - "description": "参数无效", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/mag/user/search": { - "post": { - "security": [ - { - "AdminKeyAuth": [] - } - ], - "description": "用户列表展示和搜索", - "produces": [ - "application/json" - ], - "tags": [ - "admin.user" - ], - "summary": "用户管理-列表", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchUserParam" - } - } - ], - "responses": { - "0": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.User" - } - } - } - } - ] - } - } - } - ] - } - } - } - } - }, - "/u_center/bind": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "绑定邮箱/手机", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-绑定邮箱/手机", - "parameters": [ - { - "description": "验证信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PhoneEmailVerifyReq" - } - } - ], - "responses": { - "200": { - "description": "绑定成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "绑定失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "用户信息,比AuthInfo提供信息更详细", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户信息", - "responses": { - "0": { - "description": "重置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/login_record": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "登录历史记录", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-历史登录记录", - "parameters": [ - { - "description": "搜索参数集", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.SearchLoginRecordReq" - } - } - ], - "responses": { - "200": { - "description": "获取成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "allOf": [ - { - "$ref": "#/definitions/respdata.SearchListResponse" - }, - { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/models.UserLoginRecord" - } - } - } - } - ] - } - } - } - ] - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/modify_info": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "修改个人信息", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-修改个人信息", - "parameters": [ - { - "description": "账户信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ModifyInfoReq" - } - } - ], - "responses": { - "200": { - "description": "授权成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - }, - "500": { - "description": "授权失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/modify_pwd": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "授权登录后修改密码", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "用户中心-修改密码", - "parameters": [ - { - "description": "修改密码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ModifyPasswordReq" - } - } - ], - "responses": { - "0": { - "description": "修改成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/u_center/reset_pwd": { - "post": { - "description": "忘记密码场景下重置密码", - "produces": [ - "application/json" - ], - "tags": [ - "user" - ], - "summary": "忘记密码", - "parameters": [ - { - "description": "重置密码", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.ResetPasswordReq" - } - } - ], - "responses": { - "0": { - "description": "重置成功", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/verify_code/send": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "发送短信验证码", - "produces": [ - "application/json" - ], - "tags": [ - "user.other" - ], - "summary": "短信验证码-发送", - "parameters": [ - { - "description": "发送对象信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PhoneEmailSendReq" - } - } - ], - "responses": { - "200": { - "description": "发送成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.SmsCodeSendResp" - } - } - } - ] - } - }, - "500": { - "description": "发送失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - }, - "/verify_code/verify": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "校验短信验证码", - "produces": [ - "application/json" - ], - "tags": [ - "user.other" - ], - "summary": "短信验证码-校验", - "parameters": [ - { - "description": "验证信息", - "name": "param", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/reqdata.PhoneEmailVerifyReq" - } - } - ], - "responses": { - "0": { - "description": "验证成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/respdata.ResponseData" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/respdata.SmsCodeVerifyResp" - } - } - } - ] - } - }, - "5": { - "description": "验证失败", - "schema": { - "$ref": "#/definitions/respdata.ResponseData" - } - } - } - } - } - }, - "definitions": { - "configstc.AuthConfig": { - "type": "object", - "properties": { - "AuthExpired": { - "description": "授权失效时间,单位:秒", - "type": "integer" - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "SecretKey": { - "description": "加密秘钥,如JWT", - "type": "string" - } - } - }, - "configstc.CommonExtendParams": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "configstc.CreateUserConfig": { - "type": "object", - "properties": { - "Account": { - "description": "账户", - "type": "string" - }, - "Password": { - "description": "密码", - "type": "string" - }, - "UserName": { - "description": "用户名", - "type": "string" - } - } - }, - "configstc.DBConfig": { - "type": "object", - "properties": { - "ConnMaxIdleTime": { - "description": "每个链接最大空闲时间", - "type": "integer", - "default": 0 - }, - "ConnMaxLifeTime": { - "description": "每个链接最大生存时间", - "type": "integer", - "default": 0 - }, - "DbConn": { - "description": "数据库类型,如mysql", - "type": "string" - }, - "DbDsn": { - "description": "数据库dsn", - "type": "string" - }, - "DbHost": { - "description": "数据库地址", - "type": "string" - }, - "DbName": { - "description": "数据库", - "type": "string" - }, - "DbPassword": { - "description": "密码", - "type": "string" - }, - "DbPort": { - "description": "端口", - "type": "string" - }, - "DbUser": { - "description": "用户名", - "type": "string" - }, - "MaxConcatLen": { - "type": "string" - }, - "MaxIdleConn": { - "description": "预留并发链接数", - "type": "integer", - "default": 0 - }, - "MaxOpenConn": { - "description": "最大支持链接", - "type": "integer", - "default": 0 - }, - "TablePrefix": { - "description": "表前缀", - "type": "string" - }, - "TimeZone": { - "description": "时区设置", - "type": "string" - } - } - }, - "configstc.EmailConfig": { - "type": "object", - "properties": { - "Enable": { - "type": "boolean" - }, - "SmtpHost": { - "description": "smtp服务host", - "type": "string" - }, - "SmtpName": { - "description": "smtp 发送名称", - "type": "string" - }, - "SmtpPassword": { - "description": "smtp密码", - "type": "string" - }, - "SmtpPort": { - "description": "smtp服务端口", - "type": "integer" - }, - "SmtpUserName": { - "description": "smtp用户名", - "type": "string" - } - } - }, - "configstc.LimitingConfig": { - "type": "object", - "properties": { - "MaxRate": { - "description": "允许的最大速率", - "type": "integer" - }, - "PerRate": { - "description": "每次(秒)速率", - "type": "integer" - } - } - }, - "configstc.ServerConfig": { - "type": "object", - "properties": { - "AllowOrigins": { - "description": "指定跨域允许访问源,空则为不限制访问", - "type": "array", - "items": { - "type": "string" - } - }, - "Enable": { - "description": "是否启用", - "type": "boolean" - }, - "EndpointAddr": { - "description": "对外访问地址", - "type": "string" - }, - "EndpointPort": { - "description": "对外访问端口", - "type": "integer" - }, - "Host": { - "description": "Host is the hostname or IP address of the service.", - "type": "string" - }, - "Port": { - "description": "端口", - "type": "integer" - }, - "ServerBindAddr": { - "description": "ListenAndServe to bind to, such as 0.0.0.0", - "type": "string" - }, - "Timeout": { - "description": "Timeout specifies a timeout (in milliseconds)", - "type": "integer" - } - } - }, - "configstc.ThirdConfig": { - "type": "object", - "properties": { - "AppKey": { - "description": "app id/key", - "type": "string" - }, - "AppSecret": { - "description": "appSecret", - "type": "string" - }, - "Enable": { - "description": "是否启用第三方", - "type": "boolean" - }, - "ExtendParams": { - "description": "扩展参数,微信: EncodingAESKey", - "allOf": [ - { - "$ref": "#/definitions/configstc.CommonExtendParams" - } - ] - } - } - }, - "configstc.UserAppConfig": { - "type": "object", - "properties": { - "AdminAuthConfig": { - "description": "授权配置(管理站)", - "allOf": [ - { - "$ref": "#/definitions/configstc.AuthConfig" - } - ] - }, - "ApiServer": { - "description": "作为api服务器", - "allOf": [ - { - "$ref": "#/definitions/configstc.ServerConfig" - } - ] - }, - "AuthConfig": { - "description": "授权配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.AuthConfig" - } - ] - }, - "AuthRegister": { - "description": "是否支持注册", - "type": "boolean" - }, - "AutoCreateUser": { - "description": "自动创建用户列表", - "type": "array", - "items": { - "$ref": "#/definitions/configstc.CreateUserConfig" - } - }, - "DBConfig": { - "description": "数据库配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.DBConfig" - } - ] - }, - "Debug": { - "description": "debug开关", - "type": "boolean" - }, - "DocsEnable": { - "description": "是否启用文档", - "type": "boolean" - }, - "EmailConfig": { - "description": "邮件配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.EmailConfig" - } - ] - }, - "LimitingApi": { - "description": "api限流", - "allOf": [ - { - "$ref": "#/definitions/configstc.LimitingConfig" - } - ] - }, - "LogLevel": { - "type": "string" - }, - "LogPath": { - "description": "日志路径", - "type": "string" - }, - "ModuleMode": { - "description": "模块模式,作为module使用", - "type": "boolean" - }, - "Name": { - "type": "string" - }, - "PProfEnable": { - "description": "是否启用pprof", - "type": "boolean" - }, - "PasswordSalt": { - "description": "密码salt", - "type": "string" - }, - "RoutePrefix": { - "description": "路由前缀", - "type": "string" - }, - "RpcServer": { - "description": "作为rpc服务器", - "allOf": [ - { - "$ref": "#/definitions/configstc.ServerConfig" - } - ] - }, - "SmsConfig": { - "description": "短信配置,目前使用阿里云", - "allOf": [ - { - "$ref": "#/definitions/configstc.ThirdConfig" - } - ] - }, - "WechatAuth": { - "description": "微信配置", - "allOf": [ - { - "$ref": "#/definitions/configstc.ThirdConfig" - } - ] - } - } - }, - "models.User": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "email": { - "description": "email", - "type": "string" - }, - "id": { - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "description": "昵称", - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "salt": { - "description": "密码盐", - "type": "string" - }, - "sex": { - "description": "性别,0:未知,1:男,2:女", - "type": "integer" - }, - "status": { - "type": "integer" - }, - "tenant_id": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "models.UserLoginRecord": { - "type": "object", - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "description": "=0未删除,\u003e0为删除时间", - "type": "integer" - }, - "id": { - "type": "integer" - }, - "last_device": { - "description": "操作设备", - "type": "string" - }, - "last_ip": { - "type": "string" - }, - "last_locate": { - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "remark": { - "type": "string" - }, - "uid": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - } - }, - "paginate.Pager": { - "type": "object", - "properties": { - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_count": { - "description": "总页数", - "type": "integer" - }, - "paging_id": { - "description": "分页用id,用于辅助分页用,可为主键id值", - "type": "integer" - }, - "size": { - "description": "单页数量", - "type": "integer" - }, - "total": { - "description": "总条数", - "type": "integer" - } - } - }, - "reqdata.AddEditUserReq": { - "type": "object", - "properties": { - "account": { - "description": "账户", - "type": "string", - "example": "demo" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "" - }, - "id": { - "description": "id,\u003e0为编辑对应,=0为新增", - "type": "integer", - "example": 0 - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "user123" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号", - "type": "string", - "example": "13699991234" - }, - "status": { - "description": "状态", - "type": "integer", - "example": 1 - } - } - }, - "reqdata.AuthReq": { - "type": "object", - "properties": { - "account": { - "description": "账户名", - "type": "string", - "example": "13488886666" - }, - "captcha_code": { - "description": "验证码", - "type": "string", - "example": "123456" - }, - "captcha_key": { - "description": "验证码key", - "type": "string", - "example": "xxxx" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.DetailReq": { - "type": "object", - "properties": { - "id": { - "description": "数据id", - "type": "integer", - "example": 0 - }, - "ids": { - "description": "多个数据id", - "type": "array", - "items": { - "type": "integer" - }, - "example": [ - 1, - 2 - ] - } - } - }, - "reqdata.ModifyInfoReq": { - "type": "object", - "properties": { - "avatar": { - "description": "头像", - "type": "string", - "example": "xxx" - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo" - }, - "sex": { - "description": "性别", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.ModifyPasswordReq": { - "type": "object", - "properties": { - "old_password": { - "description": "旧密码", - "type": "string", - "example": "123456" - }, - "password": { - "description": "新密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.PhoneEmailSendReq": { - "type": "object", - "properties": { - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - } - } - }, - "reqdata.PhoneEmailVerifyReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "123456" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - } - } - }, - "reqdata.RegisterReq": { - "type": "object", - "properties": { - "account": { - "description": "账户密码", - "type": "string", - "example": "13488886666" - }, - "avatar": { - "description": "头像", - "type": "string", - "example": "xxx" - }, - "code": { - "type": "string", - "example": "123456" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "nickname": { - "description": "昵称", - "type": "string", - "example": "demo" - }, - "password": { - "description": "密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - }, - "sex": { - "description": "性别", - "type": "integer", - "example": 0 - } - } - }, - "reqdata.ResetPasswordReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "123456" - }, - "email": { - "description": "邮箱", - "type": "string", - "example": "123@qq.com" - }, - "password": { - "description": "新密码", - "type": "string", - "example": "123456" - }, - "phone": { - "description": "手机号,都传的情况下优先手机号", - "type": "string", - "example": "13488886666" - } - } - }, - "reqdata.ResetUserPasswdReq": { - "type": "object", - "properties": { - "admin_password": { - "description": "当前管理员密码,可不填", - "type": "string", - "example": "123456" - }, - "id": { - "description": "指定用户id", - "type": "integer", - "example": 0 - }, - "password": { - "description": "重置的新密码", - "type": "string", - "example": "123456" - } - } - }, - "reqdata.SearchLoginRecordReq": { - "type": "object", - "properties": { - "keywords": { - "description": "关键字搜索", - "type": "string", - "example": "m" - }, - "page": { - "description": "分页-页码", - "type": "integer", - "example": 1 - }, - "size": { - "description": "分页-条数", - "type": "integer", - "example": 20 - } - } - }, - "reqdata.SearchUserParam": { - "type": "object", - "properties": { - "keywords": { - "type": "string", - "example": "d" - }, - "page": { - "type": "integer", - "example": 1 - }, - "size": { - "type": "integer", - "example": 10 - }, - "status": { - "type": "integer", - "example": 0 - } - } - }, - "reqdata.SetStatusReq": { - "type": "object", - "properties": { - "id": { - "description": "id", - "type": "integer" - }, - "status": { - "description": "状态", - "type": "integer" - } - } - }, - "reqdata.ThirdAuthReq": { - "type": "object", - "properties": { - "code": { - "type": "string", - "example": "123456" - } - } - }, - "respdata.AuthResp": { - "type": "object", - "properties": { - "auth": { - "description": "授权信息", - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "extends": { - "description": "额外信息", - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "nickname": { - "type": "string" - }, - "saas_id": { - "description": "saas模式下用到的归属租户id", - "type": "integer" - }, - "saas_name": { - "description": "saas模式下用到的归属租户的名称", - "type": "string" - }, - "status": { - "type": "integer" - } - } - }, - "expired_at": { - "description": "过期时间戳,秒级", - "type": "integer" - }, - "token": { - "description": "授权凭证", - "type": "string" - } - } - }, - "respdata.CaptchaResponse": { - "type": "object", - "properties": { - "img": { - "type": "string" - }, - "key": { - "type": "string" - } - } - }, - "respdata.DetailResp": { - "type": "object", - "properties": { - "id": { - "description": "指定编辑的对象id", - "type": "integer" - } - } - }, - "respdata.QueryUserResp": { - "type": "object", - "properties": { - "account": { - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "email": { - "description": "email", - "type": "string" - }, - "id": { - "type": "integer" - }, - "last_ip": { - "description": "上次登录ip", - "type": "string" - }, - "last_login": { - "description": "上次登录时间", - "type": "string" - }, - "nickname": { - "description": "昵称", - "type": "string" - }, - "phone": { - "description": "手机号", - "type": "string" - }, - "sex": { - "description": "性别,0:未知,1:男,2:女", - "type": "integer" - }, - "status": { - "type": "integer" - }, - "third_binds": { - "description": "第三方绑定列表", - "type": "array", - "items": { - "$ref": "#/definitions/respdata.UserThirdInfo" - } - }, - "updated_at": { - "type": "string" - } - } - }, - "respdata.ResponseData": { - "type": "object", - "properties": { - "code": { - "description": "返回码,0:成功,\u003e0为对应错误码", - "type": "integer" - }, - "data": {}, - "msg": { - "type": "string" - } - } - }, - "respdata.SearchListResponse": { - "type": "object", - "properties": { - "list": { - "description": "列表" - }, - "paginate": { - "description": "分页信息", - "allOf": [ - { - "$ref": "#/definitions/paginate.Pager" - } - ] - } - } - }, - "respdata.SmsCodeSendResp": { - "type": "object", - "properties": { - "target": { - "description": "发送目标,可为手机号/邮箱", - "type": "string", - "example": "13488886666" - }, - "valid_minute": { - "description": "有效分钟数,单位:分钟", - "type": "integer", - "example": 33 - } - } - }, - "respdata.SmsCodeVerifyResp": { - "type": "object", - "properties": { - "success": { - "description": "是否验证成功", - "type": "boolean" - }, - "target": { - "description": "发送目标,可为手机号/邮箱", - "type": "string", - "example": "13488886666" - } - } - }, - "respdata.UserThirdInfo": { - "type": "object", - "properties": { - "avatar": { - "type": "string" - }, - "email": { - "type": "string" - }, - "extend_info": { - "description": "拓展信息,可以存json", - "type": "string" - }, - "id": { - "type": "integer" - }, - "nickname": { - "type": "string" - }, - "phone": { - "description": "额外可获取的用户信息", - "type": "string" - }, - "third_id": { - "description": "第三方id", - "type": "string" - }, - "third_type": { - "description": "第三方类型", - "type": "string" - }, - "third_union_id": { - "description": "第三方union id", - "type": "string" - }, - "uid": { - "type": "integer" - } - } - } - }, - "securityDefinitions": { - "ApiKeyAuth": { - "description": "Api-Token, Header: Authorization", - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" - } -} \ No newline at end of file diff --git a/src/apps/userapp/docs/userservice_swagger.yaml b/src/apps/userapp/docs/userservice_swagger.yaml deleted file mode 100644 index b3838ed176601d922df645c489de877a50f07eb5..0000000000000000000000000000000000000000 --- a/src/apps/userapp/docs/userservice_swagger.yaml +++ /dev/null @@ -1,1371 +0,0 @@ -basePath: / -definitions: - configstc.AuthConfig: - properties: - AuthExpired: - description: 授权失效时间,单位:秒 - type: integer - Enable: - description: 是否启用 - type: boolean - SecretKey: - description: 加密秘钥,如JWT - type: string - type: object - configstc.CommonExtendParams: - additionalProperties: - type: string - type: object - configstc.CreateUserConfig: - properties: - Account: - description: 账户 - type: string - Password: - description: 密码 - type: string - UserName: - description: 用户名 - type: string - type: object - configstc.DBConfig: - properties: - ConnMaxIdleTime: - default: 0 - description: 每个链接最大空闲时间 - type: integer - ConnMaxLifeTime: - default: 0 - description: 每个链接最大生存时间 - type: integer - DbConn: - description: 数据库类型,如mysql - type: string - DbDsn: - description: 数据库dsn - type: string - DbHost: - description: 数据库地址 - type: string - DbName: - description: 数据库 - type: string - DbPassword: - description: 密码 - type: string - DbPort: - description: 端口 - type: string - DbUser: - description: 用户名 - type: string - MaxConcatLen: - type: string - MaxIdleConn: - default: 0 - description: 预留并发链接数 - type: integer - MaxOpenConn: - default: 0 - description: 最大支持链接 - type: integer - TablePrefix: - description: 表前缀 - type: string - TimeZone: - description: 时区设置 - type: string - type: object - configstc.EmailConfig: - properties: - Enable: - type: boolean - SmtpHost: - description: smtp服务host - type: string - SmtpName: - description: smtp 发送名称 - type: string - SmtpPassword: - description: smtp密码 - type: string - SmtpPort: - description: smtp服务端口 - type: integer - SmtpUserName: - description: smtp用户名 - type: string - type: object - configstc.LimitingConfig: - properties: - MaxRate: - description: 允许的最大速率 - type: integer - PerRate: - description: 每次(秒)速率 - type: integer - type: object - configstc.ServerConfig: - properties: - AllowOrigins: - description: 指定跨域允许访问源,空则为不限制访问 - items: - type: string - type: array - Enable: - description: 是否启用 - type: boolean - EndpointAddr: - description: 对外访问地址 - type: string - EndpointPort: - description: 对外访问端口 - type: integer - Host: - description: Host is the hostname or IP address of the service. - type: string - Port: - description: 端口 - type: integer - ServerBindAddr: - description: ListenAndServe to bind to, such as 0.0.0.0 - type: string - Timeout: - description: Timeout specifies a timeout (in milliseconds) - type: integer - type: object - configstc.ThirdConfig: - properties: - AppKey: - description: app id/key - type: string - AppSecret: - description: appSecret - type: string - Enable: - description: 是否启用第三方 - type: boolean - ExtendParams: - allOf: - - $ref: '#/definitions/configstc.CommonExtendParams' - description: 扩展参数,微信: EncodingAESKey - type: object - configstc.UserAppConfig: - properties: - AdminAuthConfig: - allOf: - - $ref: '#/definitions/configstc.AuthConfig' - description: 授权配置(管理站) - ApiServer: - allOf: - - $ref: '#/definitions/configstc.ServerConfig' - description: 作为api服务器 - AuthConfig: - allOf: - - $ref: '#/definitions/configstc.AuthConfig' - description: 授权配置 - AuthRegister: - description: 是否支持注册 - type: boolean - AutoCreateUser: - description: 自动创建用户列表 - items: - $ref: '#/definitions/configstc.CreateUserConfig' - type: array - DBConfig: - allOf: - - $ref: '#/definitions/configstc.DBConfig' - description: 数据库配置 - Debug: - description: debug开关 - type: boolean - DocsEnable: - description: 是否启用文档 - type: boolean - EmailConfig: - allOf: - - $ref: '#/definitions/configstc.EmailConfig' - description: 邮件配置 - LimitingApi: - allOf: - - $ref: '#/definitions/configstc.LimitingConfig' - description: api限流 - LogLevel: - type: string - LogPath: - description: 日志路径 - type: string - ModuleMode: - description: 模块模式,作为module使用 - type: boolean - Name: - type: string - PProfEnable: - description: 是否启用pprof - type: boolean - PasswordSalt: - description: 密码salt - type: string - RoutePrefix: - description: 路由前缀 - type: string - RpcServer: - allOf: - - $ref: '#/definitions/configstc.ServerConfig' - description: 作为rpc服务器 - SmsConfig: - allOf: - - $ref: '#/definitions/configstc.ThirdConfig' - description: 短信配置,目前使用阿里云 - WechatAuth: - allOf: - - $ref: '#/definitions/configstc.ThirdConfig' - description: 微信配置 - type: object - models.User: - properties: - account: - type: string - avatar: - description: 头像 - type: string - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - email: - description: email - type: string - id: - type: integer - last_ip: - description: 上次登录ip - type: string - last_login: - description: 上次登录时间 - type: string - nickname: - description: 昵称 - type: string - password: - type: string - phone: - description: 手机号 - type: string - salt: - description: 密码盐 - type: string - sex: - description: 性别,0:未知,1:男,2:女 - type: integer - status: - type: integer - tenant_id: - type: integer - updated_at: - type: string - type: object - models.UserLoginRecord: - properties: - created_at: - type: string - deleted_at: - description: =0未删除,>0为删除时间 - type: integer - id: - type: integer - last_device: - description: 操作设备 - type: string - last_ip: - type: string - last_locate: - type: string - last_login: - description: 上次登录时间 - type: string - remark: - type: string - uid: - type: integer - updated_at: - type: string - type: object - paginate.Pager: - properties: - page: - description: 当前页码 - type: integer - page_count: - description: 总页数 - type: integer - paging_id: - description: 分页用id,用于辅助分页用,可为主键id值 - type: integer - size: - description: 单页数量 - type: integer - total: - description: 总条数 - type: integer - type: object - reqdata.AddEditUserReq: - properties: - account: - description: 账户 - example: demo - type: string - email: - description: 邮箱 - example: "" - type: string - id: - description: id,>0为编辑对应,=0为新增 - example: 0 - type: integer - nickname: - description: 昵称 - example: user123 - type: string - password: - description: 密码 - example: "123456" - type: string - phone: - description: 手机号 - example: "13699991234" - type: string - status: - description: 状态 - example: 1 - type: integer - type: object - reqdata.AuthReq: - properties: - account: - description: 账户名 - example: "13488886666" - type: string - captcha_code: - description: 验证码 - example: "123456" - type: string - captcha_key: - description: 验证码key - example: xxxx - type: string - password: - description: 密码 - example: "123456" - type: string - type: object - reqdata.DetailReq: - properties: - id: - description: 数据id - example: 0 - type: integer - ids: - description: 多个数据id - example: - - 1 - - 2 - items: - type: integer - type: array - type: object - reqdata.ModifyInfoReq: - properties: - avatar: - description: 头像 - example: xxx - type: string - nickname: - description: 昵称 - example: demo - type: string - sex: - description: 性别 - example: 0 - type: integer - type: object - reqdata.ModifyPasswordReq: - properties: - old_password: - description: 旧密码 - example: "123456" - type: string - password: - description: 新密码 - example: "123456" - type: string - type: object - reqdata.PhoneEmailSendReq: - properties: - email: - description: 邮箱 - example: 123@qq.com - type: string - phone: - description: 手机号,都传的情况下优先手机号 - example: "13488886666" - type: string - type: object - reqdata.PhoneEmailVerifyReq: - properties: - code: - example: "123456" - type: string - email: - description: 邮箱 - example: 123@qq.com - type: string - phone: - description: 手机号,都传的情况下优先手机号 - example: "13488886666" - type: string - type: object - reqdata.RegisterReq: - properties: - account: - description: 账户密码 - example: "13488886666" - type: string - avatar: - description: 头像 - example: xxx - type: string - code: - example: "123456" - type: string - email: - description: 邮箱 - example: 123@qq.com - type: string - nickname: - description: 昵称 - example: demo - type: string - password: - description: 密码 - example: "123456" - type: string - phone: - description: 手机号,都传的情况下优先手机号 - example: "13488886666" - type: string - sex: - description: 性别 - example: 0 - type: integer - type: object - reqdata.ResetPasswordReq: - properties: - code: - example: "123456" - type: string - email: - description: 邮箱 - example: 123@qq.com - type: string - password: - description: 新密码 - example: "123456" - type: string - phone: - description: 手机号,都传的情况下优先手机号 - example: "13488886666" - type: string - type: object - reqdata.ResetUserPasswdReq: - properties: - admin_password: - description: 当前管理员密码,可不填 - example: "123456" - type: string - id: - description: 指定用户id - example: 0 - type: integer - password: - description: 重置的新密码 - example: "123456" - type: string - type: object - reqdata.SearchLoginRecordReq: - properties: - keywords: - description: 关键字搜索 - example: m - type: string - page: - description: 分页-页码 - example: 1 - type: integer - size: - description: 分页-条数 - example: 20 - type: integer - type: object - reqdata.SearchUserParam: - properties: - keywords: - example: d - type: string - page: - example: 1 - type: integer - size: - example: 10 - type: integer - status: - example: 0 - type: integer - type: object - reqdata.SetStatusReq: - properties: - id: - description: id - type: integer - status: - description: 状态 - type: integer - type: object - reqdata.ThirdAuthReq: - properties: - code: - example: "123456" - type: string - type: object - respdata.AuthResp: - properties: - auth: - description: 授权信息 - properties: - account: - type: string - avatar: - type: string - extends: - additionalProperties: - type: string - description: 额外信息 - type: object - id: - type: integer - nickname: - type: string - saas_id: - description: saas模式下用到的归属租户id - type: integer - saas_name: - description: saas模式下用到的归属租户的名称 - type: string - status: - type: integer - type: object - expired_at: - description: 过期时间戳,秒级 - type: integer - token: - description: 授权凭证 - type: string - type: object - respdata.CaptchaResponse: - properties: - img: - type: string - key: - type: string - type: object - respdata.DetailResp: - properties: - id: - description: 指定编辑的对象id - type: integer - type: object - respdata.QueryUserResp: - properties: - account: - type: string - avatar: - description: 头像 - type: string - created_at: - type: string - email: - description: email - type: string - id: - type: integer - last_ip: - description: 上次登录ip - type: string - last_login: - description: 上次登录时间 - type: string - nickname: - description: 昵称 - type: string - phone: - description: 手机号 - type: string - sex: - description: 性别,0:未知,1:男,2:女 - type: integer - status: - type: integer - third_binds: - description: 第三方绑定列表 - items: - $ref: '#/definitions/respdata.UserThirdInfo' - type: array - updated_at: - type: string - type: object - respdata.ResponseData: - properties: - code: - description: 返回码,0:成功,>0为对应错误码 - type: integer - data: {} - msg: - type: string - type: object - respdata.SearchListResponse: - properties: - list: - description: 列表 - paginate: - allOf: - - $ref: '#/definitions/paginate.Pager' - description: 分页信息 - type: object - respdata.SmsCodeSendResp: - properties: - target: - description: 发送目标,可为手机号/邮箱 - example: "13488886666" - type: string - valid_minute: - description: 有效分钟数,单位:分钟 - example: 33 - type: integer - type: object - respdata.SmsCodeVerifyResp: - properties: - success: - description: 是否验证成功 - type: boolean - target: - description: 发送目标,可为手机号/邮箱 - example: "13488886666" - type: string - type: object - respdata.UserThirdInfo: - properties: - avatar: - type: string - email: - type: string - extend_info: - description: 拓展信息,可以存json - type: string - id: - type: integer - nickname: - type: string - phone: - description: 额外可获取的用户信息 - type: string - third_id: - description: 第三方id - type: string - third_type: - description: 第三方类型 - type: string - third_union_id: - description: 第三方union id - type: string - uid: - type: integer - type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ -host: localhost:8080 -info: - contact: - email: sage12345678@qq.com - name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: User模块API - version: "1.0" -paths: - /-user-config: - post: - description: CONFIG-配置内容 - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/configstc.UserAppConfig' - type: array - summary: CONFIG-配置 - tags: - - user - /auth/fresh_token: - post: - description: 刷新授权token - produces: - - application/json - responses: - "200": - description: 刷新成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - "500": - description: 刷新失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: Auth-刷新授权 - tags: - - user.auth - x-response-apikey-token-set: - apiKey: ApiKeyAuth - tokenKey: response.data.token - /auth/info: - post: - description: 获取登录信息 - produces: - - application/json - responses: - "200": - description: 授权信息 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - security: - - ApiKeyAuth: [] - summary: Auth-登录信息 - tags: - - user.auth - /auth/login: - post: - description: 登录 - parameters: - - description: 账户信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.AuthReq' - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: Auth-授权登录 - tags: - - user.auth - x-response-apikey-token-set: - apiKey: ApiKeyAuth - tokenKey: response.data.token - /auth/logout: - post: - description: 取消授权 - produces: - - application/json - responses: - "200": - description: 取消成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 取消失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: Auth-取消授权 - tags: - - user.auth - /auth/qq_code: - post: - description: 第三方登录-QQ - parameters: - - description: 第三方授权码 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.ThirdAuthReq' - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: Auth-QQ授权登录 - tags: - - user.auth - x-response-apikey-token-set: - apiKey: ApiKeyAuth - tokenKey: response.data.token - /auth/register: - post: - consumes: - - application/json - description: 注册账户(账户/密码) - parameters: - - description: 注册信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.RegisterReq' - produces: - - application/json - responses: - "0": - description: 注册成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: 注册账户 - tags: - - user.auth - /auth/wechat_code: - post: - description: 第三方登录-微信 - parameters: - - description: 第三方授权码 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.ThirdAuthReq' - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: Auth-微信code授权 - tags: - - user.auth - x-response-apikey-token-set: - apiKey: ApiKeyAuth - tokenKey: response.data.token - /captcha/get: - post: - description: 验证码生成图片 - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.CaptchaResponse' - type: object - "1": - description: 获取失败 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - code: - type: integer - type: object - summary: 验证码图片 - tags: - - user.other - /debug/auth/third: - post: - description: 第三方登录-微信 - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.AuthResp' - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: '[DEBUG]第三方授权' - tags: - - user.auth - x-response-apikey-token-set: - apiKey: ApiKeyAuth - tokenKey: response.data.token - /mag/user/delete: - post: - description: 删除指定用户 - parameters: - - description: 指定用户id - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "0": - description: 成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 用户管理-删除用户 - tags: - - admin.user - /mag/user/detail: - post: - description: 查询单个用户的详细信息 - parameters: - - description: 查询指定id详情 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.DetailReq' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.QueryUserResp' - type: object - "2": - description: 系统繁忙 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数无效 - schema: - $ref: '#/definitions/respdata.ResponseData' - "10": - description: 未查询到 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 用户管理-详情 - tags: - - admin.user - /mag/user/disable: - post: - consumes: - - application/json - description: 操作启用/禁用用户 - parameters: - - description: 状态设置请求 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SetStatusReq' - produces: - - application/json - responses: - "200": - description: 设置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 用户管理-启用/禁用 - tags: - - admin.user - /mag/user/reset_password: - post: - consumes: - - application/json - description: 密码重置 - parameters: - - description: 重置密码请求 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.ResetUserPasswdReq' - produces: - - application/json - responses: - "200": - description: 成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 用户管理-重置密码 - tags: - - admin.user - /mag/user/save: - post: - description: 创建或编辑用户 - parameters: - - description: 提交用户信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.AddEditUserReq' - produces: - - application/json - responses: - "0": - description: 保存成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.DetailResp' - type: object - "2": - description: 系统繁忙 - schema: - $ref: '#/definitions/respdata.ResponseData' - "4": - description: 参数无效 - schema: - $ref: '#/definitions/respdata.ResponseData' - "10": - description: 未查询到 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - AdminKeyAuth: [] - summary: 用户管理-保存 - tags: - - admin.user - /mag/user/search: - post: - description: 用户列表展示和搜索 - parameters: - - description: 搜索参数集 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchUserParam' - produces: - - application/json - responses: - "0": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/models.User' - type: array - type: object - type: object - security: - - AdminKeyAuth: [] - summary: 用户管理-列表 - tags: - - admin.user - /u_center/bind: - post: - description: 绑定邮箱/手机 - parameters: - - description: 验证信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.PhoneEmailVerifyReq' - produces: - - application/json - responses: - "200": - description: 绑定成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 绑定失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 用户中心-绑定邮箱/手机 - tags: - - user - /u_center/info: - post: - description: 用户信息,比AuthInfo提供信息更详细 - produces: - - application/json - responses: - "0": - description: 重置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 用户信息 - tags: - - user - /u_center/login_record: - post: - description: 登录历史记录 - parameters: - - description: 搜索参数集 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.SearchLoginRecordReq' - produces: - - application/json - responses: - "200": - description: 获取成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - allOf: - - $ref: '#/definitions/respdata.SearchListResponse' - - properties: - list: - items: - $ref: '#/definitions/models.UserLoginRecord' - type: array - type: object - type: object - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 用户中心-历史登录记录 - tags: - - user - /u_center/modify_info: - post: - description: 修改个人信息 - parameters: - - description: 账户信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.ModifyInfoReq' - produces: - - application/json - responses: - "200": - description: 授权成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - "500": - description: 授权失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 用户中心-修改个人信息 - tags: - - user - /u_center/modify_pwd: - post: - description: 授权登录后修改密码 - parameters: - - description: 修改密码 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.ModifyPasswordReq' - produces: - - application/json - responses: - "0": - description: 修改成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 用户中心-修改密码 - tags: - - user - /u_center/reset_pwd: - post: - description: 忘记密码场景下重置密码 - parameters: - - description: 重置密码 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.ResetPasswordReq' - produces: - - application/json - responses: - "0": - description: 重置成功 - schema: - $ref: '#/definitions/respdata.ResponseData' - summary: 忘记密码 - tags: - - user - /verify_code/send: - post: - description: 发送短信验证码 - parameters: - - description: 发送对象信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.PhoneEmailSendReq' - produces: - - application/json - responses: - "200": - description: 发送成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.SmsCodeSendResp' - type: object - "500": - description: 发送失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 短信验证码-发送 - tags: - - user.other - /verify_code/verify: - post: - description: 校验短信验证码 - parameters: - - description: 验证信息 - in: body - name: param - required: true - schema: - $ref: '#/definitions/reqdata.PhoneEmailVerifyReq' - produces: - - application/json - responses: - "0": - description: 验证成功 - schema: - allOf: - - $ref: '#/definitions/respdata.ResponseData' - - properties: - data: - $ref: '#/definitions/respdata.SmsCodeVerifyResp' - type: object - "5": - description: 验证失败 - schema: - $ref: '#/definitions/respdata.ResponseData' - security: - - ApiKeyAuth: [] - summary: 短信验证码-校验 - tags: - - user.other -produces: -- application/json -- text/html -schemes: -- http -- https -securityDefinitions: - ApiKeyAuth: - description: 'Api-Token, Header: Authorization' - in: header - name: Authorization - type: apiKey - BasicAuth: - type: basic -swagger: "2.0" diff --git a/src/apps/userapp/gen_docs.sh b/src/apps/userapp/gen_docs.sh deleted file mode 100644 index 09e54e5e7d70749d75000005375f86804f28534b..0000000000000000000000000000000000000000 --- a/src/apps/userapp/gen_docs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -swag init -g app.go --parseDependency --parseInternal --instanceName userservice - - - - - - - - diff --git a/src/apps/userapp/rpc_server.go b/src/apps/userapp/rpc_server.go deleted file mode 100644 index 96983957016cb03ab2666a4c9335f4885495a666..0000000000000000000000000000000000000000 --- a/src/apps/userapp/rpc_server.go +++ /dev/null @@ -1,114 +0,0 @@ -package userapp - -import ( - "context" - "fmt" - grpcController "gitee.com/captials-team/ubdframe/src/apps/userapp/controllers/grpc" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - etcdlib "gitee.com/captials-team/ubdframe/src/infrastructure/clients/etcd" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/uber_help" - pbService "gitee.com/captials-team/ubdframe/src/protobufs/pb/service" - "go.uber.org/dig" - "google.golang.org/grpc" - "net" -) - -type RpcServer struct { - di *dig.Container - conf *configstc.UserAppConfig - - server *grpc.Server - module bool //是否作为模块服务 - l v1log.ILog -} - -func (s *RpcServer) RegisterService() error { - return s.registerServices(s.server) -} - -func (s *RpcServer) RegisterServiceForGRpc(server *grpc.Server) error { - return s.registerServices(server) -} - -func (s *RpcServer) registerServices(server *grpc.Server) error { - - common.ErrPanic(s.di.Invoke(func(authService pbService.UserServiceServer) { - pbService.RegisterUserServiceServer(server, authService) - })) - - return nil -} - -func (s *RpcServer) WithModule(t bool) { - s.module = t -} - -func (s *RpcServer) Start() error { - //作为模块不启动相关服务 - if s.module { - return nil - } - - //注册服务 - s.RegisterService() - - //使用注册服务-etcd - etcdAddr := "" - //etcdAddr = "127.0.0.1:2379" // 临时测试 - if len(etcdAddr) > 0 { - srName := "setting_sr" - - sr := etcdlib.RegisterService( - etcdAddr, - srName, - s.conf.RpcServer.Endpoint(), 5) - go sr.ListenLease() - defer sr.Close() - s.l.Info("use discovery etcd %s", etcdAddr) - } - //启动服务 - lisAddr := s.conf.RpcServer.ListenAddr() - //监听端口 - lis, err := net.Listen("tcp", lisAddr) - common.ErrPanic(err) - defer lis.Close() - - s.l.Info("RPC running at %s", lisAddr) - defer s.l.Warn("RPC running complete") - return s.server.Serve(lis) -} - -func (s *RpcServer) Stop() error { - s.server.Stop() - defer s.l.Warn("RPC stop") - return nil -} - -func (s *RpcServer) interceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { - fmt.Println("token interceptor") - fmt.Println("\t", req) - fmt.Println("\t", info) - - return handler(ctx, req) -} - -func NewRpcServer(di *dig.Container, conf *configstc.UserAppConfig, logger v1log.ILog) *RpcServer { - s := &RpcServer{ - di: di, - conf: conf, - l: logger, - } - - common.ErrPanic(di.Provide(grpcController.NewAuthServiceServer, dig.As(new(pbService.UserServiceServer))), uber_help.ErrAlreadyProvided) - - //启动 - server := grpc.NewServer( - grpc.UnaryInterceptor(s.interceptor), //拦截器 - ) - - s.server = server - - return s -} diff --git a/src/apps/webapp/README.md b/src/apps/webapp/README.md deleted file mode 100644 index 62a218cf69af59ea48259b99cadf5078940f7879..0000000000000000000000000000000000000000 --- a/src/apps/webapp/README.md +++ /dev/null @@ -1,17 +0,0 @@ - - -# WebApp - -支持web渲染功能,代理转发功能 - - - -### 支持功能 - -目前支持功能: - -- 静态文件渲染 -- 模板Template文件渲染 -- Proxy转发,支持前缀替换、完全匹配的方式进行匹配转发 - - diff --git a/src/apps/webapp/api_server.go b/src/apps/webapp/api_server.go deleted file mode 100644 index e893dcf7b187b5ff356e939e6c0e70cdfc884f54..0000000000000000000000000000000000000000 --- a/src/apps/webapp/api_server.go +++ /dev/null @@ -1,176 +0,0 @@ -package webapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/proxyhandler" - httplibs "gitee.com/captials-team/ubdframe/src/pkg/viewhandler" - "github.com/gin-contrib/static" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "html/template" - "net/http" -) - -type ApiServer struct { - *apps.ApiServer - di *dig.Container - conf *configstc.WebAppConfig - l v1log.ILog - - gin_http.CorsOption - - funcMaps []template.FuncMap - - templateParamFunc func(*http.Request) string -} - -func (s *ApiServer) Name() string { - return "web_server" -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.regRouter(s.Engine()) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - s.regRouter(engine) -} - -// regRouter 注册路由 -func (s *ApiServer) regRouter(engine *gin.Engine) { - //默认增加跨域 - //已通过 ApiServer.WithCors() 跨域 - //if !s.NoCors { - // corsConfig := cors.DefaultConfig() - // corsConfig.AllowOrigins = []string{"*"} - // corsConfig.AllowHeaders = []string{"*"} - // corsConfig.OptionsResponseStatusCode = http.StatusOK - // engine.Use(cors.New(corsConfig)) - //} - - //proxy和staticServe不可使用engine.Group功能 - s._regProxyRouter(engine) - s._regStaticRouter(engine) - s._regTemplateEngine(engine) - - return -} - -// _regStaticRouter 静态文件支持 -func (s *ApiServer) _regStaticRouter(engine *gin.Engine) { - prefix := "/" - if s.conf.RoutePrefix != "" { - prefix = s.conf.RoutePrefix - } - prefix = utils.KeepHasPrefix(prefix, "/") - if s.conf.StaticRouter != "" { - prefix = s.conf.StaticRouter - } else { - prefix = prefix + "/static" - } - //静态文件 - //访问地址: http://{DOMAIN}/{prefix} - - path := s.conf.StaticPath - if path == "" { - s.l.Warn("[Web Static] No Configured %s", path) - return - } - if !utils.FilePathExist(path) { - panic("[Web Static] Dir Not Exist " + path) - } - engine.Use(static.ServeRoot(prefix, path)) - s.l.Info("[Web Static] %s\t\t--> %s", prefix, path) - - return -} - -// _regProxyRouter 转发路由 -func (s *ApiServer) _regProxyRouter(engine *gin.Engine) { - //转发Proxy功能 - engine.Use(proxyhandler.ProxyHandler(proxyhandler.NewProxyGroup(s.conf.ProxyRules...)...)) - return -} - -// _regTemplateEngine 模板引擎支持 -func (s *ApiServer) _regTemplateEngine(engine *gin.Engine) { - prefix := "/" - tplPath := s.conf.TemplatePath - - if s.conf.RoutePrefix != "" { - prefix = s.conf.RoutePrefix - } - - prefix = utils.KeepHasPrefix(prefix, "/") - if s.conf.TemplateRouter != "" { - prefix = s.conf.TemplateRouter - } else { - prefix = prefix + "/views" - } - - //目录存在才配置 - path := s.conf.TemplatePath - if path == "" || !utils.FilePathExist(path) { - s.l.Warn("[Web Template] Not Configure %s", path) - return - } - //自定义设置渲染器 - viewConfig := httplibs.DefaultViewHandlerConfig - //viewConfig.ViewFs = viewFs - viewConfig.ViewDir = tplPath - viewConfig.FuncMaps = s.funcMaps - - viewConfig.ParamFunc = s.templateParamFunc - //可指定ParamFunc - // 示例:可从get参数 r 来指定模板解析名称,此时访问地址应为: xxx/views?r=index.html - //viewConfig.ParamFunc = func(r *http.Request) string { - // err := r.ParseForm() - // s.l.Ctl(err != nil).Error("ParseForm %s", err) - // return r.FormValue("r") - //} - - viewHandler := httplibs.NewViewHandler(viewConfig) - viewHandler.AddLogger(s.l) - viewHandler.InitiateRender() - viewHandler.GinRouterJump(engine, prefix) - s.l.Info("[Web Template] %s\t\t--> %s", prefix, path) - return -} - -func (s *ApiServer) AddFuncMap(funcs ...template.FuncMap) { - s.funcMaps = append(s.funcMaps, funcs...) -} - -func (s *ApiServer) SetTemplateParseFunc(f func(r *http.Request) string) { - s.templateParamFunc = f -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Container, conf *configstc.WebAppConfig, logger v1log.ILog) *ApiServer { - s := &ApiServer{ - di: di, - conf: conf, - l: logger, - ApiServer: apps.NewApiServer(gin.Default(), conf.WebServer), - } - - s.WithName(conf.Name) - s.WithCors() //开启跨域设置 - - return s -} diff --git a/src/apps/webapp/app.go b/src/apps/webapp/app.go deleted file mode 100644 index fde7764c9424c2e2949d04365fdd2bc8c8c9fdc4..0000000000000000000000000000000000000000 --- a/src/apps/webapp/app.go +++ /dev/null @@ -1,59 +0,0 @@ -// @title Web模块API -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email sage12345678@qq.com - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath / -// @schemes http https -// @produce json,html - -// @securityDefinitions.basic BasicAuth - -// @securityDefinitions.apikey ApiKeyAuth -// @in header -// @name Authorization -// @description Api-Token, Header: Authorization - -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ -package webapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" -) - -type App struct { - *apps.App - - di *dig.Container - Conf *configstc.WebAppConfig - ApiServer *ApiServer -} - -func NewApp(di *dig.Container, conf *configstc.WebAppConfig, logger v1log.ILog) *App { - app := &App{ - di: di, - Conf: conf, - App: apps.NewApp(di, "web_app"), - } - common.ErrPanic(di.Provide(NewApiServer)) - - common.ErrPanic(di.Invoke(func(api *ApiServer) { - app.WithApiServer(api) - app.ApiServer = api - })) - - return app -} diff --git a/src/apps/webapp/config.go b/src/apps/webapp/config.go deleted file mode 100644 index b67b376ee2b1480536b1162d4e7ccdd99c407f09..0000000000000000000000000000000000000000 --- a/src/apps/webapp/config.go +++ /dev/null @@ -1,16 +0,0 @@ -package webapp - -import ( - "gitee.com/captials-team/ubdframe/src/domain/configstc" -) - -// NewConfig godoc -// @Summary CONFIG-配置 -// @Description CONFIG-配置内容 -// @Tags web -// @Produce json -// @Success 200 {array} configstc.WebAppConfig -// @Router /-web-config [post] -func NewConfig() *configstc.WebAppConfig { - return configstc.LoadConfig(new(configstc.WebAppConfig)) -} diff --git a/src/apps/wssapp/api_server.go b/src/apps/wssapp/api_server.go deleted file mode 100644 index d0b4c7a94433d1e2d6fd2eac036d4e74e8283b4f..0000000000000000000000000000000000000000 --- a/src/apps/wssapp/api_server.go +++ /dev/null @@ -1,89 +0,0 @@ -package wssapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - "gitee.com/captials-team/ubdframe/src/pkg/gin_http" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "github.com/gin-gonic/gin" - "go.uber.org/dig" - "net/http" -) - -type ApiServer struct { - *apps.ApiServer - di *dig.Container - conf *configstc.WebsocketAppConfig - l v1log.ILog - - wsConnectEntry http.HandlerFunc //连接入口处理func - - gin_http.CorsOption -} - -func (s *ApiServer) Name() string { - return "wss_server" -} - -func (s *ApiServer) SetWsHandler(f http.HandlerFunc) { - s.wsConnectEntry = f -} - -func (s *ApiServer) InitRouter() { - s.Engine().GET("ping", gin_http.PingHandler) - s.InitRouterForGin(s.Engine()) -} - -func (s *ApiServer) InitRouterForGin(engine *gin.Engine) { - var g = engine.Group("") - if len(s.conf.RoutePrefix) > 0 { - g = engine.Group(s.conf.RoutePrefix) - } - - s.router(g) - - return -} - -func (s *ApiServer) router(g gin.IRouter) { - g.Use( - gin_http.PanicHandler, - gin_http.QPSLimiterHandler(10, 10), - ) - - //websocket - common.ErrPanic(s.di.Invoke(func() { - g.GET("/ws/online", func(ctx *gin.Context) { - if s.wsConnectEntry != nil { - s.wsConnectEntry(ctx.Writer, ctx.Request) - } - s.l.Warn("ws online not support") - ctx.String(http.StatusNotFound, "") - }) - })) -} - -func (s *ApiServer) Start() error { - if !s.Module() { - s.InitRouter() - } - return s.ApiServer.Start() -} - -func (s *ApiServer) Stop() error { - return s.ApiServer.Stop() -} - -func NewApiServer(di *dig.Container, conf *configstc.WebsocketAppConfig, logger v1log.ILog) *ApiServer { - s := &ApiServer{ - di: di, - conf: conf, - l: logger, - ApiServer: apps.NewApiServer(gin.Default(), conf.ApiServer), - } - - s.ApiServer.WithCors() - - return s -} diff --git a/src/apps/wssapp/app.go b/src/apps/wssapp/app.go deleted file mode 100644 index eb78e70a7511a52eb3d52f7568210a787c72f73c..0000000000000000000000000000000000000000 --- a/src/apps/wssapp/app.go +++ /dev/null @@ -1,59 +0,0 @@ -package wssapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps" - "gitee.com/captials-team/ubdframe/src/apps/wssapp/workers" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/wsserver" - "go.uber.org/dig" -) - -type App struct { - *apps.App - - di *dig.Container - Conf *configstc.WebsocketAppConfig - - ApiServer *ApiServer - Hub *wsserver.Hub - WorkerMgr *workers.WorkerMgr -} - -func NewApp(di *dig.Container, conf *configstc.WebsocketAppConfig) *App { - app := &App{ - di: di, - Conf: conf, - App: apps.NewApp(di, "websocket_app"), - } - - logger := v1log.NewZapLog("websocket_app", conf.LogPath) - - common.ErrPanic(di.Provide(NewApiServer)) - - wsserver.SetMessageSize(2048 * 1000) - wsserver.SetLogger(logger.CallerSkip(-1)) - - common.ErrPanic(di.Provide(wsserver.NewHub)) - common.ErrPanic(di.Provide(workers.NewWorkerMgr)) - - common.ErrPanic(di.Invoke(func(api *ApiServer, hub *wsserver.Hub, mgr *workers.WorkerMgr) { - api.SetWsHandler(hub.ServeHTTP) - - mgr.AddWorker("log", workers.NewLogWorker(di, logger)) - hub.SetWorker(mgr) - })) - - common.ErrPanic(di.Invoke(func(api *ApiServer, hub *wsserver.Hub, mgr *workers.WorkerMgr) { - app.WithApiServer(api) - app.ApiServer = api - - app.WithWorker(hub) - app.Hub = hub - - app.WorkerMgr = mgr - })) - - return app -} diff --git a/src/apps/wssapp/app_test.go b/src/apps/wssapp/app_test.go deleted file mode 100644 index 661400ca3c7788738ddb35ed161720e31e74e249..0000000000000000000000000000000000000000 --- a/src/apps/wssapp/app_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package wssapp - -import ( - "gitee.com/captials-team/ubdframe/src/apps/wssapp/workers" - "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "go.uber.org/dig" - "os" - "testing" -) - -func TestAppStart(t *testing.T) { - di := testDi() - common.ErrPanic(di.Provide(NewApp)) - - common.ErrPanic(di.Invoke(func(app *App) error { - // - app.WorkerMgr.AddWorker("demo", new(workers.DemoWorker)) - app.WorkerMgr.AddWorker("demoCopy", new(workers.DemoWorker)) - - //app.WithModule(true) - - return app.Start() - })) -} - -func testDi() *dig.Container { - di := dig.New() - common.ErrPanic(di.Provide(func() *dig.Container { - return di - })) - common.ErrPanic(di.Provide(func() v1log.ILog { - return v1log.NewWriterLog(os.Stdout, v1log.DebugLog) - })) - - common.ErrPanic(di.Provide(func() *configstc.WebsocketAppConfig { - return &configstc.WebsocketAppConfig{ - ApiServer: configstc.ServerConfig{ - Enable: true, - ServerBindAddr: "", - Port: 10000, - }, - } - })) - - return di -} diff --git a/src/apps/wssapp/config.go b/src/apps/wssapp/config.go deleted file mode 100644 index f5a7ef4930784ffa3c19e267e90155018cb8c34a..0000000000000000000000000000000000000000 --- a/src/apps/wssapp/config.go +++ /dev/null @@ -1 +0,0 @@ -package wssapp diff --git a/src/apps/wssapp/workers/mgr.go b/src/apps/wssapp/workers/mgr.go deleted file mode 100644 index d86d0f966c88d70889fe14fd270e36cd0c215a4c..0000000000000000000000000000000000000000 --- a/src/apps/wssapp/workers/mgr.go +++ /dev/null @@ -1,108 +0,0 @@ -package workers - -import ( - "encoding/json" - "gitee.com/captials-team/ubdframe/src/domain/dto/cmddata" - "gitee.com/captials-team/ubdframe/src/domain/interfaces" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/wsserver" - "go.uber.org/dig" - "runtime/debug" -) - -// WorkerMgr worker管理器 -type WorkerMgr struct { - di *dig.Container - l v1log.ILog - workers map[string]interfaces.IWebsocketWorker -} - -func NewWorkerMgr(di *dig.Container, logger v1log.ILog) *WorkerMgr { - return &WorkerMgr{ - di: di, - l: logger, - workers: make(map[string]interfaces.IWebsocketWorker), - } -} - -// AddWorker 添加worker,name指定消息结构中的action对应名称都会发送到worker中 -func (mgr *WorkerMgr) AddWorker(name string, worker interfaces.IWebsocketWorker) { - mgr.workers[name] = worker -} - -func (mgr *WorkerMgr) SetHub(h *wsserver.Hub) { - -} - -func (mgr *WorkerMgr) Receive(msg *wsserver.WebSocketMessage) { - mgr.l.Debug("receive msg %d,%s", msg.MessageType, string(msg.Message)) - - cmd := mgr.convertCmd(msg.Message) - if cmd == nil { - return - } - - cmd.Client = msg.Client - cmd.OrigMessage = msg - mgr.handleCmd(cmd) -} - -func (mgr *WorkerMgr) Pong(messageType int, message []byte) (bool, []byte) { - cmd := mgr.convertCmd(message) - if cmd.Action == cmddata.PingCmd.Action { - return true, cmddata.PongMessage - } - return false, nil -} - -func (mgr *WorkerMgr) Online(client *wsserver.Client) { - client.Conn().SetReadLimit(2048 * 1000) - for _, w := range mgr.workers { - w.Online(client) - } -} - -func (mgr *WorkerMgr) Close(client *wsserver.Client) { - for _, w := range mgr.workers { - w.Close(client) - } -} - -// convertCmd 将消息转为Cmd -func (mgr *WorkerMgr) convertCmd(message []byte) *cmddata.ClientCmd { - cmd := cmddata.ClientCmd{} - err := json.Unmarshal(message, &cmd) - if err != nil { - v1log.Out.Error("message invalid: %s", message) - return &cmd - } - return &cmd -} - -// handleCmd 处理消息cmd -func (mgr *WorkerMgr) handleCmd(cmd *cmddata.ClientCmd) { - defer func() { - if err := recover(); err != nil { - v1log.Out.Error("recover err: %s", err) - v1log.Out.Error("recover stack %s", debug.Stack()) - cmd.Client.SendMessage(cmddata.CmdErrFrame) - } - }() - - //find worker - w, exist := mgr.workers[cmd.ParseAction(0)] - if !exist { - v1log.Out.Error("ws worker not exist: %s", cmd.Action) - cmd.Client.SendMessage(cmddata.CmdErrFrame) - return - } - //logger.Info("ws action: %s", cmd.Action) - - //accredit - if w.NeedAccredit(cmd.Client) { - v1log.Out.Error("client need accredit: %s", cmd.Client.ID()) - cmd.Client.SendMessage(cmddata.NotAuthFrame) - return - } - w.Receive(cmd) -} diff --git a/src/apps/wssapp/workers/worker_demo.go b/src/apps/wssapp/workers/worker_demo.go deleted file mode 100644 index 0b75f9b2d9cc1c2ca8d0defb9b6a12048f68edc0..0000000000000000000000000000000000000000 --- a/src/apps/wssapp/workers/worker_demo.go +++ /dev/null @@ -1,41 +0,0 @@ -package workers - -import ( - "gitee.com/captials-team/ubdframe/src/domain/dto/cmddata" - "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/wsserver" -) - -type DemoWorker struct { -} - -func (w *DemoWorker) Name() string { - return "demo" -} - -func (w *DemoWorker) Receive(cmd *cmddata.ClientCmd) { - logs.Out.Info("RECEIVE %+v", cmd) - - cmd.Client.SendMessage(&cmddata.ClientAnswer{ - Group: cmd.FirstAction(), - Message: "receive success", - }) -} - -func (w *DemoWorker) Online(client *wsserver.Client) { - logs.Out.Info("ONLINE %s", client.ID()) - - client.SendMessage(&cmddata.ClientAnswer{ - Group: w.Name(), - Message: "this is demo", - }) -} - -func (w *DemoWorker) Close(client *wsserver.Client) { - logs.Out.Info("CLOSED %s", client.ID()) - return -} - -func (w *DemoWorker) NeedAccredit(client *wsserver.Client) bool { - return false -} diff --git a/src/apps/wssapp/workers/worker_log.go b/src/apps/wssapp/workers/worker_log.go deleted file mode 100644 index 13a7269943458435672ddf24431d35291b290e46..0000000000000000000000000000000000000000 --- a/src/apps/wssapp/workers/worker_log.go +++ /dev/null @@ -1,47 +0,0 @@ -package workers - -import ( - "gitee.com/captials-team/ubdframe/src/domain/dto/cmddata" - v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" - "gitee.com/captials-team/ubdframe/src/pkg/wsserver" - "go.uber.org/dig" -) - -type LogWorker struct { - l v1log.ILog -} - -func (w *LogWorker) Name() string { - return "log" -} - -func (w *LogWorker) Receive(cmd *cmddata.ClientCmd) { - w.l.Info("RECEIVE %+v", cmd) - - cmd.Client.SendMessage(&cmddata.ClientAnswer{ - Group: w.Name(), - Message: "receive success", - }) -} - -func (w *LogWorker) Online(client *wsserver.Client) { - w.l.Info("ONLINE %s", client.ID()) - client.SendMessage(&cmddata.ClientAnswer{ - Group: w.Name(), - Message: "welcome", - }) -} - -func (w *LogWorker) Close(client *wsserver.Client) { - w.l.Info("CLOSED %s", client.ID()) -} - -func (w *LogWorker) NeedAccredit(client *wsserver.Client) bool { - return false -} - -func NewLogWorker(di *dig.Container, logger v1log.ILog) *LogWorker { - return &LogWorker{ - l: logger, - } -} diff --git a/src/common/consts/common.go b/src/common/consts/common.go index 7ed7fdf770c0036f25deeb1c3ac91995f3ee3809..b7a7d21f2fe236446a4c070ca995c9bf0912a042 100644 --- a/src/common/consts/common.go +++ b/src/common/consts/common.go @@ -1,5 +1,7 @@ package consts +import "fmt" + // 权限类型,供参考 const ( PermissionTypeMenu = "menu" @@ -17,7 +19,7 @@ const ( AccreditAllowWithIn AccreditMode = "allow_no_config" //未在权限配置中的全部allow ) -// 常用状态 +// 通用状态码 const ( StatusAll = 0 @@ -34,6 +36,27 @@ const ( StatusFail = 3 //处理失败 ) +func ValidateStatusBool(status int) error { + if status != StatusFalse && status != StatusTrue { + return fmt.Errorf("status invalid") + } + return nil +} + +func ValidateStatusEnable(status int) error { + if status != StatusUnknown && status != StatusEnable && status != StatusDisable { + return fmt.Errorf("status invalid") + } + return nil +} + +func ValidateStatusDo(status int) error { + if status != StatusCreated && status != StatusDoing && status != StatusSuccess && status != StatusFail { + return fmt.Errorf("status invalid") + } + return nil +} + // 时间缩写 const ( MinuteAbbr = "m" @@ -42,3 +65,5 @@ const ( MonthAbbr = "mo" YearAbbr = "y" ) + +const MaxFileSize = 5 * 1024 * 1024 //最大文件大小,单位:b diff --git a/src/common/utils/array.go b/src/common/utils/array.go new file mode 100644 index 0000000000000000000000000000000000000000..cf462d00752e044b3a7a737ab2ceecaf166abaf6 --- /dev/null +++ b/src/common/utils/array.go @@ -0,0 +1,90 @@ +package utils + +import ( + "fmt" +) + +// ArrayIntersection 取数组交集 +func ArrayIntersection[T interface{}](slices ...[]T) []T { + elemCount := make(map[string]int) + elements := make(map[string]T) + for _, item := range slices { + temp := make(map[string]bool) + for _, v := range item { + k := fmt.Sprintf("%+v", v) + elements[k] = v + if _, exist := temp[k]; exist { + // 避免当前切片内重复元素干扰 + continue + } + temp[k] = true + if _, exists := elemCount[k]; !exists { + elemCount[k] = 0 + } + //计数 + elemCount[k]++ + } + } + + var intersection []T + for k, v := range elemCount { + //计数值=总数组数则是所有数都存在的 + if v == len(slices) { + intersection = append(intersection, elements[k]) + } + } + + return intersection +} + +// ArrayDifference 取数组差集 +func ArrayDifference[T interface{}](slices ...[]T) []T { + elemCount := make(map[string]int) + elements := make(map[string]T) + for _, item := range slices { + temp := make(map[string]bool) + for _, v := range item { + k := fmt.Sprintf("%+v", v) + fmt.Printf("%s\n", k) + elements[k] = v + if _, exist := temp[k]; exist { + // 避免当前切片内重复元素干扰 + continue + } + temp[k] = true + if _, exists := elemCount[k]; !exists { + elemCount[k] = 0 + } + //计数 + elemCount[k]++ + } + } + + var intersection []T + for k, v := range elemCount { + //计数值=1表示只出现过一次的,即为差值 + if v == 1 { + intersection = append(intersection, elements[k]) + } + } + + return intersection +} + +// ArrayUnion 取数组并集 +func ArrayUnion[T interface{}](slices ...[]T) []T { + var union []T + m := make(map[string]bool) + for _, item := range slices { + for _, v := range item { + k := fmt.Sprintf("%+v", v) + if _, exist := m[k]; exist { + continue + } + + m[k] = true + union = append(union, v) + } + } + return union +} diff --git a/src/common/utils/array_test.go b/src/common/utils/array_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0df2e808d9ce6d3046ca83b910c90fad976bab5c --- /dev/null +++ b/src/common/utils/array_test.go @@ -0,0 +1,76 @@ +package utils + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestArrayIntersection(t *testing.T) { + + array := ArrayIntersection([]int{1, 2, 3}, []int{1, 2, 3, 4}) + t.Logf("Intersection= %+v", array) + assert.Equal(t, len(array), 3) + assert.Equal(t, array[0], 1) + assert.Equal(t, array[1], 2) + assert.Equal(t, array[2], 3) + + array = ArrayIntersection([]int{1, 2, 3}, []int{4, 5, 6}) + t.Logf("Intersection= %+v", array) + assert.Equal(t, len(array), 0) + + array = ArrayIntersection([]int{1, 2, 4}, []int{4, 5, 6}) + t.Logf("Intersection= %+v", array) + assert.Equal(t, len(array), 1) + assert.Equal(t, array[0], 4) +} + +func TestArrayDifference(t *testing.T) { + + array := ArrayDifference([]int{1, 2, 3}, []int{1, 2, 3, 4}) + t.Logf("Difference= %+v", array) + assert.Equal(t, len(array), 1) + assert.Equal(t, array[0], 4) + + array = ArrayDifference([]int{1, 2, 3}, []int{4, 5, 6}) + t.Logf("Difference= %+v", array) + assert.Equal(t, len(array), 6) + assert.Equal(t, array[0], 1) + assert.Equal(t, array[1], 2) + assert.Equal(t, array[2], 3) + assert.Equal(t, array[5], 6) + + array = ArrayDifference([]int{1, 2, 4}, []int{4, 5, 6}) + t.Logf("Difference= %+v", array) + assert.Equal(t, len(array), 4) + assert.Equal(t, array[0], 1) + assert.Equal(t, array[1], 2) + assert.Equal(t, array[2], 5) +} + +func TestArrayUnion(t *testing.T) { + + array := ArrayUnion([]int{1, 2, 3}, []int{1, 2, 3, 4}) + t.Logf("Union= %+v", array) + assert.Equal(t, len(array), 4) + assert.Equal(t, array[0], 1) + assert.Equal(t, array[1], 2) + assert.Equal(t, array[2], 3) + assert.Equal(t, array[3], 4) + + array = ArrayUnion([]int{1, 2, 3}, []int{4, 5, 6}) + t.Logf("Union= %+v", array) + assert.Equal(t, len(array), 6) + assert.Equal(t, array[0], 1) + assert.Equal(t, array[1], 2) + assert.Equal(t, array[2], 3) + assert.Equal(t, array[5], 6) + + array = ArrayUnion([]int{1, 2, 4}, []int{4, 5, 6}) + t.Logf("Union= %+v", array) + assert.Equal(t, len(array), 5) + assert.Equal(t, array[0], 1) + assert.Equal(t, array[1], 2) + assert.Equal(t, array[2], 4) + assert.Equal(t, array[3], 5) + assert.Equal(t, array[4], 6) +} diff --git a/src/common/utils/other.go b/src/common/utils/other.go index aafd9ef4ae859ba35ccde47273ea344554e6909d..5033b6953a357c07ef871389c9bd00583bbc2d17 100644 --- a/src/common/utils/other.go +++ b/src/common/utils/other.go @@ -292,3 +292,15 @@ func StringIntId(s string) int { // v == MinInt return 0 } + +// CopyMap 复制map +func CopyMap[T int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 | string | struct{}, T1 interface{}](m map[T]T1) map[T]T1 { + if m == nil { + return nil + } + newM := make(map[T]T1, len(m)) + for k, v := range m { + newM[k] = v + } + return newM +} diff --git a/src/domain/configstc/app.go b/src/domain/configstc/app.go deleted file mode 100644 index e6df2dbdf7e9cfb4cd466e87ce6bc8044fecfbe6..0000000000000000000000000000000000000000 --- a/src/domain/configstc/app.go +++ /dev/null @@ -1,335 +0,0 @@ -package configstc - -type UserAppConfig struct { - Name string `json:"Name" yaml:"Name"` - - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` //作为api服务器 - RpcServer ServerConfig `json:"RpcServer" yaml:"RpcServer"` //作为rpc服务器 - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //debug开关 - Debug bool `json:"Debug" yaml:"Debug"` - - AuthConfig AuthConfig `json:"AuthConfig" yaml:"AuthConfig"` //授权配置 - AuthRegister bool `json:"AuthRegister" yaml:"AuthRegister"` //是否支持注册 - - AdminAuthConfig AuthConfig `json:"AdminAuthConfig" yaml:"AdminAuthConfig"` //授权配置(管理站) - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` //数据库配置 - - EmailConfig EmailConfig `json:"EmailConfig" yaml:"EmailConfig"` //邮件配置 - - LimitingApi LimitingConfig `json:"LimitingApi" yaml:"LimitingApi"` //api限流 - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 - - AutoCreateUser []CreateUserConfig `json:"AutoCreateUser" yaml:"AutoCreateUser"` //自动创建用户列表 - - WechatAuth ThirdConfig `json:"WechatAuth" yaml:"WechatAuth"` //微信配置 - - SmsConfig ThirdConfig `json:"SmsConfig" yaml:"SmsConfig"` //短信配置,目前使用阿里云 - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - PasswordSalt string `json:"PasswordSalt" yaml:"PasswordSalt"` //密码salt - - ModuleMode bool `json:"ModuleMode" yaml:"ModuleMode"` //模块模式,作为module使用 -} - -type CreateUserConfig struct { - UserName string `json:"UserName" yaml:"UserName"` //用户名 - Account string `json:"Account" yaml:"Account"` // 账户 - Password string `json:"Password" yaml:"Password"` //密码 -} - -type BaseDataAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //debug开关 - Debug bool `json:"Debug" yaml:"Debug"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - ModuleMode bool `json:"ModuleMode" yaml:"ModuleMode"` //模块模式,作为module使用 -} - -type WebAppConfig struct { - Name string `json:"Name" yaml:"Name"` - WebServer ServerConfig `json:"WebServer" yaml:"WebServer"` //web服务器配置 - //支持静态文件 - StaticPath string `json:"StaticPath" yaml:"StaticPath"` //静态文件路径,支持静态html等 - StaticRouter string `json:"StaticRouter" yaml:"StaticRouter"` //静态路由前缀 - - TemplatePath string `json:"TemplatePath" yaml:"TemplatePath"` //模板文件路径,按html/template解析 - TemplateRouter string `json:"TemplateRouter" yaml:"TemplateRouter"` //模板访问的路由前缀 - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 - - //支持转发功能 - ProxyRules []ProxyRule `json:"ProxyRules" yaml:"ProxyRules"` //转发配置列表 - - ModuleMode bool `json:"ModuleMode" yaml:"ModuleMode"` //模块模式,作为module使用 -} - -type AdminAppConfig struct { - Name string `json:"Name" yaml:"Name"` - - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //debug开关 - Debug bool `json:"Debug" yaml:"Debug"` - - AuthConfig AuthConfig `json:"AuthConfig" yaml:"AuthConfig"` - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` - - //api限流 - LimitingApi LimitingConfig `json:"LimitingApi" yaml:"LimitingApi"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` - - AutoCreateAdmin bool `json:"AutoCreateAdmin" yaml:"AutoCreateAdmin"` //是否自动创建admin账户 - - //多语言配置:key=language,value=path - I18nFiles map[string]string `json:"I18nFiles" yaml:"I18nFiles"` - - //权限文件json - PermissionFile string `json:"PermissionFile" yaml:"PermissionFile"` //权限文件 - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - PasswordSalt string `json:"PasswordSalt" yaml:"PasswordSalt"` //密码salt - UserPasswordSalt string `json:"UserPasswordSalt" yaml:"UserPasswordSalt"` //用户-密码salt - - ModuleMode bool `json:"ModuleMode" yaml:"ModuleMode"` //模块模式,作为module使用 -} - -// ProxyRule 转发规则 -type ProxyRule struct { - Mode string `json:"Mode" yaml:"Mode"` //转发模式 - - Match string `json:"Match" yaml:"Match"` //匹配模式,见下面的 ProxyModePrefix/ProxyModeFix - - Forward string `json:"Forward" yaml:"Forward"` //转发目标 - Replace string `json:"Replace" yaml:"Replace"` //替换前缀 -} - -// WebsocketAppConfig ws应用app -type WebsocketAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` //web服务器配置 - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 -} - -// OssAppConfig oss存储app -type OssAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` //web服务器配置 - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 - - StoragePath string `yaml:"StoragePath"` //临时存储目录 - //配置来源,可配置: - // file:配置文件,取下面的 UploadConfig 配置 - // db: 数据库,取上面配置的 DBConfig 里的表数据 - ConfigSource string `yaml:"ConfigSource"` - - UploadMaxSize int64 `yaml:"UploadMaxSize"` //最大上传大小,单位: b - - //上传类型和上传参数,参考 ossadaptor 包 - UploadType string `yaml:"UploadType"` - UploadConfig map[string]map[string]string `yaml:"UploadConfig"` -} - -// SettingAppConfig 配置app -type SettingAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` //web服务器配置 - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 -} - -// IotAppConfig IOT app -type IotAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` //web服务器配置 - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` - - AuthConfig AuthConfig `json:"AuthConfig" yaml:"AuthConfig"` - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 -} - -// BlockAppConfig 块app -type BlockAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` //web服务器配置 - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` - - AuthConfig AuthConfig `json:"AuthConfig" yaml:"AuthConfig"` - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 -} - -// JobAppConfig job app -type JobAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` //web服务器配置 - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` - - AuthConfig AuthConfig `json:"AuthConfig" yaml:"AuthConfig"` - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - //日志路径 - LogPath string `json:"LogPath" yaml:"LogPath"` - LogLevel string `json:"LogLevel" yaml:"LogLevel"` - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 - - JobConfig -} - -type RssAppConfig struct { - Name string `json:"Name" yaml:"Name"` - ApiServer ServerConfig `json:"ApiServer" yaml:"ApiServer"` - - LogConfig LogConfig `json:"LogConfig" yaml:"LogConfig"` //日志配置 - - //debug开关 - Debug bool `json:"Debug" yaml:"Debug"` - - AuthConfig AuthConfig `json:"AuthConfig" yaml:"AuthConfig"` //授权配置 - - DBConfig DBConfig `json:"DBConfig" yaml:"DBConfig"` //数据库配置 - - LimitingApi LimitingConfig `json:"LimitingApi" yaml:"LimitingApi"` //api限流 - - //路由前缀 - RoutePrefix string `json:"RoutePrefix" yaml:"RoutePrefix"` //路由前缀 - - //是否启用文档 - DocsEnable bool `json:"DocsEnable" yaml:"DocsEnable"` - - //是否启用pprof - PProfEnable bool `json:"PProfEnable" yaml:"PProfEnable"` - - //rss配置,示例: - //RssConfig: - // - Name: "人民网" - // Rss: "http://www.people.com.cn/rss/politics.xml" - // Enable: true - // - Name: "搜狐中国" - // Rss: "http://rss.news.sohu.com/rss/pfocus.xml" - // Enable: false - - RssConfig []RssMetaConfig `json:"RssConfig" yaml:"RssConfig"` - - AsyncInit bool `json:"AsyncInit" yaml:"AsyncInit"` //是否异步初始化运行,包含定时任务等 - - ModuleMode bool `json:"ModuleMode" yaml:"ModuleMode"` //模块模式,作为module使用 -} - -type RssMetaConfig struct { - Enable bool `json:"Enable" yaml:"Enable"` - Name string `json:"Name" yaml:"Name"` - Rss string `json:"Rss" yaml:"Rss"` -} - -const ( - ProxyModePrefix = "prefix" //前缀替换,匹配并替换指定前缀 - ProxyModeFix = "fixed" //固定地址,完全匹配路由进行转发 -) diff --git a/src/domain/configstc/config.go b/src/domain/configstc/config.go index bdc1c998a8e8a8dee58edaba79d4577e1dfe6948..6eba580da74378218c94c0984b8d74997e26e0b3 100644 --- a/src/domain/configstc/config.go +++ b/src/domain/configstc/config.go @@ -12,7 +12,8 @@ const _configPath = "./data/config.yaml" var DefiConfigPath = ParseConfigPath -// ParseConfigPath 默认的config path获取 +// ParseConfigPath 默认的config path获取,默认从 -c 命令行获取 +// 如: ./app -c ./data/config.yaml func ParseConfigPath(s ...string) string { var filepath = "" @@ -31,6 +32,11 @@ func ParseConfigPath(s ...string) string { return filepath } +func NewConfig[T interface{}]() *T { + return LoadConfig(new(T)) +} + +// LoadConfig 加载配置(默认) func LoadConfig[T interface{}](c *T, s ...string) *T { err := utils.ReadYamlFile(c, ParseConfigPath(s...)) if err != nil { diff --git a/src/domain/configstc/config_job.go b/src/domain/configstc/config_job.go deleted file mode 100644 index e5296269cfd6f0916e2b9cbc6ec18597c71dff45..0000000000000000000000000000000000000000 --- a/src/domain/configstc/config_job.go +++ /dev/null @@ -1,45 +0,0 @@ -package configstc - -// JobConfig 执行job配置 -/* 示例配置 - - multi_files: - #平常灵活使用的压测配置 - - data/jobs/iot_demo.yaml - - # 详细action配置,数组,每个子项配置如下: - # actions 定义需要执行的操作,多个以逗号分隔,值可参考 当前所在目录/config/consts.go 文件 - # op_interval 定义本批次操作的再次执行的间隔时间,单位:毫秒 - # 如本次操作组合有10次操作,定义500毫秒间隔,则相当于下单频率为每分钟20 - # extend_params 定义扩展参数,不同的action使用的参数不一样,可配置key参考 当前所在目录/config/consts.go 文件 - # - # 总qps = sum(actions数量*contracts数量*accounts数量*1000/间隔时间) - # 每个qps = sum(actions数量*accounts数量*1000/间隔时间) - multi_actions: - ################################下面是demo worker - - actions1: "demo" - count: 1 - op_interval: 1000 #每个操作的间隔时间,单位:毫秒 - extend_params: - percent: "21" - - # 全局可用参数配置 - global_params: - mqtt_core: "192.168.149.128:57081" - mqtt_driver: "16774105" - -*/ -type JobConfig struct { - MultiFiles []string `yaml:"multi_files"` //多压测动作配置文件数组 - MultiActions []MultiActionItem `yaml:"multi_actions"` //多压测动作配置数组 - GlobalParams map[string]string `yaml:"global_params"` //全局参数 -} - -// MultiActionItem 压测动作配置项 -type MultiActionItem struct { - Id int - Actions string `yaml:"actions"` //动作,多个以逗号分割,每个单一动作名标识某种操作 - Count int `yaml:"count"` //执行数量 - OpInterval int64 `yaml:"op_interval"` //执行间隔,为0则表示持续执行,>0为指定多少ms执行一次 - ExtendParams map[string]string `yaml:"extend_params"` //扩展参数,不同action支持不同参数 -} diff --git a/src/domain/configstc/config_params.go b/src/domain/configstc/config_params.go index 2ec15a80bc9fd72835bf9ca733393dcf799889f9..68e3851ea7b786ee5a4a48e238fe1cf4e8168d1e 100644 --- a/src/domain/configstc/config_params.go +++ b/src/domain/configstc/config_params.go @@ -1,83 +1,7 @@ package configstc import ( - "strconv" - "strings" + "gitee.com/captials-team/ubdframe/src/pkg/extendparams" ) -type CommonExtendParams map[string]string - -// ExtendParamByInt 返回extendParam指定k的int类型值 -func (op CommonExtendParams) ExtendParamByInt(k string, def ...int) int { - v := op.ExtendParamValue(k) - ret, err := strconv.Atoi(v) - if err != nil { - if len(def) > 0 { - return def[0] - } - return 0 - } - return ret -} - -// ExtendParamByInt64 返回extendParam指定k的int类型值 -func (op CommonExtendParams) ExtendParamByInt64(k string, def ...int64) int64 { - v := op.ExtendParamValue(k) - ret, err := strconv.ParseInt(v, 10, 64) - if err != nil { - if len(def) > 0 { - return def[0] - } - return 0 - } - return ret -} - -// ExtendParamByFloat 返回extendParam指定k的float类型值 -func (op CommonExtendParams) ExtendParamByFloat(k string, def ...float64) float64 { - v := op.ExtendParamValue(k) - ret, err := strconv.ParseFloat(v, 64) - if err != nil { - if len(def) > 0 { - return def[0] - } - return 0 - } - return ret -} - -// ExtendParamByBool 返回extendParam指定k的bool类型值 -func (op CommonExtendParams) ExtendParamByBool(k string, def ...bool) bool { - v := op.ExtendParamValue(k) - if v == "" { - if len(def) > 0 { - return def[0] - } - return false - } - - if v == "true" { - return true - } - - if v == "false" { - return true - } - - return v != "0" -} - -func (op CommonExtendParams) ExtendParamValue(key string, def ...string) string { - if op == nil { - return "" - } - v := strings.TrimSpace(op[key]) - if v == "" { - if len(def) > 0 { - return def[0] - } - return "" - } - - return v -} +type CommonExtendParams = extendparams.CommonExtendParams diff --git a/src/domain/converts/validate.go b/src/domain/converts/validate.go new file mode 100644 index 0000000000000000000000000000000000000000..27598f7702db068caab0807a6d8d453c2e7aa60e --- /dev/null +++ b/src/domain/converts/validate.go @@ -0,0 +1 @@ +package converts diff --git a/src/domain/dto/cms.go b/src/domain/dto/cms.go new file mode 100644 index 0000000000000000000000000000000000000000..fd0a21b4f2de82dc048a0c4ef2cc1b9e293c076e --- /dev/null +++ b/src/domain/dto/cms.go @@ -0,0 +1,27 @@ +package dto + +// SearchCmsColumnParams cms专栏搜索参数 +type SearchCmsColumnParams struct { + ParentColumn int64 `json:"parent_column"` //指定上级专栏id + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` +} + +// SearchCmsArticleParams cms文章搜索参数 +type SearchCmsArticleParams struct { + CmsColumn int64 `json:"cms_column"` //指定专栏 + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` +} + +// SearchCmsProductParams cms文章搜索参数 +type SearchCmsProductParams struct { + CmsColumn int64 `json:"cms_column"` //指定专栏 + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` +} + +// SearchRichContentParams cms文章搜索参数 +type SearchRichContentParams struct { + Render string `json:"render"` //指定渲染方式 +} diff --git a/src/domain/dto/iot.go b/src/domain/dto/iot.go new file mode 100644 index 0000000000000000000000000000000000000000..0468ce6f0e5f9821f6f43c97be3594e4ad1c8251 --- /dev/null +++ b/src/domain/dto/iot.go @@ -0,0 +1,14 @@ +package dto + +// SearchIotProductParams iot产品搜索参数 +type SearchIotProductParams struct { + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` +} + +// SearchIotDeviceParams iot设备搜索参数 +type SearchIotDeviceParams struct { + ProductId int64 `json:"product_id"` //指定产品 + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` +} diff --git a/src/domain/dto/job.go b/src/domain/dto/job.go new file mode 100644 index 0000000000000000000000000000000000000000..592c794f9df48638a66dd3156d56e09a78ad72b6 --- /dev/null +++ b/src/domain/dto/job.go @@ -0,0 +1,14 @@ +package dto + +type JobWorkerItem struct { + Worker string `json:"worker"` //worker名称 + Action string `json:"action"` //支持的操作action名 + Running *JobRunningData `json:"running,omitempty"` +} + +type JobRunningData struct { + Interval string `json:"interval"` //运行间隔 + Count int64 `json:"count"` //已运行次数 + StartAt int64 `json:"start_at,omitempty"` //运行开始时间 + LastAt int64 `json:"last_at,omitempty"` //最后运行时间 +} diff --git a/src/domain/dto/other.go b/src/domain/dto/other.go index 7bb942ba2f45e1b823d6996a7a4feeb8d33bd0ab..5e816b1c657046df71ccba78a632fe712b87c388 100644 --- a/src/domain/dto/other.go +++ b/src/domain/dto/other.go @@ -1,5 +1,10 @@ package dto +import ( + "net/http" + "time" +) + // SearchGenericRecordParams 用户通用记录搜索参数 type SearchGenericRecordParams struct { Uid int64 `json:"uid" ` @@ -25,3 +30,11 @@ type WeatherInfo struct { Temp string `json:"temp"` //温度 Icon string `json:"icon"` //图标 } + +// RequestInfo 浏览器访问信息 +type RequestInfo struct { + Time time.Time //登录时间 + Ip string //ip + Device string //登陆设备名 + Request *http.Request +} diff --git a/src/domain/dto/reqdata/req.go b/src/domain/dto/reqdata/req.go index 7a5acfddeab9914e48de152484dd6f1592d2f5f4..e6a6aa5b943f2dcdbc26c8f8e13baf75a74dadf4 100644 --- a/src/domain/dto/reqdata/req.go +++ b/src/domain/dto/reqdata/req.go @@ -1,7 +1,10 @@ package reqdata -type DetailReq struct { - Id int64 `json:"id" example:"0"` //数据id +type QueryByIdReq struct { + Id int64 `json:"id" example:"0"` //数据id +} + +type MultiQueryReq struct { Ids []int64 `json:"ids" example:"1,2"` //多个数据id } diff --git a/src/domain/dto/reqdata/req_cms.go b/src/domain/dto/reqdata/req_cms.go new file mode 100644 index 0000000000000000000000000000000000000000..bd7c4b3cdc2e973446dc64b72bc428e889116cd4 --- /dev/null +++ b/src/domain/dto/reqdata/req_cms.go @@ -0,0 +1,97 @@ +package reqdata + +// SearchCmsColumnReq cms专栏搜索参数 +type SearchCmsColumnReq struct { + ParentColumn int64 `json:"parent_column"` //指定上级专栏id + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` + + Page int `json:"page" example:"1"` + Size int `json:"size" example:"10"` +} + +// AddEditCmsColumnReq 专栏列表保存请求 +type AddEditCmsColumnReq struct { + Id int64 `json:"id"` //id为0时为创建,>0为更新保存 + + Name string `json:"name" example:""` //栏目名称 + Alias string `json:"alias" example:""` //栏目别名,可为英文 + Pic string `json:"pic" example:""` //图片 + + Sort int64 `json:"sort"` //排序值,越大越靠前 + ParentColumn int64 `json:"parent_column" example:"0"` //上级专栏id + + Model string `json:"model" validate:"required"` //对应模型 + Status int `json:"status" validate:"gte=0,lte=2"` //状态,0:无,1:可用,2:禁用 +} + +// SearchCmsProductReq cms产品搜索参数 +type SearchCmsProductReq struct { + ColumnId int64 `json:"column_id"` //指定专栏id + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` + + Page int `json:"page" example:"1"` + Size int `json:"size" example:"10"` +} + +// AddEditCmsProductReq cms产品模型保存req +type AddEditCmsProductReq struct { + Id int64 `json:"id"` //id为0时为创建,>0为更新保存 + + ColumnId int64 `json:"column_id"` //对应栏目id + Title string `json:"title"` //标题 + SubTitle string `json:"sub_title"` //副标题 + Describe string `json:"describe"` //简介 + Cover string `json:"cover"` //封面 + Sort int64 `json:"sort"` //排序值,越大越靠前 + Content string `json:"content"` //对应内容(url) + Extends string `json:"extends" gorm:"type:varchar(512)"` + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 +} + +// SearchCmsArticleReq cms文章搜索参数 +type SearchCmsArticleReq struct { + ColumnId int64 `json:"column_id"` //指定专栏id + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` + + Page int `json:"page" example:"1"` + Size int `json:"size" example:"10"` +} + +// AddEditCmsArticleReq cms文章模型保存req +type AddEditCmsArticleReq struct { + Id int64 `json:"id"` //id为0时为创建,>0为更新保存 + + ColumnId int64 `json:"column_id"` //对应栏目id + Title string `json:"title"` //标题 + SubTitle string `json:"sub_title"` //副标题 + Describe string `json:"describe"` //简介 + Cover string `json:"cover"` //封面 + Sort int64 `json:"sort"` //排序值,越大越靠前 + Author string `json:"author"` + PublishStart int64 `json:"publish_start"` //发布时间开始,时间戳 + PublishEnd int64 `json:"publish_end"` //发布时间结束,时间戳 + Content string `json:"content"` //对应内容(url) + Extends string `json:"extends" gorm:"type:varchar(512)"` + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 +} + +// SearchRichContentReq 富文本内容搜索参数 +type SearchRichContentReq struct { + Render int64 `json:"render"` //渲染类型 + + Page int `json:"page" example:"1"` + Size int `json:"size" example:"10"` +} + +// AddEditRichContentReq 富文本内容保存req +type AddEditRichContentReq struct { + Id int64 `json:"id"` //id为0时为创建,>0为更新保存 + + Render int64 `json:"render"` //渲染类型 + Content string `json:"content"` //对应内容(url) +} diff --git a/src/domain/dto/reqdata/req_iot.go b/src/domain/dto/reqdata/req_iot.go new file mode 100644 index 0000000000000000000000000000000000000000..f3ac6a644b06069852bb83984885d8436b02a893 --- /dev/null +++ b/src/domain/dto/reqdata/req_iot.go @@ -0,0 +1,52 @@ +package reqdata + +// SearchIotProductReq iot产品搜索参数 +type SearchIotProductReq struct { + NodeType int `json:"node_type"` //节点类型,0:未知,1:直连设备,2:网关,3:网关子设备 + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` + + Page int `json:"page" example:"1"` + Size int `json:"size" example:"10"` +} + +// AddEditIotProductReq iot产品保存req +type AddEditIotProductReq struct { + Id int64 `json:"id"` //id为0时为创建,>0为更新保存 + + Name string `json:"name"` //标题 + Describe string `json:"describe"` //简介 + Cover string `json:"cover"` //封面 + Sort int64 `json:"sort"` //排序值,越大越靠前 + NodeType int `json:"node_type"` //节点类型,0:未知,1:直连设备,2:网关,3:网关子设备 + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 +} + +// SearchIotDeviceReq iot设备搜索参数 +type SearchIotDeviceReq struct { + SN string `json:"sn"` //设备的sn序列号 + ProductId int64 `json:"product_id"` //所属产品id + Keywords string `json:"keywords"` //关键字 + Status int `json:"status" example:"0"` + + Page int `json:"page" example:"1"` + Size int `json:"size" example:"10"` +} + +// AddEditIotDeviceReq cms产品模型保存req +type AddEditIotDeviceReq struct { + Id int64 `json:"id"` //id为0时为创建,>0为更新保存 + + ParentDevice string `json:"parent_device"` //上级设备key + ProductId int64 `json:"product_id"` //所属产品id + Name string `json:"name"` //标题 + Describe string `json:"describe"` //简介 + SN string `json:"sn"` //设备的sn序列号 + Cover string `json:"cover"` //封面 + Virtual int `json:"virtual"` //是否虚拟设备,0:不是,1:是 + Sort int64 `json:"sort"` //排序值,越大越靠前 + Geo string `json:"geo"` //经纬度,逗号分隔,如:120.15,30.25 + + Status int `json:"status"` //状态码,0:无,1:未激活,2:激活可用,3:禁用 +} diff --git a/src/domain/dto/reqdata/req_rbac.go b/src/domain/dto/reqdata/req_rbac.go index 25b72c2f1489b4561d0a509051d486c12fbd37f9..4311e7628c923e6ebb30a2dac521afef906a65b2 100644 --- a/src/domain/dto/reqdata/req_rbac.go +++ b/src/domain/dto/reqdata/req_rbac.go @@ -49,3 +49,9 @@ type ListOptionReq struct { IsTree bool `json:"is_tree"` //是否树型返回 IsSimple bool `json:"is_simple"` //是否简易返回,false:正常返回,true:simple返回 } + +// SearchRolePermissionsReq 搜索角色权限请求 +type SearchRolePermissionsReq struct { + Id int64 `json:"id" example:"0"` //数据id + Ids []int64 `json:"ids" example:"1,2"` //多个数据id +} diff --git a/src/domain/dto/respdata/resp_cms.go b/src/domain/dto/respdata/resp_cms.go new file mode 100644 index 0000000000000000000000000000000000000000..c58fe618e77a25a32889f9cb8542f33725db5f2f --- /dev/null +++ b/src/domain/dto/respdata/resp_cms.go @@ -0,0 +1,151 @@ +package respdata + +import "time" + +// CmsColumnListRespItem 专栏列表item +type CmsColumnListRespItem struct { + Id int64 `json:"id" ` + + Name string `json:"name"` //栏目名称 + Alias string `json:"alias"` //栏目别名,可为英文 + Pic string `json:"pic"` //图片 + + Sort int64 `json:"sort"` //排序值,越大越靠前 + ParentColumn int64 `json:"parent_column"` //上级专栏id + + Model string `json:"model"` + ModelName string `json:"model_name"` //模型名称 + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type CmsColumnDetailResp struct { + Id int64 `json:"id" ` + + Name string `json:"name"` //栏目名称 + Alias string `json:"alias"` //栏目别名,可为英文 + Pic string `json:"pic"` //图片 + + Sort int64 `json:"sort"` //排序值,越大越靠前 + ParentColumn int64 `json:"parent_column"` //上级专栏id + ParentColumnName string `json:"parent_column_name"` //上级专栏名称 + + Model string `json:"model"` + ModelName string `json:"model_name"` //模型名称 + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +// CmsProductListRespItem cms产品列表item +type CmsProductListRespItem struct { + Id int64 `json:"id" ` + ColumnId int64 `json:"column_id"` //对应栏目id + ColumnName int64 `json:"column_name"` //对应栏目名称 + Title string `json:"title"` + SubTitle string `json:"sub_title"` + Describe string `json:"describe"` //简介 + Cover string `json:"cover"` //封面 + Hits int64 `json:"hits"` + Sort int64 `json:"sort"` //排序值,越大越靠前 + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type CmsProductDetailResp struct { + Id int64 `json:"id" ` + ColumnId int64 `json:"column_id"` //对应栏目id + ColumnName int64 `json:"column_name"` //对应栏目名称 + Title string `json:"title"` + SubTitle string `json:"sub_title"` + Describe string `json:"describe"` //简介 + Cover string `json:"cover"` //封面 + Hits int64 `json:"hits"` + Sort int64 `json:"sort"` //排序值,越大越靠前 + Content string `json:"content"` //对应内容(url) + Extends string `json:"extends" gorm:"type:varchar(512)"` + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +// CmsArticleListRespItem cms文章列表item +type CmsArticleListRespItem struct { + Id int64 `json:"id" ` + ColumnId int64 `json:"column_id"` //对应栏目id + ColumnName int64 `json:"column_name"` //对应栏目名称 + Title string `json:"title"` + SubTitle string `json:"sub_title"` + Cover string `json:"cover"` //封面 + Hits int64 `json:"hits"` + Sort int64 `json:"sort"` //排序值,越大越靠前 + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + Author string `json:"author"` + PublishStart int64 `json:"publish_start"` //发布时间开始,时间戳 + PublishEnd int64 `json:"publish_end"` //发布时间结束,时间戳 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type CmsArticleDetailResp struct { + Id int64 `json:"id" ` + ColumnId int64 `json:"column_id"` //对应栏目id + ColumnName int64 `json:"column_name"` //对应栏目名称 + Title string `json:"title"` + SubTitle string `json:"sub_title"` + Cover string `json:"cover"` //封面 + Hits int64 `json:"hits"` + Sort int64 `json:"sort"` //排序值,越大越靠前 + + Content string `json:"content"` //对应内容(url) + Extends string `json:"extends"` + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + Author string `json:"author"` + PublishStart int64 `json:"publish_start"` //发布时间开始,时间戳 + PublishEnd int64 `json:"publish_end"` //发布时间结束,时间戳 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +// RichContentListRespItem 专栏列表item +type RichContentListRespItem struct { + Id int64 `json:"id" ` + Render string `json:"render"` //渲染方式 + ContentUrl string `json:"content_url"` //内容地址 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type RichContentDetailResp struct { + Id int64 `json:"id" ` + + Render string `json:"render"` //渲染方式 + Content string `json:"content"` //内容 + ContentUrl string `json:"content_url"` //内容地址 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type RichContentResp struct { + Render string `json:"render"` //渲染方式 + Content string `json:"content"` //内容 +} diff --git a/src/domain/dto/respdata/resp_iot.go b/src/domain/dto/respdata/resp_iot.go new file mode 100644 index 0000000000000000000000000000000000000000..f0b33892ebcf29b4b82d5ededdec9f518aa229ea --- /dev/null +++ b/src/domain/dto/respdata/resp_iot.go @@ -0,0 +1,98 @@ +package respdata + +import "time" + +// IotProductListRespItem iot产品列表item +type IotProductListRespItem struct { + Id int64 `json:"id" ` + ProductKey string `json:"product_key"` //产品key + + Name string `json:"name"` + Cover string `json:"cover"` //封面 + Sort int64 `json:"sort"` //排序值,越大越靠前 + + NodeType int `json:"node_type"` //节点类型,0:未知,1:直连设备,2:网关,3:网关子设备 + NodeTypeName string `json:"node_type_name"` //节点类型名称 + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type IotProductDetailResp struct { + Id int64 `json:"id" ` + + ProductKey string `json:"product_key"` //产品key + + Name string `json:"name"` + Describe string `json:"describe"` //简介 + Cover string `json:"cover"` //封面 + Sort int64 `json:"sort"` //排序值,越大越靠前 + + NodeType int `json:"node_type"` //节点类型,0:未知,1:直连设备,2:网关,3:网关子设备 + NodeTypeName string `json:"node_type_name"` //节点类型名称 + + Status int `json:"status"` //状态,0:无,1:可用,2:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +// IotDeviceListRespItem iot设备列表item +type IotDeviceListRespItem struct { + Id int64 `json:"id" ` + + DeviceKey string `json:"device_key"` //设备key + + ProductKey string `json:"product_key"` //产品key + ProductName string `json:"product_name"` //产品名称 + + ParentDevice string `json:"parent_device"` //上级设备key + ParentDeviceName string `json:"parent_device_name"` //上级设备名称 + + Name string `json:"name"` + Cover string `json:"cover"` //封面 + SN string `json:"sn"` //设备的sn序列号 + + Virtual int `json:"virtual"` //是否虚拟设备,0:不是,1:是 + OnlineStatus int `json:"online_status"` //在线状态,0:未激活,1:在线,2:离线 + OnlineTimestamp int64 `json:"online_timestamp"` //最后在线,时间戳:毫秒级 + + Status int `json:"status"` //状态码,0:无,1:未激活,2:激活可用,3:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type IotDeviceDetailResp struct { + Id int64 `json:"id" ` + + DeviceKey string `json:"device_key"` //设备key + + ProductKey string `json:"product_key"` //产品key + ProductName string `json:"product_name"` //产品名称 + + ParentDevice string `json:"parent_device"` //上级设备key + ParentDeviceName string `json:"parent_device_name"` //上级设备名称 + + Name string `json:"name"` + Describe string `json:"describe"` //简介 + Cover string `json:"cover"` //封面 + Sort int64 `json:"sort"` //排序值,越大越靠前 + SN string `json:"sn"` //设备的sn序列号 + Geo string `json:"geo"` //经纬度,逗号分隔,如:120.15,30.25 + + Virtual int `json:"virtual"` //是否虚拟设备,0:不是,1:是 + OnlineStatus int `json:"online_status"` //在线状态,0:未激活,1:在线,2:离线 + OnlineTimestamp int64 `json:"online_timestamp"` //最后在线,时间戳:毫秒级 + + Status int `json:"status"` //状态码,0:无,1:未激活,2:激活可用,3:禁用 + StatusName string `json:"status_name"` //状态名 + + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} diff --git a/src/domain/events/user.go b/src/domain/events/user.go new file mode 100644 index 0000000000000000000000000000000000000000..3bf550f01eb051d12324c3092e98a3d71fda7a83 --- /dev/null +++ b/src/domain/events/user.go @@ -0,0 +1,10 @@ +package events + +const UserCreated = "UserCreated" //用户创建后触发,参数:userId +const UserUpdated = "UserUpdated" //用户信息更新后触发,参数:userId +const UserDeleted = "UserDeleted" //用户信息更新后触发,参数:userId + +const UserLogin = "UserLogin" //用户登录后触发,参数:userId int64,param dto.RequestInfo +const UserLogout = "UserLogout" //用户退出登录后触发,参数:userId int64,param dto.RequestInfo + +const UserLogRecord = "UserLogRecord" //用户操作记录,参数:string,*http.Request diff --git a/src/domain/interfaces/app.go b/src/domain/interfaces/app.go index 0297b7e3d8a609e7eda5cf5913c4bb99243adb41..1b924f7065df5bcdaccd6270e7525ddec6cd6ab6 100644 --- a/src/domain/interfaces/app.go +++ b/src/domain/interfaces/app.go @@ -2,6 +2,13 @@ package interfaces import "github.com/gin-gonic/gin" +// ItfFullApp 一个完备的app需要的接口 +type ItfFullApp interface { + ItfApp + ItfAppInitialize + ItfAppModule +} + type ItfApp interface { Name() string //app名称 @@ -13,13 +20,26 @@ type ItfApp interface { Stop() error } +type ItfServer ItfApiServer + +// ItfApiServer api服务 type ItfApiServer interface { Start() error Stop() error } -// ItfSupportModule 支持模块服务 -type ItfSupportModule interface { +// ItfAppName app带名称 +type ItfAppName interface { + Name() string +} + +// ItfAppInitialize app初始化支持 +type ItfAppInitialize interface { + Initialize() +} + +// ItfAppModule 支持模块服务 +type ItfAppModule interface { WithModule(t bool) } diff --git a/src/domain/interfaces/controller_gin.go b/src/domain/interfaces/controller_gin.go index 3ccd7b231f68761f8a35cd4d414ddbf00e1f55a9..5ac750efbb9a8e7c72f8982bb23f2ecded0f966b 100644 --- a/src/domain/interfaces/controller_gin.go +++ b/src/domain/interfaces/controller_gin.go @@ -6,6 +6,14 @@ import ( "github.com/gin-gonic/gin" ) +// commonCurdController 通用curd控制器 +type commonCurdController interface { + Search(ctx *gin.Context) + Query(ctx *gin.Context) + Save(ctx *gin.Context) + Delete(ctx *gin.Context) +} + type ItfResponseController interface { Response(ctx *gin.Context, data respdata.ResponseData, msgData ...map[string]string) ResponseCode(ctx *gin.Context, code int, data respdata.ResponseData, msgData ...map[string]string) @@ -140,12 +148,29 @@ type ItfSettingController interface { PutMultiSetting(ctx *gin.Context) } +// ItfTelemetryController 遥测api控制器 type ItfTelemetryController interface { GetLatest(ctx *gin.Context) SearchHistory(ctx *gin.Context) SearchStats(ctx *gin.Context) } +// ItfIotProductController iot产品管理 +type ItfIotProductController interface { + commonCurdController + + Disable(ctx *gin.Context) + QueryThinModel(ctx *gin.Context) //物模型查询 + ImportThinModel(ctx *gin.Context) //物模型导入 +} + +// ItfIotDeviceController iot设备管理 +type ItfIotDeviceController interface { + commonCurdController + + Disable(ctx *gin.Context) +} + // ItfBlockContentController 块内容控制器 type ItfBlockContentController interface { SearchBlock(ctx *gin.Context) @@ -155,8 +180,47 @@ type ItfBlockContentController interface { DisableBlock(ctx *gin.Context) } +// ItfCmsColumnController cms专栏控制器 +type ItfCmsColumnController interface { + SearchColumn(ctx *gin.Context) + QueryColumn(ctx *gin.Context) + SaveColumn(ctx *gin.Context) + DeleteColumn(ctx *gin.Context) + DisableColumn(ctx *gin.Context) +} + +// ItfCmsProductModelController 产品模型控制器 +type ItfCmsProductModelController interface { + commonCurdController + + Disable(ctx *gin.Context) +} + +// ItfCmsArticleModelController 文章模型控制器 +type ItfCmsArticleModelController interface { + commonCurdController + + Disable(ctx *gin.Context) +} + +// ItfCmsPageModelController 单页模型 +type ItfCmsPageModelController interface { + Query(ctx *gin.Context) + Save(ctx *gin.Context) + Delete(ctx *gin.Context) +} + +// ItfRichContentController 富文本内容控制器 +type ItfRichContentController interface { + commonCurdController + + Content(ctx *gin.Context) //供外部查询内容 +} + type ItfJobController interface { - SearchJobs(ctx *gin.Context) + RegJobs(ctx *gin.Context) //已注册jobs + + RunningJobs(ctx *gin.Context) //运行中jobs //QueryJob(ctx *gin.Context) //JobTypes(ctx *gin.Context) } diff --git a/src/domain/interfaces/dao.go b/src/domain/interfaces/dao.go index 9cd6a44ca7c3c303bfa8bd38cb6fbbaa9b1856b4..b75c0a9ae6fc1775949ff91f76765ac2ad23f1c3 100644 --- a/src/domain/interfaces/dao.go +++ b/src/domain/interfaces/dao.go @@ -17,7 +17,7 @@ type ItfAdminDao interface { Update(id int64, admin *models.Admin) (int64, error) Delete(id int64) (int64, error) - ResetStatus(id int64, status int) (int64, error) + SetStatus(id int64, status int) (int64, error) ResetPassword(id int64, password string, noRoot bool) (int64, error) UpdateProInfo(id int64, admin *models.Admin) (int64, error) @@ -85,7 +85,7 @@ type ItfRbacRole interface { Add(*models.RbacRole) (int64, error) Update(int64, *models.RbacRole) (int64, error) Delete(id int64) error - ResetStatus(id int64, status int) (int64, error) + SetStatus(id int64, status int) (int64, error) Use(db *gorm.DB) ItfRbacRole //使用db @@ -119,7 +119,7 @@ type ItfUser interface { LoginNote(id int64, info *dto.LoginInfoParam) (int64, error) //登录记录 - ResetStatus(id int64, status int) (int64, error) + SetStatus(id int64, status int) (int64, error) ResetPassword(id int64, password string) (int64, error) UpdateProInfo(id int64, user *models.User) (int64, error) @@ -206,6 +206,68 @@ type ItfBlockContentDao interface { ItfGormDB } +// ItfCmsColumnDao cms专栏操作dao +type ItfCmsColumnDao interface { + Search(search *dto.SearchCmsColumnParams, pa *paginate.Pager) ([]*models.CmsColumn, *paginate.Pager, error) + Query(id int64) (*models.CmsColumn, error) + Add(code *models.CmsColumn) (int64, error) + Update(id int64, up *models.CmsColumn) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) + SetSort(id int64, sort int) (int64, error) + + Use(db *gorm.DB) ItfCmsColumnDao //使用db + + ItfMigrate + ItfGormDB +} + +// ItfCmsArticleDao cms专栏操作dao +type ItfCmsArticleDao interface { + Search(search *dto.SearchCmsArticleParams, pa *paginate.Pager) ([]*models.CmsArticle, *paginate.Pager, error) + Query(id int64) (*models.CmsArticle, error) + Add(code *models.CmsArticle) (int64, error) + Update(id int64, up *models.CmsArticle) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) + SetSort(id int64, sort int) (int64, error) + + Use(db *gorm.DB) ItfCmsArticleDao //使用db + + ItfMigrate + ItfGormDB +} + +// ItfCmsProductDao cms产品操作dao +type ItfCmsProductDao interface { + Search(search *dto.SearchCmsProductParams, pa *paginate.Pager) ([]*models.CmsProduct, *paginate.Pager, error) + Query(id int64) (*models.CmsProduct, error) + Add(code *models.CmsProduct) (int64, error) + Update(id int64, up *models.CmsProduct) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) + SetSort(id int64, sort int) (int64, error) + + Use(db *gorm.DB) ItfCmsProductDao //使用db + + ItfMigrate + ItfGormDB +} + +// ItfRichContentDao cms内容dao +type ItfRichContentDao interface { + Search(search *dto.SearchRichContentParams, pa *paginate.Pager) ([]*models.RichContent, *paginate.Pager, error) + Query(id int64) (*models.RichContent, error) + Add(code *models.RichContent) (int64, error) + Update(id int64, up *models.RichContent) (int64, error) + Delete(id int64) (int64, error) + + Use(db *gorm.DB) ItfRichContentDao //使用db + + ItfMigrate + ItfGormDB +} + // ItfStatistical 统计相关 type ItfStatistical interface { Search(search *dto.SearchStatisticalParams, pa *paginate.Pager) ([]*models.Statistical, *paginate.Pager, error) @@ -226,7 +288,7 @@ type ItfOrganize interface { Delete(id int64) (int64, error) DeleteByPid(pid int64) (int64, error) - ResetStatus(id int64, status int) (int64, error) + SetStatus(id int64, status int) (int64, error) Use(db *gorm.DB) ItfOrganize //使用db @@ -326,3 +388,35 @@ type ItfMetricStatDataDao interface { ItfMigrate ItfGormDB } + +// ItfIotProductDao iot产品操作dao +type ItfIotProductDao interface { + Search(search *dto.SearchIotProductParams, pa *paginate.Pager) ([]*models.IotProduct, *paginate.Pager, error) + Query(id int64) (*models.IotProduct, error) + Add(code *models.IotProduct) (int64, error) + Update(id int64, up *models.IotProduct) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) + SetSort(id int64, sort int) (int64, error) + + Use(db *gorm.DB) ItfIotProductDao //使用db + + ItfMigrate + ItfGormDB +} + +// ItfIotDeviceDao iot设备操作dao +type ItfIotDeviceDao interface { + Search(search *dto.SearchIotDeviceParams, pa *paginate.Pager) ([]*models.IotDevice, *paginate.Pager, error) + Query(id int64) (*models.IotDevice, error) + Add(code *models.IotDevice) (int64, error) + Update(id int64, up *models.IotDevice) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) + SetSort(id int64, sort int) (int64, error) + + Use(db *gorm.DB) ItfIotDeviceDao //使用db + + ItfMigrate + ItfGormDB +} diff --git a/src/domain/interfaces/dao_facade.go b/src/domain/interfaces/dao_facade.go index 7e1495dff7e11511a79749eef53051de5ed75e8e..d6b4ec378556d4f25c8d498dedc9ca4c229b7289 100644 --- a/src/domain/interfaces/dao_facade.go +++ b/src/domain/interfaces/dao_facade.go @@ -14,7 +14,7 @@ type DBFacade[T interface{}] interface { Add(T) (int64, error) //添加记录 Update(id int64, up T) (int64, error) //更新记录 Delete(id int64) (int64, error) //删除记录 - ResetStatus(id int64, status int) (int64, error) //重置status + SetStatus(id int64, status int) (int64, error) //重置status QueryByScope(apply ...GormApplyQuery) (*T, error) //自定义scope查询单条记录 DeleteByScope(scopes ...GormApplyQuery) (int64, error) diff --git a/src/domain/interfaces/eventbus.go b/src/domain/interfaces/eventbus.go new file mode 100644 index 0000000000000000000000000000000000000000..08badf2f91ad7ded85908357cebc658c1ecf775b --- /dev/null +++ b/src/domain/interfaces/eventbus.go @@ -0,0 +1 @@ +package interfaces diff --git a/src/domain/interfaces/services.go b/src/domain/interfaces/services.go index 3d6925aced456ebbdda5a5f2676103fa0dfc5d9e..9a416d4e795eab5676c2555b1c7c3e9ee513f458 100644 --- a/src/domain/interfaces/services.go +++ b/src/domain/interfaces/services.go @@ -3,6 +3,7 @@ package interfaces import ( "gitee.com/captials-team/ubdframe/src/domain/dto" "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" "gitee.com/captials-team/ubdframe/src/domain/models" ) @@ -25,7 +26,7 @@ type ItfAdminService interface { Search(search *dto.SearchAdminParams, pa *paginate.Pager) ([]*models.Admin, *paginate.Pager, error) - ResetStatus(id int64, status int) (int64, error) + SetStatus(id int64, status int) (int64, error) ResetPassword(id int64, password string) (int64, error) ResetRootPassword(id int64, password string) (int64, error) UpdateProInfo(id int64, profile *dto.UpdateProfileParams) (int64, error) @@ -52,6 +53,49 @@ type ItfBlockContentService interface { Delete(id int64) (int64, error) } +// ItfCmsColumnService 专栏services +type ItfCmsColumnService interface { + Search(search *dto.SearchCmsColumnParams, pa *paginate.Pager) ([]*respdata.CmsColumnListRespItem, *paginate.Pager, error) + Query(id int64) (*respdata.CmsColumnDetailResp, error) + Save(id int64, b *reqdata.AddEditCmsColumnReq) (int64, error) + Create(b *reqdata.AddEditCmsColumnReq) (int64, error) + Update(id int64, b *reqdata.AddEditCmsColumnReq) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) +} + +// ItfCmsProductModelService cms产品模型service +type ItfCmsProductModelService interface { + Search(search *dto.SearchCmsProductParams, pa *paginate.Pager) ([]*respdata.CmsProductListRespItem, *paginate.Pager, error) + Query(id int64) (*respdata.CmsProductDetailResp, error) + Save(id int64, b *reqdata.AddEditCmsProductReq) (int64, error) + Create(b *reqdata.AddEditCmsProductReq) (int64, error) + Update(id int64, b *reqdata.AddEditCmsProductReq) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) +} + +// ItfCmsArticleModelService cms文章模型service +type ItfCmsArticleModelService interface { + Search(search *dto.SearchCmsArticleParams, pa *paginate.Pager) ([]*respdata.CmsArticleListRespItem, *paginate.Pager, error) + Query(id int64) (*respdata.CmsArticleDetailResp, error) + Save(id int64, b *reqdata.AddEditCmsArticleReq) (int64, error) + Create(b *reqdata.AddEditCmsArticleReq) (int64, error) + Update(id int64, b *reqdata.AddEditCmsArticleReq) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) +} + +// ItfRichContentService 富文本内容service +type ItfRichContentService interface { + Search(search *dto.SearchRichContentParams, pa *paginate.Pager) ([]*respdata.RichContentListRespItem, *paginate.Pager, error) + Query(id int64) (*respdata.RichContentDetailResp, error) + Save(id int64, b *reqdata.AddEditRichContentReq) (int64, error) + Create(b *reqdata.AddEditRichContentReq) (int64, error) + Update(id int64, b *reqdata.AddEditRichContentReq) (int64, error) + Delete(id int64) (int64, error) +} + // ItfTelemetryService telemetry遥测service type ItfTelemetryService interface { ItfMetricService @@ -80,6 +124,28 @@ type ItfMetricDataService interface { WriteStat(data []*models.MetricStatData, merge bool) (int64, error) //写入一个统计数据(合并) } +// ItfIotProductService iot产品service +type ItfIotProductService interface { + Search(search *dto.SearchIotProductParams, pa *paginate.Pager) ([]*respdata.IotProductListRespItem, *paginate.Pager, error) + Query(id int64) (*respdata.IotProductDetailResp, error) + Save(id int64, b *reqdata.AddEditIotProductReq) (int64, error) + Create(b *reqdata.AddEditIotProductReq) (int64, error) + Update(id int64, b *reqdata.AddEditIotProductReq) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) +} + +// ItfIotDeviceService iot设备service +type ItfIotDeviceService interface { + Search(search *dto.SearchIotDeviceParams, pa *paginate.Pager) ([]*respdata.IotDeviceListRespItem, *paginate.Pager, error) + Query(id int64) (*respdata.IotDeviceDetailResp, error) + Save(id int64, b *reqdata.AddEditIotDeviceReq) (int64, error) + Create(b *reqdata.AddEditIotDeviceReq) (int64, error) + Update(id int64, b *reqdata.AddEditIotDeviceReq) (int64, error) + Delete(id int64) (int64, error) + SetStatus(id int64, status int) (int64, error) +} + type ItfOrganizeService interface { Search(search dto.SearchOrganizeParams, pa *paginate.Pager) ([]*respdata.OrganizeListItem, *paginate.Pager, error) Tree(search dto.TreeOrganizeParams) ([]*dto.TreeNode[*models.Organize], error) diff --git a/src/domain/models/article.go b/src/domain/models/article.go deleted file mode 100644 index 37e8a66863d93114a6565f00bc85db0104835fb0..0000000000000000000000000000000000000000 --- a/src/domain/models/article.go +++ /dev/null @@ -1,40 +0,0 @@ -package models - -import ( - "gorm.io/gorm/schema" - "time" -) - -type Article struct { - Id int64 `json:"id" gorm:"primaryKey"` - SqlTimeFields - - Title string `json:"title" gorm:"type:varchar(128);"` - SubTitle string `json:"sub_title" gorm:"type:varchar(256)"` - Describe string `json:"describe" gorm:"type:varchar(512)"` //简介 - Cover string `json:"cover" gorm:"type:varchar(256)"` //封面 - Author string `json:"author" gorm:"type:varchar(128)"` - Hits int64 `json:"hits" gorm:"type:int"` - Sort int `json:"sort" gorm:"type:int"` - PublishStart *time.Time `json:"publish_start"` //发布时间开始 - PublishEnd *time.Time `json:"publish_end"` //发布时间结束 - ContentId int64 `json:"content_id"` //对应内容记录id - Extends string `json:"extends" gorm:"type:varchar(512)"` - Status int `json:"status"` //0:无,1:可用,2:禁用 -} - -func (a *Article) TableName(namer schema.Namer) string { - return namer.TableName("article") -} - -type ArticleContent struct { - Id int64 `json:"id" gorm:"primaryKey"` - SqlTimeFields - - Renderer string `json:"renderer" gorm:"type:varchar(20)"` //渲染方式,如:richtext,html,markdown,string等 - Content string `json:"content" gorm:"type:text"` -} - -func (a *ArticleContent) TableName(namer schema.Namer) string { - return namer.TableName("article_content") -} diff --git a/src/domain/models/cms.go b/src/domain/models/cms.go new file mode 100644 index 0000000000000000000000000000000000000000..f29bd2502dd8dad0ae261891326c4b8df636317b --- /dev/null +++ b/src/domain/models/cms.go @@ -0,0 +1,31 @@ +package models + +import "gorm.io/gorm/schema" + +// CmsColumn cms栏目列表 +type CmsColumn struct { + Id int64 `json:"id" gorm:"primaryKey"` + SqlTimeFields + + Name string `json:"name" gorm:"type:varchar(64);"` //栏目名称 + Alias string `json:"alias" gorm:"type:varchar(64);"` //栏目别名,可为英文 + Pic string `json:"pic" gorm:"type:varchar(512);"` //图片 + + Sort int64 `json:"sort" gorm:"index"` //排序值,越大越靠前 + ParentColumn int64 `json:"parent_column" gorm:"default:0;index"` //上级专栏id + + //内容模型,枚举值如: + // article(文章模型), + // page(单页模型), + // product(产品模型), + // picture(图片模型), + // download(下载模型), + // link(链接模型), + //不同模型展示的内容不一样,模型由系统自动加载,后续可由管理站自由添加组合 + Model string `json:"model" gorm:"type:varchar(16);"` + Status int `json:"show" gorm:"type:tinyint"` //状态,0:无,1:可用,2:禁用 +} + +func (a *CmsColumn) TableName(namer schema.Namer) string { + return namer.TableName("cms_column") +} diff --git a/src/domain/models/cms_article.go b/src/domain/models/cms_article.go new file mode 100644 index 0000000000000000000000000000000000000000..27227d0cd84f322d0b656bbbe73e314817e8669c --- /dev/null +++ b/src/domain/models/cms_article.go @@ -0,0 +1,30 @@ +package models + +import ( + "gorm.io/gorm/schema" +) + +// CmsArticle 文章模型 +type CmsArticle struct { + Id int64 `json:"id" gorm:"primaryKey"` + SqlTimeFields + + ColumnId int64 `json:"column_id"` //对应栏目id + + Title string `json:"title" gorm:"type:varchar(128);"` + SubTitle string `json:"sub_title" gorm:"type:varchar(256)"` + Describe string `json:"describe" gorm:"type:varchar(512)"` //简介 + Cover string `json:"cover" gorm:"type:varchar(256)"` //封面 + Author string `json:"author" gorm:"type:varchar(128)"` //作者 + Hits int64 `json:"hits" gorm:"type:int"` //点击量 + Sort int `json:"sort" gorm:"type:int"` //排序值 + PublishStart int64 `json:"publish_start"` //发布时间开始,时间戳 + PublishEnd int64 `json:"publish_end"` //发布时间结束,时间戳 + Content string `json:"content" gorm:"type:varchar(256)"` //对应内容记录(可为url) + Extends string `json:"extends" gorm:"type:varchar(512)"` + Status int `json:"status"` //0:无,1:可用,2:禁用 +} + +func (a *CmsArticle) TableName(namer schema.Namer) string { + return namer.TableName("cms_article") +} diff --git a/src/domain/models/cms_content.go b/src/domain/models/cms_content.go new file mode 100644 index 0000000000000000000000000000000000000000..87bdc5d0f8877d1b94e4f72f2e383bc0d12b1595 --- /dev/null +++ b/src/domain/models/cms_content.go @@ -0,0 +1,16 @@ +package models + +import "gorm.io/gorm/schema" + +// RichContent 富文本内容表(用于不同的内容渲染) +type RichContent struct { + Id int64 `json:"id" gorm:"primaryKey"` + SqlTimeFields + + Render string `json:"render" gorm:"type:varchar(20)"` //渲染方式,如:richtext,html,markdown,string等 + Content string `json:"content" gorm:"type:text"` +} + +func (a *RichContent) TableName(namer schema.Namer) string { + return namer.TableName("rich_content") +} diff --git a/src/domain/models/cms_product.go b/src/domain/models/cms_product.go new file mode 100644 index 0000000000000000000000000000000000000000..425ec772d3d8e2319c227d5e0204bc967369077b --- /dev/null +++ b/src/domain/models/cms_product.go @@ -0,0 +1,27 @@ +package models + +import ( + "gorm.io/gorm/schema" +) + +// CmsProduct 产品表 +type CmsProduct struct { + Id int64 `json:"id" gorm:"primaryKey"` + SqlTimeFields + + ColumnId int64 `json:"column_id"` //对应栏目id + + Title string `json:"title" gorm:"type:varchar(128);"` + SubTitle string `json:"sub_title" gorm:"type:varchar(256)"` + Describe string `json:"describe" gorm:"type:varchar(512)"` //简介 + Cover string `json:"cover" gorm:"type:varchar(256)"` //封面 + Hits int64 `json:"hits" gorm:"type:int"` + Sort int `json:"sort" gorm:"type:int"` + Content string `json:"content" gorm:"type:varchar(256)"` //对应内容记录(可为url) + Extends string `json:"extends" gorm:"type:varchar(512)"` + Status int `json:"status"` //通用状态码 +} + +func (a *CmsProduct) TableName(namer schema.Namer) string { + return namer.TableName("cms_product") +} diff --git a/src/domain/models/iot_device.go b/src/domain/models/iot_device.go new file mode 100644 index 0000000000000000000000000000000000000000..33a6f50464265bf55d0672e1e80f92b2354f1128 --- /dev/null +++ b/src/domain/models/iot_device.go @@ -0,0 +1,35 @@ +package models + +import ( + "gorm.io/gorm/schema" +) + +// IotDevice iot设备表 +type IotDevice struct { + Id int64 `json:"id" gorm:"primaryKey"` + SqlTimeFields + + DeviceKey string `json:"device_key" gorm:"type:varchar(32);"` //设备key + ProductKey string `json:"product_key" gorm:"type:varchar(32);"` //对应产品key + ParentDevice string `json:"parent_device" gorm:"type:varchar(32);"` //上级设备key + + Name string `json:"name" gorm:"type:varchar(128);"` //设备名称 + Describe string `json:"describe" gorm:"type:varchar(512)"` //设备描述 + SN string `json:"sn" gorm:"type:varchar(128);"` //设备的sn序列号 + Cover string `json:"cover" gorm:"type:varchar(256)"` //设备封面 + + Geo string `json:"geo" gorm:"type:varchar(32);"` //经纬度,逗号分隔,如:120.15,30.25 + Sort int `json:"sort" gorm:"type:int"` //排序值,值越大越靠前 + Virtual int `json:"virtual"` //是否虚拟设备,0:不是,1:是 + + OnlineStatus int `json:"online_status"` //在线状态,0:未激活,1:在线,2:离线 + OnlineTimestamp int64 `json:"online_timestamp"` //最后在线,时间戳:毫秒级 + + Status int `json:"status"` //状态码,0:无,1:未激活,2:激活可用,3:禁用 + + Extends string `json:"extends" gorm:"type:varchar(512)"` +} + +func (a *IotDevice) TableName(namer schema.Namer) string { + return namer.TableName("iot_device") +} diff --git a/src/domain/models/iot_product.go b/src/domain/models/iot_product.go new file mode 100644 index 0000000000000000000000000000000000000000..40519ec411e61ad645a7bec3d9a67fa926769296 --- /dev/null +++ b/src/domain/models/iot_product.go @@ -0,0 +1,42 @@ +package models + +import ( + "gorm.io/gorm/schema" +) + +// IotProduct iot产品表 +type IotProduct struct { + Id int64 `json:"id" gorm:"primaryKey"` + SqlTimeFields + + ProductKey string `json:"product_key" gorm:"type:varchar(32);"` //产品key + + Name string `json:"name" gorm:"type:varchar(128);"` //产品名称 + Describe string `json:"describe" gorm:"type:varchar(512)"` //产品描述 + Cover string `json:"cover" gorm:"type:varchar(256)"` //产品封面 + NodeType int `json:"node_type" gorm:"type:int"` //节点类型,0:未知,1:直连设备,2:网关,3:网关子设备 + Extends string `json:"extends" gorm:"type:varchar(512)"` + Status int `json:"status"` //通用状态码,见 consts.StatusEnable +} + +func (a *IotProduct) TableName(namer schema.Namer) string { + return namer.TableName("iot_product") +} + +// IotThingModel iot物模型 +type IotThingModel struct { + Id int64 `json:"id" gorm:"primaryKey"` + SqlTimeFields + + ProductId int64 `json:"product_id"` //产品id + ProductKey string `json:"product_key" gorm:"type:varchar(32);"` //产品key + + Base string `json:"base" gorm:"type:text;"` //基本(除掉下面的属性+事件+服务以外的配置),对应json + Properties string `json:"properties" gorm:"type:text;"` //属性,对应json + Events string `json:"events" gorm:"type:text;"` //事件,对应json + Services string `json:"services" gorm:"type:text;"` //服务,对应json +} + +func (a *IotThingModel) TableName(namer schema.Namer) string { + return namer.TableName("iot_thing_model") +} diff --git a/src/domain/services/admin.go b/src/domain/services/admin.go index 6423ede71520135ef720c0b1e053dd5e09f038c6..e70213be0c18ab8f01e260e60b58f846bfeb6e7c 100644 --- a/src/domain/services/admin.go +++ b/src/domain/services/admin.go @@ -57,8 +57,8 @@ func (s *AdminService) Search(search *dto.SearchAdminParams, pa *paginate.Pager) return s.adminDao.Search(search, pa) } -func (s *AdminService) ResetStatus(id int64, status int) (int64, error) { - return s.adminDao.ResetStatus(id, status) +func (s *AdminService) SetStatus(id int64, status int) (int64, error) { + return s.adminDao.SetStatus(id, status) } func (s *AdminService) ResetPassword(id int64, password string) (int64, error) { diff --git a/src/domain/services/basedata_test.go b/src/domain/services/basedata_test.go index 313ae31a3e9e491f88915d90029e75c3acb21ae5..979c1f91276d72b79ad67f767c3cb2e15a977ab2 100644 --- a/src/domain/services/basedata_test.go +++ b/src/domain/services/basedata_test.go @@ -1,6 +1,7 @@ package services import ( + "gitee.com/captials-team/ubdframe/src/common" "gitee.com/captials-team/ubdframe/src/domain/dto" "gitee.com/captials-team/ubdframe/src/tests" "github.com/stretchr/testify/assert" @@ -30,10 +31,12 @@ func TestDistrictRegionService(t *testing.T) { } for _, v := range regions { - info := srv.Query(v) + info, err := srv.Query(v) + common.ErrPanic(err) t.Logf("====%+v", dto.EncodeRegionItem(info)) - subs := srv.Districts(v) + subs, err := srv.Districts(v) + common.ErrPanic(err) for _, sub := range subs { t.Logf("\t\t%+v", dto.EncodeRegionItem(sub)) } diff --git a/src/domain/services/block.go b/src/domain/services/block.go index 5e4bb31fb287884b0169462c980c260bf98d6d6d..5c2894b6eb9748d865fd88463a43ef14084c7db6 100644 --- a/src/domain/services/block.go +++ b/src/domain/services/block.go @@ -63,10 +63,11 @@ func (s *BlockService) QueryByCode(code string) (*models.BlockContent, error) { } func (s *BlockService) Save(id int64, b *models.BlockContent) (int64, error) { - if id > 0 { - return s.dao.Update(id, b) + if id == 0 { + return s.dao.Add(b) + } - return s.dao.Add(b) + return s.dao.Update(id, b) } func (s *BlockService) Search(search *dto.SearchBlockContentParams, pa *paginate.Pager) ([]*models.BlockContent, *paginate.Pager, error) { diff --git a/src/domain/services/cms_column.go b/src/domain/services/cms_column.go new file mode 100644 index 0000000000000000000000000000000000000000..4a39647cfa7e1fa1da3ec6f1ecc04f0f5d858792 --- /dev/null +++ b/src/domain/services/cms_column.go @@ -0,0 +1,140 @@ +package services + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/consts" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" + "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "gitee.com/captials-team/ubdframe/src/pkg/validate_help" +) + +type CmsColumnService struct { + l v1log.ILog + dao interfaces.ItfCmsColumnDao + + cacheById *caches.CacheFacade[int64, *models.CmsColumn] +} + +func NewCmsColumnService(l v1log.ILog, cmsColumn interfaces.ItfCmsColumnDao, cache caches.ItfCache) *CmsColumnService { + svc := &CmsColumnService{ + l: l, + dao: cmsColumn, + cacheById: caches.NewCacheFacade[int64, *models.CmsColumn](cache), + } + + svc.cacheById.WithValueFunc(svc.cmsColumnCache).WithKeyPrefix("cms_column_") + + return svc +} + +func (s *CmsColumnService) cmsColumnCache(k int64) *models.CmsColumn { + find, err := s.dao.Query(k) + if err != nil { + return nil + } + return find +} + +func (s *CmsColumnService) Search(search *dto.SearchCmsColumnParams, pa *paginate.Pager) ([]*respdata.CmsColumnListRespItem, *paginate.Pager, error) { + var respList []*respdata.CmsColumnListRespItem + list, count, err := s.dao.Search(search, pa) + if err != nil { + return respList, count, err + } + + for _, v := range list { + var item respdata.CmsColumnListRespItem + utils.CopyTo(v, &item) + + item.ModelName = "" + + respList = append(respList, &item) + } + + return respList, count, nil +} + +func (s *CmsColumnService) Query(id int64) (*respdata.CmsColumnDetailResp, error) { + if id <= 0 { + return nil, fmt.Errorf("invalid") + } + data, err := s.dao.Query(id) + if err != nil { + return nil, err + } + var detail respdata.CmsColumnDetailResp + utils.CopyTo(data, &detail) + + return &detail, fmt.Errorf("invalid") +} + +func (s *CmsColumnService) QueryCache(id int64) (*models.CmsColumn, error) { + return s.cacheById.Get(id) +} + +func (s *CmsColumnService) Save(id int64, b *reqdata.AddEditCmsColumnReq) (int64, error) { + if id == 0 { + return s.Create(b) + } + return s.Update(id, b) +} + +func (s *CmsColumnService) Create(b *reqdata.AddEditCmsColumnReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.CmsColumn + utils.CopyTo(b, &save) + return s.dao.Add(&save) +} + +func (s *CmsColumnService) Update(id int64, b *reqdata.AddEditCmsColumnReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.CmsColumn + utils.CopyTo(b, &save) + save.Id = id + return s.dao.Update(id, &save) +} + +func (s *CmsColumnService) Delete(id int64) (int64, error) { + b, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if b == nil { + return 0, nil + } + defer s.cacheById.Delete(id) + + return s.dao.Delete(id) +} + +func (s *CmsColumnService) SetStatus(id int64, status int) (int64, error) { + //验证 + if err := consts.ValidateStatusEnable(status); err != nil { + return 0, err + } + detail, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if detail == nil { + return 0, fmt.Errorf("target not exist") + } + affect, err := s.dao.SetStatus(id, status) + if err != nil { + return 0, err + } + return affect, nil +} diff --git a/src/domain/services/cms_column_test.go b/src/domain/services/cms_column_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ef2ddf321de774367ff05fb1f2acba60df78c574 --- /dev/null +++ b/src/domain/services/cms_column_test.go @@ -0,0 +1,37 @@ +package services + +import ( + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" + "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "gitee.com/captials-team/ubdframe/src/tests" + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +func TestCmsColumnService_Save(t *testing.T) { + s := newCmsColumnService(t) + assert.NotEqual(t, s, nil) + + var id int64 = 0 + //id = 4 + saveId, err := s.Save(id, &reqdata.AddEditCmsColumnReq{ + Name: "xxx", + //Status: 1, + Model: "ddd", + Status: 5, + }) + assert.Equal(t, err, nil) + + t.Logf("Column= %+v,%d", saveId, id) +} + +func newCmsColumnService(t *testing.T) *CmsColumnService { + + columnDao := mysql.NewCmsColumnDao(tests.TestingDBConfig) + columnDao.Migrate() + + return NewCmsColumnService(v1log.NewTestingLog(t, v1log.DebugLog), columnDao, caches.NewMemoryStore(time.Minute*10)) +} diff --git a/src/domain/services/cms_model_article.go b/src/domain/services/cms_model_article.go new file mode 100644 index 0000000000000000000000000000000000000000..f6e1e1870ee2b1acf8815b169018ca40e4eeab49 --- /dev/null +++ b/src/domain/services/cms_model_article.go @@ -0,0 +1,138 @@ +package services + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/consts" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" + "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "gitee.com/captials-team/ubdframe/src/pkg/validate_help" +) + +type CmsArticleModelService struct { + l v1log.ILog + dao interfaces.ItfCmsArticleDao + + cacheById *caches.CacheFacade[int64, *models.CmsArticle] +} + +func NewCmsArticleModelService(l v1log.ILog, cmsArticle interfaces.ItfCmsArticleDao, cache caches.ItfCache) *CmsArticleModelService { + svc := &CmsArticleModelService{ + l: l, + dao: cmsArticle, + cacheById: caches.NewCacheFacade[int64, *models.CmsArticle](cache), + } + + svc.cacheById.WithValueFunc(svc.cmsArticleCache).WithKeyPrefix("cms_article_model_") + + return svc +} + +func (s *CmsArticleModelService) cmsArticleCache(k int64) *models.CmsArticle { + find, err := s.dao.Query(k) + if err != nil { + return nil + } + return find +} + +func (s *CmsArticleModelService) Search(search *dto.SearchCmsArticleParams, pa *paginate.Pager) ([]*respdata.CmsArticleListRespItem, *paginate.Pager, error) { + var respList []*respdata.CmsArticleListRespItem + list, count, err := s.dao.Search(search, pa) + if err != nil { + return respList, count, err + } + + for _, v := range list { + var item respdata.CmsArticleListRespItem + utils.CopyTo(v, &item) + + respList = append(respList, &item) + } + + return respList, count, nil +} + +func (s *CmsArticleModelService) Query(id int64) (*respdata.CmsArticleDetailResp, error) { + if id <= 0 { + return nil, fmt.Errorf("invalid") + } + data, err := s.dao.Query(id) + if err != nil { + return nil, err + } + var detail respdata.CmsArticleDetailResp + utils.CopyTo(data, &detail) + + return &detail, fmt.Errorf("invalid") +} + +func (s *CmsArticleModelService) QueryCache(id int64) (*models.CmsArticle, error) { + return s.cacheById.Get(id) +} + +func (s *CmsArticleModelService) Save(id int64, b *reqdata.AddEditCmsArticleReq) (int64, error) { + if id == 0 { + return s.Create(b) + } + return s.Update(id, b) +} + +func (s *CmsArticleModelService) Create(b *reqdata.AddEditCmsArticleReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.CmsArticle + utils.CopyTo(b, &save) + return s.dao.Add(&save) +} + +func (s *CmsArticleModelService) Update(id int64, b *reqdata.AddEditCmsArticleReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.CmsArticle + utils.CopyTo(b, &save) + save.Id = id + return s.dao.Update(id, &save) +} + +func (s *CmsArticleModelService) Delete(id int64) (int64, error) { + b, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if b == nil { + return 0, nil + } + defer s.cacheById.Delete(id) + + return s.dao.Delete(id) +} + +func (s *CmsArticleModelService) SetStatus(id int64, status int) (int64, error) { + //验证 + if err := consts.ValidateStatusEnable(status); err != nil { + return 0, err + } + detail, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if detail == nil { + return 0, fmt.Errorf("target not exist") + } + affect, err := s.dao.SetStatus(id, status) + if err != nil { + return 0, err + } + return affect, nil +} diff --git a/src/domain/services/cms_model_product.go b/src/domain/services/cms_model_product.go new file mode 100644 index 0000000000000000000000000000000000000000..4c1176d8c977eb1a0e292b19f3857b8feb38433a --- /dev/null +++ b/src/domain/services/cms_model_product.go @@ -0,0 +1,138 @@ +package services + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/consts" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" + "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "gitee.com/captials-team/ubdframe/src/pkg/validate_help" +) + +type CmsProductModelService struct { + l v1log.ILog + dao interfaces.ItfCmsProductDao + + cacheById *caches.CacheFacade[int64, *models.CmsProduct] +} + +func NewCmsProductModelService(l v1log.ILog, cmsProduct interfaces.ItfCmsProductDao, cache caches.ItfCache) *CmsProductModelService { + svc := &CmsProductModelService{ + l: l, + dao: cmsProduct, + cacheById: caches.NewCacheFacade[int64, *models.CmsProduct](cache), + } + + svc.cacheById.WithValueFunc(svc.cmsProductCache).WithKeyPrefix("cms_product_model_") + + return svc +} + +func (s *CmsProductModelService) cmsProductCache(k int64) *models.CmsProduct { + find, err := s.dao.Query(k) + if err != nil { + return nil + } + return find +} + +func (s *CmsProductModelService) Search(search *dto.SearchCmsProductParams, pa *paginate.Pager) ([]*respdata.CmsProductListRespItem, *paginate.Pager, error) { + var respList []*respdata.CmsProductListRespItem + list, count, err := s.dao.Search(search, pa) + if err != nil { + return respList, count, err + } + + for _, v := range list { + var item respdata.CmsProductListRespItem + utils.CopyTo(v, &item) + + respList = append(respList, &item) + } + + return respList, count, nil +} + +func (s *CmsProductModelService) Query(id int64) (*respdata.CmsProductDetailResp, error) { + if id <= 0 { + return nil, fmt.Errorf("invalid") + } + data, err := s.dao.Query(id) + if err != nil { + return nil, err + } + var detail respdata.CmsProductDetailResp + utils.CopyTo(data, &detail) + + return &detail, fmt.Errorf("invalid") +} + +func (s *CmsProductModelService) QueryCache(id int64) (*models.CmsProduct, error) { + return s.cacheById.Get(id) +} + +func (s *CmsProductModelService) Save(id int64, b *reqdata.AddEditCmsProductReq) (int64, error) { + if id == 0 { + return s.Create(b) + } + return s.Update(id, b) +} + +func (s *CmsProductModelService) Create(b *reqdata.AddEditCmsProductReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.CmsProduct + utils.CopyTo(b, &save) + return s.dao.Add(&save) +} + +func (s *CmsProductModelService) Update(id int64, b *reqdata.AddEditCmsProductReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.CmsProduct + utils.CopyTo(b, &save) + save.Id = id + return s.dao.Update(id, &save) +} + +func (s *CmsProductModelService) Delete(id int64) (int64, error) { + b, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if b == nil { + return 0, nil + } + defer s.cacheById.Delete(id) + + return s.dao.Delete(id) +} + +func (s *CmsProductModelService) SetStatus(id int64, status int) (int64, error) { + //验证 + if err := consts.ValidateStatusEnable(status); err != nil { + return 0, err + } + detail, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if detail == nil { + return 0, fmt.Errorf("target not exist") + } + affect, err := s.dao.SetStatus(id, status) + if err != nil { + return 0, err + } + return affect, nil +} diff --git a/src/domain/services/grpc/service_auth.go b/src/domain/services/grpc/service_auth.go index ba9b782ba564932d7ac68ae1e507eb32aaf8f362..42a7a4cab900af9f4893e4ed1bcb874219733406 100644 --- a/src/domain/services/grpc/service_auth.go +++ b/src/domain/services/grpc/service_auth.go @@ -3,7 +3,6 @@ package grpc import ( "context" "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" "gitee.com/captials-team/ubdframe/src/domain/dto" "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" @@ -15,15 +14,13 @@ import ( type UserService struct { l v1log.ILog - conf *configstc.UserAppConfig - cc pbService.UserServiceClient + cc pbService.UserServiceClient } -func NewUserService(di *dig.Container, l v1log.ILog, conf *configstc.UserAppConfig, cc grpc.ClientConnInterface) *UserService { +func NewUserService(di *dig.Container, l v1log.ILog, cc grpc.ClientConnInterface) *UserService { ctr := &UserService{ - l: l, - conf: conf, - cc: pbService.NewUserServiceClient(cc), + l: l, + cc: pbService.NewUserServiceClient(cc), } return ctr diff --git a/src/domain/services/grpc/service_auth_test.go b/src/domain/services/grpc/service_auth_test.go index 93a7c9cb278ccbdb88588a10b4929c6dddad9b6d..23903824234156a67d2cf87fe77d33b99496db02 100644 --- a/src/domain/services/grpc/service_auth_test.go +++ b/src/domain/services/grpc/service_auth_test.go @@ -3,7 +3,6 @@ package grpc import ( "fmt" "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" "gitee.com/captials-team/ubdframe/src/domain/dto" "gitee.com/captials-team/ubdframe/src/pkg/logs" "go.uber.org/dig" @@ -26,7 +25,7 @@ func TestUserService_DoAuth(t *testing.T) { defer conn.Close() di := dig.New() - service := NewUserService(di, logs.Out, &configstc.UserAppConfig{}, conn) + service := NewUserService(di, logs.Out, conn) resp, err := service.DoAuth(&dto.AccountLoginParams{ Account: "user1", Password: "123456", diff --git a/src/domain/services/iot_device.go b/src/domain/services/iot_device.go new file mode 100644 index 0000000000000000000000000000000000000000..6786c6676ad0cb57d54b9d527ed67a6a0b62c4c5 --- /dev/null +++ b/src/domain/services/iot_device.go @@ -0,0 +1,153 @@ +package services + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/consts" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" + "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "gitee.com/captials-team/ubdframe/src/pkg/validate_help" +) + +type IotDeviceService struct { + l v1log.ILog + dao interfaces.ItfIotDeviceDao + + cacheById *caches.CacheFacade[int64, *models.IotDevice] +} + +func NewIotDeviceService(l v1log.ILog, iotDevice interfaces.ItfIotDeviceDao, cache caches.ItfCache) *IotDeviceService { + svc := &IotDeviceService{ + l: l, + dao: iotDevice, + cacheById: caches.NewCacheFacade[int64, *models.IotDevice](cache), + } + + svc.cacheById.WithValueFunc(svc.iotDeviceCache).WithKeyPrefix("iot_device_") + + return svc +} + +func (s *IotDeviceService) iotDeviceCache(k int64) *models.IotDevice { + find, err := s.dao.Query(k) + if err != nil { + return nil + } + return find +} + +func (s *IotDeviceService) Search(search *dto.SearchIotDeviceParams, pa *paginate.Pager) ([]*respdata.IotDeviceListRespItem, *paginate.Pager, error) { + var respList []*respdata.IotDeviceListRespItem + list, count, err := s.dao.Search(search, pa) + if err != nil { + return respList, count, err + } + + for _, v := range list { + var item respdata.IotDeviceListRespItem + utils.CopyTo(v, &item) + + respList = append(respList, &item) + } + + return respList, count, nil +} + +func (s *IotDeviceService) Query(id int64) (*respdata.IotDeviceDetailResp, error) { + if id <= 0 { + return nil, fmt.Errorf("invalid") + } + data, err := s.dao.Query(id) + if err != nil { + return nil, err + } + var detail respdata.IotDeviceDetailResp + utils.CopyTo(data, &detail) + + return &detail, fmt.Errorf("invalid") +} + +func (s *IotDeviceService) QueryCache(id int64) (*models.IotDevice, error) { + return s.cacheById.Get(id) +} + +func (s *IotDeviceService) Save(id int64, b *reqdata.AddEditIotDeviceReq) (int64, error) { + if id == 0 { + return s.Create(b) + } + return s.Update(id, b) +} + +func (s *IotDeviceService) Create(b *reqdata.AddEditIotDeviceReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.IotDevice + utils.CopyTo(b, &save) + return s.dao.Add(&save) +} + +func (s *IotDeviceService) Update(id int64, b *reqdata.AddEditIotDeviceReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.IotDevice + utils.CopyTo(b, &save) + save.Id = id + return s.dao.Update(id, &save) +} + +func (s *IotDeviceService) Delete(id int64) (int64, error) { + b, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if b == nil { + return 0, nil + } + defer s.cacheById.Delete(id) + + return s.dao.Delete(id) +} + +func (s *IotDeviceService) SetStatus(id int64, status int) (int64, error) { + //验证 + if err := consts.ValidateStatusEnable(status); err != nil { + return 0, err + } + detail, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if detail == nil { + return 0, fmt.Errorf("target not exist") + } + affect, err := s.dao.SetStatus(id, status) + if err != nil { + return 0, err + } + return affect, nil +} + +func (s *IotDeviceService) SetSort(id int64, sort int) (int64, error) { + detail, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if detail == nil { + return 0, fmt.Errorf("target not exist") + } + affect, err := s.dao.SetSort(id, sort) + if err != nil { + return 0, err + } + return affect, nil +} diff --git a/src/domain/services/iot_product.go b/src/domain/services/iot_product.go new file mode 100644 index 0000000000000000000000000000000000000000..1649ccc7890237e17837af90c364a70726d9ded3 --- /dev/null +++ b/src/domain/services/iot_product.go @@ -0,0 +1,153 @@ +package services + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/consts" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" + "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "gitee.com/captials-team/ubdframe/src/pkg/validate_help" +) + +type IotProductService struct { + l v1log.ILog + dao interfaces.ItfIotProductDao + + cacheById *caches.CacheFacade[int64, *models.IotProduct] +} + +func NewIotProductService(l v1log.ILog, iotProduct interfaces.ItfIotProductDao, cache caches.ItfCache) *IotProductService { + svc := &IotProductService{ + l: l, + dao: iotProduct, + cacheById: caches.NewCacheFacade[int64, *models.IotProduct](cache), + } + + svc.cacheById.WithValueFunc(svc.iotProductCache).WithKeyPrefix("iot_product_") + + return svc +} + +func (s *IotProductService) iotProductCache(k int64) *models.IotProduct { + find, err := s.dao.Query(k) + if err != nil { + return nil + } + return find +} + +func (s *IotProductService) Search(search *dto.SearchIotProductParams, pa *paginate.Pager) ([]*respdata.IotProductListRespItem, *paginate.Pager, error) { + var respList []*respdata.IotProductListRespItem + list, count, err := s.dao.Search(search, pa) + if err != nil { + return respList, count, err + } + + for _, v := range list { + var item respdata.IotProductListRespItem + utils.CopyTo(v, &item) + + respList = append(respList, &item) + } + + return respList, count, nil +} + +func (s *IotProductService) Query(id int64) (*respdata.IotProductDetailResp, error) { + if id <= 0 { + return nil, fmt.Errorf("invalid") + } + data, err := s.dao.Query(id) + if err != nil { + return nil, err + } + var detail respdata.IotProductDetailResp + utils.CopyTo(data, &detail) + + return &detail, fmt.Errorf("invalid") +} + +func (s *IotProductService) QueryCache(id int64) (*models.IotProduct, error) { + return s.cacheById.Get(id) +} + +func (s *IotProductService) Save(id int64, b *reqdata.AddEditIotProductReq) (int64, error) { + if id == 0 { + return s.Create(b) + } + return s.Update(id, b) +} + +func (s *IotProductService) Create(b *reqdata.AddEditIotProductReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.IotProduct + utils.CopyTo(b, &save) + return s.dao.Add(&save) +} + +func (s *IotProductService) Update(id int64, b *reqdata.AddEditIotProductReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.IotProduct + utils.CopyTo(b, &save) + save.Id = id + return s.dao.Update(id, &save) +} + +func (s *IotProductService) Delete(id int64) (int64, error) { + b, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if b == nil { + return 0, nil + } + defer s.cacheById.Delete(id) + + return s.dao.Delete(id) +} + +func (s *IotProductService) SetStatus(id int64, status int) (int64, error) { + //验证 + if err := consts.ValidateStatusEnable(status); err != nil { + return 0, err + } + detail, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if detail == nil { + return 0, fmt.Errorf("target not exist") + } + affect, err := s.dao.SetStatus(id, status) + if err != nil { + return 0, err + } + return affect, nil +} + +func (s *IotProductService) SetSort(id int64, sort int) (int64, error) { + detail, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if detail == nil { + return 0, fmt.Errorf("target not exist") + } + affect, err := s.dao.SetSort(id, sort) + if err != nil { + return 0, err + } + return affect, nil +} diff --git a/src/domain/services/organize.go b/src/domain/services/organize.go index 4501159777f624c32326f4c63a20dc1e2096f0ed..55ec8596753675dbe9f0bcc5334c914ddbe0cae9 100644 --- a/src/domain/services/organize.go +++ b/src/domain/services/organize.go @@ -293,5 +293,5 @@ func (s *OrganizeService) fixParentRelation(orgId int64, parentId int64) (int64, func (s *OrganizeService) Enable(id int64, status int) (int64, error) { defer s.cacheById.Delete(id) - return s.organizeDao.ResetStatus(id, status) + return s.organizeDao.SetStatus(id, status) } diff --git a/src/domain/services/organize_test.go b/src/domain/services/organize_test.go index 6ae92e917995dce02899c05f343cad772348cb82..d74cf7dd1c532a7e7fa6487eeb1dfd2aa622a526 100644 --- a/src/domain/services/organize_test.go +++ b/src/domain/services/organize_test.go @@ -22,7 +22,7 @@ func TestOrganizeService_Query(t *testing.T) { t.Logf("Org= %+v,%d", find, id) } -func TestOrganizeService_save(t *testing.T) { +func TestOrganizeService_Save(t *testing.T) { s := newOrganizeService(t) assert.NotEqual(t, s, nil) @@ -39,7 +39,7 @@ func TestOrganizeService_save(t *testing.T) { t.Logf("Org= %+v,%d", find, id) } -func TestOrganizeService_delete(t *testing.T) { +func TestOrganizeService_Delete(t *testing.T) { s := newOrganizeService(t) assert.NotEqual(t, s, nil) diff --git a/src/domain/services/rich_content.go b/src/domain/services/rich_content.go new file mode 100644 index 0000000000000000000000000000000000000000..3bd5957ea5b9d9f5b37b30ffcc2a22ccd6881a63 --- /dev/null +++ b/src/domain/services/rich_content.go @@ -0,0 +1,118 @@ +package services + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/dto/reqdata" + "gitee.com/captials-team/ubdframe/src/domain/dto/respdata" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "gitee.com/captials-team/ubdframe/src/pkg/validate_help" +) + +type RichContentService struct { + l v1log.ILog + dao interfaces.ItfRichContentDao + + cacheById *caches.CacheFacade[int64, *models.RichContent] +} + +func NewRichContentService(l v1log.ILog, cmsColumn interfaces.ItfRichContentDao, cache caches.ItfCache) *RichContentService { + svc := &RichContentService{ + l: l, + dao: cmsColumn, + cacheById: caches.NewCacheFacade[int64, *models.RichContent](cache), + } + + svc.cacheById.WithValueFunc(svc.richContentCache).WithKeyPrefix("rich_content_") + + return svc +} + +func (s *RichContentService) richContentCache(k int64) *models.RichContent { + find, err := s.dao.Query(k) + if err != nil { + return nil + } + return find +} + +func (s *RichContentService) Search(search *dto.SearchRichContentParams, pa *paginate.Pager) ([]*respdata.RichContentListRespItem, *paginate.Pager, error) { + var respList []*respdata.RichContentListRespItem + list, count, err := s.dao.Search(search, pa) + if err != nil { + return respList, count, err + } + + for _, v := range list { + var item respdata.RichContentListRespItem + utils.CopyTo(v, &item) + + respList = append(respList, &item) + } + + return respList, count, nil +} + +func (s *RichContentService) Query(id int64) (*respdata.RichContentDetailResp, error) { + if id <= 0 { + return nil, fmt.Errorf("invalid") + } + data, err := s.dao.Query(id) + if err != nil { + return nil, err + } + var detail respdata.RichContentDetailResp + utils.CopyTo(data, &detail) + + return &detail, fmt.Errorf("invalid") +} + +func (s *RichContentService) QueryCache(id int64) (*models.RichContent, error) { + return s.cacheById.Get(id) +} + +func (s *RichContentService) Save(id int64, b *reqdata.AddEditRichContentReq) (int64, error) { + if id == 0 { + return s.Create(b) + } + return s.Update(id, b) +} + +func (s *RichContentService) Create(b *reqdata.AddEditRichContentReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.RichContent + utils.CopyTo(b, &save) + return s.dao.Add(&save) +} + +func (s *RichContentService) Update(id int64, b *reqdata.AddEditRichContentReq) (int64, error) { + //验证 + if err := validate_help.FastValidateStruct(b); err != nil { + return 0, err + } + var save models.RichContent + utils.CopyTo(b, &save) + save.Id = id + return s.dao.Update(id, &save) +} + +func (s *RichContentService) Delete(id int64) (int64, error) { + b, err := s.dao.Query(id) + if err != nil { + return 0, err + } + if b == nil { + return 0, nil + } + defer s.cacheById.Delete(id) + + return s.dao.Delete(id) +} diff --git a/src/domain/services/rss.go b/src/domain/services/rss.go index 632fe6d1e15faffc84f692142de12488a0d27306..6030dba09ca2576b3b304722a9dbd78597c82d80 100644 --- a/src/domain/services/rss.go +++ b/src/domain/services/rss.go @@ -1,8 +1,8 @@ package services import ( - "gitee.com/captials-team/ubdframe/src/domain/vo" "gitee.com/captials-team/ubdframe/src/infrastructure/caches" + "gitee.com/captials-team/ubdframe/src/pkg/rsshelp" ) -type RssCache = *caches.CacheFacade[string, *vo.RssBody] +type RssCache = *caches.CacheFacade[string, *rsshelp.RssBody] diff --git a/src/domain/services/user.go b/src/domain/services/user.go index d804cb1dd60172bfd88a0dfd6644db2b970e57d5..db31b3cb98fa3e8f6b2ac34dfb2d24d10fc8e4d3 100644 --- a/src/domain/services/user.go +++ b/src/domain/services/user.go @@ -42,10 +42,10 @@ func (s *UserService) AutoCreateUser(nickname string, account string, password s } func (s *UserService) SaveUser(id int64, up *models.User) (int64, error) { - if id > 0 { - return s.updateUser(id, up) + if id == 0 { + return s.createUser(up) } - return s.createUser(up) + return s.updateUser(id, up) } func (s *UserService) createUser(user *models.User) (int64, error) { diff --git a/src/domain/vo/rss.go b/src/domain/vo/rss.go index b254f7e10faefae9aba7e3f5b44f64f38cf936ae..1e0f122d80d7a1ce8ae7860c6d1d12fa13af7d6c 100644 --- a/src/domain/vo/rss.go +++ b/src/domain/vo/rss.go @@ -1,51 +1,2 @@ package vo -import ( - "encoding/xml" - "io" -) - -// RssMeta 源信息 -type RssMeta struct { - Name string - RssUrl string -} - -// RssBody rss内容body -type RssBody struct { - Channel RssChannel `xml:"channel"` -} - -type RssChannel struct { - Title string `xml:"title"` - Description string `xml:"description"` - Link string `xml:"link"` - PubDate string `xml:"pubDate"` - Language string `xml:"language"` - Copyright string `xml:"copyright"` - Generator string `xml:"generator"` - Image struct { - Title string `xml:"title"` - Url string `xml:"url"` - Link string `xml:"link"` - } `xml:"image"` - Items []*RssItems `xml:"item"` -} - -type RssItems struct { - Title string `json:"title" xml:"title"` //新闻标题 - Author string `json:"author" xml:"author"` //作者 - Link string `json:"link" xml:"link"` //连接 - PubDate string `json:"pubDate" xml:"pubDate"` //发布日期/时间 - Description string `json:"description" xml:"description"` //描述信息 -} - -func (rss *RssBody) Parse(r io.Reader) error { - decoder := xml.NewDecoder(r) - err := decoder.Decode(rss) - if err != nil { - return err - } - - return nil -} diff --git a/src/infrastructure/dao/help.go b/src/infrastructure/dao/help.go index 9363f4f6333372accba029020d3c3da624f824fc..447826704faf6bff0c087d9b361b5575f680a939 100644 --- a/src/infrastructure/dao/help.go +++ b/src/infrastructure/dao/help.go @@ -33,3 +33,8 @@ func (h *SplitTableDaoHelp) SetSplitStrategyById(f1 func(int64) string) { func (h *SplitTableDaoHelp) SetSplitStrategyByKey(f2 func(string) string) { h.f2 = f2 } + +func InitMigrate[T interfaces.ItfMigrate](d T) error { + _, err := d.Migrate() + return err +} diff --git a/src/infrastructure/dao/mysql/admin.go b/src/infrastructure/dao/mysql/admin.go index b4c4daccf30bc14473a00e4c214687b3bb33185e..3c8a541a0dc13f14cc1ad0c581cf690d637ba29f 100644 --- a/src/infrastructure/dao/mysql/admin.go +++ b/src/infrastructure/dao/mysql/admin.go @@ -151,7 +151,7 @@ func (dao *AdminDao) QueryPassword(id int64) (string, string, error) { return info.Password, info.Salt, nil } -func (dao *AdminDao) ResetStatus(id int64, status int) (int64, error) { +func (dao *AdminDao) SetStatus(id int64, status int) (int64, error) { // 根据条件更新 db := dao.db.Model(&models.Admin{}) ret := db.Where("id = ?", id).Where("is_root=0").Update("status", status) diff --git a/src/infrastructure/dao/mysql/admin_test.go b/src/infrastructure/dao/mysql/admin_test.go index bc57b773994654eba239f6b58befa27212882a1c..fdbd0907783764667d5449e9d88f66559e8ce762 100644 --- a/src/infrastructure/dao/mysql/admin_test.go +++ b/src/infrastructure/dao/mysql/admin_test.go @@ -3,12 +3,13 @@ package mysql import ( "gitee.com/captials-team/ubdframe/src/common" "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" "gitee.com/captials-team/ubdframe/src/domain/dto" "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" "gitee.com/captials-team/ubdframe/src/domain/interfaces" "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/dao" "gitee.com/captials-team/ubdframe/src/pkg/passwd" + "gitee.com/captials-team/ubdframe/src/tests" "github.com/stretchr/testify/assert" "go.uber.org/dig" "os" @@ -104,7 +105,7 @@ func TestAdminUpdate(t *testing.T) { })) } -func TestAdminResetStatus(t *testing.T) { +func TestAdminSetStatus(t *testing.T) { di := testModelDao() err := di.Invoke(func(sd interfaces.ItfAdminDao) { ad := &models.Admin{ @@ -125,7 +126,7 @@ func TestAdminResetStatus(t *testing.T) { assert.Equal(t, info.Status, ad.Status) - _, err = sd.ResetStatus(id, 2) + _, err = sd.SetStatus(id, 2) assert.Equal(t, nil, err) info, err = sd.Query(id) @@ -287,20 +288,9 @@ func testModelDao() *dig.Container { common.ErrPanic(os.Setenv("TZ", "Asia/Shanghai")) di := dig.New() - common.ErrPanic(di.Provide(func() *dig.Container { - return di - })) - common.ErrPanic(di.Provide(func() configstc.DBConfig { - return configstc.DBConfig{ - DbConn: "mysql", - DbHost: "192.168.149.128", - DbPort: "3306", - DbUser: "root", - DbPassword: "root", - DbName: "db_test", - TablePrefix: "micro_", - } - })) + + common.ErrPanic(di.Provide(tests.GetTestingDBConfig)) + common.ErrPanic(di.Provide(NewAdminDao, dig.As(new(interfaces.ItfAdminDao)))) common.ErrPanic(di.Provide(NewAdminLogDao, dig.As(new(interfaces.ItfAdminLog)))) common.ErrPanic(di.Provide(NewRbacDao, dig.As(new(interfaces.ItfRbac)))) @@ -310,36 +300,14 @@ func testModelDao() *dig.Container { common.ErrPanic(di.Provide(NewUserGenericRecordDao, dig.As(new(interfaces.ItfUserGenericRecord)))) common.ErrPanic(di.Provide(NewBlockContentDao, dig.As(new(interfaces.ItfBlockContentDao)))) - common.ErrPanic(di.Invoke(func( - adminModel interfaces.ItfAdminDao, - adminLogModel interfaces.ItfAdminLog, rbac interfaces.ItfRbac, setting interfaces.ItfSettingDao, - user interfaces.ItfUser, genericRecord interfaces.ItfUserGenericRecord, - blockContent interfaces.ItfBlockContentDao, - ) { - var err error - - _, err = adminModel.Migrate() - common.ErrPanic(err) - - _, err = adminLogModel.Migrate() - common.ErrPanic(err) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfAdminDao])) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfAdminLog])) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfRbac])) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfRbacRole])) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfSettingDao])) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfUser])) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfUserGenericRecord])) + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfBlockContentDao])) - _, err = rbac.Migrate() - common.ErrPanic(err) - - _, err = setting.Migrate() - common.ErrPanic(err) - - _, err = user.Migrate() - common.ErrPanic(err) - - _, err = genericRecord.Migrate() - common.ErrPanic(err) - - _, err = blockContent.Migrate() - common.ErrPanic(err) - - return - })) return di } diff --git a/src/infrastructure/dao/mysql/cms_article.go b/src/infrastructure/dao/mysql/cms_article.go new file mode 100644 index 0000000000000000000000000000000000000000..ac2a74806c16272d4285a31b00c89d841532e657 --- /dev/null +++ b/src/infrastructure/dao/mysql/cms_article.go @@ -0,0 +1,162 @@ +package mysql + +import ( + "errors" + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + mysqlClients "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql" + "gorm.io/gorm" +) + +func NewCmsArticleDao(conf configstc.DBConfig) *CmsArticleDao { + return &CmsArticleDao{ + db: mysqlClients.NewGormDB(conf), + conf: conf, + } +} + +type CmsArticleDao struct { + db *gorm.DB + conf configstc.DBConfig +} + +func (dao *CmsArticleDao) Search(search *dto.SearchCmsArticleParams, pa *paginate.Pager) ([]*models.CmsArticle, *paginate.Pager, error) { + if search == nil { + search = &dto.SearchCmsArticleParams{} + } + if pa == nil { + pa = &paginate.Pager{} + } + pa.Correct() + + db := dao.db.Model(new(models.CmsArticle)) + + var list []*models.CmsArticle + + if search.Keywords != "" { + keywords := "%" + search.Keywords + "%" + db = db.Where("(title like ? OR sub_title like ?)", keywords) + } + if search.Status > 0 { + db = db.Where("status=?", search.Status) + } + if search.CmsColumn > 0 { + db = db.Where("column_id=?", search.CmsColumn) + } + if ret := db.Count(&pa.Total); ret.Error != nil { + return list, pa, ret.Error + } + + db = db.Order("id desc") + if pa.PagingId > 0 { + db = db.Where("id 0 { + return 0, fmt.Errorf("not support update") + } + ret := dao.db.Model(add).Create(add) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("add fail") + } + + return add.Id, nil +} + +func (dao *CmsArticleDao) Update(id int64, up *models.CmsArticle) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + up.Id = id + + ret := dao.db.Select("title", "sub_title", "describe", "cover", "author", "hits", "sort", "column_id", "content_id", "publish_start", "publish_end", "status").Save(up) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsArticleDao) SetSort(id int64, sort int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.CmsArticle)).Where("id=?", id).Update("sort", sort) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsArticleDao) Query(id int64) (*models.CmsArticle, error) { + var info models.CmsArticle + ret := dao.db.Model(&info).First(&info, "id = ?", id) + if errors.Is(ret.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + if ret.Error != nil { + return nil, ret.Error + } + return &info, nil +} + +func (dao *CmsArticleDao) Delete(id int64) (int64, error) { + ret := dao.db.Where("id=?", id).Delete(&models.CmsArticle{}) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no delete") + } + return ret.RowsAffected, nil +} + +func (dao *CmsArticleDao) SetStatus(id int64, status int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.CmsArticle)).Where("id=?", id).Update("status", status) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsArticleDao) Migrate() (int64, error) { + return 1, dao.db.AutoMigrate(new(models.CmsArticle)) +} + +func (dao *CmsArticleDao) Use(db *gorm.DB) interfaces.ItfCmsArticleDao { + return &CmsArticleDao{db: db} +} + +func (dao *CmsArticleDao) DB() *gorm.DB { + return dao.db +} diff --git a/src/infrastructure/dao/mysql/cms_article_test.go b/src/infrastructure/dao/mysql/cms_article_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e9ea326e097df9ee1c7097c6e79b41eaceaebacf --- /dev/null +++ b/src/infrastructure/dao/mysql/cms_article_test.go @@ -0,0 +1,66 @@ +package mysql + +import ( + "gitee.com/captials-team/ubdframe/src/common" + "gitee.com/captials-team/ubdframe/src/common/consts" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + "gitee.com/captials-team/ubdframe/src/infrastructure/dao" + "gitee.com/captials-team/ubdframe/src/tests" + "github.com/stretchr/testify/assert" + "go.uber.org/dig" + "os" + "testing" + "time" +) + +func TestCmsModelDao_Add(t *testing.T) { + di := testCmsModelDao() + common.ErrPanic(di.Invoke(func(sd interfaces.ItfCmsArticleDao) { + add := &models.CmsArticle{ + ColumnId: 1, + Title: "章节12-巨兔", + SubTitle: "巨兔突然出现,惊动一众人", + Describe: "", + Cover: "127.0.0.1/img/a.png", + Author: "Any", + Hits: 12, + Sort: 12, + PublishStart: time.Now().UnixMilli(), + PublishEnd: 0, + Content: "", + Extends: "", + Status: consts.StatusEnable, + } + + //添加 + id, err := sd.Add(add) + assert.Equal(t, err, nil) + assert.Equal(t, id, add.Id) + assert.Greater(t, id, int64(0)) + + list, pa, err := sd.Search(nil, nil) + assert.Equal(t, err, nil) + assert.NotEqual(t, len(list), int(0)) + assert.GreaterOrEqual(t, pa.Total, int64(len(list))) + for _, v := range list { + t.Logf("\t%+v", v) + } + + find := list[0] + t.Logf("%d-%d", find.Id, add.Id) + assert.Equal(t, find.Id, add.Id) + })) +} + +func testCmsModelDao() *dig.Container { + common.ErrPanic(os.Setenv("TZ", "Asia/Shanghai")) + + di := dig.New() + + common.ErrPanic(di.Provide(tests.GetTestingDBConfig)) + common.ErrPanic(di.Provide(NewCmsArticleDao, dig.As(new(interfaces.ItfCmsArticleDao)))) + + common.ErrPanic(di.Invoke(dao.InitMigrate[interfaces.ItfCmsArticleDao])) + return di +} diff --git a/src/infrastructure/dao/mysql/cms_column.go b/src/infrastructure/dao/mysql/cms_column.go new file mode 100644 index 0000000000000000000000000000000000000000..f6cda2cdc97634dd8a5353747f86f7b3af6669fa --- /dev/null +++ b/src/infrastructure/dao/mysql/cms_column.go @@ -0,0 +1,162 @@ +package mysql + +import ( + "errors" + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + mysqlClients "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql" + "gorm.io/gorm" +) + +func NewCmsColumnDao(conf configstc.DBConfig) *CmsColumnDao { + return &CmsColumnDao{ + db: mysqlClients.NewGormDB(conf), + conf: conf, + } +} + +type CmsColumnDao struct { + db *gorm.DB + conf configstc.DBConfig +} + +func (dao *CmsColumnDao) Search(search *dto.SearchCmsColumnParams, pa *paginate.Pager) ([]*models.CmsColumn, *paginate.Pager, error) { + if search == nil { + search = &dto.SearchCmsColumnParams{} + } + if pa == nil { + pa = &paginate.Pager{} + } + pa.Correct() + + db := dao.db.Model(new(models.CmsColumn)) + + var list []*models.CmsColumn + + if search.Keywords != "" { + keywords := "%" + search.Keywords + "%" + db = db.Where("(name like ?)", keywords) + } + if search.Status > 0 { + db = db.Where("status=?", search.Status) + } + if search.ParentColumn > 0 { + db = db.Where("parent_column=?", search.ParentColumn) + } + if ret := db.Count(&pa.Total); ret.Error != nil { + return list, pa, ret.Error + } + + db = db.Order("id desc") + if pa.PagingId > 0 { + db = db.Where("id 0 { + return 0, fmt.Errorf("not support update") + } + ret := dao.db.Model(add).Create(add) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("add fail") + } + + return add.Id, nil +} + +func (dao *CmsColumnDao) Update(id int64, up *models.CmsColumn) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + up.Id = id + + ret := dao.db.Select("name", "alias", "pic", "sort", "parent_column", "model", "status").Save(up) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsColumnDao) SetSort(id int64, sort int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.CmsColumn)).Where("id=?", id).Update("sort", sort) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsColumnDao) SetStatus(id int64, status int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.CmsColumn)).Where("id=?", id).Update("status", status) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsColumnDao) Query(id int64) (*models.CmsColumn, error) { + var info models.CmsColumn + ret := dao.db.Model(&info).First(&info, "id = ?", id) + if errors.Is(ret.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + if ret.Error != nil { + return nil, ret.Error + } + return &info, nil +} + +func (dao *CmsColumnDao) Delete(id int64) (int64, error) { + ret := dao.db.Where("id=?", id).Delete(&models.CmsColumn{}) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no delete") + } + return ret.RowsAffected, nil +} + +func (dao *CmsColumnDao) Migrate() (int64, error) { + return 1, dao.db.AutoMigrate(new(models.CmsColumn)) +} + +func (dao *CmsColumnDao) Use(db *gorm.DB) interfaces.ItfCmsColumnDao { + return &CmsColumnDao{db: db} +} + +func (dao *CmsColumnDao) DB() *gorm.DB { + return dao.db +} diff --git a/src/infrastructure/dao/mysql/cms_content.go b/src/infrastructure/dao/mysql/cms_content.go new file mode 100644 index 0000000000000000000000000000000000000000..9b64a9f3a465f3882cc91284308babefb042421e --- /dev/null +++ b/src/infrastructure/dao/mysql/cms_content.go @@ -0,0 +1,125 @@ +package mysql + +import ( + "errors" + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + mysqlClients "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql" + "gorm.io/gorm" +) + +func NewRichContentDao(conf configstc.DBConfig) *RichContentDao { + return &RichContentDao{ + db: mysqlClients.NewGormDB(conf), + conf: conf, + } +} + +type RichContentDao struct { + db *gorm.DB + conf configstc.DBConfig +} + +func (dao *RichContentDao) Search(search *dto.SearchRichContentParams, pa *paginate.Pager) ([]*models.RichContent, *paginate.Pager, error) { + if search == nil { + search = &dto.SearchRichContentParams{} + } + if pa == nil { + pa = &paginate.Pager{} + } + pa.Correct() + + db := dao.db.Model(new(models.RichContent)) + + var list []*models.RichContent + + if search.Render != "" { + db = db.Where("render = ?", search.Render) + } + if ret := db.Count(&pa.Total); ret.Error != nil { + return list, pa, ret.Error + } + + db = db.Order("id desc") + if pa.PagingId > 0 { + db = db.Where("id 0 { + return 0, fmt.Errorf("not support update") + } + ret := dao.db.Model(add).Create(add) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("add fail") + } + + return add.Id, nil +} + +func (dao *RichContentDao) Update(id int64, up *models.RichContent) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + up.Id = id + + ret := dao.db.Select("render", "content").Save(up) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *RichContentDao) Query(id int64) (*models.RichContent, error) { + var info models.RichContent + ret := dao.db.Model(&info).First(&info, "id = ?", id) + if errors.Is(ret.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + if ret.Error != nil { + return nil, ret.Error + } + return &info, nil +} + +func (dao *RichContentDao) Delete(id int64) (int64, error) { + ret := dao.db.Where("id=?", id).Delete(&models.RichContent{}) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no delete") + } + return ret.RowsAffected, nil +} + +func (dao *RichContentDao) Migrate() (int64, error) { + return 1, dao.db.AutoMigrate(new(models.RichContent)) +} + +func (dao *RichContentDao) Use(db *gorm.DB) interfaces.ItfRichContentDao { + return &RichContentDao{db: db} +} + +func (dao *RichContentDao) DB() *gorm.DB { + return dao.db +} diff --git a/src/infrastructure/dao/mysql/cms_product.go b/src/infrastructure/dao/mysql/cms_product.go new file mode 100644 index 0000000000000000000000000000000000000000..d6ac335df284235adb6a8af596e5f98f00b580cc --- /dev/null +++ b/src/infrastructure/dao/mysql/cms_product.go @@ -0,0 +1,162 @@ +package mysql + +import ( + "errors" + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + mysqlClients "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql" + "gorm.io/gorm" +) + +func NewCmsProductDao(conf configstc.DBConfig) *CmsProductDao { + return &CmsProductDao{ + db: mysqlClients.NewGormDB(conf), + conf: conf, + } +} + +type CmsProductDao struct { + db *gorm.DB + conf configstc.DBConfig +} + +func (dao *CmsProductDao) Search(search *dto.SearchCmsProductParams, pa *paginate.Pager) ([]*models.CmsProduct, *paginate.Pager, error) { + if search == nil { + search = &dto.SearchCmsProductParams{} + } + if pa == nil { + pa = &paginate.Pager{} + } + pa.Correct() + + db := dao.db.Model(new(models.CmsProduct)) + + var list []*models.CmsProduct + + if search.Keywords != "" { + keywords := "%" + search.Keywords + "%" + db = db.Where("(name like ?)", keywords) + } + if search.Status > 0 { + db = db.Where("status=?", search.Status) + } + if search.CmsColumn > 0 { + db = db.Where("column_id=?", search.CmsColumn) + } + if ret := db.Count(&pa.Total); ret.Error != nil { + return list, pa, ret.Error + } + + db = db.Order("id desc") + if pa.PagingId > 0 { + db = db.Where("id 0 { + return 0, fmt.Errorf("not support update") + } + ret := dao.db.Model(add).Create(add) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("add fail") + } + + return add.Id, nil +} + +func (dao *CmsProductDao) Update(id int64, up *models.CmsProduct) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + up.Id = id + + ret := dao.db.Select("title", "sub_title", "describe", "cover", "hits", "sort", "column_id", "content_id", "status").Save(up) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsProductDao) SetSort(id int64, sort int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.CmsProduct)).Where("id=?", id).Update("sort", sort) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsProductDao) Query(id int64) (*models.CmsProduct, error) { + var info models.CmsProduct + ret := dao.db.Model(&info).First(&info, "id = ?", id) + if errors.Is(ret.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + if ret.Error != nil { + return nil, ret.Error + } + return &info, nil +} + +func (dao *CmsProductDao) Delete(id int64) (int64, error) { + ret := dao.db.Where("id=?", id).Delete(&models.CmsProduct{}) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no delete") + } + return ret.RowsAffected, nil +} + +func (dao *CmsProductDao) SetStatus(id int64, status int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.CmsProduct)).Where("id=?", id).Update("status", status) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *CmsProductDao) Migrate() (int64, error) { + return 1, dao.db.AutoMigrate(new(models.CmsProduct)) +} + +func (dao *CmsProductDao) Use(db *gorm.DB) interfaces.ItfCmsProductDao { + return &CmsProductDao{db: db} +} + +func (dao *CmsProductDao) DB() *gorm.DB { + return dao.db +} diff --git a/src/infrastructure/dao/mysql/db_help.go b/src/infrastructure/dao/mysql/db_help.go index 6d308e227a82b30e2aae2dfc55a30c9e3ab04719..49dbc6866bb66795c11417380eca9e74df187a18 100644 --- a/src/infrastructure/dao/mysql/db_help.go +++ b/src/infrastructure/dao/mysql/db_help.go @@ -189,7 +189,7 @@ func (fa *GormDBFacade[T]) DeleteByScope(scopes ...interfaces.GormApplyQuery) (i return ret.RowsAffected, ret.Error } -func (fa *GormDBFacade[T]) ResetStatus(id int64, status int) (int64, error) { +func (fa *GormDBFacade[T]) SetStatus(id int64, status int) (int64, error) { db := fa.db.Model(fa.model) ret := db.Model(new(T)).Where("id=?", id).Update("status", status) if ret.Error != nil { diff --git a/src/infrastructure/dao/mysql/iot_device.go b/src/infrastructure/dao/mysql/iot_device.go new file mode 100644 index 0000000000000000000000000000000000000000..77ce94a0614c5fd2f91c56fbc9fabe4cf3cc41b9 --- /dev/null +++ b/src/infrastructure/dao/mysql/iot_device.go @@ -0,0 +1,159 @@ +package mysql + +import ( + "errors" + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + mysqlClients "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql" + "gorm.io/gorm" +) + +func NewIotDeviceDao(conf configstc.DBConfig) *IotDeviceDao { + return &IotDeviceDao{ + db: mysqlClients.NewGormDB(conf), + conf: conf, + } +} + +type IotDeviceDao struct { + db *gorm.DB + conf configstc.DBConfig +} + +func (dao *IotDeviceDao) Search(search *dto.SearchIotDeviceParams, pa *paginate.Pager) ([]*models.IotDevice, *paginate.Pager, error) { + if search == nil { + search = &dto.SearchIotDeviceParams{} + } + if pa == nil { + pa = &paginate.Pager{} + } + pa.Correct() + + db := dao.db.Model(new(models.IotDevice)) + + var list []*models.IotDevice + + if search.Keywords != "" { + keywords := "%" + search.Keywords + "%" + db = db.Where("(name like ?)", keywords) + } + if search.Status > 0 { + db = db.Where("status=?", search.Status) + } + if ret := db.Count(&pa.Total); ret.Error != nil { + return list, pa, ret.Error + } + + db = db.Order("id desc") + if pa.PagingId > 0 { + db = db.Where("id 0 { + return 0, fmt.Errorf("not support update") + } + ret := dao.db.Model(add).Create(add) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("add fail") + } + + return add.Id, nil +} + +func (dao *IotDeviceDao) Update(id int64, up *models.IotDevice) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + up.Id = id + + ret := dao.db.Select("title", "sub_title", "describe", "cover", "hits", "sort", "column_id", "content_id", "status").Save(up) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *IotDeviceDao) SetSort(id int64, sort int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.IotDevice)).Where("id=?", id).Update("sort", sort) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *IotDeviceDao) Query(id int64) (*models.IotDevice, error) { + var info models.IotDevice + ret := dao.db.Model(&info).First(&info, "id = ?", id) + if errors.Is(ret.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + if ret.Error != nil { + return nil, ret.Error + } + return &info, nil +} + +func (dao *IotDeviceDao) Delete(id int64) (int64, error) { + ret := dao.db.Where("id=?", id).Delete(&models.IotDevice{}) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no delete") + } + return ret.RowsAffected, nil +} + +func (dao *IotDeviceDao) SetStatus(id int64, status int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.IotDevice)).Where("id=?", id).Update("status", status) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *IotDeviceDao) Migrate() (int64, error) { + return 1, dao.db.AutoMigrate(new(models.IotDevice)) +} + +func (dao *IotDeviceDao) Use(db *gorm.DB) interfaces.ItfIotDeviceDao { + return &IotDeviceDao{db: db} +} + +func (dao *IotDeviceDao) DB() *gorm.DB { + return dao.db +} diff --git a/src/infrastructure/dao/mysql/iot_product.go b/src/infrastructure/dao/mysql/iot_product.go new file mode 100644 index 0000000000000000000000000000000000000000..2d12128c56285329becaf0d2993544e9bf21ffce --- /dev/null +++ b/src/infrastructure/dao/mysql/iot_product.go @@ -0,0 +1,159 @@ +package mysql + +import ( + "errors" + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/domain/dto" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + "gitee.com/captials-team/ubdframe/src/domain/models" + mysqlClients "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql" + "gorm.io/gorm" +) + +func NewIotProductDao(conf configstc.DBConfig) *IotProductDao { + return &IotProductDao{ + db: mysqlClients.NewGormDB(conf), + conf: conf, + } +} + +type IotProductDao struct { + db *gorm.DB + conf configstc.DBConfig +} + +func (dao *IotProductDao) Search(search *dto.SearchIotProductParams, pa *paginate.Pager) ([]*models.IotProduct, *paginate.Pager, error) { + if search == nil { + search = &dto.SearchIotProductParams{} + } + if pa == nil { + pa = &paginate.Pager{} + } + pa.Correct() + + db := dao.db.Model(new(models.IotProduct)) + + var list []*models.IotProduct + + if search.Keywords != "" { + keywords := "%" + search.Keywords + "%" + db = db.Where("(name like ?)", keywords) + } + if search.Status > 0 { + db = db.Where("status=?", search.Status) + } + if ret := db.Count(&pa.Total); ret.Error != nil { + return list, pa, ret.Error + } + + db = db.Order("id desc") + if pa.PagingId > 0 { + db = db.Where("id 0 { + return 0, fmt.Errorf("not support update") + } + ret := dao.db.Model(add).Create(add) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("add fail") + } + + return add.Id, nil +} + +func (dao *IotProductDao) Update(id int64, up *models.IotProduct) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + up.Id = id + + ret := dao.db.Select("title", "sub_title", "describe", "cover", "hits", "sort", "column_id", "content_id", "status").Save(up) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *IotProductDao) SetSort(id int64, sort int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.IotProduct)).Where("id=?", id).Update("sort", sort) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *IotProductDao) Query(id int64) (*models.IotProduct, error) { + var info models.IotProduct + ret := dao.db.Model(&info).First(&info, "id = ?", id) + if errors.Is(ret.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + if ret.Error != nil { + return nil, ret.Error + } + return &info, nil +} + +func (dao *IotProductDao) Delete(id int64) (int64, error) { + ret := dao.db.Where("id=?", id).Delete(&models.IotProduct{}) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no delete") + } + return ret.RowsAffected, nil +} + +func (dao *IotProductDao) SetStatus(id int64, status int) (int64, error) { + if id <= 0 { + return 0, fmt.Errorf("not find info") + } + + ret := dao.db.Model(new(models.IotProduct)).Where("id=?", id).Update("status", status) + if ret.Error != nil { + return 0, ret.Error + } + if ret.RowsAffected == 0 { + return 0, fmt.Errorf("no update") + } + return ret.RowsAffected, nil +} + +func (dao *IotProductDao) Migrate() (int64, error) { + return 1, dao.db.AutoMigrate(new(models.IotProduct)) +} + +func (dao *IotProductDao) Use(db *gorm.DB) interfaces.ItfIotProductDao { + return &IotProductDao{db: db} +} + +func (dao *IotProductDao) DB() *gorm.DB { + return dao.db +} diff --git a/src/infrastructure/dao/mysql/organize.go b/src/infrastructure/dao/mysql/organize.go index 8b07d49557cd60b2cec5ba07d3e55df94ad72198..4761979e78a601367112f94dbd3dd5c59a908dfa 100644 --- a/src/infrastructure/dao/mysql/organize.go +++ b/src/infrastructure/dao/mysql/organize.go @@ -38,7 +38,7 @@ func (dao *OrganizeDao) DeleteByPid(pid int64) (int64, error) { return ret.RowsAffected, nil } -func (dao *OrganizeDao) ResetStatus(id int64, status int) (int64, error) { +func (dao *OrganizeDao) SetStatus(id int64, status int) (int64, error) { ret := dao.db.Model(new(models.Organize)).Where("id=?", id).Update("status", status) if ret.Error != nil { return 0, ret.Error diff --git a/src/infrastructure/dao/mysql/rbac_role.go b/src/infrastructure/dao/mysql/rbac_role.go index 162be92511dc839e62e526bfe01d4f01e973b278..97a07764eebae952ba98e82ada51721ddc6d091c 100644 --- a/src/infrastructure/dao/mysql/rbac_role.go +++ b/src/infrastructure/dao/mysql/rbac_role.go @@ -128,7 +128,7 @@ func (dao *RbacRoleDao) Delete(id int64) error { return nil } -func (dao *RbacRoleDao) ResetStatus(id int64, status int) (int64, error) { +func (dao *RbacRoleDao) SetStatus(id int64, status int) (int64, error) { // 根据条件更新 db := dao.db.Model(&models.RbacRole{}) ret := db.Where("id = ?", id).Update("status", status) diff --git a/src/infrastructure/dao/mysql/user.go b/src/infrastructure/dao/mysql/user.go index f45b41bdc58b01fd0a16f8cf0f47f91727d005ed..616f5fc17d0c7616aca4551f09986b95856457ac 100644 --- a/src/infrastructure/dao/mysql/user.go +++ b/src/infrastructure/dao/mysql/user.go @@ -137,7 +137,7 @@ func (dao *UserDao) AddCheckAccount(u *models.User) (int64, error) { return dao.Add(u) } -func (dao *UserDao) ResetStatus(id int64, status int) (int64, error) { +func (dao *UserDao) SetStatus(id int64, status int) (int64, error) { // 根据条件更新 db := dao.db.Model(&models.User{}) ret := db.Where("id = ?", id).Update("status", status) diff --git a/src/apps/api.go b/src/pkg/app_help/api.go similarity index 92% rename from src/apps/api.go rename to src/pkg/app_help/api.go index 9a44103c1d52ed6103df6f6b1f3fb7d7420584e3..4cf7a9301b0023375115e2c52c3bec86d1ab9d01 100644 --- a/src/apps/api.go +++ b/src/pkg/app_help/api.go @@ -1,4 +1,4 @@ -package apps +package app_help import ( "context" @@ -15,10 +15,12 @@ import ( ) type ApiServer struct { + SupportModule + SupportInitialize + name string engine *gin.Engine serverConfig configstc.ServerConfig - module bool //是否作为模块服务 server *http.Server } @@ -33,17 +35,12 @@ func (s *ApiServer) Name() string { return "API_SERVER" } -func (s *ApiServer) WithModule(t bool) { - s.module = t -} +func (s *ApiServer) Start() error { -func (s *ApiServer) Module() bool { - return s.module -} + s.Initialize() -func (s *ApiServer) Start() error { //作为模块不启动相关服务 - if s.module { + if s.Module() { return nil } diff --git a/src/apps/api_test.go b/src/pkg/app_help/api_test.go similarity index 98% rename from src/apps/api_test.go rename to src/pkg/app_help/api_test.go index b4e68d0acc1ef6864f631788a926e9df96900cf2..9e5e8ef226304760e9048e78d8cf017cdfca28a1 100644 --- a/src/apps/api_test.go +++ b/src/pkg/app_help/api_test.go @@ -1,4 +1,4 @@ -package apps +package app_help import ( "gitee.com/captials-team/ubdframe/src/domain/configstc" diff --git a/src/pkg/app_help/app.go b/src/pkg/app_help/app.go new file mode 100644 index 0000000000000000000000000000000000000000..ce0784ea605bcf211d712382858292768c72934c --- /dev/null +++ b/src/pkg/app_help/app.go @@ -0,0 +1,88 @@ +package app_help + +import ( + "context" + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "go.uber.org/dig" +) + +type App struct { + SupportInitialize + SupportServer + SupportModule + + di *dig.Container + name string + + servers []interfaces.ItfApiServer + worker []interfaces.ItfWorker + + module bool +} + +func (app *App) DIC() *dig.Container { + return app.di +} + +func (app *App) Name() string { + return app.name +} + +func (app *App) Start() error { + v1log.Out.Debug("====== App[%s] ready start", app.Name()) + app.Initialize() + + servers := app.SupportServer.Servers() + v1log.Out.Debug("====== App[%s] ready servers num %d", app.Name(), len(servers)) + + //当前app若为模块,则需启动的servers也设置为模块 + //暂不执行,app自行处理 + //for _, v := range servers { + // app.SupportModule.SetServer(v) + //} + app.SupportServer.Start() + + return nil +} + +func (app *App) WithName(name string) *App { + app.name = name + return app +} + +func NewApp(di *dig.Container, name string) *App { + v1log.Out.Debug("new app %s", name) + return &App{ + di: di, + name: name, + } +} + +type FuncApp struct { + Name string `json:"name"` + Fn func(ctx context.Context) + + cancel context.CancelFunc +} + +func (app *FuncApp) Start() error { + if app.Fn == nil { + return fmt.Errorf("%s fn empty", app.Name) + } + + ctx, cancel := context.WithCancel(context.Background()) + + app.cancel = cancel + app.Fn(ctx) + return nil +} + +func (app *FuncApp) Stop() error { + if app.cancel != nil { + app.cancel() + } + + return nil +} diff --git a/src/apps/app_mgr.go b/src/pkg/app_help/app_mgr.go similarity index 58% rename from src/apps/app_mgr.go rename to src/pkg/app_help/app_mgr.go index b1b923baa38b24395138694eea039886560a1de3..25381230ef989483a9b5f22eafa2eff75a947bab 100644 --- a/src/apps/app_mgr.go +++ b/src/pkg/app_help/app_mgr.go @@ -1,4 +1,15 @@ -package apps +//示例-App管理器 +/* +app管理器可以添加app(符合app接口)来进行统一启动统一停止,支持优雅重启功能 + +创建一个app管理器: apps.NewAppManager() + +添加对应app进行管理: mgr.WithApp(app1) + +app需符合 interfaces.ItfApp 接口 + +*/ +package app_help import ( "context" @@ -20,25 +31,36 @@ type AppManager struct { process *comag.ConProcessModelActuator } +// WithApp 添加需管理的app func (mgr *AppManager) WithApp(app interfaces.ItfApp) { mgr.apps = append(mgr.apps, app) } -// Start 启动,启动所有application,会阻塞直到有退出问题 +// Start 启动,启动所有管理app,会阻塞直到有退出问题 func (mgr *AppManager) Start() error { + + v1log.Out.Info("AppManager ready apps num %d", len(mgr.apps)) + //准备启动事宜 for _, v := range mgr.apps { var ap = v mgr.process.Add(func(ctx context.Context) { - defer mgr.logger.Info("%s STOP SUCCESS", ap.Name()) + defer mgr.logger.Info("App[%s] STOP SUCCESS", ap.Name()) //异步启动 go func() { - mgr.logger.Info("%s START...", ap.Name()) + mgr.logger.Info("App[%s] START...", ap.Name()) + + //对app初始化处理 + if s, ok := ap.(interfaces.ItfAppInitialize); ok && s != nil { + v1log.Out.Info("App[%s] Initialize", ap.Name()) + s.Initialize() + } + if err := ap.Start(); err != nil { //一个失败停止全部 - mgr.logger.Warn("%s START FAIL..%s", ap.Name(), err) + mgr.logger.Warn("App[%s] START FAIL..%s", ap.Name(), err) mgr.process.Stop() return } @@ -48,7 +70,7 @@ func (mgr *AppManager) Start() error { for { select { case <-ctx.Done(): - mgr.logger.Warn("%s STOPPING...", ap.Name()) + mgr.logger.Warn("App[%s] STOPPING...", ap.Name()) common.ErrPanic(ap.Stop()) return } @@ -73,7 +95,7 @@ func (mgr *AppManager) Stop() error { return mgr.process.Wait() } -// WithSignalExit 收到系统信号后退出所有app +// WithSignalExit 收到系统信号后退出所有app(优雅退出) func (mgr *AppManager) WithSignalExit(signs ...os.Signal) { sigCh := make(chan os.Signal) if len(signs) == 0 { @@ -98,10 +120,16 @@ func (mgr *AppManager) WithSignalExit(signs ...os.Signal) { }() } -func NewAppManager(di *dig.Container, logger v1log.ILog) *AppManager { +// NewAppManager 创建app管理器 +func NewAppManager(logger v1log.ILog) *AppManager { return &AppManager{ - di: di, + di: dig.New(), logger: logger, process: comag.NewConProcessModelActuator(), } } + +// DebugConsoleLog 提供一个基于控制台输出的debug级别的日志记录器 +func DebugConsoleLog() v1log.ILog { + return v1log.NewWriterLog(os.Stdout, v1log.DebugLog) +} diff --git a/src/apps/app_mgr_test.go b/src/pkg/app_help/app_mgr_test.go similarity index 98% rename from src/apps/app_mgr_test.go rename to src/pkg/app_help/app_mgr_test.go index f45cf2d3d9934f4e0edb865707ead82da471f3b9..206854cd49faef5ca3299010bf60d1ad96ba6e3d 100644 --- a/src/apps/app_mgr_test.go +++ b/src/pkg/app_help/app_mgr_test.go @@ -1,4 +1,4 @@ -package apps +package app_help import ( "context" diff --git a/src/pkg/app_help/app_support.go b/src/pkg/app_help/app_support.go new file mode 100644 index 0000000000000000000000000000000000000000..ba8e47d40fe30e823517820a2607714053ac533e --- /dev/null +++ b/src/pkg/app_help/app_support.go @@ -0,0 +1,131 @@ +package app_help + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common" + "gitee.com/captials-team/ubdframe/src/domain/interfaces" + v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" + "sync" +) + +// SupportServer 服务支持组件 +// +// 用于设置server和启动server +type SupportServer struct { + servers []interfaces.ItfServer +} + +// WithServer 指定任意Server +func (app *SupportServer) WithServer(s ...interfaces.ItfServer) { + app.servers = append(app.servers, s...) +} + +// WithApiServer 指定apiServer +func (app *SupportServer) WithApiServer(s ...interfaces.ItfApiServer) { + for _, v := range s { + app.servers = append(app.servers, v) + } +} + +// WithWorker 指定worker +func (app *SupportServer) WithWorker(s ...interfaces.ItfWorker) { + for _, v := range s { + app.servers = append(app.servers, v) + } +} + +// Servers 指定worker +func (app *SupportServer) Servers() []interfaces.ItfServer { + return app.servers +} + +// Start 启动 +func (app *SupportServer) Start() { + var wg sync.WaitGroup + + for index, v := range app.servers { + wg.Add(1) + server := v + + name := fmt.Sprintf("ID-%d", index) + if n, ok := server.(interfaces.ItfAppName); ok { + name = n.Name() + } + v1log.Out.Debug("====== Server[%s] DEFAULT START[%d/%d]", name, index+1, len(app.servers)) + go func() { + defer wg.Done() + + err := server.Start() + if err != nil { + v1log.Out.Error("====== Server[%s] DEFAULT START FAIL %s", name, err) + return + } + }() + } + wg.Wait() +} + +func (app *SupportServer) Stop() error { + var wg sync.WaitGroup + + for _, v := range app.servers { + wg.Add(1) + server := v + go func() { + defer wg.Done() + err := server.Stop() + common.ErrPanic(err) + }() + } + wg.Wait() + return nil +} + +// SupportInitialize 初始化支持组件 +// +// 用于设置初始化函数和执行初始化函数 +type SupportInitialize struct { + initializeFuncs []func() //初始化函数 +} + +// WithInitialize 设置初始化函数 +func (app *SupportInitialize) WithInitialize(fn ...func()) { + app.initializeFuncs = append(app.initializeFuncs, fn...) +} + +// Initialize 初始化 +func (app *SupportInitialize) Initialize() { + v1log.Out.Debug("====== Ready Initialize Num %d", len(app.initializeFuncs)) + + for index, fn := range app.initializeFuncs { + v1log.Out.Debug("====== Initialize Func [%d/%d]", index+1, len(app.initializeFuncs)) + fn() + } +} + +// SupportModule 模块支持组件 +// +// 用于设置是否模块启动 +type SupportModule struct { + module bool +} + +// WithModule 设置是否模块 +func (app *SupportModule) WithModule(t bool) { + app.module = t +} + +func (app *SupportModule) Module() bool { + return app.module +} + +// SetServer 设置模块启动 +func (app *SupportModule) SetServer(servers ...interface{}) { + for _, server := range servers { + //对模块支持进行处理 + if s, ok := server.(interfaces.ItfAppModule); ok && s != nil { + //设置module + s.WithModule(app.module) + } + } +} diff --git a/src/pkg/app_help/app_test.go b/src/pkg/app_help/app_test.go new file mode 100644 index 0000000000000000000000000000000000000000..3fb64bb1886a7560ff99e93e0a307b19a422fee4 --- /dev/null +++ b/src/pkg/app_help/app_test.go @@ -0,0 +1,70 @@ +package app_help + +import ( + "context" + "go.uber.org/dig" + "testing" + "time" +) + +func TestNewApp(t *testing.T) { + ap := NewApp(dig.New(), "testing") + + ap.WithServer(&FuncApp{ + Name: "", + Fn: func(ctx context.Context) { + defer t.Logf("Done") + for { + select { + case <-ctx.Done(): + return + default: + t.Logf("running %s", time.Now().Format(time.DateTime)) + time.Sleep(time.Second) + } + } + }, + }) + + go func() { + time.Sleep(time.Second * 5) + t.Logf("Stopping") + ap.Stop() + }() + + ap.Start() +} + +func TestNewApp_Initialize(t *testing.T) { + + ap := new(testApp) + //ap.App = NewApp(dig.New(), "testing") + + ap.App = App{ + di: dig.New(), + name: "testing", + } + ap.Start() + + t.Logf("speak= %s", ap.Speak()) +} + +type Dog struct { +} + +func (dg Dog) Speak() string { + return "dog" +} + +type testApp struct { + App + Dog +} + +func (ap *testApp) Initialize() { + panic("initialize") +} + +func (ap *testApp) Speak() string { + return "happy dog" +} diff --git a/src/pkg/atapi/config/config.go b/src/pkg/atapi/config/config.go new file mode 100644 index 0000000000000000000000000000000000000000..eb36212c479f8c1330f1e8bb8674fcbfcd0fb688 --- /dev/null +++ b/src/pkg/atapi/config/config.go @@ -0,0 +1,105 @@ +package config + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/pkg/extendparams" + "go/types" + "strings" +) + +type AutoApiConfig struct { + Apis []AutoApiDefined `json:"Apis" yaml:"Apis"` + ExtendParams extendparams.CommonExtendParams `json:"ExtendParams" yaml:"ExtendParams"` //扩展参数 +} + +// AutoApiDefined 单个autoApi的定义 +type AutoApiDefined struct { + Name string `json:"Name" yaml:"Name"` //api总称 + ShowName string `json:"ShowName" yaml:"ShowName"` //展示名称(一般为中文) + Version string `json:"Version" yaml:"Version"` //版本,v1/v2 这样,为空则默认使用最新版本 + + LoadFile string `json:"LoadFile" yaml:"LoadFile"` //加载文件路径,有路径值则从该路径加载覆盖当前AutoApi + + Actions []AutoApiActionDefined `json:"Actions" yaml:"Actions"` //使用的插件列表 + + Data AutoApiDataDefined `json:"Data" yaml:"Data"` //数据定义 + + Comment string `json:"Comment" yaml:"Comment"` //备注/注释说明 +} + +type AutoApiDataDefined struct { + //结构 + DataName string `json:"DataName" yaml:"DataName"` //数据名称,用于给数据区分存储来源,如表名 + AutoTable bool `json:"AutoTable" yaml:"AutoTable"` //是否自动建表,true:自动检查并创建表,false:不检查 + Fields []AutoApiFieldDefined `json:"Fields" yaml:"Fields"` + Comment string `json:"Comment" yaml:"Comment"` //数据名称,用于给数据区分存储来源,如表名 +} + +func (a AutoApiDataDefined) FieldNames() []string { + var fs []string + for _, v := range a.Fields { + fs = append(fs, v.Name) + } + return fs +} + +// AutoApiFieldDefined 单个autoApi字段的定义 +type AutoApiFieldDefined struct { + Name string `json:"Name" yaml:"Name"` //字段名,如:name + ShowName string `json:"ShowName" yaml:"ShowName"` //展示名称(一般为中文) + + //类型, 可为: + // varchar(32) + // bigint unsigned + // int unsigned + // tinyint unsigned + // datetime(3) + SqlType string `json:"SqlType" yaml:"SqlType"` + + Default string `json:"Default" yaml:"Default"` //默认值 + Comment string `json:"Comment" yaml:"Comment"` //备注/注释说明 + + ExtendParams extendparams.CommonExtendParams `json:"ExtendParams" yaml:"ExtendParams"` //扩展参数 +} + +func (f *AutoApiFieldDefined) CreateSql() string { + def := "" + if f.Default != "" { + switch f.Type() { + case types.String: + def = fmt.Sprintf("default '%s'", f.Default) + default: + def = "default " + f.Default + } + } + return fmt.Sprintf("`%s` %s %s comment '%s'", f.Name, f.SqlType, def, f.Comment) +} + +func (f *AutoApiFieldDefined) Type() types.BasicKind { + a := f.SqlType + if strings.HasPrefix(a, "varchar") { + return types.String + } else if strings.HasPrefix(a, "int") { + return types.Int64 + } else if strings.HasPrefix(a, "tinyint") { + return types.Int8 + } + + return types.String +} + +// AutoApiActionDefined 单个autoApi使用插件的定义 +type AutoApiActionDefined struct { + Name string `json:"Name" yaml:"Name"` //api操作名称 + Describe string `json:"Describe" yaml:"Describe"` //api操作具体描述内容 + Enable bool `json:"Enable" yaml:"Enable"` //是否启用 + Plugins []AutoApiActionPluginDefined `json:"Plugins" yaml:"Plugins"` //该api操作的插件列表 +} + +// AutoApiActionPluginDefined 单个autoApi使用插件的定义 +type AutoApiActionPluginDefined struct { + Enable bool `json:"Enable" yaml:"Enable"` //是否启用 + Name string `json:"Name" yaml:"Name"` //插件名称,如:API_SEARCH,必须为注册的插件 + ExtendParams extendparams.CommonExtendParams `json:"ExtendParams" yaml:"ExtendParams"` //扩展参数 + Remark string `json:"Remark" yaml:"Remark"` //备注,如使用的插件用途的具体描述 +} diff --git a/src/pkg/atapi/config/param.go b/src/pkg/atapi/config/param.go new file mode 100644 index 0000000000000000000000000000000000000000..7b97e94301eaa54bfaf1c4230d4b96c3c0f559e3 --- /dev/null +++ b/src/pkg/atapi/config/param.go @@ -0,0 +1,23 @@ +package config + +import ( + "github.com/gin-gonic/gin" + "github.com/go-openapi/spec" +) + +type GinHandleParam struct { + Method string + Path string + HandlerFunc []gin.HandlerFunc + + //下面用于生成swagger文档 + SwaggerPaths map[string]spec.PathItem //对应路由的swagger路径集合 + SwaggerDefinitions map[string]spec.Schema //对应路由的swagger定义集合 +} + +// PluginData 插件使用的参数合集 +type PluginData struct { + Api AutoApiDefined //当前api信息 + Action AutoApiActionDefined //当前action信息 + Plugin AutoApiActionPluginDefined //当前plugin信息 +} diff --git a/src/pkg/atapi/config/parse.go b/src/pkg/atapi/config/parse.go new file mode 100644 index 0000000000000000000000000000000000000000..0f34038479cc21f5d7e7aaee1fc58621df5ea65b --- /dev/null +++ b/src/pkg/atapi/config/parse.go @@ -0,0 +1,5 @@ +package config + +func ParseConfig() { + +} diff --git a/src/pkg/atapi/dataexec/dataexec_mysql.go b/src/pkg/atapi/dataexec/dataexec_mysql.go new file mode 100644 index 0000000000000000000000000000000000000000..4c7687eb780ed013f908f388ce61c8d14635f029 --- /dev/null +++ b/src/pkg/atapi/dataexec/dataexec_mysql.go @@ -0,0 +1,294 @@ +package dataexec + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gorm.io/gorm" + "strings" + "time" +) + +type MysqlDbExec struct { + db *gorm.DB + name string + tbName string +} + +func (exec *MysqlDbExec) DoSearch(conditions map[string]interface{}, fields []string, page, size int) ([]map[string]interface{}, int64, error) { + //fmt.Printf("search params: %+v ,%+v ,%d ,%d\n", params, fields, page, size) + //fields = append(fields, "id", "created_at", "updated_at") + if conditions == nil { + conditions = map[string]interface{}{} + } + fields = append(fields, "id") + where := []string{ + "deleted_uid=0", + } + whereArgs := []interface{}{} + for k := range conditions { + v := conditions[k] + where = append(where, k) + whereArgs = append(whereArgs, v) + } + orderBy := []string{ + "id desc", + } + var list []map[string]interface{} + + newScan := func() ([]interface{}, []interface{}) { + arr := make([]interface{}, len(fields)) + arr1 := make([]interface{}, len(fields)) + for i := range fields { + arr1[i] = &arr[i] + } + return arr, arr1 + } + + toRetRow := func(arr []interface{}) map[string]interface{} { + m := map[string]interface{}{} + + for i := range arr { + v := arr[i] + var value interface{} + switch v.(type) { + case string: + value = v.(string) + case []byte: + value = string(v.([]byte)) + case int64: + value = v.(int64) + default: + value = v + } + m[fields[i]] = value + } + return m + } + + whereStr := "" + if len(where) > 0 { + whereStr = "WHERE " + strings.Join(where, " AND ") + } + var total int64 + countSql := fmt.Sprintf("SELECT COUNT(*) FROM %s %s LIMIT 1", exec.tbName, whereStr) + + ret := exec.db.Raw(countSql, whereArgs...).Scan(&total) + if ret.Error != nil { + return nil, 0, ret.Error + } + + if len(fields) <= 0 { + fields = append(fields, "*") + } + orderByStr := strings.Join(orderBy, ",") + if orderByStr != "" { + orderByStr = "ORDER BY " + orderByStr + } + whereArgs = append(whereArgs, size) + whereArgs = append(whereArgs, size*(page-1)) + dataSql := fmt.Sprintf("SELECT %s FROM %s %s %s LIMIT ? OFFSET ?", strings.Join(fields, ","), exec.tbName, whereStr, orderByStr) + + rows, err := exec.db.Raw(dataSql, whereArgs...).Rows() + if err != nil { + return nil, 0, err + } + + for rows.Next() { + arr, scans := newScan() + err := rows.Scan(scans...) + if err != nil { + return list, 0, err + } + + list = append(list, toRetRow(arr)) + } + + return list, total, err +} + +func (exec *MysqlDbExec) DoQuery(conditions map[string]interface{}, fields []string) (map[string]interface{}, error) { + //fmt.Printf("query params: %s, %+v, %+v\n", exec.tbName, conditions, fields) + fields = append(fields, "id") + where := []string{ + "deleted_uid=0", + } + whereArgs := []interface{}{} + for k, v := range conditions { + where = append(where, fmt.Sprintf("%s=?", k)) + whereArgs = append(whereArgs, v) + } + var fieldArr = []string{} + var scanArr = []interface{}{} + + m := map[string]interface{}{} + arr := make([]interface{}, len(fields)) + for i, v := range fields { + m[v] = &arr[i] + + fieldArr = append(fieldArr, fmt.Sprintf("`%s`", v)) + scanArr = append(scanArr, &arr[i]) + } + + whereStr := "" + orderByStr := "" + if len(where) > 0 { + whereStr = "WHERE " + strings.Join(where, " AND ") + } + fieldStr := strings.Join(fieldArr, ",") + + selectSql := fmt.Sprintf("SELECT %s FROM %s %s %s LIMIT 1", + fieldStr, exec.tbName, whereStr, orderByStr) + + ret := exec.db.Raw(selectSql, whereArgs...).Scan(&m) + if ret.Error != nil { + return nil, ret.Error + } + + return m, nil +} + +func (exec *MysqlDbExec) DoCreate(params map[string]interface{}) (int64, error) { + var values = map[string]interface{}{} + + for k, v := range params { + values[k] = v + } + + ret := exec.db.Table(exec.tbName).Create(values) + if ret.Error != nil { + return 0, ret.Error + } + //logs.Out.Info("Values= %+v", values["@id"]) + //主键id值 + id, exist := values["@id"] + if exist { + return id.(int64), nil + } + return ret.RowsAffected, nil +} + +func (exec *MysqlDbExec) DoUpdate(id int64, params map[string]interface{}) (int64, error) { + //fmt.Printf("update params: %d, %+v\n", id, params) + where := []string{ + "id=?", + "deleted_uid=0", + } + whereArgs := []interface{}{ + id, + } + params["updated_at"] = time.Now().UnixMilli() + + var fieldArr = []string{} + var valueArr = []interface{}{} + for k, v := range params { + fieldArr = append(fieldArr, fmt.Sprintf("`%s`=?", k)) + valueArr = append(valueArr, v) + } + + fieldStr := strings.Join(fieldArr, ",") + + whereStr := "" + if len(where) > 0 { + whereStr = "WHERE " + strings.Join(where, " AND ") + } + + if len(whereArgs) > 0 { + for _, v := range whereArgs { + valueArr = append(valueArr, v) + } + } + + updateSql := fmt.Sprintf("UPDATE %s SET %s %s", exec.tbName, fieldStr, whereStr) + ret := exec.db.Exec(updateSql, valueArr...) + + if ret.Error != nil { + return 0, ret.Error + } + + return ret.RowsAffected, nil +} + +func (exec *MysqlDbExec) DoDelete(id int64) (int64, error) { + return exec.DoUpdate(id, map[string]interface{}{ + "deleted_uid": 1, + "deleted_at": time.Now().UnixMilli(), + }) +} + +func (exec *MysqlDbExec) Copy() ifs.IAutoApiDataExec { + return &MysqlDbExec{ + db: exec.db, + } +} + +func (exec *MysqlDbExec) InitDB(name string, c config.AutoApiDataDefined) error { + return exec.initV1(name, c) +} + +func (exec *MysqlDbExec) initV1(name string, config config.AutoApiDataDefined) error { + exec.name = name + exec.tbName = exec.genTableName(config) + //log.Printf("data init: %s, %+v",exec.name,exec.tbName) + + //自动初始化表 + if config.AutoTable { + ret := exec.db.Exec(exec.tableSql(config)) + return ret.Error + } + + return nil +} + +func (exec *MysqlDbExec) TableName() string { + return exec.tbName +} + +func (exec *MysqlDbExec) genTableName(config config.AutoApiDataDefined) string { + name := config.DataName + if name == "" { + name = exec.name + } + return "atapi_" + name +} + +func (exec *MysqlDbExec) tableSql(config config.AutoApiDataDefined) string { + tableName := exec.tbName + tableComment := "" + + fields := []string{} + + for _, f := range config.Fields { + fields = append(fields, + f.CreateSql(), + ) + } + + sql := ` +CREATE TABLE IF NOT EXISTS %s +( + id int unsigned auto_increment, + created_at datetime default current_timestamp null comment 'create time', + updated_at datetime default null comment 'update time', + deleted_at datetime default null comment 'delete time', + deleted_uid int unsigned default 0, + + %s, + + PRIMARY KEY (id) +) +COMMENT '%s'; +` + return fmt.Sprintf(sql, tableName, + strings.Join(fields, ",\n"), + tableComment) +} + +func NewMysqlDbExec(c configstc.DBConfig) (*MysqlDbExec, error) { + db := mysql.NewGormDB(c) + return &MysqlDbExec{ + db: db, + }, nil +} diff --git a/src/pkg/atapi/dataexec/dataexec_test.go b/src/pkg/atapi/dataexec/dataexec_test.go new file mode 100644 index 0000000000000000000000000000000000000000..202a22dfdba9ace07d428b5fbc5d6a9a577354b5 --- /dev/null +++ b/src/pkg/atapi/dataexec/dataexec_test.go @@ -0,0 +1 @@ +package dataexec diff --git a/src/pkg/atapi/dataexec_test.go b/src/pkg/atapi/dataexec_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b11d47bd8f94a485d0ffab88a5bd72693995e9e3 --- /dev/null +++ b/src/pkg/atapi/dataexec_test.go @@ -0,0 +1,68 @@ +package atapi + +import ( + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/dataexec" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestMysqlDbExec(t *testing.T) { + exec, err := dataexec.NewMysqlDbExec(configstc.DBConfig{ + DbHost: "192.168.149.128", + DbPort: "3306", + DbUser: "root", + DbPassword: "root", + DbName: "db_ubd_frame", + TablePrefix: "test_", + }) + assert.Equal(t, err, nil) + + err = exec.InitDB("tttt", testDataExecConfig()) + assert.Equal(t, nil, err) + + doTestDBExec(t, exec) +} + +func doTestDBExec(t *testing.T, exec ifs.IAutoApiDataExec) { + + list, total, err := exec.DoSearch(nil, nil, 1, 10) + assert.Equal(t, nil, err) + t.Logf("Count=%d", total) + t.Logf("List=%+v", list) + + lastId, err := exec.DoCreate(map[string]interface{}{ + "name": "测试", + "status": 1, + }) + assert.Equal(t, nil, err) + + t.Logf("Id=%d", lastId) +} + +func testDataExecConfig() config.AutoApiDataDefined { + return config.AutoApiDataDefined{ + AutoTable: true, + DataName: "", + Fields: []config.AutoApiFieldDefined{ + { + Name: "name", + ShowName: "名称", + SqlType: "varchar(32)", + Default: "", + Comment: "", + ExtendParams: nil, + }, + { + Name: "status", + ShowName: "状态", + SqlType: "int", + Default: "", + Comment: "", + ExtendParams: nil, + }, + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/api.go b/src/pkg/atapi/httpapi/v1/api.go new file mode 100644 index 0000000000000000000000000000000000000000..213eb729b7de8b1ec7bd9d308a504bee8d8ab0d2 --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/api.go @@ -0,0 +1,158 @@ +package v1 + +import ( + "context" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gitee.com/captials-team/ubdframe/src/pkg/extendparams" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/gin-gonic/gin" +) + +func NewAutoApi(c config.AutoApiDefined, extends map[string]string) (*AutoApi, error) { + return &AutoApi{ + c: c, + extends: extends, + }, nil +} + +type AutoApi struct { + c config.AutoApiDefined + extends extendparams.CommonExtendParams + + dataExec ifs.IAutoApiDataExec //数据处理器 + supportPlugins []ifs.IApiPlugin //支持的插件列表 + + actions []actionData +} + +func (a *AutoApi) SetDataExec(exec ifs.IAutoApiDataExec) { + a.dataExec = exec +} + +func (a *AutoApi) GetDataExec() ifs.IAutoApiDataExec { + return a.dataExec +} + +func (a *AutoApi) SetVars(m map[string]string) { + a.extends = m +} + +func (a *AutoApi) GetVars() map[string]string { + return a.extends +} + +func (a *AutoApi) AddPlugin(arr ...ifs.IApiPlugin) { + a.supportPlugins = append(a.supportPlugins, arr...) +} + +func (a *AutoApi) Config() config.AutoApiDefined { + return a.c +} + +func (a *AutoApi) Code() string { + return a.c.Name +} + +func (a *AutoApi) ShowName() string { + return a.c.ShowName +} + +func (a *AutoApi) Init() error { + //初始化数据库 + err := a.dataExec.InitDB(a.c.Name, a.c.Data) + if err != nil { + return err + } + logs.Out.Info("[%s] table: %s init", a.c.Name, a.dataExec.TableName()) + + //初始化操作 + a._initActions() + + return nil +} + +// _initActions 初始化操作集合 +func (a *AutoApi) _initActions() { + var actions []actionData + + supportPluginMap := map[string]ifs.IApiPlugin{} + for _, v := range a.supportPlugins { + supportPluginMap[v.Name()] = v + } + + for _, action := range a.c.Actions { + item := actionData{ + action: action, + } + logs.Out.Info("[%s] action: %s init", a.c.Name, action.Name) + for _, plugin := range action.Plugins { + if tmp, exist := supportPluginMap[plugin.Name]; exist { + item.usePlugins = append(item.usePlugins, tmp.Factory(&config.PluginData{ + Api: a.c, + Action: action, + Plugin: plugin, + })) + item.usePluginsConfig = append(item.usePluginsConfig, plugin) + + logs.Out.Info("\tplugin[%s] load", plugin.Name) + } else { + logs.Out.Warn("\tplugin[%s] not support", plugin.Name) + } + } + + actions = append(actions, item) + } + + a.actions = actions +} + +func (a *AutoApi) Handlers() []config.GinHandleParam { + var routers []config.GinHandleParam + for _, act := range a.actions { + for _, plugin := range act.usePlugins { + h := plugin.HttpHandler() + if h == nil { + continue + } + + r := h.Router() + if len(r) > 0 { + for _, router := range r { + if router.HandlerFunc == nil { + router.HandlerFunc = []gin.HandlerFunc{a.ginHandler(act)} + } + routers = append(routers, router) + } + } + } + } + return routers +} + +func (a *AutoApi) ginHandler(act actionData) gin.HandlerFunc { + + return func(ctx *gin.Context) { + + running := runningData{ + ctx: context.Background(), + ginCtx: ctx, + dataExec: a.dataExec, + data: map[string]interface{}{}, + } + for _, v := range act.usePlugins { + v.Do(&running) + if running.abort { + break + } + } + } +} + +// actionData 单个操作Data +type actionData struct { + action config.AutoApiActionDefined + + usePlugins []ifs.IApiPluginFactory + usePluginsConfig []config.AutoApiActionPluginDefined +} diff --git a/src/pkg/atapi/httpapi/v1/const.go b/src/pkg/atapi/httpapi/v1/const.go new file mode 100644 index 0000000000000000000000000000000000000000..4b31b8203bcc5bc1c9e84ae80c15b21cfa5c0067 --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/const.go @@ -0,0 +1,3 @@ +package v1 + +const Version = "1" diff --git a/src/pkg/atapi/httpapi/v1/plugins/api_create.go b/src/pkg/atapi/httpapi/v1/plugins/api_create.go new file mode 100644 index 0000000000000000000000000000000000000000..5aa72ee72ec6949f2e3c079d0cc04aca351b31c0 --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/api_create.go @@ -0,0 +1,171 @@ +package plugins + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/go-openapi/spec" + "net/http" + "strings" +) + +type ApiCreatePlugin struct { + conf *config.PluginData +} + +func NewApiCreatePlugin() *ApiCreatePlugin { + //初始化 + p := &ApiCreatePlugin{} + + return p +} + +func (p *ApiCreatePlugin) Name() string { + return "API_CREATE" +} + +func (p *ApiCreatePlugin) Describe() string { + return ` +提供创建数据的能力,可以自定义创建数据 +` +} + +func (p *ApiCreatePlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &ApiCreatePlugin{conf: conf} + return fa +} + +func (p *ApiCreatePlugin) Do(running ifs.RunningParam) { + var m = make(map[string]interface{}) + running.GinCtx().ShouldBindJSON(&m) + + create := map[string]interface{}{} + for _, v := range p.conf.Api.Data.Fields { + val, exist := m[v.Name] + if !exist { + running.SetVar("error", fmt.Errorf("%s must post", v.Name)) + return + } + create[v.Name] = val + } + + //todo 增加搜索参数的处理 + + //具体操作 + id, err := running.DataExec().DoCreate(create) + if err != nil { + running.SetVar("error", err) + return + } + running.SetVar("data", map[string]interface{}{ + "id": id, + }) +} + +func (p *ApiCreatePlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return &ApiCreateHttpHandler{ + action: p, + data: p.conf, + } +} + +func (p *ApiCreatePlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} + +type ApiCreateHttpHandler struct { + action *ApiCreatePlugin + //运行时参数变量 + data *config.PluginData +} + +func (p *ApiCreateHttpHandler) swaggerPathItem() spec.PathItem { + postParams := map[string]spec.Schema{} + fields := map[string]spec.Schema{} + + logs.Out.Info("Fields= %+v", p.data.Api.Data.Fields) + logs.Out.Info("Api= %+v", p.data.Api) + + for _, v := range p.data.Api.Data.Fields { + ty := "string" + var example interface{} = "example" + if strings.Index(v.SqlType, "int") >= 0 { + ty = "int" + example = 1 + } + + postParams[v.Name] = newSwaggerSpecSchema(ty, v.ShowName, example) + fields[v.Name] = newSwaggerSpecSchema(ty, v.ShowName, example) + } + + resp1 := spec.Response{ + ResponseProps: spec.ResponseProps{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Description: "响应Data", + Properties: map[string]spec.Schema{ + "id": newSwaggerSpecSchema("int", "条目id", 1), + }, + }, + }, + Headers: nil, + Examples: nil, + }, + } + + return spec.PathItem{ + PathItemProps: spec.PathItemProps{ + Post: &spec.Operation{ + OperationProps: spec.OperationProps{ + Summary: "新建", + Description: "新建操作,根据提交参数创建数据并返回条目id", + Produces: []string{"application/json"}, + Schemes: nil, + Tags: []string{p.data.Api.Name}, + Parameters: []spec.Parameter{ + { + ParamProps: spec.ParamProps{ + Description: "传参", + Name: "param", + In: "body", + Required: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: postParams, + }, + }, + AllowEmptyValue: true, + }, + }, + }, + Responses: &spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + Default: nil, + StatusCodeResponses: map[int]spec.Response{ + 200: newSwaggerResponseFromRef("api.common.response"), + 201: resp1, + }, + }, + }, + }, + }, + }, + } +} + +func (p *ApiCreateHttpHandler) Router() []config.GinHandleParam { + path := fmt.Sprintf("/%s/create", p.data.Api.Name) + + return []config.GinHandleParam{ + { + Method: http.MethodPost, + Path: path, + SwaggerPaths: map[string]spec.PathItem{ + path: p.swaggerPathItem(), + }, + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/api_delete.go b/src/pkg/atapi/httpapi/v1/plugins/api_delete.go new file mode 100644 index 0000000000000000000000000000000000000000..f72090911a557be6312fafc9dcaf0a938cabfdcb --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/api_delete.go @@ -0,0 +1,161 @@ +package plugins + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/go-openapi/spec" + "github.com/spf13/cast" + "net/http" +) + +type ApiDeletePlugin struct { + //请求参数(可搜索条件字段) + idParam string //主键用参数 + + //返回字段 + respFields []string + + conf *config.PluginData +} + +func NewApiDeletePlugin() *ApiDeletePlugin { + //初始化 + p := &ApiDeletePlugin{} + + return p +} + +func (p *ApiDeletePlugin) Name() string { + return "API_DELETE" +} + +func (p *ApiDeletePlugin) init() { + m := p.conf.Plugin.ExtendParams + if m == nil { + m = map[string]string{} + } + + //默认值 + p.idParam = m.ExtendParamByString(IdFieldKey, "id") +} + +func (p *ApiDeletePlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &ApiDeletePlugin{conf: conf} + fa.init() + return fa +} + +func (p *ApiDeletePlugin) Describe() string { + return ` +提供删除单条数据的能力 +` +} + +func (p *ApiDeletePlugin) Extends() map[string]string { + return map[string]string{ + IdFieldKey: "id", //指定返回字段名称,多个逗号分隔 + } +} + +func (p *ApiDeletePlugin) Do(running ifs.RunningParam) { + var m = make(map[string]interface{}) + running.GinCtx().ShouldBindJSON(&m) + + id := cast.ToInt64(m[p.idParam]) + + //todo 增加搜索参数的处理 + + //具体操作查询 + data, err := running.DataExec().DoDelete(id) + if err != nil { + running.SetVar("error", err) + return + } + + running.SetVar("data", data) +} + +func (p *ApiDeletePlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return &ApiDeleteHttpHandler{ + plugin: p, + data: p.conf, + } +} + +func (p *ApiDeletePlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} + +type ApiDeleteHttpHandler struct { + plugin *ApiDeletePlugin + //运行时参数变量 + data *config.PluginData +} + +func (p *ApiDeleteHttpHandler) swaggerPathItem() spec.PathItem { + reqParams := map[string]spec.Schema{} + fields := map[string]spec.Schema{} + + logs.Out.Info("Fields= %+v", p.data.Api.Data.Fields) + logs.Out.Info("Api= %+v", p.data.Api) + + reqParams[p.plugin.idParam] = newSwaggerSpecSchema("string", "指定id", 1) + for _, v := range p.plugin.respFields { + fields[v] = newSwaggerSpecSchema("string", v, "example") + } + + return spec.PathItem{ + PathItemProps: spec.PathItemProps{ + Post: &spec.Operation{ + OperationProps: spec.OperationProps{ + Summary: "删除数据", + Description: "删除数据,根据传递参数删除指定条目数据", + Produces: []string{"application/json"}, + Schemes: nil, + Tags: []string{p.data.Api.Name}, + Parameters: []spec.Parameter{ + { + ParamProps: spec.ParamProps{ + Description: "传参", + Name: "param", + In: "body", + Required: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: reqParams, + }, + }, + AllowEmptyValue: true, + }, + }, + }, + Responses: &spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + Default: nil, + StatusCodeResponses: map[int]spec.Response{ + 200: newSwaggerResponseFromRef("api.common.response"), + }, + }, + }, + }, + }, + }, + } +} + +func (p *ApiDeleteHttpHandler) Router() []config.GinHandleParam { + path := fmt.Sprintf("/%s/delete", p.data.Api.Name) + + return []config.GinHandleParam{ + { + Method: http.MethodPost, + Path: path, + SwaggerPaths: map[string]spec.PathItem{ + path: p.swaggerPathItem(), + }, + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/api_detail.go b/src/pkg/atapi/httpapi/v1/plugins/api_detail.go new file mode 100644 index 0000000000000000000000000000000000000000..f0ea5d26b80144034aea5f75359587a1ad11a44b --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/api_detail.go @@ -0,0 +1,201 @@ +package plugins + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/go-openapi/spec" + "github.com/spf13/cast" + "net/http" + "strings" +) + +type ApiQueryPlugin struct { + //请求参数(可搜索条件字段) + idParam string //主键用参数 + + //返回字段 + respFields []string + + conf *config.PluginData +} + +func NewApiQueryPlugin() *ApiQueryPlugin { + //初始化 + p := &ApiQueryPlugin{} + + return p +} + +func (p *ApiQueryPlugin) Name() string { + return "API_QUERY" +} + +func (p *ApiQueryPlugin) init() { + m := p.conf.Plugin.ExtendParams + if m == nil { + m = map[string]string{} + } + + //响应字段集合 + p.respFields = p.conf.Api.Data.FieldNames() + responseFields := strings.Split(m[ResponseFieldsParamsKey], ",") + if len(responseFields) > 0 { + p.respFields = utils.ArrayIntersection(p.respFields, responseFields) + } + p.respFields = utils.ArrayUnion([]string{ + "id", + "created_at", + "updated_at", + }, p.respFields) + + //默认值 + p.idParam = m.ExtendParamByString(IdFieldKey, "id") +} + +func (p *ApiQueryPlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &ApiQueryPlugin{conf: conf} + fa.init() + return fa +} + +func (p *ApiQueryPlugin) Describe() string { + return ` +提供查询单条数据的能力 +` +} + +func (p *ApiQueryPlugin) Extends() map[string]string { + return map[string]string{ + ResponseFieldsParamsKey: "f1,f2,f3", //指定返回字段名称,多个逗号分隔 + IdFieldKey: "id", //指定返回字段名称,多个逗号分隔 + } +} + +func (p *ApiQueryPlugin) Do(running ifs.RunningParam) { + var m = make(map[string]interface{}) + running.GinCtx().ShouldBindJSON(&m) + + id := cast.ToInt(m[p.idParam]) + + //todo 增加搜索参数的处理 + + //具体操作查询 + data, err := running.DataExec().DoQuery(map[string]interface{}{ + "id": id, + }, p.respFields) + if err != nil { + running.SetVar("error", err) + return + } + + running.SetVar("data", data) +} + +func (p *ApiQueryPlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return &ApiQueryHttpHandler{ + plugin: p, + data: p.conf, + } +} + +func (p *ApiQueryPlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} + +type ApiQueryHttpHandler struct { + plugin *ApiQueryPlugin + //运行时参数变量 + data *config.PluginData +} + +func (p *ApiQueryHttpHandler) swaggerPathItem() spec.PathItem { + reqParams := map[string]spec.Schema{} + fields := map[string]spec.Schema{} + + logs.Out.Info("Fields= %+v", p.data.Api.Data.Fields) + logs.Out.Info("Api= %+v", p.data.Api) + + reqParams[p.plugin.idParam] = newSwaggerSpecSchema("string", "指定id", 1) + for _, v := range p.plugin.respFields { + fields[v] = newSwaggerSpecSchema("string", v, "example") + } + + resp1 := spec.Response{ + ResponseProps: spec.ResponseProps{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "详情数据", + Type: []string{"object"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "详情内容", + Type: []string{"object"}, + Properties: fields, + }, + }, + }, + }, + }, + Headers: nil, + Examples: nil, + }, + } + + return spec.PathItem{ + PathItemProps: spec.PathItemProps{ + Post: &spec.Operation{ + OperationProps: spec.OperationProps{ + Summary: "查询详情", + Description: "查询详情,根据传递参数返回详情信息", + Produces: []string{"application/json"}, + Schemes: nil, + Tags: []string{p.data.Api.Name}, + Parameters: []spec.Parameter{ + { + ParamProps: spec.ParamProps{ + Description: "传参", + Name: "param", + In: "body", + Required: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: reqParams, + }, + }, + AllowEmptyValue: true, + }, + }, + }, + Responses: &spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + Default: nil, + StatusCodeResponses: map[int]spec.Response{ + 200: newSwaggerResponseFromRef("api.common.response"), + 201: resp1, + }, + }, + }, + }, + }, + }, + } +} + +func (p *ApiQueryHttpHandler) Router() []config.GinHandleParam { + path := fmt.Sprintf("/%s/query", p.data.Api.Name) + + return []config.GinHandleParam{ + { + Method: http.MethodPost, + Path: path, + SwaggerPaths: map[string]spec.PathItem{ + path: p.swaggerPathItem(), + }, + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/api_response.go b/src/pkg/atapi/httpapi/v1/plugins/api_response.go new file mode 100644 index 0000000000000000000000000000000000000000..44e8e9ccc3377155ed9a07aef03e71a5b09d4663 --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/api_response.go @@ -0,0 +1,114 @@ +package plugins + +import ( + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "github.com/go-openapi/spec" + "net/http" +) + +type ApiResponsePlugin struct { + conf *config.PluginData +} + +func NewApiResponsePlugin() *ApiResponsePlugin { + //初始化 + p := &ApiResponsePlugin{} + + return p +} + +func (p *ApiResponsePlugin) Name() string { + return "API_RESPONSE" +} + +func (p *ApiResponsePlugin) Describe() string { + return ` +提供返回响应数据,http路由定义的能力 +` +} + +func (p *ApiResponsePlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &ApiResponsePlugin{conf: conf} + return fa +} + +func (p *ApiResponsePlugin) Do(running ifs.RunningParam) { + ctx := running.GinCtx() + + resp := struct { + Code int `json:"code"` //返回码,0:成功,>0为对应错误码 + Msg string `json:"msg"` + Data interface{} `json:"data"` + }{ + Code: 0, + Msg: "SUCCESS", + Data: nil, + } + + //支持error直接处理 + err, ok := running.GetVar("error").(error) + if ok { + resp.Code = 1 + resp.Msg = err.Error() + ctx.JSON(http.StatusOK, resp) + return + } + + code, ok := running.GetVar("code").(int) + if ok { + resp.Code = code + } + msg, ok := running.GetVar("msg").(string) + if ok { + resp.Msg = msg + } + data := running.GetVar("data") + if data != nil { + resp.Data = data + } + + ctx.JSON(http.StatusOK, resp) +} + +func (p *ApiResponsePlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return &ApiResponseHttpHandler{ + action: p, + data: p.conf, + } +} + +func (p *ApiResponsePlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} + +type ApiResponseHttpHandler struct { + action *ApiResponsePlugin + data *config.PluginData +} + +func (p *ApiResponseHttpHandler) swaggerDefinitions() map[string]spec.Schema { + resp := newSwaggerSpecSchema("object", "通用返回信息", "") + resp.SchemaProps = spec.SchemaProps{ + Description: "响应数据", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "code": newSwaggerSpecSchema("int", "状态码,0为正常,非0为有错误", 1), + "msg": newSwaggerSpecSchema("string", "提示消息", "SUCCESS"), + "data": newSwaggerSpecSchema("object", "具体数据", nil), + }, + } + schema := map[string]spec.Schema{ + "api.common.response": resp, + } + + return schema +} + +func (p *ApiResponseHttpHandler) Router() []config.GinHandleParam { + return []config.GinHandleParam{ + { + SwaggerDefinitions: p.swaggerDefinitions(), + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/api_search.go b/src/pkg/atapi/httpapi/v1/plugins/api_search.go new file mode 100644 index 0000000000000000000000000000000000000000..e1be624d0b9633d55136714b94d35792da52e08a --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/api_search.go @@ -0,0 +1,249 @@ +package plugins + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/dto/paginate" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/go-openapi/spec" + "github.com/spf13/cast" + "net/http" + "strings" +) + +type ApiSearchPlugin struct { + //请求参数(可搜索条件字段) + matchSearch []string //匹配查询参数 + fuzzySearch []string // + orderRules []string + + //分页用参数 + pageParam string + sizeParam string + + //返回字段 + respFields []string + + conf *config.PluginData +} + +func NewApiSearchPlugin() *ApiSearchPlugin { + //初始化 + p := &ApiSearchPlugin{} + + return p +} + +func (p *ApiSearchPlugin) Name() string { + return "API_SEARCH" +} + +func (p *ApiSearchPlugin) init() { + m := p.conf.Plugin.ExtendParams + if m == nil { + m = map[string]string{} + } + + //响应字段集合 + p.respFields = p.conf.Api.Data.FieldNames() //默认为全部字段 + responseFields := strings.Split(m[ResponseFieldsParamsKey], ",") + if len(responseFields) > 0 { + p.respFields = utils.ArrayIntersection(p.respFields, responseFields) + } + + logs.Out.Info("SetRespFields= %+v", responseFields) + p.respFields = utils.ArrayUnion([]string{ + "id", + "created_at", + "updated_at", + }, p.respFields) + + p.matchSearch = strings.Split(m[SearchFieldsParamsKey], ",") + p.fuzzySearch = strings.Split(m[SearchFuzzyFieldsParamsKey], ",") + p.orderRules = strings.Split(m[OrderRulesParamKey], ",") + //默认值 + p.pageParam = m.ExtendParamByString(PageNumParamsKey, "_page_no") + p.sizeParam = m.ExtendParamByString(PageSizeParamsKey, "_page_size") +} + +func (p *ApiSearchPlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &ApiSearchPlugin{conf: conf} + fa.init() + return fa +} + +func (p *ApiSearchPlugin) Describe() string { + return ` +提供查询查询数据列表的能力,可以自定义查询过滤条件,包括完全匹配查询字段和模糊匹配查询字段 +` +} + +func (p *ApiSearchPlugin) Extends() map[string]string { + return map[string]string{ + ResponseFieldsParamsKey: "f1,f2,f3", //指定返回字段名称,多个逗号分隔 + PageNumParamsKey: "_page_no", //指定页码 + PageSizeParamsKey: "_page_size", //指定查询条目 + } +} + +func (p *ApiSearchPlugin) Do(running ifs.RunningParam) { + var m = make(map[string]interface{}) + running.GinCtx().ShouldBindJSON(&m) + + pageNoInt := cast.ToInt(m[p.pageParam]) + pageSizeInt := cast.ToInt(m[p.sizeParam]) + + //todo 增加搜索参数的处理 + + //具体操作 + list, count, err := running.DataExec().DoSearch(nil, p.respFields, pageNoInt, pageSizeInt) + if err != nil { + running.SetVar("error", err) + return + } + pager := paginate.Pager{ + Page: pageNoInt, + Size: pageSizeInt, + Total: count, + } + pager.Correct() + + if list == nil { + list = []map[string]interface{}{} + } + running.SetVar("data", map[string]interface{}{ + "list": list, + "paginate": pager, + }) +} + +func (p *ApiSearchPlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return &ApiSearchHttpHandler{ + plugin: p, + data: p.conf, + } +} + +func (p *ApiSearchPlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} + +type ApiSearchHttpHandler struct { + plugin *ApiSearchPlugin + //运行时参数变量 + data *config.PluginData +} + +func (p *ApiSearchHttpHandler) swaggerPathItem() spec.PathItem { + searchParams := map[string]spec.Schema{} + fields := map[string]spec.Schema{} + + logs.Out.Info("Fields= %+v", p.data.Api.Data.Fields) + logs.Out.Info("Api= %+v", p.data.Api) + + searchParams["keywords"] = newSwaggerSpecSchema("string", "keywords", "") + + for _, v := range p.plugin.respFields { + fields[v] = newSwaggerSpecSchema("string", v, "example") + } + + searchParams[p.plugin.pageParam] = newSwaggerSpecSchema("int", "指定页码", 1) + searchParams[p.plugin.sizeParam] = newSwaggerSpecSchema("int", "指定条目数量", 10) + resp1 := spec.Response{ + ResponseProps: spec.ResponseProps{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Description: "响应Data", + Properties: map[string]spec.Schema{ + "list": { + SchemaProps: spec.SchemaProps{ + Description: "列表数据", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "数组子项内容", + Type: []string{"object"}, + Properties: fields, + }, + }, + }, + }, + }, + "paginate": { + SchemaProps: spec.SchemaProps{ + Description: "分页数据", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "page_no": newSwaggerSpecSchema("int", "当前页码", 1), + "page_size": newSwaggerSpecSchema("int", "单页数量", 10), + "total": newSwaggerSpecSchema("int", "页码总数", 7), + "count": newSwaggerSpecSchema("int", "数据总条数", 68), + }, + }, + }, + }, + }, + }, + Headers: nil, + Examples: nil, + }, + } + + return spec.PathItem{ + PathItemProps: spec.PathItemProps{ + Post: &spec.Operation{ + OperationProps: spec.OperationProps{ + Summary: "搜索列表", + Description: "搜索列表,根据搜索参数返回列表和分页信息", + Produces: []string{"application/json"}, + Schemes: nil, + Tags: []string{p.data.Api.Name}, + Parameters: []spec.Parameter{ + { + ParamProps: spec.ParamProps{ + Description: "搜索参数", + Name: "param", + In: "body", + Required: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: searchParams, + }, + }, + AllowEmptyValue: true, + }, + }, + }, + Responses: &spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + Default: nil, + StatusCodeResponses: map[int]spec.Response{ + 200: newSwaggerResponseFromRef("api.common.response"), + 201: resp1, + }, + }, + }, + }, + }, + }, + } +} + +func (p *ApiSearchHttpHandler) Router() []config.GinHandleParam { + path := fmt.Sprintf("/%s/search", p.data.Api.Name) + + return []config.GinHandleParam{ + { + Method: http.MethodPost, + Path: path, + SwaggerPaths: map[string]spec.PathItem{ + path: p.swaggerPathItem(), + }, + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/api_update.go b/src/pkg/atapi/httpapi/v1/plugins/api_update.go new file mode 100644 index 0000000000000000000000000000000000000000..c75d59204138d19d27f637454285b1711c8a073d --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/api_update.go @@ -0,0 +1,172 @@ +package plugins + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/go-openapi/spec" + "net/http" + "strings" +) + +type ApiUpdatePlugin struct { + conf *config.PluginData +} + +func NewApiUpdatePlugin() *ApiUpdatePlugin { + //初始化 + p := &ApiUpdatePlugin{} + + return p +} + +func (p *ApiUpdatePlugin) Name() string { + return "API_UPDATE" +} + +func (p *ApiUpdatePlugin) Describe() string { + return ` +提供更新数据的能力,可以自定义更新数据 +` +} + +func (p *ApiUpdatePlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &ApiUpdatePlugin{conf: conf} + return fa +} + +func (p *ApiUpdatePlugin) Do(running ifs.RunningParam) { + var m = make(map[string]interface{}) + running.GinCtx().ShouldBindJSON(&m) + + save := map[string]interface{}{} + for _, v := range p.conf.Api.Data.Fields { + val, exist := m[v.Name] + if !exist { + running.SetVar("error", fmt.Errorf("%s must post", v.Name)) + return + } + save[v.Name] = val + } + + //todo 增加搜索参数的处理 + id := int64(1) + + //具体操作 + id, err := running.DataExec().DoUpdate(id, save) + if err != nil { + running.SetVar("error", err) + return + } + running.SetVar("data", map[string]interface{}{ + "id": id, + }) +} + +func (p *ApiUpdatePlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return &ApiUpdateHttpHandler{ + action: p, + data: p.conf, + } +} + +func (p *ApiUpdatePlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} + +type ApiUpdateHttpHandler struct { + action *ApiUpdatePlugin + //运行时参数变量 + data *config.PluginData +} + +func (p *ApiUpdateHttpHandler) swaggerPathItem() spec.PathItem { + postParams := map[string]spec.Schema{} + fields := map[string]spec.Schema{} + + logs.Out.Info("Fields= %+v", p.data.Api.Data.Fields) + logs.Out.Info("Api= %+v", p.data.Api) + + for _, v := range p.data.Api.Data.Fields { + ty := "string" + var example interface{} = "example" + if strings.Index(v.SqlType, "int") >= 0 { + ty = "int" + example = 1 + } + + postParams[v.Name] = newSwaggerSpecSchema(ty, v.ShowName, example) + fields[v.Name] = newSwaggerSpecSchema(ty, v.ShowName, example) + } + + resp1 := spec.Response{ + ResponseProps: spec.ResponseProps{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Description: "响应Data", + Properties: map[string]spec.Schema{ + "id": newSwaggerSpecSchema("int", "条目id", 1), + }, + }, + }, + Headers: nil, + Examples: nil, + }, + } + + return spec.PathItem{ + PathItemProps: spec.PathItemProps{ + Post: &spec.Operation{ + OperationProps: spec.OperationProps{ + Summary: "更新保存", + Description: "更新操作,根据提交参数更新数据并返回条目id", + Produces: []string{"application/json"}, + Schemes: nil, + Tags: []string{p.data.Api.Name}, + Parameters: []spec.Parameter{ + { + ParamProps: spec.ParamProps{ + Description: "传参", + Name: "param", + In: "body", + Required: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: postParams, + }, + }, + AllowEmptyValue: true, + }, + }, + }, + Responses: &spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + Default: nil, + StatusCodeResponses: map[int]spec.Response{ + 200: newSwaggerResponseFromRef("api.common.response"), + 201: resp1, + }, + }, + }, + }, + }, + }, + } +} + +func (p *ApiUpdateHttpHandler) Router() []config.GinHandleParam { + path := fmt.Sprintf("/%s/update", p.data.Api.Name) + + return []config.GinHandleParam{ + { + Method: http.MethodPost, + Path: path, + SwaggerPaths: map[string]spec.PathItem{ + path: p.swaggerPathItem(), + }, + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/authorize_jwt.go b/src/pkg/atapi/httpapi/v1/plugins/authorize_jwt.go new file mode 100644 index 0000000000000000000000000000000000000000..7fe637245708872f9c61a9a3c11f2e4f07d11671 --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/authorize_jwt.go @@ -0,0 +1,60 @@ +package plugins + +import ( + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "net/http" +) + +type JWTAuthorizePlugin struct { + conf *config.PluginData + + tokenHeader string //token获取名 +} + +func NewJWTAuthorizePlugin() *JWTAuthorizePlugin { + p := &JWTAuthorizePlugin{} + + return p +} + +func (p *JWTAuthorizePlugin) Name() string { + return "AUTH_JWT" +} + +func (p *JWTAuthorizePlugin) Describe() string { + return ` +对请求进行授权检查 +` +} + +func (p *JWTAuthorizePlugin) Extends() map[string]string { + return map[string]string{ + SecretKey: "xxx", //指定秘钥key + } +} +func (p *JWTAuthorizePlugin) init() { + p.tokenHeader = "Authorization" +} + +func (p *JWTAuthorizePlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &JWTAuthorizePlugin{conf: conf} + fa.init() + return fa +} + +func (p *JWTAuthorizePlugin) Do(running ifs.RunningParam) { + token := running.GinCtx().Request.Header.Get(p.tokenHeader) + if token == "" { + running.GinCtx().String(http.StatusOK, "authorization deny") + running.Abort() + } +} + +func (p *JWTAuthorizePlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return nil +} + +func (p *JWTAuthorizePlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/base.go b/src/pkg/atapi/httpapi/v1/plugins/base.go new file mode 100644 index 0000000000000000000000000000000000000000..41e3fe6bf61edc0de53e4d1f8eef3ffd02adb9eb --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/base.go @@ -0,0 +1,18 @@ +package plugins + +const ( + SecretKey = "SECRET" //秘钥配置字段 + + SearchFieldsParamsKey = "SEARCH_FIELDS" //完全匹配搜索字段列表配置 + SearchFuzzyFieldsParamsKey = "SEARCH_FUZZY_FIELDS" //模糊搜索搜索字段列表 + OrderRulesParamKey = "ORDER_RULES" //排序规则参数配置 + + PageNumParamsKey = "PAGE_NUM_PARAM" //分页-页码参数名 + PageSizeParamsKey = "PAGE_SIZE_PARAM" //分页-单页数量参数名 + ResponseFieldsParamsKey = "RESPONSE_FIELDS" //响应返回字段列表 + SubmitFieldsParamsKey = "SUBMIT_FIELDS" //提交参数字段列表 + IdFieldKey = "ID_FIELD" //id字段(用于指定数据id) + SaasIdKey = "SAAS_ID_FIELD" //saas_id字段 + + RateLimitKey = "LIMIT_RATE" //每秒限制速率 +) diff --git a/src/pkg/atapi/httpapi/v1/plugins/help.go b/src/pkg/atapi/httpapi/v1/plugins/help.go new file mode 100644 index 0000000000000000000000000000000000000000..bb9e7f1c558c153758849bdb6b063f4093c12a45 --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/help.go @@ -0,0 +1,33 @@ +package plugins + +import "github.com/go-openapi/spec" + +func newSwaggerSpecSchema(ty string, desc string, example interface{}) spec.Schema { + return spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: desc, + Type: []string{ty}, + }, + ExtraProps: map[string]interface{}{ + "example": example, + }, + } +} + +func newSwaggerResponseFromRef(refName string) spec.Response { + return spec.Response{ + ResponseProps: spec.ResponseProps{ + Description: "", + Schema: &spec.Schema{ + VendorExtensible: spec.VendorExtensible{}, + SchemaProps: spec.SchemaProps{}, + SwaggerSchemaProps: spec.SwaggerSchemaProps{}, + ExtraProps: map[string]interface{}{ + "$ref": "#/definitions/" + refName, + }, + }, + Headers: nil, + Examples: nil, + }, + } +} diff --git a/src/pkg/atapi/httpapi/v1/plugins/rate_limit.go b/src/pkg/atapi/httpapi/v1/plugins/rate_limit.go new file mode 100644 index 0000000000000000000000000000000000000000..1facbdb5412b969cce2f88b1b044e5ada7f0f06d --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/plugins/rate_limit.go @@ -0,0 +1,55 @@ +package plugins + +import ( + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "net/http" +) + +type RateLimitPlugin struct { + conf *config.PluginData +} + +func NewRateLimitPlugin() *RateLimitPlugin { + p := &RateLimitPlugin{} + + return p +} + +func (p *RateLimitPlugin) Name() string { + return "RATE_LIMIT" +} + +func (p *RateLimitPlugin) Describe() string { + return ` +限流处理 +` +} + +func (p *RateLimitPlugin) Extends() map[string]string { + return map[string]string{ + RateLimitKey: "100", //指定限流大小 + } +} + +func (p *RateLimitPlugin) Factory(conf *config.PluginData) ifs.IApiPluginFactory { + fa := &RateLimitPlugin{conf: conf} + return fa +} + +func (p *RateLimitPlugin) Do(running ifs.RunningParam) { + ip := utils.GetRequestIp(running.GinCtx().Request) + if utils.TrueScopeRand(0, 100) < 50 { + running.GinCtx().String(http.StatusOK, ip+",rate limit") + running.Abort() + } +} + +func (p *RateLimitPlugin) HttpHandler() ifs.IApiPluginHttpHandler { + return nil +} + +func (p *RateLimitPlugin) CmdHandler() ifs.IApiPluginCmdHandler { + return nil +} diff --git a/src/pkg/atapi/httpapi/v1/running.go b/src/pkg/atapi/httpapi/v1/running.go new file mode 100644 index 0000000000000000000000000000000000000000..1ada25c21e01ab80d15abcf602e8cdba29db82ee --- /dev/null +++ b/src/pkg/atapi/httpapi/v1/running.go @@ -0,0 +1,46 @@ +package v1 + +import ( + "context" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "github.com/gin-gonic/gin" +) + +type runningData struct { + ctx context.Context + dataExec ifs.IDataExecCURD + abort bool + ginCtx *gin.Context + + data map[string]interface{} +} + +func (r *runningData) Ctx() context.Context { + return r.ctx +} + +func (r *runningData) Abort() { + r.abort = true +} + +func (r *runningData) GinCtx() *gin.Context { + return r.ginCtx +} + +func (r *runningData) DataExec() ifs.IDataExecCURD { + return r.dataExec +} + +func (r *runningData) GetVar(k string) interface{} { + if r.data == nil { + return nil + } + return r.data[k] +} + +func (r *runningData) SetVar(k string, v interface{}) { + if r.data == nil { + r.data = map[string]interface{}{} + } + r.data[k] = v +} diff --git a/src/pkg/atapi/ifs/data_exec.go b/src/pkg/atapi/ifs/data_exec.go new file mode 100644 index 0000000000000000000000000000000000000000..4ce61857f16e1862c2bde1ecc337035abc6a9b5d --- /dev/null +++ b/src/pkg/atapi/ifs/data_exec.go @@ -0,0 +1,23 @@ +package ifs + +import "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + +// IAutoApiDataExec 自定义的数据执行器 +type IAutoApiDataExec interface { + IDataExecBase + IDataExecCURD +} + +type IDataExecBase interface { + TableName() string + InitDB(name string, c config.AutoApiDataDefined) error + Copy() IAutoApiDataExec +} + +type IDataExecCURD interface { + DoSearch(params map[string]interface{}, fields []string, page, size int) ([]map[string]interface{}, int64, error) + DoQuery(params map[string]interface{}, fields []string) (map[string]interface{}, error) + DoCreate(params map[string]interface{}) (int64, error) + DoUpdate(id int64, params map[string]interface{}) (int64, error) + DoDelete(id int64) (int64, error) +} diff --git a/src/pkg/atapi/ifs/http_api.go b/src/pkg/atapi/ifs/http_api.go new file mode 100644 index 0000000000000000000000000000000000000000..169b4ac04344b916619bad220c0b50ebb9f0bb42 --- /dev/null +++ b/src/pkg/atapi/ifs/http_api.go @@ -0,0 +1,46 @@ +package ifs + +import ( + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" +) + +type IAutoApi interface { + IDataExec + IVars + + Config() config.AutoApiDefined + Code() string //唯一code + ShowName() string //展示名称 + Init() error //初始化 + + //InitHttp() error //初始化http api + // + //ApiEntry(request *http.Request, action string, params map[string]interface{}) (interface{}, error) //api-入口 + // + //Docs(req *http.Request) string //api文档 + // + //Configuration() string //序列化配置 + // + //LoadedProcesses() []IProcess //返回加载后的process处理器数组 + //LoadedActions() []IApiAction //返回加载后的process处理器数组 + + Handlers() []config.GinHandleParam +} + +// IDataExec dataExec操作 +type IDataExec interface { + SetDataExec(IAutoApiDataExec) //设置数据处理器-负责初始化数据库,操作数据CURD的相关操作 + GetDataExec() IAutoApiDataExec +} + +// IVars 共享变量操作 +type IVars interface { + SetVars(map[string]string) //设置可替换变量值 + GetVars() map[string]string +} + +type IAutoApiHelp interface { + Config() config.AutoApiDefined + GetDataExec() IAutoApiDataExec + GetVars() map[string]string //全局参数 +} diff --git a/src/pkg/atapi/ifs/plugin.go b/src/pkg/atapi/ifs/plugin.go new file mode 100644 index 0000000000000000000000000000000000000000..91fde0b71fe597544c38066068d68424bde7196b --- /dev/null +++ b/src/pkg/atapi/ifs/plugin.go @@ -0,0 +1,39 @@ +package ifs + +import ( + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" +) + +type IApiPlugin interface { + Name() string //plugin名称 + Describe() string //插件具体描述内容 + + Factory(*config.PluginData) IApiPluginFactory //工厂类,生成具体执行的插件 +} + +type IApiPluginFactory interface { + Do(param RunningParam) + + HttpHandler() IApiPluginHttpHandler //该插件的具体handler类 + CmdHandler() IApiPluginCmdHandler //该插件的具体handler类 +} + +// IApiPluginHandler 插件http场景下需支持的处理 +type IApiPluginHandler interface { + Do(param RunningParam) +} + +// IApiPluginHttpHandler 插件http场景下需支持的处理 +type IApiPluginHttpHandler interface { + Router() []config.GinHandleParam +} + +// IApiPluginCmdHandler 插件命令行场景下需支持的处理 +type IApiPluginCmdHandler interface { + //todo 后续增加 +} + +// IApiPluginRPCHandler 插件rpc场景下需支持的处理 +type IApiPluginRPCHandler interface { + //todo 后续增加 +} diff --git a/src/pkg/atapi/ifs/running.go b/src/pkg/atapi/ifs/running.go new file mode 100644 index 0000000000000000000000000000000000000000..276c74cd1d0c473f5e55ad93180d85966635e9c7 --- /dev/null +++ b/src/pkg/atapi/ifs/running.go @@ -0,0 +1,18 @@ +package ifs + +import ( + "context" + "github.com/gin-gonic/gin" +) + +// RunningParam 运行时使用的参数合集 +type RunningParam interface { + Ctx() context.Context + GinCtx() *gin.Context + DataExec() IDataExecCURD + + Abort() //终止处理 + + GetVar(string) interface{} + SetVar(string, interface{}) +} diff --git a/src/pkg/atapi/manager.go b/src/pkg/atapi/manager.go new file mode 100644 index 0000000000000000000000000000000000000000..4af13e50f6e9cb819baa34498e8a0fd4c2fa0c6b --- /dev/null +++ b/src/pkg/atapi/manager.go @@ -0,0 +1,201 @@ +package atapi + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + v1 "gitee.com/captials-team/ubdframe/src/pkg/atapi/httpapi/v1" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/httpapi/v1/plugins" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/ifs" + "gitee.com/captials-team/ubdframe/src/pkg/codec" + logv1 "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/gin-gonic/gin" + "github.com/go-openapi/spec" + "io/ioutil" + "strings" +) + +type pluginFunc func(map[string]string) ifs.IApiPlugin + +// AtApisManager at apis管理器 +type AtApisManager struct { + //配置 + config *config.AutoApiConfig + + //数据存储器 + store ifs.IAutoApiDataExec + + //格式化器 + format *codec.JsonCodec + + //所有atapis + httpApis map[string]ifs.IAutoApi + + extraPlugins []pluginFunc + + logv1.InvokeLog +} + +func NewAtApisManager(config *config.AutoApiConfig, opts ...interface{}) *AtApisManager { + mag := &AtApisManager{ + httpApis: map[string]ifs.IAutoApi{}, + config: config, + } + + for _, v := range opts { + if tmp, ok := v.(ifs.IAutoApiDataExec); ok { + mag.store = tmp + } + if tmp, ok := v.(logv1.ILog); ok { + mag.AddLogger(tmp) + } + } + mag.format = &codec.JsonCodec{} + return mag +} + +func (mag *AtApisManager) SetDataExec(store ifs.IAutoApiDataExec) { + mag.store = store +} + +func (mag *AtApisManager) AddPlugin(f pluginFunc) { + mag.extraPlugins = append(mag.extraPlugins, f) +} + +func (mag *AtApisManager) Initial() error { + for _, def := range mag.config.Apis { + var api config.AutoApiDefined = def + + if def.LoadFile != "" { + tmp, err := mag.readApiPath(def.LoadFile) + if err != nil { + return err + } + api = tmp + } + + //基本信息 + mag.Info("=====> API: %s-%s, Version: %s", api.Name, api.ShowName, api.Version) + apiHandler, err := mag.newAutoApi(api) + if err != nil { + mag.Error("at_api init fail: %s,%s", apiHandler.Code(), err) + continue + } + mag.httpApis[apiHandler.Code()] = apiHandler + mag.Info("%s loaded, handler: %s", api.Name, apiHandler.Code()) + } + return nil +} + +func (mag *AtApisManager) StartByGin(g gin.IRouter) error { + for _, v := range mag.httpApis { + mag.Info("%s start", v.Code()) + handlers := v.Handlers() + for _, h := range handlers { + if h.Method != "" && len(h.HandlerFunc) > 0 { + g.Handle(h.Method, h.Path, h.HandlerFunc...) + mag.Info("register router: %s,%s", h.Method, h.Path) + } + } + } + return nil +} + +func (mag *AtApisManager) StartBySwagger(w *spec.Swagger) error { + if w.Paths == nil { + w.Paths = &spec.Paths{} + } + if w.Definitions == nil { + w.Definitions = spec.Definitions{} + } + if w.Paths.Paths == nil { + w.Paths.Paths = make(map[string]spec.PathItem) + } + for _, api := range mag.httpApis { + handlers := api.Handlers() + mag.Info("%s swagger len=%d", api.Code(), len(handlers)) + for _, h := range handlers { + //合并swagger + if h.SwaggerPaths != nil { + for k, v := range h.SwaggerPaths { + w.Paths.Paths[k] = v + mag.Info("\tadd swagger path: %s", k) + } + } + if h.SwaggerDefinitions != nil { + for k, v := range h.SwaggerDefinitions { + w.Definitions[k] = v + mag.Info("\tadd swagger definition: %s", k) + } + } + } + } + return nil +} + +func (mag *AtApisManager) newAutoApi(api config.AutoApiDefined) (ifs.IAutoApi, error) { + switch strings.ToLower(api.Version) { + case v1.Version: + return mag.newAutoApiV1(api) + default: + return mag.newAutoApiV1(api) + } +} + +func (mag *AtApisManager) newAutoApiV1(apiDef config.AutoApiDefined) (*v1.AutoApi, error) { + api, err := v1.NewAutoApi(apiDef, mag.config.ExtendParams) + if err != nil { + return nil, fmt.Errorf("at_api new fail: %s", err) + } + api.SetDataExec(mag.store.Copy()) + //api.SetVars(vars) + //内置plugin + api.AddPlugin( + plugins.NewRateLimitPlugin(), + plugins.NewJWTAuthorizePlugin(), + ) + api.AddPlugin( + plugins.NewApiSearchPlugin(), + plugins.NewApiQueryPlugin(), + plugins.NewApiCreatePlugin(), + plugins.NewApiUpdatePlugin(), + plugins.NewApiDeletePlugin(), + plugins.NewApiResponsePlugin(), + ) + //自定义插件 + for _, tmp := range mag.extraPlugins { + api.AddPlugin(tmp(mag.config.ExtendParams)) + } + + if err := api.Init(); err != nil { + return nil, err + } + + return api, nil +} + +func (mag *AtApisManager) readApiPath(path string) (config.AutoApiDefined, error) { + vars := mag.config.ExtendParams + var c config.AutoApiDefined + + content, err := ioutil.ReadFile(path) + if err != nil { + return c, err + } + + //替换变量 + if vars != nil { + s := string(content) + for k, v := range vars { + s = strings.Replace(s, fmt.Sprintf("{{%s}}", k), v, -1) + } + content = []byte(s) + } + + err = utils.ReadYamlFile(&c, path) + if err != nil { + return c, err + } + + return c, nil +} diff --git a/src/pkg/atapi/manager_test.go b/src/pkg/atapi/manager_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6828515724814306b14421a75a5761ee9ea22abc --- /dev/null +++ b/src/pkg/atapi/manager_test.go @@ -0,0 +1,65 @@ +package atapi + +import ( + "encoding/json" + "gitee.com/captials-team/ubdframe/src/common" + "gitee.com/captials-team/ubdframe/src/common/utils" + "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/config" + "gitee.com/captials-team/ubdframe/src/pkg/atapi/dataexec" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/gin-gonic/gin" + "github.com/go-openapi/spec" + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +func TestNewManager(t *testing.T) { + g := gin.New() + mag := getTestAtApiManager(t) + + common.ErrPanic(mag.StartByGin(g)) + + common.ErrPanic(g.Run(":10000")) + time.Sleep(time.Hour) +} + +// TestAtManager_swagger 测试生成swagger +func TestAtManager_swagger(t *testing.T) { + mag := getTestAtApiManager(t) + + swg := &spec.Swagger{} + common.ErrPanic(mag.StartBySwagger(swg)) + + s, err := json.MarshalIndent(swg, "", "\t") + common.ErrPanic(err) + + t.Logf("\t%s", s) +} + +func getTestAtApiManager(t *testing.T) *AtApisManager { + c := config.AutoApiConfig{ + Apis: []config.AutoApiDefined{ + {LoadFile: utils.AbsPath(1) + "./tests/v1/org.yaml"}, + {LoadFile: utils.AbsPath(1) + "./tests/v1/demo.yaml"}, + }, + } + dataEx, err := dataexec.NewMysqlDbExec(configstc.DBConfig{ + DbHost: "192.168.149.128", + DbPort: "3306", + DbUser: "root", + DbPassword: "root", + DbName: "db_ubd_frame", + TablePrefix: "test_", + }) + assert.Equal(t, err, nil) + + mag := NewAtApisManager(&c) + mag.SetDataExec(dataEx) + mag.AddLogger(logs.Out.CallerSkip(1)) + + common.ErrPanic(mag.Initial()) + + return mag +} diff --git a/src/pkg/atapi/tests/v1/demo.yaml b/src/pkg/atapi/tests/v1/demo.yaml new file mode 100644 index 0000000000000000000000000000000000000000..58abe690f31465052784d45e7f3ccc071a9a48c3 --- /dev/null +++ b/src/pkg/atapi/tests/v1/demo.yaml @@ -0,0 +1,83 @@ +#这里是有全部功能配置的配置文件,供参考配置 +Version: "1" +Name: demo +ShowName: "DEMO" + +# 定义处理器(可以理解为API),有以下配置: +# Name,名称(将会使用在api path构成中),每一项为一个action +# Plugins,定义使用的插件 +Actions: + - Name: "搜索接口" + Enable: true + Plugins: + - Name: "RATE_LIMIT" + ExtendParams: + LIMIT_RATE: 30 + - Name: "API_SEARCH" + ExtendParams: + RESPONSE_FIELDS: "id,title,type,status" + - Name: "API_RESPONSE" + + - Name: "详情接口" + Enable: true + Plugins: + - Name: "RATE_LIMIT" + ExtendParams: + LIMIT_RATE: 30 + - Name: "API_QUERY" + ExtendParams: + RESPONSE_FIELDS: "id,title,type,content,status" + - Name: "API_RESPONSE" + + - Name: "创建接口" + Enable: true + Plugins: + - Name: "AUTH_JWT" + ExtendParams: + SECRET: abc123 + - Name: "RATE_LIMIT" + ExtendParams: + LIMIT_RATE: 30 + - Name: "API_CREATE" + ExtendParams: + RESPONSE_FIELDS: "id,title,type,status" + - Name: "API_RESPONSE" + + - Name: "保存接口" + Enable: true + Plugins: + - Name: "AUTH_JWT" + ExtendParams: + SECRET: abc123 + - Name: "RATE_LIMIT" + ExtendParams: + LIMIT_RATE: 30 + - Name: "API_UPDATE" + ExtendParams: + RESPONSE_FIELDS: "id,title,type,status" + - Name: "API_RESPONSE" + +#是否自动创建表数据等信息 +Data: + DataName: "" #自定义数据存储的标识名称,为空则会自动根据api名生成名称 + AutoTable: true + Fields: + - Name: title + SqlType: varchar(64) + Default: "" + Comment: 标题 + - Name: type + SqlType: tinyint unsigned + Default: "1" + Comment: "类型,0:无,1:文本,2:图片" + - Name: content + SqlType: varchar(1000) + Default: "1" + Comment: 块内容 + - Name: status + SqlType: tinyint unsigned + Default: "1" + Comment: 状态,0:无,1:有效,2:禁用 + Comment: DEMO管理 + + diff --git a/src/pkg/atapi/tests/v1/org.yaml b/src/pkg/atapi/tests/v1/org.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ed50feee415b48cb19b784c06022a46c287a2525 --- /dev/null +++ b/src/pkg/atapi/tests/v1/org.yaml @@ -0,0 +1,42 @@ +#这里是有全部功能配置的配置文件,供参考配置 +Version: "1" +Name: org +ShowName: "组织" + +# 定义处理器(可以理解为API),有以下配置: +# Name,名称(将会使用在api path构成中),每一项为一个action +# Plugins,定义使用的插件 +Actions: + - Name: "搜索接口" + Enable: true + Plugins: + - Name: "RATE_LIMIT" + ExtendParams: + limit_rate: 2 + - Name: "API_SEARCH" + ExtendParams: + fields: "id,name,pid,status" + - Name: "API_RESPONSE" + +#是否自动创建表数据等信息 +Data: + DataName: "" #自定义数据存储的标识名称,为空则会自动根据api名生成名称 + AutoTable: true + Fields: + - Name: saas_id + SqlType: varchar(20) + Default: "" + Comment: saas model + - Name: name + SqlType: varchar(64) + Default: "未命名" + Comment: 组织名 + - Name: pid + SqlType: bigint unsigned + Default: "0" + Comment: pid + - Name: status + SqlType: tinyint unsigned + Default: "1" + Comment: 状态,0:无,1:有效,2:禁用 + Comment: 组织管理 \ No newline at end of file diff --git a/src/pkg/extendparams/params.go b/src/pkg/extendparams/params.go new file mode 100644 index 0000000000000000000000000000000000000000..0ad2582ad7be3a6427a3670948e9093fa7aa3166 --- /dev/null +++ b/src/pkg/extendparams/params.go @@ -0,0 +1,88 @@ +package extendparams + +import ( + "strconv" + "strings" +) + +type CommonExtendParams map[string]string + +// ExtendParamByInt 返回extendParam指定k的int类型值 +func (op CommonExtendParams) ExtendParamByInt(k string, def ...int) int { + v := op.ExtendParamValue(k) + ret, err := strconv.Atoi(v) + if err != nil { + if len(def) > 0 { + return def[0] + } + return 0 + } + return ret +} + +// ExtendParamByInt64 返回extendParam指定k的int类型值 +func (op CommonExtendParams) ExtendParamByInt64(k string, def ...int64) int64 { + v := op.ExtendParamValue(k) + ret, err := strconv.ParseInt(v, 10, 64) + if err != nil { + if len(def) > 0 { + return def[0] + } + return 0 + } + return ret +} + +// ExtendParamByFloat 返回extendParam指定k的float类型值 +func (op CommonExtendParams) ExtendParamByFloat(k string, def ...float64) float64 { + v := op.ExtendParamValue(k) + ret, err := strconv.ParseFloat(v, 64) + if err != nil { + if len(def) > 0 { + return def[0] + } + return 0 + } + return ret +} + +// ExtendParamByBool 返回extendParam指定k的bool类型值 +func (op CommonExtendParams) ExtendParamByBool(k string, def ...bool) bool { + v := op.ExtendParamValue(k) + if v == "" { + if len(def) > 0 { + return def[0] + } + return false + } + + if v == "true" { + return true + } + + if v == "false" { + return true + } + + return v != "0" +} + +// ExtendParamByString 返回extendParam指定k的string类型值 +func (op CommonExtendParams) ExtendParamByString(k string, def ...string) string { + return op.ExtendParamValue(k, def...) +} + +func (op CommonExtendParams) ExtendParamValue(key string, def ...string) string { + if op == nil { + return "" + } + v := strings.TrimSpace(op[key]) + if v == "" { + if len(def) > 0 { + return def[0] + } + return "" + } + + return v +} diff --git a/src/pkg/jobworker/config.go b/src/pkg/jobworker/config.go index 931d5c1f21615fced023fc5aa6b687373b5a14ce..fdc44025feb6975ba11ee0272e6a3bc1220ddced 100644 --- a/src/pkg/jobworker/config.go +++ b/src/pkg/jobworker/config.go @@ -7,8 +7,52 @@ import ( "gopkg.in/yaml.v3" ) -func NewJobConfig(s ...string) *configstc.JobConfig { - var c configstc.JobConfig +// JobConfig 执行job配置 +/* 示例配置 + + multi_files: + #平常灵活使用的压测配置 + - data/jobs/iot_demo.yaml + + # 详细action配置,数组,每个子项配置如下: + # actions 定义需要执行的操作,多个以逗号分隔,值可参考 当前所在目录/config/consts.go 文件 + # op_interval 定义本批次操作的再次执行的间隔时间,单位:毫秒 + # 如本次操作组合有10次操作,定义500毫秒间隔,则相当于下单频率为每分钟20 + # extend_params 定义扩展参数,不同的action使用的参数不一样,可配置key参考 当前所在目录/config/consts.go 文件 + # + # 总qps = sum(actions数量*contracts数量*accounts数量*1000/间隔时间) + # 每个qps = sum(actions数量*accounts数量*1000/间隔时间) + multi_actions: + ################################下面是demo worker + - actions1: "demo" + count: 1 + op_interval: 1000 #每个操作的间隔时间,单位:毫秒 + extend_params: + percent: "21" + + # 全局可用参数配置 + global_params: + mqtt_core: "192.168.149.128:57081" + mqtt_driver: "16774105" + +*/ +type JobConfig struct { + MultiFiles []string `yaml:"multi_files"` //多压测动作配置文件数组 + MultiActions []MultiActionItem `yaml:"multi_actions"` //多压测动作配置数组 + GlobalParams map[string]string `yaml:"global_params"` //全局参数 +} + +// MultiActionItem 压测动作配置项 +type MultiActionItem struct { + Id int + Actions string `yaml:"actions"` //动作,多个以逗号分割,每个单一动作名标识某种操作 + Count int `yaml:"count"` //执行数量 + OpInterval int64 `yaml:"op_interval"` //执行间隔,为0则表示持续执行,>0为指定多少ms执行一次 + ExtendParams map[string]string `yaml:"extend_params"` //扩展参数,不同action支持不同参数 +} + +func NewJobConfig(s ...string) *JobConfig { + var c JobConfig err := utils.ReadYamlFile(&c, configstc.DefiConfigPath(s...)) if err != nil { @@ -18,8 +62,8 @@ func NewJobConfig(s ...string) *configstc.JobConfig { return &c } -func ParseJobConfig(s string) *configstc.JobConfig { - var c configstc.JobConfig +func ParseJobConfig(s string) *JobConfig { + var c JobConfig yaml.Unmarshal([]byte(s), &c) return &c } diff --git a/src/pkg/jobworker/mgr.go b/src/pkg/jobworker/mgr.go index 409e7b93d187a5ba53c6f6352a4fdecf22f800e8..8d63486f5d357657e0207c86e326bd6744665f1d 100644 --- a/src/pkg/jobworker/mgr.go +++ b/src/pkg/jobworker/mgr.go @@ -1,9 +1,10 @@ package jobworker import ( + "context" "fmt" "gitee.com/captials-team/ubdframe/src/common/utils" - "gitee.com/captials-team/ubdframe/src/domain/configstc" + "gitee.com/captials-team/ubdframe/src/pkg/contexts" v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" "gitee.com/captials-team/ubdframe/src/pkg/metrics" "go.uber.org/dig" @@ -12,10 +13,18 @@ import ( "time" ) +// WorkerRunningData worker运行信息 +type WorkerRunningData struct { + Count int64 //已运行次数 + StartAt int64 //开始运行时间,时间戳 + LastAt int64 //最后运行时间,时间戳 +} + type WorkerMgr struct { di *dig.Container - cfg *configstc.JobConfig + cfg *JobConfig l v1log.ILog + ctx *contexts.AdvancedContext //运行的worker workers []IWorker @@ -26,19 +35,23 @@ type WorkerMgr struct { monitor chan metrics.IndicData indicators []metrics.IIndicator //上报指标 + + running map[string]*WorkerRunningData //运行信息 } func (mgr *WorkerMgr) Name() string { return "worker_mgr" } -func NewWorkerMgr(di *dig.Container, c *configstc.JobConfig, l v1log.ILog) *WorkerMgr { +func NewWorkerMgr(di *dig.Container, c *JobConfig, l v1log.ILog) *WorkerMgr { mgr := &WorkerMgr{ di: di, cfg: c, l: l, regWorkers: map[string]YieldWorkerFunc{}, monitor: make(chan metrics.IndicData, 64), + ctx: contexts.NewCancelAdvancedContext(context.Background()), + running: make(map[string]*WorkerRunningData, 64), } return mgr @@ -53,6 +66,11 @@ func (mgr *WorkerMgr) Start() error { return nil } +func (mgr *WorkerMgr) Run() error { + mgr.RunOnce(1) + return nil +} + func (mgr *WorkerMgr) RunOnce(times ...int64) { mgr.loadFiles() mgr.loadWorkers() @@ -66,8 +84,20 @@ func (mgr *WorkerMgr) Stop() error { return nil } +func (mgr *WorkerMgr) Workers() []IWorker { + return mgr.workers +} + +func (mgr *WorkerMgr) RegWorkers() map[string]IWorker { + var list = make(map[string]IWorker) + for k, v := range mgr.regWorkers { + list[k] = v(mgr.di, nil) + } + return list +} + // StartAction 单独启动一个action处理 -func (mgr *WorkerMgr) StartAction(item configstc.MultiActionItem) error { +func (mgr *WorkerMgr) StartAction(item MultiActionItem) error { workers := mgr.actionItem2Workers(0, item) mgr.runWorkers(workers) @@ -75,7 +105,7 @@ func (mgr *WorkerMgr) StartAction(item configstc.MultiActionItem) error { } // AsyncStartAction 异步-StartAction -func (mgr *WorkerMgr) AsyncStartAction(item configstc.MultiActionItem) { +func (mgr *WorkerMgr) AsyncStartAction(item MultiActionItem) { go mgr.StartAction(item) } @@ -90,6 +120,10 @@ func (mgr *WorkerMgr) runWorkers(workers []IWorker, times ...int64) { var wg sync.WaitGroup + for _, w := range workers { + mgr.running[w.Op().OpId] = &WorkerRunningData{} + } + for _, w := range workers { mgr.l.Info("worker start: %s, id=%s", w.Name(), w.Op().OpId) mgr.l.Info("worker Op config[%s-%s] %+v", w.Name(), w.Op().OpId, w.Op()) @@ -99,11 +133,18 @@ func (mgr *WorkerMgr) runWorkers(workers []IWorker, times ...int64) { go func() { defer wg.Done() + //只运行count次数 if count > 0 { - copyW.Run(count) - } else { - copyW.Start() + go mgr.runWorkerByCount(copyW, count) + return + } + //受控运行 + if ctrW, ok := copyW.(IWorkerCtr); ok { + go mgr.runWorkerByCtr(ctrW) + return } + + go mgr.runWorkerByInterval(copyW) }() } @@ -111,12 +152,72 @@ func (mgr *WorkerMgr) runWorkers(workers []IWorker, times ...int64) { wg.Wait() } -func (mgr *WorkerMgr) stopWorkers(workers []IWorker) { - for _, v := range workers { - v.Stop() +// runWorkerByCount 指定次数运行 +func (mgr *WorkerMgr) runWorkerByCount(w IWorker, count int64) { + running := mgr.running[w.Op().OpId] + running.StartAt = time.Now().UnixMilli() + + for i := int64(1); i <= count; i++ { + select { + case <-mgr.ctx.Done(): + return + default: + w.Run(1) + running.LastAt = time.Now().UnixMilli() + running.Count++ + } } } +// runWorkerByCtr 受控运行 +func (mgr *WorkerMgr) runWorkerByCtr(w IWorkerCtr) { + running := mgr.running[w.Op().OpId] + running.StartAt = time.Now().UnixMilli() + w.Start() + + for { + select { + case <-mgr.ctx.Done(): + w.Stop() + return + } + } +} + +// runWorkerByInterval 间隔运行 +func (mgr *WorkerMgr) runWorkerByInterval(w IWorker) { + ti := time.NewTicker(time.Second) + if w.Interval() > 0 { + ti = time.NewTicker(w.Interval()) + } + i := 0 + running := mgr.running[w.Op().OpId] + running.StartAt = time.Now().UnixMilli() + + for { + i++ + select { + case <-mgr.ctx.Done(): + return + case <-ti.C: + w.Run(1) + running.LastAt = time.Now().UnixMilli() + running.Count++ + } + } +} + +func (mgr *WorkerMgr) QueryRunning(opId string) *WorkerRunningData { + if d, exist := mgr.running[opId]; exist { + return d + } + return nil +} + +func (mgr *WorkerMgr) stopWorkers(workers []IWorker) { + mgr.ctx.Cancel(nil) +} + func (mgr *WorkerMgr) runMonitor(ch chan metrics.IndicData) { defer mgr.l.Info("worker monitor stop") @@ -141,7 +242,7 @@ func (mgr *WorkerMgr) AsyncStart() { func (mgr *WorkerMgr) loadFiles() { for _, f := range mgr.cfg.MultiFiles { - var c configstc.JobConfig + var c JobConfig err := utils.ReadYamlFile(&c, f) if err != nil { panic(fmt.Sprintf("read config yaml: %s", err)) @@ -167,7 +268,7 @@ func (mgr *WorkerMgr) loadWorkers() { mgr.workers = workers } -func (mgr *WorkerMgr) actionItem2Workers(index int, item configstc.MultiActionItem) []IWorker { +func (mgr *WorkerMgr) actionItem2Workers(index int, item MultiActionItem) []IWorker { var workers []IWorker item.Id = index //将配置的动作(Action)转为实际操作参数(JobParam) @@ -224,7 +325,7 @@ func (mgr *WorkerMgr) RegAction(f DoWorkerActionFunc, moreNames ...string) { mgr.Reg(f.YieldWorkerFunc, moreNames...) } -func (mgr *WorkerMgr) action2JobParams(cfg *configstc.JobConfig, item configstc.MultiActionItem) []*JobParam { +func (mgr *WorkerMgr) action2JobParams(cfg *JobConfig, item MultiActionItem) []*JobParam { //生成worker并append count := item.Count if count <= 0 { @@ -257,7 +358,7 @@ func (mgr *WorkerMgr) action2JobParams(cfg *configstc.JobConfig, item configstc. return ops } -func (mgr *WorkerMgr) itemOpId(item configstc.MultiActionItem, index int) string { +func (mgr *WorkerMgr) itemOpId(item MultiActionItem, index int) string { count := item.Count if count <= 0 { count = 1 diff --git a/src/pkg/jobworker/worker.go b/src/pkg/jobworker/worker.go index d8173f624016df0ccf784df4b3cb273fb5cffe6c..cba12580ee3f5e63841e645a794366d8a5079882 100644 --- a/src/pkg/jobworker/worker.go +++ b/src/pkg/jobworker/worker.go @@ -16,9 +16,6 @@ type IWorker interface { Actions() []string //支持的actions Params() map[string]string //支持的参数 - Start() //一直运行 - Stop() - Run(int64) //只运行一次 Debug() //debug用 @@ -26,6 +23,14 @@ type IWorker interface { //Tps() float64 //总tps } +// IWorkerCtr 可受控worker +type IWorkerCtr interface { + IWorker + + Start() //自行处理start + Stop() +} + type IWorkerMonitor interface { SetMonitor(chan metrics.IndicData) } diff --git a/src/pkg/logs/consts.go b/src/pkg/logs/consts.go index 7fc51e3606598c65b6ca9d9f6a9482a4612b2928..fcc52c21db203fd7641a7eddc4a8d3859ab5b285 100644 --- a/src/pkg/logs/consts.go +++ b/src/pkg/logs/consts.go @@ -7,7 +7,7 @@ import ( // 全局logger var ( - Out ILog = NewWriterLog(os.Stdout, DebugLog).CallerSkip(01) + Out ILog = NewWriterLog(os.Stdout, DebugLog).CallerSkip(0) ) func SetLogger(log ILog) { diff --git a/src/pkg/ossadaptor/local_oss.go b/src/pkg/ossadaptor/local_oss.go index 8c6aedff3fd764ec614bfdf01c4e3a7c1b2b24b1..bec59e8539ce8c192d440e4bc199cf486431df1e 100644 --- a/src/pkg/ossadaptor/local_oss.go +++ b/src/pkg/ossadaptor/local_oss.go @@ -1,11 +1,14 @@ package ossadaptor import ( + "crypto/md5" "encoding/json" "fmt" "gitee.com/captials-team/ubdframe/src/common/utils" + "io" "os" "path" + "path/filepath" "strings" "time" ) @@ -16,14 +19,14 @@ type LocalOss struct { subPath string } -func NewLocalOss(bindDomain string, path string) *LocalOss { +func NewLocalOss(bindDomain string, storagePath string) *LocalOss { if !strings.HasPrefix(bindDomain, "http") { bindDomain = "http://" + bindDomain } return &LocalOss{ bindDomain: bindDomain, - storagePath: path, - subPath: "oss", + storagePath: storagePath, + subPath: "", } } @@ -49,27 +52,81 @@ func renameFileName() string { func (oss *LocalOss) ossStoragePath() string { p := path.Join(oss.storagePath, oss.subPath) - if !utils.IsExistPath(p) { - os.MkdirAll(p, os.ModeDir|0755) - } return p } func (oss *LocalOss) url(fName string) string { - return fmt.Sprintf("%s/%s/%s", oss.bindDomain, oss.subPath, fName) + var arr []string + if oss.bindDomain != "" { + arr = append(arr, oss.bindDomain) + } + if oss.subPath != "" { + arr = append(arr, oss.subPath) + } + if fName != "" { + arr = append(arr, fName) + } + + return strings.Join(arr, "/") +} + +// PutReader 上传文件, file: 本地文件路径,objName: 存储的对象名 +func (oss *LocalOss) PutReader(file io.Reader, objName string) (*UploadRet, error) { + + var ret UploadRet + filePath, err := SaveReaderFile(file, oss.ossStoragePath(), objName) + if err != nil { + return &ret, err + } + + ret.Url = oss.url(objName) + + f, err := os.Open(filePath) + if err != nil { + return &ret, err + } + + md := md5.New() + io.Copy(md, f) + f.Close() + ret.Md5Sum = fmt.Sprintf("%x", md.Sum(nil)) //文件md5值 + + return &ret, nil } +// Put 上传文件, file: 本地文件路径,objName: 存储的对象名 func (oss *LocalOss) Put(file string, objName string) (*UploadRet, error) { - ret := &UploadRet{} + var ret UploadRet + + f, err := os.Open(file) + if err != nil { + return &ret, err + } - fPath := path.Join(oss.ossStoragePath(), objName) + return oss.PutReader(f, objName) +} - err := os.Rename(file, fPath) +// SaveReaderFile 保存文件,file:对应reader,saveDir:保存路径,saveFile:保存文件名 +func SaveReaderFile(file io.Reader, saveDir, saveFile string) (string, error) { + // 确保目标文件夹存在 + err := utils.EnsureDir(saveDir) if err != nil { - return ret, err + return "", err } - ret.Url = oss.url(objName) + // 创建目标文件 + dstPath := filepath.Join(saveDir, saveFile) + dst, err := os.Create(dstPath) + if err != nil { + return "", err + } + defer dst.Close() + + // 将上传的文件内容复制到目标文件 + _, err = io.Copy(dst, file) + if err != nil { + return "", err + } - return ret, nil + return dstPath, nil } diff --git a/src/pkg/ossadaptor/local_oss_test.go b/src/pkg/ossadaptor/local_oss_test.go new file mode 100644 index 0000000000000000000000000000000000000000..221ed93b0d8aeb4c1d4e1b22bb45fc13e024ff28 --- /dev/null +++ b/src/pkg/ossadaptor/local_oss_test.go @@ -0,0 +1,16 @@ +package ossadaptor + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestLocalOss_Put(t *testing.T) { + o := NewLocalOss("127.0.0.1:10000/oss", "./runtime/oss") + + ret, err := o.Put("./local_oss_test.go", "aaa.tmp") + assert.Equal(t, err, nil) + + t.Logf("URL= %s", ret.Url) + t.Logf("MD5= %s", ret.Md5Sum) +} diff --git a/src/pkg/ossadaptor/minio_oss.go b/src/pkg/ossadaptor/minio_oss.go index db5672b8a2f47596ae52e0a97fdd41dbf6b2ee0e..ffde4bf4e1eef9f114876ffbee727ecf5ab08bf2 100644 --- a/src/pkg/ossadaptor/minio_oss.go +++ b/src/pkg/ossadaptor/minio_oss.go @@ -1,12 +1,15 @@ package ossadaptor import ( + "crypto/md5" "encoding/json" "fmt" "gitee.com/captials-team/ubdframe/src/pkg/logs" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "golang.org/x/net/context" + "io" + "os" "path" "strings" ) @@ -70,6 +73,26 @@ func (oss *MinioOss) url(info minio.UploadInfo) string { return fmt.Sprintf("%s/%s/%s", oss.bindDomain, info.Bucket, info.Key) } +// PutReader 上传文件, file: 本地文件路径,objName: 存储的对象名 +func (oss *MinioOss) PutReader(file io.Reader, objName string) (*UploadRet, error) { + ret := &UploadRet{} + + distPath := fmt.Sprintf("./tmp_oss_%s.tmp", renameFileName()) + dst, err := os.Create(distPath) + if err != nil { + return ret, err + } + defer os.Remove(distPath) + + _, err = io.Copy(dst, file) + if err != nil { + return ret, err + } + dst.Close() + + return oss.Put(distPath, objName) +} + // Put 上传文件, file: 本地文件路径,objName: minio存储的对象名 func (oss *MinioOss) Put(file string, objName string) (*UploadRet, error) { ret := &UploadRet{} @@ -83,6 +106,15 @@ func (oss *MinioOss) Put(file string, objName string) (*UploadRet, error) { ret.Url = oss.url(info) + f, err := os.Open(file) + if err != nil { + return ret, err + } + + md := md5.New() + io.Copy(md, f) + f.Close() + ret.Md5Sum = fmt.Sprintf("%x", md.Sum(nil)) //文件md5值 //println(oss.client.EndpointURL()) return ret, nil diff --git a/src/pkg/ossadaptor/oss.go b/src/pkg/ossadaptor/oss.go index 8cc7ccf6b132b141ea6de9236c9832ce57c72eb5..14cbb6184635803ff1eda5feab9096d7baf52f20 100644 --- a/src/pkg/ossadaptor/oss.go +++ b/src/pkg/ossadaptor/oss.go @@ -11,7 +11,8 @@ type IOssHandler interface { // UploadRet 上传结果struct type UploadRet struct { - Url string + Url string `json:"url"` + Md5Sum string `json:"md5Sum"` } func NewOssUploader(upType string, config map[string]string) (IOssHandler, error) { diff --git a/src/pkg/proxyhandler/config.go b/src/pkg/proxyhandler/config.go new file mode 100644 index 0000000000000000000000000000000000000000..4d9731adfd6861484156968df1564cb7dfb243a6 --- /dev/null +++ b/src/pkg/proxyhandler/config.go @@ -0,0 +1,16 @@ +package proxyhandler + +// ProxyRule 转发规则 +type ProxyRule struct { + Mode string `json:"Mode" yaml:"Mode"` //转发模式 + + Match string `json:"Match" yaml:"Match"` //匹配模式,见下面的 ProxyModePrefix/ProxyModeFix + + Forward string `json:"Forward" yaml:"Forward"` //转发目标 + Replace string `json:"Replace" yaml:"Replace"` //替换前缀 +} + +const ( + ProxyModePrefix = "prefix" //前缀替换,匹配并替换指定前缀 + ProxyModeFix = "fixed" //固定地址,完全匹配路由进行转发 +) diff --git a/src/pkg/proxyhandler/proxy.go b/src/pkg/proxyhandler/proxy.go index 2e1de80a4381ad6c203a13ca941dc980806182d6..1337fbc89bb86bdd7e35475561e3fec5fcfcded5 100644 --- a/src/pkg/proxyhandler/proxy.go +++ b/src/pkg/proxyhandler/proxy.go @@ -2,7 +2,6 @@ package proxyhandler import ( "gitee.com/captials-team/ubdframe/src/common" - "gitee.com/captials-team/ubdframe/src/domain/configstc" "github.com/gin-gonic/gin" "net/http" "net/http/httputil" @@ -17,11 +16,11 @@ type ItfProxyMode interface { // ProxyByPrefix 根据前缀转发的代理 type ProxyByPrefix struct { - rule *configstc.ProxyRule + rule *ProxyRule proxy *httputil.ReverseProxy } -func NewProxyByPrefix(rule configstc.ProxyRule) *ProxyByPrefix { +func NewProxyByPrefix(rule ProxyRule) *ProxyByPrefix { parseRootUrl, err := url.Parse(rule.Forward) common.ErrPanic(err) proxy := httputil.NewSingleHostReverseProxy(parseRootUrl) @@ -46,11 +45,11 @@ func (p *ProxyByPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // ProxyByFixed 固定匹配转发 type ProxyByFixed struct { - rule *configstc.ProxyRule + rule *ProxyRule proxy *httputil.ReverseProxy } -func NewProxyByFixed(rule configstc.ProxyRule) *ProxyByFixed { +func NewProxyByFixed(rule ProxyRule) *ProxyByFixed { parseRootUrl, err := url.Parse(rule.Forward) common.ErrPanic(err) proxy := httputil.NewSingleHostReverseProxy(parseRootUrl) @@ -82,17 +81,17 @@ func (p *ProxyNone) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } -func NewProxy(rule configstc.ProxyRule) ItfProxyMode { +func NewProxy(rule ProxyRule) ItfProxyMode { switch rule.Mode { - case configstc.ProxyModePrefix: + case ProxyModePrefix: return NewProxyByPrefix(rule) - case configstc.ProxyModeFix: + case ProxyModeFix: return NewProxyByFixed(rule) } return &ProxyNone{} } -func NewProxyGroup(rules ...configstc.ProxyRule) []ItfProxyMode { +func NewProxyGroup(rules ...ProxyRule) []ItfProxyMode { var arr []ItfProxyMode for _, v := range rules { diff --git a/src/pkg/rsshelp/rss.go b/src/pkg/rsshelp/rss.go index dbb3257081e55c6a71b0a10be47d2f36a6b44ae3..79df60f249e3d730af1a77649651899829c0820c 100644 --- a/src/pkg/rsshelp/rss.go +++ b/src/pkg/rsshelp/rss.go @@ -2,7 +2,6 @@ package rsshelp import ( "fmt" - "gitee.com/captials-team/ubdframe/src/domain/vo" v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" "io" "net/http" @@ -12,12 +11,12 @@ import ( type RssFetcher struct { l v1log.ILog - rssMap map[string]*vo.RssMeta + rssMap map[string]*RssMeta client *http.Client handlers []RssHandler } -type RssHandler func(meta *vo.RssMeta, body *vo.RssBody) +type RssHandler func(meta *RssMeta, body *RssBody) func NewRssFetcher(l v1log.ILog) *RssFetcher { if l == nil { @@ -25,19 +24,19 @@ func NewRssFetcher(l v1log.ILog) *RssFetcher { } return &RssFetcher{ client: &http.Client{Timeout: time.Second * 5}, - rssMap: map[string]*vo.RssMeta{}, + rssMap: map[string]*RssMeta{}, l: l, } } -func (w *RssFetcher) AddRssMeta(meta ...*vo.RssMeta) { +func (w *RssFetcher) AddRssMeta(meta ...*RssMeta) { for _, v := range meta { w.rssMap[v.Name] = v } } func (w *RssFetcher) AddRss(name, url string) { - w.rssMap[name] = &vo.RssMeta{ + w.rssMap[name] = &RssMeta{ Name: name, RssUrl: url, } @@ -48,7 +47,7 @@ func (w *RssFetcher) AddHandler(h RssHandler) { } // runPullRss 拉取rss -func (w *RssFetcher) runPullRss(meta *vo.RssMeta, handlers ...RssHandler) error { +func (w *RssFetcher) runPullRss(meta *RssMeta, handlers ...RssHandler) error { w.l.Info("rss pull running: %+v", meta) var err error @@ -94,8 +93,8 @@ func (w *RssFetcher) FetchHandler(handlers ...RssHandler) { } } -func (w *RssFetcher) parseRss(r io.Reader) (*vo.RssBody, error) { - rss := &vo.RssBody{} +func (w *RssFetcher) parseRss(r io.Reader) (*RssBody, error) { + rss := &RssBody{} err := rss.Parse(r) if err != nil { return rss, err diff --git a/src/pkg/rsshelp/rss_test.go b/src/pkg/rsshelp/rss_test.go index d7cbf5ec71fd94e6f00f666cd4148f24b4eb2d7f..358bcd40db1f2ff11e19e86f957ba3fa2815c2a9 100644 --- a/src/pkg/rsshelp/rss_test.go +++ b/src/pkg/rsshelp/rss_test.go @@ -1,7 +1,6 @@ package rsshelp import ( - "gitee.com/captials-team/ubdframe/src/domain/vo" v1log "gitee.com/captials-team/ubdframe/src/pkg/logs" "testing" ) @@ -10,14 +9,14 @@ func TestRssFetchWorker_Run(t *testing.T) { l := v1log.NewTestingLog(t, v1log.DebugLog) rss := NewRssFetcher(l) - rss.AddRssMeta(&vo.RssMeta{ + rss.AddRssMeta(&RssMeta{ Name: "people_com_china", RssUrl: "http://www.people.com.cn/rss/politics.xml", }) rss.AddRss("sohu_com_china", "http://rss.news.sohu.com/rss/pfocus.xml") rss.AddRss("baidu_news", "https://news.baidu.com/n?cmd=1&class=civilnews&tn=rss&sub=0") - rss.AddHandler(func(meta *vo.RssMeta, body *vo.RssBody) { + rss.AddHandler(func(meta *RssMeta, body *RssBody) { t.Logf("META %+v", meta) //t.Logf("Content %+v", body.Channel) diff --git a/src/pkg/rsshelp/vo.go b/src/pkg/rsshelp/vo.go new file mode 100644 index 0000000000000000000000000000000000000000..7cbb10ec2bc8e2d77fb2fa47f829ce365baeaaeb --- /dev/null +++ b/src/pkg/rsshelp/vo.go @@ -0,0 +1,51 @@ +package rsshelp + +import ( + "encoding/xml" + "io" +) + +// RssMeta 源信息 +type RssMeta struct { + Name string + RssUrl string +} + +// RssBody rss内容body +type RssBody struct { + Channel RssChannel `xml:"channel"` +} + +type RssChannel struct { + Title string `xml:"title"` + Description string `xml:"description"` + Link string `xml:"link"` + PubDate string `xml:"pubDate"` + Language string `xml:"language"` + Copyright string `xml:"copyright"` + Generator string `xml:"generator"` + Image struct { + Title string `xml:"title"` + Url string `xml:"url"` + Link string `xml:"link"` + } `xml:"image"` + Items []*RssItems `xml:"item"` +} + +type RssItems struct { + Title string `json:"title" xml:"title"` //新闻标题 + Author string `json:"author" xml:"author"` //作者 + Link string `json:"link" xml:"link"` //连接 + PubDate string `json:"pubDate" xml:"pubDate"` //发布日期/时间 + Description string `json:"description" xml:"description"` //描述信息 +} + +func (rss *RssBody) Parse(r io.Reader) error { + decoder := xml.NewDecoder(r) + err := decoder.Decode(rss) + if err != nil { + return err + } + + return nil +} diff --git a/src/pkg/validate_help/validate.go b/src/pkg/validate_help/validate.go new file mode 100644 index 0000000000000000000000000000000000000000..28605a746958e180a6cb494457cc663eca1a0f26 --- /dev/null +++ b/src/pkg/validate_help/validate.go @@ -0,0 +1,53 @@ +package validate_help + +import ( + "errors" + "fmt" + "github.com/go-playground/validator/v10" + "strings" +) + +var validate = validator.New(validator.WithRequiredStructEnabled()) + +func ConvertErrors(err error) error { + if err == nil { + return nil + } + var validateErrs validator.ValidationErrors + if errors.As(err, &validateErrs) { + s := []string{} + for _, e := range validateErrs { + //fmt.Println("Namespace=", e.Namespace()) + //fmt.Println("Field=", e.Field()) + //fmt.Println(e.StructNamespace()) + //fmt.Println(e.StructField()) + //fmt.Println("Tag=", e.Tag()) + //fmt.Println("ActualTag=", e.ActualTag()) + //fmt.Println("Kind=", e.Kind()) + //fmt.Println("Type=", e.Type()) + //fmt.Println("Value=", e.Value()) + //fmt.Println(e.Param()) + //fmt.Println() + + s = append(s, fmt.Sprintf("%s %s %v", e.Field(), e.Tag(), e.Param())) + break + } + return fmt.Errorf("validate fail: %s", strings.Join(s, ";")) + } + return err +} + +// FastValidateStruct 快速验证struct(使用内置validate和错误转换) +func FastValidateStruct(b interface{}) error { + return ConvertErrors(validate.Struct(b)) +} + +// ValidateEnum 验证struct(使用内置validate和错误转换) +func ValidateEnum[T string | int | int64 | float64](b T, enums ...T) bool { + for _, v := range enums { + if v == b { + return true + } + } + return false +} diff --git a/src/pkg/viewhandler/view.go b/src/pkg/viewhandler/view.go index aaacebcb8ef18112bc8661cfb78b491a10af6cdb..948df34329bb3513a311275be733d633fb82dff2 100644 --- a/src/pkg/viewhandler/view.go +++ b/src/pkg/viewhandler/view.go @@ -30,6 +30,11 @@ type ViewHandlerConfig struct { ParamFunc func(r *http.Request) string //定制化获取view渲染模板名称的方法(不存在则默认方式获取) OptionLayoutFlag string //布局文件前缀标志 + + //加载文件前缀标志 + // 如: fs目录为 view/components/* 下的文件都是只作为template引入的文件 + // 则可以设置 OptionIncludeFlag= view/components/ 来只引入这下面的文件作为解析模板用的文件 + OptionIncludeFlag string } // ViewHandler viewHandler @@ -84,7 +89,7 @@ func (h *ViewHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // GinRouter 推荐的ginRouter配置 -func (h *ViewHandler) GinRouter(r *gin.Engine, prefix string) { +func (h *ViewHandler) GinRouter(r gin.IRouter, prefix string) { prefix = utils.KeepHasPrefix(prefix, "/") r.GET(prefix, h.ViewForGin) @@ -141,18 +146,23 @@ func (h *ViewHandler) templateName(name string) string { func (h *ViewHandler) loadRenderFromFs(embFs embed.FS, funcs ...template.FuncMap) multitemplate.Renderer { r := multitemplate.NewRenderer() templates := [][2]string{} - layouts := []string{} + includes := []string{} layoutPrefix := h.LayoutFilePrefix() + includePrefix := h.IncludeFilePrefix() //扫描分为模板文件和布局文件(l_开头的为布局文件) err := utils.ScanEmbedFsDo(embFs, func(file string, path string) error { + if strings.HasPrefix(path, includePrefix) { + includes = append(includes, path) + return nil + } if strings.HasPrefix(file, layoutPrefix) { - layouts = append(layouts, path) - //logger.Info("content:%s", bt) - } else { - layouts = append(layouts, path) - templates = append(templates, [2]string{file, path}) + includes = append(includes, path) + return nil } + templates = append(templates, [2]string{file, path}) + v1log.Out.Info("load template %s,%s", file, path) + return nil }) common.ErrPanic(err) @@ -160,7 +170,8 @@ func (h *ViewHandler) loadRenderFromFs(embFs embed.FS, funcs ...template.FuncMap h.Error("scan embed err: %s", err) return r } - //h.Info("templates %+v", templates) + h.Info("templates %+v", templates) + h.Info("includes %+v", includes) for _, f := range templates { file := f[0] @@ -170,18 +181,10 @@ func (h *ViewHandler) loadRenderFromFs(embFs embed.FS, funcs ...template.FuncMap for _, v := range funcs { tpl = tpl.Funcs(v) } - tmpl := template.Must(tpl.ParseFS(embFs, append(layouts, path)...)) + //需要把当前文件和引入的文件共同解析 + tmpl := template.Must(tpl.ParseFS(embFs, append(includes, path)...)) r.Add(file, tmpl) - - //debug - //if file == "index.html" { - // tmpl.ExecuteTemplate(os.Stdout, file, map[string]string{ - // "action": "xxx", - // }) - //} - - //h.Info("%s", path) - //h.Info("templateAdd %s,%+v,%s", file, layouts, path) + v1log.Out.Info("AddTemplate %s", file) } return r @@ -191,18 +194,22 @@ func (h *ViewHandler) loadRenderFromFs(embFs embed.FS, funcs ...template.FuncMap func (h *ViewHandler) loadRenderFromDir(dir string, funcs ...template.FuncMap) multitemplate.Renderer { r := multitemplate.NewRenderer() templates := [][2]string{} - layouts := []string{} + includes := []string{} layoutPrefix := h.LayoutFilePrefix() + includePrefix := h.IncludeFilePrefix() //扫描分为模板文件和布局文件(l_开头的为布局文件) err := utils.ScanDirFileDo(dir, func(file string, path string) error { + if strings.HasPrefix(path, includePrefix) { + includes = append(includes, path) + return nil + } if strings.HasPrefix(file, layoutPrefix) { - layouts = append(layouts, path) - //logger.Info("content:%s", bt) - } else { - layouts = append(layouts, path) - templates = append(templates, [2]string{file, path}) + includes = append(includes, path) + return nil } + templates = append(templates, [2]string{file, path}) + v1log.Out.Info("load template %s,%s", file, path) return nil }) @@ -221,18 +228,10 @@ func (h *ViewHandler) loadRenderFromDir(dir string, funcs ...template.FuncMap) m for _, v := range funcs { tpl = tpl.Funcs(v) } - tmpl := template.Must(tpl.ParseFiles(append(layouts, path)...)) + //需要把当前文件和引入的文件共同解析 + tmpl := template.Must(tpl.ParseFiles(append(includes, path)...)) r.Add(file, tmpl) - - //debug - //if file == "index.html" { - // tmpl.ExecuteTemplate(os.Stdout, file, map[string]string{ - // "action": "xxx", - // }) - //} - - //h.Info("%s", path) - //h.Info("templateAdd %s,%+v,%s", file, layouts, path) + v1log.Out.Info("AddTemplate %s", file) } return r @@ -246,6 +245,14 @@ func (h *ViewHandler) LayoutFilePrefix() string { return "l_" } +// IncludeFilePrefix 加载文件前缀 +func (h *ViewHandler) IncludeFilePrefix() string { + if len(h.OptionIncludeFlag) > 0 { + return h.OptionIncludeFlag + } + return "" +} + // loadTemplates 直接使用目录 func (h *ViewHandler) loadTemplates(templatesDir string) multitemplate.Renderer { r := multitemplate.NewRenderer() diff --git a/src/pkg/workflow/dag.go b/src/pkg/workflow/dag.go new file mode 100644 index 0000000000000000000000000000000000000000..89c4a80f01ccf59c570b28056365806976efd9d1 --- /dev/null +++ b/src/pkg/workflow/dag.go @@ -0,0 +1,101 @@ +package workflow + +import ( + "fmt" + "gitee.com/captials-team/ubdframe/src/common/utils" +) + +// DAG 有序无向图 +// 提供方法:添加顶点,添加边,获取有向图 +type DAG struct { + nodes map[string]interface{} //存储所有节点 + edges map[string][]string //存储所有边,key=当前节点,value=当前节点相邻的节点数组 +} + +// AddVertex 添加顶点 +func (dag *DAG) AddVertex(id string, node interface{}) error { + dag.nodes[id] = node + return nil +} + +// AddEdge 添加边 +func (dag *DAG) AddEdge(from string, to string) error { + edges := utils.CopyMap(dag.edges) + if _, exist := edges[from]; !exist { + edges[from] = []string{} + } + edges[from] = append(edges[from], to) + + //检测环 + if dag.checkLoop(from, edges, nil) { + return fmt.Errorf("has circle loop") + } + //通过检测的才可加入边 + dag.edges = edges + return nil +} + +// checkLoop 检测是否存在环,true:存在环,false:不存在 +func (dag *DAG) checkLoop(start string, edges map[string][]string, has map[string]bool) bool { + if edges == nil { + return false + } + edge, exist := edges[start] + if !exist { + return false + } + if has == nil { + has = make(map[string]bool) + } + for _, v := range edge { + if _, exs := has[v]; exs { + return true + } + + newHas := utils.CopyMap(has) + newHas[start] = true + if dag.checkLoop(v, edges, newHas) { + return true + } + } + return false +} + +// TopologicalSort 有序拓扑图 +func (dag *DAG) TopologicalSort() [][]string { + nodes := utils.CopyMap(dag.nodes) + var topo [][]string + + for len(nodes) > 0 { + has := make(map[string]bool) + //查找目前剩余节点的所有边, + for node, _ := range nodes { + edge, exist := dag.edges[node] + if !exist || edge == nil { + continue + } + //将节点所有边的相邻节点记录下 + for _, v := range edge { + has[v] = true + } + } + + var deal []string + //若节点不在当前相邻节点中的则先加入 + for k, _ := range nodes { + if _, exist := has[k]; !exist { + deal = append(deal, k) + delete(nodes, k) + } + } + topo = append(topo, deal) + } + return topo +} + +func NewDAG() *DAG { + return &DAG{ + nodes: make(map[string]interface{}), + edges: make(map[string][]string), + } +} diff --git a/src/pkg/workflow/dag_test.go b/src/pkg/workflow/dag_test.go new file mode 100644 index 0000000000000000000000000000000000000000..97d76b2d96ca8639a4e4966b014c26805da5d522 --- /dev/null +++ b/src/pkg/workflow/dag_test.go @@ -0,0 +1,80 @@ +package workflow + +import ( + "gitee.com/captials-team/ubdframe/src/common" + "github.com/stretchr/testify/assert" + "strings" + "testing" +) + +// TestDAG_TopologicalSort 有序无环图(无环情况) +func TestDAG_TopologicalSort(t *testing.T) { + tests := [][]string{ + {"1-2", "3"}, + {"1-4", "2-3", "3-4"}, + {"1-2", "2-3", "3-4", "5-6", "6-7", "7-8"}, + } + + var empty struct{} + for index, list := range tests { + t.Logf("========== %d", index) + dag := NewDAG() + for _, v := range list { + arr := strings.Split(v, "-") + if len(arr) == 1 { + common.ErrPanic(dag.AddVertex(arr[0], empty)) + t.Logf("Add %s", v) + } + if len(arr) == 2 { + common.ErrPanic(dag.AddVertex(arr[0], empty)) + common.ErrPanic(dag.AddVertex(arr[1], empty)) + common.ErrPanic(dag.AddEdge(arr[0], arr[1])) + t.Logf("AddEdge %s", v) + } + } + + ret := dag.TopologicalSort() + for i, v := range ret { + t.Logf("[%d]%s", i, strings.Join(v, ",")) + } + } +} + +// TestDAG_TopologicalSort_circle 有序无环图(有环情况) +func TestDAG_TopologicalSort_circle(t *testing.T) { + tests := [][]string{ + {"1-2", "2-3", "3-4", "5-6", "6-7", "7-8", "3-5", "7-1"}, //有环 + {"1-2", "2-3", "3-4", "5-6", "6-7", "7-8", "3-5", "7-2"}, //有环 + {"1-1", "2-3"}, //有环 + {"1-2", "2-3", "3-1"}, //有环 + {"1-2", "2-3", "3-2"}, //有环 + } + + var empty struct{} + for index, list := range tests { + t.Logf("========== %d", index) + dag := NewDAG() + var errCount int + for _, v := range list { + arr := strings.Split(v, "-") + if len(arr) == 1 { + common.ErrPanic(dag.AddVertex(arr[0], empty)) + t.Logf("Add %s", v) + } + if len(arr) == 2 { + common.ErrPanic(dag.AddVertex(arr[0], empty)) + common.ErrPanic(dag.AddVertex(arr[1], empty)) + + err := dag.AddEdge(arr[0], arr[1]) + t.Logf("AddEdge %s", v) + + if err != nil { + errCount++ + } + } + } + + assert.Greater(t, errCount, 0) + t.Logf("CIRCLE LOOP") + } +} diff --git a/src/pkg/workflow/sts.go b/src/pkg/workflow/sts.go new file mode 100644 index 0000000000000000000000000000000000000000..6cc11f1c937c76edca500ecc50a3db00bf70510d --- /dev/null +++ b/src/pkg/workflow/sts.go @@ -0,0 +1,30 @@ +package workflow + +import "sync" + +// State 工作流状态类型 +type State string + +const ( + StatePending State = "pending" + StateRunning State = "running" + StateCompleted State = "completed" + StateFailed State = "failed" +) + +// Node 工作流节点定义 +type Node struct { + ID string `json:"ID"` // 节点唯一标识 + Action func(ctx Context) error `json:"-"` // 执行函数 + RetryPolicy int `json:"RetryPolicy"` // 重试次数 + DependsOn []string `json:"DependsOn"` // 依赖的节点ID +} + +// Context 工作流上下文 +type Context struct { + sync.Locker //锁 + + Data map[string]interface{} `json:"data"` // 共享数据 + NodeID string `json:"nodeID"` // 当前节点ID + Workflow *Workflow `json:"workflow"` // 所属工作流 +} diff --git a/src/pkg/workflow/workflow.go b/src/pkg/workflow/workflow.go new file mode 100644 index 0000000000000000000000000000000000000000..c480771bf1752d5fe6b9368e4927559a1e64c7de --- /dev/null +++ b/src/pkg/workflow/workflow.go @@ -0,0 +1,192 @@ +package workflow + +import ( + "encoding/json" + "fmt" + "gitee.com/captials-team/ubdframe/src/pkg/logs" + "github.com/Jeffail/tunny" + "gorm.io/gorm" + "gorm.io/gorm/schema" + "math" + "runtime" + "sync" + "time" +) + +// Workflow 工作流定义 +type Workflow struct { + ID string `json:"id"` //工作流唯一ID + Nodes map[string]Node //节点集合 + State State `json:"state"` //当前工作流状态 + + Success map[string]bool `json:"success"` + context Context +} + +// Run 执行工作流(并发安全) +func (w *Workflow) Run() error { + //重置 + w.State = StateRunning + w.context.Workflow = w + w.context.Locker = &sync.Mutex{} + if w.context.Data == nil { + w.context.Data = make(map[string]interface{}) + } + if w.Success == nil { + w.Success = make(map[string]bool) + } + for k, node := range w.Nodes { + node.ID = k + w.Nodes[k] = node + } + + // 构建DAG依赖关系 + dag := w.buildDAG() + + // 使用协程池控制并发 + pool := tunny.NewFunc(runtime.NumCPU(), func(payload interface{}) interface{} { + nodeID := payload.(string) + return w.executeNode(nodeID) + }) + defer pool.Close() + + // 拓扑排序后顺序执行 + for _, nodeIDs := range dag.TopologicalSort() { + var wg sync.WaitGroup + for _, nodeID := range nodeIDs { + wg.Add(1) + go func(id string) { + defer wg.Done() + pool.Process(id) + }(nodeID) + } + wg.Wait() + + // 检查是否有节点失败 + if w.State == StateFailed { + return fmt.Errorf("workflow aborted %+v", w.Success) + } + } + + w.State = StateCompleted + return nil +} + +// buildDAG 构建DAG图 +func (w *Workflow) buildDAG() *DAG { + d := NewDAG() + for id, node := range w.Nodes { + _ = d.AddVertex(id, node) + for _, depID := range node.DependsOn { + _ = d.AddEdge(depID, id) + } + } + return d +} + +// 执行单个节点 +func (w *Workflow) executeNode(nodeID string) error { + node := w.Nodes[nodeID] + var err error + for i := 0; i <= node.RetryPolicy; i++ { + err = node.Action(Context{ + Data: w.context.Data, + NodeID: node.ID, + Workflow: w, + Locker: w.context.Locker, + }) + if err == nil { + w.context.Lock() + w.Success[nodeID] = true + w.context.Unlock() + return nil + } + time.Sleep(time.Millisecond * 100 * time.Duration(math.Pow(2, float64(i)))) // 指数退避 + } + + w.State = StateFailed + return fmt.Errorf("node %s failed: %v", nodeID, err) +} + +// Resume 从失败节点恢复 +func (w *Workflow) Resume() error { + if w.State != StateFailed { + return nil + } + + // 找出未完成的节点 + pendingNodes := w.getPendingNodes() + + //logs.Out.Info("Pending= %+v", pendingNodes) + // 创建子工作流继续执行 + subflow := &Workflow{ + ID: w.ID + "_recovery", + Nodes: pendingNodes, + Success: w.Success, + context: w.context, + } + return subflow.Run() +} + +func (w *Workflow) getPendingNodes() map[string]Node { + pending := map[string]Node{} + for _, v := range w.Nodes { + if result, exist := w.Success[v.ID]; exist && result { + continue + } + + var newDepends []string + for _, vv := range v.DependsOn { + if result, exist := w.Success[vv]; exist && result { + continue + } + newDepends = append(newDepends, vv) + } + var newNode = v + newNode.DependsOn = newDepends + pending[v.ID] = newNode + + logs.Out.Info("AddPending= %+v", newNode) + } + return pending +} + +type saveModel struct { + Id int64 `json:"id" gorm:"primaryKey"` + CreatedAt *time.Time `json:"created_at,omitempty" gorm:"default:current_timestamp(3);<-:false"` + Workflow string `json:"workflow" gorm:"type:varchar(64);index"` + Data string `json:"data,omitempty" gorm:"type:varchar(512)"` //流数据 +} + +func (ad *saveModel) TableName(namer schema.Namer) string { + return namer.TableName("workflows") +} + +// SaveWorkflow 保存工作流状态到数据库(gorm版本,如需自行保存可做参考) +func SaveWorkflow(db *gorm.DB, w *Workflow) error { + data, err := json.Marshal(w) + if err != nil { + return err + } + query := db.Model(new(saveModel)) + + ret := query.Create(&saveModel{ + Workflow: w.ID, + Data: string(data), + }) + + return ret.Error +} + +// LoadWorkflow 从数据库恢复工作流(gorm版本,如需自行保存可做参考) +func LoadWorkflow(db *gorm.DB, id string) (*Workflow, error) { + query := db.Model(new(saveModel)) + + m := new(saveModel) + ret := query.Order("id DESC").Where("workflow", id).First(m) + if ret.Error != nil { + return nil, ret.Error + } + var w Workflow + return &w, json.Unmarshal([]byte(m.Data), &w) +} diff --git a/src/pkg/workflow/workflow_test.go b/src/pkg/workflow/workflow_test.go new file mode 100644 index 0000000000000000000000000000000000000000..049d4dde1722aeab7d03d38000cade9185786039 --- /dev/null +++ b/src/pkg/workflow/workflow_test.go @@ -0,0 +1,159 @@ +package workflow + +import ( + "encoding/json" + "fmt" + "gitee.com/captials-team/ubdframe/src/common" + "gitee.com/captials-team/ubdframe/src/common/utils" + "strings" + "testing" +) + +func TestWorkflow_Run(t *testing.T) { + w := testWorkflow(t, false) + + s, _ := json.MarshalIndent(w, "", "\t") + t.Logf("Workflow= %s", string(s)) + + common.ErrPanic(w.Run()) +} + +// TestWorkflow_concurrence 测试并发 +func TestWorkflow_concurrence(t *testing.T) { + for i := 1; i <= 100000; i++ { + t.Logf("%s %d", strings.Repeat("=", 30), i) + TestWorkflow_Run(t) + } +} + +func TestWorkflow_context(t *testing.T) { + ctx := Context{Data: map[string]interface{}{}} + + c1 := Context{Data: ctx.Data} + c2 := Context{Data: ctx.Data} + + c1.Data["xxx"] = 123 + + t.Logf("%+v", c2.Data) +} + +// TestWorkflow_Persistence 持久化 +func TestWorkflow_Persistence(t *testing.T) { + w := testWorkflow(t, false) + + s, err := json.MarshalIndent(w, "", "\t") + common.ErrPanic(err) + t.Logf("Workflow= %s", string(s)) + + common.ErrPanic(w.Run()) + + s1, err1 := json.MarshalIndent(w, "", "\t") + common.ErrPanic(err1) + t.Logf("Workflow= %s", string(s1)) +} + +// TestWorkflow_Resume 重新运行服务 +func TestWorkflow_Resume(t *testing.T) { + w := testWorkflow(t, true) + + err := w.Run() + t.Logf("RunFail %s", err) + if err != nil { + for i := 1; i <= 10; i++ { + t.Logf("Resume=> %d", i) + if err1 := w.Resume(); err1 != nil { + t.Logf("ResumeFail %s", err1) + continue + } + break + } + } + +} + +func testWorkflow(t *testing.T, needFail bool) *Workflow { + retry := 1 + + return &Workflow{ + ID: "order_process", + Nodes: map[string]Node{ + "order_create": { + Action: func(ctx Context) error { + orderId := utils.RandLetterFigureCode(10) + userId := utils.RandLetterFigureCode(10) + + //随机失败 + if needFail && utils.TrueScopeRand(1, 100) > 20 { + return fmt.Errorf("create order randome fail") + } + + ctx.Lock() + ctx.Data["orderId"] = orderId + ctx.Data["userId"] = userId + ctx.Unlock() + + t.Logf("CreateOrder= %s,User= %s", orderId, userId) + return nil + }, + RetryPolicy: retry, + DependsOn: nil, + }, + "order_pay": { + Action: func(ctx Context) error { + payId := utils.RandLetterFigureCode(10) + + //随机失败 + if needFail && utils.TrueScopeRand(1, 100) > 20 { + return fmt.Errorf("pay order randome fail") + } + + ctx.Lock() + ctx.Data["payId"] = payId + ctx.Unlock() + t.Logf("PayOrder= %s", payId) + return nil + }, + RetryPolicy: retry, + DependsOn: []string{"order_create"}, + }, + "notify_user": { + Action: func(ctx Context) error { + + //随机失败 + if needFail && utils.TrueScopeRand(1, 100) > 20 { + return fmt.Errorf("notify randome fail") + } + + ctx.Lock() + userId := ctx.Data["userId"] + ctx.Unlock() + + t.Logf("NotifyUser= %s", userId) + return nil + }, + RetryPolicy: retry, + DependsOn: []string{"order_create", "order_pay"}, + }, + "order_complete": { + Action: func(ctx Context) error { + + //随机失败 + if needFail && utils.TrueScopeRand(1, 100) > 20 { + return fmt.Errorf("complete order randome fail") + } + + ctx.Lock() + orderId := ctx.Data["orderId"] + payId := ctx.Data["payId"] + ctx.Unlock() + + t.Logf("CompleteOrder= %s,%s", orderId, payId) + return nil + }, + RetryPolicy: retry, + DependsOn: []string{"order_pay"}, + }, + }, + } + +} diff --git a/src/tests/source.go b/src/tests/source.go index 84b9e5044be5340581b5792e9e1629da7cf47070..f0711155fbccbc86433e1af74d22fd09ad464af8 100644 --- a/src/tests/source.go +++ b/src/tests/source.go @@ -17,6 +17,10 @@ var TestingDBConfig = configstc.DBConfig{ TablePrefix: "test_", } +func GetTestingDBConfig() configstc.DBConfig { + return TestingDBConfig +} + var TestingApiServer = configstc.ServerConfig{ Enable: true, ServerBindAddr: "",