Compare commits

...

64 Commits

Author SHA1 Message Date
刘祥超
9f9787e30f 版本号更改为1.2.6 2023-07-28 09:27:08 +08:00
刘祥超
529016d4d5 版本号更改为1.2.5 2023-07-26 15:30:37 +08:00
刘祥超
63942bfb08 将版本号修改为1.2.4 2023-07-26 10:19:02 +08:00
刘祥超
f4e4f32f9c 修复SysLocker无法写入新Key的问题 2023-07-26 10:18:52 +08:00
刘祥超
0a3c740502 版本号修改为1.2.3 2023-07-25 13:17:59 +08:00
刘祥超
9a3438e066 优化IP名单使用IP搜索查询速度 2023-07-25 12:26:12 +08:00
刘祥超
814b82e1b6 优化TOA相关代码 2023-07-24 15:33:44 +08:00
刘祥超
89cfd175cd 优化TOA相关API 2023-07-24 09:56:43 +08:00
刘祥超
860816719e 单个节点所在多个集群共用一个缓存策略时只加载其中一个 2023-07-20 16:54:34 +08:00
刘祥超
caa936f0ac 大幅提升SysLocker自增性能 2023-07-20 14:25:42 +08:00
刘祥超
97836a89eb 优化代码 2023-07-19 18:49:23 +08:00
刘祥超
84483dce61 版本号更改为1.2.2 2023-07-18 14:33:53 +08:00
刘祥超
a4eb7a47f3 更新SQL 2023-07-16 19:12:10 +08:00
刘祥超
20c84d7fe5 手动同步集群任务后把所有相关任务标记为已完成 2023-07-14 10:04:44 +08:00
刘祥超
9d5acd2b36 优化代码 2023-07-12 17:10:33 +08:00
刘祥超
7508f6b92b 增加页面优化相关API 2023-07-11 19:46:00 +08:00
刘祥超
379030fe71 版本号改为1.2.1 2023-07-09 17:38:09 +08:00
刘祥超
10027eea20 缓存策略移除“容纳Key数量”选项 2023-07-08 18:50:58 +08:00
刘祥超
69f25a176b 提交SQL 2023-07-07 18:52:37 +08:00
刘祥超
ac19f06b6c 网站列表增加QPS和攻击QPS信息 2023-07-07 18:51:36 +08:00
刘祥超
87a81f59c7 修复查询网站日流量统计时可能不兼容MySQL8的问题 2023-07-07 17:35:23 +08:00
刘祥超
7389e5e54b 远程安装时可以覆盖运行中的文件 2023-07-07 15:59:51 +08:00
刘祥超
e6792b8188 优化自定义页面设置,页面URL不再支持填写本地文件 2023-07-07 11:48:48 +08:00
刘祥超
a037546cfa 优化代码 2023-07-07 09:52:53 +08:00
刘祥超
8efaacf1ef 国家/地区、省份等相关表增加真实ID字段,防止数据表被用户修改时无法对应 2023-07-07 09:52:46 +08:00
刘祥超
a38dd1cef8 “集群设置 -- 网站设置”增加“允许记录访问日志”选项 2023-07-05 15:29:11 +08:00
刘祥超
77521112d0 试用 executils.LookPath()代替 exec.LookPath() 2023-07-05 11:34:52 +08:00
刘祥超
4f9a5d238c 优化本地mysql服务自动启动逻辑 2023-07-05 11:14:51 +08:00
刘祥超
d5fb39ed50 更新TeaGo库 2023-07-05 09:25:27 +08:00
刘祥超
58a84083ae 优化自增锁性能 2023-07-04 22:02:17 +08:00
刘祥超
9f564a4739 重写规则API支持用户操作 2023-07-04 18:31:12 +08:00
刘祥超
c20accbf58 减少在自增锁中生成的sql statements 2023-07-04 14:42:14 +08:00
刘祥超
3f21b3148e 优化代码 2023-07-03 17:12:24 +08:00
刘祥超
74e909a501 增加清空节点同步任务、清空DNS同步任务API 2023-07-02 17:29:19 +08:00
刘祥超
4150ee1b47 优化自增锁算法 2023-07-02 15:27:49 +08:00
刘祥超
df04de2151 修复测试用例 2023-07-02 15:25:13 +08:00
刘祥超
4dc5d9aa7e 修复自动生成的用户没有绑定集群、用户名不规范的问题 2023-07-02 14:30:46 +08:00
刘祥超
0ef7e6ccd8 增加部分数据清理周期设置 2023-07-01 17:54:40 +08:00
刘祥超
ed2b831e5a 查找当前API节点版本中增加角色 2023-07-01 15:09:54 +08:00
刘祥超
5d392ecd43 优化代码 2023-06-30 19:06:55 +08:00
刘祥超
ea147d7506 优化代码 2023-06-30 19:01:47 +08:00
刘祥超
b45136c2c8 优化代码 2023-06-30 18:54:45 +08:00
刘祥超
530e1513ec 日志API增加多语言代号参数 2023-06-30 18:10:11 +08:00
刘祥超
6c60677b72 添加多语言最基础代码 2023-06-28 09:11:20 +08:00
刘祥超
a1bec5e578 创建Web配置时自动设置访客IP获取方式为“直接获取” 2023-06-23 17:05:52 +08:00
刘祥超
9dece058d9 优化查询所有集群性能 2023-06-23 16:23:21 +08:00
刘祥超
89df6ae6bf 优化集群列表性能 2023-06-23 16:15:22 +08:00
刘祥超
85b6e6428c 源站支持HTTP/2 2023-06-23 11:44:02 +08:00
刘祥超
0df204a1df 初始化时修改默认生成的用户名,并将用户自动关联到默认集群 2023-06-21 11:51:07 +08:00
刘祥超
ecef94b700 增加简化版的创建TCP网站API 2023-06-18 17:14:24 +08:00
刘祥超
a493bbb280 增加简化版的创建HTTP网站API 2023-06-18 16:20:00 +08:00
刘祥超
eee902abec 优化错误提示 2023-06-16 08:17:00 +08:00
刘祥超
2aceb4fb4d 版本号改为1.2.0 2023-06-12 14:42:26 +08:00
刘祥超
c1bbcc8dab 已停用的节点不计算在离线节点里 2023-06-12 14:10:18 +08:00
刘祥超
262f8a5594 已经停用的节点不提示需要升级 2023-06-12 14:04:50 +08:00
刘祥超
a85b49a377 智能DNS实现DoH功能 2023-06-11 17:57:31 +08:00
刘祥超
75e353db0e 初步实现对象存储源站 2023-06-07 17:25:20 +08:00
刘祥超
ccbb14836e 修复因serverId传入0而可能删除WAF策略的问题 2023-06-06 15:03:18 +08:00
刘祥超
7fbc61aa21 改进DNS域名解析相关函数 2023-06-05 12:36:29 +08:00
刘祥超
8b804cb500 修复一个测试用例 2023-06-04 09:38:13 +08:00
刘祥超
3ddb95731a Update sql.json 2023-06-03 09:08:44 +08:00
刘祥超
beeb46ab7f 修复节点IP为IPv6时无法健康检查的问题 2023-06-02 14:46:38 +08:00
刘祥超
a65255e4e5 优化代码 2023-06-01 18:08:45 +08:00
刘祥超
b7768ea0c0 初步实现HTTP3 2023-06-01 17:46:10 +08:00
118 changed files with 46838 additions and 6482 deletions

View File

@@ -12,5 +12,5 @@ dbs:
fields:
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified" ]
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified", "http2Enabled", "http3Enabled" ]

View File

@@ -52,7 +52,7 @@ func main() {
return
}
unzip := helpers.NewUnzip(zipPath, targetPath)
var unzip = helpers.NewUnzip(zipPath, targetPath)
err := unzip.Run()
if err != nil {
stderr("ERROR: " + err.Error())

13
go.mod
View File

@@ -10,25 +10,26 @@ require (
github.com/andybalholm/brotli v1.0.4
github.com/cespare/xxhash v1.1.0
github.com/cespare/xxhash/v2 v2.1.1
github.com/go-acme/lego/v4 v4.9.0
github.com/fsnotify/fsnotify v1.6.0
github.com/go-acme/lego/v4 v4.10.2
github.com/go-sql-driver/mysql v1.7.0
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
github.com/iwind/TeaGo v0.0.0-20230304012706-c1f4a4e27470
github.com/iwind/TeaGo v0.0.0-20230704135818-4a5646ab1f5b
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62
github.com/miekg/dns v1.1.50
github.com/mozillazg/go-pinyin v0.18.0
github.com/pkg/sftp v1.12.0
github.com/shirou/gopsutil/v3 v3.22.2
github.com/smartwalle/alipay/v3 v3.1.7
golang.org/x/crypto v0.1.0
golang.org/x/crypto v0.5.0
golang.org/x/net v0.8.0
golang.org/x/sys v0.6.0
golang.org/x/sys v0.8.0
google.golang.org/grpc v1.45.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
@@ -40,6 +41,8 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/smartwalle/crypto4go v1.0.2 // indirect
github.com/tdewolff/minify/v2 v2.12.7 // indirect
github.com/tdewolff/parse/v2 v2.6.6 // indirect
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect

32
go.sum
View File

@@ -12,13 +12,14 @@ github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -30,6 +31,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200624174652-8d2f3be8b2d9/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -38,6 +41,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
@@ -79,8 +84,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20230304012706-c1f4a4e27470 h1:TuRxvKRv9PxKVijWOkUnZm5TeanQqWGUJyPx9u6cra4=
github.com/iwind/TeaGo v0.0.0-20230304012706-c1f4a4e27470/go.mod h1:fi/Pq+/5m2HZoseM+39dMF57ANXRt6w4PkGu3NXPc5s=
github.com/iwind/TeaGo v0.0.0-20230704135818-4a5646ab1f5b h1:yYUaxnc04uzfr7C9HBN52ZZvcQomND+C5aZTpjOUYFI=
github.com/iwind/TeaGo v0.0.0-20230704135818-4a5646ab1f5b/go.mod h1:fi/Pq+/5m2HZoseM+39dMF57ANXRt6w4PkGu3NXPc5s=
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62 h1:HJH6RDheAY156DnIfJSD/bEvqyXzsZuE2gzs8PuUjoo=
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -96,10 +101,11 @@ github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -140,12 +146,20 @@ github.com/smartwalle/crypto4go v1.0.2 h1:9DUEOOsPhmp00438L4oBdcL8EZG1zumecft5bW
github.com/smartwalle/crypto4go v1.0.2/go.mod h1:LQ7vCZIb7BE5+MuMtJBuO8ORkkQ01m4DXDBWPzLbkMY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/tdewolff/minify/v2 v2.12.7 h1:pBzz2tAfz5VghOXiQIsSta6srhmTeinQPjRDHWoumCA=
github.com/tdewolff/minify/v2 v2.12.7/go.mod h1:ZRKTheiOGyLSK8hOZWWv+YoJAECzDivNgAlVYDHp/Ws=
github.com/tdewolff/parse/v2 v2.6.6 h1:Yld+0CrKUJaCV78DL1G2nk3C9lKrxyRTux5aaK/AkDo=
github.com/tdewolff/parse/v2 v2.6.6/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0=
github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
@@ -162,8 +176,8 @@ golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
@@ -222,8 +236,10 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -1,7 +1,7 @@
package teaconst
const (
Version = "1.1.0"
Version = "1.2.6"
ProductName = "Edge API"
ProcessName = "edge-api"
@@ -18,7 +18,7 @@ const (
// 其他节点版本号,用来检测是否有需要升级的节点
NodeVersion = "1.1.0"
NodeVersion = "1.2.6"
// SQLVersion SQL版本号
SQLVersion = "11"

View File

@@ -2,6 +2,22 @@ package models
import "github.com/iwind/TeaGo/dbs"
const (
AdminField_Id dbs.FieldName = "id" // ID
AdminField_IsOn dbs.FieldName = "isOn" // 是否启用
AdminField_Username dbs.FieldName = "username" // 用户名
AdminField_Password dbs.FieldName = "password" // 密码
AdminField_Fullname dbs.FieldName = "fullname" // 全名
AdminField_IsSuper dbs.FieldName = "isSuper" // 是否为超级管理员
AdminField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
AdminField_UpdatedAt dbs.FieldName = "updatedAt" // 修改时间
AdminField_State dbs.FieldName = "state" // 状态
AdminField_Modules dbs.FieldName = "modules" // 允许的模块
AdminField_CanLogin dbs.FieldName = "canLogin" // 是否可以登录
AdminField_Theme dbs.FieldName = "theme" // 模板设置
AdminField_Lang dbs.FieldName = "lang" // 语言代号
)
// Admin 管理员
type Admin struct {
Id uint32 `field:"id"` // ID
@@ -16,6 +32,7 @@ type Admin struct {
Modules dbs.JSON `field:"modules"` // 允许的模块
CanLogin bool `field:"canLogin"` // 是否可以登录
Theme string `field:"theme"` // 模板设置
Lang string `field:"lang"` // 语言代号
}
type AdminOperator struct {
@@ -31,6 +48,7 @@ type AdminOperator struct {
Modules any // 允许的模块
CanLogin any // 是否可以登录
Theme any // 模板设置
Lang any // 语言代号
}
func NewAdminOperator() *AdminOperator {

View File

@@ -335,6 +335,7 @@ func (this *APINodeDAO) UpdateAPINodeStatus(tx *dbs.Tx, apiNodeId int64, statusJ
func (this *APINodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
return this.Query(tx).
State(APINodeStateEnabled).
Attr("isOn", true).
Where("status IS NOT NULL").
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
Param("version", utils.VersionToLong(version)).

View File

@@ -210,6 +210,7 @@ func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeSta
func (this *AuthorityNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
return this.Query(tx).
State(AuthorityNodeStateEnabled).
Attr("isOn", true).
Where("status IS NOT NULL").
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
Param("version", utils.VersionToLong(version)).

View File

@@ -155,6 +155,12 @@ func (this *DNSTaskDAO) DeleteDNSTask(tx *dbs.Tx, taskId int64) error {
return err
}
// DeleteAllDNSTasks 删除所有任务
func (this *DNSTaskDAO) DeleteAllDNSTasks(tx *dbs.Tx) error {
return this.Query(tx).
DeleteQuickly()
}
// UpdateDNSTaskError 设置任务错误
func (this *DNSTaskDAO) UpdateDNSTaskError(tx *dbs.Tx, taskId int64, err string) error {
if taskId <= 0 {
@@ -195,6 +201,27 @@ func (this *DNSTaskDAO) UpdateDNSTaskDone(tx *dbs.Tx, taskId int64, taskVersion
return this.Save(tx, op)
}
// GenerateVersion 生成最新的版本号
func (this *DNSTaskDAO) GenerateVersion() int64 {
return time.Now().UnixNano()
}
// UpdateClusterDNSTasksDone 设置所有集群任务完成
func (this *DNSTaskDAO) UpdateClusterDNSTasksDone(tx *dbs.Tx, clusterId int64, maxVersion int64) error {
if clusterId <= 0 || maxVersion <= 0 {
return nil
}
return this.Query(tx).
Attr("clusterId", clusterId).
Attr("isOk", false).
Lte("version", maxVersion).
Set("isDone", true).
Set("isOk", true).
Set("error", "").
UpdateQuickly()
}
// DeleteDNSTasksWithClusterId 删除集群相关任务
func (this *DNSTaskDAO) DeleteDNSTasksWithClusterId(tx *dbs.Tx, clusterId int64) error {
if clusterId <= 0 {

View File

@@ -1,17 +1,28 @@
package dns
package dns_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/dbs"
"testing"
"time"
)
func TestDNSTaskDAO_CreateDNSTask(t *testing.T) {
dbs.NotifyReady()
err := SharedDNSTaskDAO.CreateDNSTask(nil, 1, 2, 3, 0, "cdn", "taskType")
err := dns.SharedDNSTaskDAO.CreateDNSTask(nil, 1, 2, 3, 0, "cdn", "taskType")
if err != nil {
t.Fatal(err)
}
t.Log("ok")
}
func TestDNSTaskDAO_UpdateClusterDNSTasksDone(t *testing.T) {
var dao = dns.NewDNSTaskDAO()
var tx *dbs.Tx
err := dao.UpdateClusterDNSTasksDone(tx, 46, time.Now().UnixNano())
if err != nil {
t.Fatal(err)
}
}

View File

@@ -96,7 +96,7 @@ func (this *HTTPCachePolicyDAO) FindAllEnabledCachePolicies(tx *dbs.Tx) (result
}
// CreateCachePolicy 创建缓存策略
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) (int64, error) {
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) (int64, error) {
var op = NewHTTPCachePolicyOperator()
op.State = HTTPCachePolicyStateEnabled
op.IsOn = isOn
@@ -105,7 +105,6 @@ func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name st
if len(capacityJSON) > 0 {
op.Capacity = capacityJSON
}
op.MaxKeys = maxKeys
if len(maxSizeJSON) > 0 {
op.MaxSize = maxSizeJSON
}
@@ -184,7 +183,7 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
return 0, err
}
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
if err != nil {
return 0, err
}
@@ -192,7 +191,7 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
}
// UpdateCachePolicy 修改缓存策略
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) error {
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) error {
if policyId <= 0 {
return errors.New("invalid policyId")
}
@@ -205,7 +204,6 @@ func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, is
if len(capacityJSON) > 0 {
op.Capacity = capacityJSON
}
op.MaxKeys = maxKeys
if len(maxSizeJSON) > 0 {
op.MaxSize = maxSizeJSON
}
@@ -256,8 +254,6 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
config.Capacity = capacityConfig
}
config.MaxKeys = types.Int64(policy.MaxKeys)
// max size
if IsNotNull(policy.MaxSize) {
maxSizeConfig := &shared.SizeCapacity{}

View File

@@ -33,7 +33,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedHTTPCacheTaskDAO.Clean(nil, 30) // 只保留N天
err := SharedHTTPCacheTaskDAO.CleanDefaultDays(nil, 30) // 只保留N天
if err != nil {
remotelogs.Error("HTTPCacheTaskDAO", "clean expired data failed: "+err.Error())
}
@@ -228,8 +228,8 @@ func (this *HTTPCacheTaskDAO) CheckUserTask(tx *dbs.Tx, userId int64, taskId int
return nil
}
// Clean 清理以往的任务
func (this *HTTPCacheTaskDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理N天以前的任务
func (this *HTTPCacheTaskDAO) CleanDays(tx *dbs.Tx, days int) error {
if days <= 0 {
days = 30
}
@@ -248,6 +248,23 @@ func (this *HTTPCacheTaskDAO) Clean(tx *dbs.Tx, days int) error {
return err
}
// CleanDefaultDays 清除任务
func (this *HTTPCacheTaskDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.HTTPCacheTask.Clean.Days > 0 {
defaultDays = databaseConfig.HTTPCacheTask.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 30
}
return this.CleanDays(tx, defaultDays)
}
// NotifyChange 发送通知
func (this *HTTPCacheTaskDAO) NotifyChange(tx *dbs.Tx, taskId int64) error {
// TODO

View File

@@ -11,7 +11,7 @@ import (
func TestHTTPCacheTaskDAO_Clean(t *testing.T) {
dbs.NotifyReady()
err := models.SharedHTTPCacheTaskDAO.Clean(nil, 30)
err := models.SharedHTTPCacheTaskDAO.CleanDays(nil, 30)
if err != nil {
t.Fatal(err)
}

View File

@@ -132,7 +132,7 @@ func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64
op.Outbound = outboundJSON
}
if userId <= 0 && serverGroupId <=0 && serverId <= 0 {
if userId <= 0 && serverGroupId <= 0 && serverId <= 0 {
// synFlood
var synFloodConfig = firewallconfigs.DefaultSYNFloodConfig()
synFloodJSON, err := json.Marshal(synFloodConfig)
@@ -611,6 +611,10 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyServerId(tx *dbs.Tx, poli
// FindFirewallPolicyIdsWithServerId 查找服务独立关联的策略IDs
func (this *HTTPFirewallPolicyDAO) FindFirewallPolicyIdsWithServerId(tx *dbs.Tx, serverId int64) ([]int64, error) {
if serverId <= 0 {
return nil, nil
}
var result = []int64{}
ones, err := this.Query(tx).
Attr("serverId", serverId).

View File

@@ -124,8 +124,9 @@ func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int
}
// CreateRewriteRule 创建规则
func (this *HTTPRewriteRuleDAO) CreateRewriteRule(tx *dbs.Tx, pattern string, replace string, mode string, redirectStatus int, isBreak bool, proxyHost string, withQuery bool, isOn bool, condsJSON []byte) (int64, error) {
func (this *HTTPRewriteRuleDAO) CreateRewriteRule(tx *dbs.Tx, userId int64, pattern string, replace string, mode string, redirectStatus int, isBreak bool, proxyHost string, withQuery bool, isOn bool, condsJSON []byte) (int64, error) {
var op = NewHTTPRewriteRuleOperator()
op.UserId = userId
op.State = HTTPRewriteRuleStateEnabled
op.IsOn = isOn
@@ -172,6 +173,34 @@ func (this *HTTPRewriteRuleDAO) UpdateRewriteRule(tx *dbs.Tx, rewriteRuleId int6
return this.NotifyUpdate(tx, rewriteRuleId)
}
func (this *HTTPRewriteRuleDAO) CheckUserRewriteRule(tx *dbs.Tx, userId int64, rewriteRuleId int64) error {
if rewriteRuleId <= 0 {
return ErrNotFound
}
exists, err := this.Query(tx).
Pk(rewriteRuleId).
Attr("userId", userId).
Exist()
if err != nil {
return err
}
if !exists {
return ErrNotFound
}
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithRewriteRuleId(tx, rewriteRuleId)
if err != nil {
return err
}
if webId <= 0 {
return ErrNotFound
}
return SharedHTTPWebDAO.CheckUserWeb(tx, userId, webId)
}
// NotifyUpdate 通知更新
func (this *HTTPRewriteRuleDAO) NotifyUpdate(tx *dbs.Tx, rewriteRuleId int64) error {
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithRewriteRuleId(tx, rewriteRuleId)

View File

@@ -151,6 +151,18 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, isLocationOrGr
}
}
// Optimization
if IsNotNull(web.Optimization) {
var optimizationConfig = serverconfigs.NewHTTPPageOptimizationConfig()
err = json.Unmarshal(web.Optimization, optimizationConfig)
if err != nil {
return nil, err
}
if this.shouldCompose(isLocationOrGroup, forNode, optimizationConfig.IsPrior, true) {
config.Optimization = optimizationConfig
}
}
// charset
if IsNotNull(web.Charset) {
var charsetConfig = &serverconfigs.HTTPCharsetConfig{}
@@ -550,7 +562,20 @@ func (this *HTTPWebDAO) CreateWeb(tx *dbs.Tx, adminId int64, userId int64, rootJ
if len(rootJSON) > 0 {
op.Root = JSONBytes(rootJSON)
}
err := this.Save(tx, op)
// 设置默认的remote-addr
// set default remote-addr config
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{
IsOn: true,
Value: "${rawRemoteAddr}",
}
remoteAddrConfigJSON, err := json.Marshal(remoteAddrConfig)
if err != nil {
return 0, err
}
op.RemoteAddr = remoteAddrConfigJSON
err = this.Save(tx, op)
if err != nil {
return 0, err
}
@@ -574,14 +599,42 @@ func (this *HTTPWebDAO) UpdateWeb(tx *dbs.Tx, webId int64, rootJSON []byte) erro
}
// UpdateWebCompression 修改压缩配置
func (this *HTTPWebDAO) UpdateWebCompression(tx *dbs.Tx, webId int64, compressionConfig []byte) error {
func (this *HTTPWebDAO) UpdateWebCompression(tx *dbs.Tx, webId int64, compressionConfig *serverconfigs.HTTPCompressionConfig) error {
if webId <= 0 {
return errors.New("invalid webId")
}
compressionJSON, err := json.Marshal(compressionConfig)
if err != nil {
return err
}
var op = NewHTTPWebOperator()
op.Id = webId
op.Compression = JSONBytes(compressionConfig)
err := this.Save(tx, op)
op.Compression = compressionJSON
err = this.Save(tx, op)
if err != nil {
return err
}
return this.NotifyUpdate(tx, webId)
}
// UpdateWebOptimization 修改页面优化配置
func (this *HTTPWebDAO) UpdateWebOptimization(tx *dbs.Tx, webId int64, optimizationConfig *serverconfigs.HTTPPageOptimizationConfig) error {
if webId <= 0 {
return errors.New("invalid webId")
}
optimizationJSON, err := json.Marshal(optimizationConfig)
if err != nil {
return err
}
var op = NewHTTPWebOperator()
op.Id = webId
op.Optimization = optimizationJSON
err = this.Save(tx, op)
if err != nil {
return err
}

View File

@@ -2,6 +2,47 @@ package models
import "github.com/iwind/TeaGo/dbs"
const (
HTTPWebField_Id dbs.FieldName = "id" // ID
HTTPWebField_IsOn dbs.FieldName = "isOn" // 是否启用
HTTPWebField_TemplateId dbs.FieldName = "templateId" // 模版ID
HTTPWebField_AdminId dbs.FieldName = "adminId" // 管理员ID
HTTPWebField_UserId dbs.FieldName = "userId" // 用户ID
HTTPWebField_State dbs.FieldName = "state" // 状态
HTTPWebField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
HTTPWebField_Root dbs.FieldName = "root" // 根目录
HTTPWebField_Charset dbs.FieldName = "charset" // 字符集
HTTPWebField_Shutdown dbs.FieldName = "shutdown" // 临时关闭页面配置
HTTPWebField_Pages dbs.FieldName = "pages" // 特殊页面
HTTPWebField_RedirectToHttps dbs.FieldName = "redirectToHttps" // 跳转到HTTPS设置
HTTPWebField_Indexes dbs.FieldName = "indexes" // 首页文件列表
HTTPWebField_MaxRequestBodySize dbs.FieldName = "maxRequestBodySize" // 最大允许的请求内容尺寸
HTTPWebField_RequestHeader dbs.FieldName = "requestHeader" // 请求Header配置
HTTPWebField_ResponseHeader dbs.FieldName = "responseHeader" // 响应Header配置
HTTPWebField_AccessLog dbs.FieldName = "accessLog" // 访问日志配置
HTTPWebField_Stat dbs.FieldName = "stat" // 统计配置
HTTPWebField_Gzip dbs.FieldName = "gzip" // Gzip配置v0.3.2弃用)
HTTPWebField_Compression dbs.FieldName = "compression" // 压缩配置
HTTPWebField_Cache dbs.FieldName = "cache" // 缓存配置
HTTPWebField_Firewall dbs.FieldName = "firewall" // 防火墙设置
HTTPWebField_Locations dbs.FieldName = "locations" // 路由规则配置
HTTPWebField_Websocket dbs.FieldName = "websocket" // Websocket设置
HTTPWebField_RewriteRules dbs.FieldName = "rewriteRules" // 重写规则配置
HTTPWebField_HostRedirects dbs.FieldName = "hostRedirects" // 域名跳转
HTTPWebField_Fastcgi dbs.FieldName = "fastcgi" // Fastcgi配置
HTTPWebField_Auth dbs.FieldName = "auth" // 认证策略配置
HTTPWebField_Webp dbs.FieldName = "webp" // WebP配置
HTTPWebField_RemoteAddr dbs.FieldName = "remoteAddr" // 客户端IP配置
HTTPWebField_MergeSlashes dbs.FieldName = "mergeSlashes" // 是否合并路径中的斜杠
HTTPWebField_RequestLimit dbs.FieldName = "requestLimit" // 请求限制
HTTPWebField_RequestScripts dbs.FieldName = "requestScripts" // 请求脚本
HTTPWebField_Uam dbs.FieldName = "uam" // UAM设置
HTTPWebField_Cc dbs.FieldName = "cc" // CC设置
HTTPWebField_Referers dbs.FieldName = "referers" // 防盗链设置
HTTPWebField_UserAgent dbs.FieldName = "userAgent" // UserAgent设置
HTTPWebField_Optimization dbs.FieldName = "optimization" // 页面优化配置
)
// HTTPWeb HTTP Web
type HTTPWeb struct {
Id uint32 `field:"id"` // ID
@@ -41,6 +82,7 @@ type HTTPWeb struct {
Cc dbs.JSON `field:"cc"` // CC设置
Referers dbs.JSON `field:"referers"` // 防盗链设置
UserAgent dbs.JSON `field:"userAgent"` // UserAgent设置
Optimization dbs.JSON `field:"optimization"` // 页面优化配置
}
type HTTPWebOperator struct {
@@ -81,6 +123,7 @@ type HTTPWebOperator struct {
Cc any // CC设置
Referers any // 防盗链设置
UserAgent any // UserAgent设置
Optimization any // 页面优化配置
}
func NewHTTPWebOperator() *HTTPWebOperator {

View File

@@ -14,6 +14,7 @@ import (
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
"math"
"net"
"time"
)
@@ -498,7 +499,11 @@ func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, sourceUserId int64, ke
}
}
if len(keyword) > 0 {
query.Like("ipFrom", dbutils.QuoteLike(keyword))
if net.ParseIP(keyword) != nil { // 是一个IP地址
query.Attr("ipFrom", keyword)
} else {
query.Like("ipFrom", dbutils.QuoteLike(keyword))
}
}
if len(ip) > 0 {
query.Attr("ipFrom", ip)
@@ -540,7 +545,11 @@ func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, sourceUserId int64, key
}
}
if len(keyword) > 0 {
query.Like("ipFrom", dbutils.QuoteLike(keyword))
if net.ParseIP(keyword) != nil { // 是一个IP地址
query.Attr("ipFrom", keyword)
} else {
query.Like("ipFrom", dbutils.QuoteLike(keyword))
}
}
if len(ip) > 0 {
query.Attr("ipFrom", ip)

View File

@@ -339,7 +339,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
var countries = []*iplibrary.Country{}
for _, country := range dbCountries {
countries = append(countries, &iplibrary.Country{
Id: types.Uint16(country.Id),
Id: types.Uint16(country.ValueId),
Name: country.DisplayName(),
Codes: country.AllCodes(),
})
@@ -354,7 +354,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
var provinces = []*iplibrary.Province{}
for _, province := range dbProvinces {
provinces = append(provinces, &iplibrary.Province{
Id: types.Uint16(province.Id),
Id: types.Uint16(province.ValueId),
Name: province.DisplayName(),
Codes: province.AllCodes(),
})
@@ -369,7 +369,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
var cities = []*iplibrary.City{}
for _, city := range dbCities {
cities = append(cities, &iplibrary.City{
Id: city.Id,
Id: city.ValueId,
Name: city.DisplayName(),
Codes: city.AllCodes(),
})
@@ -384,7 +384,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
var towns = []*iplibrary.Town{}
for _, town := range dbTowns {
towns = append(towns, &iplibrary.Town{
Id: town.Id,
Id: town.ValueId,
Name: town.DisplayName(),
Codes: town.AllCodes(),
})
@@ -399,7 +399,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
var providers = []*iplibrary.Provider{}
for _, provider := range dbProviders {
providers = append(providers, &iplibrary.Provider{
Id: types.Uint16(provider.Id),
Id: types.Uint16(provider.ValueId),
Name: provider.DisplayName(),
Codes: provider.AllCodes(),
})
@@ -440,35 +440,35 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
var countryMap = map[string]int64{} // countryName => countryId
for _, country := range dbCountries {
for _, code := range country.AllCodes() {
countryMap[code] = int64(country.Id)
countryMap[code] = int64(country.ValueId)
}
}
var provinceMap = map[string]int64{} // countryId_provinceName => provinceId
for _, province := range dbProvinces {
for _, code := range province.AllCodes() {
provinceMap[types.String(province.CountryId)+"_"+code] = int64(province.Id)
provinceMap[types.String(province.CountryId)+"_"+code] = int64(province.ValueId)
}
}
var cityMap = map[string]int64{} // provinceId_cityName => cityId
for _, city := range dbCities {
for _, code := range city.AllCodes() {
cityMap[types.String(city.ProvinceId)+"_"+code] = int64(city.Id)
cityMap[types.String(city.ProvinceId)+"_"+code] = int64(city.ValueId)
}
}
var townMap = map[string]int64{} // cityId_townName => townId
for _, town := range dbTowns {
for _, code := range town.AllCodes() {
townMap[types.String(town.CityId)+"_"+code] = int64(town.Id)
townMap[types.String(town.CityId)+"_"+code] = int64(town.ValueId)
}
}
var providerMap = map[string]int64{} // providerName => providerId
for _, provider := range dbProviders {
for _, code := range provider.AllCodes() {
providerMap[code] = int64(provider.Id)
providerMap[code] = int64(provider.ValueId)
}
}

View File

@@ -1,9 +1,11 @@
package models
import (
"encoding/json"
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
@@ -36,7 +38,7 @@ func init() {
}
// CreateLog 创建管理员日志
func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level string, description string, action string, ip string) error {
func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level string, description string, action string, ip string, langMessageCode langs.MessageCode, langMessageArgs []any) error {
var op = NewLogOperator()
op.Level = level
op.Description = utils.LimitString(description, 1000)
@@ -53,6 +55,16 @@ func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level
op.ProviderId = adminId
}
// i18n
op.LangMessageCode = langMessageCode
if len(langMessageArgs) > 0 {
langMessageArgsJSON, err := json.Marshal(langMessageArgs)
if err != nil {
return err
}
op.LangMessageArgs = langMessageArgsJSON
}
op.Day = timeutil.Format("Ymd")
op.Type = LogTypeAdmin
err := this.Save(tx, op)

View File

@@ -1,34 +1,60 @@
package models
// 操作日志
import "github.com/iwind/TeaGo/dbs"
const (
LogField_Id dbs.FieldName = "id" // ID
LogField_Level dbs.FieldName = "level" // 级别
LogField_Description dbs.FieldName = "description" // 描述
LogField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
LogField_Action dbs.FieldName = "action" // 动作
LogField_UserId dbs.FieldName = "userId" // 用户ID
LogField_AdminId dbs.FieldName = "adminId" // 管理员ID
LogField_ProviderId dbs.FieldName = "providerId" // 供应商ID
LogField_Ip dbs.FieldName = "ip" // IP地址
LogField_Type dbs.FieldName = "type" // 类型admin, user
LogField_Day dbs.FieldName = "day" // 日期
LogField_BillId dbs.FieldName = "billId" // 账单ID
LogField_LangMessageCode dbs.FieldName = "langMessageCode" // 多语言消息代号
LogField_LangMessageArgs dbs.FieldName = "langMessageArgs" // 多语言参数
LogField_Params dbs.FieldName = "params" // 关联对象参数
)
// Log 操作日志
type Log struct {
Id uint32 `field:"id"` // ID
Level string `field:"level"` // 级别
Description string `field:"description"` // 描述
CreatedAt uint64 `field:"createdAt"` // 创建时间
Action string `field:"action"` // 动作
UserId uint32 `field:"userId"` // 用户ID
AdminId uint32 `field:"adminId"` // 管理员ID
ProviderId uint32 `field:"providerId"` // 供应商ID
Ip string `field:"ip"` // IP地址
Type string `field:"type"` // 类型admin, user
Day string `field:"day"` // 日期
BillId uint32 `field:"billId"` // 账单ID
Id uint32 `field:"id"` // ID
Level string `field:"level"` // 级别
Description string `field:"description"` // 描述
CreatedAt uint64 `field:"createdAt"` // 创建时间
Action string `field:"action"` // 动作
UserId uint32 `field:"userId"` // 用户ID
AdminId uint32 `field:"adminId"` // 管理员ID
ProviderId uint32 `field:"providerId"` // 供应商ID
Ip string `field:"ip"` // IP地址
Type string `field:"type"` // 类型admin, user
Day string `field:"day"` // 日期
BillId uint32 `field:"billId"` // 账单ID
LangMessageCode string `field:"langMessageCode"` // 多语言消息代号
LangMessageArgs dbs.JSON `field:"langMessageArgs"` // 多语言参数
Params dbs.JSON `field:"params"` // 关联对象参数
}
type LogOperator struct {
Id interface{} // ID
Level interface{} // 级别
Description interface{} // 描述
CreatedAt interface{} // 创建时间
Action interface{} // 动作
UserId interface{} // 用户ID
AdminId interface{} // 管理员ID
ProviderId interface{} // 供应商ID
Ip interface{} // IP地址
Type interface{} // 类型admin, user
Day interface{} // 日期
BillId interface{} // 账单ID
Id any // ID
Level any // 级别
Description any // 描述
CreatedAt any // 创建时间
Action any // 动作
UserId any // 用户ID
AdminId any // 管理员ID
ProviderId any // 供应商ID
Ip any // IP地址
Type any // 类型admin, user
Day any // 日期
BillId any // 账单ID
LangMessageCode any // 多语言消息代号
LangMessageArgs any // 多语言参数
Params any // 关联对象参数
}
func NewLogOperator() *LogOperator {

View File

@@ -207,6 +207,7 @@ func (this *MonitorNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSO
func (this *MonitorNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
return this.Query(tx).
State(MonitorNodeStateEnabled).
Attr("isOn", true).
Where("status IS NOT NULL").
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
Param("version", utils.VersionToLong(version)).

View File

@@ -100,6 +100,7 @@ func (this *NodeClusterDAO) FindNodeClusterName(tx *dbs.Tx, clusterId int64) (st
// FindAllEnableClusters 查找所有可用的集群
func (this *NodeClusterDAO) FindAllEnableClusters(tx *dbs.Tx) (result []*NodeCluster, err error) {
_, err = this.Query(tx).
Result(NodeClusterField_Id, NodeClusterField_Name, NodeClusterField_IsOn, NodeClusterField_HealthCheck, NodeClusterField_AutoRemoteStart, NodeClusterField_AutoRegister, NodeClusterField_CreatedAt, NodeClusterField_UniqueId, NodeClusterField_Secret).
State(NodeClusterStateEnabled).
Slice(&result).
Desc("isPinned").
@@ -175,7 +176,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
// 全局服务配置
if globalServerConfig == nil {
globalServerConfig = serverconfigs.DefaultGlobalServerConfig()
globalServerConfig = serverconfigs.NewGlobalServerConfig()
}
globalServerConfigJSON, err := json.Marshal(globalServerConfig)
if err != nil {
@@ -262,19 +263,40 @@ func (this *NodeClusterDAO) CountAllEnabledClusters(tx *dbs.Tx, keyword string)
// ListEnabledClusters 列出单页集群
func (this *NodeClusterDAO) ListEnabledClusters(tx *dbs.Tx, keyword string, offset, size int64) (result []*NodeCluster, err error) {
query := this.Query(tx).
var query = this.Query(tx).
State(NodeClusterStateEnabled)
if len(keyword) > 0 {
query.Where("(name LIKE :keyword OR dnsName like :keyword OR (dnsDomainId > 0 AND dnsDomainId IN (SELECT id FROM "+dns.SharedDNSDomainDAO.Table+" WHERE name LIKE :keyword AND state=1)))").
Param("keyword", dbutils.QuoteLike(keyword))
}
_, err = query.
Result(
NodeClusterField_Id,
NodeClusterField_Name,
NodeClusterField_IsOn,
NodeClusterField_IsPinned,
NodeClusterField_InstallDir,
NodeClusterField_HttpFirewallPolicyId,
NodeClusterField_AdminId,
NodeClusterField_IsOn,
NodeClusterField_IsAD,
NodeClusterField_UserId,
NodeClusterField_DnsName,
NodeClusterField_DnsDomainId,
NodeClusterField_Dns,
NodeClusterField_CreatedAt,
NodeClusterField_UniqueId,
NodeClusterField_Secret,
NodeClusterField_GrantId,
NodeClusterField_TimeZone,
).
Offset(offset).
Limit(size).
Slice(&result).
Desc("isPinned").
DescPk().
FindAll()
return
}
@@ -625,10 +647,10 @@ func (this *NodeClusterDAO) FindClusterTOAConfig(tx *dbs.Tx, clusterId int64, ca
return nil, err
}
if !IsNotNull([]byte(toa)) {
return nodeconfigs.DefaultTOAConfig(), nil
return nodeconfigs.NewTOAConfig(), nil
}
config := &nodeconfigs.TOAConfig{}
var config = nodeconfigs.NewTOAConfig()
err = json.Unmarshal([]byte(toa), config)
if err != nil {
return nil, err
@@ -653,7 +675,7 @@ func (this *NodeClusterDAO) UpdateClusterTOA(tx *dbs.Tx, clusterId int64, toaJSO
if err != nil {
return err
}
return this.NotifyUpdate(tx, clusterId)
return this.NotifyTOAUpdate(tx, clusterId)
}
// CountAllEnabledNodeClustersWithHTTPCachePolicyId 计算使用某个缓存策略的集群数量
@@ -996,7 +1018,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
cluster, err := this.Query(tx).
Pk(clusterId).
State(NodeClusterStateEnabled).
Result("id", "name", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "cc", "httpPages", "isOn", "ddosProtection", "clock", "globalServerConfig", "autoInstallNftables").
Result("id", "name", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "cc", "httpPages", "http3", "isOn", "ddosProtection", "clock", "globalServerConfig", "autoInstallNftables").
Find()
if err != nil || cluster == nil {
return nil, err
@@ -1113,11 +1135,12 @@ func (this *NodeClusterDAO) FindClusterUAMPolicy(tx *dbs.Tx, clusterId int64, ca
return nil, err
}
var policy = nodeconfigs.NewUAMPolicy()
if IsNull(uamJSON) {
return nodeconfigs.DefaultUAMPolicy, nil
return policy, nil
}
var policy = &nodeconfigs.UAMPolicy{}
err = json.Unmarshal(uamJSON, policy)
if err != nil {
return nil, err
@@ -1184,6 +1207,65 @@ func (this *NodeClusterDAO) FindClusterHTTPCCPolicy(tx *dbs.Tx, clusterId int64,
return policy, nil
}
// UpdateClusterHTTP3Policy 修改HTTP3策略设置
func (this *NodeClusterDAO) UpdateClusterHTTP3Policy(tx *dbs.Tx, clusterId int64, http3Policy *nodeconfigs.HTTP3Policy) error {
if http3Policy == nil {
err := this.Query(tx).
Pk(clusterId).
Set("http3", dbs.SQL("null")).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyHTTP3Update(tx, clusterId)
}
http3PolicyJSON, err := json.Marshal(http3Policy)
if err != nil {
return err
}
err = this.Query(tx).
Pk(clusterId).
Set("http3", http3PolicyJSON).
UpdateQuickly()
if err != nil {
return err
}
return this.NotifyHTTP3Update(tx, clusterId)
}
// FindClusterHTTP3Policy 查询HTTP3策略设置
func (this *NodeClusterDAO) FindClusterHTTP3Policy(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (*nodeconfigs.HTTP3Policy, error) {
var cacheKey = this.Table + ":FindClusterHTTP3Policy:" + types.String(clusterId)
if cacheMap != nil {
cache, ok := cacheMap.Get(cacheKey)
if ok {
return cache.(*nodeconfigs.HTTP3Policy), nil
}
}
http3PolicyJSON, err := this.Query(tx).
Pk(clusterId).
Result("http3").
FindJSONCol()
if err != nil {
return nil, err
}
if IsNull(http3PolicyJSON) {
return nodeconfigs.NewHTTP3Policy(), nil
}
var policy = nodeconfigs.NewHTTP3Policy()
err = json.Unmarshal(http3PolicyJSON, policy)
if err != nil {
return nil, err
}
return policy, nil
}
// UpdateClusterHTTPPagesPolicy 修改自定义页面设置
func (this *NodeClusterDAO) UpdateClusterHTTPPagesPolicy(tx *dbs.Tx, clusterId int64, httpPagesPolicy *nodeconfigs.HTTPPagesPolicy) error {
if httpPagesPolicy == nil {
@@ -1314,7 +1396,7 @@ func (this *NodeClusterDAO) FindClusterGlobalServerConfig(tx *dbs.Tx, clusterId
return nil, err
}
var config = serverconfigs.DefaultGlobalServerConfig()
var config = serverconfigs.NewGlobalServerConfig()
if IsNull(configJSON) {
return config, nil
}
@@ -1330,7 +1412,7 @@ func (this *NodeClusterDAO) FindClusterGlobalServerConfig(tx *dbs.Tx, clusterId
// UpdateClusterGlobalServerConfig 修改全局服务配置
func (this *NodeClusterDAO) UpdateClusterGlobalServerConfig(tx *dbs.Tx, clusterId int64, config *serverconfigs.GlobalServerConfig) error {
if config == nil {
config = serverconfigs.DefaultGlobalServerConfig()
config = serverconfigs.NewGlobalServerConfig()
}
configJSON, err := json.Marshal(config)
if err != nil {
@@ -1362,17 +1444,23 @@ func (this *NodeClusterDAO) NotifyHTTPCCUpdate(tx *dbs.Tx, clusterId int64) erro
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypeHTTPCCPolicyChanged)
}
// NotifyHTTP3Update 通知HTTP3更新
func (this *NodeClusterDAO) NotifyHTTP3Update(tx *dbs.Tx, clusterId int64) error {
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypeHTTP3PolicyChanged)
}
// NotifyHTTPPagesPolicyUpdate 通知HTTP Pages更新
func (this *NodeClusterDAO) NotifyHTTPPagesPolicyUpdate(tx *dbs.Tx, clusterId int64) error {
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypeHTTPPagesPolicyChanged)
}
// NotifyTOAUpdate 通知TOA变化
func (this *NodeClusterDAO) NotifyTOAUpdate(tx *dbs.Tx, clusterId int64) error {
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypeTOAChanged)
}
// NotifyDNSUpdate 通知DNS更新
// TODO 更新新的DNS解析记录的同时需要删除老的DNS解析记录
func (this *NodeClusterDAO) NotifyDNSUpdate(tx *dbs.Tx, clusterId int64) error {
err := dns.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dns.DNSTaskTypeClusterChange)
if err != nil {
return err
}
return nil
return dns.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dns.DNSTaskTypeClusterChange)
}

View File

@@ -2,6 +2,49 @@ package models
import "github.com/iwind/TeaGo/dbs"
const (
NodeClusterField_Id dbs.FieldName = "id" // ID
NodeClusterField_AdminId dbs.FieldName = "adminId" // 管理员ID
NodeClusterField_UserId dbs.FieldName = "userId" // 用户ID
NodeClusterField_IsOn dbs.FieldName = "isOn" // 是否启用
NodeClusterField_Name dbs.FieldName = "name" // 名称
NodeClusterField_UseAllAPINodes dbs.FieldName = "useAllAPINodes" // 是否使用所有API节点
NodeClusterField_ApiNodes dbs.FieldName = "apiNodes" // 使用的API节点
NodeClusterField_InstallDir dbs.FieldName = "installDir" // 安装目录
NodeClusterField_Order dbs.FieldName = "order" // 排序
NodeClusterField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
NodeClusterField_GrantId dbs.FieldName = "grantId" // 默认认证方式
NodeClusterField_SshParams dbs.FieldName = "sshParams" // SSH默认参数
NodeClusterField_State dbs.FieldName = "state" // 状态
NodeClusterField_AutoRegister dbs.FieldName = "autoRegister" // 是否开启自动注册
NodeClusterField_UniqueId dbs.FieldName = "uniqueId" // 唯一ID
NodeClusterField_Secret dbs.FieldName = "secret" // 密钥
NodeClusterField_HealthCheck dbs.FieldName = "healthCheck" // 健康检查
NodeClusterField_DnsName dbs.FieldName = "dnsName" // DNS名称
NodeClusterField_DnsDomainId dbs.FieldName = "dnsDomainId" // 域名ID
NodeClusterField_Dns dbs.FieldName = "dns" // DNS配置
NodeClusterField_Toa dbs.FieldName = "toa" // TOA配置
NodeClusterField_CachePolicyId dbs.FieldName = "cachePolicyId" // 缓存策略ID
NodeClusterField_HttpFirewallPolicyId dbs.FieldName = "httpFirewallPolicyId" // WAF策略ID
NodeClusterField_AccessLog dbs.FieldName = "accessLog" // 访问日志设置
NodeClusterField_SystemServices dbs.FieldName = "systemServices" // 系统服务设置
NodeClusterField_TimeZone dbs.FieldName = "timeZone" // 时区
NodeClusterField_NodeMaxThreads dbs.FieldName = "nodeMaxThreads" // 节点最大线程数
NodeClusterField_DdosProtection dbs.FieldName = "ddosProtection" // DDoS防护设置
NodeClusterField_AutoOpenPorts dbs.FieldName = "autoOpenPorts" // 是否自动尝试开放端口
NodeClusterField_IsPinned dbs.FieldName = "isPinned" // 是否置顶
NodeClusterField_Webp dbs.FieldName = "webp" // WebP设置
NodeClusterField_Uam dbs.FieldName = "uam" // UAM设置
NodeClusterField_Clock dbs.FieldName = "clock" // 时钟配置
NodeClusterField_GlobalServerConfig dbs.FieldName = "globalServerConfig" // 全局服务配置
NodeClusterField_AutoRemoteStart dbs.FieldName = "autoRemoteStart" // 自动远程启动
NodeClusterField_AutoInstallNftables dbs.FieldName = "autoInstallNftables" // 自动安装nftables
NodeClusterField_IsAD dbs.FieldName = "isAD" // 是否为高防集群
NodeClusterField_HttpPages dbs.FieldName = "httpPages" // 自定义页面设置
NodeClusterField_Cc dbs.FieldName = "cc" // CC设置
NodeClusterField_Http3 dbs.FieldName = "http3" // HTTP3设置
)
// NodeCluster 节点集群
type NodeCluster struct {
Id uint32 `field:"id"` // ID
@@ -43,6 +86,7 @@ type NodeCluster struct {
IsAD bool `field:"isAD"` // 是否为高防集群
HttpPages dbs.JSON `field:"httpPages"` // 自定义页面设置
Cc dbs.JSON `field:"cc"` // CC设置
Http3 dbs.JSON `field:"http3"` // HTTP3设置
}
type NodeClusterOperator struct {
@@ -85,6 +129,7 @@ type NodeClusterOperator struct {
IsAD any // 是否为高防集群
HttpPages any // 自定义页面设置
Cc any // CC设置
Http3 any // HTTP3设置
}
func NewNodeClusterOperator() *NodeClusterOperator {

View File

@@ -60,7 +60,7 @@ func (this *NodeCluster) DecodeClock() *nodeconfigs.ClockConfig {
// DecodeGlobalServerConfig 解析全局服务配置
func (this *NodeCluster) DecodeGlobalServerConfig() *serverconfigs.GlobalServerConfig {
var config = serverconfigs.DefaultGlobalServerConfig()
var config = serverconfigs.NewGlobalServerConfig()
if IsNotNull(this.GlobalServerConfig) {
err := json.Unmarshal(this.GlobalServerConfig, config)
if err != nil {

View File

@@ -295,6 +295,7 @@ func (this *NodeDAO) CountAllEnabledNodes(tx *dbs.Tx) (int64, error) {
func (this *NodeDAO) CountAllEnabledOfflineNodes(tx *dbs.Tx) (int64, error) {
return this.Query(tx).
State(NodeStateEnabled).
Attr("isOn", true).
Where("clusterId IN (SELECT id FROM "+SharedNodeClusterDAO.Table+" WHERE state=:clusterState)").
Param("clusterState", NodeClusterStateEnabled).
Where("(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)").
@@ -1086,7 +1087,11 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
config.WebPImagePolicies = map[int64]*nodeconfigs.WebPImagePolicy{}
config.UAMPolicies = map[int64]*nodeconfigs.UAMPolicy{}
config.HTTPCCPolicies = map[int64]*nodeconfigs.HTTPCCPolicy{}
config.HTTP3Policies = map[int64]*nodeconfigs.HTTP3Policy{}
config.HTTPPagesPolicies = map[int64]*nodeconfigs.HTTPPagesPolicy{}
var cachePolicyIds = []int64{}
var allowIPMaps = map[string]bool{}
for _, clusterId := range clusterIds {
nodeCluster, err := SharedNodeClusterDAO.FindClusterBasicInfo(tx, clusterId, cacheMap)
@@ -1126,12 +1131,15 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
// 缓存策略
var httpCachePolicyId = int64(nodeCluster.CachePolicyId)
if httpCachePolicyId > 0 {
cachePolicy, err := SharedHTTPCachePolicyDAO.ComposeCachePolicy(tx, httpCachePolicyId, cacheMap)
if err != nil {
return nil, err
}
if cachePolicy != nil {
config.HTTPCachePolicies = append(config.HTTPCachePolicies, cachePolicy)
if !lists.ContainsInt64(cachePolicyIds, httpCachePolicyId) {
cachePolicyIds = append(cachePolicyIds, httpCachePolicyId)
cachePolicy, err := SharedHTTPCachePolicyDAO.ComposeCachePolicy(tx, httpCachePolicyId, cacheMap)
if err != nil {
return nil, err
}
if cachePolicy != nil {
config.HTTPCachePolicies = append(config.HTTPCachePolicies, cachePolicy)
}
}
}
@@ -1172,7 +1180,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
// UAM
if IsNotNull(nodeCluster.Uam) {
var uamPolicy = &nodeconfigs.UAMPolicy{}
var uamPolicy = nodeconfigs.NewUAMPolicy()
err = json.Unmarshal(nodeCluster.Uam, uamPolicy)
if err != nil {
return nil, err
@@ -1189,7 +1197,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
}
// 集成默认设置
for i := 0; i < len(serverconfigs.DefaultHTTPCCThresholds); i ++ {
for i := 0; i < len(serverconfigs.DefaultHTTPCCThresholds); i++ {
if i < len(ccPolicy.Thresholds) {
ccPolicy.Thresholds[i].MergeIfEmpty(serverconfigs.DefaultHTTPCCThresholds[i])
}
@@ -1198,6 +1206,16 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
config.HTTPCCPolicies[clusterId] = ccPolicy
}
// HTTP3 Policy
if IsNotNull(nodeCluster.Http3) {
var http3Policy = nodeconfigs.NewHTTP3Policy()
err = json.Unmarshal(nodeCluster.Http3, http3Policy)
if err != nil {
return nil, err
}
config.HTTP3Policies[clusterId] = http3Policy
}
// HTTP Pages Policy
if IsNotNull(nodeCluster.HttpPages) {
var httpPagesPolicy = nodeconfigs.NewHTTPPagesPolicy()
@@ -1473,6 +1491,7 @@ func (this *NodeDAO) FindAllNotInstalledNodesWithClusterId(tx *dbs.Tx, clusterId
func (this *NodeDAO) CountAllLowerVersionNodesWithClusterId(tx *dbs.Tx, clusterId int64, os string, arch string, version string) (int64, error) {
return this.Query(tx).
State(NodeStateEnabled).
Attr("isOn", true).
Attr("clusterId", clusterId).
Where("status IS NOT NULL").
Where("JSON_EXTRACT(status, '$.os')=:os").
@@ -1506,6 +1525,7 @@ func (this *NodeDAO) FindAllLowerVersionNodesWithClusterId(tx *dbs.Tx, clusterId
func (this *NodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
return this.Query(tx).
State(NodeStateEnabled).
Attr("isOn", true).
Where("clusterId IN (SELECT id FROM "+SharedNodeClusterDAO.Table+" WHERE state=1)").
Where("status IS NOT NULL").
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").

View File

@@ -27,7 +27,9 @@ const (
NodeTaskTypeUAMPolicyChanged NodeTaskType = "uamPolicyChanged" // UAM策略变化
NodeTaskTypeHTTPPagesPolicyChanged NodeTaskType = "httpPagesPolicyChanged" // 自定义页面变化
NodeTaskTypeHTTPCCPolicyChanged NodeTaskType = "httpCCPolicyChanged" // CC策略变化
NodeTaskTypeHTTP3PolicyChanged NodeTaskType = "http3PolicyChanged" // HTTP3策略变化
NodeTaskTypeUpdatingServers NodeTaskType = "updatingServers" // 更新一组服务
NodeTaskTypeTOAChanged NodeTaskType = "toaChanged" // TOA配置变化
// NS相关
@@ -232,6 +234,12 @@ func (this *NodeTaskDAO) DeleteNodeTasks(tx *dbs.Tx, role string, nodeId int64)
return err
}
// DeleteAllNodeTasks 删除所有节点相关任务
func (this *NodeTaskDAO) DeleteAllNodeTasks(tx *dbs.Tx) error {
return this.Query(tx).
DeleteQuickly()
}
// FindDoingNodeTasks 查询一个节点的所有任务
func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, role string, nodeId int64, version int64) (result []*NodeTask, err error) {
if nodeId <= 0 {

View File

@@ -22,7 +22,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedNodeTrafficDailyStatDAO.Clean(nil, 30) // 只保留N天
err := SharedNodeTrafficDailyStatDAO.CleanDefaultDays(nil, 32) // 只保留N天
if err != nil {
remotelogs.Error("NodeTrafficDailyStatDAO", "clean expired data failed: "+err.Error())
}
@@ -134,11 +134,27 @@ func (this *NodeTrafficDailyStatDAO) SumDailyStat(tx *dbs.Tx, role string, nodeI
return one.(*NodeTrafficDailyStat), nil
}
// Clean 清理历史数据
func (this *NodeTrafficDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理历史数据
func (this *NodeTrafficDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
_, err := this.Query(tx).
Lt("day", day).
Delete()
return err
}
func (this *NodeTrafficDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.NodeTrafficDailyStat.Clean.Days > 0 {
defaultDays = databaseConfig.NodeTrafficDailyStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 32
}
return this.CleanDays(tx, defaultDays)
}

View File

@@ -15,6 +15,7 @@ type NSCluster struct {
Tcp dbs.JSON `field:"tcp"` // TCP设置
Tls dbs.JSON `field:"tls"` // TLS设置
Udp dbs.JSON `field:"udp"` // UDP设置
Doh dbs.JSON `field:"doh"` // DoH设置
DdosProtection dbs.JSON `field:"ddosProtection"` // DDoS防护设置
Hosts dbs.JSON `field:"hosts"` // DNS主机地址
Soa dbs.JSON `field:"soa"` // SOA配置
@@ -39,6 +40,7 @@ type NSClusterOperator struct {
Tcp any // TCP设置
Tls any // TLS设置
Udp any // UDP设置
Doh any // DoH设置
DdosProtection any // DDoS防护设置
Hosts any // DNS主机地址
Soa any // SOA配置

View File

@@ -93,6 +93,7 @@ func (this *NSNodeDAO) CountAllLowerVersionNodesWithClusterId(tx *dbs.Tx, cluste
return this.Query(tx).
State(NSNodeStateEnabled).
Attr("clusterId", clusterId).
Attr("isOn", true).
Where("status IS NOT NULL").
Where("JSON_EXTRACT(status, '$.os')=:os").
Where("JSON_EXTRACT(status, '$.arch')=:arch").
@@ -161,6 +162,7 @@ func (this *NSNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *no
func (this *NSNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
return this.Query(tx).
State(NSNodeStateEnabled).
Attr("isOn", true).
Where("clusterId IN (SELECT id FROM "+SharedNSClusterDAO.Table+" WHERE state=1)").
Where("status IS NOT NULL").
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").

View File

@@ -5,6 +5,7 @@ import (
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
_ "github.com/go-sql-driver/mysql"
@@ -91,7 +92,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
adminId int64,
userId int64,
name string,
addrJSON string,
addrJSON []byte,
ossConfig *ossconfigs.OSSConfig,
description string,
weight int32, isOn bool,
connTimeout *shared.TimeDuration,
@@ -102,7 +104,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
certRef *sslconfigs.SSLCertRef,
domains []string,
host string,
followPort bool) (originId int64, err error) {
followPort bool,
http2Enabled bool) (originId int64, err error) {
var op = NewOriginOperator()
op.AdminId = adminId
op.UserId = userId
@@ -141,7 +144,18 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
op.MaxIdleConns = 0
}
op.Addr = addrJSON
if len(addrJSON) > 0 {
op.Addr = addrJSON
}
if ossConfig != nil {
ossConfigJSON, err := json.Marshal(ossConfig)
if err != nil {
return 0, err
}
op.Oss = ossConfigJSON
}
op.Description = description
if weight < 0 {
weight = 0
@@ -169,6 +183,7 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
op.Host = host
op.FollowPort = followPort
op.Http2Enabled = http2Enabled
op.State = OriginStateEnabled
err = this.Save(tx, op)
@@ -182,7 +197,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
originId int64,
name string,
addrJSON string,
addrJSON []byte,
ossConfig *ossconfigs.OSSConfig,
description string,
weight int32,
isOn bool,
@@ -194,14 +210,25 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
certRef *sslconfigs.SSLCertRef,
domains []string,
host string,
followPort bool) error {
followPort bool,
http2Enabled bool) error {
if originId <= 0 {
return errors.New("invalid originId")
}
var op = NewOriginOperator()
op.Id = originId
op.Name = name
op.Addr = addrJSON
if ossConfig != nil {
ossConfigJSON, err := json.Marshal(ossConfig)
if err != nil {
return err
}
op.Oss = ossConfigJSON
}
op.Description = description
if weight < 0 {
weight = 0
@@ -266,6 +293,7 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
op.Host = host
op.FollowPort = followPort
op.Http2Enabled = http2Enabled
err := this.Save(tx, op)
if err != nil {
@@ -329,6 +357,7 @@ func (this *OriginDAO) CloneOrigin(tx *dbs.Tx, fromOriginId int64) (newOriginId
op.Domains = origin.Domains
}
op.FollowPort = origin.FollowPort
op.Http2Enabled = origin.Http2Enabled
op.State = origin.State
return this.SaveInt64(tx, op)
}
@@ -367,8 +396,10 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, dataMap *
RequestHost: origin.Host,
Domains: origin.DecodeDomains(),
FollowPort: origin.FollowPort,
HTTP2Enabled: origin.Http2Enabled,
}
// addr
if IsNotNull(origin.Addr) {
var addr = &serverconfigs.NetworkAddressConfig{}
err = json.Unmarshal(origin.Addr, addr)
@@ -378,6 +409,16 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, dataMap *
config.Addr = addr
}
// oss
if IsNotNull(origin.Oss) {
var ossConfig = ossconfigs.NewOSSConfig()
err = json.Unmarshal(origin.Oss, ossConfig)
if err != nil {
return nil, err
}
config.OSS = ossConfig
}
if IsNotNull(origin.ConnTimeout) {
var connTimeout = &shared.TimeDuration{}
err = json.Unmarshal(origin.ConnTimeout, &connTimeout)

View File

@@ -11,6 +11,7 @@ type Origin struct {
Name string `field:"name"` // 名称
Version uint32 `field:"version"` // 版本
Addr dbs.JSON `field:"addr"` // 地址
Oss dbs.JSON `field:"oss"` // OSS配置
Description string `field:"description"` // 描述
Code string `field:"code"` // 代号
Weight uint32 `field:"weight"` // 权重
@@ -31,36 +32,39 @@ type Origin struct {
Domains dbs.JSON `field:"domains"` // 所属域名
FollowPort bool `field:"followPort"` // 端口跟随
State uint8 `field:"state"` // 状态
Http2Enabled bool `field:"http2Enabled"` // 是否支持HTTP/2
}
type OriginOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
IsOn interface{} // 是否启用
Name interface{} // 名称
Version interface{} // 版本
Addr interface{} // 地址
Description interface{} // 描述
Code interface{} // 代号
Weight interface{} // 权重
ConnTimeout interface{} // 连接超时
ReadTimeout interface{} // 超时
IdleTimeout interface{} // 空闲连接超时
MaxFails interface{} // 最多失败次数
MaxConns interface{} // 最大并发连接
MaxIdleConns interface{} // 最多空闲连接数
HttpRequestURI interface{} // 转发后的请求URI
HttpRequestHeader interface{} // 请求Header配置
HttpResponseHeader interface{} // 响应Header配置
Host interface{} // 自定义主机名
HealthCheck interface{} // 健康检查设置
Cert interface{} // 证书设置
Ftp interface{} // FTP相关设置
CreatedAt interface{} // 创建时间
Domains interface{} // 所属域名
FollowPort interface{} // 端口跟随
State interface{} // 状态
Id any // ID
AdminId any // 管理员ID
UserId any // 用户ID
IsOn any // 是否启用
Name any // 名称
Version any // 版本
Addr any // 地址
Oss any // OSS配置
Description any // 描述
Code any // 代号
Weight any // 权重
ConnTimeout any // 连接超时
ReadTimeout any // 超时
IdleTimeout any // 空闲连接超时
MaxFails any // 最多失败次
MaxConns any // 最大并发连接数
MaxIdleConns any // 最多空闲连接数
HttpRequestURI any // 转发后的请求URI
HttpRequestHeader any // 请求Header配置
HttpResponseHeader any // 响应Header配置
Host any // 自定义主机名
HealthCheck any // 健康检查设置
Cert any // 证书设置
Ftp any // FTP相关设置
CreatedAt any // 创建时间
Domains any // 所属域名
FollowPort any // 端口跟随
State any // 状态
Http2Enabled any // 是否支持HTTP/2
}
func NewOriginOperator() *OriginOperator {

View File

@@ -42,7 +42,7 @@ func init() {
// EnableRegionCity 启用条目
func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionCityStateEnabled).
Update()
return err
@@ -51,7 +51,7 @@ func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
// DisableRegionCity 禁用条目
func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionCityStateDisabled).
Update()
return err
@@ -60,7 +60,7 @@ func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
// FindEnabledRegionCity 查找启用中的条目
func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionCity, error) {
result, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Attr("state", RegionCityStateEnabled).
Find()
if result == nil {
@@ -72,7 +72,7 @@ func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionC
// FindRegionCityName 根据主键查找名称
func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, error) {
return this.Query(tx).
Pk(id).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
@@ -81,7 +81,7 @@ func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, er
func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
return this.Query(tx).
Attr("dataId", dataId).
ResultPk().
Result(RegionCityField_ValueId).
FindInt64Col(0)
}
@@ -93,7 +93,7 @@ func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string,
op.DataId = dataId
op.State = RegionCityStateEnabled
codes := []string{name}
var codes = []string{name}
codesJSON, err := json.Marshal(codes)
if err != nil {
return 0, err
@@ -103,7 +103,18 @@ func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string,
if err != nil {
return 0, err
}
return types.Int64(op.Id), nil
var cityId = types.Int64(op.Id)
// value id
err = this.Query(tx).
Pk(cityId).
Set(RegionCityField_ValueId, cityId).
UpdateQuickly()
if err != nil {
return 0, err
}
return cityId, nil
}
// FindCityIdWithName 根据城市名查找城市ID
@@ -113,7 +124,7 @@ func (this *RegionCityDAO) FindCityIdWithName(tx *dbs.Tx, provinceId int64, city
Where("(name=:cityName OR customName=:cityName OR JSON_CONTAINS(codes, :cityNameJSON) OR JSON_CONTAINS(customCodes, :cityNameJSON))").
Param("cityName", cityName).
Param("cityNameJSON", strconv.Quote(cityName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk().
Result(RegionCityField_ValueId).
FindInt64Col(0)
}
@@ -147,7 +158,7 @@ func (this *RegionCityDAO) UpdateCityCustom(tx *dbs.Tx, cityId int64, customName
}
return this.Query(tx).
Pk(cityId).
Attr(RegionCityField_ValueId, cityId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()

View File

@@ -2,9 +2,22 @@ package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionCityField_Id dbs.FieldName = "id" // ID
RegionCityField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionCityField_ProvinceId dbs.FieldName = "provinceId" // 省份ID
RegionCityField_Name dbs.FieldName = "name" // 名称
RegionCityField_Codes dbs.FieldName = "codes" // 代号
RegionCityField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionCityField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionCityField_State dbs.FieldName = "state" // 状态
RegionCityField_DataId dbs.FieldName = "dataId" // 原始数据ID
)
// RegionCity 区域-城市
type RegionCity struct {
Id uint32 `field:"id"` // ID
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
ProvinceId uint32 `field:"provinceId"` // 省份ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
@@ -15,14 +28,15 @@ type RegionCity struct {
}
type RegionCityOperator struct {
Id interface{} // ID
ProvinceId interface{} // 省份ID
Name interface{} // 名称
Codes interface{} // 代号
CustomName interface{} // 自定义名称
CustomCodes interface{} // 自定义代号
State interface{} // 状态
DataId interface{} // 原始数据ID
Id any // ID
ValueId any // 实际ID
ProvinceId any // 省份ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
}
func NewRegionCityOperator() *RegionCityOperator {

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
@@ -20,10 +21,6 @@ const (
RegionCountryStateDisabled = 0 // 已禁用
)
const (
CountryChinaId = 1
)
var regionCountryIdAndNameCacheMap = map[int64]string{} // country id => name
type RegionCountryDAO dbs.DAO
@@ -50,7 +47,7 @@ func init() {
// EnableRegionCountry 启用条目
func (this *RegionCountryDAO) EnableRegionCountry(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionCountryStateEnabled).
Update()
return err
@@ -59,7 +56,7 @@ func (this *RegionCountryDAO) EnableRegionCountry(tx *dbs.Tx, id uint32) error {
// DisableRegionCountry 禁用条目
func (this *RegionCountryDAO) DisableRegionCountry(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionCountryStateDisabled).
Update()
return err
@@ -68,7 +65,7 @@ func (this *RegionCountryDAO) DisableRegionCountry(tx *dbs.Tx, id int64) error {
// FindEnabledRegionCountry 查找启用中的条目
func (this *RegionCountryDAO) FindEnabledRegionCountry(tx *dbs.Tx, id int64) (*RegionCountry, error) {
result, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Attr("state", RegionCountryStateEnabled).
Find()
if result == nil {
@@ -88,7 +85,7 @@ func (this *RegionCountryDAO) FindRegionCountryName(tx *dbs.Tx, id int64) (strin
}
name, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Result("name").
FindStringCol("")
if err != nil {
@@ -105,7 +102,7 @@ func (this *RegionCountryDAO) FindRegionCountryName(tx *dbs.Tx, id int64) (strin
func (this *RegionCountryDAO) FindCountryIdWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
return this.Query(tx).
Attr("dataId", dataId).
ResultPk().
Result(RegionCountryField_ValueId).
FindInt64Col(0)
}
@@ -115,7 +112,7 @@ func (this *RegionCountryDAO) FindCountryIdWithName(tx *dbs.Tx, countryName stri
Where("(name=:countryName OR JSON_CONTAINS(codes, :countryNameJSON) OR customName=:countryName OR JSON_CONTAINS(customCodes, :countryNameJSON))").
Param("countryName", countryName).
Param("countryNameJSON", strconv.Quote(countryName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk().
Result(RegionCountryField_ValueId).
FindInt64Col(0)
}
@@ -145,16 +142,61 @@ func (this *RegionCountryDAO) CreateCountry(tx *dbs.Tx, name string, dataId stri
if err != nil {
return 0, err
}
return types.Int64(op.Id), nil
var countryId = types.Int64(op.Id)
err = this.Query(tx).
Pk(countryId).
Set(RegionCountryField_ValueId, countryId).
UpdateQuickly()
if err != nil {
return 0, err
}
return countryId, nil
}
// FindAllEnabledCountriesOrderByPinyin 查找所有可用的国家并按拼音排序
func (this *RegionCountryDAO) FindAllEnabledCountriesOrderByPinyin(tx *dbs.Tx) (result []*RegionCountry, err error) {
_, err = this.Query(tx).
ones, err := this.Query(tx).
State(RegionCountryStateEnabled).
Slice(&result).
Asc("pinyin").
Asc("JSON_EXTRACT(pinyin, '$[0]')").
FindAll()
if err != nil {
return nil, err
}
// resort China special regions
var chinaRegionMap = map[int64]*RegionCountry{} // countryId => *RegionCountry
for _, one := range ones {
var country = one.(*RegionCountry)
var valueId = int64(country.ValueId)
if regionconfigs.CheckRegionIsInGreaterChina(valueId) {
chinaRegionMap[valueId] = country
}
}
for _, one := range ones {
var country = one.(*RegionCountry)
var valueId = int64(country.ValueId)
if valueId == regionconfigs.RegionChinaId {
result = append(result, country)
// add hk, tw, mo, mainland ...
for _, subRegionId := range regionconfigs.FindAllGreaterChinaSubRegionIds() {
subRegion, ok := chinaRegionMap[subRegionId]
if ok {
result = append(result, subRegion)
}
}
continue
}
if regionconfigs.CheckRegionIsInGreaterChina(valueId) {
continue
}
result = append(result, country)
}
return
}
@@ -163,7 +205,7 @@ func (this *RegionCountryDAO) FindAllCountries(tx *dbs.Tx) (result []*RegionCoun
_, err = this.Query(tx).
State(RegionCountryStateEnabled).
Slice(&result).
AscPk().
Asc(RegionCountryField_ValueId).
FindAll()
return
}
@@ -185,7 +227,7 @@ func (this *RegionCountryDAO) UpdateCountryCustom(tx *dbs.Tx, countryId int64, c
}()
return this.Query(tx).
Pk(countryId).
Attr("valueId", countryId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()

View File

@@ -2,9 +2,25 @@ package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionCountryField_Id dbs.FieldName = "id" // ID
RegionCountryField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionCountryField_ValueCode dbs.FieldName = "valueCode" // 值代号
RegionCountryField_Name dbs.FieldName = "name" // 名称
RegionCountryField_Codes dbs.FieldName = "codes" // 代号
RegionCountryField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionCountryField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionCountryField_State dbs.FieldName = "state" // 状态
RegionCountryField_DataId dbs.FieldName = "dataId" // 原始数据ID
RegionCountryField_Pinyin dbs.FieldName = "pinyin" // 拼音
RegionCountryField_IsCommon dbs.FieldName = "isCommon" // 是否常用
)
// RegionCountry 区域-国家/地区
type RegionCountry struct {
Id uint32 `field:"id"` // ID
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
ValueCode string `field:"valueCode"` // 值代号
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
CustomName string `field:"customName"` // 自定义名称
@@ -12,17 +28,21 @@ type RegionCountry struct {
State uint8 `field:"state"` // 状态
DataId string `field:"dataId"` // 原始数据ID
Pinyin dbs.JSON `field:"pinyin"` // 拼音
IsCommon bool `field:"isCommon"` // 是否常用
}
type RegionCountryOperator struct {
Id interface{} // ID
Name interface{} // 名称
Codes interface{} // 代号
CustomName interface{} // 自定义名称
CustomCodes interface{} // 自定义代号
State interface{} // 状态
DataId interface{} // 原始数据ID
Pinyin interface{} // 拼音
Id any // ID
ValueId any // 实际ID
ValueCode any // 代号
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
Pinyin any // 拼音
IsCommon any // 是否常用
}
func NewRegionCountryOperator() *RegionCountryOperator {

View File

@@ -41,7 +41,7 @@ func init() {
// EnableRegionProvider 启用条目
func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionProviderStateEnabled).
Update()
return err
@@ -50,7 +50,7 @@ func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error
// DisableRegionProvider 禁用条目
func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionProviderStateDisabled).
Update()
return err
@@ -59,7 +59,7 @@ func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) erro
// FindEnabledRegionProvider 查找启用中的条目
func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id int64) (*RegionProvider, error) {
result, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Attr("state", RegionProviderStateEnabled).
Find()
if result == nil {
@@ -71,7 +71,7 @@ func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id int64) (
// FindRegionProviderName 根据主键查找名称
func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (string, error) {
return this.Query(tx).
Pk(id).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
@@ -82,7 +82,7 @@ func (this *RegionProviderDAO) FindProviderIdWithName(tx *dbs.Tx, providerName s
Where("(name=:providerName OR customName=:providerName OR JSON_CONTAINS(codes, :providerNameJSON) OR JSON_CONTAINS(customCodes, :providerNameJSON))").
Param("providerName", providerName).
Param("providerNameJSON", strconv.Quote(providerName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk().
Result(RegionProviderField_ValueId).
FindInt64Col(0)
}
@@ -96,7 +96,20 @@ func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, e
return 0, err
}
op.Codes = codesJSON
return this.SaveInt64(tx, op)
providerId, err := this.SaveInt64(tx, op)
if err != nil {
return 0, err
}
err = this.Query(tx).
Pk(providerId).
Set(RegionProviderField_ValueId, providerId).
UpdateQuickly()
if err != nil {
return 0, err
}
return providerId, nil
}
// FindAllEnabledProviders 查找所有服务商
@@ -119,7 +132,7 @@ func (this *RegionProviderDAO) UpdateProviderCustom(tx *dbs.Tx, providerId int64
}
return this.Query(tx).
Pk(providerId).
Attr("valueId", providerId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()

View File

@@ -2,9 +2,20 @@ package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionProviderField_Id dbs.FieldName = "id" // ID
RegionProviderField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionProviderField_Name dbs.FieldName = "name" // 名称
RegionProviderField_Codes dbs.FieldName = "codes" // 代号
RegionProviderField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionProviderField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionProviderField_State dbs.FieldName = "state" // 状态
)
// RegionProvider 区域-运营商
type RegionProvider struct {
Id uint32 `field:"id"` // ID
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
CustomName string `field:"customName"` // 自定义名称
@@ -13,12 +24,13 @@ type RegionProvider struct {
}
type RegionProviderOperator struct {
Id interface{} // ID
Name interface{} // 名称
Codes interface{} // 代号
CustomName interface{} // 自定义名称
CustomCodes interface{} // 自定义代号
State interface{} // 状态
Id any // ID
ValueId any // 实际ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
}
func NewRegionProviderOperator() *RegionProviderOperator {

View File

@@ -42,7 +42,7 @@ func init() {
// EnableRegionProvince 启用条目
func (this *RegionProvinceDAO) EnableRegionProvince(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionProvinceStateEnabled).
Update()
return err
@@ -51,7 +51,7 @@ func (this *RegionProvinceDAO) EnableRegionProvince(tx *dbs.Tx, id int64) error
// DisableRegionProvince 禁用条目
func (this *RegionProvinceDAO) DisableRegionProvince(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionProvinceStateDisabled).
Update()
return err
@@ -60,7 +60,7 @@ func (this *RegionProvinceDAO) DisableRegionProvince(tx *dbs.Tx, id int64) error
// FindEnabledRegionProvince 查找启用中的条目
func (this *RegionProvinceDAO) FindEnabledRegionProvince(tx *dbs.Tx, id int64) (*RegionProvince, error) {
result, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Attr("state", RegionProvinceStateEnabled).
Find()
if result == nil {
@@ -72,7 +72,7 @@ func (this *RegionProvinceDAO) FindEnabledRegionProvince(tx *dbs.Tx, id int64) (
// FindRegionProvinceName 根据主键查找名称
func (this *RegionProvinceDAO) FindRegionProvinceName(tx *dbs.Tx, id int64) (string, error) {
return this.Query(tx).
Pk(id).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
@@ -81,7 +81,7 @@ func (this *RegionProvinceDAO) FindRegionProvinceName(tx *dbs.Tx, id int64) (str
func (this *RegionProvinceDAO) FindProvinceIdWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
return this.Query(tx).
Attr("dataId", dataId).
ResultPk().
Result(RegionProvinceField_ValueId).
FindInt64Col(0)
}
@@ -92,7 +92,7 @@ func (this *RegionProvinceDAO) FindProvinceIdWithName(tx *dbs.Tx, countryId int6
Where("(name=:provinceName OR customName=:provinceName OR JSON_CONTAINS(codes, :provinceNameJSON) OR JSON_CONTAINS(customCodes, :provinceNameJSON))").
Param("provinceName", provinceName).
Param("provinceNameJSON", strconv.Quote(provinceName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk().
Result(RegionProvinceField_ValueId).
FindInt64Col(0)
}
@@ -104,7 +104,7 @@ func (this *RegionProvinceDAO) CreateProvince(tx *dbs.Tx, countryId int64, name
op.DataId = dataId
op.State = RegionProvinceStateEnabled
codes := []string{name}
var codes = []string{name}
codesJSON, err := json.Marshal(codes)
if err != nil {
return 0, err
@@ -114,7 +114,17 @@ func (this *RegionProvinceDAO) CreateProvince(tx *dbs.Tx, countryId int64, name
if err != nil {
return 0, err
}
return types.Int64(op.Id), nil
var provinceId = types.Int64(op.Id)
err = this.Query(tx).
Pk(provinceId).
Set(RegionProvinceField_ValueId, provinceId).
UpdateQuickly()
if err != nil {
return 0, err
}
return provinceId, nil
}
// FindAllEnabledProvincesWithCountryId 查找某个国家/地区的所有省份
@@ -122,7 +132,7 @@ func (this *RegionProvinceDAO) FindAllEnabledProvincesWithCountryId(tx *dbs.Tx,
_, err = this.Query(tx).
State(RegionProvinceStateEnabled).
Attr("countryId", countryId).
AscPk().
Asc(RegionProvinceField_ValueId).
Slice(&result).
FindAll()
return
@@ -132,7 +142,7 @@ func (this *RegionProvinceDAO) FindAllEnabledProvincesWithCountryId(tx *dbs.Tx,
func (this *RegionProvinceDAO) FindAllEnabledProvinces(tx *dbs.Tx) (result []*RegionProvince, err error) {
_, err = this.Query(tx).
State(RegionProvinceStateEnabled).
AscPk().
Asc(RegionProvinceField_ValueId).
Slice(&result).
FindAll()
return
@@ -149,7 +159,7 @@ func (this *RegionProvinceDAO) UpdateProvinceCustom(tx *dbs.Tx, provinceId int64
}
return this.Query(tx).
Pk(provinceId).
Attr("valueId", provinceId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()

View File

@@ -2,9 +2,22 @@ package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionProvinceField_Id dbs.FieldName = "id" // ID
RegionProvinceField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionProvinceField_CountryId dbs.FieldName = "countryId" // 国家ID
RegionProvinceField_Name dbs.FieldName = "name" // 名称
RegionProvinceField_Codes dbs.FieldName = "codes" // 代号
RegionProvinceField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionProvinceField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionProvinceField_State dbs.FieldName = "state" // 状态
RegionProvinceField_DataId dbs.FieldName = "dataId" // 原始数据ID
)
// RegionProvince 区域-省份
type RegionProvince struct {
Id uint32 `field:"id"` // ID
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
CountryId uint32 `field:"countryId"` // 国家ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
@@ -15,14 +28,15 @@ type RegionProvince struct {
}
type RegionProvinceOperator struct {
Id interface{} // ID
CountryId interface{} // 国家ID
Name interface{} // 名称
Codes interface{} // 代号
CustomName interface{} // 自定义名称
CustomCodes interface{} // 自定义代号
State interface{} // 状态
DataId interface{} // 原始数据ID
Id any // ID
ValueId any // 实际ID
CountryId any // 国家ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
}
func NewRegionProvinceOperator() *RegionProvinceOperator {

View File

@@ -41,7 +41,7 @@ func init() {
// EnableRegionTown 启用条目
func (this *RegionTownDAO) EnableRegionTown(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionTownStateEnabled).
Update()
return err
@@ -50,7 +50,7 @@ func (this *RegionTownDAO) EnableRegionTown(tx *dbs.Tx, id uint32) error {
// DisableRegionTown 禁用条目
func (this *RegionTownDAO) DisableRegionTown(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Set("state", RegionTownStateDisabled).
Update()
return err
@@ -59,7 +59,7 @@ func (this *RegionTownDAO) DisableRegionTown(tx *dbs.Tx, id uint32) error {
// FindEnabledRegionTown 查找启用中的区县
func (this *RegionTownDAO) FindEnabledRegionTown(tx *dbs.Tx, id int64) (*RegionTown, error) {
result, err := this.Query(tx).
Pk(id).
Attr("valueId", id).
Attr("state", RegionTownStateEnabled).
Find()
if result == nil {
@@ -72,7 +72,7 @@ func (this *RegionTownDAO) FindEnabledRegionTown(tx *dbs.Tx, id int64) (*RegionT
func (this *RegionTownDAO) FindAllRegionTowns(tx *dbs.Tx) (result []*RegionTown, err error) {
_, err = this.Query(tx).
State(RegionTownStateEnabled).
AscPk().
Asc(RegionTownField_ValueId).
Slice(&result).
FindAll()
return
@@ -83,7 +83,7 @@ func (this *RegionTownDAO) FindAllRegionTownsWithCityId(tx *dbs.Tx, cityId int64
_, err = this.Query(tx).
State(RegionTownStateEnabled).
Attr("cityId", cityId).
AscPk().
Asc(RegionTownField_ValueId).
Slice(&result).
FindAll()
return
@@ -96,14 +96,14 @@ func (this *RegionTownDAO) FindTownIdWithName(tx *dbs.Tx, cityId int64, townName
Where("(name=:townName OR customName=:townName OR JSON_CONTAINS(codes, :townNameJSON) OR JSON_CONTAINS(customCodes, :townNameJSON))").
Param("townName", townName).
Param("townNameJSON", strconv.Quote(townName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk().
Result(RegionTownField_ValueId).
FindInt64Col(0)
}
// FindRegionTownName 根据主键查找名称
func (this *RegionTownDAO) FindRegionTownName(tx *dbs.Tx, id uint32) (string, error) {
return this.Query(tx).
Pk(id).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
@@ -118,7 +118,7 @@ func (this *RegionTownDAO) UpdateTownCustom(tx *dbs.Tx, townId int64, customName
return err
}
return this.Query(tx).
Pk(townId).
Attr("valueId", townId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()
@@ -176,5 +176,18 @@ func (this *RegionTownDAO) CreateTown(tx *dbs.Tx, cityId int64, townName string)
op.Codes = codes
op.State = RegionTownStateEnabled
return this.SaveInt64(tx, op)
townId, err := this.SaveInt64(tx, op)
if err != nil {
return 0, err
}
err = this.Query(tx).
Pk(townId).
Set(RegionTownField_ValueId, townId).
UpdateQuickly()
if err != nil {
return 0, err
}
return townId, nil
}

View File

@@ -2,9 +2,22 @@ package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionTownField_Id dbs.FieldName = "id" // ID
RegionTownField_ValueId dbs.FieldName = "valueId" // 真实ID
RegionTownField_CityId dbs.FieldName = "cityId" // 城市ID
RegionTownField_Name dbs.FieldName = "name" // 名称
RegionTownField_Codes dbs.FieldName = "codes" // 代号
RegionTownField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionTownField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionTownField_State dbs.FieldName = "state" // 状态
RegionTownField_DataId dbs.FieldName = "dataId" // 原始数据ID
)
// RegionTown 区域-省份
type RegionTown struct {
Id uint32 `field:"id"` // ID
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 真实ID
CityId uint32 `field:"cityId"` // 城市ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
@@ -15,14 +28,15 @@ type RegionTown struct {
}
type RegionTownOperator struct {
Id interface{} // ID
CityId interface{} // 城市ID
Name interface{} // 名称
Codes interface{} // 代号
CustomName interface{} // 自定义名称
CustomCodes interface{} // 自定义代号
State interface{} // 状态
DataId interface{} // 原始数据ID
Id any // ID
ValueId any // 真实ID
CityId any // 城市ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
}
func NewRegionTownOperator() *RegionTownOperator {

View File

@@ -34,7 +34,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedServerBandwidthStatDAO.Clean(nil)
err := SharedServerBandwidthStatDAO.CleanDefaultDays(nil, 100)
if err != nil {
remotelogs.Error("SharedServerBandwidthStatDAO", "clean expired data failed: "+err.Error())
}
@@ -745,9 +745,9 @@ func (this *ServerBandwidthStatDAO) SumDailyStat(tx *dbs.Tx, serverId int64, reg
return
}
// Clean 清理过期数据
func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -100)) // 保留大约3个月的数据
// CleanDays 清理过期数据
func (this *ServerBandwidthStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days)) // 保留大约3个月的数据
return this.runBatch(func(table string, locker *sync.Mutex) error {
_, err := this.Query(tx).
Table(table).
@@ -757,6 +757,22 @@ func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
})
}
func (this *ServerBandwidthStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.ServerBandwidthStat.Clean.Days > 0 {
defaultDays = databaseConfig.ServerBandwidthStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 100
}
return this.CleanDays(tx, defaultDays)
}
// 批量执行
func (this *ServerBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
var locker = &sync.Mutex{}

View File

@@ -72,11 +72,11 @@ func TestServerBandwidthStatDAO_FindAllServerStatsWithDay(t *testing.T) {
}
}
func TestServerBandwidthStatDAO_Clean(t *testing.T) {
func TestServerBandwidthStatDAO_CleanDays(t *testing.T) {
var dao = models.NewServerBandwidthStatDAO()
var tx *dbs.Tx
var before = time.Now()
err := dao.Clean(tx)
err := dao.CleanDays(tx, 100)
if err != nil {
t.Fatal(err)
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
"regexp"
"sort"
"strings"
"time"
)
@@ -28,7 +29,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedServerDailyStatDAO.Clean(nil, 60) // 只保留 N 天,时间需要长一些,因为需要用来生成账单
err := SharedServerDailyStatDAO.CleanDefaultDays(nil, 60) // 只保留 N 天,时间需要长一些,因为需要用来生成账单
if err != nil {
logs.Println("ServerDailyStatDAO", "clean expired data failed: "+err.Error())
}
@@ -513,7 +514,8 @@ func (this *ServerDailyStatDAO) FindStatsWithDay(tx *dbs.Tx, serverId int64, day
Result("SUM(bytes) AS bytes", "SUM(cachedBytes) AS cachedBytes", "SUM(countRequests) AS countRequests", "SUM(countCachedRequests) AS countCachedRequests", "SUM(countAttackRequests) AS countAttackRequests", "SUM(attackBytes) AS attackBytes", "day", "timeFrom", "MIN(timeTo) AS timeTo").
Attr("serverId", serverId).
Attr("day", day).
Group("day").Group("timeFrom", dbs.QueryOrderDesc)
Group("day").
Group("timeFrom")
if len(timeFrom) > 0 {
query.Gte("timeFrom", timeFrom)
@@ -530,6 +532,11 @@ func (this *ServerDailyStatDAO) FindStatsWithDay(tx *dbs.Tx, serverId int64, day
return nil, err
}
// sort results
sort.Slice(result, func(i, j int) bool {
return result[i].TimeFrom < result[j].TimeFrom
})
return
}
@@ -673,8 +680,8 @@ func (this *ServerDailyStatDAO) compatFindHourlyStats(tx *dbs.Tx, serverId int64
result = append(result, stat)
} else {
result = append(result, &ServerDailyStat{
Hour: hour,
Day: hour[:8],
Hour: hour,
Day: hour[:8],
TimeFrom: hour[8:] + "00",
})
}
@@ -742,11 +749,27 @@ func (this *ServerDailyStatDAO) UpdateStatFee(tx *dbs.Tx, statId int64, fee floa
UpdateQuickly()
}
// Clean 清理历史数据
func (this *ServerDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理历史数据
func (this *ServerDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
_, err := this.Query(tx).
Lt("day", day).
Delete()
return err
}
func (this *ServerDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.ServerDailyStat.Clean.Days > 0 {
defaultDays = databaseConfig.ServerDailyStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 60
}
return this.CleanDays(tx, defaultDays)
}

View File

@@ -140,6 +140,6 @@ func TestServerDailyStatDAO_FindStatsWithDay(t *testing.T) {
t.Fatal(err)
}
for _, stat := range stats {
t.Log(stat.TimeFrom, stat.TimeTo, stat.Bytes)
t.Log(stat.Day, stat.TimeFrom, stat.TimeTo, stat.Bytes)
}
}

View File

@@ -354,6 +354,9 @@ func (this *ServerDAO) UpdateServerBasic(tx *dbs.Tx, serverId int64, name string
// UpdateServerGroupIds 修改服务所在分组
func (this *ServerDAO) UpdateServerGroupIds(tx *dbs.Tx, serverId int64, groupIds []int64) error {
if serverId <= 0 {
return errors.New("serverId should not be smaller than 0")
}
if groupIds == nil {
groupIds = []int64{}
}
@@ -390,6 +393,10 @@ func (this *ServerDAO) UpdateUserServerBasic(tx *dbs.Tx, serverId int64, name st
// UpdateServerIsOn 修复服务是否启用
func (this *ServerDAO) UpdateServerIsOn(tx *dbs.Tx, serverId int64, isOn bool) error {
if serverId <= 0 {
return errors.New("serverId should not be smaller than 0")
}
_, err := this.Query(tx).
Pk(serverId).
Set("isOn", isOn).
@@ -896,6 +903,22 @@ func (this *ServerDAO) ListEnabledServersMatch(tx *dbs.Tx, offset int64, size in
query.Desc("IF(FIND_IN_SET(bandwidthTime, :times), bandwidthBytes, 0)")
query.Param("times", strings.Join(times, ","))
query.DescPk()
case "requestsAsc":
query.Asc("IF(FIND_IN_SET(bandwidthTime, :times), countRequests, 0)")
query.Param("times", strings.Join(times, ","))
query.DescPk()
case "requestsDesc":
query.Desc("IF(FIND_IN_SET(bandwidthTime, :times), countRequests, 0)")
query.Param("times", strings.Join(times, ","))
query.DescPk()
case "attackRequestsAsc":
query.Asc("IF(FIND_IN_SET(bandwidthTime, :times), countAttackRequests, 0)")
query.Param("times", strings.Join(times, ","))
query.DescPk()
case "attackRequestsDesc":
query.Desc("IF(FIND_IN_SET(bandwidthTime, :times), countAttackRequests, 0)")
query.Param("times", strings.Join(times, ","))
query.DescPk()
default:
query.DescPk()
}
@@ -906,6 +929,8 @@ func (this *ServerDAO) ListEnabledServersMatch(tx *dbs.Tx, offset int64, size in
for _, server := range result {
if len(server.BandwidthTime) > 0 && !lists.ContainsString(times, server.BandwidthTime) {
server.BandwidthBytes = 0
server.CountRequests = 0
server.CountAttackRequests = 0
}
}
@@ -2153,6 +2178,10 @@ func (this *ServerDAO) FindFirstHTTPOrHTTPSPortWithClusterId(tx *dbs.Tx, cluster
// NotifyServerPortsUpdate 通知服务端口变化
func (this *ServerDAO) NotifyServerPortsUpdate(tx *dbs.Tx, serverId int64) error {
if serverId <= 0 {
return nil
}
one, err := this.Query(tx).
Pk(serverId).
Result("tcp", "tls", "udp", "http", "https").
@@ -2480,6 +2509,10 @@ func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitCo
// IncreaseServerTotalTraffic 增加服务的总流量
func (this *ServerDAO) IncreaseServerTotalTraffic(tx *dbs.Tx, serverId int64, bytes int64) error {
if serverId <= 0 {
return errors.New("serverId should not be smaller than 0")
}
var gb = float64(bytes) / (1 << 30)
var day = timeutil.Format("Ymd")
var month = timeutil.Format("Ym")
@@ -2539,6 +2572,10 @@ func (this *ServerDAO) UpdateServersClusterIdWithPlanId(tx *dbs.Tx, planId int64
// UpdateServerUserPlanId 设置服务所属套餐
func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPlanId int64) error {
if serverId <= 0 {
return errors.New("serverId should not be smaller than 0")
}
oldClusterId, err := this.Query(tx).
Pk(serverId).
Result("clusterId").
@@ -2646,6 +2683,10 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
// FindServerLastUserPlanIdAndUserId 查找最后使用的套餐
func (this *ServerDAO) FindServerLastUserPlanIdAndUserId(tx *dbs.Tx, serverId int64) (userPlanId int64, userId int64, err error) {
if serverId <= 0 {
return 0, 0, errors.New("serverId should not be smaller than 0")
}
one, err := this.Query(tx).
Pk(serverId).
Result("lastUserPlanId", "userId").
@@ -2659,6 +2700,10 @@ func (this *ServerDAO) FindServerLastUserPlanIdAndUserId(tx *dbs.Tx, serverId in
// UpdateServerUAM 开启UAM
func (this *ServerDAO) UpdateServerUAM(tx *dbs.Tx, serverId int64, uamConfig *serverconfigs.UAMConfig) error {
if serverId <= 0 {
return errors.New("serverId should not be smaller than 0")
}
if uamConfig == nil {
return nil
}
@@ -2710,7 +2755,7 @@ func (this *ServerDAO) FindUserServerClusterIds(tx *dbs.Tx, userId int64) ([]int
// UpdateServerBandwidth 更新服务带宽
// fullTime YYYYMMDDHHII
func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTime string, bandwidthBytes int64) error {
func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTime string, bandwidthBytes int64, countRequests int64, countAttackRequests int64) error {
if serverId <= 0 {
return nil
}
@@ -2731,13 +2776,19 @@ func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTim
Pk(serverId).
Set("bandwidthTime", fullTime).
Set("bandwidthBytes", bandwidthBytes).
Set("countRequests", countRequests).
Set("countAttackRequests", countAttackRequests).
UpdateQuickly()
} else {
return this.Query(tx).
Pk(serverId).
Set("bandwidthTime", fullTime).
Set("bandwidthBytes", dbs.SQL("bandwidthBytes+:bytes")).
Set("countRequests", dbs.SQL("countRequests+:countRequests")).
Set("countAttackRequests", dbs.SQL("countAttackRequests+:countAttackRequests")).
Param("bytes", bandwidthBytes).
Param("countRequests", countRequests).
Param("countAttackRequests", countAttackRequests).
UpdateQuickly()
}
}
@@ -2832,6 +2883,10 @@ func (this *ServerDAO) FindEnabledServersWithIds(tx *dbs.Tx, serverIds []int64)
// NotifyUpdate 同步服务所在的集群
func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
if serverId <= 0 {
return nil
}
// 创建任务
clusterId, err := this.FindServerClusterId(tx, serverId)
if err != nil {
@@ -2845,6 +2900,9 @@ func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
// NotifyClusterUpdate 同步指定的集群
func (this *ServerDAO) NotifyClusterUpdate(tx *dbs.Tx, clusterId, serverId int64) error {
if serverId <= 0 {
return nil
}
if clusterId <= 0 {
return nil
}
@@ -2853,6 +2911,10 @@ func (this *ServerDAO) NotifyClusterUpdate(tx *dbs.Tx, clusterId, serverId int64
// NotifyDNSUpdate 通知当前集群DNS更新
func (this *ServerDAO) NotifyDNSUpdate(tx *dbs.Tx, serverId int64) error {
if serverId <= 0 {
return nil
}
clusterId, err := this.Query(tx).
Pk(serverId).
Result("clusterId").
@@ -2878,6 +2940,10 @@ func (this *ServerDAO) NotifyDNSUpdate(tx *dbs.Tx, serverId int64) error {
// NotifyClusterDNSUpdate 通知某个集群中的DNS更新
func (this *ServerDAO) NotifyClusterDNSUpdate(tx *dbs.Tx, clusterId int64, serverId int64) error {
if serverId <= 0 {
return nil
}
dnsInfo, err := SharedNodeClusterDAO.FindClusterDNSInfo(tx, clusterId, nil)
if err != nil {
return err
@@ -2893,6 +2959,10 @@ func (this *ServerDAO) NotifyClusterDNSUpdate(tx *dbs.Tx, clusterId int64, serve
// NotifyDisable 通知禁用
func (this *ServerDAO) NotifyDisable(tx *dbs.Tx, serverId int64) error {
if serverId <= 0 {
return nil
}
// 禁用缓存策略相关的内容
policyIds, err := SharedHTTPFirewallPolicyDAO.FindFirewallPolicyIdsWithServerId(tx, serverId)
if err != nil {

View File

@@ -229,7 +229,7 @@ func TestServerDAO_FindEnabledServerWithDomain(t *testing.T) {
for _, domain := range []string{"a", "a.com", "teaos.cn", "www.teaos.cn", "cdn.teaos.cn", "google.com"} {
var before = time.Now()
server, err := dao.FindEnabledServerWithDomain(tx, domain)
server, err := dao.FindEnabledServerWithDomain(tx, 0, domain)
var costMs = time.Since(before).Seconds() * 1000
if err != nil {
t.Fatal(err)
@@ -326,7 +326,7 @@ func TestServerDAO_FindBool(t *testing.T) {
func TestServerDAO_UpdateServerBandwidth(t *testing.T) {
var dao = models.NewServerDAO()
var tx *dbs.Tx
err := dao.UpdateServerBandwidth(tx, 1, timeutil.FormatTime("YmdHi", time.Now().Unix()/300*300), 1024)
err := dao.UpdateServerBandwidth(tx, 1, timeutil.FormatTime("YmdHi", time.Now().Unix()/300*300), 1024, 1, 0)
if err != nil {
t.Fatal(err)
}

View File

@@ -2,6 +2,57 @@ package models
import "github.com/iwind/TeaGo/dbs"
const (
ServerField_Id dbs.FieldName = "id" // ID
ServerField_IsOn dbs.FieldName = "isOn" // 是否启用
ServerField_UserId dbs.FieldName = "userId" // 用户ID
ServerField_AdminId dbs.FieldName = "adminId" // 管理员ID
ServerField_Type dbs.FieldName = "type" // 服务类型
ServerField_Name dbs.FieldName = "name" // 名称
ServerField_Description dbs.FieldName = "description" // 描述
ServerField_PlainServerNames dbs.FieldName = "plainServerNames" // 扁平化域名列表
ServerField_ServerNames dbs.FieldName = "serverNames" // 域名列表
ServerField_AuditingAt dbs.FieldName = "auditingAt" // 审核提交时间
ServerField_AuditingServerNames dbs.FieldName = "auditingServerNames" // 审核中的域名
ServerField_IsAuditing dbs.FieldName = "isAuditing" // 是否正在审核
ServerField_AuditingResult dbs.FieldName = "auditingResult" // 审核结果
ServerField_Http dbs.FieldName = "http" // HTTP配置
ServerField_Https dbs.FieldName = "https" // HTTPS配置
ServerField_Tcp dbs.FieldName = "tcp" // TCP配置
ServerField_Tls dbs.FieldName = "tls" // TLS配置
ServerField_Unix dbs.FieldName = "unix" // Unix配置
ServerField_Udp dbs.FieldName = "udp" // UDP配置
ServerField_WebId dbs.FieldName = "webId" // WEB配置
ServerField_ReverseProxy dbs.FieldName = "reverseProxy" // 反向代理配置
ServerField_GroupIds dbs.FieldName = "groupIds" // 分组ID列表
ServerField_Config dbs.FieldName = "config" // 服务配置,自动生成
ServerField_ConfigMd5 dbs.FieldName = "configMd5" // Md5
ServerField_ClusterId dbs.FieldName = "clusterId" // 集群ID
ServerField_IncludeNodes dbs.FieldName = "includeNodes" // 部署条件
ServerField_ExcludeNodes dbs.FieldName = "excludeNodes" // 节点排除条件
ServerField_Version dbs.FieldName = "version" // 版本号
ServerField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
ServerField_State dbs.FieldName = "state" // 状态
ServerField_DnsName dbs.FieldName = "dnsName" // DNS名称
ServerField_TcpPorts dbs.FieldName = "tcpPorts" // 所包含TCP端口
ServerField_UdpPorts dbs.FieldName = "udpPorts" // 所包含UDP端口
ServerField_SupportCNAME dbs.FieldName = "supportCNAME" // 允许CNAME不在域名名单
ServerField_TrafficLimit dbs.FieldName = "trafficLimit" // 流量限制
ServerField_TrafficDay dbs.FieldName = "trafficDay" // YYYYMMDD
ServerField_TrafficMonth dbs.FieldName = "trafficMonth" // YYYYMM
ServerField_TotalDailyTraffic dbs.FieldName = "totalDailyTraffic" // 日流量
ServerField_TotalMonthlyTraffic dbs.FieldName = "totalMonthlyTraffic" // 月流量
ServerField_TrafficLimitStatus dbs.FieldName = "trafficLimitStatus" // 流量限制状态
ServerField_TotalTraffic dbs.FieldName = "totalTraffic" // 总流量
ServerField_UserPlanId dbs.FieldName = "userPlanId" // 所属套餐ID
ServerField_LastUserPlanId dbs.FieldName = "lastUserPlanId" // 上一次使用的套餐
ServerField_Uam dbs.FieldName = "uam" // UAM设置
ServerField_BandwidthTime dbs.FieldName = "bandwidthTime" // 带宽更新时间YYYYMMDDHHII
ServerField_BandwidthBytes dbs.FieldName = "bandwidthBytes" // 最近带宽峰值
ServerField_CountAttackRequests dbs.FieldName = "countAttackRequests" // 最近攻击请求数
ServerField_CountRequests dbs.FieldName = "countRequests" // 最近总请求数
)
// Server 服务
type Server struct {
Id uint32 `field:"id"` // ID
@@ -50,6 +101,8 @@ type Server struct {
Uam dbs.JSON `field:"uam"` // UAM设置
BandwidthTime string `field:"bandwidthTime"` // 带宽更新时间YYYYMMDDHHII
BandwidthBytes uint64 `field:"bandwidthBytes"` // 最近带宽峰值
CountAttackRequests uint64 `field:"countAttackRequests"` // 最近攻击请求数
CountRequests uint64 `field:"countRequests"` // 最近总请求数
}
type ServerOperator struct {
@@ -99,6 +152,8 @@ type ServerOperator struct {
Uam any // UAM设置
BandwidthTime any // 带宽更新时间YYYYMMDDHHII
BandwidthBytes any // 最近带宽峰值
CountAttackRequests any // 最近攻击请求数
CountRequests any // 最近总请求数
}
func NewServerOperator() *ServerOperator {

View File

@@ -100,7 +100,8 @@ func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, ignore
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn
config.ClientAuthType = int(policy.ClientAuthType)
config.HTTP2Enabled = policy.Http2Enabled == 1
config.HTTP2Enabled = policy.Http2Enabled
config.HTTP3Enabled = policy.Http3Enabled
config.MinVersion = policy.MinVersion
// certs
@@ -200,7 +201,7 @@ func (this *SSLPolicyDAO) FindAllEnabledPolicyIdsWithCertId(tx *dbs.Tx, certId i
}
// CreatePolicy 创建Policy
func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) (int64, error) {
func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64, http2Enabled bool, http3Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) (int64, error) {
var op = NewSSLPolicyOperator()
op.State = SSLPolicyStateEnabled
op.IsOn = true
@@ -208,6 +209,7 @@ func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64,
op.UserId = userId
op.Http2Enabled = http2Enabled
op.Http3Enabled = http3Enabled
op.MinVersion = minVersion
if len(certsJSON) > 0 {
@@ -240,7 +242,7 @@ func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64,
}
// UpdatePolicy 修改Policy
func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) error {
func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled bool, http3Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) error {
if policyId <= 0 {
return errors.New("invalid policyId")
}
@@ -248,6 +250,7 @@ func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled
var op = NewSSLPolicyOperator()
op.Id = policyId
op.Http2Enabled = http2Enabled
op.Http3Enabled = http3Enabled
op.MinVersion = minVersion
if len(certsJSON) > 0 {

View File

@@ -7,7 +7,7 @@ type SSLPolicy struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
IsOn bool `field:"isOn"` // 是否启用
Certs dbs.JSON `field:"certs"` // 证书列表
ClientCACerts dbs.JSON `field:"clientCACerts"` // 客户端证书
ClientAuthType uint32 `field:"clientAuthType"` // 客户端认证类型
@@ -15,28 +15,30 @@ type SSLPolicy struct {
CipherSuitesIsOn uint8 `field:"cipherSuitesIsOn"` // 是否自定义加密算法套件
CipherSuites dbs.JSON `field:"cipherSuites"` // 加密算法套件
Hsts dbs.JSON `field:"hsts"` // HSTS设置
Http2Enabled uint8 `field:"http2Enabled"` // 是否启用HTTP/2
Http2Enabled bool `field:"http2Enabled"` // 是否启用HTTP/2
Http3Enabled bool `field:"http3Enabled"` // 是否启用HTTP/3
OcspIsOn uint8 `field:"ocspIsOn"` // 是否启用OCSP
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
}
type SSLPolicyOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
IsOn interface{} // 是否启用
Certs interface{} // 证书列表
ClientCACerts interface{} // 客户端证书
ClientAuthType interface{} // 客户端认证类型
MinVersion interface{} // 支持的SSL最小版本
CipherSuitesIsOn interface{} // 是否自定义加密算法套件
CipherSuites interface{} // 加密算法套件
Hsts interface{} // HSTS设置
Http2Enabled interface{} // 是否启用HTTP/2
OcspIsOn interface{} // 是否启用OCSP
State interface{} // 状态
CreatedAt interface{} // 创建时间
Id any // ID
AdminId any // 管理员ID
UserId any // 用户ID
IsOn any // 是否启用
Certs any // 证书列表
ClientCACerts any // 客户端证书
ClientAuthType any // 客户端认证类型
MinVersion any // 支持的SSL最小版本
CipherSuitesIsOn any // 是否自定义加密算法套件
CipherSuites any // 加密算法套件
Hsts any // HSTS设置
Http2Enabled any // 是否启用HTTP/2
Http3Enabled any // 是否启用HTTP/3
OcspIsOn any // 是否启用OCSP
State any // 状态
CreatedAt any // 创建时间
}
func NewSSLPolicyOperator() *SSLPolicyOperator {

View File

@@ -1,6 +1,7 @@
package stats
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
@@ -22,7 +23,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedNodeClusterTrafficDailyStatDAO.Clean(nil, 30) // 只保留N天
err := SharedNodeClusterTrafficDailyStatDAO.CleanDefaultDays(nil, 30) // 只保留N天
if err != nil {
remotelogs.Error("NodeClusterTrafficDailyStatDAO", "clean expired data failed: "+err.Error())
}
@@ -128,11 +129,27 @@ func (this *NodeClusterTrafficDailyStatDAO) SumDailyStat(tx *dbs.Tx, clusterId i
return one.(*NodeClusterTrafficDailyStat), nil
}
// Clean 清理历史数据
func (this *NodeClusterTrafficDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理历史数据
func (this *NodeClusterTrafficDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
_, err := this.Query(tx).
Lt("day", day).
Delete()
return err
}
func (this *NodeClusterTrafficDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.NodeClusterTrafficDailyStat.Clean.Days > 0 {
defaultDays = databaseConfig.NodeClusterTrafficDailyStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 30
}
return this.CleanDays(tx, defaultDays)
}

View File

@@ -1,6 +1,7 @@
package stats
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
@@ -22,7 +23,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedNodeTrafficHourlyStatDAO.Clean(nil, 15) // 只保留N天
err := SharedNodeTrafficHourlyStatDAO.CleanDefaultDays(nil, 15) // 只保留N天
if err != nil {
remotelogs.Error("NodeTrafficHourlyStatDAO", "clean expired data failed: "+err.Error())
}
@@ -197,11 +198,27 @@ func (this *NodeTrafficHourlyStatDAO) FindHourlyStatsWithNodeId(tx *dbs.Tx, role
return result, nil
}
// Clean 清理历史数据
func (this *NodeTrafficHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理历史数据
func (this *NodeTrafficHourlyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
_, err := this.Query(tx).
Lt("hour", hour).
Delete()
return err
}
func (this *NodeTrafficHourlyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.NodeTrafficHourlyStat.Clean.Days > 0 {
defaultDays = databaseConfig.NodeTrafficHourlyStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 15
}
return this.CleanDays(tx, defaultDays)
}

View File

@@ -1,6 +1,7 @@
package stats
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
@@ -25,7 +26,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedServerDomainHourlyStatDAO.Clean(nil, 7) // 只保留 N 天
err := SharedServerDomainHourlyStatDAO.CleanDefaultDays(nil, 7) // 只保留 N 天
if err != nil {
remotelogs.Error("ServerDomainHourlyStatDAO", "clean expired data failed: "+err.Error())
}
@@ -366,8 +367,8 @@ func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithServerId(tx *dbs.Tx
return
}
// Clean 清理历史数据
func (this *ServerDomainHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理历史数据
func (this *ServerDomainHourlyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
for _, table := range this.FindAllPartitionTables() {
_, err := this.Query(tx).
@@ -380,3 +381,19 @@ func (this *ServerDomainHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
}
return nil
}
func (this *ServerDomainHourlyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.ServerDomainHourlyStat.Clean.Days > 0 {
defaultDays = databaseConfig.ServerDomainHourlyStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 7
}
return this.CleanDays(tx, defaultDays)
}

View File

@@ -1,6 +1,7 @@
package stats
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
@@ -22,7 +23,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedTrafficDailyStatDAO.Clean(nil, 30) // 只保留N天
err := SharedTrafficDailyStatDAO.CleanDefaultDays(nil, 30) // 只保留N天
if err != nil {
remotelogs.Error("TrafficDailyStatDAO", "clean expired data failed: "+err.Error())
}
@@ -124,11 +125,27 @@ func (this *TrafficDailyStatDAO) FindDailyStat(tx *dbs.Tx, day string) (*Traffic
return one.(*TrafficDailyStat), nil
}
// Clean 清理历史数据
func (this *TrafficDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理历史数据
func (this *TrafficDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
_, err := this.Query(tx).
Lt("day", day).
Delete()
return err
}
func (this *TrafficDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.TrafficDailyStat.Clean.Days > 0 {
defaultDays = databaseConfig.TrafficDailyStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 30
}
return this.CleanDays(tx, defaultDays)
}

View File

@@ -1,6 +1,7 @@
package stats
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/goman"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
@@ -22,7 +23,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedTrafficHourlyStatDAO.Clean(nil, 15) // 只保留N天
err := SharedTrafficHourlyStatDAO.CleanDefaultDays(nil, 15) // 只保留N天
if err != nil {
remotelogs.Error("TrafficHourlyStatDAO", "clean expired data failed: "+err.Error())
}
@@ -137,11 +138,27 @@ func (this *TrafficHourlyStatDAO) SumHourlyStats(tx *dbs.Tx, hourFrom string, ho
return one.(*TrafficHourlyStat), nil
}
// Clean 清理历史数据
func (this *TrafficHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
// CleanDays 清理历史数据
func (this *TrafficHourlyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
_, err := this.Query(tx).
Lt("hour", hour).
Delete()
return err
}
func (this *TrafficHourlyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.TrafficHourlyStat.Clean.Days > 0 {
defaultDays = databaseConfig.TrafficHourlyStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 15
}
return this.CleanDays(tx, defaultDays)
}

View File

@@ -1,11 +1,13 @@
package models
import (
"errors"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"strings"
"time"
)
@@ -64,7 +66,7 @@ func (this *SysLockerDAO) Lock(tx *dbs.Tx, key string, timeout int64) (ok bool,
}
// 如果已经有锁
locker := one.(*SysLocker)
var locker = one.(*SysLocker)
if time.Now().Unix() <= int64(locker.TimeoutAt) {
return false, nil
}
@@ -95,7 +97,7 @@ func (this *SysLockerDAO) Lock(tx *dbs.Tx, key string, timeout int64) (ok bool,
}
continue
}
if types.Int64(version) != int64(locker.Version)+1 {
if types.Int64(version) > int64(locker.Version)+1 {
return false, nil
}
@@ -112,11 +114,38 @@ func (this *SysLockerDAO) Unlock(tx *dbs.Tx, key string) error {
return err
}
const sysLockerStep = 8
var increment = NewSysLockerIncrement(sysLockerStep)
// Increase 增加版本号
func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (int64, error) {
// validate key
if strings.Contains(key, "'") {
return 0, errors.New("invalid key '" + key + "'")
}
if tx == nil {
var result int64
var err error
{
colValue, err := this.Query(tx).
Result("version").
Attr("key", key).
FindInt64Col(0)
if err != nil {
return 0, err
}
var lastVersion = types.Int64(colValue)
if lastVersion <= increment.MaxValue(key) {
value, ok := increment.Pop(key)
if ok {
return value, nil
}
}
}
err = this.Instance.RunTx(func(tx *dbs.Tx) error {
result, err = this.Increase(tx, key, defaultValue)
if err != nil {
@@ -126,7 +155,26 @@ func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (
})
return result, err
}
err := this.Query(tx).
// combine statements to make increasing faster
colValue, err := tx.FindCol(0, "INSERT INTO `"+this.Table+"` (`key`, `version`) VALUES ('"+key+"', "+types.String(defaultValue+sysLockerStep)+") ON DUPLICATE KEY UPDATE `version`=`version`+"+types.String(sysLockerStep)+"; SELECT `version` FROM `"+this.Table+"` WHERE `key`='"+key+"'")
if err != nil {
if CheckSQLErrCode(err, 1064 /** syntax error **/) {
// continue to use seperated query
err = nil
} else {
return 0, err
}
} else {
var maxVersion = types.Int64(colValue)
var minVersion = maxVersion - sysLockerStep + 1
increment.Push(key, minVersion+1, maxVersion)
return minVersion, nil
}
err = this.Query(tx).
Reuse(false). // no need to prepare statement in every transaction
InsertOrUpdateQuickly(maps.Map{
"key": key,
"version": defaultValue,
@@ -137,16 +185,16 @@ func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (
return 0, err
}
return this.Query(tx).
Reuse(false). // no need to prepare statement in every transaction
Attr("key", key).
Result("version").
FindInt64Col(0)
}
// 读取当前版本号
func (this *SysLockerDAO) Read(tx *dbs.Tx, key string) (int64, error) {
return this.Query(tx).
Attr("key", key).
Result("version").
FindInt64Col(0)
}
}

View File

@@ -3,44 +3,190 @@ package models
import (
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types"
"sync"
"testing"
"time"
)
func TestSysLockerDAO_Lock(t *testing.T) {
var tx *dbs.Tx
isOk, err := SharedSysLockerDAO.Lock(tx, "test", 600)
var dao = NewSysLockerDAO()
isOk, err := dao.Lock(tx, "test", 600)
if err != nil {
t.Fatal(err)
}
t.Log(isOk)
if isOk {
err = SharedSysLockerDAO.Unlock(tx, "test")
err = dao.Unlock(tx, "test")
if err != nil {
t.Fatal(err)
}
}
}
func TestSysLocker_Increase_SQL(t *testing.T) {
var dao = NewSysLockerDAO()
value, err := dao.Read(nil, "hello")
if err != nil {
t.Fatal(err)
}
t.Log("before:", value)
v, err := dao.Increase(nil, "hello", 0)
if err != nil {
t.Log("err:", err)
return
}
t.Log("after:", v)
}
func TestSysLocker_Increase_New_Key(t *testing.T) {
var key = "KEY" + types.String(time.Now().Unix())
var dao = NewSysLockerDAO()
value, err := dao.Read(nil, key)
if err != nil {
t.Fatal(err)
}
t.Log("before:", value)
for i := 0; i < 2; i++ {
v, err := dao.Increase(nil, key, 0)
if err != nil {
t.Log("err:", err)
return
}
t.Log("after:", v)
}
}
func TestSysLocker_Increase_Cache(t *testing.T) {
var dao = NewSysLockerDAO()
for i := 0; i < 11; i++ {
v, err := dao.Increase(nil, "hello", 0)
if err != nil {
t.Log("err:", err)
return
}
t.Log("hello", i, "after:", v)
}
for i := 0; i < 11; i++ {
v, err := dao.Increase(nil, "hello2", 0)
if err != nil {
t.Log("err:", err)
return
}
t.Log("hello2", i, "after:", v)
}
}
func TestSysLocker_Increase(t *testing.T) {
count := 100
wg := sync.WaitGroup{}
dbs.NotifyReady()
var dao = NewSysLockerDAO()
dao.Instance.Raw().SetMaxOpenConns(64)
var count = 1000
value, err := dao.Read(nil, "hello")
if err != nil {
t.Fatal(err)
}
t.Log("before", value)
var locker = sync.Mutex{}
var allValueMap = map[int64]bool{}
var before = time.Now()
var wg = sync.WaitGroup{}
wg.Add(count)
for i := 0; i < count; i++ {
go func() {
go func(i int) {
defer wg.Done()
v, err := NewSysLockerDAO().Increase(nil, "hello", 0)
var key = "hello"
v, err := dao.Increase(nil, key, 0)
if err != nil {
t.Log("err:", err)
return
}
t.Log("v:", v)
}()
locker.Lock()
if allValueMap[v] {
t.Log("duplicated:", v)
} else {
allValueMap[v] = true
}
locker.Unlock()
//t.Log("v:", v)
_ = v
}(i)
}
wg.Wait()
t.Log("ok")
t.Log("cost:", time.Since(before).Seconds()*1000, "ms")
value, err = dao.Read(nil, "hello")
if err != nil {
t.Fatal(err)
}
t.Log("after", value, "values:", len(allValueMap))
}
func TestSysLocker_Increase_Performance(t *testing.T) {
dbs.NotifyReady()
var count = 1000
var dao = NewSysLockerDAO()
var before = time.Now()
var wg = sync.WaitGroup{}
wg.Add(count)
for i := 0; i < count; i++ {
go func(i int) {
defer wg.Done()
var key = "hello" + types.String(i%10)
v, err := dao.Increase(nil, key, 0)
if err != nil {
t.Log("err:", err)
return
}
//t.Log("v:", v)
_ = v
}(i)
}
wg.Wait()
t.Log("cost:", time.Since(before).Seconds()*1000, "ms")
}
func BenchmarkSysLockerDAO_Increase(b *testing.B) {
var dao = NewSysLockerDAO()
dao.Instance.Raw().SetMaxOpenConns(64)
_, _ = dao.Increase(nil, "hello", 0)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := dao.Increase(nil, "hello", 0)
if err != nil {
b.Fatal(err)
}
}
})
}

View File

@@ -0,0 +1,110 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package models
import (
"sync"
)
type SysLockerIncrementItem struct {
size int
c chan int64
maxValue int64
}
func NewSysLockerIncrementItem(size int) *SysLockerIncrementItem {
if size <= 0 {
size = 10
}
return &SysLockerIncrementItem{
size: size,
c: make(chan int64, size),
}
}
func (this *SysLockerIncrementItem) Pop() (result int64, ok bool) {
select {
case v := <-this.c:
result = v
ok = true
return
default:
return
}
}
func (this *SysLockerIncrementItem) Push(value int64) {
if this.maxValue < value {
this.maxValue = value
}
select {
case this.c <- value:
default:
}
}
func (this *SysLockerIncrementItem) Reset() {
close(this.c)
this.c = make(chan int64, this.size)
}
func (this *SysLockerIncrementItem) MaxValue() int64 {
return this.maxValue
}
type SysLockerIncrement struct {
itemMap map[string]*SysLockerIncrementItem // key => item
size int
locker sync.RWMutex
}
func NewSysLockerIncrement(size int) *SysLockerIncrement {
if size <= 0 {
size = 10
}
return &SysLockerIncrement{
itemMap: map[string]*SysLockerIncrementItem{},
size: size,
}
}
func (this *SysLockerIncrement) Pop(key string) (result int64, ok bool) {
this.locker.Lock()
defer this.locker.Unlock()
item, itemOk := this.itemMap[key]
if itemOk {
result, ok = item.Pop()
}
return
}
func (this *SysLockerIncrement) Push(key string, minValue int64, maxValue int64) {
this.locker.Lock()
defer this.locker.Unlock()
item, itemOk := this.itemMap[key]
if itemOk {
item.Reset()
} else {
item = NewSysLockerIncrementItem(this.size)
this.itemMap[key] = item
}
for i := minValue; i <= maxValue; i++ {
item.Push(i)
}
}
func (this *SysLockerIncrement) MaxValue(key string) int64 {
this.locker.RLock()
defer this.locker.RUnlock()
item, itemOk := this.itemMap[key]
if itemOk {
return item.MaxValue()
}
return 0
}

View File

@@ -0,0 +1,23 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package models_test
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"testing"
)
func TestNewSysLockerIncrement(t *testing.T) {
var increment = models.NewSysLockerIncrement(10)
increment.Push("key", 1, 10)
t.Log(increment.MaxValue("key"))
for i := 0; i < 11; i++ {
result, value := increment.Pop("key")
t.Log(i, "=>", result, value)
}
for i := 0; i < 11; i++ {
result, value := increment.Pop("key1")
t.Log(i, "=>", result, value)
}
}

View File

@@ -262,3 +262,20 @@ func (this *SysSettingDAO) ReadUserRegisterConfig(tx *dbs.Tx) (*userconfigs.User
}
return config, nil
}
func (this *SysSettingDAO) ReadDatabaseConfig(tx *dbs.Tx) (config *systemconfigs.DatabaseConfig, err error) {
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeDatabaseConfigSetting)
if err != nil {
return nil, err
}
if len(valueJSON) == 0 {
return systemconfigs.NewDatabaseConfig(), nil
}
config = systemconfigs.NewDatabaseConfig()
err = json.Unmarshal(valueJSON, config)
if err != nil {
return nil, err
}
return config, nil
}

View File

@@ -36,7 +36,7 @@ func init() {
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
goman.New(func() {
for range ticker.C {
err := SharedUserBandwidthStatDAO.Clean(nil)
err := SharedUserBandwidthStatDAO.CleanDefaultDays(nil, 100)
if err != nil {
remotelogs.Error("SharedUserBandwidthStatDAO", "clean expired data failed: "+err.Error())
}
@@ -460,9 +460,9 @@ func (this *UserBandwidthStatDAO) SumDailyStat(tx *dbs.Tx, userId int64, regionI
return
}
// Clean 清理过期数据
func (this *UserBandwidthStatDAO) Clean(tx *dbs.Tx) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -100)) // 保留大约3个月的数据
// CleanDays 清理过期数据
func (this *UserBandwidthStatDAO) CleanDays(tx *dbs.Tx, days int) error {
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days)) // 保留大约3个月的数据
return this.runBatch(func(table string, locker *sync.Mutex) error {
_, err := this.Query(tx).
Table(table).
@@ -472,6 +472,22 @@ func (this *UserBandwidthStatDAO) Clean(tx *dbs.Tx) error {
})
}
func (this *UserBandwidthStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
if err != nil {
return err
}
if databaseConfig != nil && databaseConfig.UserBandwidthStat.Clean.Days > 0 {
defaultDays = databaseConfig.UserBandwidthStat.Clean.Days
}
if defaultDays <= 0 {
defaultDays = 100
}
return this.CleanDays(tx, defaultDays)
}
// 批量执行
func (this *UserBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
var locker = &sync.Mutex{}

View File

@@ -57,10 +57,10 @@ func TestUserBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
t.Log("ok")
}
func TestUserBandwidthStatDAO_Clean(t *testing.T) {
func TestUserBandwidthStatDAO_CleanDays(t *testing.T) {
var dao = models.NewUserBandwidthStatDAO()
var tx *dbs.Tx
err := dao.Clean(tx)
err := dao.CleanDays(tx, 100)
if err != nil {
t.Fatal(err)
}

View File

@@ -2,6 +2,42 @@ package models
import "github.com/iwind/TeaGo/dbs"
const (
UserField_Id dbs.FieldName = "id" // ID
UserField_IsOn dbs.FieldName = "isOn" // 是否启用
UserField_Username dbs.FieldName = "username" // 用户名
UserField_Password dbs.FieldName = "password" // 密码
UserField_Fullname dbs.FieldName = "fullname" // 真实姓名
UserField_Mobile dbs.FieldName = "mobile" // 手机号
UserField_VerifiedMobile dbs.FieldName = "verifiedMobile" // 已验证手机号
UserField_Tel dbs.FieldName = "tel" // 联系电话
UserField_Remark dbs.FieldName = "remark" // 备注
UserField_Email dbs.FieldName = "email" // 邮箱地址
UserField_VerifiedEmail dbs.FieldName = "verifiedEmail" // 激活后的邮箱
UserField_EmailIsVerified dbs.FieldName = "emailIsVerified" // 邮箱是否已验证
UserField_AvatarFileId dbs.FieldName = "avatarFileId" // 头像文件ID
UserField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
UserField_Day dbs.FieldName = "day" // YYYYMMDD
UserField_UpdatedAt dbs.FieldName = "updatedAt" // 修改时间
UserField_State dbs.FieldName = "state" // 状态
UserField_Source dbs.FieldName = "source" // 来源
UserField_ClusterId dbs.FieldName = "clusterId" // 集群ID
UserField_Features dbs.FieldName = "features" // 允许操作的特征
UserField_RegisteredIP dbs.FieldName = "registeredIP" // 注册使用的IP
UserField_IsRejected dbs.FieldName = "isRejected" // 是否已拒绝
UserField_RejectReason dbs.FieldName = "rejectReason" // 拒绝理由
UserField_IsVerified dbs.FieldName = "isVerified" // 是否验证通过
UserField_RequirePlans dbs.FieldName = "requirePlans" // 是否需要购买套餐
UserField_Modules dbs.FieldName = "modules" // 用户模块
UserField_PriceType dbs.FieldName = "priceType" // 计费类型traffic|bandwidth
UserField_PricePeriod dbs.FieldName = "pricePeriod" // 结算周期
UserField_ServersEnabled dbs.FieldName = "serversEnabled" // 是否禁用所有服务
UserField_Notification dbs.FieldName = "notification" // 通知设置
UserField_BandwidthAlgo dbs.FieldName = "bandwidthAlgo" // 带宽算法
UserField_BandwidthModifier dbs.FieldName = "bandwidthModifier" // 带宽修正值
UserField_Lang dbs.FieldName = "lang" // 语言代号
)
// User 用户
type User struct {
Id uint32 `field:"id"` // ID
@@ -36,6 +72,7 @@ type User struct {
Notification dbs.JSON `field:"notification"` // 通知设置
BandwidthAlgo string `field:"bandwidthAlgo"` // 带宽算法
BandwidthModifier float64 `field:"bandwidthModifier"` // 带宽修正值
Lang string `field:"lang"` // 语言代号
}
type UserOperator struct {
@@ -71,6 +108,7 @@ type UserOperator struct {
Notification any // 通知设置
BandwidthAlgo any // 带宽算法
BandwidthModifier any // 带宽修正值
Lang any // 语言代号
}
func NewUserOperator() *UserOperator {

View File

@@ -280,6 +280,7 @@ func (this *UserNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *
func (this *UserNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
return this.Query(tx).
State(UserNodeStateEnabled).
Attr("isOn", true).
Where("status IS NOT NULL").
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
Param("version", utils.VersionToLong(version)).

View File

@@ -80,3 +80,12 @@ func CheckSQLDuplicateErr(err error) bool {
}
return CheckSQLErrCode(err, 1062)
}
// IsMySQLError Check error is MySQLError
func IsMySQLError(err error) bool {
if err == nil {
return false
}
_, ok := err.(*mysql.MySQLError)
return ok
}

View File

@@ -1,10 +1,18 @@
package dbutils
import (
executils "github.com/TeaOSLab/EdgeAPI/internal/utils/exec"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/types"
"net"
"os"
"os/exec"
"regexp"
"strings"
"time"
)
// NewQuery 构造Query
@@ -127,3 +135,79 @@ func MySQLVersionFrom8() (bool, error) {
}
return false, nil
}
// FindMySQLPath find out mysqld_safe path from system processes
func FindMySQLPath() string {
psExe, err := executils.LookPath("ps")
if err != nil {
return ""
}
var cmd = executils.NewTimeoutCmd(3*time.Second, psExe, "-ef").
WithStdout().
WithStderr()
err = cmd.Run()
if err != nil {
return ""
}
var reg = regexp.MustCompile(`\s(/\S+/mysqld_safe)\s`)
var matches = reg.FindStringSubmatch(cmd.Stdout())
if len(matches) > 1 {
var path = matches[1]
_, err = os.Stat(path)
if err != nil {
return ""
}
return path
}
return ""
}
// FindMySQLPathAndRemember find out mysqld_safe path then remember it for future usage
func FindMySQLPathAndRemember() {
var path = FindMySQLPath()
if len(path) == 0 {
return
}
var cacheFile = Tea.Root + "/data/mysql-path.cache"
_ = os.WriteFile(cacheFile, []byte(path), 0666) // ignore error
}
// StartLocalMySQL try to start local mysql server
func StartLocalMySQL() {
// possible installed paths
var mysqldSafeFiles = []string{}
// read last path from cache file
var cacheFile = Tea.Root + "/data/mysql-path.cache"
cacheData, err := os.ReadFile(cacheFile)
if err == nil && len(cacheData) > 0 {
mysqldSafeFiles = append(mysqldSafeFiles, string(cacheData))
}
// from $PATH variable
exePath, lookErr := executils.LookPath("mysqld_safe")
if lookErr == nil && len(exePath) > 0 && !lists.ContainsString(mysqldSafeFiles, exePath) {
mysqldSafeFiles = append(mysqldSafeFiles, exePath)
}
// these installed by edge-boot or foolish-mysql
for _, path := range []string{
"/usr/local/mysql/bin/mysqld_safe",
"/usr/local/mysql8/bin/mysqld_safe",
} {
if !lists.ContainsString(mysqldSafeFiles, path) {
mysqldSafeFiles = append(mysqldSafeFiles, path)
}
}
for _, mysqldSafeFile := range mysqldSafeFiles {
_, err := os.Stat(mysqldSafeFile)
if err == nil {
logs.Println("[API_NODE]try to start local mysql server from '" + mysqldSafeFile + "' ...")
var mysqlCmd = exec.Command(mysqldSafeFile)
_ = mysqlCmd.Start()
break
}
}
}

View File

@@ -35,3 +35,11 @@ func TestMySQLVersion(t *testing.T) {
func TestMySQLVersionFrom8(t *testing.T) {
t.Log(dbutils.MySQLVersionFrom8())
}
func TestFindMySQLPath(t *testing.T) {
t.Log(dbutils.FindMySQLPath())
}
func TestStartLocalMySQL(t *testing.T) {
dbutils.StartLocalMySQL()
}

View File

@@ -37,8 +37,8 @@ func (this *Unzip) Run() error {
}()
for _, file := range reader.File {
info := file.FileInfo()
target := this.targetDir + "/" + file.Name
var info = file.FileInfo()
var target = this.targetDir + "/" + file.Name
// 目录
if info.IsDir() {
@@ -62,7 +62,7 @@ func (this *Unzip) Run() error {
}
// 文件
err := func(file *zip.File, target string) error {
err = func(file *zip.File, target string) error {
fileReader, err := file.Open()
if err != nil {
return err
@@ -71,6 +71,10 @@ func (this *Unzip) Run() error {
_ = fileReader.Close()
}()
// remove old
_ = os.Remove(target)
// create new
fileWriter, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, file.FileInfo().Mode())
if err != nil {
return err

View File

@@ -28,6 +28,7 @@ import (
"github.com/iwind/gosock/pkg/gosock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/status"
"gopkg.in/yaml.v3"
"log"
"net"
@@ -294,6 +295,9 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err
func (this *APINode) checkDB() error {
logs.Println("[API_NODE]checking database connection ...")
// lookup mysqld_safe process
go dbutils.FindMySQLPathAndRemember()
db, err := dbs.Default()
if err != nil {
return err
@@ -310,13 +314,7 @@ func (this *APINode) checkDB() error {
if strings.Contains(err.Error(), "connection refused") {
config, _ := db.Config()
if config != nil && (strings.Contains(config.Dsn, "tcp(127.0.0.1:") || strings.Contains(config.Dsn, "tcp(localhost:")) && os.Getgid() == 0 /** ROOT 用户 **/ {
var mysqldSafeFile = "/usr/local/mysql/bin/mysqld_safe"
_, err = os.Stat(mysqldSafeFile)
if err == nil {
logs.Println("[API_NODE]try to start local mysql server from '" + mysqldSafeFile + "' ...")
var mysqlCmd = exec.Command(mysqldSafeFile)
_ = mysqlCmd.Start()
}
dbutils.StartLocalMySQL()
}
}
@@ -832,7 +830,12 @@ func (this *APINode) unaryInterceptor(ctx context.Context, req any, info *grpc.U
}
result, err := handler(ctx, req)
if err != nil {
err = errors.New("'" + info.FullMethod + "()' says: " + err.Error())
statusErr, ok := status.FromError(err)
if ok {
err = status.Error(statusErr.Code(), "'"+info.FullMethod+"()' says: "+err.Error())
} else {
err = errors.New("'" + info.FullMethod + "()' says: " + err.Error())
}
}
return result, err
}

View File

@@ -283,7 +283,7 @@ func (this *AdminService) FindAllAdminModules(ctx context.Context, req *pb.FindA
return nil, err
}
result := []*pb.AdminModuleList{}
var result = []*pb.AdminModuleList{}
for _, admin := range admins {
modules := []*systemconfigs.AdminModule{}
if len(admin.Modules) > 0 {
@@ -292,7 +292,7 @@ func (this *AdminService) FindAllAdminModules(ctx context.Context, req *pb.FindA
return nil, err
}
}
pbModules := []*pb.AdminModule{}
var pbModules = []*pb.AdminModule{}
for _, module := range modules {
pbModules = append(pbModules, &pb.AdminModule{
AllowAll: module.AllowAll,
@@ -301,11 +301,12 @@ func (this *AdminService) FindAllAdminModules(ctx context.Context, req *pb.FindA
})
}
list := &pb.AdminModuleList{
var list = &pb.AdminModuleList{
AdminId: int64(admin.Id),
IsSuper: admin.IsSuper,
Fullname: admin.Fullname,
Theme: admin.Theme,
Lang: admin.Lang,
Modules: pbModules,
}
result = append(result, list)

View File

@@ -240,7 +240,7 @@ func (this *APINodeService) FindEnabledAPINode(ctx context.Context, req *pb.Find
// FindCurrentAPINodeVersion 获取当前API节点的版本
func (this *APINodeService) FindCurrentAPINodeVersion(ctx context.Context, req *pb.FindCurrentAPINodeVersionRequest) (*pb.FindCurrentAPINodeVersionResponse, error) {
_, _, _, err := rpcutils.ValidateRequest(ctx)
role, _, _, err := rpcutils.ValidateRequest(ctx)
if err != nil {
return nil, err
}
@@ -249,6 +249,7 @@ func (this *APINodeService) FindCurrentAPINodeVersion(ctx context.Context, req *
Version: teaconst.Version,
Os: runtime.GOOS,
Arch: runtime.GOARCH,
Role: role,
}, nil
}

View File

@@ -16,7 +16,9 @@ import (
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
type BaseService struct {
@@ -229,7 +231,7 @@ func (this *BaseService) PermissionError() error {
}
func (this *BaseService) NotImplementedYet() error {
return errors.New("not implemented yet")
return status.Error(codes.Unimplemented, "not implemented yet")
}
// NullTx 空的数据库事务

View File

@@ -303,7 +303,24 @@ func (this *DNSDomainService) SyncDNSDomainData(ctx context.Context, req *pb.Syn
if err != nil {
return nil, err
}
return this.syncClusterDNS(req)
var latestVersion = dns.SharedDNSTaskDAO.GenerateVersion()
resp, err := this.syncClusterDNS(req)
if err != nil {
return resp, err
}
// 标记集群所有任务已完成
if req.NodeClusterId > 0 && resp != nil && resp.IsOk {
var tx = this.NullTx()
err = dns.SharedDNSTaskDAO.UpdateClusterDNSTasksDone(tx, req.NodeClusterId, latestVersion)
if err != nil {
return resp, err
}
}
return resp, err
}
// FindAllDNSDomainRoutes 查看支持的线路

View File

@@ -117,3 +117,19 @@ func (this *DNSTaskService) DeleteDNSTask(ctx context.Context, req *pb.DeleteDNS
}
return this.Success()
}
// DeleteAllDNSTasks 删除所有同步任务
func (this *DNSTaskService) DeleteAllDNSTasks(ctx context.Context, req *pb.DeleteAllDNSTasksRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
err = dns.SharedDNSTaskDAO.DeleteAllDNSTasks(tx)
if err != nil {
return nil, err
}
return this.Success()
}

View File

@@ -46,7 +46,7 @@ func (this *HTTPCachePolicyService) CreateHTTPCachePolicy(ctx context.Context, r
var tx = this.NullTx()
policyId, err := models.SharedHTTPCachePolicyDAO.CreateCachePolicy(tx, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxKeys, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
policyId, err := models.SharedHTTPCachePolicyDAO.CreateCachePolicy(tx, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
if err != nil {
return nil, err
}
@@ -63,7 +63,7 @@ func (this *HTTPCachePolicyService) UpdateHTTPCachePolicy(ctx context.Context, r
var tx = this.NullTx()
err = models.SharedHTTPCachePolicyDAO.UpdateCachePolicy(tx, req.HttpCachePolicyId, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxKeys, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
err = models.SharedHTTPCachePolicyDAO.UpdateCachePolicy(tx, req.HttpCachePolicyId, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
if err != nil {
return nil, err
}

View File

@@ -3,8 +3,11 @@ package services
import (
"context"
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/types"
)
@@ -22,6 +25,34 @@ func (this *HTTPPageService) CreateHTTPPage(ctx context.Context, req *pb.CreateH
var tx = this.NullTx()
// validate
const maxURLLength = 512
const maxBodyLength = 32 * 1024
switch req.BodyType {
case shared.BodyTypeURL:
if len(req.Url) > maxURLLength {
return nil, errors.New("'url' too long")
}
if !regexputils.HTTPProtocol.MatchString(req.Url) {
return nil, errors.New("invalid 'url' format")
}
if len(req.Body) > maxBodyLength { // we keep short body for user experience
req.Body = ""
}
case shared.BodyTypeHTML:
if len(req.Body) > maxBodyLength {
return nil, errors.New("'body' too long")
}
if len(req.Url) > maxURLLength { // we keep short url for user experience
req.Url = ""
}
default:
return nil, errors.New("invalid 'bodyType': " + req.BodyType)
}
pageId, err := models.SharedHTTPPageDAO.CreatePage(tx, userId, req.StatusList, req.BodyType, req.Url, req.Body, types.Int(req.NewStatus))
if err != nil {
return nil, err
@@ -46,6 +77,34 @@ func (this *HTTPPageService) UpdateHTTPPage(ctx context.Context, req *pb.UpdateH
}
}
// validate
const maxURLLength = 512
const maxBodyLength = 32 * 1024
switch req.BodyType {
case shared.BodyTypeURL:
if len(req.Url) > maxURLLength {
return nil, errors.New("'url' too long")
}
if !regexputils.HTTPProtocol.MatchString(req.Url) {
return nil, errors.New("invalid 'url' format")
}
if len(req.Body) > maxBodyLength { // we keep short body for user experience
req.Body = ""
}
case shared.BodyTypeHTML:
if len(req.Body) > maxBodyLength {
return nil, errors.New("'body' too long")
}
if len(req.Url) > maxURLLength { // we keep short url for user experience
req.Url = ""
}
default:
return nil, errors.New("invalid 'bodyType': " + req.BodyType)
}
err = models.SharedHTTPPageDAO.UpdatePage(tx, req.HttpPageId, req.StatusList, req.BodyType, req.Url, req.Body, types.Int(req.NewStatus))
if err != nil {
return nil, err

View File

@@ -15,14 +15,14 @@ type HTTPRewriteRuleService struct {
// CreateHTTPRewriteRule 创建重写规则
func (this *HTTPRewriteRuleService) CreateHTTPRewriteRule(ctx context.Context, req *pb.CreateHTTPRewriteRuleRequest) (*pb.CreateHTTPRewriteRuleResponse, error) {
// 校验请求
_, err := this.ValidateAdmin(ctx)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
rewriteRuleId, err := models.SharedHTTPRewriteRuleDAO.CreateRewriteRule(tx, req.Pattern, req.Replace, req.Mode, types.Int(req.RedirectStatus), req.IsBreak, req.ProxyHost, req.WithQuery, req.IsOn, req.CondsJSON)
rewriteRuleId, err := models.SharedHTTPRewriteRuleDAO.CreateRewriteRule(tx, userId, req.Pattern, req.Replace, req.Mode, types.Int(req.RedirectStatus), req.IsBreak, req.ProxyHost, req.WithQuery, req.IsOn, req.CondsJSON)
if err != nil {
return nil, err
}
@@ -33,12 +33,18 @@ func (this *HTTPRewriteRuleService) CreateHTTPRewriteRule(ctx context.Context, r
// UpdateHTTPRewriteRule 修改重写规则
func (this *HTTPRewriteRuleService) UpdateHTTPRewriteRule(ctx context.Context, req *pb.UpdateHTTPRewriteRuleRequest) (*pb.RPCSuccess, error) {
// 校验请求
_, err := this.ValidateAdmin(ctx)
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
if userId > 0 {
err = models.SharedHTTPRewriteRuleDAO.CheckUserRewriteRule(tx, userId, req.RewriteRuleId)
if err != nil {
return nil, err
}
}
err = models.SharedHTTPRewriteRuleDAO.UpdateRewriteRule(tx, req.RewriteRuleId, req.Pattern, req.Replace, req.Mode, types.Int(req.RedirectStatus), req.IsBreak, req.ProxyHost, req.WithQuery, req.IsOn, req.CondsJSON)
if err != nil {

View File

@@ -5,8 +5,10 @@ import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/dbs"
)
@@ -109,6 +111,8 @@ func (this *HTTPWebService) UpdateHTTPWeb(ctx context.Context, req *pb.UpdateHTT
if err != nil {
return nil, err
}
req.RootJSON = []byte("{}") // 为了安全
}
var tx = this.NullTx()
@@ -139,7 +143,60 @@ func (this *HTTPWebService) UpdateHTTPWebCompression(ctx context.Context, req *p
var tx = this.NullTx()
err = models.SharedHTTPWebDAO.UpdateWebCompression(tx, req.HttpWebId, req.CompressionJSON)
if len(req.CompressionJSON) == 0 {
return nil, errors.New("'compressionJSON' should not be empty")
}
var compressionConfig = &serverconfigs.HTTPCompressionConfig{}
err = json.Unmarshal(req.CompressionJSON, compressionConfig)
if err != nil {
return nil, err
}
err = compressionConfig.Init()
if err != nil {
return nil, err
}
err = models.SharedHTTPWebDAO.UpdateWebCompression(tx, req.HttpWebId, compressionConfig)
if err != nil {
return nil, err
}
return this.Success()
}
// UpdateHTTPWebOptimization 修改页面优化配置
func (this *HTTPWebService) UpdateHTTPWebOptimization(ctx context.Context, req *pb.UpdateHTTPWebOptimizationRequest) (*pb.RPCSuccess, error) {
// 校验请求
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
if userId > 0 {
// 检查用户权限
err = models.SharedHTTPWebDAO.CheckUserWeb(nil, userId, req.HttpWebId)
if err != nil {
return nil, err
}
}
var tx = this.NullTx()
if len(req.OptimizationJSON) == 0 {
return nil, errors.New("invalid 'optimizationJSON'")
}
var optimizationConfig = serverconfigs.NewHTTPPageOptimizationConfig()
err = json.Unmarshal(req.OptimizationJSON, optimizationConfig)
if err != nil {
return nil, err
}
err = optimizationConfig.Init()
if err != nil {
return nil, err
}
err = models.SharedHTTPWebDAO.UpdateWebOptimization(tx, req.HttpWebId, optimizationConfig)
if err != nil {
return nil, err
}
@@ -292,8 +349,53 @@ func (this *HTTPWebService) UpdateHTTPWebShutdown(ctx context.Context, req *pb.U
}
var tx = this.NullTx()
var newShutdownJSON = req.ShutdownJSON
if len(req.ShutdownJSON) > 0 {
const maxURLLength = 512
const maxBodyLength = 32 * 1024
err = models.SharedHTTPWebDAO.UpdateWebShutdown(tx, req.HttpWebId, req.ShutdownJSON)
var shutdownConfig = &serverconfigs.HTTPShutdownConfig{}
err = json.Unmarshal(req.ShutdownJSON, shutdownConfig)
if err != nil {
return nil, err
}
err = shutdownConfig.Init()
if err != nil {
return nil, errors.New("validate config failed: " + err.Error())
}
switch shutdownConfig.BodyType {
case shared.BodyTypeURL:
if len(shutdownConfig.URL) > maxURLLength {
return nil, errors.New("'url' too long")
}
if !regexputils.HTTPProtocol.MatchString(shutdownConfig.URL) {
return nil, errors.New("invalid 'url' format")
}
if len(shutdownConfig.Body) > maxBodyLength { // we keep short body for user experience
shutdownConfig.Body = ""
}
case shared.BodyTypeHTML:
if len(shutdownConfig.Body) > maxBodyLength {
return nil, errors.New("'body' too long")
}
if len(shutdownConfig.URL) > maxURLLength { // we keep short url for user experience
shutdownConfig.URL = ""
}
default:
return nil, errors.New("invalid 'bodyType': " + shutdownConfig.BodyType)
}
newShutdownJSON, err = json.Marshal(shutdownConfig)
if err != nil {
return nil, err
}
}
err = models.SharedHTTPWebDAO.UpdateWebShutdown(tx, req.HttpWebId, newShutdownJSON)
if err != nil {
return nil, err
}
@@ -319,14 +421,23 @@ func (this *HTTPWebService) UpdateHTTPWebPages(ctx context.Context, req *pb.Upda
var tx = this.NullTx()
// 检查配置
var pages = []*serverconfigs.HTTPPageConfig{}
err = json.Unmarshal(req.PagesJSON, &pages)
if err != nil {
return nil, errors.New("decode 'pages' failed: " + err.Error())
}
var newPages = []*serverconfigs.HTTPPageConfig{}
for _, page := range pages {
newPages = append(newPages, &serverconfigs.HTTPPageConfig{Id: page.Id})
if len(req.PagesJSON) > 0 {
var pages = []*serverconfigs.HTTPPageConfig{}
err = json.Unmarshal(req.PagesJSON, &pages)
for _, page := range pages {
err = page.Init()
if err != nil {
return nil, errors.New("validate page failed: " + err.Error())
}
// reset not needed fields, keep "id" reference only
page.URL = ""
page.Body = ""
newPages = append(newPages, &serverconfigs.HTTPPageConfig{Id: page.Id})
}
}
newPagesJSON, err := json.Marshal(newPages)
if err != nil {

View File

@@ -309,7 +309,7 @@ func (this *IPLibraryFileService) CheckCountriesWithIPLibraryFileId(ctx context.
}
for _, similarCountry := range similarCountries {
pbMissingCountry.SimilarCountries = append(pbMissingCountry.SimilarCountries, &pb.RegionCountry{
Id: int64(similarCountry.Id),
Id: int64(similarCountry.ValueId),
Name: similarCountry.Name,
DisplayName: similarCountry.DisplayName(),
})
@@ -391,7 +391,7 @@ func (this *IPLibraryFileService) CheckProvincesWithIPLibraryFileId(ctx context.
for _, similarProvince := range similarProvinces {
pbMissingProvince.SimilarProvinces = append(pbMissingProvince.SimilarProvinces, &pb.RegionProvince{
Id: int64(similarProvince.Id),
Id: int64(similarProvince.ValueId),
Name: similarProvince.Name,
DisplayName: similarProvince.DisplayName(),
})
@@ -482,7 +482,7 @@ func (this *IPLibraryFileService) CheckCitiesWithIPLibraryFileId(ctx context.Con
for _, similarCity := range similarCities {
pbMissingCity.SimilarCities = append(pbMissingCity.SimilarCities, &pb.RegionCity{
Id: int64(similarCity.Id),
Id: int64(similarCity.ValueId),
Name: similarCity.Name,
DisplayName: similarCity.DisplayName(),
})
@@ -597,7 +597,7 @@ func (this *IPLibraryFileService) CheckTownsWithIPLibraryFileId(ctx context.Cont
for _, similarTown := range similarTowns {
pbMissingTown.SimilarTowns = append(pbMissingTown.SimilarTowns, &pb.RegionTown{
Id: int64(similarTown.Id),
Id: int64(similarTown.ValueId),
Name: similarTown.Name,
DisplayName: similarTown.DisplayName(),
})
@@ -654,7 +654,7 @@ func (this *IPLibraryFileService) CheckProvidersWithIPLibraryFileId(ctx context.
}
for _, similarProvider := range similarProviders {
pbMissingProvider.SimilarProviders = append(pbMissingProvider.SimilarProviders, &pb.RegionProvider{
Id: int64(similarProvider.Id),
Id: int64(similarProvider.ValueId),
Name: similarProvider.Name,
DisplayName: similarProvider.DisplayName(),
})

View File

@@ -2,8 +2,10 @@ package services
import (
"context"
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
@@ -22,7 +24,16 @@ func (this *LogService) CreateLog(ctx context.Context, req *pb.CreateLogRequest)
var tx = this.NullTx()
err = models.SharedLogDAO.CreateLog(tx, userType, userId, req.Level, req.Description, req.Action, req.Ip)
// i18n
var langMessageArgs = []any{}
if len(req.LangMessageArgsJSON) > 0 {
err = json.Unmarshal(req.LangMessageArgsJSON, &langMessageArgs)
if err != nil {
return nil, err
}
}
err = models.SharedLogDAO.CreateLog(tx, userType, userId, req.Level, req.Description, req.Action, req.Ip, langs.MessageCode(req.LangMessageCode), langMessageArgs)
if err != nil {
return nil, err
}

View File

@@ -2016,7 +2016,7 @@ func (this *NodeService) FindNodeGlobalServerConfig(ctx context.Context, req *pb
}
}
if config == nil {
config = serverconfigs.DefaultGlobalServerConfig()
config = serverconfigs.NewGlobalServerConfig()
}
configJSON, err := json.Marshal(config)

View File

@@ -34,7 +34,7 @@ func (this *NodeClusterService) CreateNodeCluster(ctx context.Context, req *pb.C
}
// 全局服务配置
var serverGlobalConfig = serverconfigs.DefaultGlobalServerConfig()
var serverGlobalConfig = serverconfigs.NewGlobalServerConfig()
if len(req.GlobalServerConfigJSON) > 0 {
err = json.Unmarshal(req.GlobalServerConfigJSON, serverGlobalConfig)
if err != nil {
@@ -1102,7 +1102,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
// toa
if models.IsNotNull(cluster.Toa) {
var toaConfig = &nodeconfigs.TOAConfig{}
var toaConfig = nodeconfigs.NewTOAConfig()
err = json.Unmarshal(cluster.Toa, toaConfig)
if err != nil {
return nil, err
@@ -1130,15 +1130,15 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
}
// UAM
var uamPolicy = nodeconfigs.NewUAMPolicy()
if models.IsNotNull(cluster.Uam) {
var uamPolicy = &nodeconfigs.UAMPolicy{}
err = json.Unmarshal(cluster.Uam, uamPolicy)
if err != nil {
return nil, err
}
result.UamIsOn = uamPolicy.IsOn
} else {
result.UamIsOn = nodeconfigs.DefaultUAMPolicy.IsOn
result.UamIsOn = uamPolicy.IsOn
}
// HTTP CC
@@ -1180,6 +1180,16 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
result.HasHTTPPagesPolicy = pagesPolicy.IsOn && len(pagesPolicy.Pages) > 0
}
// HTTP/3
if models.IsNotNull(cluster.Http3) {
var http3Policy = nodeconfigs.NewHTTP3Policy()
err = json.Unmarshal(cluster.Http3, http3Policy)
if err != nil {
return nil, err
}
result.Http3IsOn = http3Policy.IsOn
}
return result, nil
}
@@ -1282,7 +1292,7 @@ func (this *NodeClusterService) UpdateNodeClusterUAMPolicy(ctx context.Context,
return nil, err
}
var uamPolicy = &nodeconfigs.UAMPolicy{}
var uamPolicy = nodeconfigs.NewUAMPolicy()
err = json.Unmarshal(req.UamPolicyJSON, uamPolicy)
if err != nil {
return nil, err
@@ -1301,7 +1311,6 @@ func (this *NodeClusterService) UpdateNodeClusterUAMPolicy(ctx context.Context,
return this.Success()
}
// FindEnabledNodeClusterHTTPCCPolicy 读取集群HTTP CC策略
func (this *NodeClusterService) FindEnabledNodeClusterHTTPCCPolicy(ctx context.Context, req *pb.FindEnabledNodeClusterHTTPCCPolicyRequest) (*pb.FindEnabledNodeClusterHTTPCCPolicyResponse, error) {
if !teaconst.IsPlus {
@@ -1435,7 +1444,7 @@ func (this *NodeClusterService) UpdateNodeClusterGlobalServerConfig(ctx context.
return nil, err
}
var config = serverconfigs.DefaultGlobalServerConfig()
var config = serverconfigs.NewGlobalServerConfig()
err = json.Unmarshal(req.GlobalServerConfigJSON, config)
if err != nil {
return nil, err
@@ -1502,3 +1511,33 @@ func (this *NodeClusterService) UpdateNodeClusterHTTPPagesPolicy(ctx context.Con
return this.Success()
}
// UpdateNodeClusterHTTP3Policy 修改集群的HTTP3设置
func (this *NodeClusterService) UpdateNodeClusterHTTP3Policy(ctx context.Context, req *pb.UpdateNodeClusterHTTP3PolicyRequest) (*pb.RPCSuccess, error) {
if !teaconst.IsPlus {
return nil, this.NotImplementedYet()
}
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var http3Policy = nodeconfigs.NewHTTP3Policy()
err = json.Unmarshal(req.Http3PolicyJSON, http3Policy)
if err != nil {
return nil, err
}
err = http3Policy.Init()
if err != nil {
return nil, errors.New("validate http3 policy failed: " + err.Error())
}
var tx = this.NullTx()
err = models.SharedNodeClusterDAO.UpdateClusterHTTP3Policy(tx, req.NodeClusterId, http3Policy)
if err != nil {
return nil, err
}
return this.Success()
}

View File

@@ -0,0 +1,13 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package services
import (
"context"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
func (this *NodeClusterService) FindNodeClusterHTTP3Policy(ctx context.Context, req *pb.FindNodeClusterHTTP3PolicyRequest) (*pb.FindNodeClusterHTTP3PolicyResponse, error) {
return nil, this.NotImplementedYet()
}

View File

@@ -16,6 +16,10 @@ func (this *NodeService) FindNodeHTTPCCPolicies(ctx context.Context, req *pb.Fin
return nil, this.NotImplementedYet()
}
func (this *NodeService) FindNodeHTTP3Policies(ctx context.Context, req *pb.FindNodeHTTP3PoliciesRequest) (*pb.FindNodeHTTP3PoliciesResponse, error) {
return nil, this.NotImplementedYet()
}
func (this *NodeService) FindNodeHTTPPagesPolicies(ctx context.Context, req *pb.FindNodeHTTPPagesPoliciesRequest) (*pb.FindNodeHTTPPagesPoliciesResponse, error) {
return nil, this.NotImplementedYet()
}
@@ -43,3 +47,8 @@ func (this *NodeService) CopyNodeActionsToNodeGroup(ctx context.Context, req *pb
func (this *NodeService) CopyNodeActionsToNodeCluster(ctx context.Context, req *pb.CopyNodeActionsToNodeClusterRequest) (*pb.RPCSuccess, error) {
return nil, this.NotImplementedYet()
}
// FindNodeTOAConfig 查找节点的TOA配置
func (this *NodeService) FindNodeTOAConfig(ctx context.Context, req *pb.FindNodeTOAConfigRequest) (*pb.FindNodeTOAConfigResponse, error) {
return nil, this.NotImplementedYet()
}

View File

@@ -216,6 +216,22 @@ func (this *NodeTaskService) DeleteNodeTasks(ctx context.Context, req *pb.Delete
return this.Success()
}
// DeleteAllNodeTasks 删除所有任务
func (this *NodeTaskService) DeleteAllNodeTasks(ctx context.Context, req *pb.DeleteAllNodeTasksRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
err = models.SharedNodeTaskDAO.DeleteAllNodeTasks(tx)
if err != nil {
return nil, err
}
return this.Success()
}
// CountDoingNodeTasks 计算正在执行的任务数量
func (this *NodeTaskService) CountDoingNodeTasks(ctx context.Context, req *pb.CountDoingNodeTasksRequest) (*pb.RPCCountResponse, error) {
_, err := this.ValidateAdmin(ctx)

View File

@@ -6,6 +6,7 @@ import (
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
"github.com/iwind/TeaGo/maps"
@@ -23,15 +24,26 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
return nil, err
}
// 源站地址设置
if req.Addr == nil {
return nil, errors.New("'addr' can not be nil")
}
addrMap := maps.Map{
var addrMap = maps.Map{
"protocol": req.Addr.Protocol,
"portRange": req.Addr.PortRange,
"host": req.Addr.Host,
}
// OSS设置
var ossConfig *ossconfigs.OSSConfig
if len(req.OssJSON) > 0 {
ossConfig = ossconfigs.NewOSSConfig()
err = json.Unmarshal(req.OssJSON, ossConfig)
if err != nil {
return nil, err
}
}
var tx = this.NullTx()
// 校验参数
@@ -72,7 +84,7 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
}
}
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, addrMap.AsJSON(), ossConfig, req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort, req.Http2Enabled)
if err != nil {
return nil, err
}
@@ -95,6 +107,8 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
return nil, err
}
}
// 源站地址设置
if req.Addr == nil {
return nil, errors.New("'addr' can not be nil")
}
@@ -104,6 +118,16 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
"host": req.Addr.Host,
}
// OSS设置
var ossConfig *ossconfigs.OSSConfig
if len(req.OssJSON) > 0 {
ossConfig = ossconfigs.NewOSSConfig()
err = json.Unmarshal(req.OssJSON, ossConfig)
if err != nil {
return nil, err
}
}
// 校验参数
var connTimeout = &shared.TimeDuration{}
if len(req.ConnTimeoutJSON) > 0 {
@@ -142,7 +166,7 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
}
}
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, addrMap.AsJSON(), ossConfig, req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort, req.Http2Enabled)
if err != nil {
return nil, err
}
@@ -180,7 +204,7 @@ func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEn
return nil, err
}
result := &pb.Origin{
return &pb.FindEnabledOriginResponse{Origin: &pb.Origin{
Id: int64(origin.Id),
IsOn: origin.IsOn,
Name: origin.Name,
@@ -189,10 +213,11 @@ func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEn
Host: addr.Host,
PortRange: addr.PortRange,
},
Description: origin.Description,
Domains: origin.DecodeDomains(),
}
return &pb.FindEnabledOriginResponse{Origin: result}, nil
Description: origin.Description,
Domains: origin.DecodeDomains(),
FollowPort: origin.FollowPort,
Http2Enabled: origin.Http2Enabled,
}}, nil
}
// FindEnabledOriginConfig 查找源站配置

View File

@@ -49,7 +49,7 @@ func (this *RegionCityService) FindAllEnabledRegionCities(ctx context.Context, r
}
pbProvince = &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.Name,
Codes: province.DecodeCodes(),
DisplayName: province.DisplayName(),
@@ -57,7 +57,7 @@ func (this *RegionCityService) FindAllEnabledRegionCities(ctx context.Context, r
}
pbCities = append(pbCities, &pb.RegionCity{
Id: int64(city.Id),
Id: int64(city.ValueId),
Name: city.Name,
Codes: city.DecodeCodes(),
RegionProvinceId: int64(city.ProvinceId),
@@ -108,7 +108,7 @@ func (this *RegionCityService) FindAllRegionCities(ctx context.Context, req *pb.
}
pbProvince = &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.Name,
Codes: province.DecodeCodes(),
CustomName: province.CustomName,
@@ -118,7 +118,7 @@ func (this *RegionCityService) FindAllRegionCities(ctx context.Context, req *pb.
}
pbCities = append(pbCities, &pb.RegionCity{
Id: int64(city.Id),
Id: int64(city.ValueId),
Name: city.Name,
Codes: city.DecodeCodes(),
RegionProvinceId: int64(city.ProvinceId),
@@ -155,7 +155,7 @@ func (this *RegionCityService) FindAllRegionCitiesWithRegionProvinceId(ctx conte
var pbProvince = &pb.RegionProvince{Id: provinceId}
pbCities = append(pbCities, &pb.RegionCity{
Id: int64(city.Id),
Id: int64(city.ValueId),
Name: city.Name,
Codes: city.DecodeCodes(),
RegionProvinceId: int64(city.ProvinceId),
@@ -192,7 +192,7 @@ func (this *RegionCityService) FindEnabledRegionCity(ctx context.Context, req *p
return &pb.FindEnabledRegionCityResponse{
RegionCity: &pb.RegionCity{
Id: int64(city.Id),
Id: int64(city.ValueId),
Name: city.Name,
Codes: city.DecodeCodes(),
RegionProvinceId: int64(city.ProvinceId),
@@ -223,7 +223,7 @@ func (this *RegionCityService) FindRegionCity(ctx context.Context, req *pb.FindR
return &pb.FindRegionCityResponse{
RegionCity: &pb.RegionCity{
Id: int64(city.Id),
Id: int64(city.ValueId),
Name: city.Name,
Codes: city.DecodeCodes(),
RegionProvinceId: int64(city.ProvinceId),

View File

@@ -40,13 +40,14 @@ func (this *RegionCountryService) FindAllEnabledRegionCountries(ctx context.Cont
}
result = append(result, &pb.RegionCountry{
Id: int64(country.Id),
Id: int64(country.ValueId),
Name: country.Name,
Codes: country.DecodeCodes(),
Pinyin: pinyinStrings,
CustomName: country.CustomName,
CustomCodes: country.DecodeCustomCodes(),
DisplayName: country.DisplayName(),
IsCommon: country.IsCommon,
})
}
return &pb.FindAllEnabledRegionCountriesResponse{
@@ -74,7 +75,7 @@ func (this *RegionCountryService) FindEnabledRegionCountry(ctx context.Context,
}
return &pb.FindEnabledRegionCountryResponse{RegionCountry: &pb.RegionCountry{
Id: int64(country.Id),
Id: int64(country.ValueId),
Name: country.Name,
Codes: country.DecodeCodes(),
CustomName: country.CustomName,
@@ -110,13 +111,14 @@ func (this *RegionCountryService) FindAllRegionCountries(ctx context.Context, re
}
result = append(result, &pb.RegionCountry{
Id: int64(country.Id),
Id: int64(country.ValueId),
Name: country.Name,
Codes: country.DecodeCodes(),
Pinyin: pinyinStrings,
CustomName: country.CustomName,
CustomCodes: country.DecodeCustomCodes(),
DisplayName: country.DisplayName(),
IsCommon: country.IsCommon,
})
}
return &pb.FindAllRegionCountriesResponse{
@@ -143,12 +145,13 @@ func (this *RegionCountryService) FindRegionCountry(ctx context.Context, req *pb
}
return &pb.FindRegionCountryResponse{RegionCountry: &pb.RegionCountry{
Id: int64(country.Id),
Id: int64(country.ValueId),
Name: country.Name,
Codes: country.DecodeCodes(),
CustomName: country.CustomName,
CustomCodes: country.DecodeCustomCodes(),
DisplayName: country.DisplayName(),
IsCommon: country.IsCommon,
}}, nil
}

View File

@@ -30,7 +30,7 @@ func (this *RegionProviderService) FindAllEnabledRegionProviders(ctx context.Con
var pbProviders = []*pb.RegionProvider{}
for _, provider := range providers {
pbProviders = append(pbProviders, &pb.RegionProvider{
Id: int64(provider.Id),
Id: int64(provider.ValueId),
Name: provider.Name,
Codes: provider.DecodeCodes(),
CustomName: provider.CustomName,
@@ -65,7 +65,7 @@ func (this *RegionProviderService) FindEnabledRegionProvider(ctx context.Context
return &pb.FindEnabledRegionProviderResponse{
RegionProvider: &pb.RegionProvider{
Id: int64(provider.Id),
Id: int64(provider.ValueId),
Name: provider.Name,
Codes: provider.DecodeCodes(),
CustomName: provider.CustomName,
@@ -91,7 +91,7 @@ func (this *RegionProviderService) FindAllRegionProviders(ctx context.Context, r
var pbProviders = []*pb.RegionProvider{}
for _, provider := range providers {
pbProviders = append(pbProviders, &pb.RegionProvider{
Id: int64(provider.Id),
Id: int64(provider.ValueId),
Name: provider.Name,
Codes: provider.DecodeCodes(),
CustomName: provider.CustomName,
@@ -125,7 +125,7 @@ func (this *RegionProviderService) FindRegionProvider(ctx context.Context, req *
return &pb.FindRegionProviderResponse{
RegionProvider: &pb.RegionProvider{
Id: int64(provider.Id),
Id: int64(provider.ValueId),
Name: provider.Name,
Codes: provider.DecodeCodes(),
CustomName: provider.CustomName,

View File

@@ -29,7 +29,7 @@ func (this *RegionProvinceService) FindAllEnabledRegionProvincesWithCountryId(ct
result := []*pb.RegionProvince{}
for _, province := range provinces {
result = append(result, &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.Name,
Codes: province.DecodeCodes(),
CustomName: province.CustomName,
@@ -64,7 +64,7 @@ func (this *RegionProvinceService) FindEnabledRegionProvince(ctx context.Context
return &pb.FindEnabledRegionProvinceResponse{
RegionProvince: &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.Name,
Codes: province.DecodeCodes(),
CustomName: province.CustomName,
@@ -91,7 +91,7 @@ func (this *RegionProvinceService) FindAllRegionProvincesWithRegionCountryId(ctx
var result = []*pb.RegionProvince{}
for _, province := range provinces {
result = append(result, &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.Name,
Codes: province.DecodeCodes(),
CustomName: province.CustomName,
@@ -125,7 +125,7 @@ func (this *RegionProvinceService) FindRegionProvince(ctx context.Context, req *
return &pb.FindRegionProvinceResponse{
RegionProvince: &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.Name,
Codes: province.DecodeCodes(),
CustomName: province.CustomName,

View File

@@ -48,7 +48,7 @@ func (this *RegionTownService) FindAllRegionTowns(ctx context.Context, req *pb.F
}
pbCity = &pb.RegionCity{
Id: int64(city.Id),
Id: int64(city.ValueId),
Name: city.Name,
Codes: city.DecodeCodes(),
CustomName: city.CustomName,
@@ -58,7 +58,7 @@ func (this *RegionTownService) FindAllRegionTowns(ctx context.Context, req *pb.F
}
pbTowns = append(pbTowns, &pb.RegionTown{
Id: int64(town.Id),
Id: int64(town.ValueId),
Name: town.Name,
Codes: town.DecodeCodes(),
RegionCityId: int64(town.CityId),
@@ -95,7 +95,7 @@ func (this *RegionTownService) FindAllRegionTownsWithRegionCityId(ctx context.Co
var pbCity = &pb.RegionCity{Id: cityId}
pbTowns = append(pbTowns, &pb.RegionTown{
Id: int64(town.Id),
Id: int64(town.ValueId),
Name: town.Name,
Codes: town.DecodeCodes(),
RegionCityId: int64(town.CityId),
@@ -131,7 +131,7 @@ func (this *RegionTownService) FindRegionTown(ctx context.Context, req *pb.FindR
return &pb.FindRegionTownResponse{
RegionTown: &pb.RegionTown{
Id: int64(town.Id),
Id: int64(town.ValueId),
Name: town.Name,
Codes: town.DecodeCodes(),
RegionCityId: int64(town.CityId),

View File

@@ -9,13 +9,17 @@ import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
"net"
"net/url"
"regexp"
"strings"
)
@@ -184,6 +188,505 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe
return &pb.CreateServerResponse{ServerId: serverId}, nil
}
// CreateBasicHTTPServer 快速创建基本的HTTP网站
func (this *ServerService) CreateBasicHTTPServer(ctx context.Context, req *pb.CreateBasicHTTPServerRequest) (*pb.CreateBasicHTTPServerResponse, error) {
adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
// 集群
var tx = this.NullTx()
if userId > 0 {
req.UserId = userId
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
if err != nil {
return nil, err
}
req.NodeClusterId = nodeClusterId
} else if adminId > 0 && req.UserId > 0 && req.NodeClusterId <= 0 {
// check user
existUser, err := models.SharedUserDAO.Exist(tx, req.UserId)
if err != nil {
return nil, err
}
if !existUser {
return nil, errors.New("user id '" + types.String(req.UserId) + "' not found")
}
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
if err != nil {
return nil, err
}
req.NodeClusterId = nodeClusterId
}
if req.NodeClusterId <= 0 {
return nil, errors.New("invalid 'nodeClusterId'")
}
if len(req.Domains) == 0 {
return nil, errors.New("'domains' should not be empty")
}
var serverNames = []*serverconfigs.ServerNameConfig{}
for _, domain := range req.Domains {
domain = strings.ToLower(domain)
if !domainutils.ValidateDomainFormat(domain) {
return nil, errors.New("invalid domain format '" + domain + "'")
}
// 检查域名是否已存在
existServerName, err := models.SharedServerDAO.ExistServerNameInCluster(tx, req.NodeClusterId, domain, 0, true)
if err != nil {
return nil, err
}
if existServerName {
return nil, errors.New("domain '" + domain + "' already created by other server")
}
serverNames = append(serverNames, &serverconfigs.ServerNameConfig{Name: domain})
}
serverNamesJSON, err := json.Marshal(serverNames)
if err != nil {
return nil, errors.New("encode 'serverNames' failed: " + err.Error())
}
// 是否需要审核
var isAuditing = false
var auditingServerNamesJSON = []byte("[]")
if userId > 0 {
// 如果域名不为空的时候需要审核
if len(serverNamesJSON) > 0 && string(serverNamesJSON) != "[]" {
globalConfig, err := models.SharedSysSettingDAO.ReadGlobalConfig(tx)
if err != nil {
return nil, err
}
if globalConfig != nil && globalConfig.HTTPAll.DomainAuditingIsOn {
isAuditing = true
serverNamesJSON = []byte("[]")
auditingServerNamesJSON = serverNamesJSON
}
}
}
// HTTP
var httpConfig = &serverconfigs.HTTPProtocolConfig{
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
Listen: []*serverconfigs.NetworkAddressConfig{
{
Protocol: "http",
PortRange: "80",
},
},
},
}
httpJSON, err := json.Marshal(httpConfig)
if err != nil {
return nil, err
}
// HTTPS
var certRefs = []*sslconfigs.SSLCertRef{}
for _, certId := range req.SslCertIds {
// 检查所有权
if userId > 0 {
err = models.SharedSSLCertDAO.CheckUserCert(tx, certId, userId)
if err != nil {
return nil, errors.New("check cert permission failed: " + err.Error())
}
} else {
existCert, err := models.SharedSSLCertDAO.Exist(tx, certId)
if err != nil {
return nil, err
}
if !existCert {
return nil, errors.New("cert '" + types.String(certId) + "' not found")
}
}
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
IsOn: true,
CertId: certId,
})
}
certRefsJSON, err := json.Marshal(certRefs)
if err != nil {
return nil, err
}
sslPolicyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, req.UserId, false, false, "TLS 1.0", certRefsJSON, nil, false, 0, nil, false, nil)
if err != nil {
return nil, err
}
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
Listen: []*serverconfigs.NetworkAddressConfig{
{
Protocol: "https",
PortRange: "443",
},
},
},
SSLPolicyRef: &sslconfigs.SSLPolicyRef{
IsOn: true,
SSLPolicyId: sslPolicyId,
},
}
httpsJSON, err := json.Marshal(httpsConfig)
if err != nil {
return nil, err
}
// Reverse Proxy
var reverseProxyScheduleConfig = &serverconfigs.SchedulingConfig{
Code: "random",
Options: nil,
}
reverseProxyScheduleJSON, err := json.Marshal(reverseProxyScheduleConfig)
var primaryOrigins = []*serverconfigs.OriginRef{}
for _, originAddr := range req.OriginAddrs {
u, err := url.Parse(originAddr)
if err != nil {
return nil, errors.New("parse origin address '" + originAddr + "' failed: " + err.Error())
}
if len(u.Scheme) == 0 || (u.Scheme != "http" && u.Scheme != "https" /** 特意不支持大写形式 **/) {
return nil, errors.New("invalid scheme in origin address '" + originAddr + "'")
}
if len(u.Host) == 0 {
return nil, errors.New("invalid host address '" + originAddr + "', contains no host")
}
host, port, err := net.SplitHostPort(u.Host)
if err != nil {
err = nil // ignore error
if domainutils.ValidateDomainFormat(u.Host) { // host with no port
host = u.Host
port = ""
} else {
return nil, errors.New("invalid host address '" + originAddr + "', invalid host format")
}
}
if len(port) == 0 {
switch u.Scheme {
case "http":
port = "80"
case "https":
port = "443"
}
}
var addr = &serverconfigs.NetworkAddressConfig{
Protocol: serverconfigs.Protocol(u.Scheme),
Host: host,
PortRange: port,
}
addrJSON, err := json.Marshal(addr)
if err != nil {
return nil, err
}
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, req.UserId, "", addrJSON, nil, "", 10, true, nil, nil, nil, 0, 0, nil, nil, u.Host, false, false)
if err != nil {
return nil, err
}
primaryOrigins = append(primaryOrigins, &serverconfigs.OriginRef{
IsOn: true,
OriginId: originId,
})
}
primaryOriginsJSON, err := json.Marshal(primaryOrigins)
if err != nil {
return nil, err
}
reverseProxyId, err := models.SharedReverseProxyDAO.CreateReverseProxy(tx, adminId, req.UserId, reverseProxyScheduleJSON, primaryOriginsJSON, nil)
if err != nil {
return nil, err
}
reverseProxyJSON, err := json.Marshal(&serverconfigs.ReverseProxyRef{
IsPrior: false,
IsOn: true,
ReverseProxyId: reverseProxyId,
})
if err != nil {
return nil, err
}
// Web
webId, err := models.SharedHTTPWebDAO.CreateWeb(tx, adminId, req.UserId, nil)
if err != nil {
return nil, err
}
// Enable websocket
if req.EnableWebsocket {
websocketId, err := models.SharedHTTPWebsocketDAO.CreateWebsocket(tx, nil, true, nil, true, "")
if err != nil {
return nil, err
}
websocketRef, err := json.Marshal(&serverconfigs.HTTPWebsocketRef{
IsPrior: false,
IsOn: true,
WebsocketId: websocketId,
})
if err != nil {
return nil, err
}
err = models.SharedHTTPWebDAO.UpdateWebsocket(tx, webId, websocketRef)
if err != nil {
return nil, err
}
}
// finally, we create ...
serverId, err := models.SharedServerDAO.CreateServer(tx, adminId, req.UserId, serverconfigs.ServerTypeHTTPProxy, req.Domains[0], "", serverNamesJSON, isAuditing, auditingServerNamesJSON, httpJSON, httpsJSON, nil, nil, nil, nil, webId, reverseProxyJSON, req.NodeClusterId, nil, nil, nil, 0)
if err != nil {
return nil, err
}
return &pb.CreateBasicHTTPServerResponse{ServerId: serverId}, nil
}
// CreateBasicTCPServer 快速创建基本的TCP网站
func (this *ServerService) CreateBasicTCPServer(ctx context.Context, req *pb.CreateBasicTCPServerRequest) (*pb.CreateBasicTCPServerResponse, error) {
adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
// 集群
var tx = this.NullTx()
if userId > 0 {
req.UserId = userId
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
if err != nil {
return nil, err
}
req.NodeClusterId = nodeClusterId
} else if adminId > 0 && req.UserId > 0 && req.NodeClusterId <= 0 {
// check user
existUser, err := models.SharedUserDAO.Exist(tx, req.UserId)
if err != nil {
return nil, err
}
if !existUser {
return nil, errors.New("user id '" + types.String(req.UserId) + "' not found")
}
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
if err != nil {
return nil, err
}
req.NodeClusterId = nodeClusterId
}
if req.NodeClusterId <= 0 {
return nil, errors.New("invalid 'nodeClusterId'")
}
// 检查用户权限
if userId > 0 {
features, err := models.SharedUserDAO.FindUserFeatures(tx, userId)
if err != nil {
return nil, err
}
var canSpecifyTCPPort = false
for _, feature := range features {
if feature.Code == "server.tcp.port" {
canSpecifyTCPPort = true
break
}
}
if !canSpecifyTCPPort {
if len(req.TcpPorts) > 0 || len(req.TlsPorts) > 0 {
return nil, errors.New("no permission to specify tcp/tls ports")
}
}
}
if len(req.TcpPorts) == 0 || len(req.TlsPorts) == 0 {
// TODO 未来支持自动创建端口
return nil, errors.New("no ports valid")
}
// TCP
var tcpConfig = &serverconfigs.HTTPProtocolConfig{
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
Listen: []*serverconfigs.NetworkAddressConfig{},
},
}
for _, port := range req.TcpPorts {
existPort, err := models.SharedServerDAO.CheckPortIsUsing(tx, req.NodeClusterId, "tcp", int(port), 0, "")
if err != nil {
return nil, err
}
if existPort {
return nil, errors.New("port '" + types.String(port) + "' already used by other server")
}
tcpConfig.BaseProtocol.Listen = append(tcpConfig.BaseProtocol.Listen, &serverconfigs.NetworkAddressConfig{
Protocol: "tcp",
PortRange: types.String(port),
})
}
tcpJSON, err := json.Marshal(tcpConfig)
if err != nil {
return nil, err
}
// TLS
var tlsConfig = &serverconfigs.HTTPSProtocolConfig{
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
Listen: []*serverconfigs.NetworkAddressConfig{},
},
}
for _, port := range req.TlsPorts {
existPort, err := models.SharedServerDAO.CheckPortIsUsing(tx, req.NodeClusterId, "tcp", int(port), 0, "")
if err != nil {
return nil, err
}
if existPort {
return nil, errors.New("port '" + types.String(port) + "' already used by other server")
}
tlsConfig.BaseProtocol.Listen = append(tlsConfig.BaseProtocol.Listen, &serverconfigs.NetworkAddressConfig{
Protocol: "tls",
PortRange: types.String(port),
})
}
var certRefs = []*sslconfigs.SSLCertRef{}
for _, certId := range req.SslCertIds {
// 检查所有权
if userId > 0 {
err = models.SharedSSLCertDAO.CheckUserCert(tx, certId, userId)
if err != nil {
return nil, errors.New("check cert permission failed: " + err.Error())
}
} else {
existCert, err := models.SharedSSLCertDAO.Exist(tx, certId)
if err != nil {
return nil, err
}
if !existCert {
return nil, errors.New("cert '" + types.String(certId) + "' not found")
}
}
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
IsOn: true,
CertId: certId,
})
}
certRefsJSON, err := json.Marshal(certRefs)
if err != nil {
return nil, err
}
sslPolicyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, req.UserId, false, false, "TLS 1.0", certRefsJSON, nil, false, 0, nil, false, nil)
if err != nil {
return nil, err
}
tlsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
IsOn: true,
SSLPolicyId: sslPolicyId,
}
tlsJSON, err := json.Marshal(tlsConfig)
if err != nil {
return nil, err
}
// Reverse Proxy
var reverseProxyScheduleConfig = &serverconfigs.SchedulingConfig{
Code: "random",
Options: nil,
}
reverseProxyScheduleJSON, err := json.Marshal(reverseProxyScheduleConfig)
var primaryOrigins = []*serverconfigs.OriginRef{}
for _, originAddr := range req.OriginAddrs {
u, err := url.Parse(originAddr)
if err != nil {
return nil, errors.New("parse origin address '" + originAddr + "' failed: " + err.Error())
}
if len(u.Scheme) == 0 || (u.Scheme != "tcp" && u.Scheme != "tls" && u.Scheme != "ssl" /** 特意不支持大写形式 **/) {
return nil, errors.New("invalid scheme in origin address '" + originAddr + "'")
}
if len(u.Host) == 0 {
return nil, errors.New("invalid host address '" + originAddr + "', contains no host")
}
host, port, err := net.SplitHostPort(u.Host)
if err != nil || len(host) == 0 || len(port) == 0 {
err = nil // ignore error
return nil, errors.New("invalid host address '" + originAddr + "', invalid host format")
}
if u.Scheme == "ssl" {
u.Scheme = "tls"
}
var addr = &serverconfigs.NetworkAddressConfig{
Protocol: serverconfigs.Protocol(u.Scheme),
Host: host,
PortRange: port,
}
addrJSON, err := json.Marshal(addr)
if err != nil {
return nil, err
}
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, req.UserId, "", addrJSON, nil, "", 10, true, nil, nil, nil, 0, 0, nil, nil, "", false, false)
if err != nil {
return nil, err
}
primaryOrigins = append(primaryOrigins, &serverconfigs.OriginRef{
IsOn: true,
OriginId: originId,
})
}
primaryOriginsJSON, err := json.Marshal(primaryOrigins)
if err != nil {
return nil, err
}
reverseProxyId, err := models.SharedReverseProxyDAO.CreateReverseProxy(tx, adminId, req.UserId, reverseProxyScheduleJSON, primaryOriginsJSON, nil)
if err != nil {
return nil, err
}
reverseProxyJSON, err := json.Marshal(&serverconfigs.ReverseProxyRef{
IsPrior: false,
IsOn: true,
ReverseProxyId: reverseProxyId,
})
if err != nil {
return nil, err
}
// finally, we create ...
serverId, err := models.SharedServerDAO.CreateServer(tx, adminId, req.UserId, serverconfigs.ServerTypeTCPProxy, "TCP Service", "", nil, false, nil, nil, nil, tcpJSON, tlsJSON, nil, nil, 0, reverseProxyJSON, req.NodeClusterId, nil, nil, nil, 0)
if err != nil {
return nil, err
}
return &pb.CreateBasicTCPServerResponse{ServerId: serverId}, nil
}
// UpdateServerBasic 修改服务基本信息
func (this *ServerService) UpdateServerBasic(ctx context.Context, req *pb.UpdateServerBasicRequest) (*pb.RPCSuccess, error) {
// 校验请求
@@ -798,6 +1301,14 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
order = "trafficOutAsc"
} else if req.TrafficOutDesc {
order = "trafficOutDesc"
} else if req.RequestsAsc {
order = "requestsAsc"
} else if req.RequestsDesc {
order = "requestsDesc"
} else if req.AttackRequestsAsc {
order = "attackRequestsAsc"
} else if req.AttackRequestsDesc {
order = "attackRequestsDesc"
}
servers, err := models.SharedServerDAO.ListEnabledServersMatch(tx, req.Offset, req.Size, req.ServerGroupId, req.Keyword, req.UserId, req.NodeClusterId, req.AuditingFlag, utils.SplitStrings(req.ProtocolFamily, ","), order)
@@ -915,11 +1426,13 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
Id: int64(server.ClusterId),
Name: clusterName,
},
ServerGroups: pbGroups,
UserId: int64(server.UserId),
User: pbUser,
BandwidthTime: server.BandwidthTime,
BandwidthBytes: int64(server.BandwidthBytes),
ServerGroups: pbGroups,
UserId: int64(server.UserId),
User: pbUser,
BandwidthTime: server.BandwidthTime,
BandwidthBytes: int64(server.BandwidthBytes),
CountRequests: int64(server.CountRequests),
CountAttackRequests: int64(server.CountAttackRequests),
})
}

View File

@@ -65,12 +65,12 @@ func init() {
for _, stat := range m {
// 更新服务的带宽峰值
if stat.ServerId > 0 {
err := models.SharedServerBandwidthStatDAO.UpdateServerBandwidth(tx, stat.UserId, stat.ServerId, stat.NodeRegionId, stat.Day, stat.TimeAt, stat.Bytes, stat.TotalBytes, stat.CachedBytes, stat.AttackBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests)
err = models.SharedServerBandwidthStatDAO.UpdateServerBandwidth(tx, stat.UserId, stat.ServerId, stat.NodeRegionId, stat.Day, stat.TimeAt, stat.Bytes, stat.TotalBytes, stat.CachedBytes, stat.AttackBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests)
if err != nil {
remotelogs.Error("ServerBandwidthStatService", "dump bandwidth stats failed: "+err.Error())
}
err = models.SharedServerDAO.UpdateServerBandwidth(tx, stat.ServerId, stat.Day+stat.TimeAt, stat.Bytes)
err = models.SharedServerDAO.UpdateServerBandwidth(tx, stat.ServerId, stat.Day+stat.TimeAt, stat.Bytes, stat.CountRequests, stat.CountAttackRequests)
if err != nil {
remotelogs.Error("ServerBandwidthStatService", "update server bandwidth failed: "+err.Error())
}

View File

@@ -483,6 +483,7 @@ func (this *ServerGroupService) FindEnabledServerGroupConfigInfo(ctx context.Con
result.HasAccessLogConfig = webConfig != nil && webConfig.AccessLogRef != nil && webConfig.AccessLogRef.IsPrior
result.HasStatConfig = webConfig != nil && webConfig.StatRef != nil && webConfig.StatRef.IsPrior
result.HasCompressionConfig = webConfig != nil && webConfig.Compression != nil && webConfig.Compression.IsPrior
result.HasOptimizationConfig = webConfig != nil && webConfig.Optimization != nil && webConfig.Optimization.IsPrior
result.HasWebsocketConfig = webConfig != nil && webConfig.WebsocketRef != nil && webConfig.WebsocketRef.IsPrior
result.HasRequestHeadersConfig = webConfig != nil && webConfig.RequestHeaderPolicyRef != nil && webConfig.RequestHeaderPolicyRef.IsPrior
result.HasResponseHeadersConfig = webConfig != nil && webConfig.ResponseHeaderPolicyRef != nil && webConfig.ResponseHeaderPolicyRef.IsPrior

View File

@@ -62,15 +62,15 @@ func (this *ServerRegionCityMonthlyStatService) FindTopServerRegionCityMonthlySt
continue
}
pbStat.RegionCountry = &pb.RegionCountry{
Id: int64(country.Id),
Id: int64(country.ValueId),
Name: country.DisplayName(),
}
pbStat.RegionProvince = &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.DisplayName(),
}
pbStat.RegionCity = &pb.RegionCity{
Id: int64(city.Id),
Id: int64(city.ValueId),
Name: city.DisplayName(),
}
pbStats = append(pbStats, pbStat)

View File

@@ -46,7 +46,7 @@ func (this *ServerRegionCountryMonthlyStatService) FindTopServerRegionCountryMon
continue
}
pbStat.RegionCountry = &pb.RegionCountry{
Id: int64(country.Id),
Id: int64(country.ValueId),
Name: country.DisplayName(),
}

View File

@@ -45,7 +45,7 @@ func (this *ServerRegionProviderMonthlyStatService) FindTopServerRegionProviderM
continue
}
pbStat.RegionProvider = &pb.RegionProvider{
Id: int64(provider.Id),
Id: int64(provider.ValueId),
Name: provider.DisplayName(),
}
pbStats = append(pbStats, pbStat)

View File

@@ -52,11 +52,11 @@ func (this *ServerRegionProvinceMonthlyStatService) FindTopServerRegionProvinceM
continue
}
pbStat.RegionCountry = &pb.RegionCountry{
Id: int64(country.Id),
Id: int64(country.ValueId),
Name: country.DisplayName(),
}
pbStat.RegionProvince = &pb.RegionProvince{
Id: int64(province.Id),
Id: int64(province.ValueId),
Name: province.DisplayName(),
}
pbStats = append(pbStats, pbStat)

View File

@@ -44,7 +44,7 @@ func (this *SSLPolicyService) CreateSSLPolicy(ctx context.Context, req *pb.Creat
// TODO
}
policyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, userId, req.Http2Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
policyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, userId, req.Http2Enabled, req.Http3Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
if err != nil {
return nil, err
}
@@ -63,13 +63,13 @@ func (this *SSLPolicyService) UpdateSSLPolicy(ctx context.Context, req *pb.Updat
var tx = this.NullTx()
if userId > 0 {
err := models.SharedSSLPolicyDAO.CheckUserPolicy(tx, userId, req.SslPolicyId)
err = models.SharedSSLPolicyDAO.CheckUserPolicy(tx, userId, req.SslPolicyId)
if err != nil {
return nil, errors.New("check ssl policy failed: " + err.Error())
}
}
err = models.SharedSSLPolicyDAO.UpdatePolicy(tx, req.SslPolicyId, req.Http2Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
err = models.SharedSSLPolicyDAO.UpdatePolicy(tx, req.SslPolicyId, req.Http2Enabled, req.Http3Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
if err != nil {
return nil, err
}

Some files were not shown because too many files have changed in this diff Show More