Compare commits

...

51 Commits

Author SHA1 Message Date
刘祥超
57247d0f5b 修复访问日志可能无法写入当天数据表的Bug 2022-03-23 10:58:54 +08:00
刘祥超
813267c50f 修复访问日志表可能无法自动创建的Bug 2022-03-23 10:05:42 +08:00
刘祥超
b8078e73b2 更改版本为v0.4.6 2022-03-23 10:03:57 +08:00
刘祥超
f958c57984 优化代码 2022-03-22 22:11:32 +08:00
刘祥超
30bfbdc01e 优化代码 2022-03-22 21:45:07 +08:00
刘祥超
314362c24d 优化代码 2022-03-22 19:30:30 +08:00
刘祥超
8582715be7 字段中的blob和JSON类型映射为[]byte和dbs.JSON 2022-03-21 21:39:36 +08:00
刘祥超
74e585263c 升级TeaGo 2022-03-21 19:46:14 +08:00
刘祥超
35cb10fffe 自动升级一个SQL注入规则 2022-03-20 11:54:17 +08:00
刘祥超
7c84794ac4 GRPC通讯支持gzip压缩 2022-03-20 11:28:45 +08:00
刘祥超
5859f5df91 更新相关库 2022-03-20 10:50:34 +08:00
刘祥超
e370944233 OCSP支持过期时间 2022-03-18 20:21:24 +08:00
刘祥超
a23a2ed826 获取OCSP更新列表兼容MySQL 5.7.22以下版本 2022-03-18 18:28:28 +08:00
刘祥超
3f9c250dff 动态更新OCSP,防止过期 2022-03-18 17:08:51 +08:00
刘祥超
06c9c9403b WAF统计图表中把page归为拦截,把tag归为记录 2022-03-17 16:49:46 +08:00
刘祥超
0e580a0890 源站支持自定义回源主机名 2022-03-17 15:48:40 +08:00
刘祥超
7aba622403 增加置顶集群功能 2022-03-17 11:12:46 +08:00
刘祥超
72cc8389e6 修复服务配置可能无法更新的Bug 2022-03-16 21:42:56 +08:00
刘祥超
39cf470b0c 上传SQL 2022-03-16 17:15:54 +08:00
刘祥超
6e71dda713 节点可以单独设置缓存目录 2022-03-16 15:23:58 +08:00
刘祥超
10909e28c8 修复集群配置/节点配置无法同步的Bug 2022-03-16 15:23:36 +08:00
刘祥超
6bd6e350b9 WAF全局看板中拦截类型只显示当天的统计/合并同名规则分组统计 2022-03-14 16:44:56 +08:00
刘祥超
d2ae7834ae 增加SQL子版本 2022-03-14 16:06:25 +08:00
刘祥超
c1ffd25c8b 上传SQL 2022-03-14 15:43:24 +08:00
刘祥超
931e55162b 缓存策略可以使用存储类型筛选 2022-03-14 15:42:48 +08:00
刘祥超
fa2bac6d1d 实现源站跟随功能 2022-03-14 15:42:45 +08:00
刘祥超
2f7b7240dd 增加证书OCSP错误日志管理 2022-03-11 20:27:53 +08:00
刘祥超
da67e726a2 优化代码 2022-03-11 17:39:08 +08:00
刘祥超
6cb5529c3f 证书ocsp获取失败时,报告错误 2022-03-11 13:02:53 +08:00
刘祥超
473d0d9439 修改OCSP自动更新的间隔时间和条数 2022-03-11 10:00:53 +08:00
刘祥超
bf0db231fc 上传sql 2022-03-10 21:33:08 +08:00
刘祥超
5644906b77 HTTP DNS QueryRecord动作支持返回null 2022-03-10 19:45:03 +08:00
刘祥超
3e32fe8e10 HTTP DNS请求时增加Content-Type 2022-03-10 19:13:53 +08:00
刘祥超
8459f106e9 域名操作错误时显示具体的域名、记录信息等 2022-03-10 17:42:23 +08:00
刘祥超
b768bbce5d 修改用户平台版本为0.3.2 2022-03-10 16:05:21 +08:00
刘祥超
9e7beb39c0 修复用户可能无法添加黑白名单IP的Bug 2022-03-10 15:59:00 +08:00
刘祥超
94287f5857 增加OCSP Stapling功能 2022-03-10 11:54:35 +08:00
刘祥超
60690dfd01 使用IPv6的IP搜索访问日志时自动去掉[] 2022-03-09 11:10:56 +08:00
刘祥超
fb00a7931e 支持使用小时筛选访问日志 2022-03-09 11:00:54 +08:00
刘祥超
42a6494bde 增加对访问日志自动分表配置 2022-03-09 10:01:24 +08:00
刘祥超
85a46a9827 自动对访问日志进行分表 2022-03-08 19:55:39 +08:00
刘祥超
088636553c 修复审计日志无法自动清理的Bug 2022-03-08 09:53:10 +08:00
刘祥超
95de3b12e2 缓存一些看板数据,以加快看板打开速度 2022-03-07 11:45:58 +08:00
刘祥超
b66b8d198a 更新相关库 2022-03-07 09:58:17 +08:00
刘祥超
e968a79886 更新TeaGo 2022-03-04 15:08:56 +08:00
刘祥超
4fc5d5b549 升级相关依赖库 2022-03-04 12:31:44 +08:00
刘祥超
77606709b3 增加是否同步写入压缩缓存设置 2022-02-24 20:11:53 +08:00
刘祥超
3529ceefcd 修改版本为0.4.5 2022-02-24 19:25:31 +08:00
刘祥超
7e851f07b1 修改版本为0.4.4 2022-02-23 14:49:12 +08:00
刘祥超
a62711e520 修改版本为v0.4.3 2022-02-21 18:31:47 +08:00
刘祥超
ffce574b39 更改版本为v0.4.2 2022-02-21 17:52:53 +08:00
289 changed files with 4620 additions and 2566 deletions

21
go.mod
View File

@@ -1,31 +1,26 @@
module github.com/TeaOSLab/EdgeAPI
go 1.15
go 1.16
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
require (
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183
github.com/andybalholm/brotli v1.0.4
github.com/cespare/xxhash/v2 v2.1.1
github.com/go-acme/lego/v4 v4.5.2
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/go-sql-driver/mysql v1.5.0
github.com/go-yaml/yaml v2.1.0+incompatible
github.com/golang/protobuf v1.5.2
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24
github.com/iwind/TeaGo v0.0.0-20220321132348-7da816422f25 // indirect
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
github.com/json-iterator/go v1.1.12 // indirect
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible
github.com/mozillazg/go-pinyin v0.18.0
github.com/pkg/sftp v1.12.0
github.com/shirou/gopsutil v3.21.5+incompatible
github.com/tklauser/go-sysconf v0.3.6 // indirect
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect
google.golang.org/grpc v1.38.0
google.golang.org/protobuf v1.26.0
github.com/shirou/gopsutil/v3 v3.22.2
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

101
go.sum
View File

@@ -43,8 +43,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -52,6 +50,7 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183 h1:dkj8/dxOQ4L1XpwCzRLqukvUBbx
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
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/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
@@ -78,6 +77,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI=
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=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -101,7 +104,8 @@ github.com/dnsimple/dnsimple-go v0.70.1/go.mod h1:F9WHww9cC76hrnwGFfAfrqdW99j3MO
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=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/exoscale/egoscale v0.67.0/go.mod h1:wi0myUxPsV8SdEtdJHQJxFLL/wEw9fiw9Gs1PWRkvkM=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -122,8 +126,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
@@ -132,8 +136,6 @@ github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gG
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -161,6 +163,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
@@ -173,8 +176,10 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
@@ -201,6 +206,7 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@@ -231,11 +237,13 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13 h1:HuEJ5xJfujW1Q6rNDhOu5LQXEBB2qLPah3jYslT8Gz4=
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24 h1:1cGulkD2SNJJRok5OKwyhP/Ddm+PgSWKOupn0cR36/A=
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
github.com/iwind/TeaGo v0.0.0-20220321112016-5a2cd71d3151 h1:jksmjwlGC8QMpyHZmzxr7J+3NeMOr9Zy2+yNJxVSIjI=
github.com/iwind/TeaGo v0.0.0-20220321112016-5a2cd71d3151/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
github.com/iwind/TeaGo v0.0.0-20220321131553-fd7b112ba7e7 h1:gdMQZQk/aXfNuKuWCBQhP3byy5Dr8XHMe5+GXdGHcPQ=
github.com/iwind/TeaGo v0.0.0-20220321131553-fd7b112ba7e7/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
github.com/iwind/TeaGo v0.0.0-20220321132348-7da816422f25 h1:UpJ52iq8FEz2OeaXFhW1kuYeqVRUQ/5N+NVHvVuTnvw=
github.com/iwind/TeaGo v0.0.0-20220321132348-7da816422f25/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
@@ -250,8 +258,6 @@ github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -277,12 +283,12 @@ github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/linode/linodego v0.31.1/go.mod h1:BR0gVkCJffEdIGJSl6bHR80Ty+Uvg/2jkjmrWaFectM=
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible h1:1qp9iks+69h7IGLazAplzS9Ca14HAxuD5c0rbFdPGy4=
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
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/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -322,7 +328,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
@@ -371,6 +376,8 @@ github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
@@ -390,14 +397,15 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc=
github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -436,10 +444,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
@@ -456,13 +464,15 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@@ -482,8 +492,9 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -507,7 +518,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@@ -516,7 +526,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -551,8 +560,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -588,6 +599,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -611,19 +623,23 @@ golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -631,8 +647,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -674,7 +691,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -714,9 +730,10 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus=
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg=
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -726,9 +743,10 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -739,8 +757,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -58,7 +58,7 @@ func (this *StorageManager) Loop() error {
}
var policyIds = []int64{}
for _, policy := range policies {
if policy.IsOn == 1 {
if policy.IsOn {
policyIds = append(policyIds, int64(policy.Id))
}
}
@@ -92,7 +92,7 @@ func (this *StorageManager) Loop() error {
}
if len(policy.Options) > 0 {
err = json.Unmarshal([]byte(policy.Options), storage.Config())
err = json.Unmarshal(policy.Options, storage.Config())
if err != nil {
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "unmarshal policy '"+types.String(policyId)+"' config failed: "+err.Error())
storage.SetOk(false)
@@ -110,7 +110,7 @@ func (this *StorageManager) Loop() error {
remotelogs.Println("ACCESS_LOG_STORAGE_MANAGER", "restart policy '"+types.String(policyId)+"'")
}
} else {
storage, err := this.createStorage(policy.Type, []byte(policy.Options))
storage, err := this.createStorage(policy.Type, policy.Options)
if err != nil {
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "create policy '"+types.String(policyId)+"' failed: "+err.Error())
continue

View File

@@ -2,8 +2,8 @@ package configs
import (
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
"github.com/go-yaml/yaml"
"github.com/iwind/TeaGo/Tea"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
"path/filepath"

View File

@@ -1,7 +1,7 @@
package teaconst
const (
Version = "0.4.1"
Version = "0.4.6"
ProductName = "Edge API"
ProcessName = "edge-api"
@@ -18,10 +18,13 @@ const (
// 其他节点版本号,用来检测是否有需要升级的节点
NodeVersion = "0.4.1"
UserNodeVersion = "0.3.1"
NodeVersion = "0.4.5"
UserNodeVersion = "0.3.2"
AuthorityNodeVersion = "0.0.2"
MonitorNodeVersion = "0.0.3"
DNSNodeVersion = "0.2.1"
ReportNodeVersion = "0.1.0"
// SQLVersion SQL版本号
SQLVersion = "5"
)

View File

@@ -1,19 +1,21 @@
package accounts
import "github.com/iwind/TeaGo/dbs"
// UserAccountLog 用户账户日志
type UserAccountLog struct {
Id uint64 `field:"id"` // ID
UserId uint64 `field:"userId"` // 用户ID
AccountId uint64 `field:"accountId"` // 账户ID
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
Total float64 `field:"total"` // 操作后余额
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
EventType string `field:"eventType"` // 类型
Description string `field:"description"` // 描述文字
Day string `field:"day"` // YYYYMMDD
CreatedAt uint64 `field:"createdAt"` // 时间
Params string `field:"params"` // 参数
Id uint64 `field:"id"` // ID
UserId uint64 `field:"userId"` // 用户ID
AccountId uint64 `field:"accountId"` // 账户ID
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
Total float64 `field:"total"` // 操作后余额
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
EventType string `field:"eventType"` // 类型
Description string `field:"description"` // 描述文字
Day string `field:"day"` // YYYYMMDD
CreatedAt uint64 `field:"createdAt"` // 时间
Params dbs.JSON `field:"params"` // 参数
}
type UserAccountLogOperator struct {

View File

@@ -3,7 +3,7 @@ package acme
// ACMEProviderAccount ACME提供商
type ACMEProviderAccount struct {
Id uint64 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
ProviderCode string `field:"providerCode"` // 代号
Error string `field:"error"` // 最后一条错误信息

View File

@@ -271,7 +271,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
errMsg = "找不到要执行的任务"
return
}
if task.IsOn != 1 {
if !task.IsOn {
errMsg = "任务没有启用"
return
}
@@ -330,7 +330,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
})
if len(user.Registration) > 0 {
err = remoteUser.SetRegistration([]byte(user.Registration))
err = remoteUser.SetRegistration(user.Registration)
if err != nil {
errMsg = "设置注册信息时出错:" + err.Error()
return
@@ -453,7 +453,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
return
}
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn == 1, cert.Name, cert.Description, cert.ServerName, cert.IsCA == 1, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn, cert.Name, cert.Description, cert.ServerName, cert.IsCA, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
if err != nil {
errMsg = "证书生成成功,但是修改数据库中的证书信息时出错:" + err.Error()
return

View File

@@ -1,10 +1,10 @@
package acme
// ACME任务运行日志
// ACMETaskLog ACME任务运行日志
type ACMETaskLog struct {
Id uint64 `field:"id"` // ID
TaskId uint64 `field:"taskId"` // 任务ID
IsOk uint8 `field:"isOk"` // 是否成功
IsOk bool `field:"isOk"` // 是否成功
Error string `field:"error"` // 错误信息
CreatedAt uint64 `field:"createdAt"` // 运行时间
}

View File

@@ -1,21 +1,23 @@
package acme
import "github.com/iwind/TeaGo/dbs"
// ACMETask ACME任务
type ACMETask struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
DnsDomain string `field:"dnsDomain"` // DNS主域名
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
Domains string `field:"domains"` // 证书域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
CertId uint64 `field:"certId"` // 生成的证书ID
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
AuthType string `field:"authType"` // 认证类型
AuthURL string `field:"authURL"` // 认证URL
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
DnsDomain string `field:"dnsDomain"` // DNS主域名
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
Domains dbs.JSON `field:"domains"` // 证书域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
CertId uint64 `field:"certId"` // 生成的证书ID
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
AuthType string `field:"authType"` // 认证类型
AuthURL string `field:"authURL"` // 认证URL
}
type ACMETaskOperator struct {

View File

@@ -5,13 +5,13 @@ import (
"github.com/iwind/TeaGo/logs"
)
// 将域名解析成字符串数组
// DecodeDomains 将域名解析成字符串数组
func (this *ACMETask) DecodeDomains() []string {
if len(this.Domains) == 0 || this.Domains == "null" {
if len(this.Domains) == 0 {
return nil
}
result := []string{}
err := json.Unmarshal([]byte(this.Domains), &result)
err := json.Unmarshal(this.Domains, &result)
if err != nil {
logs.Error(err)
return nil

View File

@@ -1,18 +1,20 @@
package acme
import "github.com/iwind/TeaGo/dbs"
// ACMEUser ACME用户
type ACMEUser struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
PrivateKey string `field:"privateKey"` // 私钥
Email string `field:"email"` // E-mail
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 备注介绍
Registration string `field:"registration"` // 注册信息
ProviderCode string `field:"providerCode"` // 服务商代号
AccountId uint64 `field:"accountId"` // 提供商ID
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
PrivateKey string `field:"privateKey"` // 私钥
Email string `field:"email"` // E-mail
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 备注介绍
Registration dbs.JSON `field:"registration"` // 注册信息
ProviderCode string `field:"providerCode"` // 服务商代号
AccountId uint64 `field:"accountId"` // 提供商ID
}
type ACMEUserOperator struct {

View File

@@ -1,19 +1,21 @@
package models
import "github.com/iwind/TeaGo/dbs"
// Admin 管理员
type Admin struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Username string `field:"username"` // 用户名
Password string `field:"password"` // 密码
Fullname string `field:"fullname"` // 全名
IsSuper uint8 `field:"isSuper"` // 是否为超级管理员
CreatedAt uint64 `field:"createdAt"` // 创建时间
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
State uint8 `field:"state"` // 状态
Modules string `field:"modules"` // 允许的模块
CanLogin uint8 `field:"canLogin"` // 是否可以登录
Theme string `field:"theme"` // 模板设置
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Username string `field:"username"` // 用户名
Password string `field:"password"` // 密码
Fullname string `field:"fullname"` // 全名
IsSuper bool `field:"isSuper"` // 是否为超级管理员
CreatedAt uint64 `field:"createdAt"` // 创建时间
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
State uint8 `field:"state"` // 状态
Modules dbs.JSON `field:"modules"` // 允许的模块
CanLogin uint8 `field:"canLogin"` // 是否可以登录
Theme string `field:"theme"` // 模板设置
}
type AdminOperator struct {

View File

@@ -1,26 +1,28 @@
package models
// API节点
import "github.com/iwind/TeaGo/dbs"
// APINode API节点
type APINode struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
ClusterId uint32 `field:"clusterId"` // 专用集群ID
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Http string `field:"http"` // 监听的HTTP配置
Https string `field:"https"` // 监听的HTTPS配置
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
RestHTTP string `field:"restHTTP"` // REST HTTP配置
RestHTTPS string `field:"restHTTPS"` // REST HTTPS配置
AccessAddrs string `field:"accessAddrs"` // 外部访问地址
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status string `field:"status"` // 运行状态
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
ClusterId uint32 `field:"clusterId"` // 专用集群ID
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Http dbs.JSON `field:"http"` // 监听的HTTP配置
Https dbs.JSON `field:"https"` // 监听的HTTPS配置
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
RestHTTP dbs.JSON `field:"restHTTP"` // REST HTTP配置
RestHTTPS dbs.JSON `field:"restHTTPS"` // REST HTTPS配置
AccessAddrs dbs.JSON `field:"accessAddrs"` // 外部访问地址
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status dbs.JSON `field:"status"` // 运行状态
}
type APINodeOperator struct {

View File

@@ -13,7 +13,7 @@ func (this *APINode) DecodeHTTP() (*serverconfigs.HTTPProtocolConfig, error) {
return nil, nil
}
config := &serverconfigs.HTTPProtocolConfig{}
err := json.Unmarshal([]byte(this.Http), config)
err := json.Unmarshal(this.Http, config)
if err != nil {
return nil, err
}
@@ -32,7 +32,7 @@ func (this *APINode) DecodeHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*serverc
return nil, nil
}
config := &serverconfigs.HTTPSProtocolConfig{}
err := json.Unmarshal([]byte(this.Https), config)
err := json.Unmarshal(this.Https, config)
if err != nil {
return nil, err
}
@@ -70,7 +70,7 @@ func (this *APINode) DecodeAccessAddrs() ([]*serverconfigs.NetworkAddressConfig,
}
addrConfigs := []*serverconfigs.NetworkAddressConfig{}
err := json.Unmarshal([]byte(this.AccessAddrs), &addrConfigs)
err := json.Unmarshal(this.AccessAddrs, &addrConfigs)
if err != nil {
return nil, err
}
@@ -105,7 +105,7 @@ func (this *APINode) DecodeRestHTTP() (*serverconfigs.HTTPProtocolConfig, error)
return nil, nil
}
config := &serverconfigs.HTTPProtocolConfig{}
err := json.Unmarshal([]byte(this.RestHTTP), config)
err := json.Unmarshal(this.RestHTTP, config)
if err != nil {
return nil, err
}
@@ -130,7 +130,7 @@ func (this *APINode) DecodeRestHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*ser
return nil, nil
}
config := &serverconfigs.HTTPSProtocolConfig{}
err := json.Unmarshal([]byte(this.RestHTTPS), config)
err := json.Unmarshal(this.RestHTTPS, config)
if err != nil {
return nil, err
}

View File

@@ -1,15 +1,17 @@
package authority
import "github.com/iwind/TeaGo/dbs"
// AuthorityKey 企业版认证信息
type AuthorityKey struct {
Id uint32 `field:"id"` // ID
Value string `field:"value"` // Key值
DayFrom string `field:"dayFrom"` // 开始日期
DayTo string `field:"dayTo"` // 结束日期
Hostname string `field:"hostname"` // Hostname
MacAddresses string `field:"macAddresses"` // MAC地址
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
Company string `field:"company"` // 公司组织
Id uint32 `field:"id"` // ID
Value string `field:"value"` // Key值
DayFrom string `field:"dayFrom"` // 开始日期
DayTo string `field:"dayTo"` // 结束日期
Hostname string `field:"hostname"` // Hostname
MacAddresses dbs.JSON `field:"macAddresses"` // MAC地址
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
Company string `field:"company"` // 公司组织
}
type AuthorityKeyOperator struct {

View File

@@ -1,19 +1,21 @@
package authority
import "github.com/iwind/TeaGo/dbs"
// AuthorityNode 监控节点
type AuthorityNode struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status string `field:"status"` // 运行状态
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status dbs.JSON `field:"status"` // 运行状态
}
type AuthorityNodeOperator struct {

View File

@@ -1,11 +1,13 @@
package models
// 终端浏览器信息
import "github.com/iwind/TeaGo/dbs"
// ClientBrowser 终端浏览器信息
type ClientBrowser struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 浏览器名称
Codes string `field:"codes"` // 代号
State uint8 `field:"state"` // 状态
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 浏览器名称
Codes dbs.JSON `field:"codes"` // 代号
State uint8 `field:"state"` // 状态
}
type ClientBrowserOperator struct {

View File

@@ -1,11 +1,13 @@
package models
// 终端操作系统信息
import "github.com/iwind/TeaGo/dbs"
// ClientSystem 终端操作系统信息
type ClientSystem struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 系统名称
Codes string `field:"codes"` // 代号
State uint8 `field:"state"` //
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 系统名称
Codes dbs.JSON `field:"codes"` // 代号
State uint8 `field:"state"` //
}
type ClientSystemOperator struct {

View File

@@ -29,8 +29,7 @@ type httpAccessLogDefinition struct {
}
// HTTP服务访问
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
var httpAccessLogTableMapping = map[string]*httpAccessLogDefinition{} // tableName_crc(dsn) => true
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
// DNS服务访问
var nsAccessLogDAOMapping = map[int64]*NSAccessLogDAOWrapper{} // dbNodeId => DAO
@@ -86,36 +85,6 @@ func randomNSAccessLogDAO() (dao *NSAccessLogDAOWrapper) {
return
}
// 检查表格是否存在
func findHTTPAccessLogTableName(db *dbs.DB, day string) (tableName string, hasRemoteAddr bool, hasDomain bool, ok bool, err error) {
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
return
}
config, err := db.Config()
if err != nil {
return "", false, false, false, err
}
tableName = "edgeHTTPAccessLogs_" + day
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
accessLogLocker.RLock()
def, ok := httpAccessLogTableMapping[cacheKey]
accessLogLocker.RUnlock()
if ok {
return tableName, def.HasRemoteAddr, def.HasDomain, true, nil
}
def, err = findHTTPAccessLogTable(db, day, false)
if err != nil {
return tableName, false, false, false, err
}
return tableName, def.HasRemoteAddr, def.HasDomain, def.Exists, nil
}
func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool, err error) {
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
@@ -145,75 +114,6 @@ func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool
return tableName, utils.ContainsStringInsensitive(tableNames, tableName), nil
}
// 根据日期获取表名
func findHTTPAccessLogTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
config, err := db.Config()
if err != nil {
return nil, err
}
tableName := "edgeHTTPAccessLogs_" + day
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
if !force {
accessLogLocker.RLock()
definition, ok := httpAccessLogTableMapping[cacheKey]
accessLogLocker.RUnlock()
if ok {
return definition, nil
}
}
tableNames, err := db.TableNames()
if err != nil {
return nil, err
}
if utils.ContainsStringInsensitive(tableNames, tableName) {
table, err := db.FindTable(tableName)
if err != nil {
return nil, err
}
accessLogLocker.Lock()
var definition = &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: table.FindFieldWithName("remoteAddr") != nil,
HasDomain: table.FindFieldWithName("domain") != nil,
Exists: true,
}
httpAccessLogTableMapping[cacheKey] = definition
accessLogLocker.Unlock()
return definition, nil
}
if !force {
return &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: true,
HasDomain: true,
Exists: false,
}, nil
}
// 创建表格
_, err = db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
if err != nil {
return nil, err
}
accessLogLocker.Lock()
var definition = &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: true,
Exists: true,
}
httpAccessLogTableMapping[cacheKey] = definition
accessLogLocker.Unlock()
return definition, nil
}
func findNSAccessLogTable(db *dbs.DB, day string, force bool) (string, error) {
config, err := db.Config()
if err != nil {
@@ -351,22 +251,17 @@ func (this *DBNodeInitializer) loop() error {
// 检查表是否存在
// httpAccessLog
{
tableDef, err := findHTTPAccessLogTable(db, timeutil.Format("Ymd"), true)
tableDef, err := SharedHTTPAccessLogManager.FindTable(db, timeutil.Format("Ymd"), true)
if err != nil {
if !strings.Contains(err.Error(), "1050") { // 非表格已存在错误
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
// 创建节点日志
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix(), "", nil)
if createLogErr != nil {
remotelogs.Error("NODE_LOG", createLogErr.Error())
}
continue
} else {
err = nil
continue
// 创建节点日志
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix(), "", nil)
if createLogErr != nil {
remotelogs.Error("NODE_LOG", createLogErr.Error())
}
continue
}
daoObject := dbs.DAOObject{

View File

@@ -1,9 +1,7 @@
package models
import (
"runtime"
"testing"
"time"
)
func TestDBNodeInitializer_loop(t *testing.T) {
@@ -14,32 +12,3 @@ func TestDBNodeInitializer_loop(t *testing.T) {
}
t.Log(len(accessLogDBMapping), len(httpAccessLogDAOMapping))
}
func TestFindAccessLogTable(t *testing.T) {
before := time.Now()
db := SharedHTTPAccessLogDAO.Instance
tableName, err := findHTTPAccessLogTable(db, "20201010", false)
if err != nil {
t.Fatal(err)
}
t.Log(tableName)
t.Log(time.Since(before).Seconds()*1000, "ms")
before = time.Now()
tableName, err = findHTTPAccessLogTable(db, "20201010", false)
if err != nil {
t.Fatal(err)
}
t.Log(tableName)
t.Log(time.Since(before).Seconds()*1000, "ms")
}
func BenchmarkFindAccessLogTable(b *testing.B) {
db := SharedHTTPAccessLogDAO.Instance
runtime.GOMAXPROCS(1)
for i := 0; i < b.N; i++ {
_, _ = findHTTPAccessLogTable(db, "20201010", false)
}
}

View File

@@ -1,9 +1,9 @@
package models
// 数据库节点
// DBNode 数据库节点
type DBNode struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
IsOn bool `field:"isOn"` // 是否启用
Role string `field:"role"` // 数据库角色
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述

View File

@@ -1,22 +1,24 @@
package dns
import "github.com/iwind/TeaGo/dbs"
// DNSDomain 管理的域名
type DNSDomain struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ProviderId uint32 `field:"providerId"` // 服务商ID
IsOn uint8 `field:"isOn"` // 是否可用
Name string `field:"name"` // 域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
DataError string `field:"dataError"` // 数据更新错误
Data string `field:"data"` // 原始数据信息
Records string `field:"records"` // 所有解析记录
Routes string `field:"routes"` // 线路数据
IsUp uint8 `field:"isUp"` // 是否在线
State uint8 `field:"state"` // 状态
IsDeleted uint8 `field:"isDeleted"` // 是否已删除
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ProviderId uint32 `field:"providerId"` // 服务商ID
IsOn bool `field:"isOn"` // 是否可用
Name string `field:"name"` // 域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
DataError string `field:"dataError"` // 数据更新错误
Data string `field:"data"` // 原始数据信息
Records dbs.JSON `field:"records"` // 所有解析记录
Routes dbs.JSON `field:"routes"` // 线路数据
IsUp bool `field:"isUp"` // 是否在线
State uint8 `field:"state"` // 状态
IsDeleted bool `field:"isDeleted"` // 是否已删除
}
type DNSDomainOperator struct {

View File

@@ -7,11 +7,11 @@ import (
// DecodeRoutes 获取所有的线路
func (this *DNSDomain) DecodeRoutes() ([]*dnstypes.Route, error) {
if len(this.Routes) == 0 || this.Routes == "null" {
if len(this.Routes) == 0 {
return nil, nil
}
result := []*dnstypes.Route{}
err := json.Unmarshal([]byte(this.Routes), &result)
err := json.Unmarshal(this.Routes, &result)
if err != nil {
return nil, err
}
@@ -35,11 +35,11 @@ func (this *DNSDomain) ContainsRouteCode(route string) (bool, error) {
// DecodeRecords 获取所有的记录
func (this *DNSDomain) DecodeRecords() ([]*dnstypes.Record, error) {
records := this.Records
if len(records) == 0 || records == "null" {
if len(records) == 0 {
return nil, nil
}
result := []*dnstypes.Record{}
err := json.Unmarshal([]byte(records), &result)
err := json.Unmarshal(records, &result)
if err != nil {
return nil, err
}

View File

@@ -1,16 +1,18 @@
package dns
// DNS服务商
import "github.com/iwind/TeaGo/dbs"
// DNSProvider DNS服务商
type DNSProvider struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Type string `field:"type"` // 供应商类型
ApiParams string `field:"apiParams"` // API参数
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Type string `field:"type"` // 供应商类型
ApiParams dbs.JSON `field:"apiParams"` // API参数
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
}
type DNSProviderOperator struct {

View File

@@ -5,12 +5,12 @@ import (
"github.com/iwind/TeaGo/maps"
)
// 获取API参数
// DecodeAPIParams 获取API参数
func (this *DNSProvider) DecodeAPIParams() (maps.Map, error) {
if len(this.ApiParams) == 0 || this.ApiParams == "null" {
if len(this.ApiParams) == 0 {
return maps.Map{}, nil
}
result := maps.Map{}
err := json.Unmarshal([]byte(this.ApiParams), &result)
err := json.Unmarshal(this.ApiParams, &result)
return result, err
}

View File

@@ -9,8 +9,8 @@ type DNSTask struct {
DomainId uint32 `field:"domainId"` // 域名ID
Type string `field:"type"` // 任务类型
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
IsDone uint8 `field:"isDone"` // 是否已完成
IsOk uint8 `field:"isOk"` // 是否成功
IsDone bool `field:"isDone"` // 是否已完成
IsOk bool `field:"isOk"` // 是否成功
Error string `field:"error"` // 错误信息
}

View File

@@ -4,7 +4,7 @@ package models
type FileChunk struct {
Id uint32 `field:"id"` // ID
FileId uint32 `field:"fileId"` // 文件ID
Data string `field:"data"` // 分块内容
Data []byte `field:"data"` // 分块内容
}
type FileChunkOperator struct {

View File

@@ -12,8 +12,8 @@ type File struct {
Order uint32 `field:"order"` // 排序
Type string `field:"type"` // 类型
State uint8 `field:"state"` // 状态
IsFinished uint8 `field:"isFinished"` // 是否已完成上传
IsPublic uint8 `field:"isPublic"` // 是否可以公开访问
IsFinished bool `field:"isFinished"` // 是否已完成上传
IsPublic bool `field:"isPublic"` // 是否可以公开访问
}
type FileOperator struct {

View File

@@ -34,13 +34,25 @@ type HTTPAccessLogDAO dbs.DAO
var SharedHTTPAccessLogDAO *HTTPAccessLogDAO
// 队列
var oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
var accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
var accessLogQueueMaxLength = 100_000
var accessLogQueuePercent = 100 // 0-100
var accessLogCountPerSecond = 10_000 // 0 表示不限制
var accessLogConfigJSON = []byte{}
var accessLogQueueChanged = make(chan zero.Zero, 1)
var (
oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
accessLogQueueMaxLength = 100_000
accessLogQueuePercent = 100 // 0-100
accessLogCountPerSecond = 10_000 // 0 表示不限制
accessLogConfigJSON = []byte{}
accessLogQueueChanged = make(chan zero.Zero, 1)
accessLogEnableAutoPartial = true // 是否启用自动分表
accessLogRowsPerTable int64 = 500_000 // 自动分表的单表最大值
)
type accessLogTableQuery struct {
daoWrapper *HTTPAccessLogDAOWrapper
name string
hasRemoteAddrField bool
hasDomainField bool
}
func init() {
dbs.OnReady(func() {
@@ -120,7 +132,7 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLogs(tx *dbs.Tx, accessLogs []*pb.
// DumpAccessLogsFromQueue 从队列导入访问日志
func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(tx *dbs.Tx, size int) error {
dao := randomHTTPAccessLogDAO()
var dao = randomHTTPAccessLogDAO()
if dao == nil {
dao = &HTTPAccessLogDAOWrapper{
DAO: SharedHTTPAccessLogDAO,
@@ -168,8 +180,8 @@ Loop:
// CreateHTTPAccessLog 写入单条访问日志
func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLogDAO, accessLog *pb.HTTPAccessLog) error {
day := timeutil.Format("Ymd", time.Unix(accessLog.Timestamp, 0))
tableDef, err := findHTTPAccessLogTable(dao.Instance, day, false)
var day = timeutil.FormatTime("Ymd", accessLog.Timestamp)
tableDef, err := SharedHTTPAccessLogManager.FindTable(dao.Instance, day, true)
if err != nil {
return err
}
@@ -203,27 +215,33 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
}
fields["content"] = content
_, err = dao.Query(tx).
var lastId int64
lastId, err = dao.Query(tx).
Table(tableDef.Name).
Sets(fields).
Insert()
if err != nil {
// 是否为 Error 1146: Table 'xxx.xxx' doesn't exist 如果是,则创建表之后重试
if strings.Contains(err.Error(), "1146") {
tableDef, err = findHTTPAccessLogTable(dao.Instance, day, true)
// 错误重试
if CheckSQLErrCode(err, 1146) { // Error 1146: Table 'xxx' doesn't exist
err = SharedHTTPAccessLogManager.CreateTable(dao.Instance, tableDef.Name)
if err != nil {
return err
}
_, err = dao.Query(tx).
// 重新尝试
lastId, err = dao.Query(tx).
Table(tableDef.Name).
Sets(fields).
Insert()
if err != nil {
return err
}
} else {
remotelogs.Error("HTTP_ACCESS_LOG", err.Error())
}
if err != nil {
return err
}
}
if accessLogEnableAutoPartial && accessLogRowsPerTable > 0 && lastId >= accessLogRowsPerTable {
SharedHTTPAccessLogManager.ResetTable(dao.Instance, day)
}
return nil
@@ -233,6 +251,8 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
size int64,
day string,
hourFrom string,
hourTo string,
clusterId int64,
nodeId int64,
serverId int64,
@@ -255,18 +275,36 @@ func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
size = 1000
}
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
if err != nil || int64(len(result)) < size {
return
}
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
hasMore = len(moreResult) > 0
return
}
// 读取往前的单页访问日志
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, size int64, day string, clusterId int64, nodeId int64, serverId int64, reverse bool, hasError bool, firewallPolicyId int64, firewallRuleGroupId int64, firewallRuleSetId int64, hasFirewallPolicy bool, userId int64, keyword string, ip string, domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
lastRequestId string,
size int64,
day string,
hourFrom string,
hourTo string,
clusterId int64,
nodeId int64,
serverId int64,
reverse bool,
hasError bool,
firewallPolicyId int64,
firewallRuleGroupId int64,
firewallRuleSetId int64,
hasFirewallPolicy bool,
userId int64,
keyword string,
ip string,
domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
if size <= 0 {
return nil, lastRequestId, nil
}
@@ -296,42 +334,57 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
}}
}
locker := sync.Mutex{}
// 查询某个集群下的节点
var nodeIds = []int64{}
if clusterId > 0 {
nodeIds, err = SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
if err != nil {
remotelogs.Error("DBNODE", err.Error())
return
}
sort.Slice(nodeIds, func(i, j int) bool {
return nodeIds[i] < nodeIds[j]
})
}
count := len(daoList)
wg := &sync.WaitGroup{}
wg.Add(count)
// 准备查询
var tableQueries = []*accessLogTableQuery{}
for _, daoWrapper := range daoList {
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
var instance = daoWrapper.DAO.Instance
tableDefs, err := SharedHTTPAccessLogManager.FindTables(instance, day)
if err != nil {
return nil, "", err
}
for _, def := range tableDefs {
tableQueries = append(tableQueries, &accessLogTableQuery{
daoWrapper: daoWrapper,
name: def.Name,
hasRemoteAddrField: def.HasRemoteAddr,
hasDomainField: def.HasDomain,
})
}
}
var locker = sync.Mutex{}
var statusPrefixReg = regexp.MustCompile(`status:\s*(\d{3})\b`)
var statusRangeReg = regexp.MustCompile(`status:\s*(\d{3})-(\d{3})\b`)
var count = len(tableQueries)
var wg = &sync.WaitGroup{}
wg.Add(count)
for _, tableQuery := range tableQueries {
go func(tableQuery *accessLogTableQuery) {
defer wg.Done()
dao := daoWrapper.DAO
tableName, hasRemoteAddrField, hasDomainField, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
if err != nil {
logs.Println("[DB_NODE]" + err.Error())
return
}
if !exists {
// 表格不存在则跳过
return
}
query := dao.Query(tx)
var dao = tableQuery.daoWrapper.DAO
var query = dao.Query(tx)
// 条件
if nodeId > 0 {
query.Attr("nodeId", nodeId)
} else if clusterId > 0 {
nodeIds, err := SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
if err != nil {
remotelogs.Error("DBNODE", err.Error())
return
}
if len(nodeIds) > 0 {
sort.Slice(nodeIds, func(i, j int) bool {
return nodeIds[i] < nodeIds[j]
})
var nodeIdStrings = []string{}
for _, subNodeId := range nodeIds {
nodeIdStrings = append(nodeIdStrings, types.String(subNodeId))
@@ -370,7 +423,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
// keyword
if len(ip) > 0 {
// TODO 支持IP范围
if hasRemoteAddrField {
if tableQuery.hasRemoteAddrField {
// IP格式
if strings.Contains(ip, ",") || strings.Contains(ip, "-") {
rangeConfig, err := shared.ParseIPRange(ip)
@@ -380,6 +433,9 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
}
}
} else {
// 去掉IPv6的[]
ip = strings.Trim(ip, "[]")
query.Attr("remoteAddr", ip)
query.UseIndex("remoteAddr")
}
@@ -389,7 +445,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
}
}
if len(domain) > 0 {
if hasDomainField {
if tableQuery.hasDomainField {
if strings.Contains(domain, "*") {
domain = strings.ReplaceAll(domain, "*", "%")
domain = regexp.MustCompile(`[^a-zA-Z0-9-.%]`).ReplaceAllString(domain, "")
@@ -404,11 +460,12 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
Param("host1", domain)
}
}
if len(keyword) > 0 {
// remoteAddr
if hasRemoteAddrField && net.ParseIP(keyword) != nil {
if tableQuery.hasRemoteAddrField && net.ParseIP(keyword) != nil {
query.Attr("remoteAddr", keyword)
} else if hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
} else if tableQuery.hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
keyword = keyword[3:]
pieces := strings.SplitN(keyword, ",", 2)
if len(pieces) == 1 || len(pieces[1]) == 0 {
@@ -416,12 +473,21 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
} else {
query.Between("INET_ATON(remoteAddr)", utils.IP2Long(pieces[0]), utils.IP2Long(pieces[1]))
}
} else if statusRangeReg.MatchString(keyword) {
var matches = statusRangeReg.FindStringSubmatch(keyword)
query.Between("status", types.Int(matches[1]), types.Int(matches[2]))
// TODO 处理剩余的关键词
} else if statusPrefixReg.MatchString(keyword) {
var matches = statusPrefixReg.FindStringSubmatch(keyword)
query.Attr("status", matches[1])
// TODO 处理剩余的关键词
} else {
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
keyword = keyword[3:]
}
useOriginKeyword := false
var useOriginKeyword = false
where := "JSON_EXTRACT(content, '$.remoteAddr') LIKE :keyword OR JSON_EXTRACT(content, '$.requestURI') LIKE :keyword OR JSON_EXTRACT(content, '$.host') LIKE :keyword OR JSON_EXTRACT(content, '$.userAgent') LIKE :keyword"
@@ -447,13 +513,13 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
// 响应状态码
if regexp.MustCompile(`^\d{3}$`).MatchString(keyword) {
where += " OR JSON_EXTRACT(content, '$.status')=:intKeyword"
where += " OR status=:intKeyword"
query.Param("intKeyword", types.Int(keyword))
}
if regexp.MustCompile(`^\d{3}-\d{3}$`).MatchString(keyword) {
pieces := strings.Split(keyword, "-")
where += " OR JSON_EXTRACT(content, '$.status') BETWEEN :intKeyword1 AND :intKeyword2"
where += " OR status BETWEEN :intKeyword1 AND :intKeyword2"
query.Param("intKeyword1", types.Int(pieces[0]))
query.Param("intKeyword2", types.Int(pieces[1]))
}
@@ -471,6 +537,20 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
}
}
// hourFrom - hourTo
if len(hourFrom) > 0 && len(hourTo) > 0 {
var hourFromInt = types.Int(hourFrom)
var hourToInt = types.Int(hourTo)
if hourFromInt >= 0 && hourFromInt <= 23 && hourToInt >= hourFromInt && hourToInt <= 23 {
var y = types.Int(day[:4])
var m = types.Int(day[4:6])
var d = types.Int(day[6:])
var timeFrom = time.Date(y, time.Month(m), d, hourFromInt, 0, 0, 0, time.Local)
var timeTo = time.Date(y, time.Month(m), d, hourToInt, 59, 59, 0, time.Local)
query.Between("createdAt", timeFrom.Unix(), timeTo.Unix())
}
}
// offset
if len(lastRequestId) > 0 {
if !reverse {
@@ -490,20 +570,21 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
// 开始查询
ones, err := query.
Table(tableName).
Table(tableQuery.name).
Limit(size).
FindAll()
if err != nil {
logs.Println("[DB_NODE]" + err.Error())
return
}
locker.Lock()
for _, one := range ones {
accessLog := one.(*HTTPAccessLog)
result = append(result, accessLog)
}
locker.Unlock()
}(daoWrapper)
}(tableQuery)
}
wg.Wait()
@@ -524,7 +605,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
result = result[:size]
}
requestId := result[len(result)-1].RequestId
var requestId = result[len(result)-1].RequestId
if reverse {
lists.Reverse(result)
}
@@ -556,28 +637,36 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
}}
}
count := len(daoList)
wg := &sync.WaitGroup{}
// 准备查询
var day = timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
var tableQueries = []*accessLogTableQuery{}
for _, daoWrapper := range daoList {
var instance = daoWrapper.DAO.Instance
tableDefs, err := SharedHTTPAccessLogManager.FindTables(instance, day)
if err != nil {
return nil, err
}
for _, def := range tableDefs {
tableQueries = append(tableQueries, &accessLogTableQuery{
daoWrapper: daoWrapper,
name: def.Name,
hasRemoteAddrField: def.HasRemoteAddr,
hasDomainField: def.HasDomain,
})
}
}
var count = len(tableQueries)
var wg = &sync.WaitGroup{}
wg.Add(count)
var result *HTTPAccessLog = nil
day := timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
for _, daoWrapper := range daoList {
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
for _, tableQuery := range tableQueries {
go func(tableQuery *accessLogTableQuery) {
defer wg.Done()
dao := daoWrapper.DAO
tableName, _, _, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
if err != nil {
logs.Println("[DB_NODE]" + err.Error())
return
}
if !exists {
return
}
var dao = tableQuery.daoWrapper.DAO
one, err := dao.Query(tx).
Table(tableName).
Table(tableQuery.name).
Attr("requestId", requestId).
Find()
if err != nil {
@@ -587,7 +676,7 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
if one != nil {
result = one.(*HTTPAccessLog)
}
}(daoWrapper)
}(tableQuery)
}
wg.Wait()
return result, nil
@@ -623,11 +712,18 @@ func (this *HTTPAccessLogDAO) SetupQueue() {
config.MaxLength = 100_000
}
accessLogEnableAutoPartial = config.EnableAutoPartial
if config.RowsPerTable > 0 {
accessLogRowsPerTable = config.RowsPerTable
}
if accessLogQueueMaxLength != config.MaxLength {
accessLogQueueMaxLength = config.MaxLength
oldAccessLogQueue = accessLogQueue
accessLogQueue = make(chan *pb.HTTPAccessLog, config.MaxLength)
}
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue max length: "+types.String(config.MaxLength)+", percent: "+types.String(config.Percent)+", countPerSecond: "+types.String(config.CountPerSecond))
if Tea.IsTesting() {
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue "+string(configJSON))
}
}

View File

@@ -53,7 +53,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs(t *testing.T) {
t.Fatal(err)
}
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
if err != nil {
t.Fatal(err)
}
@@ -80,7 +80,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page(t *testing.T) {
times := 0 // 防止循环次数太多
for {
before := time.Now()
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd"), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
cost := time.Since(before).Seconds()
if err != nil {
t.Fatal(err)
@@ -111,7 +111,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Reverse(t *testing.T) {
}
before := time.Now()
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
cost := time.Since(before).Seconds()
if err != nil {
t.Fatal(err)
@@ -136,7 +136,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
times := 0 // 防止循环次数太多
for {
before := time.Now()
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
cost := time.Since(before).Seconds()
if err != nil {
t.Fatal(err)

View File

@@ -0,0 +1,319 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package models
import (
"fmt"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
"regexp"
"sort"
"strings"
"sync"
)
// 访问日志的两个表格形式
var accessLogTableMainReg = regexp.MustCompile(`_(\d{8})$`)
var accessLogTablePartialReg = regexp.MustCompile(`_(\d{8})_(\d{4})$`)
var SharedHTTPAccessLogManager = NewHTTPAccessLogManager()
type HTTPAccessLogManager struct {
currentTableMapping map[string]*httpAccessLogDefinition // dsn => def
locker sync.Mutex
}
func NewHTTPAccessLogManager() *HTTPAccessLogManager {
return &HTTPAccessLogManager{
currentTableMapping: map[string]*httpAccessLogDefinition{},
}
}
// FindTableNames 读取数据库中某日所有日志表名称
func (this *HTTPAccessLogManager) FindTableNames(db *dbs.DB, day string) ([]string, error) {
var results = []string{}
// 需要防止用户设置了表名自动小写
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
ones, columnNames, err := db.FindOnes(`SHOW TABLES LIKE '` + prefix + `'`)
if err != nil {
return nil, errors.New("query table names error: " + err.Error())
}
var columnName = columnNames[0]
for _, one := range ones {
var tableName = one[columnName].(string)
if lists.ContainsString(results, tableName) {
continue
}
if accessLogTableMainReg.MatchString(tableName) || accessLogTablePartialReg.MatchString(tableName) {
results = append(results, tableName)
}
}
}
// 排序
// 这里不能直接使用sort.Strings(),因为表名里面可能大小写混合
sort.Slice(results, func(i, j int) bool {
var name1 = results[i]
var name2 = results[j]
if len(name1) < len(name2) {
return true
}
return strings.ToLower(name1) < strings.ToLower(name2)
})
return results, nil
}
// FindTables 读取数据库中某日所有日志表
func (this *HTTPAccessLogManager) FindTables(db *dbs.DB, day string) ([]*httpAccessLogDefinition, error) {
var results = []*httpAccessLogDefinition{}
var tableNames = []string{}
// 需要防止用户设置了表名自动小写
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
ones, columnNames, err := db.FindOnes(`SHOW TABLES LIKE '` + prefix + `'`)
if err != nil {
return nil, errors.New("query table names error: " + err.Error())
}
var columnName = columnNames[0]
for _, one := range ones {
var tableName = one[columnName].(string)
if lists.ContainsString(tableNames, tableName) {
continue
}
if accessLogTableMainReg.MatchString(tableName) {
tableNames = append(tableNames, tableName)
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, tableName)
if err != nil {
return nil, err
}
results = append(results, &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: hasRemoteAddrField,
HasDomain: hasDomainField,
Exists: true,
})
} else if accessLogTablePartialReg.MatchString(tableName) {
tableNames = append(tableNames, tableName)
results = append(results, &httpAccessLogDefinition{
Name: tableName,
HasRemoteAddr: true,
HasDomain: true,
Exists: true,
})
}
}
}
// 排序
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
return results, nil
}
// FindTable 根据日期获取表名
// 表名组成
// - PREFIX_DAY
// - PREFIX_DAY_0001
func (this *HTTPAccessLogManager) FindTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
this.locker.Lock()
defer this.locker.Unlock()
config, err := db.Config()
if err != nil {
return nil, err
}
var cachePrefix = config.Dsn
var cacheKey = this.composeTableCacheKey(cachePrefix, day)
def, ok := this.currentTableMapping[cacheKey]
if ok {
return def, nil
}
def, err = this.findTableWithoutCache(db, day, force)
if err != nil {
return nil, err
}
// 只有存在的表格才缓存
if def != nil && def.Exists {
this.currentTableMapping[cacheKey] = def
// 清除过时缓存
for oldCacheKey := range this.currentTableMapping {
var dayIndex = strings.LastIndex(oldCacheKey, "_")
if dayIndex > 0 {
var oldPrefix = oldCacheKey[:dayIndex]
var oldDay = oldCacheKey[dayIndex+1:]
if oldPrefix == cachePrefix && oldDay < day {
delete(this.currentTableMapping, oldCacheKey)
}
}
}
}
return def, nil
}
// CreateTable 创建访问日志表格
func (this *HTTPAccessLogManager) CreateTable(db *dbs.DB, tableName string) error {
_, err := db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
if err != nil {
if CheckSQLErrCode(err, 1050) { // Error 1050: Table 'xxx' already exists
return nil
}
return err
}
return nil
}
// ResetTable 清除某个数据库表名缓存
func (this *HTTPAccessLogManager) ResetTable(db *dbs.DB, day string) {
this.locker.Lock()
defer this.locker.Unlock()
config, err := db.Config()
if err != nil {
return
}
delete(this.currentTableMapping, this.composeTableCacheKey(config.Dsn, day))
}
// 查找某个表格
func (this *HTTPAccessLogManager) findTableWithoutCache(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
tableNames, err := this.FindTableNames(db, day)
if err != nil {
return nil, err
}
var prefix = "edgeHTTPAccessLogs_" + day
if len(tableNames) == 0 {
if force {
err := this.CreateTable(db, prefix)
if err != nil {
return nil, err
}
return &httpAccessLogDefinition{
Name: prefix,
HasRemoteAddr: true,
HasDomain: true,
Exists: true,
}, nil
}
return &httpAccessLogDefinition{
Name: prefix,
HasRemoteAddr: true,
HasDomain: true,
Exists: false,
}, nil
}
var lastTableName = tableNames[len(tableNames)-1]
if !force || !accessLogEnableAutoPartial || accessLogRowsPerTable <= 0 {
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
if err != nil {
return nil, err
}
return &httpAccessLogDefinition{
Name: lastTableName,
HasRemoteAddr: hasRemoteAddrField,
HasDomain: hasDomainField,
Exists: true,
}, nil
}
// 检查是否生成下个分表
lastId, err := db.FindCol(0, "SELECT id FROM "+lastTableName+" ORDER BY id DESC LIMIT 1")
if err != nil {
return nil, err
}
if lastId != nil {
var lastInt64Id = types.Int64(lastId)
if accessLogRowsPerTable > 0 && lastInt64Id >= accessLogRowsPerTable {
// create next partial table
var nextTableName = ""
if accessLogTableMainReg.MatchString(lastTableName) {
nextTableName = prefix + "_0001"
} else if accessLogTablePartialReg.MatchString(lastTableName) {
var matches = accessLogTablePartialReg.FindStringSubmatch(lastTableName)
if len(matches) < 3 {
return nil, errors.New("fatal error: invalid 'accessLogTablePartialReg'")
}
var lastPartial = matches[2]
nextTableName = prefix + "_" + fmt.Sprintf("%04d", types.Int(lastPartial)+1)
} else {
nextTableName = prefix + "_0001"
}
err = this.CreateTable(db, nextTableName)
if err != nil {
return nil, err
}
return &httpAccessLogDefinition{
Name: nextTableName,
HasRemoteAddr: true,
HasDomain: true,
Exists: true,
}, nil
}
}
// 检查字段
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
if err != nil {
return nil, err
}
return &httpAccessLogDefinition{
Name: lastTableName,
HasRemoteAddr: hasRemoteAddrField,
HasDomain: hasDomainField,
Exists: true,
}, nil
}
// TODO 考虑缓存检查结果
func (this *HTTPAccessLogManager) checkTableFields(db *dbs.DB, tableName string) (hasRemoteAddrField bool, hasDomainField bool, err error) {
fields, _, err := db.FindOnes("SHOW FIELDS FROM " + tableName)
if err != nil {
return false, false, err
}
for _, field := range fields {
var fieldName = field.GetString("Field")
if strings.ToLower(fieldName) == strings.ToLower("remoteAddr") {
hasRemoteAddrField = true
}
if strings.ToLower(fieldName) == "domain" {
hasDomainField = true
}
}
return
}
// 组合表格的缓存Key
func (this *HTTPAccessLogManager) composeTableCacheKey(dsn string, day string) string {
// 注意:格式一定要固定,下面清除缓存的时候需要用到
return dsn + "_" + day
}

View File

@@ -0,0 +1,148 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package models_test
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/iwind/TeaGo/dbs"
"testing"
"time"
)
func TestNewHTTPAccessLogManager(t *testing.T) {
var config = &dbs.DBConfig{
Driver: "mysql",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
Prefix: "edge",
Connections: struct {
Pool int `yaml:"pool"`
Max int `yaml:"max"`
Life string `yaml:"life"`
LifeDuration time.Duration `yaml:",omitempty"`
}{},
Models: struct {
Package string `yaml:"package"`
}{},
}
db, err := dbs.NewInstanceFromConfig(config)
if err != nil {
t.Fatal(err)
}
var manager = models.SharedHTTPAccessLogManager
err = manager.CreateTable(db, "accessLog_1")
if err != nil {
t.Fatal(err)
}
}
func TestHTTPAccessLogManager_FindTableNames(t *testing.T) {
var config = &dbs.DBConfig{
Driver: "mysql",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
Prefix: "edge",
Connections: struct {
Pool int `yaml:"pool"`
Max int `yaml:"max"`
Life string `yaml:"life"`
LifeDuration time.Duration `yaml:",omitempty"`
}{},
Models: struct {
Package string `yaml:"package"`
}{},
}
db, err := dbs.NewInstanceFromConfig(config)
if err != nil {
t.Fatal(err)
}
for i := 0; i < 3; i++ {
var before = time.Now()
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
if err != nil {
t.Fatal(err)
}
data, err := json.Marshal(tables)
if err != nil {
t.Fatal(err)
}
t.Log(string(data))
t.Log(time.Since(before).Seconds()*1000, "ms")
}
}
func TestHTTPAccessLogManager_FindTables(t *testing.T) {
var config = &dbs.DBConfig{
Driver: "mysql",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
Prefix: "edge",
Connections: struct {
Pool int `yaml:"pool"`
Max int `yaml:"max"`
Life string `yaml:"life"`
LifeDuration time.Duration `yaml:",omitempty"`
}{},
Models: struct {
Package string `yaml:"package"`
}{},
}
db, err := dbs.NewInstanceFromConfig(config)
if err != nil {
t.Fatal(err)
}
for i := 0; i < 3; i++ {
var before = time.Now()
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
if err != nil {
t.Fatal(err)
}
data, err := json.Marshal(tables)
if err != nil {
t.Fatal(err)
}
t.Log(string(data))
t.Log(time.Since(before).Seconds()*1000, "ms")
}
}
func TestHTTPAccessLogManager_FindTable(t *testing.T) {
var config = &dbs.DBConfig{
Driver: "mysql",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
Prefix: "edge",
Connections: struct {
Pool int `yaml:"pool"`
Max int `yaml:"max"`
Life string `yaml:"life"`
LifeDuration time.Duration `yaml:",omitempty"`
}{},
Models: struct {
Package string `yaml:"package"`
}{},
}
db, err := dbs.NewInstanceFromConfig(config)
if err != nil {
t.Fatal(err)
}
for i := 0; i < 3; i++ {
var before = time.Now()
tableDef, err := models.SharedHTTPAccessLogManager.FindTable(db, "20220306", false)
if err != nil {
t.Fatal(err)
}
data, err := json.Marshal(tableDef)
if err != nil {
t.Fatal(err)
}
t.Log(string(data))
t.Log(time.Since(before).Seconds()*1000, "ms")
}
}

View File

@@ -1,22 +1,24 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPAccessLog 访问日志
type HTTPAccessLog struct {
Id uint64 `field:"id"` // ID
ServerId uint32 `field:"serverId"` // 服务ID
NodeId uint32 `field:"nodeId"` // 节点ID
Status uint32 `field:"status"` // 状态码
CreatedAt uint64 `field:"createdAt"` // 创建时间
Content string `field:"content"` // 日志内容
RequestId string `field:"requestId"` // 请求ID
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
RemoteAddr string `field:"remoteAddr"` // IP地址
Domain string `field:"domain"` // 域名
RequestBody string `field:"requestBody"` // 请求内容
ResponseBody string `field:"responseBody"` // 响应内容
Id uint64 `field:"id"` // ID
ServerId uint32 `field:"serverId"` // 服务ID
NodeId uint32 `field:"nodeId"` // 节点ID
Status uint32 `field:"status"` // 状态码
CreatedAt uint64 `field:"createdAt"` // 创建时间
Content dbs.JSON `field:"content"` // 日志内容
RequestId string `field:"requestId"` // 请求ID
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
RemoteAddr string `field:"remoteAddr"` // IP地址
Domain string `field:"domain"` // 域名
RequestBody []byte `field:"requestBody"` // 请求内容
ResponseBody []byte `field:"responseBody"` // 响应内容
}
type HTTPAccessLogOperator struct {

View File

@@ -8,11 +8,11 @@ import (
// ToPB 转换成PB对象
func (this *HTTPAccessLog) ToPB() (*pb.HTTPAccessLog, error) {
p := &pb.HTTPAccessLog{}
err := json.Unmarshal([]byte(this.Content), p)
err := json.Unmarshal(this.Content, p)
if err != nil {
return nil, err
}
p.RequestId = this.RequestId
p.RequestBody = []byte(this.RequestBody)
p.RequestBody = this.RequestBody
return p, nil
}

View File

@@ -161,7 +161,7 @@ func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, nam
op.Version = dbs.SQL("version+1")
} else {
var m1 = maps.Map{}
_ = json.Unmarshal([]byte(oldPolicy.Options), &m1)
_ = json.Unmarshal(oldPolicy.Options, &m1)
var m2 = maps.Map{}
_ = json.Unmarshal(optionsJSON, &m2)

View File

@@ -1,20 +1,22 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPAccessLogPolicy 访问日志策略
type HTTPAccessLogPolicy struct {
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Name string `field:"name"` // 名称
IsOn uint8 `field:"isOn"` // 是否启用
Type string `field:"type"` // 存储类型
Options string `field:"options"` // 存储选项
Conds string `field:"conds"` // 请求条件
IsPublic uint8 `field:"isPublic"` // 是否为公用
Version uint32 `field:"version"` // 版本号
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Name string `field:"name"` // 名称
IsOn bool `field:"isOn"` // 是否启用
Type string `field:"type"` // 存储类型
Options dbs.JSON `field:"options"` // 存储选项
Conds dbs.JSON `field:"conds"` // 请求条件
IsPublic bool `field:"isPublic"` // 是否为公用
Version uint32 `field:"version"` // 版本号
}
type HTTPAccessLogPolicyOperator struct {

View File

@@ -116,13 +116,13 @@ func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, c
var config = &serverconfigs.HTTPAuthPolicy{
Id: int64(policy.Id),
Name: policy.Name,
IsOn: policy.IsOn == 1,
IsOn: policy.IsOn,
Type: policy.Type,
}
var params map[string]interface{}
if IsNotNull(policy.Params) {
err = json.Unmarshal([]byte(policy.Params), &params)
err = json.Unmarshal(policy.Params, &params)
if err != nil {
return nil, err
}

View File

@@ -1,15 +1,17 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPAuthPolicy HTTP认证策略
type HTTPAuthPolicy struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Type string `field:"type"` // 类型
Params string `field:"params"` // 参数
State uint8 `field:"state"` // 状态
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Type string `field:"type"` // 类型
Params dbs.JSON `field:"params"` // 参数
State uint8 `field:"state"` // 状态
}
type HTTPAuthPolicyOperator struct {

View File

@@ -80,10 +80,10 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
config := &serverconfigs.HTTPBrotliCompressionConfig{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
if IsNotNull(policy.MinLength) {
minLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
err = json.Unmarshal(policy.MinLength, minLengthConfig)
if err != nil {
return nil, err
}
@@ -91,7 +91,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
}
if IsNotNull(policy.MaxLength) {
maxLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
if err != nil {
return nil, err
}
@@ -101,7 +101,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
if IsNotNull(policy.Conds) {
condsConfig := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
err = json.Unmarshal(policy.Conds, condsConfig)
if err != nil {
return nil, err
}

View File

@@ -1,17 +1,19 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPBrotliPolicy Gzip配置
type HTTPBrotliPolicy struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength string `field:"minLength"` // 可压缩最小值
MaxLength string `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds string `field:"conds"` // 条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds dbs.JSON `field:"conds"` // 条件
}
type HTTPBrotliPolicyOperator struct {

View File

@@ -95,7 +95,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) (int64, error) {
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) {
op := NewHTTPCachePolicyOperator()
op.State = HTTPCachePolicyStateEnabled
op.IsOn = isOn
@@ -112,6 +112,7 @@ func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name st
if len(storageOptionsJSON) > 0 {
op.Options = storageOptionsJSON
}
op.SyncCompressionCache = syncCompressionCache
// 默认的缓存条件
cacheRef := &serverconfigs.HTTPCacheRef{
@@ -182,13 +183,19 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
var storageOptions = &serverconfigs.HTTPFileCacheStorage{
Dir: "/opt/cache",
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
Capacity: &shared.SizeCapacity{
Count: 1,
Unit: shared.SizeCapacityUnitGB,
},
},
}
storageOptionsJSON, err := json.Marshal(storageOptions)
if err != nil {
return 0, err
}
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON)
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
if err != nil {
return 0, err
}
@@ -196,7 +203,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) error {
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 {
if policyId <= 0 {
return errors.New("invalid policyId")
}
@@ -217,6 +224,7 @@ func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, is
if len(storageOptionsJSON) > 0 {
op.Options = storageOptionsJSON
}
op.SyncCompressionCache = syncCompressionCache
err := this.Save(tx, op)
if err != nil {
return err
@@ -244,14 +252,15 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
}
config := &serverconfigs.HTTPCachePolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
config.Name = policy.Name
config.Description = policy.Description
config.SyncCompressionCache = policy.SyncCompressionCache == 1
// capacity
if IsNotNull(policy.Capacity) {
capacityConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.Capacity), capacityConfig)
err = json.Unmarshal(policy.Capacity, capacityConfig)
if err != nil {
return nil, err
}
@@ -263,7 +272,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
// max size
if IsNotNull(policy.MaxSize) {
maxSizeConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MaxSize), maxSizeConfig)
err = json.Unmarshal(policy.MaxSize, maxSizeConfig)
if err != nil {
return nil, err
}
@@ -275,7 +284,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
// options
if IsNotNull(policy.Options) {
m := map[string]interface{}{}
err = json.Unmarshal([]byte(policy.Options), &m)
err = json.Unmarshal(policy.Options, &m)
if err != nil {
return nil, errors.Wrap(err)
}
@@ -285,7 +294,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
// refs
if IsNotNull(policy.Refs) {
refs := []*serverconfigs.HTTPCacheRef{}
err = json.Unmarshal([]byte(policy.Refs), &refs)
err = json.Unmarshal(policy.Refs, &refs)
if err != nil {
return nil, err
}
@@ -300,7 +309,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
}
// CountAllEnabledHTTPCachePolicies 计算可用缓存策略数量
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, storageType string) (int64, error) {
query := this.Query(tx).
State(HTTPCachePolicyStateEnabled)
if clusterId > 0 {
@@ -311,11 +320,14 @@ func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clu
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
}
if len(storageType) > 0 {
query.Attr("type", storageType)
}
return query.Count()
}
// ListEnabledHTTPCachePolicies 列出单页的缓存策略
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, storageType string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
query := this.Query(tx).
State(HTTPCachePolicyStateEnabled)
if clusterId > 0 {
@@ -326,6 +338,9 @@ func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, cluster
query.Where("(name LIKE :keyword)").
Param("keyword", "%"+keyword+"%")
}
if len(storageType) > 0 {
query.Attr("type", storageType)
}
ones, err := query.
ResultPk().
Offset(offset).

View File

@@ -1,40 +1,44 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPCachePolicy HTTP缓存策略
type HTTPCachePolicy struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Capacity string `field:"capacity"` // 容量数据
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
MaxSize string `field:"maxSize"` // 最大缓存内容尺寸
Type string `field:"type"` // 存储类型
Options string `field:"options"` // 存储选项
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 描述
Refs string `field:"refs"` // 默认的缓存设置
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Capacity dbs.JSON `field:"capacity"` // 容量数据
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
MaxSize dbs.JSON `field:"maxSize"` // 最大缓存内容尺寸
Type string `field:"type"` // 存储类型
Options dbs.JSON `field:"options"` // 存储选项
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
Description string `field:"description"` // 描述
Refs dbs.JSON `field:"refs"` // 默认的缓存设置
SyncCompressionCache uint8 `field:"syncCompressionCache"` // 是否同步写入压缩缓存
}
type HTTPCachePolicyOperator struct {
Id interface{} // ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
TemplateId interface{} // 模版ID
IsOn interface{} // 是否启用
Name interface{} // 名称
Capacity interface{} // 容量数据
MaxKeys interface{} // 最多Key值
MaxSize interface{} // 最大缓存内容尺寸
Type interface{} // 存储类型
Options interface{} // 存储选项
CreatedAt interface{} // 创建时间
State interface{} // 状态
Description interface{} // 描述
Refs interface{} // 默认的缓存设置
Id interface{} // ID
AdminId interface{} // 管理员ID
UserId interface{} // 用户ID
TemplateId interface{} // 模版ID
IsOn interface{} // 是否启用
Name interface{} // 名称
Capacity interface{} // 容量数据
MaxKeys interface{} // 最多Key值
MaxSize interface{} // 最大缓存内容尺寸
Type interface{} // 存储类型
Options interface{} // 存储选项
CreatedAt interface{} // 创建时间
State interface{} // 状态
Description interface{} // 描述
Refs interface{} // 默认的缓存设置
SyncCompressionCache interface{} // 是否同步写入压缩缓存
}
func NewHTTPCachePolicyOperator() *HTTPCachePolicyOperator {

View File

@@ -80,10 +80,10 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
config := &serverconfigs.HTTPDeflateCompressionConfig{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
if IsNotNull(policy.MinLength) {
minLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
err = json.Unmarshal(policy.MinLength, minLengthConfig)
if err != nil {
return nil, err
}
@@ -91,7 +91,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
}
if IsNotNull(policy.MaxLength) {
maxLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
if err != nil {
return nil, err
}
@@ -101,7 +101,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
if IsNotNull(policy.Conds) {
condsConfig := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
err = json.Unmarshal(policy.Conds, condsConfig)
if err != nil {
return nil, err
}

View File

@@ -1,17 +1,19 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPDeflatePolicy Gzip配置
type HTTPDeflatePolicy struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength string `field:"minLength"` // 可压缩最小值
MaxLength string `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds string `field:"conds"` // 条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds dbs.JSON `field:"conds"` // 条件
}
type HTTPDeflatePolicyOperator struct {

View File

@@ -81,12 +81,12 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
}
config := &serverconfigs.HTTPFastcgiConfig{}
config.Id = int64(fastcgi.Id)
config.IsOn = fastcgi.IsOn == 1
config.IsOn = fastcgi.IsOn
config.Address = fastcgi.Address
if IsNotNull(fastcgi.Params) {
params := []*serverconfigs.HTTPFastcgiParam{}
err = json.Unmarshal([]byte(fastcgi.Params), &params)
err = json.Unmarshal(fastcgi.Params, &params)
if err != nil {
return nil, err
}
@@ -95,7 +95,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
if IsNotNull(fastcgi.ReadTimeout) {
duration := &shared.TimeDuration{}
err = json.Unmarshal([]byte(fastcgi.ReadTimeout), duration)
err = json.Unmarshal(fastcgi.ReadTimeout, duration)
if err != nil {
return nil, err
}
@@ -104,7 +104,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
if IsNotNull(fastcgi.ConnTimeout) {
duration := &shared.TimeDuration{}
err = json.Unmarshal([]byte(fastcgi.ConnTimeout), duration)
err = json.Unmarshal(fastcgi.ConnTimeout, duration)
if err != nil {
return nil, err
}

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFastcgi Fastcgi设置
type HTTPFastcgi struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Address string `field:"address"` // 地址
Params string `field:"params"` // 参数
ReadTimeout string `field:"readTimeout"` // 读取超时
ConnTimeout string `field:"connTimeout"` // 连接超时
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
State uint8 `field:"state"` // 状态
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Address string `field:"address"` // 地址
Params dbs.JSON `field:"params"` // 参数
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
State uint8 `field:"state"` // 状态
}
type HTTPFastcgiOperator struct {

View File

@@ -366,7 +366,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
config := &firewallconfigs.HTTPFirewallPolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
config.Name = policy.Name
config.Description = policy.Description
config.UseLocalFirewall = policy.UseLocalFirewall == 1
@@ -379,7 +379,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
// Inbound
inbound := &firewallconfigs.HTTPFirewallInboundConfig{}
if IsNotNull(policy.Inbound) {
err = json.Unmarshal([]byte(policy.Inbound), inbound)
err = json.Unmarshal(policy.Inbound, inbound)
if err != nil {
return nil, err
}
@@ -407,7 +407,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
// Outbound
outbound := &firewallconfigs.HTTPFirewallOutboundConfig{}
if IsNotNull(policy.Outbound) {
err = json.Unmarshal([]byte(policy.Outbound), outbound)
err = json.Unmarshal(policy.Outbound, outbound)
if err != nil {
return nil, err
}
@@ -435,7 +435,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
// Block动作配置
if IsNotNull(policy.BlockOptions) {
blockAction := &firewallconfigs.HTTPFirewallBlockAction{}
err = json.Unmarshal([]byte(policy.BlockOptions), blockAction)
err = json.Unmarshal(policy.BlockOptions, blockAction)
if err != nil {
return config, err
}
@@ -443,9 +443,9 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
}
// syn flood
if len(policy.SynFlood) > 0 {
if IsNotNull(policy.SynFlood) {
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
err = json.Unmarshal([]byte(policy.SynFlood), synFloodConfig)
err = json.Unmarshal(policy.SynFlood, synFloodConfig)
if err != nil {
return nil, err
}

View File

@@ -1,24 +1,26 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallPolicy HTTP防火墙
type HTTPFirewallPolicy struct {
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ServerId uint32 `field:"serverId"` // 服务ID
GroupId uint32 `field:"groupId"` // 服务分组ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Inbound string `field:"inbound"` // 入站规则
Outbound string `field:"outbound"` // 出站规则
BlockOptions string `field:"blockOptions"` // BLOCK选项
Mode string `field:"mode"` // 模式
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
SynFlood string `field:"synFlood"` // SynFlood防御设置
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ServerId uint32 `field:"serverId"` // 服务ID
GroupId uint32 `field:"groupId"` // 服务分组ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Inbound dbs.JSON `field:"inbound"` // 入站规则
Outbound dbs.JSON `field:"outbound"` // 出站规则
BlockOptions dbs.JSON `field:"blockOptions"` // BLOCK选项
Mode string `field:"mode"` // 模式
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
SynFlood dbs.JSON `field:"synFlood"` // SynFlood防御设置
}
type HTTPFirewallPolicyOperator struct {

View File

@@ -35,12 +35,12 @@ func init() {
})
}
// 初始化
// Init 初始化
func (this *HTTPFirewallRuleDAO) Init() {
_ = this.DAOObject.Init()
}
// 启用条目
// EnableHTTPFirewallRule 启用条目
func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
@@ -49,7 +49,7 @@ func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) er
return err
}
// 禁用条目
// DisableHTTPFirewallRule 禁用条目
func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int64) error {
_, err := this.Query(tx).
Pk(ruleId).
@@ -61,7 +61,7 @@ func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int6
return this.NotifyUpdate(tx, ruleId)
}
// 查找启用中的条目
// FindEnabledHTTPFirewallRule 查找启用中的条目
func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int64) (*HTTPFirewallRule, error) {
result, err := this.Query(tx).
Pk(id).
@@ -73,7 +73,7 @@ func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int6
return result.(*HTTPFirewallRule), err
}
// 组合配置
// ComposeFirewallRule 组合配置
func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (*firewallconfigs.HTTPFirewallRule, error) {
rule, err := this.FindEnabledHTTPFirewallRule(tx, ruleId)
if err != nil {
@@ -84,12 +84,12 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
}
config := &firewallconfigs.HTTPFirewallRule{}
config.Id = int64(rule.Id)
config.IsOn = rule.IsOn == 1
config.IsOn = rule.IsOn
config.Param = rule.Param
paramFilters := []*firewallconfigs.ParamFilter{}
if IsNotNull(rule.ParamFilters) {
err = json.Unmarshal([]byte(rule.ParamFilters), &paramFilters)
err = json.Unmarshal(rule.ParamFilters, &paramFilters)
if err != nil {
return nil, err
}
@@ -98,11 +98,11 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
config.Operator = rule.Operator
config.Value = rule.Value
config.IsCaseInsensitive = rule.IsCaseInsensitive == 1
config.IsCaseInsensitive = rule.IsCaseInsensitive
if IsNotNull(rule.CheckpointOptions) {
checkpointOptions := map[string]interface{}{}
err = json.Unmarshal([]byte(rule.CheckpointOptions), &checkpointOptions)
err = json.Unmarshal(rule.CheckpointOptions, &checkpointOptions)
if err != nil {
return nil, err
}
@@ -114,7 +114,7 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
return config, nil
}
// 从配置中配置规则
// CreateOrUpdateRuleFromConfig 从配置中配置规则
func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleConfig *firewallconfigs.HTTPFirewallRule) (int64, error) {
op := NewHTTPFirewallRuleOperator()
op.Id = ruleConfig.Id
@@ -160,7 +160,7 @@ func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleCo
return types.Int64(op.Id), nil
}
// 通知更新
// NotifyUpdate 通知更新
func (this *HTTPFirewallRuleDAO) NotifyUpdate(tx *dbs.Tx, ruleId int64) error {
setId, err := SharedHTTPFirewallRuleSetDAO.FindEnabledRuleSetIdWithRuleId(tx, ruleId)
if err != nil {

View File

@@ -91,15 +91,15 @@ func (this *HTTPFirewallRuleGroupDAO) ComposeFirewallRuleGroup(tx *dbs.Tx, group
}
config := &firewallconfigs.HTTPFirewallRuleGroup{}
config.Id = int64(group.Id)
config.IsOn = group.IsOn == 1
config.IsOn = group.IsOn
config.Name = group.Name
config.Description = group.Description
config.Code = group.Code
config.IsTemplate = group.IsTemplate == 1
config.IsTemplate = group.IsTemplate
if IsNotNull(group.Sets) {
setRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
err = json.Unmarshal([]byte(group.Sets), &setRefs)
err = json.Unmarshal(group.Sets, &setRefs)
if err != nil {
return nil, err
}

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallRuleGroup 防火墙规则分组
type HTTPFirewallRuleGroup struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Code string `field:"code"` // 代号
IsTemplate uint8 `field:"isTemplate"` // 是否为预置模板
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
Sets string `field:"sets"` // 规则集列表
CreatedAt uint64 `field:"createdAt"` // 创建时间
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Code string `field:"code"` // 代号
IsTemplate bool `field:"isTemplate"` // 是否为预置模板
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
Sets dbs.JSON `field:"sets"` // 规则集列表
CreatedAt uint64 `field:"createdAt"` // 创建时间
}
type HTTPFirewallRuleGroupOperator struct {

View File

@@ -1,20 +1,22 @@
package models
// 防火墙规则
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallRule 防火墙规则
type HTTPFirewallRule struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Description string `field:"description"` // 说明
Param string `field:"param"` // 参数
ParamFilters string `field:"paramFilters"` // 处理器
Operator string `field:"operator"` // 操作符
Value string `field:"value"` // 对比值
IsCaseInsensitive uint8 `field:"isCaseInsensitive"` // 是否大小写不敏感
CheckpointOptions string `field:"checkpointOptions"` // 检查点参数
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Description string `field:"description"` // 说明
Param string `field:"param"` // 参数
ParamFilters dbs.JSON `field:"paramFilters"` // 处理器
Operator string `field:"operator"` // 操作符
Value string `field:"value"` // 对比值
IsCaseInsensitive bool `field:"isCaseInsensitive"` // 是否大小写不敏感
CheckpointOptions dbs.JSON `field:"checkpointOptions"` // 检查点参数
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
}
type HTTPFirewallRuleOperator struct {

View File

@@ -94,7 +94,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
}
config := &firewallconfigs.HTTPFirewallRuleSet{}
config.Id = int64(set.Id)
config.IsOn = set.IsOn == 1
config.IsOn = set.IsOn
config.Name = set.Name
config.Description = set.Description
config.Code = set.Code
@@ -103,7 +103,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
if IsNotNull(set.Rules) {
ruleRefs := []*firewallconfigs.HTTPFirewallRuleRef{}
err = json.Unmarshal([]byte(set.Rules), &ruleRefs)
err = json.Unmarshal(set.Rules, &ruleRefs)
if err != nil {
return nil, err
}
@@ -121,7 +121,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
var actionConfigs = []*firewallconfigs.HTTPFirewallActionConfig{}
if len(set.Actions) > 0 {
err = json.Unmarshal([]byte(set.Actions), &actionConfigs)
err = json.Unmarshal(set.Actions, &actionConfigs)
if err != nil {
return nil, err
}

View File

@@ -1,22 +1,24 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPFirewallRuleSet 防火墙规则集
type HTTPFirewallRuleSet struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Code string `field:"code"` // 代号
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
CreatedAt uint64 `field:"createdAt"` // 创建时间
Rules string `field:"rules"` // 规则列表
Connector string `field:"connector"` // 规则之间的关系
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Action string `field:"action"` // 执行的动作(过期)
ActionOptions string `field:"actionOptions"` // 动作的选项(过期)
Actions string `field:"actions"` // 一组动作
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Code string `field:"code"` // 代号
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
CreatedAt uint64 `field:"createdAt"` // 创建时间
Rules dbs.JSON `field:"rules"` // 规则列表
Connector string `field:"connector"` // 规则之间的关系
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Action string `field:"action"` // 执行的动作(过期)
ActionOptions dbs.JSON `field:"actionOptions"` // 动作的选项(过期)
Actions dbs.JSON `field:"actions"` // 一组动作
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
}
type HTTPFirewallRuleSetOperator struct {

View File

@@ -88,10 +88,10 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
config := &serverconfigs.HTTPGzipCompressionConfig{}
config.Id = int64(gzip.Id)
config.IsOn = gzip.IsOn == 1
config.IsOn = gzip.IsOn
if IsNotNull(gzip.MinLength) {
minLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(gzip.MinLength), minLengthConfig)
err = json.Unmarshal(gzip.MinLength, minLengthConfig)
if err != nil {
return nil, err
}
@@ -99,7 +99,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
}
if IsNotNull(gzip.MaxLength) {
maxLengthConfig := &shared.SizeCapacity{}
err = json.Unmarshal([]byte(gzip.MaxLength), maxLengthConfig)
err = json.Unmarshal(gzip.MaxLength, maxLengthConfig)
if err != nil {
return nil, err
}
@@ -109,7 +109,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
if IsNotNull(gzip.Conds) {
condsConfig := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(gzip.Conds), condsConfig)
err = json.Unmarshal(gzip.Conds, condsConfig)
if err != nil {
return nil, err
}

View File

@@ -1,17 +1,19 @@
package models
// Gzip配置
import "github.com/iwind/TeaGo/dbs"
// HTTPGzip Gzip配置
type HTTPGzip struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength string `field:"minLength"` // 可压缩最小值
MaxLength string `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds string `field:"conds"` // 条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Level uint32 `field:"level"` // 压缩级别
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Conds dbs.JSON `field:"conds"` // 条件
}
type HTTPGzipOperator struct {

View File

@@ -5,22 +5,22 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
// 解析最小长度
// DecodeMinLength 解析最小长度
func (this *HTTPGzip) DecodeMinLength() (*shared.SizeCapacity, error) {
if len(this.MinLength) == 0 {
return nil, nil
}
capacity := &shared.SizeCapacity{}
err := json.Unmarshal([]byte(this.MinLength), capacity)
err := json.Unmarshal(this.MinLength, capacity)
return capacity, err
}
// 解析最大长度
// DecodeMaxLength 解析最大长度
func (this *HTTPGzip) DecodeMaxLength() (*shared.SizeCapacity, error) {
if len(this.MaxLength) == 0 {
return nil, nil
}
capacity := &shared.SizeCapacity{}
err := json.Unmarshal([]byte(this.MaxLength), capacity)
err := json.Unmarshal(this.MaxLength, capacity)
return capacity, err
}

View File

@@ -236,7 +236,7 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
config := &shared.HTTPHeaderConfig{}
config.Id = int64(header.Id)
config.IsOn = header.IsOn == 1
config.IsOn = header.IsOn
config.Name = header.Name
config.Value = header.Value
config.DisableRedirect = header.DisableRedirect == 1
@@ -244,9 +244,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
// replace
config.ShouldReplace = header.ShouldReplace == 1
if len(header.ReplaceValues) > 0 {
if IsNotNull(header.ReplaceValues) {
var values = []*shared.HTTPHeaderReplaceValue{}
err = json.Unmarshal([]byte(header.ReplaceValues), &values)
err = json.Unmarshal(header.ReplaceValues, &values)
if err != nil {
return nil, err
}
@@ -254,9 +254,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
}
// status
if len(header.Status) > 0 {
if IsNotNull(header.Status) {
status := &shared.HTTPStatusConfig{}
err = json.Unmarshal([]byte(header.Status), status)
err = json.Unmarshal(header.Status, status)
if err != nil {
return nil, err
}
@@ -264,9 +264,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
}
// methods
if len(header.Methods) > 0 {
if IsNotNull(header.Methods) {
var methods = []string{}
err = json.Unmarshal([]byte(header.Methods), &methods)
err = json.Unmarshal(header.Methods, &methods)
if err != nil {
return nil, err
}
@@ -274,9 +274,9 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
}
// domains
if len(header.Domains) > 0 {
if IsNotNull(header.Domains) {
var domains = []string{}
err = json.Unmarshal([]byte(header.Domains), &domains)
err = json.Unmarshal(header.Domains, &domains)
if err != nil {
return nil, err
}

View File

@@ -1,24 +1,26 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPHeader HTTP Header
type HTTPHeader struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Value string `field:"value"` // 值
Order uint32 `field:"order"` // 排序
Status string `field:"status"` // 状态码设置
DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
ReplaceValues string `field:"replaceValues"` // 替换的值
Methods string `field:"methods"` // 支持的方法
Domains string `field:"domains"` // 支持的域名
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Value string `field:"value"` // 值
Order uint32 `field:"order"` // 排序
Status dbs.JSON `field:"status"` // 状态码设置
DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
ReplaceValues dbs.JSON `field:"replaceValues"` // 替换的值
Methods dbs.JSON `field:"methods"` // 支持的方法
Domains dbs.JSON `field:"domains"` // 支持的域名
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
}
type HTTPHeaderOperator struct {

View File

@@ -184,12 +184,12 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
config := &shared.HTTPHeaderPolicy{}
config.Id = int64(policy.Id)
config.IsOn = policy.IsOn == 1
config.IsOn = policy.IsOn
// SetHeaders
if len(policy.SetHeaders) > 0 {
if IsNotNull(policy.SetHeaders) {
refs := []*shared.HTTPHeaderRef{}
err = json.Unmarshal([]byte(policy.SetHeaders), &refs)
err = json.Unmarshal(policy.SetHeaders, &refs)
if err != nil {
return nil, err
}
@@ -211,9 +211,9 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
}
// Delete Headers
if len(policy.DeleteHeaders) > 0 {
if IsNotNull(policy.DeleteHeaders) {
headers := []string{}
err = json.Unmarshal([]byte(policy.DeleteHeaders), &headers)
err = json.Unmarshal(policy.DeleteHeaders, &headers)
if err != nil {
return nil, err
}

View File

@@ -1,19 +1,21 @@
package models
import "github.com/iwind/TeaGo/dbs"
//
type HTTPHeaderPolicy struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
AddHeaders string `field:"addHeaders"` // 添加的Header
AddTrailers string `field:"addTrailers"` // 添加的Trailers
SetHeaders string `field:"setHeaders"` // 设置Header
ReplaceHeaders string `field:"replaceHeaders"` // 替换Header内容
Expires string `field:"expires"` // Expires单独设置
DeleteHeaders string `field:"deleteHeaders"` // 删除的Headers
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
AddHeaders dbs.JSON `field:"addHeaders"` // 添加的Header
AddTrailers dbs.JSON `field:"addTrailers"` // 添加的Trailers
SetHeaders dbs.JSON `field:"setHeaders"` // 设置Header
ReplaceHeaders dbs.JSON `field:"replaceHeaders"` // 替换Header内容
Expires dbs.JSON `field:"expires"` // Expires单独设置
DeleteHeaders dbs.JSON `field:"deleteHeaders"` // 删除的Headers
}
type HTTPHeaderPolicyOperator struct {

View File

@@ -170,12 +170,12 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
config := &serverconfigs.HTTPLocationConfig{}
config.Id = int64(location.Id)
config.IsOn = location.IsOn == 1
config.IsOn = location.IsOn
config.Description = location.Description
config.Name = location.Name
config.Pattern = location.Pattern
config.URLPrefix = location.UrlPrefix
config.IsBreak = location.IsBreak == 1
config.IsBreak = location.IsBreak
// web
if location.WebId > 0 {
@@ -189,7 +189,7 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
// reverse proxy
if IsNotNull(location.ReverseProxy) {
ref := &serverconfigs.ReverseProxyRef{}
err = json.Unmarshal([]byte(location.ReverseProxy), ref)
err = json.Unmarshal(location.ReverseProxy, ref)
if err != nil {
return nil, err
}
@@ -204,9 +204,9 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
}
// conds
if len(location.Conds) > 0 {
if IsNotNull(location.Conds) {
conds := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(location.Conds), conds)
err = json.Unmarshal(location.Conds, conds)
if err != nil {
return nil, err
}
@@ -214,9 +214,9 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
}
// domains
if len(location.Domains) > 0 {
if IsNotNull(location.Domains) {
var domains = []string{}
err = json.Unmarshal([]byte(location.Domains), &domains)
err = json.Unmarshal(location.Domains, &domains)
if err != nil {
return nil, err
}
@@ -241,7 +241,7 @@ func (this *HTTPLocationDAO) FindLocationReverseProxy(tx *dbs.Tx, locationId int
if err != nil {
return nil, err
}
if IsNotNull(refString) {
if IsNotNull([]byte(refString)) {
ref := &serverconfigs.ReverseProxyRef{}
err = json.Unmarshal([]byte(refString), ref)
if err != nil {

View File

@@ -1,24 +1,26 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPLocation 路由规则配置
type HTTPLocation struct {
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ParentId uint32 `field:"parentId"` // 父级ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
WebId uint32 `field:"webId"` // Web配置ID
ReverseProxy string `field:"reverseProxy"` // 反向代理
UrlPrefix string `field:"urlPrefix"` // URL前缀
IsBreak uint8 `field:"isBreak"` // 是否终止匹配
Conds string `field:"conds"` // 匹配条件
Domains string `field:"domains"` // 专属域名
Id uint32 `field:"id"` // ID
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
ParentId uint32 `field:"parentId"` // 父级ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
WebId uint32 `field:"webId"` // Web配置ID
ReverseProxy dbs.JSON `field:"reverseProxy"` // 反向代理
UrlPrefix string `field:"urlPrefix"` // URL前缀
IsBreak bool `field:"isBreak"` // 是否终止匹配
Conds dbs.JSON `field:"conds"` // 匹配条件
Domains dbs.JSON `field:"domains"` // 专属域名
}
type HTTPLocationOperator struct {

View File

@@ -154,7 +154,7 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
config := &serverconfigs.HTTPPageConfig{}
config.Id = int64(page.Id)
config.IsOn = page.IsOn == 1
config.IsOn = page.IsOn
config.NewStatus = int(page.NewStatus)
config.URL = page.Url
config.Body = page.Body
@@ -166,7 +166,7 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *u
if len(page.StatusList) > 0 {
statusList := []string{}
err = json.Unmarshal([]byte(page.StatusList), &statusList)
err = json.Unmarshal(page.StatusList, &statusList)
if err != nil {
return nil, err
}

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPPage 特殊页面
type HTTPPage struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
StatusList string `field:"statusList"` // 状态列表
Url string `field:"url"` // 页面URL
NewStatus int32 `field:"newStatus"` // 新状态码
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Body string `field:"body"` // 页面内容
BodyType string `field:"bodyType"` // 内容类型
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
StatusList dbs.JSON `field:"statusList"` // 状态列表
Url string `field:"url"` // 页面URL
NewStatus int32 `field:"newStatus"` // 新状态码
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Body string `field:"body"` // 页面内容
BodyType string `field:"bodyType"` // 内容类型
}
type HTTPPageOperator struct {

View File

@@ -97,19 +97,19 @@ func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int
config := &serverconfigs.HTTPRewriteRule{}
config.Id = int64(rule.Id)
config.IsOn = rule.IsOn == 1
config.IsOn = rule.IsOn
config.Pattern = rule.Pattern
config.Replace = rule.Replace
config.Mode = rule.Mode
config.RedirectStatus = types.Int(rule.RedirectStatus)
config.ProxyHost = rule.ProxyHost
config.IsBreak = rule.IsBreak == 1
config.IsBreak = rule.IsBreak
config.WithQuery = rule.WithQuery == 1
// conds
if len(rule.Conds) > 0 {
conds := &shared.HTTPRequestCondsConfig{}
err = json.Unmarshal([]byte(rule.Conds), conds)
err = json.Unmarshal(rule.Conds, conds)
if err != nil {
return nil, err
}

View File

@@ -1,22 +1,24 @@
package models
import "github.com/iwind/TeaGo/dbs"
// 重写规则
type HTTPRewriteRule struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn uint8 `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
Replace string `field:"replace"` // 跳转后的地址
Mode string `field:"mode"` // 替换模式
RedirectStatus uint32 `field:"redirectStatus"` // 跳转的状态码
ProxyHost string `field:"proxyHost"` // 代理的主机名
IsBreak uint8 `field:"isBreak"` // 是否终止解析
WithQuery uint8 `field:"withQuery"` // 是否保留URI参数
Conds string `field:"conds"` // 匹配条件
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
TemplateId uint32 `field:"templateId"` // 模版ID
IsOn bool `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Pattern string `field:"pattern"` // 匹配规则
Replace string `field:"replace"` // 跳转后的地址
Mode string `field:"mode"` // 替换模式
RedirectStatus uint32 `field:"redirectStatus"` // 跳转的状态码
ProxyHost string `field:"proxyHost"` // 代理的主机名
IsBreak bool `field:"isBreak"` // 是否终止解析
WithQuery uint8 `field:"withQuery"` // 是否保留URI参数
Conds dbs.JSON `field:"conds"` // 匹配条件
}
type HTTPRewriteRuleOperator struct {

View File

@@ -96,12 +96,12 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
config := &serverconfigs.HTTPWebConfig{}
config.Id = webId
config.IsOn = web.IsOn == 1
config.IsOn = web.IsOn
// root
if IsNotNull(web.Root) {
rootConfig := &serverconfigs.HTTPRootConfig{}
err = json.Unmarshal([]byte(web.Root), rootConfig)
err = json.Unmarshal(web.Root, rootConfig)
if err != nil {
return nil, err
}
@@ -111,7 +111,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// compression
if IsNotNull(web.Compression) {
compression := &serverconfigs.HTTPCompressionConfig{}
err = json.Unmarshal([]byte(web.Compression), compression)
err = json.Unmarshal(web.Compression, compression)
if err != nil {
return nil, err
}
@@ -148,7 +148,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// charset
if IsNotNull(web.Charset) {
charsetConfig := &serverconfigs.HTTPCharsetConfig{}
err = json.Unmarshal([]byte(web.Charset), charsetConfig)
err = json.Unmarshal(web.Charset, charsetConfig)
if err != nil {
return nil, err
}
@@ -158,7 +158,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// headers
if IsNotNull(web.RequestHeader) {
ref := &shared.HTTPHeaderPolicyRef{}
err = json.Unmarshal([]byte(web.RequestHeader), ref)
err = json.Unmarshal(web.RequestHeader, ref)
if err != nil {
return nil, err
}
@@ -177,7 +177,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
if IsNotNull(web.ResponseHeader) {
ref := &shared.HTTPHeaderPolicyRef{}
err = json.Unmarshal([]byte(web.ResponseHeader), ref)
err = json.Unmarshal(web.ResponseHeader, ref)
if err != nil {
return nil, err
}
@@ -197,7 +197,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// shutdown
if IsNotNull(web.Shutdown) {
shutdownConfig := &serverconfigs.HTTPShutdownConfig{}
err = json.Unmarshal([]byte(web.Shutdown), shutdownConfig)
err = json.Unmarshal(web.Shutdown, shutdownConfig)
if err != nil {
return nil, err
}
@@ -207,7 +207,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// pages
if IsNotNull(web.Pages) {
pages := []*serverconfigs.HTTPPageConfig{}
err = json.Unmarshal([]byte(web.Pages), &pages)
err = json.Unmarshal(web.Pages, &pages)
if err != nil {
return nil, err
}
@@ -226,7 +226,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 访问日志
if IsNotNull(web.AccessLog) {
accessLogConfig := &serverconfigs.HTTPAccessLogRef{}
err = json.Unmarshal([]byte(web.AccessLog), accessLogConfig)
err = json.Unmarshal(web.AccessLog, accessLogConfig)
if err != nil {
return nil, err
}
@@ -236,7 +236,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 统计配置
if IsNotNull(web.Stat) {
statRef := &serverconfigs.HTTPStatRef{}
err = json.Unmarshal([]byte(web.Stat), statRef)
err = json.Unmarshal(web.Stat, statRef)
if err != nil {
return nil, err
}
@@ -246,7 +246,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 缓存配置
if IsNotNull(web.Cache) {
cacheConfig := &serverconfigs.HTTPCacheConfig{}
err = json.Unmarshal([]byte(web.Cache), &cacheConfig)
err = json.Unmarshal(web.Cache, &cacheConfig)
if err != nil {
return nil, err
}
@@ -258,7 +258,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 防火墙配置
if IsNotNull(web.Firewall) {
firewallRef := &firewallconfigs.HTTPFirewallRef{}
err = json.Unmarshal([]byte(web.Firewall), firewallRef)
err = json.Unmarshal(web.Firewall, firewallRef)
if err != nil {
return nil, err
}
@@ -281,7 +281,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 路由规则
if IsNotNull(web.Locations) {
refs := []*serverconfigs.HTTPLocationRef{}
err = json.Unmarshal([]byte(web.Locations), &refs)
err = json.Unmarshal(web.Locations, &refs)
if err != nil {
return nil, err
}
@@ -299,7 +299,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 跳转
if IsNotNull(web.RedirectToHttps) {
redirectToHTTPSConfig := &serverconfigs.HTTPRedirectToHTTPSConfig{}
err = json.Unmarshal([]byte(web.RedirectToHttps), redirectToHTTPSConfig)
err = json.Unmarshal(web.RedirectToHttps, redirectToHTTPSConfig)
if err != nil {
return nil, err
}
@@ -309,7 +309,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// Websocket
if IsNotNull(web.Websocket) {
ref := &serverconfigs.HTTPWebsocketRef{}
err = json.Unmarshal([]byte(web.Websocket), ref)
err = json.Unmarshal(web.Websocket, ref)
if err != nil {
return nil, err
}
@@ -328,7 +328,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 重写规则
if IsNotNull(web.RewriteRules) {
refs := []*serverconfigs.HTTPRewriteRef{}
err = json.Unmarshal([]byte(web.RewriteRules), &refs)
err = json.Unmarshal(web.RewriteRules, &refs)
if err != nil {
return nil, err
}
@@ -347,7 +347,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 主机跳转
if IsNotNull(web.HostRedirects) {
redirects := []*serverconfigs.HTTPHostRedirectConfig{}
err = json.Unmarshal([]byte(web.HostRedirects), &redirects)
err = json.Unmarshal(web.HostRedirects, &redirects)
if err != nil {
return nil, err
}
@@ -357,7 +357,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// Fastcgi
if IsNotNull(web.Fastcgi) {
ref := &serverconfigs.HTTPFastcgiRef{}
err = json.Unmarshal([]byte(web.Fastcgi), ref)
err = json.Unmarshal(web.Fastcgi, ref)
if err != nil {
return nil, err
}
@@ -381,7 +381,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// 认证
if IsNotNull(web.Auth) {
authConfig := &serverconfigs.HTTPAuthConfig{}
err = json.Unmarshal([]byte(web.Auth), authConfig)
err = json.Unmarshal(web.Auth, authConfig)
if err != nil {
return nil, err
}
@@ -402,7 +402,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// WebP
if IsNotNull(web.Webp) {
var webpConfig = &serverconfigs.WebPImageConfig{}
err = json.Unmarshal([]byte(web.Webp), webpConfig)
err = json.Unmarshal(web.Webp, webpConfig)
if err != nil {
return nil, err
}
@@ -412,7 +412,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
// RemoteAddr
if IsNotNull(web.RemoteAddr) {
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{}
err = json.Unmarshal([]byte(web.RemoteAddr), remoteAddrConfig)
err = json.Unmarshal(web.RemoteAddr, remoteAddrConfig)
if err != nil {
return nil, err
}
@@ -426,7 +426,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
if len(web.RequestLimit) > 0 {
var requestLimitConfig = &serverconfigs.HTTPRequestLimitConfig{}
if len(web.RequestLimit) > 0 {
err = json.Unmarshal([]byte(web.RequestLimit), requestLimitConfig)
err = json.Unmarshal(web.RequestLimit, requestLimitConfig)
if err != nil {
return nil, err
}
@@ -438,7 +438,7 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
if len(web.RequestScripts) > 0 {
var requestScriptsConfig = &serverconfigs.HTTPRequestScriptsConfig{}
if len(web.RequestScripts) > 0 {
err = json.Unmarshal([]byte(web.RequestScripts), requestScriptsConfig)
err = json.Unmarshal(web.RequestScripts, requestScriptsConfig)
if err != nil {
return nil, err
}

View File

@@ -1,40 +1,42 @@
package models
import "github.com/iwind/TeaGo/dbs"
// HTTPWeb HTTP Web
type HTTPWeb struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Root string `field:"root"` // 根目录
Charset string `field:"charset"` // 字符集
Shutdown string `field:"shutdown"` // 临时关闭页面配置
Pages string `field:"pages"` // 特殊页面
RedirectToHttps string `field:"redirectToHttps"` // 跳转到HTTPS设置
Indexes string `field:"indexes"` // 首页文件列表
MaxRequestBodySize string `field:"maxRequestBodySize"` // 最大允许的请求内容尺寸
RequestHeader string `field:"requestHeader"` // 请求Header配置
ResponseHeader string `field:"responseHeader"` // 响应Header配置
AccessLog string `field:"accessLog"` // 访问日志配置
Stat string `field:"stat"` // 统计配置
Gzip string `field:"gzip"` // Gzip配置v0.3.2弃用)
Compression string `field:"compression"` // 压缩配置
Cache string `field:"cache"` // 缓存配置
Firewall string `field:"firewall"` // 防火墙设置
Locations string `field:"locations"` // 路由规则配置
Websocket string `field:"websocket"` // Websocket设置
RewriteRules string `field:"rewriteRules"` // 重写规则配置
HostRedirects string `field:"hostRedirects"` // 域名跳转
Fastcgi string `field:"fastcgi"` // Fastcgi配置
Auth string `field:"auth"` // 认证策略配置
Webp string `field:"webp"` // WebP配置
RemoteAddr string `field:"remoteAddr"` // 客户端IP配置
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
RequestLimit string `field:"requestLimit"` // 请求限制
RequestScripts string `field:"requestScripts"` // 请求脚本
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
TemplateId uint32 `field:"templateId"` // 模版ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Root dbs.JSON `field:"root"` // 根目录
Charset dbs.JSON `field:"charset"` // 字符集
Shutdown dbs.JSON `field:"shutdown"` // 临时关闭页面配置
Pages dbs.JSON `field:"pages"` // 特殊页面
RedirectToHttps dbs.JSON `field:"redirectToHttps"` // 跳转到HTTPS设置
Indexes dbs.JSON `field:"indexes"` // 首页文件列表
MaxRequestBodySize dbs.JSON `field:"maxRequestBodySize"` // 最大允许的请求内容尺寸
RequestHeader dbs.JSON `field:"requestHeader"` // 请求Header配置
ResponseHeader dbs.JSON `field:"responseHeader"` // 响应Header配置
AccessLog dbs.JSON `field:"accessLog"` // 访问日志配置
Stat dbs.JSON `field:"stat"` // 统计配置
Gzip dbs.JSON `field:"gzip"` // Gzip配置v0.3.2弃用)
Compression dbs.JSON `field:"compression"` // 压缩配置
Cache dbs.JSON `field:"cache"` // 缓存配置
Firewall dbs.JSON `field:"firewall"` // 防火墙设置
Locations dbs.JSON `field:"locations"` // 路由规则配置
Websocket dbs.JSON `field:"websocket"` // Websocket设置
RewriteRules dbs.JSON `field:"rewriteRules"` // 重写规则配置
HostRedirects dbs.JSON `field:"hostRedirects"` // 域名跳转
Fastcgi dbs.JSON `field:"fastcgi"` // Fastcgi配置
Auth dbs.JSON `field:"auth"` // 认证策略配置
Webp dbs.JSON `field:"webp"` // WebP配置
RemoteAddr dbs.JSON `field:"remoteAddr"` // 客户端IP配置
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
RequestLimit dbs.JSON `field:"requestLimit"` // 请求限制
RequestScripts dbs.JSON `field:"requestScripts"` // 请求脚本
}
type HTTPWebOperator struct {

View File

@@ -37,7 +37,7 @@ func init() {
})
}
// 启用条目
// EnableHTTPWebsocket 启用条目
func (this *HTTPWebsocketDAO) EnableHTTPWebsocket(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
@@ -46,7 +46,7 @@ func (this *HTTPWebsocketDAO) EnableHTTPWebsocket(tx *dbs.Tx, id int64) error {
return err
}
// 禁用条目
// DisableHTTPWebsocket 禁用条目
func (this *HTTPWebsocketDAO) DisableHTTPWebsocket(tx *dbs.Tx, websocketId int64) error {
_, err := this.Query(tx).
Pk(websocketId).
@@ -58,7 +58,7 @@ func (this *HTTPWebsocketDAO) DisableHTTPWebsocket(tx *dbs.Tx, websocketId int64
return this.NotifyUpdate(tx, websocketId)
}
// 查找启用中的条目
// FindEnabledHTTPWebsocket 查找启用中的条目
func (this *HTTPWebsocketDAO) FindEnabledHTTPWebsocket(tx *dbs.Tx, id int64) (*HTTPWebsocket, error) {
result, err := this.Query(tx).
Pk(id).
@@ -70,7 +70,7 @@ func (this *HTTPWebsocketDAO) FindEnabledHTTPWebsocket(tx *dbs.Tx, id int64) (*H
return result.(*HTTPWebsocket), err
}
// 组合配置
// ComposeWebsocketConfig 组合配置
func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int64) (*serverconfigs.HTTPWebsocketConfig, error) {
websocket, err := this.FindEnabledHTTPWebsocket(tx, websocketId)
if err != nil {
@@ -81,12 +81,12 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
}
config := &serverconfigs.HTTPWebsocketConfig{}
config.Id = int64(websocket.Id)
config.IsOn = websocket.IsOn == 1
config.IsOn = websocket.IsOn
config.AllowAllOrigins = websocket.AllowAllOrigins == 1
if IsNotNull(websocket.AllowedOrigins) {
origins := []string{}
err = json.Unmarshal([]byte(websocket.AllowedOrigins), &origins)
err = json.Unmarshal(websocket.AllowedOrigins, &origins)
if err != nil {
return nil, err
}
@@ -95,7 +95,7 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
if IsNotNull(websocket.HandshakeTimeout) {
duration := &shared.TimeDuration{}
err = json.Unmarshal([]byte(websocket.HandshakeTimeout), duration)
err = json.Unmarshal(websocket.HandshakeTimeout, duration)
if err != nil {
return nil, err
}
@@ -108,7 +108,7 @@ func (this *HTTPWebsocketDAO) ComposeWebsocketConfig(tx *dbs.Tx, websocketId int
return config, nil
}
// 创建Websocket配置
// CreateWebsocket 创建Websocket配置
func (this *HTTPWebsocketDAO) CreateWebsocket(tx *dbs.Tx, handshakeTimeoutJSON []byte, allowAllOrigins bool, allowedOrigins []string, requestSameOrigin bool, requestOrigin string) (websocketId int64, err error) {
op := NewHTTPWebsocketOperator()
op.IsOn = true
@@ -130,7 +130,7 @@ func (this *HTTPWebsocketDAO) CreateWebsocket(tx *dbs.Tx, handshakeTimeoutJSON [
return types.Int64(op.Id), err
}
// 修改Websocket配置
// UpdateWebsocket 修改Websocket配置
func (this *HTTPWebsocketDAO) UpdateWebsocket(tx *dbs.Tx, websocketId int64, handshakeTimeoutJSON []byte, allowAllOrigins bool, allowedOrigins []string, requestSameOrigin bool, requestOrigin string) error {
if websocketId <= 0 {
return errors.New("invalid websocketId")
@@ -159,7 +159,7 @@ func (this *HTTPWebsocketDAO) UpdateWebsocket(tx *dbs.Tx, websocketId int64, han
return this.NotifyUpdate(tx, websocketId)
}
// 通知更新
// NotifyUpdate 通知更新
func (this *HTTPWebsocketDAO) NotifyUpdate(tx *dbs.Tx, websocketId int64) error {
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithWebsocketId(tx, websocketId)
if err != nil {

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// Websocket设置
type HTTPWebsocket struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
IsOn uint8 `field:"isOn"` // 是否启用
HandshakeTimeout string `field:"handshakeTimeout"` // 握手超时时间
AllowAllOrigins uint8 `field:"allowAllOrigins"` // 是否支持所有源
AllowedOrigins string `field:"allowedOrigins"` // 支持的源域名列表
RequestSameOrigin uint8 `field:"requestSameOrigin"` // 是否请求一样的Origin
RequestOrigin string `field:"requestOrigin"` // 请求Origin
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
State uint8 `field:"state"` // 状态
IsOn bool `field:"isOn"` // 是否启用
HandshakeTimeout dbs.JSON `field:"handshakeTimeout"` // 握手超时时间
AllowAllOrigins uint8 `field:"allowAllOrigins"` // 是否支持所有源
AllowedOrigins dbs.JSON `field:"allowedOrigins"` // 支持的源域名列表
RequestSameOrigin uint8 `field:"requestSameOrigin"` // 是否请求一样的Origin
RequestOrigin string `field:"requestOrigin"` // 请求Origin
}
type HTTPWebsocketOperator struct {

View File

@@ -23,7 +23,7 @@ type IPItem struct {
SourceHTTPFirewallPolicyId uint32 `field:"sourceHTTPFirewallPolicyId"` // 来源策略ID
SourceHTTPFirewallRuleGroupId uint32 `field:"sourceHTTPFirewallRuleGroupId"` // 来源规则集分组ID
SourceHTTPFirewallRuleSetId uint32 `field:"sourceHTTPFirewallRuleSetId"` // 来源规则集ID
IsRead uint8 `field:"isRead"` // 是否已读
IsRead bool `field:"isRead"` // 是否已读
}
type IPItemOperator struct {

View File

@@ -22,11 +22,11 @@ var listTypeCacheMap = map[int64]*IPList{} // listId => *IPList
var DefaultGlobalIPList = &IPList{
Id: uint32(firewallconfigs.GlobalListId),
Name: "全局封锁名单",
IsPublic: 1,
IsGlobal: 1,
IsPublic: true,
IsGlobal: true,
Type: "black",
State: IPListStateEnabled,
IsOn: 1,
IsOn: true,
}
type IPListDAO dbs.DAO
@@ -184,6 +184,10 @@ func (this *IPListDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
// CheckUserIPList 检查用户权限
func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) error {
if userId == 0 || listId == 0 {
return ErrNotFound
}
ok, err := this.Query(tx).
Pk(listId).
Attr("userId", userId).
@@ -194,6 +198,18 @@ func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) e
if ok {
return nil
}
// 检查是否被用户的服务所使用
policyIds, err := SharedHTTPFirewallPolicyDAO.FindEnabledFirewallPolicyIdsWithIPListId(tx, listId)
if err != nil {
return err
}
for _, policyId := range policyIds {
if SharedHTTPFirewallPolicyDAO.CheckUserFirewallPolicy(tx, userId, policyId) == nil {
return nil
}
}
return ErrNotFound
}

View File

@@ -1,21 +1,23 @@
package models
import "github.com/iwind/TeaGo/dbs"
// IPList IP名单
type IPList struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Type string `field:"type"` // 类型
AdminId uint32 `field:"adminId"` // 用户ID
UserId uint32 `field:"userId"` // 用户ID
Name string `field:"name"` // 列表名
Code string `field:"code"` // 代号
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Timeout string `field:"timeout"` // 默认超时时间
Actions string `field:"actions"` // IP触发的动作
Description string `field:"description"` // 描述
IsPublic uint8 `field:"isPublic"` // 是否公用
IsGlobal uint8 `field:"isGlobal"` // 是否全局
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Type string `field:"type"` // 类型
AdminId uint32 `field:"adminId"` // 用户ID
UserId uint32 `field:"userId"` // 用户ID
Name string `field:"name"` // 列表名
Code string `field:"code"` // 代号
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Timeout dbs.JSON `field:"timeout"` // 默认超时时间
Actions dbs.JSON `field:"actions"` // IP触发的动作
Description string `field:"description"` // 描述
IsPublic bool `field:"isPublic"` // 是否公用
IsGlobal bool `field:"isGlobal"` // 是否全局
}
type IPListOperator struct {

View File

@@ -33,7 +33,7 @@ func init() {
})
}
// 创建管理员日志
// CreateLog 创建管理员日志
func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level string, description string, action string, ip string) error {
op := NewLogOperator()
op.Level = level
@@ -57,7 +57,7 @@ func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level
return err
}
// 计算所有日志数量
// CountLogs 计算所有日志数量
func (this *LogDAO) CountLogs(tx *dbs.Tx, dayFrom string, dayTo string, keyword string, userType string) (int64, error) {
dayFrom = this.formatDay(dayFrom)
dayTo = this.formatDay(dayTo)
@@ -86,7 +86,7 @@ func (this *LogDAO) CountLogs(tx *dbs.Tx, dayFrom string, dayTo string, keyword
return query.Count()
}
// 列出单页日志
// ListLogs 列出单页日志
func (this *LogDAO) ListLogs(tx *dbs.Tx, offset int64, size int64, dayFrom string, dayTo string, keyword string, userType string) (result []*Log, err error) {
dayFrom = this.formatDay(dayFrom)
dayTo = this.formatDay(dayTo)
@@ -120,7 +120,7 @@ func (this *LogDAO) ListLogs(tx *dbs.Tx, offset int64, size int64, dayFrom strin
return
}
// 物理删除日志
// DeleteLogPermanently 物理删除日志
func (this *LogDAO) DeleteLogPermanently(tx *dbs.Tx, logId int64) error {
if logId <= 0 {
return errors.New("invalid logId")
@@ -129,14 +129,14 @@ func (this *LogDAO) DeleteLogPermanently(tx *dbs.Tx, logId int64) error {
return err
}
// 物理删除所有日志
// DeleteAllLogsPermanently 物理删除所有日志
func (this *LogDAO) DeleteAllLogsPermanently(tx *dbs.Tx) error {
_, err := this.Query(tx).
Delete()
return err
}
// 物理删除某些天之前的日志
// DeleteLogsPermanentlyBeforeDays 物理删除某些天之前的日志
func (this *LogDAO) DeleteLogsPermanentlyBeforeDays(tx *dbs.Tx, days int) error {
if days <= 0 {
days = 0
@@ -148,7 +148,7 @@ func (this *LogDAO) DeleteLogsPermanentlyBeforeDays(tx *dbs.Tx, days int) error
return err
}
// 计算当前日志容量大小
// SumLogsSize 计算当前日志容量大小
func (this *LogDAO) SumLogsSize() (int64, error) {
col, err := this.Instance.FindCol(0, "SELECT DATA_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME=? LIMIT 1", this.Instance.Name(), this.Table)
if err != nil {

View File

@@ -1,14 +1,16 @@
package models
// 第三方登录认证
import "github.com/iwind/TeaGo/dbs"
// Login 第三方登录认证
type Login struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Type string `field:"type"` // 认证方式
Params string `field:"params"` // 参数
State uint8 `field:"state"` // 状态
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Type string `field:"type"` // 认证方式
Params dbs.JSON `field:"params"` // 参数
State uint8 `field:"state"` // 状态
}
type LoginOperator struct {

View File

@@ -1,16 +1,18 @@
package models
import "github.com/iwind/TeaGo/dbs"
// MessageMediaInstance 消息媒介接收人
type MessageMediaInstance struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
IsOn uint8 `field:"isOn"` // 是否启用
MediaType string `field:"mediaType"` // 媒介类型
Params string `field:"params"` // 媒介参数
Description string `field:"description"` // 备注
Rate string `field:"rate"` // 发送频率
State uint8 `field:"state"` // 状态
HashLife int32 `field:"hashLife"` // HASH有效期
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
IsOn bool `field:"isOn"` // 是否启用
MediaType string `field:"mediaType"` // 媒介类型
Params dbs.JSON `field:"params"` // 媒介参数
Description string `field:"description"` // 备注
Rate dbs.JSON `field:"rate"` // 发送频率
State uint8 `field:"state"` // 状态
HashLife int32 `field:"hashLife"` // HASH有效期
}
type MessageMediaInstanceOperator struct {

View File

@@ -1,13 +1,13 @@
package models
// 消息媒介
// MessageMedia 消息媒介
type MessageMedia struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 名称
Type string `field:"type"` // 类型
Description string `field:"description"` // 描述
UserDescription string `field:"userDescription"` // 用户描述
IsOn uint8 `field:"isOn"` // 是否启用
IsOn bool `field:"isOn"` // 是否启用
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
}

View File

@@ -1,23 +1,25 @@
package models
import "github.com/iwind/TeaGo/dbs"
// Message 消息通知
type Message struct {
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Role string `field:"role"` // 角色
ClusterId uint32 `field:"clusterId"` // 集群ID
NodeId uint32 `field:"nodeId"` // 节点ID
Level string `field:"level"` // 级别
Subject string `field:"subject"` // 标题
Body string `field:"body"` // 内容
Type string `field:"type"` // 消息类型
Params string `field:"params"` // 额外的参数
IsRead uint8 `field:"isRead"` // 是否已读
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Day string `field:"day"` // 日期YYYYMMDD
Hash string `field:"hash"` // 消息内容的Hash
Id uint64 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Role string `field:"role"` // 角色
ClusterId uint32 `field:"clusterId"` // 集群ID
NodeId uint32 `field:"nodeId"` // 节点ID
Level string `field:"level"` // 级别
Subject string `field:"subject"` // 标题
Body string `field:"body"` // 内容
Type string `field:"type"` // 消息类型
Params dbs.JSON `field:"params"` // 额外的参数
IsRead bool `field:"isRead"` // 是否已读
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
Day string `field:"day"` // 日期YYYYMMDD
Hash string `field:"hash"` // 消息内容的Hash
}
type MessageOperator struct {

View File

@@ -1,17 +1,19 @@
package models
import "github.com/iwind/TeaGo/dbs"
// MessageReceiver 消息通知接收人
type MessageReceiver struct {
Id uint32 `field:"id"` // ID
Role string `field:"role"` // 节点角色
ClusterId uint32 `field:"clusterId"` // 集群ID
NodeId uint32 `field:"nodeId"` // 节点ID
ServerId uint32 `field:"serverId"` // 服务ID
Type string `field:"type"` // 类型
Params string `field:"params"` // 参数
RecipientId uint32 `field:"recipientId"` // 接收人ID
RecipientGroupId uint32 `field:"recipientGroupId"` // 接收人分组ID
State uint8 `field:"state"` // 状态
Id uint32 `field:"id"` // ID
Role string `field:"role"` // 节点角色
ClusterId uint32 `field:"clusterId"` // 集群ID
NodeId uint32 `field:"nodeId"` // 节点ID
ServerId uint32 `field:"serverId"` // 服务ID
Type string `field:"type"` // 类型
Params dbs.JSON `field:"params"` // 参数
RecipientId uint32 `field:"recipientId"` // 接收人ID
RecipientGroupId uint32 `field:"recipientGroupId"` // 接收人分组ID
State uint8 `field:"state"` // 状态
}
type MessageReceiverOperator struct {

View File

@@ -1,11 +1,11 @@
package models
// 消息接收人分组
// MessageRecipientGroup 消息接收人分组
type MessageRecipientGroup struct {
Id uint32 `field:"id"` // ID
Name string `field:"name"` // 分组名
Order uint32 `field:"order"` // 排序
IsOn uint8 `field:"isOn"` // 是否启用
IsOn bool `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
}

View File

@@ -1,17 +1,19 @@
package models
import "github.com/iwind/TeaGo/dbs"
// MessageRecipient 消息媒介接收人
type MessageRecipient struct {
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
IsOn uint8 `field:"isOn"` // 是否启用
InstanceId uint32 `field:"instanceId"` // 实例ID
User string `field:"user"` // 接收人信息
GroupIds string `field:"groupIds"` // 分组ID
State uint8 `field:"state"` // 状态
TimeFrom string `field:"timeFrom"` // 开始时间
TimeTo string `field:"timeTo"` // 结束时间
Description string `field:"description"` // 备注
Id uint32 `field:"id"` // ID
AdminId uint32 `field:"adminId"` // 管理员ID
IsOn bool `field:"isOn"` // 是否启用
InstanceId uint32 `field:"instanceId"` // 实例ID
User string `field:"user"` // 接收人信息
GroupIds dbs.JSON `field:"groupIds"` // 分组ID
State uint8 `field:"state"` // 状态
TimeFrom string `field:"timeFrom"` // 开始时间
TimeTo string `field:"timeTo"` // 结束时间
Description string `field:"description"` // 备注
}
type MessageRecipientOperator struct {

View File

@@ -5,13 +5,13 @@ import (
"github.com/iwind/TeaGo/logs"
)
// 解析分组ID
// DecodeGroupIds 解析分组ID
func (this *MessageRecipient) DecodeGroupIds() []int64 {
if len(this.GroupIds) == 0 {
return []int64{}
}
result := []int64{}
err := json.Unmarshal([]byte(this.GroupIds), &result)
err := json.Unmarshal(this.GroupIds, &result)
if err != nil {
logs.Println("MessageRecipient.DecodeGroupIds(): " + err.Error())
// 不阻断执行

View File

@@ -5,7 +5,7 @@ type MessageTaskLog struct {
Id uint64 `field:"id"` // ID
TaskId uint64 `field:"taskId"` // 任务ID
CreatedAt uint64 `field:"createdAt"` // 创建时间
IsOk uint8 `field:"isOk"` // 是否成功
IsOk bool `field:"isOk"` // 是否成功
Error string `field:"error"` // 错误信息
Response string `field:"response"` // 响应信息
Day string `field:"day"` // YYYYMMDD

View File

@@ -1,21 +1,23 @@
package models
import "github.com/iwind/TeaGo/dbs"
// MessageTask 消息发送相关任务
type MessageTask struct {
Id uint64 `field:"id"` // ID
RecipientId uint32 `field:"recipientId"` // 接收人ID
Hash string `field:"hash"` // SUM标识
InstanceId uint32 `field:"instanceId"` // 媒介实例ID
User string `field:"user"` // 接收用户标识
Subject string `field:"subject"` // 标题
Body string `field:"body"` // 内容
CreatedAt uint64 `field:"createdAt"` // 创建时间
Status uint8 `field:"status"` // 发送状态
SentAt uint64 `field:"sentAt"` // 最后一次发送时间
State uint8 `field:"state"` // 状态
Result string `field:"result"` // 结果
Day string `field:"day"` // YYYYMMDD
IsPrimary uint8 `field:"isPrimary"` // 是否优先
Id uint64 `field:"id"` // ID
RecipientId uint32 `field:"recipientId"` // 接收人ID
Hash string `field:"hash"` // SUM标识
InstanceId uint32 `field:"instanceId"` // 媒介实例ID
User string `field:"user"` // 接收用户标识
Subject string `field:"subject"` // 标题
Body string `field:"body"` // 内容
CreatedAt uint64 `field:"createdAt"` // 创建时间
Status uint8 `field:"status"` // 发送状态
SentAt uint64 `field:"sentAt"` // 最后一次发送时间
State uint8 `field:"state"` // 状态
Result dbs.JSON `field:"result"` // 结果
Day string `field:"day"` // YYYYMMDD
IsPrimary bool `field:"isPrimary"` // 是否优先
}
type MessageTaskOperator struct {

View File

@@ -1,20 +1,22 @@
package models
import "github.com/iwind/TeaGo/dbs"
// MetricChart 指标图表
type MetricChart struct {
Id uint32 `field:"id"` // ID
ItemId uint32 `field:"itemId"` // 指标ID
Name string `field:"name"` // 名称
Code string `field:"code"` // 代号
Type string `field:"type"` // 图形类型
WidthDiv int32 `field:"widthDiv"` // 宽度划分
Params string `field:"params"` // 图形参数
Order uint32 `field:"order"` // 排序
IsOn uint8 `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
MaxItems uint32 `field:"maxItems"` // 最多条目
IgnoreEmptyKeys uint8 `field:"ignoreEmptyKeys"` // 忽略空的键值
IgnoredKeys string `field:"ignoredKeys"` // 忽略键值
Id uint32 `field:"id"` // ID
ItemId uint32 `field:"itemId"` // 指标ID
Name string `field:"name"` // 名称
Code string `field:"code"` // 代号
Type string `field:"type"` // 图形类型
WidthDiv int32 `field:"widthDiv"` // 宽度划分
Params dbs.JSON `field:"params"` // 图形参数
Order uint32 `field:"order"` // 排序
IsOn bool `field:"isOn"` // 是否启用
State uint8 `field:"state"` // 状态
MaxItems uint32 `field:"maxItems"` // 最多条目
IgnoreEmptyKeys uint8 `field:"ignoreEmptyKeys"` // 忽略空的键值
IgnoredKeys dbs.JSON `field:"ignoredKeys"` // 忽略键值
}
type MetricChartOperator struct {

View File

@@ -8,7 +8,7 @@ func (this *MetricChart) DecodeIgnoredKeys() []string {
}
var result = []string{}
err := json.Unmarshal([]byte(this.IgnoredKeys), &result)
err := json.Unmarshal(this.IgnoredKeys, &result)
if err != nil {
// 这里忽略错误
return result

View File

@@ -161,7 +161,7 @@ func (this *MetricItemDAO) UpdateItem(tx *dbs.Tx, itemId int64, name string, key
if oldItem == nil {
return nil
}
oldIsPublic := oldItem.IsPublic == 1
oldIsPublic := oldItem.IsPublic
var versionChanged = false
if strings.Join(oldItem.DecodeKeys(), "&") != strings.Join(keys, "&") || types.Int32(oldItem.Period) != period || oldItem.PeriodUnit != periodUnit || oldItem.Value != value {
versionChanged = true
@@ -194,7 +194,7 @@ func (this *MetricItemDAO) UpdateItem(tx *dbs.Tx, itemId int64, name string, key
}
// 通知更新
if versionChanged || (oldItem.IsOn == 0 && isOn) || (oldItem.IsOn == 1 && !isOn) || oldIsPublic != isPublic {
if versionChanged || (!oldItem.IsOn && isOn) || (oldItem.IsOn && !isOn) || oldIsPublic != isPublic {
err := this.NotifyUpdate(tx, itemId, isPublic || oldIsPublic)
if err != nil {
return err
@@ -283,7 +283,7 @@ func (this *MetricItemDAO) ComposeItemConfig(tx *dbs.Tx, itemId int64) (*serverc
var item = one.(*MetricItem)
var config = &serverconfigs.MetricItemConfig{
Id: int64(item.Id),
IsOn: item.IsOn == 1,
IsOn: item.IsOn,
Period: types.Int(item.Period),
PeriodUnit: item.PeriodUnit,
Category: item.Category,
@@ -302,7 +302,7 @@ func (this *MetricItemDAO) ComposeItemConfigWithItem(item *MetricItem) *serverco
}
var config = &serverconfigs.MetricItemConfig{
Id: int64(item.Id),
IsOn: item.IsOn == 1,
IsOn: item.IsOn,
Period: types.Int(item.Period),
PeriodUnit: item.PeriodUnit,
Category: item.Category,

View File

@@ -1,21 +1,23 @@
package models
import "github.com/iwind/TeaGo/dbs"
// MetricItem 指标定义
type MetricItem struct {
Id uint64 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
Code string `field:"code"` // 代号(用来区分是否内置)
Category string `field:"category"` // 类型比如http, tcp等
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Name string `field:"name"` // 指标名称
Keys string `field:"keys"` // 统计的Key
Period uint32 `field:"period"` // 周期
PeriodUnit string `field:"periodUnit"` // 周期单位
Value string `field:"value"` // 值运算
State uint8 `field:"state"` // 状态
Version uint32 `field:"version"` // 版本号
IsPublic uint8 `field:"isPublic"` // 是否为公用
Id uint64 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
Code string `field:"code"` // 代号(用来区分是否内置)
Category string `field:"category"` // 类型比如http, tcp等
AdminId uint32 `field:"adminId"` // 管理员ID
UserId uint32 `field:"userId"` // 用户ID
Name string `field:"name"` // 指标名称
Keys dbs.JSON `field:"keys"` // 统计的Key
Period uint32 `field:"period"` // 周期
PeriodUnit string `field:"periodUnit"` // 周期单位
Value string `field:"value"` // 值运算
State uint8 `field:"state"` // 状态
Version uint32 `field:"version"` // 版本号
IsPublic bool `field:"isPublic"` // 是否为公用
}
type MetricItemOperator struct {

View File

@@ -8,7 +8,7 @@ import (
func (this *MetricItem) DecodeKeys() []string {
var result []string
if len(this.Keys) > 0 {
_ = json.Unmarshal([]byte(this.Keys), &result)
_ = json.Unmarshal(this.Keys, &result)
}
return result
}

View File

@@ -1,18 +1,20 @@
package models
import "github.com/iwind/TeaGo/dbs"
// MetricStat 指标统计数据
type MetricStat struct {
Id uint64 `field:"id"` // ID
Hash string `field:"hash"` // Hash值
ClusterId uint32 `field:"clusterId"` // 集群ID
NodeId uint32 `field:"nodeId"` // 节点ID
ServerId uint32 `field:"serverId"` // 服务ID
ItemId uint64 `field:"itemId"` // 指标
Keys string `field:"keys"` // 键值
Value float64 `field:"value"` // 数值
Time string `field:"time"` // 分钟值YYYYMMDDHHII
Version uint32 `field:"version"` // 版本号
CreatedDay string `field:"createdDay"` // YYYYMMDD
Id uint64 `field:"id"` // ID
Hash string `field:"hash"` // Hash值
ClusterId uint32 `field:"clusterId"` // 集群ID
NodeId uint32 `field:"nodeId"` // 节点ID
ServerId uint32 `field:"serverId"` // 服务ID
ItemId uint64 `field:"itemId"` // 指标
Keys dbs.JSON `field:"keys"` // 键值
Value float64 `field:"value"` // 数值
Time string `field:"time"` // 分钟值YYYYMMDDHHII
Version uint32 `field:"version"` // 版本号
CreatedDay string `field:"createdDay"` // YYYYMMDD
}
type MetricStatOperator struct {

View File

@@ -6,7 +6,7 @@ import "encoding/json"
func (this *MetricStat) DecodeKeys() []string {
var result []string
if len(this.Keys) > 0 {
_ = json.Unmarshal([]byte(this.Keys), &result)
_ = json.Unmarshal(this.Keys, &result)
}
return result
}

View File

@@ -1,19 +1,21 @@
package models
// 监控节点
import "github.com/iwind/TeaGo/dbs"
// MonitorNode 监控节点
type MonitorNode struct {
Id uint32 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 是否启用
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status string `field:"status"` // 运行状态
Id uint32 `field:"id"` // ID
IsOn bool `field:"isOn"` // 是否启用
UniqueId string `field:"uniqueId"` // 唯一ID
Secret string `field:"secret"` // 密钥
Name string `field:"name"` // 名称
Description string `field:"description"` // 描述
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
CreatedAt uint64 `field:"createdAt"` // 创建时间
AdminId uint32 `field:"adminId"` // 管理员ID
Weight uint32 `field:"weight"` // 权重
Status dbs.JSON `field:"status"` // 运行状态
}
type MonitorNodeOperator struct {

View File

@@ -1,16 +1,18 @@
package nameservers
import "github.com/iwind/TeaGo/dbs"
// NSDomain DNS域名
type NSDomain struct {
Id uint32 `field:"id"` // ID
ClusterId uint32 `field:"clusterId"` // 集群ID
UserId uint32 `field:"userId"` // 用户ID
IsOn uint8 `field:"isOn"` // 是否启用
Name string `field:"name"` // 域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
Version uint64 `field:"version"` // 版本
State uint8 `field:"state"` // 状态
Tsig string `field:"tsig"` // TSIG配置
Id uint32 `field:"id"` // ID
ClusterId uint32 `field:"clusterId"` // 集群ID
UserId uint32 `field:"userId"` // 用户ID
IsOn bool `field:"isOn"` // 是否启用
Name string `field:"name"` // 域名
CreatedAt uint64 `field:"createdAt"` // 创建时间
Version uint64 `field:"version"` // 版本
State uint8 `field:"state"` // 状态
Tsig dbs.JSON `field:"tsig"` // TSIG配置
}
type NSDomainOperator struct {

View File

@@ -3,7 +3,7 @@ package nameservers
// NSKey 密钥管理
type NSKey struct {
Id uint64 `field:"id"` // ID
IsOn uint8 `field:"isOn"` // 状态
IsOn bool `field:"isOn"` // 状态
Name string `field:"name"` // 名称
DomainId uint64 `field:"domainId"` // 域名ID
ZoneId uint64 `field:"zoneId"` // 子域ID

View File

@@ -1,11 +1,13 @@
package nameservers
import "github.com/iwind/TeaGo/dbs"
// NSQuestionOption DNS请求选项
type NSQuestionOption struct {
Id uint64 `field:"id"` // ID
Name string `field:"name"` // 选项名
Values string `field:"values"` // 选项值
CreatedAt uint64 `field:"createdAt"` // 创建时间
Id uint64 `field:"id"` // ID
Name string `field:"name"` // 选项名
Values dbs.JSON `field:"values"` // 选项值
CreatedAt uint64 `field:"createdAt"` // 创建时间
}
type NSQuestionOptionOperator struct {

View File

@@ -13,17 +13,17 @@ func TestNSRecord_DecodeRouteIds(t *testing.T) {
}
{
record := &NSRecord{RouteIds: "[]"}
record := &NSRecord{RouteIds: []byte("[]")}
t.Log(record.DecodeRouteIds())
}
{
record := &NSRecord{RouteIds: "[1, 2, 3]"}
record := &NSRecord{RouteIds: []byte("[1, 2, 3]")}
t.Log(record.DecodeRouteIds())
}
{
record := &NSRecord{RouteIds: `["id:1", "id:2", "isp:liantong"]`}
record := &NSRecord{RouteIds: []byte(`["id:1", "id:2", "isp:liantong"]`)}
t.Log(record.DecodeRouteIds())
}
}

View File

@@ -1,20 +1,22 @@
package nameservers
import "github.com/iwind/TeaGo/dbs"
// NSRecord DNS记录
type NSRecord struct {
Id uint64 `field:"id"` // ID
DomainId uint32 `field:"domainId"` // 域名ID
IsOn uint8 `field:"isOn"` // 是否启用
Description string `field:"description"` // 备注
Name string `field:"name"` // 记录名
Type string `field:"type"` // 类型
Value string `field:"value"` // 值
Ttl uint32 `field:"ttl"` // TTL
Weight uint32 `field:"weight"` // 权重
RouteIds string `field:"routeIds"` // 线路
CreatedAt uint64 `field:"createdAt"` // 创建时间
Version uint64 `field:"version"` //
State uint8 `field:"state"` // 状态
Id uint64 `field:"id"` // ID
DomainId uint32 `field:"domainId"` // 域名ID
IsOn bool `field:"isOn"` // 是否启用
Description string `field:"description"` // 备注
Name string `field:"name"` // 记录名
Type string `field:"type"` // 类型
Value string `field:"value"` // 值
Ttl uint32 `field:"ttl"` // TTL
Weight uint32 `field:"weight"` // 权重
RouteIds dbs.JSON `field:"routeIds"` // 线路
CreatedAt uint64 `field:"createdAt"` // 创建时间
Version uint64 `field:"version"` //
State uint8 `field:"state"` // 状态
}
type NSRecordOperator struct {

View File

@@ -8,11 +8,11 @@ import (
func (this *NSRecord) DecodeRouteIds() []string {
var routeIds = []string{}
if len(this.RouteIds) > 0 {
err := json.Unmarshal([]byte(this.RouteIds), &routeIds)
err := json.Unmarshal(this.RouteIds, &routeIds)
if err != nil {
// 检查是否有旧的数据
var oldRouteIds = []int64{}
err = json.Unmarshal([]byte(this.RouteIds), &oldRouteIds)
err = json.Unmarshal(this.RouteIds, &oldRouteIds)
if err != nil {
return []string{}
}

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