Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84483dce61 | ||
|
|
a4eb7a47f3 | ||
|
|
20c84d7fe5 | ||
|
|
9d5acd2b36 | ||
|
|
7508f6b92b | ||
|
|
379030fe71 | ||
|
|
10027eea20 | ||
|
|
69f25a176b | ||
|
|
ac19f06b6c | ||
|
|
87a81f59c7 | ||
|
|
7389e5e54b | ||
|
|
e6792b8188 | ||
|
|
a037546cfa | ||
|
|
8efaacf1ef | ||
|
|
a38dd1cef8 | ||
|
|
77521112d0 | ||
|
|
4f9a5d238c | ||
|
|
d5fb39ed50 | ||
|
|
58a84083ae | ||
|
|
9f564a4739 | ||
|
|
c20accbf58 | ||
|
|
3f21b3148e | ||
|
|
74e909a501 | ||
|
|
4150ee1b47 | ||
|
|
df04de2151 | ||
|
|
4dc5d9aa7e | ||
|
|
0ef7e6ccd8 | ||
|
|
ed2b831e5a | ||
|
|
5d392ecd43 | ||
|
|
ea147d7506 | ||
|
|
b45136c2c8 | ||
|
|
530e1513ec | ||
|
|
6c60677b72 | ||
|
|
a1bec5e578 | ||
|
|
9dece058d9 | ||
|
|
89df6ae6bf | ||
|
|
85b6e6428c | ||
|
|
0df204a1df | ||
|
|
ecef94b700 | ||
|
|
a493bbb280 | ||
|
|
eee902abec | ||
|
|
2aceb4fb4d | ||
|
|
c1bbcc8dab | ||
|
|
262f8a5594 | ||
|
|
a85b49a377 | ||
|
|
75e353db0e | ||
|
|
ccbb14836e | ||
|
|
7fbc61aa21 | ||
|
|
8b804cb500 | ||
|
|
3ddb95731a | ||
|
|
beeb46ab7f | ||
|
|
a65255e4e5 | ||
|
|
b7768ea0c0 |
@@ -12,5 +12,5 @@ dbs:
|
||||
|
||||
|
||||
fields:
|
||||
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified" ]
|
||||
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified", "http2Enabled", "http3Enabled" ]
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
unzip := helpers.NewUnzip(zipPath, targetPath)
|
||||
var unzip = helpers.NewUnzip(zipPath, targetPath)
|
||||
err := unzip.Run()
|
||||
if err != nil {
|
||||
stderr("ERROR: " + err.Error())
|
||||
|
||||
13
go.mod
13
go.mod
@@ -10,25 +10,26 @@ require (
|
||||
github.com/andybalholm/brotli v1.0.4
|
||||
github.com/cespare/xxhash v1.1.0
|
||||
github.com/cespare/xxhash/v2 v2.1.1
|
||||
github.com/go-acme/lego/v4 v4.9.0
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/go-acme/lego/v4 v4.10.2
|
||||
github.com/go-sql-driver/mysql v1.7.0
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||
github.com/iwind/TeaGo v0.0.0-20230304012706-c1f4a4e27470
|
||||
github.com/iwind/TeaGo v0.0.0-20230704135818-4a5646ab1f5b
|
||||
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/mozillazg/go-pinyin v0.18.0
|
||||
github.com/pkg/sftp v1.12.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
github.com/smartwalle/alipay/v3 v3.1.7
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/crypto v0.5.0
|
||||
golang.org/x/net v0.8.0
|
||||
golang.org/x/sys v0.6.0
|
||||
golang.org/x/sys v0.8.0
|
||||
google.golang.org/grpc v1.45.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
@@ -40,6 +41,8 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/smartwalle/crypto4go v1.0.2 // indirect
|
||||
github.com/tdewolff/minify/v2 v2.12.7 // indirect
|
||||
github.com/tdewolff/parse/v2 v2.6.6 // indirect
|
||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
|
||||
32
go.sum
32
go.sum
@@ -12,13 +12,14 @@ github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
|
||||
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
@@ -30,6 +31,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200624174652-8d2f3be8b2d9/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -38,6 +41,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
@@ -79,8 +84,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20230304012706-c1f4a4e27470 h1:TuRxvKRv9PxKVijWOkUnZm5TeanQqWGUJyPx9u6cra4=
|
||||
github.com/iwind/TeaGo v0.0.0-20230304012706-c1f4a4e27470/go.mod h1:fi/Pq+/5m2HZoseM+39dMF57ANXRt6w4PkGu3NXPc5s=
|
||||
github.com/iwind/TeaGo v0.0.0-20230704135818-4a5646ab1f5b h1:yYUaxnc04uzfr7C9HBN52ZZvcQomND+C5aZTpjOUYFI=
|
||||
github.com/iwind/TeaGo v0.0.0-20230704135818-4a5646ab1f5b/go.mod h1:fi/Pq+/5m2HZoseM+39dMF57ANXRt6w4PkGu3NXPc5s=
|
||||
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62 h1:HJH6RDheAY156DnIfJSD/bEvqyXzsZuE2gzs8PuUjoo=
|
||||
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
@@ -96,10 +101,11 @@ github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -140,12 +146,20 @@ github.com/smartwalle/crypto4go v1.0.2 h1:9DUEOOsPhmp00438L4oBdcL8EZG1zumecft5bW
|
||||
github.com/smartwalle/crypto4go v1.0.2/go.mod h1:LQ7vCZIb7BE5+MuMtJBuO8ORkkQ01m4DXDBWPzLbkMY=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/tdewolff/minify/v2 v2.12.7 h1:pBzz2tAfz5VghOXiQIsSta6srhmTeinQPjRDHWoumCA=
|
||||
github.com/tdewolff/minify/v2 v2.12.7/go.mod h1:ZRKTheiOGyLSK8hOZWWv+YoJAECzDivNgAlVYDHp/Ws=
|
||||
github.com/tdewolff/parse/v2 v2.6.6 h1:Yld+0CrKUJaCV78DL1G2nk3C9lKrxyRTux5aaK/AkDo=
|
||||
github.com/tdewolff/parse/v2 v2.6.6/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
|
||||
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0=
|
||||
github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
@@ -162,8 +176,8 @@ golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
@@ -222,8 +236,10 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "1.1.0"
|
||||
Version = "1.2.2"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,7 +18,7 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "1.1.0"
|
||||
NodeVersion = "1.2.2"
|
||||
|
||||
// SQLVersion SQL版本号
|
||||
SQLVersion = "11"
|
||||
|
||||
@@ -2,6 +2,22 @@ package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
AdminField_Id dbs.FieldName = "id" // ID
|
||||
AdminField_IsOn dbs.FieldName = "isOn" // 是否启用
|
||||
AdminField_Username dbs.FieldName = "username" // 用户名
|
||||
AdminField_Password dbs.FieldName = "password" // 密码
|
||||
AdminField_Fullname dbs.FieldName = "fullname" // 全名
|
||||
AdminField_IsSuper dbs.FieldName = "isSuper" // 是否为超级管理员
|
||||
AdminField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
|
||||
AdminField_UpdatedAt dbs.FieldName = "updatedAt" // 修改时间
|
||||
AdminField_State dbs.FieldName = "state" // 状态
|
||||
AdminField_Modules dbs.FieldName = "modules" // 允许的模块
|
||||
AdminField_CanLogin dbs.FieldName = "canLogin" // 是否可以登录
|
||||
AdminField_Theme dbs.FieldName = "theme" // 模板设置
|
||||
AdminField_Lang dbs.FieldName = "lang" // 语言代号
|
||||
)
|
||||
|
||||
// Admin 管理员
|
||||
type Admin struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
@@ -16,6 +32,7 @@ type Admin struct {
|
||||
Modules dbs.JSON `field:"modules"` // 允许的模块
|
||||
CanLogin bool `field:"canLogin"` // 是否可以登录
|
||||
Theme string `field:"theme"` // 模板设置
|
||||
Lang string `field:"lang"` // 语言代号
|
||||
}
|
||||
|
||||
type AdminOperator struct {
|
||||
@@ -31,6 +48,7 @@ type AdminOperator struct {
|
||||
Modules any // 允许的模块
|
||||
CanLogin any // 是否可以登录
|
||||
Theme any // 模板设置
|
||||
Lang any // 语言代号
|
||||
}
|
||||
|
||||
func NewAdminOperator() *AdminOperator {
|
||||
|
||||
@@ -335,6 +335,7 @@ func (this *APINodeDAO) UpdateAPINodeStatus(tx *dbs.Tx, apiNodeId int64, statusJ
|
||||
func (this *APINodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
Param("version", utils.VersionToLong(version)).
|
||||
|
||||
@@ -210,6 +210,7 @@ func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeSta
|
||||
func (this *AuthorityNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(AuthorityNodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
Param("version", utils.VersionToLong(version)).
|
||||
|
||||
@@ -155,6 +155,12 @@ func (this *DNSTaskDAO) DeleteDNSTask(tx *dbs.Tx, taskId int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteAllDNSTasks 删除所有任务
|
||||
func (this *DNSTaskDAO) DeleteAllDNSTasks(tx *dbs.Tx) error {
|
||||
return this.Query(tx).
|
||||
DeleteQuickly()
|
||||
}
|
||||
|
||||
// UpdateDNSTaskError 设置任务错误
|
||||
func (this *DNSTaskDAO) UpdateDNSTaskError(tx *dbs.Tx, taskId int64, err string) error {
|
||||
if taskId <= 0 {
|
||||
@@ -195,6 +201,27 @@ func (this *DNSTaskDAO) UpdateDNSTaskDone(tx *dbs.Tx, taskId int64, taskVersion
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// GenerateVersion 生成最新的版本号
|
||||
func (this *DNSTaskDAO) GenerateVersion() int64 {
|
||||
return time.Now().UnixNano()
|
||||
}
|
||||
|
||||
// UpdateClusterDNSTasksDone 设置所有集群任务完成
|
||||
func (this *DNSTaskDAO) UpdateClusterDNSTasksDone(tx *dbs.Tx, clusterId int64, maxVersion int64) error {
|
||||
if clusterId <= 0 || maxVersion <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("isOk", false).
|
||||
Lte("version", maxVersion).
|
||||
Set("isDone", true).
|
||||
Set("isOk", true).
|
||||
Set("error", "").
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// DeleteDNSTasksWithClusterId 删除集群相关任务
|
||||
func (this *DNSTaskDAO) DeleteDNSTasksWithClusterId(tx *dbs.Tx, clusterId int64) error {
|
||||
if clusterId <= 0 {
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
package dns
|
||||
package dns_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDNSTaskDAO_CreateDNSTask(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
err := SharedDNSTaskDAO.CreateDNSTask(nil, 1, 2, 3, 0, "cdn", "taskType")
|
||||
err := dns.SharedDNSTaskDAO.CreateDNSTask(nil, 1, 2, 3, 0, "cdn", "taskType")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestDNSTaskDAO_UpdateClusterDNSTasksDone(t *testing.T) {
|
||||
var dao = dns.NewDNSTaskDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateClusterDNSTasksDone(tx, 46, time.Now().UnixNano())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func (this *HTTPCachePolicyDAO) FindAllEnabledCachePolicies(tx *dbs.Tx) (result
|
||||
}
|
||||
|
||||
// CreateCachePolicy 创建缓存策略
|
||||
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) (int64, error) {
|
||||
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) (int64, error) {
|
||||
var op = NewHTTPCachePolicyOperator()
|
||||
op.State = HTTPCachePolicyStateEnabled
|
||||
op.IsOn = isOn
|
||||
@@ -105,7 +105,6 @@ func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name st
|
||||
if len(capacityJSON) > 0 {
|
||||
op.Capacity = capacityJSON
|
||||
}
|
||||
op.MaxKeys = maxKeys
|
||||
if len(maxSizeJSON) > 0 {
|
||||
op.MaxSize = maxSizeJSON
|
||||
}
|
||||
@@ -184,7 +183,7 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
||||
return 0, err
|
||||
}
|
||||
|
||||
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
|
||||
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -192,7 +191,7 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
||||
}
|
||||
|
||||
// UpdateCachePolicy 修改缓存策略
|
||||
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) error {
|
||||
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -205,7 +204,6 @@ func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, is
|
||||
if len(capacityJSON) > 0 {
|
||||
op.Capacity = capacityJSON
|
||||
}
|
||||
op.MaxKeys = maxKeys
|
||||
if len(maxSizeJSON) > 0 {
|
||||
op.MaxSize = maxSizeJSON
|
||||
}
|
||||
@@ -256,8 +254,6 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
config.Capacity = capacityConfig
|
||||
}
|
||||
|
||||
config.MaxKeys = types.Int64(policy.MaxKeys)
|
||||
|
||||
// max size
|
||||
if IsNotNull(policy.MaxSize) {
|
||||
maxSizeConfig := &shared.SizeCapacity{}
|
||||
|
||||
@@ -33,7 +33,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedHTTPCacheTaskDAO.Clean(nil, 30) // 只保留N天
|
||||
err := SharedHTTPCacheTaskDAO.CleanDefaultDays(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTPCacheTaskDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -228,8 +228,8 @@ func (this *HTTPCacheTaskDAO) CheckUserTask(tx *dbs.Tx, userId int64, taskId int
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clean 清理以往的任务
|
||||
func (this *HTTPCacheTaskDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理N天以前的任务
|
||||
func (this *HTTPCacheTaskDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
if days <= 0 {
|
||||
days = 30
|
||||
}
|
||||
@@ -248,6 +248,23 @@ func (this *HTTPCacheTaskDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// CleanDefaultDays 清除任务
|
||||
func (this *HTTPCacheTaskDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.HTTPCacheTask.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.HTTPCacheTask.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 30
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
// NotifyChange 发送通知
|
||||
func (this *HTTPCacheTaskDAO) NotifyChange(tx *dbs.Tx, taskId int64) error {
|
||||
// TODO
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
func TestHTTPCacheTaskDAO_Clean(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
err := models.SharedHTTPCacheTaskDAO.Clean(nil, 30)
|
||||
err := models.SharedHTTPCacheTaskDAO.CleanDays(nil, 30)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64
|
||||
op.Outbound = outboundJSON
|
||||
}
|
||||
|
||||
if userId <= 0 && serverGroupId <=0 && serverId <= 0 {
|
||||
if userId <= 0 && serverGroupId <= 0 && serverId <= 0 {
|
||||
// synFlood
|
||||
var synFloodConfig = firewallconfigs.DefaultSYNFloodConfig()
|
||||
synFloodJSON, err := json.Marshal(synFloodConfig)
|
||||
@@ -611,6 +611,10 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyServerId(tx *dbs.Tx, poli
|
||||
|
||||
// FindFirewallPolicyIdsWithServerId 查找服务独立关联的策略IDs
|
||||
func (this *HTTPFirewallPolicyDAO) FindFirewallPolicyIdsWithServerId(tx *dbs.Tx, serverId int64) ([]int64, error) {
|
||||
if serverId <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var result = []int64{}
|
||||
ones, err := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
|
||||
@@ -124,8 +124,9 @@ func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int
|
||||
}
|
||||
|
||||
// CreateRewriteRule 创建规则
|
||||
func (this *HTTPRewriteRuleDAO) CreateRewriteRule(tx *dbs.Tx, pattern string, replace string, mode string, redirectStatus int, isBreak bool, proxyHost string, withQuery bool, isOn bool, condsJSON []byte) (int64, error) {
|
||||
func (this *HTTPRewriteRuleDAO) CreateRewriteRule(tx *dbs.Tx, userId int64, pattern string, replace string, mode string, redirectStatus int, isBreak bool, proxyHost string, withQuery bool, isOn bool, condsJSON []byte) (int64, error) {
|
||||
var op = NewHTTPRewriteRuleOperator()
|
||||
op.UserId = userId
|
||||
op.State = HTTPRewriteRuleStateEnabled
|
||||
op.IsOn = isOn
|
||||
|
||||
@@ -172,6 +173,34 @@ func (this *HTTPRewriteRuleDAO) UpdateRewriteRule(tx *dbs.Tx, rewriteRuleId int6
|
||||
return this.NotifyUpdate(tx, rewriteRuleId)
|
||||
}
|
||||
|
||||
func (this *HTTPRewriteRuleDAO) CheckUserRewriteRule(tx *dbs.Tx, userId int64, rewriteRuleId int64) error {
|
||||
if rewriteRuleId <= 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
exists, err := this.Query(tx).
|
||||
Pk(rewriteRuleId).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithRewriteRuleId(tx, rewriteRuleId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if webId <= 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
return SharedHTTPWebDAO.CheckUserWeb(tx, userId, webId)
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPRewriteRuleDAO) NotifyUpdate(tx *dbs.Tx, rewriteRuleId int64) error {
|
||||
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithRewriteRuleId(tx, rewriteRuleId)
|
||||
|
||||
@@ -151,6 +151,18 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, isLocationOrGr
|
||||
}
|
||||
}
|
||||
|
||||
// Optimization
|
||||
if IsNotNull(web.Optimization) {
|
||||
var optimizationConfig = serverconfigs.NewHTTPPageOptimizationConfig()
|
||||
err = json.Unmarshal(web.Optimization, optimizationConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if this.shouldCompose(isLocationOrGroup, forNode, optimizationConfig.IsPrior, true) {
|
||||
config.Optimization = optimizationConfig
|
||||
}
|
||||
}
|
||||
|
||||
// charset
|
||||
if IsNotNull(web.Charset) {
|
||||
var charsetConfig = &serverconfigs.HTTPCharsetConfig{}
|
||||
@@ -550,7 +562,20 @@ func (this *HTTPWebDAO) CreateWeb(tx *dbs.Tx, adminId int64, userId int64, rootJ
|
||||
if len(rootJSON) > 0 {
|
||||
op.Root = JSONBytes(rootJSON)
|
||||
}
|
||||
err := this.Save(tx, op)
|
||||
|
||||
// 设置默认的remote-addr
|
||||
// set default remote-addr config
|
||||
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{
|
||||
IsOn: true,
|
||||
Value: "${rawRemoteAddr}",
|
||||
}
|
||||
remoteAddrConfigJSON, err := json.Marshal(remoteAddrConfig)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.RemoteAddr = remoteAddrConfigJSON
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -574,14 +599,42 @@ func (this *HTTPWebDAO) UpdateWeb(tx *dbs.Tx, webId int64, rootJSON []byte) erro
|
||||
}
|
||||
|
||||
// UpdateWebCompression 修改压缩配置
|
||||
func (this *HTTPWebDAO) UpdateWebCompression(tx *dbs.Tx, webId int64, compressionConfig []byte) error {
|
||||
func (this *HTTPWebDAO) UpdateWebCompression(tx *dbs.Tx, webId int64, compressionConfig *serverconfigs.HTTPCompressionConfig) error {
|
||||
if webId <= 0 {
|
||||
return errors.New("invalid webId")
|
||||
}
|
||||
|
||||
compressionJSON, err := json.Marshal(compressionConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var op = NewHTTPWebOperator()
|
||||
op.Id = webId
|
||||
op.Compression = JSONBytes(compressionConfig)
|
||||
err := this.Save(tx, op)
|
||||
op.Compression = compressionJSON
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, webId)
|
||||
}
|
||||
|
||||
// UpdateWebOptimization 修改页面优化配置
|
||||
func (this *HTTPWebDAO) UpdateWebOptimization(tx *dbs.Tx, webId int64, optimizationConfig *serverconfigs.HTTPPageOptimizationConfig) error {
|
||||
if webId <= 0 {
|
||||
return errors.New("invalid webId")
|
||||
}
|
||||
|
||||
optimizationJSON, err := json.Marshal(optimizationConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var op = NewHTTPWebOperator()
|
||||
op.Id = webId
|
||||
op.Optimization = optimizationJSON
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,47 @@ package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
HTTPWebField_Id dbs.FieldName = "id" // ID
|
||||
HTTPWebField_IsOn dbs.FieldName = "isOn" // 是否启用
|
||||
HTTPWebField_TemplateId dbs.FieldName = "templateId" // 模版ID
|
||||
HTTPWebField_AdminId dbs.FieldName = "adminId" // 管理员ID
|
||||
HTTPWebField_UserId dbs.FieldName = "userId" // 用户ID
|
||||
HTTPWebField_State dbs.FieldName = "state" // 状态
|
||||
HTTPWebField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
|
||||
HTTPWebField_Root dbs.FieldName = "root" // 根目录
|
||||
HTTPWebField_Charset dbs.FieldName = "charset" // 字符集
|
||||
HTTPWebField_Shutdown dbs.FieldName = "shutdown" // 临时关闭页面配置
|
||||
HTTPWebField_Pages dbs.FieldName = "pages" // 特殊页面
|
||||
HTTPWebField_RedirectToHttps dbs.FieldName = "redirectToHttps" // 跳转到HTTPS设置
|
||||
HTTPWebField_Indexes dbs.FieldName = "indexes" // 首页文件列表
|
||||
HTTPWebField_MaxRequestBodySize dbs.FieldName = "maxRequestBodySize" // 最大允许的请求内容尺寸
|
||||
HTTPWebField_RequestHeader dbs.FieldName = "requestHeader" // 请求Header配置
|
||||
HTTPWebField_ResponseHeader dbs.FieldName = "responseHeader" // 响应Header配置
|
||||
HTTPWebField_AccessLog dbs.FieldName = "accessLog" // 访问日志配置
|
||||
HTTPWebField_Stat dbs.FieldName = "stat" // 统计配置
|
||||
HTTPWebField_Gzip dbs.FieldName = "gzip" // Gzip配置(v0.3.2弃用)
|
||||
HTTPWebField_Compression dbs.FieldName = "compression" // 压缩配置
|
||||
HTTPWebField_Cache dbs.FieldName = "cache" // 缓存配置
|
||||
HTTPWebField_Firewall dbs.FieldName = "firewall" // 防火墙设置
|
||||
HTTPWebField_Locations dbs.FieldName = "locations" // 路由规则配置
|
||||
HTTPWebField_Websocket dbs.FieldName = "websocket" // Websocket设置
|
||||
HTTPWebField_RewriteRules dbs.FieldName = "rewriteRules" // 重写规则配置
|
||||
HTTPWebField_HostRedirects dbs.FieldName = "hostRedirects" // 域名跳转
|
||||
HTTPWebField_Fastcgi dbs.FieldName = "fastcgi" // Fastcgi配置
|
||||
HTTPWebField_Auth dbs.FieldName = "auth" // 认证策略配置
|
||||
HTTPWebField_Webp dbs.FieldName = "webp" // WebP配置
|
||||
HTTPWebField_RemoteAddr dbs.FieldName = "remoteAddr" // 客户端IP配置
|
||||
HTTPWebField_MergeSlashes dbs.FieldName = "mergeSlashes" // 是否合并路径中的斜杠
|
||||
HTTPWebField_RequestLimit dbs.FieldName = "requestLimit" // 请求限制
|
||||
HTTPWebField_RequestScripts dbs.FieldName = "requestScripts" // 请求脚本
|
||||
HTTPWebField_Uam dbs.FieldName = "uam" // UAM设置
|
||||
HTTPWebField_Cc dbs.FieldName = "cc" // CC设置
|
||||
HTTPWebField_Referers dbs.FieldName = "referers" // 防盗链设置
|
||||
HTTPWebField_UserAgent dbs.FieldName = "userAgent" // UserAgent设置
|
||||
HTTPWebField_Optimization dbs.FieldName = "optimization" // 页面优化配置
|
||||
)
|
||||
|
||||
// HTTPWeb HTTP Web
|
||||
type HTTPWeb struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
@@ -41,6 +82,7 @@ type HTTPWeb struct {
|
||||
Cc dbs.JSON `field:"cc"` // CC设置
|
||||
Referers dbs.JSON `field:"referers"` // 防盗链设置
|
||||
UserAgent dbs.JSON `field:"userAgent"` // UserAgent设置
|
||||
Optimization dbs.JSON `field:"optimization"` // 页面优化配置
|
||||
}
|
||||
|
||||
type HTTPWebOperator struct {
|
||||
@@ -81,6 +123,7 @@ type HTTPWebOperator struct {
|
||||
Cc any // CC设置
|
||||
Referers any // 防盗链设置
|
||||
UserAgent any // UserAgent设置
|
||||
Optimization any // 页面优化配置
|
||||
}
|
||||
|
||||
func NewHTTPWebOperator() *HTTPWebOperator {
|
||||
|
||||
@@ -339,7 +339,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
|
||||
var countries = []*iplibrary.Country{}
|
||||
for _, country := range dbCountries {
|
||||
countries = append(countries, &iplibrary.Country{
|
||||
Id: types.Uint16(country.Id),
|
||||
Id: types.Uint16(country.ValueId),
|
||||
Name: country.DisplayName(),
|
||||
Codes: country.AllCodes(),
|
||||
})
|
||||
@@ -354,7 +354,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
|
||||
var provinces = []*iplibrary.Province{}
|
||||
for _, province := range dbProvinces {
|
||||
provinces = append(provinces, &iplibrary.Province{
|
||||
Id: types.Uint16(province.Id),
|
||||
Id: types.Uint16(province.ValueId),
|
||||
Name: province.DisplayName(),
|
||||
Codes: province.AllCodes(),
|
||||
})
|
||||
@@ -369,7 +369,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
|
||||
var cities = []*iplibrary.City{}
|
||||
for _, city := range dbCities {
|
||||
cities = append(cities, &iplibrary.City{
|
||||
Id: city.Id,
|
||||
Id: city.ValueId,
|
||||
Name: city.DisplayName(),
|
||||
Codes: city.AllCodes(),
|
||||
})
|
||||
@@ -384,7 +384,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
|
||||
var towns = []*iplibrary.Town{}
|
||||
for _, town := range dbTowns {
|
||||
towns = append(towns, &iplibrary.Town{
|
||||
Id: town.Id,
|
||||
Id: town.ValueId,
|
||||
Name: town.DisplayName(),
|
||||
Codes: town.AllCodes(),
|
||||
})
|
||||
@@ -399,7 +399,7 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
|
||||
var providers = []*iplibrary.Provider{}
|
||||
for _, provider := range dbProviders {
|
||||
providers = append(providers, &iplibrary.Provider{
|
||||
Id: types.Uint16(provider.Id),
|
||||
Id: types.Uint16(provider.ValueId),
|
||||
Name: provider.DisplayName(),
|
||||
Codes: provider.AllCodes(),
|
||||
})
|
||||
@@ -440,35 +440,35 @@ func (this *IPLibraryFileDAO) GenerateIPLibrary(tx *dbs.Tx, libraryFileId int64)
|
||||
var countryMap = map[string]int64{} // countryName => countryId
|
||||
for _, country := range dbCountries {
|
||||
for _, code := range country.AllCodes() {
|
||||
countryMap[code] = int64(country.Id)
|
||||
countryMap[code] = int64(country.ValueId)
|
||||
}
|
||||
}
|
||||
|
||||
var provinceMap = map[string]int64{} // countryId_provinceName => provinceId
|
||||
for _, province := range dbProvinces {
|
||||
for _, code := range province.AllCodes() {
|
||||
provinceMap[types.String(province.CountryId)+"_"+code] = int64(province.Id)
|
||||
provinceMap[types.String(province.CountryId)+"_"+code] = int64(province.ValueId)
|
||||
}
|
||||
}
|
||||
|
||||
var cityMap = map[string]int64{} // provinceId_cityName => cityId
|
||||
for _, city := range dbCities {
|
||||
for _, code := range city.AllCodes() {
|
||||
cityMap[types.String(city.ProvinceId)+"_"+code] = int64(city.Id)
|
||||
cityMap[types.String(city.ProvinceId)+"_"+code] = int64(city.ValueId)
|
||||
}
|
||||
}
|
||||
|
||||
var townMap = map[string]int64{} // cityId_townName => townId
|
||||
for _, town := range dbTowns {
|
||||
for _, code := range town.AllCodes() {
|
||||
townMap[types.String(town.CityId)+"_"+code] = int64(town.Id)
|
||||
townMap[types.String(town.CityId)+"_"+code] = int64(town.ValueId)
|
||||
}
|
||||
}
|
||||
|
||||
var providerMap = map[string]int64{} // providerName => providerId
|
||||
for _, provider := range dbProviders {
|
||||
for _, code := range provider.AllCodes() {
|
||||
providerMap[code] = int64(provider.Id)
|
||||
providerMap[code] = int64(provider.ValueId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -36,7 +38,7 @@ func init() {
|
||||
}
|
||||
|
||||
// CreateLog 创建管理员日志
|
||||
func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level string, description string, action string, ip string) error {
|
||||
func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level string, description string, action string, ip string, langMessageCode langs.MessageCode, langMessageArgs []any) error {
|
||||
var op = NewLogOperator()
|
||||
op.Level = level
|
||||
op.Description = utils.LimitString(description, 1000)
|
||||
@@ -53,6 +55,16 @@ func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level
|
||||
op.ProviderId = adminId
|
||||
}
|
||||
|
||||
// i18n
|
||||
op.LangMessageCode = langMessageCode
|
||||
if len(langMessageArgs) > 0 {
|
||||
langMessageArgsJSON, err := json.Marshal(langMessageArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.LangMessageArgs = langMessageArgsJSON
|
||||
}
|
||||
|
||||
op.Day = timeutil.Format("Ymd")
|
||||
op.Type = LogTypeAdmin
|
||||
err := this.Save(tx, op)
|
||||
|
||||
@@ -1,34 +1,60 @@
|
||||
package models
|
||||
|
||||
// 操作日志
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
LogField_Id dbs.FieldName = "id" // ID
|
||||
LogField_Level dbs.FieldName = "level" // 级别
|
||||
LogField_Description dbs.FieldName = "description" // 描述
|
||||
LogField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
|
||||
LogField_Action dbs.FieldName = "action" // 动作
|
||||
LogField_UserId dbs.FieldName = "userId" // 用户ID
|
||||
LogField_AdminId dbs.FieldName = "adminId" // 管理员ID
|
||||
LogField_ProviderId dbs.FieldName = "providerId" // 供应商ID
|
||||
LogField_Ip dbs.FieldName = "ip" // IP地址
|
||||
LogField_Type dbs.FieldName = "type" // 类型:admin, user
|
||||
LogField_Day dbs.FieldName = "day" // 日期
|
||||
LogField_BillId dbs.FieldName = "billId" // 账单ID
|
||||
LogField_LangMessageCode dbs.FieldName = "langMessageCode" // 多语言消息代号
|
||||
LogField_LangMessageArgs dbs.FieldName = "langMessageArgs" // 多语言参数
|
||||
LogField_Params dbs.FieldName = "params" // 关联对象参数
|
||||
)
|
||||
|
||||
// Log 操作日志
|
||||
type Log struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Level string `field:"level"` // 级别
|
||||
Description string `field:"description"` // 描述
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Action string `field:"action"` // 动作
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
ProviderId uint32 `field:"providerId"` // 供应商ID
|
||||
Ip string `field:"ip"` // IP地址
|
||||
Type string `field:"type"` // 类型:admin, user
|
||||
Day string `field:"day"` // 日期
|
||||
BillId uint32 `field:"billId"` // 账单ID
|
||||
Id uint32 `field:"id"` // ID
|
||||
Level string `field:"level"` // 级别
|
||||
Description string `field:"description"` // 描述
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Action string `field:"action"` // 动作
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
ProviderId uint32 `field:"providerId"` // 供应商ID
|
||||
Ip string `field:"ip"` // IP地址
|
||||
Type string `field:"type"` // 类型:admin, user
|
||||
Day string `field:"day"` // 日期
|
||||
BillId uint32 `field:"billId"` // 账单ID
|
||||
LangMessageCode string `field:"langMessageCode"` // 多语言消息代号
|
||||
LangMessageArgs dbs.JSON `field:"langMessageArgs"` // 多语言参数
|
||||
Params dbs.JSON `field:"params"` // 关联对象参数
|
||||
}
|
||||
|
||||
type LogOperator struct {
|
||||
Id interface{} // ID
|
||||
Level interface{} // 级别
|
||||
Description interface{} // 描述
|
||||
CreatedAt interface{} // 创建时间
|
||||
Action interface{} // 动作
|
||||
UserId interface{} // 用户ID
|
||||
AdminId interface{} // 管理员ID
|
||||
ProviderId interface{} // 供应商ID
|
||||
Ip interface{} // IP地址
|
||||
Type interface{} // 类型:admin, user
|
||||
Day interface{} // 日期
|
||||
BillId interface{} // 账单ID
|
||||
Id any // ID
|
||||
Level any // 级别
|
||||
Description any // 描述
|
||||
CreatedAt any // 创建时间
|
||||
Action any // 动作
|
||||
UserId any // 用户ID
|
||||
AdminId any // 管理员ID
|
||||
ProviderId any // 供应商ID
|
||||
Ip any // IP地址
|
||||
Type any // 类型:admin, user
|
||||
Day any // 日期
|
||||
BillId any // 账单ID
|
||||
LangMessageCode any // 多语言消息代号
|
||||
LangMessageArgs any // 多语言参数
|
||||
Params any // 关联对象参数
|
||||
}
|
||||
|
||||
func NewLogOperator() *LogOperator {
|
||||
|
||||
@@ -207,6 +207,7 @@ func (this *MonitorNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSO
|
||||
func (this *MonitorNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(MonitorNodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
Param("version", utils.VersionToLong(version)).
|
||||
|
||||
@@ -100,6 +100,7 @@ func (this *NodeClusterDAO) FindNodeClusterName(tx *dbs.Tx, clusterId int64) (st
|
||||
// FindAllEnableClusters 查找所有可用的集群
|
||||
func (this *NodeClusterDAO) FindAllEnableClusters(tx *dbs.Tx) (result []*NodeCluster, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Result(NodeClusterField_Id, NodeClusterField_Name, NodeClusterField_IsOn, NodeClusterField_HealthCheck, NodeClusterField_AutoRemoteStart, NodeClusterField_AutoRegister, NodeClusterField_CreatedAt, NodeClusterField_UniqueId, NodeClusterField_Secret).
|
||||
State(NodeClusterStateEnabled).
|
||||
Slice(&result).
|
||||
Desc("isPinned").
|
||||
@@ -175,7 +176,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
|
||||
// 全局服务配置
|
||||
if globalServerConfig == nil {
|
||||
globalServerConfig = serverconfigs.DefaultGlobalServerConfig()
|
||||
globalServerConfig = serverconfigs.NewGlobalServerConfig()
|
||||
}
|
||||
globalServerConfigJSON, err := json.Marshal(globalServerConfig)
|
||||
if err != nil {
|
||||
@@ -262,19 +263,40 @@ func (this *NodeClusterDAO) CountAllEnabledClusters(tx *dbs.Tx, keyword string)
|
||||
|
||||
// ListEnabledClusters 列出单页集群
|
||||
func (this *NodeClusterDAO) ListEnabledClusters(tx *dbs.Tx, keyword string, offset, size int64) (result []*NodeCluster, err error) {
|
||||
query := this.Query(tx).
|
||||
var query = this.Query(tx).
|
||||
State(NodeClusterStateEnabled)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword OR dnsName like :keyword OR (dnsDomainId > 0 AND dnsDomainId IN (SELECT id FROM "+dns.SharedDNSDomainDAO.Table+" WHERE name LIKE :keyword AND state=1)))").
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
_, err = query.
|
||||
Result(
|
||||
NodeClusterField_Id,
|
||||
NodeClusterField_Name,
|
||||
NodeClusterField_IsOn,
|
||||
NodeClusterField_IsPinned,
|
||||
NodeClusterField_InstallDir,
|
||||
NodeClusterField_HttpFirewallPolicyId,
|
||||
NodeClusterField_AdminId,
|
||||
NodeClusterField_IsOn,
|
||||
NodeClusterField_IsAD,
|
||||
NodeClusterField_UserId,
|
||||
NodeClusterField_DnsName,
|
||||
NodeClusterField_DnsDomainId,
|
||||
NodeClusterField_Dns,
|
||||
NodeClusterField_CreatedAt,
|
||||
NodeClusterField_UniqueId,
|
||||
NodeClusterField_Secret,
|
||||
NodeClusterField_GrantId,
|
||||
NodeClusterField_TimeZone,
|
||||
).
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Desc("isPinned").
|
||||
DescPk().
|
||||
FindAll()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -996,7 +1018,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
||||
cluster, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
State(NodeClusterStateEnabled).
|
||||
Result("id", "name", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "cc", "httpPages", "isOn", "ddosProtection", "clock", "globalServerConfig", "autoInstallNftables").
|
||||
Result("id", "name", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "cc", "httpPages", "http3", "isOn", "ddosProtection", "clock", "globalServerConfig", "autoInstallNftables").
|
||||
Find()
|
||||
if err != nil || cluster == nil {
|
||||
return nil, err
|
||||
@@ -1113,11 +1135,12 @@ func (this *NodeClusterDAO) FindClusterUAMPolicy(tx *dbs.Tx, clusterId int64, ca
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var policy = nodeconfigs.NewUAMPolicy()
|
||||
|
||||
if IsNull(uamJSON) {
|
||||
return nodeconfigs.DefaultUAMPolicy, nil
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
var policy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(uamJSON, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1184,6 +1207,65 @@ func (this *NodeClusterDAO) FindClusterHTTPCCPolicy(tx *dbs.Tx, clusterId int64,
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
// UpdateClusterHTTP3Policy 修改HTTP3策略设置
|
||||
func (this *NodeClusterDAO) UpdateClusterHTTP3Policy(tx *dbs.Tx, clusterId int64, http3Policy *nodeconfigs.HTTP3Policy) error {
|
||||
if http3Policy == nil {
|
||||
err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Set("http3", dbs.SQL("null")).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyHTTP3Update(tx, clusterId)
|
||||
}
|
||||
|
||||
http3PolicyJSON, err := json.Marshal(http3Policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Set("http3", http3PolicyJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyHTTP3Update(tx, clusterId)
|
||||
}
|
||||
|
||||
// FindClusterHTTP3Policy 查询HTTP3策略设置
|
||||
func (this *NodeClusterDAO) FindClusterHTTP3Policy(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (*nodeconfigs.HTTP3Policy, error) {
|
||||
var cacheKey = this.Table + ":FindClusterHTTP3Policy:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*nodeconfigs.HTTP3Policy), nil
|
||||
}
|
||||
}
|
||||
|
||||
http3PolicyJSON, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("http3").
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if IsNull(http3PolicyJSON) {
|
||||
return nodeconfigs.NewHTTP3Policy(), nil
|
||||
}
|
||||
|
||||
var policy = nodeconfigs.NewHTTP3Policy()
|
||||
err = json.Unmarshal(http3PolicyJSON, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
// UpdateClusterHTTPPagesPolicy 修改自定义页面设置
|
||||
func (this *NodeClusterDAO) UpdateClusterHTTPPagesPolicy(tx *dbs.Tx, clusterId int64, httpPagesPolicy *nodeconfigs.HTTPPagesPolicy) error {
|
||||
if httpPagesPolicy == nil {
|
||||
@@ -1314,7 +1396,7 @@ func (this *NodeClusterDAO) FindClusterGlobalServerConfig(tx *dbs.Tx, clusterId
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = serverconfigs.DefaultGlobalServerConfig()
|
||||
var config = serverconfigs.NewGlobalServerConfig()
|
||||
if IsNull(configJSON) {
|
||||
return config, nil
|
||||
}
|
||||
@@ -1330,7 +1412,7 @@ func (this *NodeClusterDAO) FindClusterGlobalServerConfig(tx *dbs.Tx, clusterId
|
||||
// UpdateClusterGlobalServerConfig 修改全局服务配置
|
||||
func (this *NodeClusterDAO) UpdateClusterGlobalServerConfig(tx *dbs.Tx, clusterId int64, config *serverconfigs.GlobalServerConfig) error {
|
||||
if config == nil {
|
||||
config = serverconfigs.DefaultGlobalServerConfig()
|
||||
config = serverconfigs.NewGlobalServerConfig()
|
||||
}
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
@@ -1362,6 +1444,11 @@ func (this *NodeClusterDAO) NotifyHTTPCCUpdate(tx *dbs.Tx, clusterId int64) erro
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypeHTTPCCPolicyChanged)
|
||||
}
|
||||
|
||||
// NotifyHTTP3Update 通知HTTP3更新
|
||||
func (this *NodeClusterDAO) NotifyHTTP3Update(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypeHTTP3PolicyChanged)
|
||||
}
|
||||
|
||||
// NotifyHTTPPagesPolicyUpdate 通知HTTP Pages更新
|
||||
func (this *NodeClusterDAO) NotifyHTTPPagesPolicyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, 0, NodeTaskTypeHTTPPagesPolicyChanged)
|
||||
|
||||
@@ -2,6 +2,49 @@ package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
NodeClusterField_Id dbs.FieldName = "id" // ID
|
||||
NodeClusterField_AdminId dbs.FieldName = "adminId" // 管理员ID
|
||||
NodeClusterField_UserId dbs.FieldName = "userId" // 用户ID
|
||||
NodeClusterField_IsOn dbs.FieldName = "isOn" // 是否启用
|
||||
NodeClusterField_Name dbs.FieldName = "name" // 名称
|
||||
NodeClusterField_UseAllAPINodes dbs.FieldName = "useAllAPINodes" // 是否使用所有API节点
|
||||
NodeClusterField_ApiNodes dbs.FieldName = "apiNodes" // 使用的API节点
|
||||
NodeClusterField_InstallDir dbs.FieldName = "installDir" // 安装目录
|
||||
NodeClusterField_Order dbs.FieldName = "order" // 排序
|
||||
NodeClusterField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
|
||||
NodeClusterField_GrantId dbs.FieldName = "grantId" // 默认认证方式
|
||||
NodeClusterField_SshParams dbs.FieldName = "sshParams" // SSH默认参数
|
||||
NodeClusterField_State dbs.FieldName = "state" // 状态
|
||||
NodeClusterField_AutoRegister dbs.FieldName = "autoRegister" // 是否开启自动注册
|
||||
NodeClusterField_UniqueId dbs.FieldName = "uniqueId" // 唯一ID
|
||||
NodeClusterField_Secret dbs.FieldName = "secret" // 密钥
|
||||
NodeClusterField_HealthCheck dbs.FieldName = "healthCheck" // 健康检查
|
||||
NodeClusterField_DnsName dbs.FieldName = "dnsName" // DNS名称
|
||||
NodeClusterField_DnsDomainId dbs.FieldName = "dnsDomainId" // 域名ID
|
||||
NodeClusterField_Dns dbs.FieldName = "dns" // DNS配置
|
||||
NodeClusterField_Toa dbs.FieldName = "toa" // TOA配置
|
||||
NodeClusterField_CachePolicyId dbs.FieldName = "cachePolicyId" // 缓存策略ID
|
||||
NodeClusterField_HttpFirewallPolicyId dbs.FieldName = "httpFirewallPolicyId" // WAF策略ID
|
||||
NodeClusterField_AccessLog dbs.FieldName = "accessLog" // 访问日志设置
|
||||
NodeClusterField_SystemServices dbs.FieldName = "systemServices" // 系统服务设置
|
||||
NodeClusterField_TimeZone dbs.FieldName = "timeZone" // 时区
|
||||
NodeClusterField_NodeMaxThreads dbs.FieldName = "nodeMaxThreads" // 节点最大线程数
|
||||
NodeClusterField_DdosProtection dbs.FieldName = "ddosProtection" // DDoS防护设置
|
||||
NodeClusterField_AutoOpenPorts dbs.FieldName = "autoOpenPorts" // 是否自动尝试开放端口
|
||||
NodeClusterField_IsPinned dbs.FieldName = "isPinned" // 是否置顶
|
||||
NodeClusterField_Webp dbs.FieldName = "webp" // WebP设置
|
||||
NodeClusterField_Uam dbs.FieldName = "uam" // UAM设置
|
||||
NodeClusterField_Clock dbs.FieldName = "clock" // 时钟配置
|
||||
NodeClusterField_GlobalServerConfig dbs.FieldName = "globalServerConfig" // 全局服务配置
|
||||
NodeClusterField_AutoRemoteStart dbs.FieldName = "autoRemoteStart" // 自动远程启动
|
||||
NodeClusterField_AutoInstallNftables dbs.FieldName = "autoInstallNftables" // 自动安装nftables
|
||||
NodeClusterField_IsAD dbs.FieldName = "isAD" // 是否为高防集群
|
||||
NodeClusterField_HttpPages dbs.FieldName = "httpPages" // 自定义页面设置
|
||||
NodeClusterField_Cc dbs.FieldName = "cc" // CC设置
|
||||
NodeClusterField_Http3 dbs.FieldName = "http3" // HTTP3设置
|
||||
)
|
||||
|
||||
// NodeCluster 节点集群
|
||||
type NodeCluster struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
@@ -43,6 +86,7 @@ type NodeCluster struct {
|
||||
IsAD bool `field:"isAD"` // 是否为高防集群
|
||||
HttpPages dbs.JSON `field:"httpPages"` // 自定义页面设置
|
||||
Cc dbs.JSON `field:"cc"` // CC设置
|
||||
Http3 dbs.JSON `field:"http3"` // HTTP3设置
|
||||
}
|
||||
|
||||
type NodeClusterOperator struct {
|
||||
@@ -85,6 +129,7 @@ type NodeClusterOperator struct {
|
||||
IsAD any // 是否为高防集群
|
||||
HttpPages any // 自定义页面设置
|
||||
Cc any // CC设置
|
||||
Http3 any // HTTP3设置
|
||||
}
|
||||
|
||||
func NewNodeClusterOperator() *NodeClusterOperator {
|
||||
|
||||
@@ -60,7 +60,7 @@ func (this *NodeCluster) DecodeClock() *nodeconfigs.ClockConfig {
|
||||
|
||||
// DecodeGlobalServerConfig 解析全局服务配置
|
||||
func (this *NodeCluster) DecodeGlobalServerConfig() *serverconfigs.GlobalServerConfig {
|
||||
var config = serverconfigs.DefaultGlobalServerConfig()
|
||||
var config = serverconfigs.NewGlobalServerConfig()
|
||||
if IsNotNull(this.GlobalServerConfig) {
|
||||
err := json.Unmarshal(this.GlobalServerConfig, config)
|
||||
if err != nil {
|
||||
|
||||
@@ -295,6 +295,7 @@ func (this *NodeDAO) CountAllEnabledNodes(tx *dbs.Tx) (int64, error) {
|
||||
func (this *NodeDAO) CountAllEnabledOfflineNodes(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("clusterId IN (SELECT id FROM "+SharedNodeClusterDAO.Table+" WHERE state=:clusterState)").
|
||||
Param("clusterState", NodeClusterStateEnabled).
|
||||
Where("(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)").
|
||||
@@ -1086,6 +1087,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
|
||||
config.WebPImagePolicies = map[int64]*nodeconfigs.WebPImagePolicy{}
|
||||
config.UAMPolicies = map[int64]*nodeconfigs.UAMPolicy{}
|
||||
config.HTTPCCPolicies = map[int64]*nodeconfigs.HTTPCCPolicy{}
|
||||
config.HTTP3Policies = map[int64]*nodeconfigs.HTTP3Policy{}
|
||||
config.HTTPPagesPolicies = map[int64]*nodeconfigs.HTTPPagesPolicy{}
|
||||
var allowIPMaps = map[string]bool{}
|
||||
for _, clusterId := range clusterIds {
|
||||
@@ -1172,7 +1174,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
|
||||
|
||||
// UAM
|
||||
if IsNotNull(nodeCluster.Uam) {
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
var uamPolicy = nodeconfigs.NewUAMPolicy()
|
||||
err = json.Unmarshal(nodeCluster.Uam, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1189,7 +1191,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
|
||||
}
|
||||
|
||||
// 集成默认设置
|
||||
for i := 0; i < len(serverconfigs.DefaultHTTPCCThresholds); i ++ {
|
||||
for i := 0; i < len(serverconfigs.DefaultHTTPCCThresholds); i++ {
|
||||
if i < len(ccPolicy.Thresholds) {
|
||||
ccPolicy.Thresholds[i].MergeIfEmpty(serverconfigs.DefaultHTTPCCThresholds[i])
|
||||
}
|
||||
@@ -1198,6 +1200,16 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, dataMap *shared
|
||||
config.HTTPCCPolicies[clusterId] = ccPolicy
|
||||
}
|
||||
|
||||
// HTTP3 Policy
|
||||
if IsNotNull(nodeCluster.Http3) {
|
||||
var http3Policy = nodeconfigs.NewHTTP3Policy()
|
||||
err = json.Unmarshal(nodeCluster.Http3, http3Policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.HTTP3Policies[clusterId] = http3Policy
|
||||
}
|
||||
|
||||
// HTTP Pages Policy
|
||||
if IsNotNull(nodeCluster.HttpPages) {
|
||||
var httpPagesPolicy = nodeconfigs.NewHTTPPagesPolicy()
|
||||
@@ -1473,6 +1485,7 @@ func (this *NodeDAO) FindAllNotInstalledNodesWithClusterId(tx *dbs.Tx, clusterId
|
||||
func (this *NodeDAO) CountAllLowerVersionNodesWithClusterId(tx *dbs.Tx, clusterId int64, os string, arch string, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Attr("clusterId", clusterId).
|
||||
Where("status IS NOT NULL").
|
||||
Where("JSON_EXTRACT(status, '$.os')=:os").
|
||||
@@ -1506,6 +1519,7 @@ func (this *NodeDAO) FindAllLowerVersionNodesWithClusterId(tx *dbs.Tx, clusterId
|
||||
func (this *NodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("clusterId IN (SELECT id FROM "+SharedNodeClusterDAO.Table+" WHERE state=1)").
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
|
||||
@@ -27,6 +27,7 @@ const (
|
||||
NodeTaskTypeUAMPolicyChanged NodeTaskType = "uamPolicyChanged" // UAM策略变化
|
||||
NodeTaskTypeHTTPPagesPolicyChanged NodeTaskType = "httpPagesPolicyChanged" // 自定义页面变化
|
||||
NodeTaskTypeHTTPCCPolicyChanged NodeTaskType = "httpCCPolicyChanged" // CC策略变化
|
||||
NodeTaskTypeHTTP3PolicyChanged NodeTaskType = "http3PolicyChanged" // HTTP3策略变化
|
||||
NodeTaskTypeUpdatingServers NodeTaskType = "updatingServers" // 更新一组服务
|
||||
|
||||
// NS相关
|
||||
@@ -232,6 +233,12 @@ func (this *NodeTaskDAO) DeleteNodeTasks(tx *dbs.Tx, role string, nodeId int64)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteAllNodeTasks 删除所有节点相关任务
|
||||
func (this *NodeTaskDAO)DeleteAllNodeTasks(tx *dbs.Tx) error {
|
||||
return this.Query(tx).
|
||||
DeleteQuickly()
|
||||
}
|
||||
|
||||
// FindDoingNodeTasks 查询一个节点的所有任务
|
||||
func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, role string, nodeId int64, version int64) (result []*NodeTask, err error) {
|
||||
if nodeId <= 0 {
|
||||
|
||||
@@ -22,7 +22,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedNodeTrafficDailyStatDAO.Clean(nil, 30) // 只保留N天
|
||||
err := SharedNodeTrafficDailyStatDAO.CleanDefaultDays(nil, 32) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeTrafficDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -134,11 +134,27 @@ func (this *NodeTrafficDailyStatDAO) SumDailyStat(tx *dbs.Tx, role string, nodeI
|
||||
return one.(*NodeTrafficDailyStat), nil
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *NodeTrafficDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理历史数据
|
||||
func (this *NodeTrafficDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *NodeTrafficDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.NodeTrafficDailyStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.NodeTrafficDailyStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 32
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ type NSCluster struct {
|
||||
Tcp dbs.JSON `field:"tcp"` // TCP设置
|
||||
Tls dbs.JSON `field:"tls"` // TLS设置
|
||||
Udp dbs.JSON `field:"udp"` // UDP设置
|
||||
Doh dbs.JSON `field:"doh"` // DoH设置
|
||||
DdosProtection dbs.JSON `field:"ddosProtection"` // DDoS防护设置
|
||||
Hosts dbs.JSON `field:"hosts"` // DNS主机地址
|
||||
Soa dbs.JSON `field:"soa"` // SOA配置
|
||||
@@ -39,6 +40,7 @@ type NSClusterOperator struct {
|
||||
Tcp any // TCP设置
|
||||
Tls any // TLS设置
|
||||
Udp any // UDP设置
|
||||
Doh any // DoH设置
|
||||
DdosProtection any // DDoS防护设置
|
||||
Hosts any // DNS主机地址
|
||||
Soa any // SOA配置
|
||||
|
||||
@@ -93,6 +93,7 @@ func (this *NSNodeDAO) CountAllLowerVersionNodesWithClusterId(tx *dbs.Tx, cluste
|
||||
return this.Query(tx).
|
||||
State(NSNodeStateEnabled).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("isOn", true).
|
||||
Where("status IS NOT NULL").
|
||||
Where("JSON_EXTRACT(status, '$.os')=:os").
|
||||
Where("JSON_EXTRACT(status, '$.arch')=:arch").
|
||||
@@ -161,6 +162,7 @@ func (this *NSNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *no
|
||||
func (this *NSNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(NSNodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("clusterId IN (SELECT id FROM "+SharedNSClusterDAO.Table+" WHERE state=1)").
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -91,7 +92,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
adminId int64,
|
||||
userId int64,
|
||||
name string,
|
||||
addrJSON string,
|
||||
addrJSON []byte,
|
||||
ossConfig *ossconfigs.OSSConfig,
|
||||
description string,
|
||||
weight int32, isOn bool,
|
||||
connTimeout *shared.TimeDuration,
|
||||
@@ -102,7 +104,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string,
|
||||
host string,
|
||||
followPort bool) (originId int64, err error) {
|
||||
followPort bool,
|
||||
http2Enabled bool) (originId int64, err error) {
|
||||
var op = NewOriginOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
@@ -141,7 +144,18 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
op.MaxIdleConns = 0
|
||||
}
|
||||
|
||||
op.Addr = addrJSON
|
||||
if len(addrJSON) > 0 {
|
||||
op.Addr = addrJSON
|
||||
}
|
||||
|
||||
if ossConfig != nil {
|
||||
ossConfigJSON, err := json.Marshal(ossConfig)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Oss = ossConfigJSON
|
||||
}
|
||||
|
||||
op.Description = description
|
||||
if weight < 0 {
|
||||
weight = 0
|
||||
@@ -169,6 +183,7 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
|
||||
op.Host = host
|
||||
op.FollowPort = followPort
|
||||
op.Http2Enabled = http2Enabled
|
||||
|
||||
op.State = OriginStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
@@ -182,7 +197,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
originId int64,
|
||||
name string,
|
||||
addrJSON string,
|
||||
addrJSON []byte,
|
||||
ossConfig *ossconfigs.OSSConfig,
|
||||
description string,
|
||||
weight int32,
|
||||
isOn bool,
|
||||
@@ -194,14 +210,25 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string,
|
||||
host string,
|
||||
followPort bool) error {
|
||||
followPort bool,
|
||||
http2Enabled bool) error {
|
||||
if originId <= 0 {
|
||||
return errors.New("invalid originId")
|
||||
}
|
||||
var op = NewOriginOperator()
|
||||
op.Id = originId
|
||||
op.Name = name
|
||||
|
||||
op.Addr = addrJSON
|
||||
|
||||
if ossConfig != nil {
|
||||
ossConfigJSON, err := json.Marshal(ossConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Oss = ossConfigJSON
|
||||
}
|
||||
|
||||
op.Description = description
|
||||
if weight < 0 {
|
||||
weight = 0
|
||||
@@ -266,6 +293,7 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
|
||||
op.Host = host
|
||||
op.FollowPort = followPort
|
||||
op.Http2Enabled = http2Enabled
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -329,6 +357,7 @@ func (this *OriginDAO) CloneOrigin(tx *dbs.Tx, fromOriginId int64) (newOriginId
|
||||
op.Domains = origin.Domains
|
||||
}
|
||||
op.FollowPort = origin.FollowPort
|
||||
op.Http2Enabled = origin.Http2Enabled
|
||||
op.State = origin.State
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
@@ -367,8 +396,10 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, dataMap *
|
||||
RequestHost: origin.Host,
|
||||
Domains: origin.DecodeDomains(),
|
||||
FollowPort: origin.FollowPort,
|
||||
HTTP2Enabled: origin.Http2Enabled,
|
||||
}
|
||||
|
||||
// addr
|
||||
if IsNotNull(origin.Addr) {
|
||||
var addr = &serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal(origin.Addr, addr)
|
||||
@@ -378,6 +409,16 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, dataMap *
|
||||
config.Addr = addr
|
||||
}
|
||||
|
||||
// oss
|
||||
if IsNotNull(origin.Oss) {
|
||||
var ossConfig = ossconfigs.NewOSSConfig()
|
||||
err = json.Unmarshal(origin.Oss, ossConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.OSS = ossConfig
|
||||
}
|
||||
|
||||
if IsNotNull(origin.ConnTimeout) {
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(origin.ConnTimeout, &connTimeout)
|
||||
|
||||
@@ -11,6 +11,7 @@ type Origin struct {
|
||||
Name string `field:"name"` // 名称
|
||||
Version uint32 `field:"version"` // 版本
|
||||
Addr dbs.JSON `field:"addr"` // 地址
|
||||
Oss dbs.JSON `field:"oss"` // OSS配置
|
||||
Description string `field:"description"` // 描述
|
||||
Code string `field:"code"` // 代号
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
@@ -31,36 +32,39 @@ type Origin struct {
|
||||
Domains dbs.JSON `field:"domains"` // 所属域名
|
||||
FollowPort bool `field:"followPort"` // 端口跟随
|
||||
State uint8 `field:"state"` // 状态
|
||||
Http2Enabled bool `field:"http2Enabled"` // 是否支持HTTP/2
|
||||
}
|
||||
|
||||
type OriginOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Version interface{} // 版本
|
||||
Addr interface{} // 地址
|
||||
Description interface{} // 描述
|
||||
Code interface{} // 代号
|
||||
Weight interface{} // 权重
|
||||
ConnTimeout interface{} // 连接超时
|
||||
ReadTimeout interface{} // 读超时
|
||||
IdleTimeout interface{} // 空闲连接超时
|
||||
MaxFails interface{} // 最多失败次数
|
||||
MaxConns interface{} // 最大并发连接数
|
||||
MaxIdleConns interface{} // 最多空闲连接数
|
||||
HttpRequestURI interface{} // 转发后的请求URI
|
||||
HttpRequestHeader interface{} // 请求Header配置
|
||||
HttpResponseHeader interface{} // 响应Header配置
|
||||
Host interface{} // 自定义主机名
|
||||
HealthCheck interface{} // 健康检查设置
|
||||
Cert interface{} // 证书设置
|
||||
Ftp interface{} // FTP相关设置
|
||||
CreatedAt interface{} // 创建时间
|
||||
Domains interface{} // 所属域名
|
||||
FollowPort interface{} // 端口跟随
|
||||
State interface{} // 状态
|
||||
Id any // ID
|
||||
AdminId any // 管理员ID
|
||||
UserId any // 用户ID
|
||||
IsOn any // 是否启用
|
||||
Name any // 名称
|
||||
Version any // 版本
|
||||
Addr any // 地址
|
||||
Oss any // OSS配置
|
||||
Description any // 描述
|
||||
Code any // 代号
|
||||
Weight any // 权重
|
||||
ConnTimeout any // 连接超时
|
||||
ReadTimeout any // 读超时
|
||||
IdleTimeout any // 空闲连接超时
|
||||
MaxFails any // 最多失败次数
|
||||
MaxConns any // 最大并发连接数
|
||||
MaxIdleConns any // 最多空闲连接数
|
||||
HttpRequestURI any // 转发后的请求URI
|
||||
HttpRequestHeader any // 请求Header配置
|
||||
HttpResponseHeader any // 响应Header配置
|
||||
Host any // 自定义主机名
|
||||
HealthCheck any // 健康检查设置
|
||||
Cert any // 证书设置
|
||||
Ftp any // FTP相关设置
|
||||
CreatedAt any // 创建时间
|
||||
Domains any // 所属域名
|
||||
FollowPort any // 端口跟随
|
||||
State any // 状态
|
||||
Http2Enabled any // 是否支持HTTP/2
|
||||
}
|
||||
|
||||
func NewOriginOperator() *OriginOperator {
|
||||
|
||||
@@ -42,7 +42,7 @@ func init() {
|
||||
// EnableRegionCity 启用条目
|
||||
func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionCityStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -51,7 +51,7 @@ func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
// DisableRegionCity 禁用条目
|
||||
func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionCityStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -60,7 +60,7 @@ func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||
// FindEnabledRegionCity 查找启用中的条目
|
||||
func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionCity, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Attr("state", RegionCityStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
@@ -72,7 +72,7 @@ func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionC
|
||||
// FindRegionCityName 根据主键查找名称
|
||||
func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, er
|
||||
func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("dataId", dataId).
|
||||
ResultPk().
|
||||
Result(RegionCityField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string,
|
||||
op.DataId = dataId
|
||||
op.State = RegionCityStateEnabled
|
||||
|
||||
codes := []string{name}
|
||||
var codes = []string{name}
|
||||
codesJSON, err := json.Marshal(codes)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -103,7 +103,18 @@ func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string,
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return types.Int64(op.Id), nil
|
||||
var cityId = types.Int64(op.Id)
|
||||
|
||||
// value id
|
||||
err = this.Query(tx).
|
||||
Pk(cityId).
|
||||
Set(RegionCityField_ValueId, cityId).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return cityId, nil
|
||||
}
|
||||
|
||||
// FindCityIdWithName 根据城市名查找城市ID
|
||||
@@ -113,7 +124,7 @@ func (this *RegionCityDAO) FindCityIdWithName(tx *dbs.Tx, provinceId int64, city
|
||||
Where("(name=:cityName OR customName=:cityName OR JSON_CONTAINS(codes, :cityNameJSON) OR JSON_CONTAINS(customCodes, :cityNameJSON))").
|
||||
Param("cityName", cityName).
|
||||
Param("cityNameJSON", strconv.Quote(cityName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
ResultPk().
|
||||
Result(RegionCityField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -147,7 +158,7 @@ func (this *RegionCityDAO) UpdateCityCustom(tx *dbs.Tx, cityId int64, customName
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Pk(cityId).
|
||||
Attr(RegionCityField_ValueId, cityId).
|
||||
Set("customName", customName).
|
||||
Set("customCodes", customCodesJSON).
|
||||
UpdateQuickly()
|
||||
|
||||
@@ -2,9 +2,22 @@ package regions
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
RegionCityField_Id dbs.FieldName = "id" // ID
|
||||
RegionCityField_ValueId dbs.FieldName = "valueId" // 实际ID
|
||||
RegionCityField_ProvinceId dbs.FieldName = "provinceId" // 省份ID
|
||||
RegionCityField_Name dbs.FieldName = "name" // 名称
|
||||
RegionCityField_Codes dbs.FieldName = "codes" // 代号
|
||||
RegionCityField_CustomName dbs.FieldName = "customName" // 自定义名称
|
||||
RegionCityField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
|
||||
RegionCityField_State dbs.FieldName = "state" // 状态
|
||||
RegionCityField_DataId dbs.FieldName = "dataId" // 原始数据ID
|
||||
)
|
||||
|
||||
// RegionCity 区域-城市
|
||||
type RegionCity struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Id1 uint32 `field:"id"` // ID
|
||||
ValueId uint32 `field:"valueId"` // 实际ID
|
||||
ProvinceId uint32 `field:"provinceId"` // 省份ID
|
||||
Name string `field:"name"` // 名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
@@ -15,14 +28,15 @@ type RegionCity struct {
|
||||
}
|
||||
|
||||
type RegionCityOperator struct {
|
||||
Id interface{} // ID
|
||||
ProvinceId interface{} // 省份ID
|
||||
Name interface{} // 名称
|
||||
Codes interface{} // 代号
|
||||
CustomName interface{} // 自定义名称
|
||||
CustomCodes interface{} // 自定义代号
|
||||
State interface{} // 状态
|
||||
DataId interface{} // 原始数据ID
|
||||
Id any // ID
|
||||
ValueId any // 实际ID
|
||||
ProvinceId any // 省份ID
|
||||
Name any // 名称
|
||||
Codes any // 代号
|
||||
CustomName any // 自定义名称
|
||||
CustomCodes any // 自定义代号
|
||||
State any // 状态
|
||||
DataId any // 原始数据ID
|
||||
}
|
||||
|
||||
func NewRegionCityOperator() *RegionCityOperator {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -20,10 +21,6 @@ const (
|
||||
RegionCountryStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
const (
|
||||
CountryChinaId = 1
|
||||
)
|
||||
|
||||
var regionCountryIdAndNameCacheMap = map[int64]string{} // country id => name
|
||||
|
||||
type RegionCountryDAO dbs.DAO
|
||||
@@ -50,7 +47,7 @@ func init() {
|
||||
// EnableRegionCountry 启用条目
|
||||
func (this *RegionCountryDAO) EnableRegionCountry(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionCountryStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -59,7 +56,7 @@ func (this *RegionCountryDAO) EnableRegionCountry(tx *dbs.Tx, id uint32) error {
|
||||
// DisableRegionCountry 禁用条目
|
||||
func (this *RegionCountryDAO) DisableRegionCountry(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionCountryStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -68,7 +65,7 @@ func (this *RegionCountryDAO) DisableRegionCountry(tx *dbs.Tx, id int64) error {
|
||||
// FindEnabledRegionCountry 查找启用中的条目
|
||||
func (this *RegionCountryDAO) FindEnabledRegionCountry(tx *dbs.Tx, id int64) (*RegionCountry, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Attr("state", RegionCountryStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
@@ -88,7 +85,7 @@ func (this *RegionCountryDAO) FindRegionCountryName(tx *dbs.Tx, id int64) (strin
|
||||
}
|
||||
|
||||
name, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
@@ -105,7 +102,7 @@ func (this *RegionCountryDAO) FindRegionCountryName(tx *dbs.Tx, id int64) (strin
|
||||
func (this *RegionCountryDAO) FindCountryIdWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("dataId", dataId).
|
||||
ResultPk().
|
||||
Result(RegionCountryField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -115,7 +112,7 @@ func (this *RegionCountryDAO) FindCountryIdWithName(tx *dbs.Tx, countryName stri
|
||||
Where("(name=:countryName OR JSON_CONTAINS(codes, :countryNameJSON) OR customName=:countryName OR JSON_CONTAINS(customCodes, :countryNameJSON))").
|
||||
Param("countryName", countryName).
|
||||
Param("countryNameJSON", strconv.Quote(countryName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
ResultPk().
|
||||
Result(RegionCountryField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -145,16 +142,61 @@ func (this *RegionCountryDAO) CreateCountry(tx *dbs.Tx, name string, dataId stri
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return types.Int64(op.Id), nil
|
||||
var countryId = types.Int64(op.Id)
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(countryId).
|
||||
Set(RegionCountryField_ValueId, countryId).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return countryId, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledCountriesOrderByPinyin 查找所有可用的国家并按拼音排序
|
||||
func (this *RegionCountryDAO) FindAllEnabledCountriesOrderByPinyin(tx *dbs.Tx) (result []*RegionCountry, err error) {
|
||||
_, err = this.Query(tx).
|
||||
ones, err := this.Query(tx).
|
||||
State(RegionCountryStateEnabled).
|
||||
Slice(&result).
|
||||
Asc("pinyin").
|
||||
Asc("JSON_EXTRACT(pinyin, '$[0]')").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// resort China special regions
|
||||
var chinaRegionMap = map[int64]*RegionCountry{} // countryId => *RegionCountry
|
||||
for _, one := range ones {
|
||||
var country = one.(*RegionCountry)
|
||||
var valueId = int64(country.ValueId)
|
||||
if regionconfigs.CheckRegionIsInGreaterChina(valueId) {
|
||||
chinaRegionMap[valueId] = country
|
||||
}
|
||||
}
|
||||
|
||||
for _, one := range ones {
|
||||
var country = one.(*RegionCountry)
|
||||
var valueId = int64(country.ValueId)
|
||||
if valueId == regionconfigs.RegionChinaId {
|
||||
result = append(result, country)
|
||||
|
||||
// add hk, tw, mo, mainland ...
|
||||
for _, subRegionId := range regionconfigs.FindAllGreaterChinaSubRegionIds() {
|
||||
subRegion, ok := chinaRegionMap[subRegionId]
|
||||
if ok {
|
||||
result = append(result, subRegion)
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
if regionconfigs.CheckRegionIsInGreaterChina(valueId) {
|
||||
continue
|
||||
}
|
||||
result = append(result, country)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -163,7 +205,7 @@ func (this *RegionCountryDAO) FindAllCountries(tx *dbs.Tx) (result []*RegionCoun
|
||||
_, err = this.Query(tx).
|
||||
State(RegionCountryStateEnabled).
|
||||
Slice(&result).
|
||||
AscPk().
|
||||
Asc(RegionCountryField_ValueId).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
@@ -185,7 +227,7 @@ func (this *RegionCountryDAO) UpdateCountryCustom(tx *dbs.Tx, countryId int64, c
|
||||
}()
|
||||
|
||||
return this.Query(tx).
|
||||
Pk(countryId).
|
||||
Attr("valueId", countryId).
|
||||
Set("customName", customName).
|
||||
Set("customCodes", customCodesJSON).
|
||||
UpdateQuickly()
|
||||
|
||||
@@ -2,9 +2,25 @@ package regions
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
RegionCountryField_Id dbs.FieldName = "id" // ID
|
||||
RegionCountryField_ValueId dbs.FieldName = "valueId" // 实际ID
|
||||
RegionCountryField_ValueCode dbs.FieldName = "valueCode" // 值代号
|
||||
RegionCountryField_Name dbs.FieldName = "name" // 名称
|
||||
RegionCountryField_Codes dbs.FieldName = "codes" // 代号
|
||||
RegionCountryField_CustomName dbs.FieldName = "customName" // 自定义名称
|
||||
RegionCountryField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
|
||||
RegionCountryField_State dbs.FieldName = "state" // 状态
|
||||
RegionCountryField_DataId dbs.FieldName = "dataId" // 原始数据ID
|
||||
RegionCountryField_Pinyin dbs.FieldName = "pinyin" // 拼音
|
||||
RegionCountryField_IsCommon dbs.FieldName = "isCommon" // 是否常用
|
||||
)
|
||||
|
||||
// RegionCountry 区域-国家/地区
|
||||
type RegionCountry struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Id1 uint32 `field:"id"` // ID
|
||||
ValueId uint32 `field:"valueId"` // 实际ID
|
||||
ValueCode string `field:"valueCode"` // 值代号
|
||||
Name string `field:"name"` // 名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
CustomName string `field:"customName"` // 自定义名称
|
||||
@@ -12,17 +28,21 @@ type RegionCountry struct {
|
||||
State uint8 `field:"state"` // 状态
|
||||
DataId string `field:"dataId"` // 原始数据ID
|
||||
Pinyin dbs.JSON `field:"pinyin"` // 拼音
|
||||
IsCommon bool `field:"isCommon"` // 是否常用
|
||||
}
|
||||
|
||||
type RegionCountryOperator struct {
|
||||
Id interface{} // ID
|
||||
Name interface{} // 名称
|
||||
Codes interface{} // 代号
|
||||
CustomName interface{} // 自定义名称
|
||||
CustomCodes interface{} // 自定义代号
|
||||
State interface{} // 状态
|
||||
DataId interface{} // 原始数据ID
|
||||
Pinyin interface{} // 拼音
|
||||
Id any // ID
|
||||
ValueId any // 实际ID
|
||||
ValueCode any // 值代号
|
||||
Name any // 名称
|
||||
Codes any // 代号
|
||||
CustomName any // 自定义名称
|
||||
CustomCodes any // 自定义代号
|
||||
State any // 状态
|
||||
DataId any // 原始数据ID
|
||||
Pinyin any // 拼音
|
||||
IsCommon any // 是否常用
|
||||
}
|
||||
|
||||
func NewRegionCountryOperator() *RegionCountryOperator {
|
||||
|
||||
@@ -41,7 +41,7 @@ func init() {
|
||||
// EnableRegionProvider 启用条目
|
||||
func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionProviderStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -50,7 +50,7 @@ func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error
|
||||
// DisableRegionProvider 禁用条目
|
||||
func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionProviderStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -59,7 +59,7 @@ func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) erro
|
||||
// FindEnabledRegionProvider 查找启用中的条目
|
||||
func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id int64) (*RegionProvider, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Attr("state", RegionProviderStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
@@ -71,7 +71,7 @@ func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id int64) (
|
||||
// FindRegionProviderName 根据主键查找名称
|
||||
func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func (this *RegionProviderDAO) FindProviderIdWithName(tx *dbs.Tx, providerName s
|
||||
Where("(name=:providerName OR customName=:providerName OR JSON_CONTAINS(codes, :providerNameJSON) OR JSON_CONTAINS(customCodes, :providerNameJSON))").
|
||||
Param("providerName", providerName).
|
||||
Param("providerNameJSON", strconv.Quote(providerName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
ResultPk().
|
||||
Result(RegionProviderField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -96,7 +96,20 @@ func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, e
|
||||
return 0, err
|
||||
}
|
||||
op.Codes = codesJSON
|
||||
return this.SaveInt64(tx, op)
|
||||
providerId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(providerId).
|
||||
Set(RegionProviderField_ValueId, providerId).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return providerId, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledProviders 查找所有服务商
|
||||
@@ -119,7 +132,7 @@ func (this *RegionProviderDAO) UpdateProviderCustom(tx *dbs.Tx, providerId int64
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Pk(providerId).
|
||||
Attr("valueId", providerId).
|
||||
Set("customName", customName).
|
||||
Set("customCodes", customCodesJSON).
|
||||
UpdateQuickly()
|
||||
|
||||
@@ -2,9 +2,20 @@ package regions
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
RegionProviderField_Id dbs.FieldName = "id" // ID
|
||||
RegionProviderField_ValueId dbs.FieldName = "valueId" // 实际ID
|
||||
RegionProviderField_Name dbs.FieldName = "name" // 名称
|
||||
RegionProviderField_Codes dbs.FieldName = "codes" // 代号
|
||||
RegionProviderField_CustomName dbs.FieldName = "customName" // 自定义名称
|
||||
RegionProviderField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
|
||||
RegionProviderField_State dbs.FieldName = "state" // 状态
|
||||
)
|
||||
|
||||
// RegionProvider 区域-运营商
|
||||
type RegionProvider struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Id1 uint32 `field:"id"` // ID
|
||||
ValueId uint32 `field:"valueId"` // 实际ID
|
||||
Name string `field:"name"` // 名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
CustomName string `field:"customName"` // 自定义名称
|
||||
@@ -13,12 +24,13 @@ type RegionProvider struct {
|
||||
}
|
||||
|
||||
type RegionProviderOperator struct {
|
||||
Id interface{} // ID
|
||||
Name interface{} // 名称
|
||||
Codes interface{} // 代号
|
||||
CustomName interface{} // 自定义名称
|
||||
CustomCodes interface{} // 自定义代号
|
||||
State interface{} // 状态
|
||||
Id any // ID
|
||||
ValueId any // 实际ID
|
||||
Name any // 名称
|
||||
Codes any // 代号
|
||||
CustomName any // 自定义名称
|
||||
CustomCodes any // 自定义代号
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewRegionProviderOperator() *RegionProviderOperator {
|
||||
|
||||
@@ -42,7 +42,7 @@ func init() {
|
||||
// EnableRegionProvince 启用条目
|
||||
func (this *RegionProvinceDAO) EnableRegionProvince(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionProvinceStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -51,7 +51,7 @@ func (this *RegionProvinceDAO) EnableRegionProvince(tx *dbs.Tx, id int64) error
|
||||
// DisableRegionProvince 禁用条目
|
||||
func (this *RegionProvinceDAO) DisableRegionProvince(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionProvinceStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -60,7 +60,7 @@ func (this *RegionProvinceDAO) DisableRegionProvince(tx *dbs.Tx, id int64) error
|
||||
// FindEnabledRegionProvince 查找启用中的条目
|
||||
func (this *RegionProvinceDAO) FindEnabledRegionProvince(tx *dbs.Tx, id int64) (*RegionProvince, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Attr("state", RegionProvinceStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
@@ -72,7 +72,7 @@ func (this *RegionProvinceDAO) FindEnabledRegionProvince(tx *dbs.Tx, id int64) (
|
||||
// FindRegionProvinceName 根据主键查找名称
|
||||
func (this *RegionProvinceDAO) FindRegionProvinceName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func (this *RegionProvinceDAO) FindRegionProvinceName(tx *dbs.Tx, id int64) (str
|
||||
func (this *RegionProvinceDAO) FindProvinceIdWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("dataId", dataId).
|
||||
ResultPk().
|
||||
Result(RegionProvinceField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func (this *RegionProvinceDAO) FindProvinceIdWithName(tx *dbs.Tx, countryId int6
|
||||
Where("(name=:provinceName OR customName=:provinceName OR JSON_CONTAINS(codes, :provinceNameJSON) OR JSON_CONTAINS(customCodes, :provinceNameJSON))").
|
||||
Param("provinceName", provinceName).
|
||||
Param("provinceNameJSON", strconv.Quote(provinceName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
ResultPk().
|
||||
Result(RegionProvinceField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ func (this *RegionProvinceDAO) CreateProvince(tx *dbs.Tx, countryId int64, name
|
||||
op.DataId = dataId
|
||||
op.State = RegionProvinceStateEnabled
|
||||
|
||||
codes := []string{name}
|
||||
var codes = []string{name}
|
||||
codesJSON, err := json.Marshal(codes)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -114,7 +114,17 @@ func (this *RegionProvinceDAO) CreateProvince(tx *dbs.Tx, countryId int64, name
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return types.Int64(op.Id), nil
|
||||
var provinceId = types.Int64(op.Id)
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(provinceId).
|
||||
Set(RegionProvinceField_ValueId, provinceId).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return provinceId, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledProvincesWithCountryId 查找某个国家/地区的所有省份
|
||||
@@ -122,7 +132,7 @@ func (this *RegionProvinceDAO) FindAllEnabledProvincesWithCountryId(tx *dbs.Tx,
|
||||
_, err = this.Query(tx).
|
||||
State(RegionProvinceStateEnabled).
|
||||
Attr("countryId", countryId).
|
||||
AscPk().
|
||||
Asc(RegionProvinceField_ValueId).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
@@ -132,7 +142,7 @@ func (this *RegionProvinceDAO) FindAllEnabledProvincesWithCountryId(tx *dbs.Tx,
|
||||
func (this *RegionProvinceDAO) FindAllEnabledProvinces(tx *dbs.Tx) (result []*RegionProvince, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(RegionProvinceStateEnabled).
|
||||
AscPk().
|
||||
Asc(RegionProvinceField_ValueId).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
@@ -149,7 +159,7 @@ func (this *RegionProvinceDAO) UpdateProvinceCustom(tx *dbs.Tx, provinceId int64
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Pk(provinceId).
|
||||
Attr("valueId", provinceId).
|
||||
Set("customName", customName).
|
||||
Set("customCodes", customCodesJSON).
|
||||
UpdateQuickly()
|
||||
|
||||
@@ -2,9 +2,22 @@ package regions
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
RegionProvinceField_Id dbs.FieldName = "id" // ID
|
||||
RegionProvinceField_ValueId dbs.FieldName = "valueId" // 实际ID
|
||||
RegionProvinceField_CountryId dbs.FieldName = "countryId" // 国家ID
|
||||
RegionProvinceField_Name dbs.FieldName = "name" // 名称
|
||||
RegionProvinceField_Codes dbs.FieldName = "codes" // 代号
|
||||
RegionProvinceField_CustomName dbs.FieldName = "customName" // 自定义名称
|
||||
RegionProvinceField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
|
||||
RegionProvinceField_State dbs.FieldName = "state" // 状态
|
||||
RegionProvinceField_DataId dbs.FieldName = "dataId" // 原始数据ID
|
||||
)
|
||||
|
||||
// RegionProvince 区域-省份
|
||||
type RegionProvince struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Id1 uint32 `field:"id"` // ID
|
||||
ValueId uint32 `field:"valueId"` // 实际ID
|
||||
CountryId uint32 `field:"countryId"` // 国家ID
|
||||
Name string `field:"name"` // 名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
@@ -15,14 +28,15 @@ type RegionProvince struct {
|
||||
}
|
||||
|
||||
type RegionProvinceOperator struct {
|
||||
Id interface{} // ID
|
||||
CountryId interface{} // 国家ID
|
||||
Name interface{} // 名称
|
||||
Codes interface{} // 代号
|
||||
CustomName interface{} // 自定义名称
|
||||
CustomCodes interface{} // 自定义代号
|
||||
State interface{} // 状态
|
||||
DataId interface{} // 原始数据ID
|
||||
Id any // ID
|
||||
ValueId any // 实际ID
|
||||
CountryId any // 国家ID
|
||||
Name any // 名称
|
||||
Codes any // 代号
|
||||
CustomName any // 自定义名称
|
||||
CustomCodes any // 自定义代号
|
||||
State any // 状态
|
||||
DataId any // 原始数据ID
|
||||
}
|
||||
|
||||
func NewRegionProvinceOperator() *RegionProvinceOperator {
|
||||
|
||||
@@ -41,7 +41,7 @@ func init() {
|
||||
// EnableRegionTown 启用条目
|
||||
func (this *RegionTownDAO) EnableRegionTown(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionTownStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -50,7 +50,7 @@ func (this *RegionTownDAO) EnableRegionTown(tx *dbs.Tx, id uint32) error {
|
||||
// DisableRegionTown 禁用条目
|
||||
func (this *RegionTownDAO) DisableRegionTown(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Set("state", RegionTownStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
@@ -59,7 +59,7 @@ func (this *RegionTownDAO) DisableRegionTown(tx *dbs.Tx, id uint32) error {
|
||||
// FindEnabledRegionTown 查找启用中的区县
|
||||
func (this *RegionTownDAO) FindEnabledRegionTown(tx *dbs.Tx, id int64) (*RegionTown, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Attr("state", RegionTownStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
@@ -72,7 +72,7 @@ func (this *RegionTownDAO) FindEnabledRegionTown(tx *dbs.Tx, id int64) (*RegionT
|
||||
func (this *RegionTownDAO) FindAllRegionTowns(tx *dbs.Tx) (result []*RegionTown, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(RegionTownStateEnabled).
|
||||
AscPk().
|
||||
Asc(RegionTownField_ValueId).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
@@ -83,7 +83,7 @@ func (this *RegionTownDAO) FindAllRegionTownsWithCityId(tx *dbs.Tx, cityId int64
|
||||
_, err = this.Query(tx).
|
||||
State(RegionTownStateEnabled).
|
||||
Attr("cityId", cityId).
|
||||
AscPk().
|
||||
Asc(RegionTownField_ValueId).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
@@ -96,14 +96,14 @@ func (this *RegionTownDAO) FindTownIdWithName(tx *dbs.Tx, cityId int64, townName
|
||||
Where("(name=:townName OR customName=:townName OR JSON_CONTAINS(codes, :townNameJSON) OR JSON_CONTAINS(customCodes, :townNameJSON))").
|
||||
Param("townName", townName).
|
||||
Param("townNameJSON", strconv.Quote(townName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
ResultPk().
|
||||
Result(RegionTownField_ValueId).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindRegionTownName 根据主键查找名称
|
||||
func (this *RegionTownDAO) FindRegionTownName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("valueId", id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func (this *RegionTownDAO) UpdateTownCustom(tx *dbs.Tx, townId int64, customName
|
||||
return err
|
||||
}
|
||||
return this.Query(tx).
|
||||
Pk(townId).
|
||||
Attr("valueId", townId).
|
||||
Set("customName", customName).
|
||||
Set("customCodes", customCodesJSON).
|
||||
UpdateQuickly()
|
||||
@@ -176,5 +176,18 @@ func (this *RegionTownDAO) CreateTown(tx *dbs.Tx, cityId int64, townName string)
|
||||
op.Codes = codes
|
||||
|
||||
op.State = RegionTownStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
townId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(townId).
|
||||
Set(RegionTownField_ValueId, townId).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return townId, nil
|
||||
}
|
||||
|
||||
@@ -2,9 +2,22 @@ package regions
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
RegionTownField_Id dbs.FieldName = "id" // ID
|
||||
RegionTownField_ValueId dbs.FieldName = "valueId" // 真实ID
|
||||
RegionTownField_CityId dbs.FieldName = "cityId" // 城市ID
|
||||
RegionTownField_Name dbs.FieldName = "name" // 名称
|
||||
RegionTownField_Codes dbs.FieldName = "codes" // 代号
|
||||
RegionTownField_CustomName dbs.FieldName = "customName" // 自定义名称
|
||||
RegionTownField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
|
||||
RegionTownField_State dbs.FieldName = "state" // 状态
|
||||
RegionTownField_DataId dbs.FieldName = "dataId" // 原始数据ID
|
||||
)
|
||||
|
||||
// RegionTown 区域-省份
|
||||
type RegionTown struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Id1 uint32 `field:"id"` // ID
|
||||
ValueId uint32 `field:"valueId"` // 真实ID
|
||||
CityId uint32 `field:"cityId"` // 城市ID
|
||||
Name string `field:"name"` // 名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
@@ -15,14 +28,15 @@ type RegionTown struct {
|
||||
}
|
||||
|
||||
type RegionTownOperator struct {
|
||||
Id interface{} // ID
|
||||
CityId interface{} // 城市ID
|
||||
Name interface{} // 名称
|
||||
Codes interface{} // 代号
|
||||
CustomName interface{} // 自定义名称
|
||||
CustomCodes interface{} // 自定义代号
|
||||
State interface{} // 状态
|
||||
DataId interface{} // 原始数据ID
|
||||
Id any // ID
|
||||
ValueId any // 真实ID
|
||||
CityId any // 城市ID
|
||||
Name any // 名称
|
||||
Codes any // 代号
|
||||
CustomName any // 自定义名称
|
||||
CustomCodes any // 自定义代号
|
||||
State any // 状态
|
||||
DataId any // 原始数据ID
|
||||
}
|
||||
|
||||
func NewRegionTownOperator() *RegionTownOperator {
|
||||
|
||||
@@ -34,7 +34,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerBandwidthStatDAO.Clean(nil)
|
||||
err := SharedServerBandwidthStatDAO.CleanDefaultDays(nil, 100)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedServerBandwidthStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -745,9 +745,9 @@ func (this *ServerBandwidthStatDAO) SumDailyStat(tx *dbs.Tx, serverId int64, reg
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理过期数据
|
||||
func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -100)) // 保留大约3个月的数据
|
||||
// CleanDays 清理过期数据
|
||||
func (this *ServerBandwidthStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days)) // 保留大约3个月的数据
|
||||
return this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
@@ -757,6 +757,22 @@ func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (this *ServerBandwidthStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.ServerBandwidthStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.ServerBandwidthStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 100
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
// 批量执行
|
||||
func (this *ServerBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
|
||||
@@ -72,11 +72,11 @@ func TestServerBandwidthStatDAO_FindAllServerStatsWithDay(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_Clean(t *testing.T) {
|
||||
func TestServerBandwidthStatDAO_CleanDays(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
var before = time.Now()
|
||||
err := dao.Clean(tx)
|
||||
err := dao.CleanDays(tx, 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -28,7 +29,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerDailyStatDAO.Clean(nil, 60) // 只保留 N 天,时间需要长一些,因为需要用来生成账单
|
||||
err := SharedServerDailyStatDAO.CleanDefaultDays(nil, 60) // 只保留 N 天,时间需要长一些,因为需要用来生成账单
|
||||
if err != nil {
|
||||
logs.Println("ServerDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -513,7 +514,8 @@ func (this *ServerDailyStatDAO) FindStatsWithDay(tx *dbs.Tx, serverId int64, day
|
||||
Result("SUM(bytes) AS bytes", "SUM(cachedBytes) AS cachedBytes", "SUM(countRequests) AS countRequests", "SUM(countCachedRequests) AS countCachedRequests", "SUM(countAttackRequests) AS countAttackRequests", "SUM(attackBytes) AS attackBytes", "day", "timeFrom", "MIN(timeTo) AS timeTo").
|
||||
Attr("serverId", serverId).
|
||||
Attr("day", day).
|
||||
Group("day").Group("timeFrom", dbs.QueryOrderDesc)
|
||||
Group("day").
|
||||
Group("timeFrom")
|
||||
|
||||
if len(timeFrom) > 0 {
|
||||
query.Gte("timeFrom", timeFrom)
|
||||
@@ -530,6 +532,11 @@ func (this *ServerDailyStatDAO) FindStatsWithDay(tx *dbs.Tx, serverId int64, day
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sort results
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].TimeFrom < result[j].TimeFrom
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -673,8 +680,8 @@ func (this *ServerDailyStatDAO) compatFindHourlyStats(tx *dbs.Tx, serverId int64
|
||||
result = append(result, stat)
|
||||
} else {
|
||||
result = append(result, &ServerDailyStat{
|
||||
Hour: hour,
|
||||
Day: hour[:8],
|
||||
Hour: hour,
|
||||
Day: hour[:8],
|
||||
TimeFrom: hour[8:] + "00",
|
||||
})
|
||||
}
|
||||
@@ -742,11 +749,27 @@ func (this *ServerDailyStatDAO) UpdateStatFee(tx *dbs.Tx, statId int64, fee floa
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *ServerDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理历史数据
|
||||
func (this *ServerDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *ServerDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.ServerDailyStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.ServerDailyStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 60
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
@@ -140,6 +140,6 @@ func TestServerDailyStatDAO_FindStatsWithDay(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, stat := range stats {
|
||||
t.Log(stat.TimeFrom, stat.TimeTo, stat.Bytes)
|
||||
t.Log(stat.Day, stat.TimeFrom, stat.TimeTo, stat.Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,6 +354,9 @@ func (this *ServerDAO) UpdateServerBasic(tx *dbs.Tx, serverId int64, name string
|
||||
|
||||
// UpdateServerGroupIds 修改服务所在分组
|
||||
func (this *ServerDAO) UpdateServerGroupIds(tx *dbs.Tx, serverId int64, groupIds []int64) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
if groupIds == nil {
|
||||
groupIds = []int64{}
|
||||
}
|
||||
@@ -390,6 +393,10 @@ func (this *ServerDAO) UpdateUserServerBasic(tx *dbs.Tx, serverId int64, name st
|
||||
|
||||
// UpdateServerIsOn 修复服务是否启用
|
||||
func (this *ServerDAO) UpdateServerIsOn(tx *dbs.Tx, serverId int64, isOn bool) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
|
||||
_, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("isOn", isOn).
|
||||
@@ -896,6 +903,22 @@ func (this *ServerDAO) ListEnabledServersMatch(tx *dbs.Tx, offset int64, size in
|
||||
query.Desc("IF(FIND_IN_SET(bandwidthTime, :times), bandwidthBytes, 0)")
|
||||
query.Param("times", strings.Join(times, ","))
|
||||
query.DescPk()
|
||||
case "requestsAsc":
|
||||
query.Asc("IF(FIND_IN_SET(bandwidthTime, :times), countRequests, 0)")
|
||||
query.Param("times", strings.Join(times, ","))
|
||||
query.DescPk()
|
||||
case "requestsDesc":
|
||||
query.Desc("IF(FIND_IN_SET(bandwidthTime, :times), countRequests, 0)")
|
||||
query.Param("times", strings.Join(times, ","))
|
||||
query.DescPk()
|
||||
case "attackRequestsAsc":
|
||||
query.Asc("IF(FIND_IN_SET(bandwidthTime, :times), countAttackRequests, 0)")
|
||||
query.Param("times", strings.Join(times, ","))
|
||||
query.DescPk()
|
||||
case "attackRequestsDesc":
|
||||
query.Desc("IF(FIND_IN_SET(bandwidthTime, :times), countAttackRequests, 0)")
|
||||
query.Param("times", strings.Join(times, ","))
|
||||
query.DescPk()
|
||||
default:
|
||||
query.DescPk()
|
||||
}
|
||||
@@ -906,6 +929,8 @@ func (this *ServerDAO) ListEnabledServersMatch(tx *dbs.Tx, offset int64, size in
|
||||
for _, server := range result {
|
||||
if len(server.BandwidthTime) > 0 && !lists.ContainsString(times, server.BandwidthTime) {
|
||||
server.BandwidthBytes = 0
|
||||
server.CountRequests = 0
|
||||
server.CountAttackRequests = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2153,6 +2178,10 @@ func (this *ServerDAO) FindFirstHTTPOrHTTPSPortWithClusterId(tx *dbs.Tx, cluster
|
||||
|
||||
// NotifyServerPortsUpdate 通知服务端口变化
|
||||
func (this *ServerDAO) NotifyServerPortsUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
one, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result("tcp", "tls", "udp", "http", "https").
|
||||
@@ -2480,6 +2509,10 @@ func (this *ServerDAO) UpdateServerTrafficLimitStatus(tx *dbs.Tx, trafficLimitCo
|
||||
|
||||
// IncreaseServerTotalTraffic 增加服务的总流量
|
||||
func (this *ServerDAO) IncreaseServerTotalTraffic(tx *dbs.Tx, serverId int64, bytes int64) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
|
||||
var gb = float64(bytes) / (1 << 30)
|
||||
var day = timeutil.Format("Ymd")
|
||||
var month = timeutil.Format("Ym")
|
||||
@@ -2539,6 +2572,10 @@ func (this *ServerDAO) UpdateServersClusterIdWithPlanId(tx *dbs.Tx, planId int64
|
||||
|
||||
// UpdateServerUserPlanId 设置服务所属套餐
|
||||
func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPlanId int64) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
|
||||
oldClusterId, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result("clusterId").
|
||||
@@ -2646,6 +2683,10 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
|
||||
|
||||
// FindServerLastUserPlanIdAndUserId 查找最后使用的套餐
|
||||
func (this *ServerDAO) FindServerLastUserPlanIdAndUserId(tx *dbs.Tx, serverId int64) (userPlanId int64, userId int64, err error) {
|
||||
if serverId <= 0 {
|
||||
return 0, 0, errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
|
||||
one, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result("lastUserPlanId", "userId").
|
||||
@@ -2659,6 +2700,10 @@ func (this *ServerDAO) FindServerLastUserPlanIdAndUserId(tx *dbs.Tx, serverId in
|
||||
|
||||
// UpdateServerUAM 开启UAM
|
||||
func (this *ServerDAO) UpdateServerUAM(tx *dbs.Tx, serverId int64, uamConfig *serverconfigs.UAMConfig) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
|
||||
if uamConfig == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -2710,7 +2755,7 @@ func (this *ServerDAO) FindUserServerClusterIds(tx *dbs.Tx, userId int64) ([]int
|
||||
|
||||
// UpdateServerBandwidth 更新服务带宽
|
||||
// fullTime YYYYMMDDHHII
|
||||
func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTime string, bandwidthBytes int64) error {
|
||||
func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTime string, bandwidthBytes int64, countRequests int64, countAttackRequests int64) error {
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -2731,13 +2776,19 @@ func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTim
|
||||
Pk(serverId).
|
||||
Set("bandwidthTime", fullTime).
|
||||
Set("bandwidthBytes", bandwidthBytes).
|
||||
Set("countRequests", countRequests).
|
||||
Set("countAttackRequests", countAttackRequests).
|
||||
UpdateQuickly()
|
||||
} else {
|
||||
return this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("bandwidthTime", fullTime).
|
||||
Set("bandwidthBytes", dbs.SQL("bandwidthBytes+:bytes")).
|
||||
Set("countRequests", dbs.SQL("countRequests+:countRequests")).
|
||||
Set("countAttackRequests", dbs.SQL("countAttackRequests+:countAttackRequests")).
|
||||
Param("bytes", bandwidthBytes).
|
||||
Param("countRequests", countRequests).
|
||||
Param("countAttackRequests", countAttackRequests).
|
||||
UpdateQuickly()
|
||||
}
|
||||
}
|
||||
@@ -2832,6 +2883,10 @@ func (this *ServerDAO) FindEnabledServersWithIds(tx *dbs.Tx, serverIds []int64)
|
||||
|
||||
// NotifyUpdate 同步服务所在的集群
|
||||
func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 创建任务
|
||||
clusterId, err := this.FindServerClusterId(tx, serverId)
|
||||
if err != nil {
|
||||
@@ -2845,6 +2900,9 @@ func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
|
||||
// NotifyClusterUpdate 同步指定的集群
|
||||
func (this *ServerDAO) NotifyClusterUpdate(tx *dbs.Tx, clusterId, serverId int64) error {
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
if clusterId <= 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -2853,6 +2911,10 @@ func (this *ServerDAO) NotifyClusterUpdate(tx *dbs.Tx, clusterId, serverId int64
|
||||
|
||||
// NotifyDNSUpdate 通知当前集群DNS更新
|
||||
func (this *ServerDAO) NotifyDNSUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
clusterId, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Result("clusterId").
|
||||
@@ -2878,6 +2940,10 @@ func (this *ServerDAO) NotifyDNSUpdate(tx *dbs.Tx, serverId int64) error {
|
||||
|
||||
// NotifyClusterDNSUpdate 通知某个集群中的DNS更新
|
||||
func (this *ServerDAO) NotifyClusterDNSUpdate(tx *dbs.Tx, clusterId int64, serverId int64) error {
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
dnsInfo, err := SharedNodeClusterDAO.FindClusterDNSInfo(tx, clusterId, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -2893,6 +2959,10 @@ func (this *ServerDAO) NotifyClusterDNSUpdate(tx *dbs.Tx, clusterId int64, serve
|
||||
|
||||
// NotifyDisable 通知禁用
|
||||
func (this *ServerDAO) NotifyDisable(tx *dbs.Tx, serverId int64) error {
|
||||
if serverId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 禁用缓存策略相关的内容
|
||||
policyIds, err := SharedHTTPFirewallPolicyDAO.FindFirewallPolicyIdsWithServerId(tx, serverId)
|
||||
if err != nil {
|
||||
|
||||
@@ -229,7 +229,7 @@ func TestServerDAO_FindEnabledServerWithDomain(t *testing.T) {
|
||||
|
||||
for _, domain := range []string{"a", "a.com", "teaos.cn", "www.teaos.cn", "cdn.teaos.cn", "google.com"} {
|
||||
var before = time.Now()
|
||||
server, err := dao.FindEnabledServerWithDomain(tx, domain)
|
||||
server, err := dao.FindEnabledServerWithDomain(tx, 0, domain)
|
||||
var costMs = time.Since(before).Seconds() * 1000
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -326,7 +326,7 @@ func TestServerDAO_FindBool(t *testing.T) {
|
||||
func TestServerDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewServerDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateServerBandwidth(tx, 1, timeutil.FormatTime("YmdHi", time.Now().Unix()/300*300), 1024)
|
||||
err := dao.UpdateServerBandwidth(tx, 1, timeutil.FormatTime("YmdHi", time.Now().Unix()/300*300), 1024, 1, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,57 @@ package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
ServerField_Id dbs.FieldName = "id" // ID
|
||||
ServerField_IsOn dbs.FieldName = "isOn" // 是否启用
|
||||
ServerField_UserId dbs.FieldName = "userId" // 用户ID
|
||||
ServerField_AdminId dbs.FieldName = "adminId" // 管理员ID
|
||||
ServerField_Type dbs.FieldName = "type" // 服务类型
|
||||
ServerField_Name dbs.FieldName = "name" // 名称
|
||||
ServerField_Description dbs.FieldName = "description" // 描述
|
||||
ServerField_PlainServerNames dbs.FieldName = "plainServerNames" // 扁平化域名列表
|
||||
ServerField_ServerNames dbs.FieldName = "serverNames" // 域名列表
|
||||
ServerField_AuditingAt dbs.FieldName = "auditingAt" // 审核提交时间
|
||||
ServerField_AuditingServerNames dbs.FieldName = "auditingServerNames" // 审核中的域名
|
||||
ServerField_IsAuditing dbs.FieldName = "isAuditing" // 是否正在审核
|
||||
ServerField_AuditingResult dbs.FieldName = "auditingResult" // 审核结果
|
||||
ServerField_Http dbs.FieldName = "http" // HTTP配置
|
||||
ServerField_Https dbs.FieldName = "https" // HTTPS配置
|
||||
ServerField_Tcp dbs.FieldName = "tcp" // TCP配置
|
||||
ServerField_Tls dbs.FieldName = "tls" // TLS配置
|
||||
ServerField_Unix dbs.FieldName = "unix" // Unix配置
|
||||
ServerField_Udp dbs.FieldName = "udp" // UDP配置
|
||||
ServerField_WebId dbs.FieldName = "webId" // WEB配置
|
||||
ServerField_ReverseProxy dbs.FieldName = "reverseProxy" // 反向代理配置
|
||||
ServerField_GroupIds dbs.FieldName = "groupIds" // 分组ID列表
|
||||
ServerField_Config dbs.FieldName = "config" // 服务配置,自动生成
|
||||
ServerField_ConfigMd5 dbs.FieldName = "configMd5" // Md5
|
||||
ServerField_ClusterId dbs.FieldName = "clusterId" // 集群ID
|
||||
ServerField_IncludeNodes dbs.FieldName = "includeNodes" // 部署条件
|
||||
ServerField_ExcludeNodes dbs.FieldName = "excludeNodes" // 节点排除条件
|
||||
ServerField_Version dbs.FieldName = "version" // 版本号
|
||||
ServerField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
|
||||
ServerField_State dbs.FieldName = "state" // 状态
|
||||
ServerField_DnsName dbs.FieldName = "dnsName" // DNS名称
|
||||
ServerField_TcpPorts dbs.FieldName = "tcpPorts" // 所包含TCP端口
|
||||
ServerField_UdpPorts dbs.FieldName = "udpPorts" // 所包含UDP端口
|
||||
ServerField_SupportCNAME dbs.FieldName = "supportCNAME" // 允许CNAME不在域名名单
|
||||
ServerField_TrafficLimit dbs.FieldName = "trafficLimit" // 流量限制
|
||||
ServerField_TrafficDay dbs.FieldName = "trafficDay" // YYYYMMDD
|
||||
ServerField_TrafficMonth dbs.FieldName = "trafficMonth" // YYYYMM
|
||||
ServerField_TotalDailyTraffic dbs.FieldName = "totalDailyTraffic" // 日流量
|
||||
ServerField_TotalMonthlyTraffic dbs.FieldName = "totalMonthlyTraffic" // 月流量
|
||||
ServerField_TrafficLimitStatus dbs.FieldName = "trafficLimitStatus" // 流量限制状态
|
||||
ServerField_TotalTraffic dbs.FieldName = "totalTraffic" // 总流量
|
||||
ServerField_UserPlanId dbs.FieldName = "userPlanId" // 所属套餐ID
|
||||
ServerField_LastUserPlanId dbs.FieldName = "lastUserPlanId" // 上一次使用的套餐
|
||||
ServerField_Uam dbs.FieldName = "uam" // UAM设置
|
||||
ServerField_BandwidthTime dbs.FieldName = "bandwidthTime" // 带宽更新时间,YYYYMMDDHHII
|
||||
ServerField_BandwidthBytes dbs.FieldName = "bandwidthBytes" // 最近带宽峰值
|
||||
ServerField_CountAttackRequests dbs.FieldName = "countAttackRequests" // 最近攻击请求数
|
||||
ServerField_CountRequests dbs.FieldName = "countRequests" // 最近总请求数
|
||||
)
|
||||
|
||||
// Server 服务
|
||||
type Server struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
@@ -50,6 +101,8 @@ type Server struct {
|
||||
Uam dbs.JSON `field:"uam"` // UAM设置
|
||||
BandwidthTime string `field:"bandwidthTime"` // 带宽更新时间,YYYYMMDDHHII
|
||||
BandwidthBytes uint64 `field:"bandwidthBytes"` // 最近带宽峰值
|
||||
CountAttackRequests uint64 `field:"countAttackRequests"` // 最近攻击请求数
|
||||
CountRequests uint64 `field:"countRequests"` // 最近总请求数
|
||||
}
|
||||
|
||||
type ServerOperator struct {
|
||||
@@ -99,6 +152,8 @@ type ServerOperator struct {
|
||||
Uam any // UAM设置
|
||||
BandwidthTime any // 带宽更新时间,YYYYMMDDHHII
|
||||
BandwidthBytes any // 最近带宽峰值
|
||||
CountAttackRequests any // 最近攻击请求数
|
||||
CountRequests any // 最近总请求数
|
||||
}
|
||||
|
||||
func NewServerOperator() *ServerOperator {
|
||||
|
||||
@@ -100,7 +100,8 @@ func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, ignore
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn
|
||||
config.ClientAuthType = int(policy.ClientAuthType)
|
||||
config.HTTP2Enabled = policy.Http2Enabled == 1
|
||||
config.HTTP2Enabled = policy.Http2Enabled
|
||||
config.HTTP3Enabled = policy.Http3Enabled
|
||||
config.MinVersion = policy.MinVersion
|
||||
|
||||
// certs
|
||||
@@ -200,7 +201,7 @@ func (this *SSLPolicyDAO) FindAllEnabledPolicyIdsWithCertId(tx *dbs.Tx, certId i
|
||||
}
|
||||
|
||||
// CreatePolicy 创建Policy
|
||||
func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) (int64, error) {
|
||||
func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64, http2Enabled bool, http3Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) (int64, error) {
|
||||
var op = NewSSLPolicyOperator()
|
||||
op.State = SSLPolicyStateEnabled
|
||||
op.IsOn = true
|
||||
@@ -208,6 +209,7 @@ func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64,
|
||||
op.UserId = userId
|
||||
|
||||
op.Http2Enabled = http2Enabled
|
||||
op.Http3Enabled = http3Enabled
|
||||
op.MinVersion = minVersion
|
||||
|
||||
if len(certsJSON) > 0 {
|
||||
@@ -240,7 +242,7 @@ func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64,
|
||||
}
|
||||
|
||||
// UpdatePolicy 修改Policy
|
||||
func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) error {
|
||||
func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled bool, http3Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -248,6 +250,7 @@ func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled
|
||||
var op = NewSSLPolicyOperator()
|
||||
op.Id = policyId
|
||||
op.Http2Enabled = http2Enabled
|
||||
op.Http3Enabled = http3Enabled
|
||||
op.MinVersion = minVersion
|
||||
|
||||
if len(certsJSON) > 0 {
|
||||
|
||||
@@ -7,7 +7,7 @@ type SSLPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Certs dbs.JSON `field:"certs"` // 证书列表
|
||||
ClientCACerts dbs.JSON `field:"clientCACerts"` // 客户端证书
|
||||
ClientAuthType uint32 `field:"clientAuthType"` // 客户端认证类型
|
||||
@@ -15,28 +15,30 @@ type SSLPolicy struct {
|
||||
CipherSuitesIsOn uint8 `field:"cipherSuitesIsOn"` // 是否自定义加密算法套件
|
||||
CipherSuites dbs.JSON `field:"cipherSuites"` // 加密算法套件
|
||||
Hsts dbs.JSON `field:"hsts"` // HSTS设置
|
||||
Http2Enabled uint8 `field:"http2Enabled"` // 是否启用HTTP/2
|
||||
Http2Enabled bool `field:"http2Enabled"` // 是否启用HTTP/2
|
||||
Http3Enabled bool `field:"http3Enabled"` // 是否启用HTTP/3
|
||||
OcspIsOn uint8 `field:"ocspIsOn"` // 是否启用OCSP
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type SSLPolicyOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Certs interface{} // 证书列表
|
||||
ClientCACerts interface{} // 客户端证书
|
||||
ClientAuthType interface{} // 客户端认证类型
|
||||
MinVersion interface{} // 支持的SSL最小版本
|
||||
CipherSuitesIsOn interface{} // 是否自定义加密算法套件
|
||||
CipherSuites interface{} // 加密算法套件
|
||||
Hsts interface{} // HSTS设置
|
||||
Http2Enabled interface{} // 是否启用HTTP/2
|
||||
OcspIsOn interface{} // 是否启用OCSP
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
Id any // ID
|
||||
AdminId any // 管理员ID
|
||||
UserId any // 用户ID
|
||||
IsOn any // 是否启用
|
||||
Certs any // 证书列表
|
||||
ClientCACerts any // 客户端证书
|
||||
ClientAuthType any // 客户端认证类型
|
||||
MinVersion any // 支持的SSL最小版本
|
||||
CipherSuitesIsOn any // 是否自定义加密算法套件
|
||||
CipherSuites any // 加密算法套件
|
||||
Hsts any // HSTS设置
|
||||
Http2Enabled any // 是否启用HTTP/2
|
||||
Http3Enabled any // 是否启用HTTP/3
|
||||
OcspIsOn any // 是否启用OCSP
|
||||
State any // 状态
|
||||
CreatedAt any // 创建时间
|
||||
}
|
||||
|
||||
func NewSSLPolicyOperator() *SSLPolicyOperator {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedNodeClusterTrafficDailyStatDAO.Clean(nil, 30) // 只保留N天
|
||||
err := SharedNodeClusterTrafficDailyStatDAO.CleanDefaultDays(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeClusterTrafficDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -128,11 +129,27 @@ func (this *NodeClusterTrafficDailyStatDAO) SumDailyStat(tx *dbs.Tx, clusterId i
|
||||
return one.(*NodeClusterTrafficDailyStat), nil
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *NodeClusterTrafficDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理历史数据
|
||||
func (this *NodeClusterTrafficDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *NodeClusterTrafficDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.NodeClusterTrafficDailyStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.NodeClusterTrafficDailyStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 30
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedNodeTrafficHourlyStatDAO.Clean(nil, 15) // 只保留N天
|
||||
err := SharedNodeTrafficHourlyStatDAO.CleanDefaultDays(nil, 15) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeTrafficHourlyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -197,11 +198,27 @@ func (this *NodeTrafficHourlyStatDAO) FindHourlyStatsWithNodeId(tx *dbs.Tx, role
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *NodeTrafficHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理历史数据
|
||||
func (this *NodeTrafficHourlyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("hour", hour).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *NodeTrafficHourlyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.NodeTrafficHourlyStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.NodeTrafficHourlyStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 15
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
@@ -25,7 +26,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerDomainHourlyStatDAO.Clean(nil, 7) // 只保留 N 天
|
||||
err := SharedServerDomainHourlyStatDAO.CleanDefaultDays(nil, 7) // 只保留 N 天
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerDomainHourlyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -366,8 +367,8 @@ func (this *ServerDomainHourlyStatDAO) FindTopDomainStatsWithServerId(tx *dbs.Tx
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *ServerDomainHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理历史数据
|
||||
func (this *ServerDomainHourlyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
|
||||
for _, table := range this.FindAllPartitionTables() {
|
||||
_, err := this.Query(tx).
|
||||
@@ -380,3 +381,19 @@ func (this *ServerDomainHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ServerDomainHourlyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.ServerDomainHourlyStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.ServerDomainHourlyStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 7
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedTrafficDailyStatDAO.Clean(nil, 30) // 只保留N天
|
||||
err := SharedTrafficDailyStatDAO.CleanDefaultDays(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("TrafficDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -124,11 +125,27 @@ func (this *TrafficDailyStatDAO) FindDailyStat(tx *dbs.Tx, day string) (*Traffic
|
||||
return one.(*TrafficDailyStat), nil
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *TrafficDailyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理历史数据
|
||||
func (this *TrafficDailyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *TrafficDailyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.TrafficDailyStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.TrafficDailyStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 30
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedTrafficHourlyStatDAO.Clean(nil, 15) // 只保留N天
|
||||
err := SharedTrafficHourlyStatDAO.CleanDefaultDays(nil, 15) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("TrafficHourlyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -137,11 +138,27 @@ func (this *TrafficHourlyStatDAO) SumHourlyStats(tx *dbs.Tx, hourFrom string, ho
|
||||
return one.(*TrafficHourlyStat), nil
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *TrafficHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
// CleanDays 清理历史数据
|
||||
func (this *TrafficHourlyStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("hour", hour).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *TrafficHourlyStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := models.SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.TrafficHourlyStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.TrafficHourlyStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 15
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/zero"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SysLockerDAO dbs.DAO
|
||||
|
||||
// concurrent transactions control
|
||||
// 考虑到存在多个API节点的可能性,容量不能太大,也不能使用mutex
|
||||
var sysLockerConcurrentLimiter = make(chan zero.Zero, 8)
|
||||
|
||||
func NewSysLockerDAO() *SysLockerDAO {
|
||||
return dbs.NewDAO(&SysLockerDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
@@ -114,9 +121,20 @@ func (this *SysLockerDAO) Unlock(tx *dbs.Tx, key string) error {
|
||||
|
||||
// Increase 增加版本号
|
||||
func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (int64, error) {
|
||||
// validate key
|
||||
if strings.Contains(key, "'") {
|
||||
return 0, errors.New("invalid key '" + key + "'")
|
||||
}
|
||||
|
||||
if tx == nil {
|
||||
var result int64
|
||||
var err error
|
||||
|
||||
sysLockerConcurrentLimiter <- zero.Zero{} // push
|
||||
defer func() {
|
||||
<-sysLockerConcurrentLimiter // pop
|
||||
}()
|
||||
|
||||
err = this.Instance.RunTx(func(tx *dbs.Tx) error {
|
||||
result, err = this.Increase(tx, key, defaultValue)
|
||||
if err != nil {
|
||||
@@ -126,7 +144,22 @@ func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
err := this.Query(tx).
|
||||
|
||||
// combine statements to make increasing faster
|
||||
colValue, err := tx.FindCol(0, "INSERT INTO `"+this.Table+"` (`key`, `version`) VALUES ('"+key+"', "+types.String(defaultValue)+") ON DUPLICATE KEY UPDATE `version`=`version`+1; SELECT `version` FROM `"+this.Table+"` WHERE `key`='"+key+"'")
|
||||
if err != nil {
|
||||
if CheckSQLErrCode(err, 1064 /** syntax error **/) {
|
||||
// continue to use seperated query
|
||||
err = nil
|
||||
} else {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
return types.Int64(colValue), nil
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Reuse(false). // no need to prepare statement in every transaction
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"key": key,
|
||||
"version": defaultValue,
|
||||
@@ -137,16 +170,16 @@ func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (
|
||||
return 0, err
|
||||
}
|
||||
return this.Query(tx).
|
||||
Reuse(false). // no need to prepare statement in every transaction
|
||||
Attr("key", key).
|
||||
Result("version").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
|
||||
// 读取当前版本号
|
||||
func (this *SysLockerDAO) Read(tx *dbs.Tx, key string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("key", key).
|
||||
Result("version").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,44 +3,146 @@ package models
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSysLockerDAO_Lock(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
|
||||
isOk, err := SharedSysLockerDAO.Lock(tx, "test", 600)
|
||||
var dao = NewSysLockerDAO()
|
||||
|
||||
isOk, err := dao.Lock(tx, "test", 600)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(isOk)
|
||||
|
||||
if isOk {
|
||||
err = SharedSysLockerDAO.Unlock(tx, "test")
|
||||
err = dao.Unlock(tx, "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSysLocker_Increase_SQL(t *testing.T) {
|
||||
var dao = NewSysLockerDAO()
|
||||
value, err := dao.Read(nil, "hello")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("before:", value)
|
||||
v, err := dao.Increase(nil, "hello", 0)
|
||||
if err != nil {
|
||||
t.Log("err:", err)
|
||||
return
|
||||
}
|
||||
t.Log("after:", v)
|
||||
}
|
||||
|
||||
func TestSysLocker_Increase(t *testing.T) {
|
||||
count := 100
|
||||
wg := sync.WaitGroup{}
|
||||
dbs.NotifyReady()
|
||||
|
||||
var count = 1000
|
||||
|
||||
var dao = NewSysLockerDAO()
|
||||
value, err := dao.Read(nil, "hello")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("before", value)
|
||||
|
||||
var locker = sync.Mutex{}
|
||||
var allValueMap = map[int64]bool{}
|
||||
|
||||
var before = time.Now()
|
||||
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
go func() {
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
v, err := NewSysLockerDAO().Increase(nil, "hello", 0)
|
||||
|
||||
var key = "hello"
|
||||
v, err := dao.Increase(nil, key, 0)
|
||||
if err != nil {
|
||||
t.Log("err:", err)
|
||||
return
|
||||
}
|
||||
t.Log("v:", v)
|
||||
}()
|
||||
|
||||
locker.Lock()
|
||||
if allValueMap[v] {
|
||||
t.Log("duplicated:", v)
|
||||
} else {
|
||||
allValueMap[v] = true
|
||||
}
|
||||
locker.Unlock()
|
||||
|
||||
//t.Log("v:", v)
|
||||
_ = v
|
||||
}(i)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
t.Log("ok")
|
||||
|
||||
t.Log("cost:", time.Since(before).Seconds()*1000, "ms")
|
||||
|
||||
value, err = dao.Read(nil, "hello")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log("after", value, "values:", len(allValueMap))
|
||||
}
|
||||
|
||||
func TestSysLocker_Increase_Performance(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var count = 1000
|
||||
|
||||
var dao = NewSysLockerDAO()
|
||||
|
||||
var before = time.Now()
|
||||
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
|
||||
var key = "hello" + types.String(i%10)
|
||||
v, err := dao.Increase(nil, key, 0)
|
||||
if err != nil {
|
||||
t.Log("err:", err)
|
||||
return
|
||||
}
|
||||
//t.Log("v:", v)
|
||||
_ = v
|
||||
}(i)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
t.Log("cost:", time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
|
||||
func BenchmarkSysLockerDAO_Increase(b *testing.B) {
|
||||
var dao = NewSysLockerDAO()
|
||||
_, _ = dao.Increase(nil, "hello", 0)
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, err := dao.Increase(nil, "hello", 0)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -262,3 +262,20 @@ func (this *SysSettingDAO) ReadUserRegisterConfig(tx *dbs.Tx) (*userconfigs.User
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (this *SysSettingDAO) ReadDatabaseConfig(tx *dbs.Tx) (config *systemconfigs.DatabaseConfig, err error) {
|
||||
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeDatabaseConfigSetting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(valueJSON) == 0 {
|
||||
return systemconfigs.NewDatabaseConfig(), nil
|
||||
}
|
||||
|
||||
config = systemconfigs.NewDatabaseConfig()
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func init() {
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedUserBandwidthStatDAO.Clean(nil)
|
||||
err := SharedUserBandwidthStatDAO.CleanDefaultDays(nil, 100)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedUserBandwidthStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
@@ -460,9 +460,9 @@ func (this *UserBandwidthStatDAO) SumDailyStat(tx *dbs.Tx, userId int64, regionI
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理过期数据
|
||||
func (this *UserBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -100)) // 保留大约3个月的数据
|
||||
// CleanDays 清理过期数据
|
||||
func (this *UserBandwidthStatDAO) CleanDays(tx *dbs.Tx, days int) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days)) // 保留大约3个月的数据
|
||||
return this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
@@ -472,6 +472,22 @@ func (this *UserBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (this *UserBandwidthStatDAO) CleanDefaultDays(tx *dbs.Tx, defaultDays int) error {
|
||||
databaseConfig, err := SharedSysSettingDAO.ReadDatabaseConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if databaseConfig != nil && databaseConfig.UserBandwidthStat.Clean.Days > 0 {
|
||||
defaultDays = databaseConfig.UserBandwidthStat.Clean.Days
|
||||
}
|
||||
if defaultDays <= 0 {
|
||||
defaultDays = 100
|
||||
}
|
||||
|
||||
return this.CleanDays(tx, defaultDays)
|
||||
}
|
||||
|
||||
// 批量执行
|
||||
func (this *UserBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
|
||||
@@ -57,10 +57,10 @@ func TestUserBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestUserBandwidthStatDAO_Clean(t *testing.T) {
|
||||
func TestUserBandwidthStatDAO_CleanDays(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.Clean(tx)
|
||||
err := dao.CleanDays(tx, 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,42 @@ package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
const (
|
||||
UserField_Id dbs.FieldName = "id" // ID
|
||||
UserField_IsOn dbs.FieldName = "isOn" // 是否启用
|
||||
UserField_Username dbs.FieldName = "username" // 用户名
|
||||
UserField_Password dbs.FieldName = "password" // 密码
|
||||
UserField_Fullname dbs.FieldName = "fullname" // 真实姓名
|
||||
UserField_Mobile dbs.FieldName = "mobile" // 手机号
|
||||
UserField_VerifiedMobile dbs.FieldName = "verifiedMobile" // 已验证手机号
|
||||
UserField_Tel dbs.FieldName = "tel" // 联系电话
|
||||
UserField_Remark dbs.FieldName = "remark" // 备注
|
||||
UserField_Email dbs.FieldName = "email" // 邮箱地址
|
||||
UserField_VerifiedEmail dbs.FieldName = "verifiedEmail" // 激活后的邮箱
|
||||
UserField_EmailIsVerified dbs.FieldName = "emailIsVerified" // 邮箱是否已验证
|
||||
UserField_AvatarFileId dbs.FieldName = "avatarFileId" // 头像文件ID
|
||||
UserField_CreatedAt dbs.FieldName = "createdAt" // 创建时间
|
||||
UserField_Day dbs.FieldName = "day" // YYYYMMDD
|
||||
UserField_UpdatedAt dbs.FieldName = "updatedAt" // 修改时间
|
||||
UserField_State dbs.FieldName = "state" // 状态
|
||||
UserField_Source dbs.FieldName = "source" // 来源
|
||||
UserField_ClusterId dbs.FieldName = "clusterId" // 集群ID
|
||||
UserField_Features dbs.FieldName = "features" // 允许操作的特征
|
||||
UserField_RegisteredIP dbs.FieldName = "registeredIP" // 注册使用的IP
|
||||
UserField_IsRejected dbs.FieldName = "isRejected" // 是否已拒绝
|
||||
UserField_RejectReason dbs.FieldName = "rejectReason" // 拒绝理由
|
||||
UserField_IsVerified dbs.FieldName = "isVerified" // 是否验证通过
|
||||
UserField_RequirePlans dbs.FieldName = "requirePlans" // 是否需要购买套餐
|
||||
UserField_Modules dbs.FieldName = "modules" // 用户模块
|
||||
UserField_PriceType dbs.FieldName = "priceType" // 计费类型:traffic|bandwidth
|
||||
UserField_PricePeriod dbs.FieldName = "pricePeriod" // 结算周期
|
||||
UserField_ServersEnabled dbs.FieldName = "serversEnabled" // 是否禁用所有服务
|
||||
UserField_Notification dbs.FieldName = "notification" // 通知设置
|
||||
UserField_BandwidthAlgo dbs.FieldName = "bandwidthAlgo" // 带宽算法
|
||||
UserField_BandwidthModifier dbs.FieldName = "bandwidthModifier" // 带宽修正值
|
||||
UserField_Lang dbs.FieldName = "lang" // 语言代号
|
||||
)
|
||||
|
||||
// User 用户
|
||||
type User struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
@@ -36,6 +72,7 @@ type User struct {
|
||||
Notification dbs.JSON `field:"notification"` // 通知设置
|
||||
BandwidthAlgo string `field:"bandwidthAlgo"` // 带宽算法
|
||||
BandwidthModifier float64 `field:"bandwidthModifier"` // 带宽修正值
|
||||
Lang string `field:"lang"` // 语言代号
|
||||
}
|
||||
|
||||
type UserOperator struct {
|
||||
@@ -71,6 +108,7 @@ type UserOperator struct {
|
||||
Notification any // 通知设置
|
||||
BandwidthAlgo any // 带宽算法
|
||||
BandwidthModifier any // 带宽修正值
|
||||
Lang any // 语言代号
|
||||
}
|
||||
|
||||
func NewUserOperator() *UserOperator {
|
||||
|
||||
@@ -280,6 +280,7 @@ func (this *UserNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *
|
||||
func (this *UserNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(UserNodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where("status IS NOT NULL").
|
||||
Where("(JSON_EXTRACT(status, '$.buildVersionCode') IS NULL OR JSON_EXTRACT(status, '$.buildVersionCode')<:version)").
|
||||
Param("version", utils.VersionToLong(version)).
|
||||
|
||||
@@ -80,3 +80,12 @@ func CheckSQLDuplicateErr(err error) bool {
|
||||
}
|
||||
return CheckSQLErrCode(err, 1062)
|
||||
}
|
||||
|
||||
// IsMySQLError Check error is MySQLError
|
||||
func IsMySQLError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
_, ok := err.(*mysql.MySQLError)
|
||||
return ok
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
package dbutils
|
||||
|
||||
import (
|
||||
executils "github.com/TeaOSLab/EdgeAPI/internal/utils/exec"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewQuery 构造Query
|
||||
@@ -127,3 +135,79 @@ func MySQLVersionFrom8() (bool, error) {
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// FindMySQLPath find out mysqld_safe path from system processes
|
||||
func FindMySQLPath() string {
|
||||
psExe, err := executils.LookPath("ps")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var cmd = executils.NewTimeoutCmd(3*time.Second, psExe, "-ef").
|
||||
WithStdout().
|
||||
WithStderr()
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var reg = regexp.MustCompile(`\s(/\S+/mysqld_safe)\s`)
|
||||
var matches = reg.FindStringSubmatch(cmd.Stdout())
|
||||
if len(matches) > 1 {
|
||||
var path = matches[1]
|
||||
_, err = os.Stat(path)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// FindMySQLPathAndRemember find out mysqld_safe path then remember it for future usage
|
||||
func FindMySQLPathAndRemember() {
|
||||
var path = FindMySQLPath()
|
||||
if len(path) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var cacheFile = Tea.Root + "/data/mysql-path.cache"
|
||||
_ = os.WriteFile(cacheFile, []byte(path), 0666) // ignore error
|
||||
}
|
||||
|
||||
// StartLocalMySQL try to start local mysql server
|
||||
func StartLocalMySQL() {
|
||||
// possible installed paths
|
||||
var mysqldSafeFiles = []string{}
|
||||
|
||||
// read last path from cache file
|
||||
var cacheFile = Tea.Root + "/data/mysql-path.cache"
|
||||
cacheData, err := os.ReadFile(cacheFile)
|
||||
if err == nil && len(cacheData) > 0 {
|
||||
mysqldSafeFiles = append(mysqldSafeFiles, string(cacheData))
|
||||
}
|
||||
|
||||
// from $PATH variable
|
||||
exePath, lookErr := executils.LookPath("mysqld_safe")
|
||||
if lookErr == nil && len(exePath) > 0 && !lists.ContainsString(mysqldSafeFiles, exePath) {
|
||||
mysqldSafeFiles = append(mysqldSafeFiles, exePath)
|
||||
}
|
||||
|
||||
// these installed by edge-boot or foolish-mysql
|
||||
for _, path := range []string{
|
||||
"/usr/local/mysql/bin/mysqld_safe",
|
||||
"/usr/local/mysql8/bin/mysqld_safe",
|
||||
} {
|
||||
if !lists.ContainsString(mysqldSafeFiles, path) {
|
||||
mysqldSafeFiles = append(mysqldSafeFiles, path)
|
||||
}
|
||||
}
|
||||
|
||||
for _, mysqldSafeFile := range mysqldSafeFiles {
|
||||
_, err := os.Stat(mysqldSafeFile)
|
||||
if err == nil {
|
||||
logs.Println("[API_NODE]try to start local mysql server from '" + mysqldSafeFile + "' ...")
|
||||
var mysqlCmd = exec.Command(mysqldSafeFile)
|
||||
_ = mysqlCmd.Start()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,3 +35,11 @@ func TestMySQLVersion(t *testing.T) {
|
||||
func TestMySQLVersionFrom8(t *testing.T) {
|
||||
t.Log(dbutils.MySQLVersionFrom8())
|
||||
}
|
||||
|
||||
func TestFindMySQLPath(t *testing.T) {
|
||||
t.Log(dbutils.FindMySQLPath())
|
||||
}
|
||||
|
||||
func TestStartLocalMySQL(t *testing.T) {
|
||||
dbutils.StartLocalMySQL()
|
||||
}
|
||||
@@ -37,8 +37,8 @@ func (this *Unzip) Run() error {
|
||||
}()
|
||||
|
||||
for _, file := range reader.File {
|
||||
info := file.FileInfo()
|
||||
target := this.targetDir + "/" + file.Name
|
||||
var info = file.FileInfo()
|
||||
var target = this.targetDir + "/" + file.Name
|
||||
|
||||
// 目录
|
||||
if info.IsDir() {
|
||||
@@ -62,7 +62,7 @@ func (this *Unzip) Run() error {
|
||||
}
|
||||
|
||||
// 文件
|
||||
err := func(file *zip.File, target string) error {
|
||||
err = func(file *zip.File, target string) error {
|
||||
fileReader, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -71,6 +71,10 @@ func (this *Unzip) Run() error {
|
||||
_ = fileReader.Close()
|
||||
}()
|
||||
|
||||
// remove old
|
||||
_ = os.Remove(target)
|
||||
|
||||
// create new
|
||||
fileWriter, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, file.FileInfo().Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/status"
|
||||
"gopkg.in/yaml.v3"
|
||||
"log"
|
||||
"net"
|
||||
@@ -294,6 +295,9 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err
|
||||
func (this *APINode) checkDB() error {
|
||||
logs.Println("[API_NODE]checking database connection ...")
|
||||
|
||||
// lookup mysqld_safe process
|
||||
go dbutils.FindMySQLPathAndRemember()
|
||||
|
||||
db, err := dbs.Default()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -310,13 +314,7 @@ func (this *APINode) checkDB() error {
|
||||
if strings.Contains(err.Error(), "connection refused") {
|
||||
config, _ := db.Config()
|
||||
if config != nil && (strings.Contains(config.Dsn, "tcp(127.0.0.1:") || strings.Contains(config.Dsn, "tcp(localhost:")) && os.Getgid() == 0 /** ROOT 用户 **/ {
|
||||
var mysqldSafeFile = "/usr/local/mysql/bin/mysqld_safe"
|
||||
_, err = os.Stat(mysqldSafeFile)
|
||||
if err == nil {
|
||||
logs.Println("[API_NODE]try to start local mysql server from '" + mysqldSafeFile + "' ...")
|
||||
var mysqlCmd = exec.Command(mysqldSafeFile)
|
||||
_ = mysqlCmd.Start()
|
||||
}
|
||||
dbutils.StartLocalMySQL()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -832,7 +830,12 @@ func (this *APINode) unaryInterceptor(ctx context.Context, req any, info *grpc.U
|
||||
}
|
||||
result, err := handler(ctx, req)
|
||||
if err != nil {
|
||||
err = errors.New("'" + info.FullMethod + "()' says: " + err.Error())
|
||||
statusErr, ok := status.FromError(err)
|
||||
if ok {
|
||||
err = status.Error(statusErr.Code(), "'"+info.FullMethod+"()' says: "+err.Error())
|
||||
} else {
|
||||
err = errors.New("'" + info.FullMethod + "()' says: " + err.Error())
|
||||
}
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ func (this *AdminService) FindAllAdminModules(ctx context.Context, req *pb.FindA
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := []*pb.AdminModuleList{}
|
||||
var result = []*pb.AdminModuleList{}
|
||||
for _, admin := range admins {
|
||||
modules := []*systemconfigs.AdminModule{}
|
||||
if len(admin.Modules) > 0 {
|
||||
@@ -292,7 +292,7 @@ func (this *AdminService) FindAllAdminModules(ctx context.Context, req *pb.FindA
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
pbModules := []*pb.AdminModule{}
|
||||
var pbModules = []*pb.AdminModule{}
|
||||
for _, module := range modules {
|
||||
pbModules = append(pbModules, &pb.AdminModule{
|
||||
AllowAll: module.AllowAll,
|
||||
@@ -301,11 +301,12 @@ func (this *AdminService) FindAllAdminModules(ctx context.Context, req *pb.FindA
|
||||
})
|
||||
}
|
||||
|
||||
list := &pb.AdminModuleList{
|
||||
var list = &pb.AdminModuleList{
|
||||
AdminId: int64(admin.Id),
|
||||
IsSuper: admin.IsSuper,
|
||||
Fullname: admin.Fullname,
|
||||
Theme: admin.Theme,
|
||||
Lang: admin.Lang,
|
||||
Modules: pbModules,
|
||||
}
|
||||
result = append(result, list)
|
||||
|
||||
@@ -240,7 +240,7 @@ func (this *APINodeService) FindEnabledAPINode(ctx context.Context, req *pb.Find
|
||||
|
||||
// FindCurrentAPINodeVersion 获取当前API节点的版本
|
||||
func (this *APINodeService) FindCurrentAPINodeVersion(ctx context.Context, req *pb.FindCurrentAPINodeVersionRequest) (*pb.FindCurrentAPINodeVersionResponse, error) {
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx)
|
||||
role, _, _, err := rpcutils.ValidateRequest(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -249,6 +249,7 @@ func (this *APINodeService) FindCurrentAPINodeVersion(ctx context.Context, req *
|
||||
Version: teaconst.Version,
|
||||
Os: runtime.GOOS,
|
||||
Arch: runtime.GOARCH,
|
||||
Role: role,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ import (
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type BaseService struct {
|
||||
@@ -229,7 +231,7 @@ func (this *BaseService) PermissionError() error {
|
||||
}
|
||||
|
||||
func (this *BaseService) NotImplementedYet() error {
|
||||
return errors.New("not implemented yet")
|
||||
return status.Error(codes.Unimplemented, "not implemented yet")
|
||||
}
|
||||
|
||||
// NullTx 空的数据库事务
|
||||
|
||||
@@ -303,7 +303,24 @@ func (this *DNSDomainService) SyncDNSDomainData(ctx context.Context, req *pb.Syn
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.syncClusterDNS(req)
|
||||
|
||||
var latestVersion = dns.SharedDNSTaskDAO.GenerateVersion()
|
||||
|
||||
resp, err := this.syncClusterDNS(req)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// 标记集群所有任务已完成
|
||||
if req.NodeClusterId > 0 && resp != nil && resp.IsOk {
|
||||
var tx = this.NullTx()
|
||||
err = dns.SharedDNSTaskDAO.UpdateClusterDNSTasksDone(tx, req.NodeClusterId, latestVersion)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// FindAllDNSDomainRoutes 查看支持的线路
|
||||
|
||||
@@ -117,3 +117,19 @@ func (this *DNSTaskService) DeleteDNSTask(ctx context.Context, req *pb.DeleteDNS
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteAllDNSTasks 删除所有同步任务
|
||||
func (this *DNSTaskService) DeleteAllDNSTasks(ctx context.Context, req *pb.DeleteAllDNSTasksRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = dns.SharedDNSTaskDAO.DeleteAllDNSTasks(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func (this *HTTPCachePolicyService) CreateHTTPCachePolicy(ctx context.Context, r
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
policyId, err := models.SharedHTTPCachePolicyDAO.CreateCachePolicy(tx, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxKeys, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
|
||||
policyId, err := models.SharedHTTPCachePolicyDAO.CreateCachePolicy(tx, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (this *HTTPCachePolicyService) UpdateHTTPCachePolicy(ctx context.Context, r
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedHTTPCachePolicyDAO.UpdateCachePolicy(tx, req.HttpCachePolicyId, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxKeys, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
|
||||
err = models.SharedHTTPCachePolicyDAO.UpdateCachePolicy(tx, req.HttpCachePolicyId, req.IsOn, req.Name, req.Description, req.CapacityJSON, req.MaxSizeJSON, req.Type, req.OptionsJSON, req.SyncCompressionCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
@@ -22,6 +25,34 @@ func (this *HTTPPageService) CreateHTTPPage(ctx context.Context, req *pb.CreateH
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// validate
|
||||
const maxURLLength = 512
|
||||
const maxBodyLength = 32 * 1024
|
||||
|
||||
switch req.BodyType {
|
||||
case shared.BodyTypeURL:
|
||||
if len(req.Url) > maxURLLength {
|
||||
return nil, errors.New("'url' too long")
|
||||
}
|
||||
if !regexputils.HTTPProtocol.MatchString(req.Url) {
|
||||
return nil, errors.New("invalid 'url' format")
|
||||
}
|
||||
|
||||
if len(req.Body) > maxBodyLength { // we keep short body for user experience
|
||||
req.Body = ""
|
||||
}
|
||||
case shared.BodyTypeHTML:
|
||||
if len(req.Body) > maxBodyLength {
|
||||
return nil, errors.New("'body' too long")
|
||||
}
|
||||
|
||||
if len(req.Url) > maxURLLength { // we keep short url for user experience
|
||||
req.Url = ""
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("invalid 'bodyType': " + req.BodyType)
|
||||
}
|
||||
|
||||
pageId, err := models.SharedHTTPPageDAO.CreatePage(tx, userId, req.StatusList, req.BodyType, req.Url, req.Body, types.Int(req.NewStatus))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -46,6 +77,34 @@ func (this *HTTPPageService) UpdateHTTPPage(ctx context.Context, req *pb.UpdateH
|
||||
}
|
||||
}
|
||||
|
||||
// validate
|
||||
const maxURLLength = 512
|
||||
const maxBodyLength = 32 * 1024
|
||||
|
||||
switch req.BodyType {
|
||||
case shared.BodyTypeURL:
|
||||
if len(req.Url) > maxURLLength {
|
||||
return nil, errors.New("'url' too long")
|
||||
}
|
||||
if !regexputils.HTTPProtocol.MatchString(req.Url) {
|
||||
return nil, errors.New("invalid 'url' format")
|
||||
}
|
||||
|
||||
if len(req.Body) > maxBodyLength { // we keep short body for user experience
|
||||
req.Body = ""
|
||||
}
|
||||
case shared.BodyTypeHTML:
|
||||
if len(req.Body) > maxBodyLength {
|
||||
return nil, errors.New("'body' too long")
|
||||
}
|
||||
|
||||
if len(req.Url) > maxURLLength { // we keep short url for user experience
|
||||
req.Url = ""
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("invalid 'bodyType': " + req.BodyType)
|
||||
}
|
||||
|
||||
err = models.SharedHTTPPageDAO.UpdatePage(tx, req.HttpPageId, req.StatusList, req.BodyType, req.Url, req.Body, types.Int(req.NewStatus))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -15,14 +15,14 @@ type HTTPRewriteRuleService struct {
|
||||
// CreateHTTPRewriteRule 创建重写规则
|
||||
func (this *HTTPRewriteRuleService) CreateHTTPRewriteRule(ctx context.Context, req *pb.CreateHTTPRewriteRuleRequest) (*pb.CreateHTTPRewriteRuleResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
rewriteRuleId, err := models.SharedHTTPRewriteRuleDAO.CreateRewriteRule(tx, req.Pattern, req.Replace, req.Mode, types.Int(req.RedirectStatus), req.IsBreak, req.ProxyHost, req.WithQuery, req.IsOn, req.CondsJSON)
|
||||
rewriteRuleId, err := models.SharedHTTPRewriteRuleDAO.CreateRewriteRule(tx, userId, req.Pattern, req.Replace, req.Mode, types.Int(req.RedirectStatus), req.IsBreak, req.ProxyHost, req.WithQuery, req.IsOn, req.CondsJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -33,12 +33,18 @@ func (this *HTTPRewriteRuleService) CreateHTTPRewriteRule(ctx context.Context, r
|
||||
// UpdateHTTPRewriteRule 修改重写规则
|
||||
func (this *HTTPRewriteRuleService) UpdateHTTPRewriteRule(ctx context.Context, req *pb.UpdateHTTPRewriteRuleRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedHTTPRewriteRuleDAO.CheckUserRewriteRule(tx, userId, req.RewriteRuleId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedHTTPRewriteRuleDAO.UpdateRewriteRule(tx, req.RewriteRuleId, req.Pattern, req.Replace, req.Mode, types.Int(req.RedirectStatus), req.IsBreak, req.ProxyHost, req.WithQuery, req.IsOn, req.CondsJSON)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
@@ -109,6 +111,8 @@ func (this *HTTPWebService) UpdateHTTPWeb(ctx context.Context, req *pb.UpdateHTT
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.RootJSON = []byte("{}") // 为了安全
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
@@ -139,7 +143,60 @@ func (this *HTTPWebService) UpdateHTTPWebCompression(ctx context.Context, req *p
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedHTTPWebDAO.UpdateWebCompression(tx, req.HttpWebId, req.CompressionJSON)
|
||||
if len(req.CompressionJSON) == 0 {
|
||||
return nil, errors.New("'compressionJSON' should not be empty")
|
||||
}
|
||||
var compressionConfig = &serverconfigs.HTTPCompressionConfig{}
|
||||
err = json.Unmarshal(req.CompressionJSON, compressionConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = compressionConfig.Init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = models.SharedHTTPWebDAO.UpdateWebCompression(tx, req.HttpWebId, compressionConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateHTTPWebOptimization 修改页面优化配置
|
||||
func (this *HTTPWebService) UpdateHTTPWebOptimization(ctx context.Context, req *pb.UpdateHTTPWebOptimizationRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
// 检查用户权限
|
||||
err = models.SharedHTTPWebDAO.CheckUserWeb(nil, userId, req.HttpWebId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
if len(req.OptimizationJSON) == 0 {
|
||||
return nil, errors.New("invalid 'optimizationJSON'")
|
||||
}
|
||||
var optimizationConfig = serverconfigs.NewHTTPPageOptimizationConfig()
|
||||
err = json.Unmarshal(req.OptimizationJSON, optimizationConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = optimizationConfig.Init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = models.SharedHTTPWebDAO.UpdateWebOptimization(tx, req.HttpWebId, optimizationConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -292,8 +349,53 @@ func (this *HTTPWebService) UpdateHTTPWebShutdown(ctx context.Context, req *pb.U
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var newShutdownJSON = req.ShutdownJSON
|
||||
if len(req.ShutdownJSON) > 0 {
|
||||
const maxURLLength = 512
|
||||
const maxBodyLength = 32 * 1024
|
||||
|
||||
err = models.SharedHTTPWebDAO.UpdateWebShutdown(tx, req.HttpWebId, req.ShutdownJSON)
|
||||
var shutdownConfig = &serverconfigs.HTTPShutdownConfig{}
|
||||
err = json.Unmarshal(req.ShutdownJSON, shutdownConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = shutdownConfig.Init()
|
||||
if err != nil {
|
||||
return nil, errors.New("validate config failed: " + err.Error())
|
||||
}
|
||||
|
||||
switch shutdownConfig.BodyType {
|
||||
case shared.BodyTypeURL:
|
||||
if len(shutdownConfig.URL) > maxURLLength {
|
||||
return nil, errors.New("'url' too long")
|
||||
}
|
||||
if !regexputils.HTTPProtocol.MatchString(shutdownConfig.URL) {
|
||||
return nil, errors.New("invalid 'url' format")
|
||||
}
|
||||
|
||||
if len(shutdownConfig.Body) > maxBodyLength { // we keep short body for user experience
|
||||
shutdownConfig.Body = ""
|
||||
}
|
||||
case shared.BodyTypeHTML:
|
||||
if len(shutdownConfig.Body) > maxBodyLength {
|
||||
return nil, errors.New("'body' too long")
|
||||
}
|
||||
|
||||
if len(shutdownConfig.URL) > maxURLLength { // we keep short url for user experience
|
||||
shutdownConfig.URL = ""
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New("invalid 'bodyType': " + shutdownConfig.BodyType)
|
||||
}
|
||||
|
||||
newShutdownJSON, err = json.Marshal(shutdownConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedHTTPWebDAO.UpdateWebShutdown(tx, req.HttpWebId, newShutdownJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -319,14 +421,23 @@ func (this *HTTPWebService) UpdateHTTPWebPages(ctx context.Context, req *pb.Upda
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查配置
|
||||
var pages = []*serverconfigs.HTTPPageConfig{}
|
||||
err = json.Unmarshal(req.PagesJSON, &pages)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode 'pages' failed: " + err.Error())
|
||||
}
|
||||
var newPages = []*serverconfigs.HTTPPageConfig{}
|
||||
for _, page := range pages {
|
||||
newPages = append(newPages, &serverconfigs.HTTPPageConfig{Id: page.Id})
|
||||
if len(req.PagesJSON) > 0 {
|
||||
var pages = []*serverconfigs.HTTPPageConfig{}
|
||||
err = json.Unmarshal(req.PagesJSON, &pages)
|
||||
|
||||
for _, page := range pages {
|
||||
err = page.Init()
|
||||
if err != nil {
|
||||
return nil, errors.New("validate page failed: " + err.Error())
|
||||
}
|
||||
|
||||
// reset not needed fields, keep "id" reference only
|
||||
page.URL = ""
|
||||
page.Body = ""
|
||||
|
||||
newPages = append(newPages, &serverconfigs.HTTPPageConfig{Id: page.Id})
|
||||
}
|
||||
}
|
||||
newPagesJSON, err := json.Marshal(newPages)
|
||||
if err != nil {
|
||||
|
||||
@@ -309,7 +309,7 @@ func (this *IPLibraryFileService) CheckCountriesWithIPLibraryFileId(ctx context.
|
||||
}
|
||||
for _, similarCountry := range similarCountries {
|
||||
pbMissingCountry.SimilarCountries = append(pbMissingCountry.SimilarCountries, &pb.RegionCountry{
|
||||
Id: int64(similarCountry.Id),
|
||||
Id: int64(similarCountry.ValueId),
|
||||
Name: similarCountry.Name,
|
||||
DisplayName: similarCountry.DisplayName(),
|
||||
})
|
||||
@@ -391,7 +391,7 @@ func (this *IPLibraryFileService) CheckProvincesWithIPLibraryFileId(ctx context.
|
||||
|
||||
for _, similarProvince := range similarProvinces {
|
||||
pbMissingProvince.SimilarProvinces = append(pbMissingProvince.SimilarProvinces, &pb.RegionProvince{
|
||||
Id: int64(similarProvince.Id),
|
||||
Id: int64(similarProvince.ValueId),
|
||||
Name: similarProvince.Name,
|
||||
DisplayName: similarProvince.DisplayName(),
|
||||
})
|
||||
@@ -482,7 +482,7 @@ func (this *IPLibraryFileService) CheckCitiesWithIPLibraryFileId(ctx context.Con
|
||||
|
||||
for _, similarCity := range similarCities {
|
||||
pbMissingCity.SimilarCities = append(pbMissingCity.SimilarCities, &pb.RegionCity{
|
||||
Id: int64(similarCity.Id),
|
||||
Id: int64(similarCity.ValueId),
|
||||
Name: similarCity.Name,
|
||||
DisplayName: similarCity.DisplayName(),
|
||||
})
|
||||
@@ -597,7 +597,7 @@ func (this *IPLibraryFileService) CheckTownsWithIPLibraryFileId(ctx context.Cont
|
||||
|
||||
for _, similarTown := range similarTowns {
|
||||
pbMissingTown.SimilarTowns = append(pbMissingTown.SimilarTowns, &pb.RegionTown{
|
||||
Id: int64(similarTown.Id),
|
||||
Id: int64(similarTown.ValueId),
|
||||
Name: similarTown.Name,
|
||||
DisplayName: similarTown.DisplayName(),
|
||||
})
|
||||
@@ -654,7 +654,7 @@ func (this *IPLibraryFileService) CheckProvidersWithIPLibraryFileId(ctx context.
|
||||
}
|
||||
for _, similarProvider := range similarProviders {
|
||||
pbMissingProvider.SimilarProviders = append(pbMissingProvider.SimilarProviders, &pb.RegionProvider{
|
||||
Id: int64(similarProvider.Id),
|
||||
Id: int64(similarProvider.ValueId),
|
||||
Name: similarProvider.Name,
|
||||
DisplayName: similarProvider.DisplayName(),
|
||||
})
|
||||
|
||||
@@ -2,8 +2,10 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
@@ -22,7 +24,16 @@ func (this *LogService) CreateLog(ctx context.Context, req *pb.CreateLogRequest)
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedLogDAO.CreateLog(tx, userType, userId, req.Level, req.Description, req.Action, req.Ip)
|
||||
// i18n
|
||||
var langMessageArgs = []any{}
|
||||
if len(req.LangMessageArgsJSON) > 0 {
|
||||
err = json.Unmarshal(req.LangMessageArgsJSON, &langMessageArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedLogDAO.CreateLog(tx, userType, userId, req.Level, req.Description, req.Action, req.Ip, langs.MessageCode(req.LangMessageCode), langMessageArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2016,7 +2016,7 @@ func (this *NodeService) FindNodeGlobalServerConfig(ctx context.Context, req *pb
|
||||
}
|
||||
}
|
||||
if config == nil {
|
||||
config = serverconfigs.DefaultGlobalServerConfig()
|
||||
config = serverconfigs.NewGlobalServerConfig()
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
|
||||
@@ -34,7 +34,7 @@ func (this *NodeClusterService) CreateNodeCluster(ctx context.Context, req *pb.C
|
||||
}
|
||||
|
||||
// 全局服务配置
|
||||
var serverGlobalConfig = serverconfigs.DefaultGlobalServerConfig()
|
||||
var serverGlobalConfig = serverconfigs.NewGlobalServerConfig()
|
||||
if len(req.GlobalServerConfigJSON) > 0 {
|
||||
err = json.Unmarshal(req.GlobalServerConfigJSON, serverGlobalConfig)
|
||||
if err != nil {
|
||||
@@ -1130,15 +1130,15 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
|
||||
}
|
||||
|
||||
// UAM
|
||||
var uamPolicy = nodeconfigs.NewUAMPolicy()
|
||||
if models.IsNotNull(cluster.Uam) {
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(cluster.Uam, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.UamIsOn = uamPolicy.IsOn
|
||||
} else {
|
||||
result.UamIsOn = nodeconfigs.DefaultUAMPolicy.IsOn
|
||||
result.UamIsOn = uamPolicy.IsOn
|
||||
}
|
||||
|
||||
// HTTP CC
|
||||
@@ -1180,6 +1180,16 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
|
||||
result.HasHTTPPagesPolicy = pagesPolicy.IsOn && len(pagesPolicy.Pages) > 0
|
||||
}
|
||||
|
||||
// HTTP/3
|
||||
if models.IsNotNull(cluster.Http3) {
|
||||
var http3Policy = nodeconfigs.NewHTTP3Policy()
|
||||
err = json.Unmarshal(cluster.Http3, http3Policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.Http3IsOn = http3Policy.IsOn
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -1282,7 +1292,7 @@ func (this *NodeClusterService) UpdateNodeClusterUAMPolicy(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
var uamPolicy = nodeconfigs.NewUAMPolicy()
|
||||
err = json.Unmarshal(req.UamPolicyJSON, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1301,7 +1311,6 @@ func (this *NodeClusterService) UpdateNodeClusterUAMPolicy(ctx context.Context,
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
|
||||
// FindEnabledNodeClusterHTTPCCPolicy 读取集群HTTP CC策略
|
||||
func (this *NodeClusterService) FindEnabledNodeClusterHTTPCCPolicy(ctx context.Context, req *pb.FindEnabledNodeClusterHTTPCCPolicyRequest) (*pb.FindEnabledNodeClusterHTTPCCPolicyResponse, error) {
|
||||
if !teaconst.IsPlus {
|
||||
@@ -1435,7 +1444,7 @@ func (this *NodeClusterService) UpdateNodeClusterGlobalServerConfig(ctx context.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = serverconfigs.DefaultGlobalServerConfig()
|
||||
var config = serverconfigs.NewGlobalServerConfig()
|
||||
err = json.Unmarshal(req.GlobalServerConfigJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1502,3 +1511,33 @@ func (this *NodeClusterService) UpdateNodeClusterHTTPPagesPolicy(ctx context.Con
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateNodeClusterHTTP3Policy 修改集群的HTTP3设置
|
||||
func (this *NodeClusterService) UpdateNodeClusterHTTP3Policy(ctx context.Context, req *pb.UpdateNodeClusterHTTP3PolicyRequest) (*pb.RPCSuccess, error) {
|
||||
if !teaconst.IsPlus {
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var http3Policy = nodeconfigs.NewHTTP3Policy()
|
||||
err = json.Unmarshal(req.Http3PolicyJSON, http3Policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = http3Policy.Init()
|
||||
if err != nil {
|
||||
return nil, errors.New("validate http3 policy failed: " + err.Error())
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterHTTP3Policy(tx, req.NodeClusterId, http3Policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
13
internal/rpc/services/service_node_cluster_ext.go
Normal file
13
internal/rpc/services/service_node_cluster_ext.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
func (this *NodeClusterService) FindNodeClusterHTTP3Policy(ctx context.Context, req *pb.FindNodeClusterHTTP3PolicyRequest) (*pb.FindNodeClusterHTTP3PolicyResponse, error) {
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
@@ -16,6 +16,10 @@ func (this *NodeService) FindNodeHTTPCCPolicies(ctx context.Context, req *pb.Fin
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
|
||||
func (this *NodeService) FindNodeHTTP3Policies(ctx context.Context, req *pb.FindNodeHTTP3PoliciesRequest) (*pb.FindNodeHTTP3PoliciesResponse, error) {
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
|
||||
func (this *NodeService) FindNodeHTTPPagesPolicies(ctx context.Context, req *pb.FindNodeHTTPPagesPoliciesRequest) (*pb.FindNodeHTTPPagesPoliciesResponse, error) {
|
||||
return nil, this.NotImplementedYet()
|
||||
}
|
||||
|
||||
@@ -216,6 +216,22 @@ func (this *NodeTaskService) DeleteNodeTasks(ctx context.Context, req *pb.Delete
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteAllNodeTasks 删除所有任务
|
||||
func (this *NodeTaskService) DeleteAllNodeTasks(ctx context.Context, req *pb.DeleteAllNodeTasksRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeTaskDAO.DeleteAllNodeTasks(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CountDoingNodeTasks 计算正在执行的任务数量
|
||||
func (this *NodeTaskService) CountDoingNodeTasks(ctx context.Context, req *pb.CountDoingNodeTasksRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
@@ -23,15 +24,26 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 源站地址设置
|
||||
if req.Addr == nil {
|
||||
return nil, errors.New("'addr' can not be nil")
|
||||
}
|
||||
addrMap := maps.Map{
|
||||
var addrMap = maps.Map{
|
||||
"protocol": req.Addr.Protocol,
|
||||
"portRange": req.Addr.PortRange,
|
||||
"host": req.Addr.Host,
|
||||
}
|
||||
|
||||
// OSS设置
|
||||
var ossConfig *ossconfigs.OSSConfig
|
||||
if len(req.OssJSON) > 0 {
|
||||
ossConfig = ossconfigs.NewOSSConfig()
|
||||
err = json.Unmarshal(req.OssJSON, ossConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 校验参数
|
||||
@@ -72,7 +84,7 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, addrMap.AsJSON(), ossConfig, req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort, req.Http2Enabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,6 +107,8 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 源站地址设置
|
||||
if req.Addr == nil {
|
||||
return nil, errors.New("'addr' can not be nil")
|
||||
}
|
||||
@@ -104,6 +118,16 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
"host": req.Addr.Host,
|
||||
}
|
||||
|
||||
// OSS设置
|
||||
var ossConfig *ossconfigs.OSSConfig
|
||||
if len(req.OssJSON) > 0 {
|
||||
ossConfig = ossconfigs.NewOSSConfig()
|
||||
err = json.Unmarshal(req.OssJSON, ossConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 校验参数
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
if len(req.ConnTimeoutJSON) > 0 {
|
||||
@@ -142,7 +166,7 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, addrMap.AsJSON(), ossConfig, req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort, req.Http2Enabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -180,7 +204,7 @@ func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEn
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &pb.Origin{
|
||||
return &pb.FindEnabledOriginResponse{Origin: &pb.Origin{
|
||||
Id: int64(origin.Id),
|
||||
IsOn: origin.IsOn,
|
||||
Name: origin.Name,
|
||||
@@ -189,10 +213,11 @@ func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEn
|
||||
Host: addr.Host,
|
||||
PortRange: addr.PortRange,
|
||||
},
|
||||
Description: origin.Description,
|
||||
Domains: origin.DecodeDomains(),
|
||||
}
|
||||
return &pb.FindEnabledOriginResponse{Origin: result}, nil
|
||||
Description: origin.Description,
|
||||
Domains: origin.DecodeDomains(),
|
||||
FollowPort: origin.FollowPort,
|
||||
Http2Enabled: origin.Http2Enabled,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// FindEnabledOriginConfig 查找源站配置
|
||||
|
||||
@@ -49,7 +49,7 @@ func (this *RegionCityService) FindAllEnabledRegionCities(ctx context.Context, r
|
||||
}
|
||||
|
||||
pbProvince = &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
DisplayName: province.DisplayName(),
|
||||
@@ -57,7 +57,7 @@ func (this *RegionCityService) FindAllEnabledRegionCities(ctx context.Context, r
|
||||
}
|
||||
|
||||
pbCities = append(pbCities, &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Id: int64(city.ValueId),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
@@ -108,7 +108,7 @@ func (this *RegionCityService) FindAllRegionCities(ctx context.Context, req *pb.
|
||||
}
|
||||
|
||||
pbProvince = &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
CustomName: province.CustomName,
|
||||
@@ -118,7 +118,7 @@ func (this *RegionCityService) FindAllRegionCities(ctx context.Context, req *pb.
|
||||
}
|
||||
|
||||
pbCities = append(pbCities, &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Id: int64(city.ValueId),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
@@ -155,7 +155,7 @@ func (this *RegionCityService) FindAllRegionCitiesWithRegionProvinceId(ctx conte
|
||||
var pbProvince = &pb.RegionProvince{Id: provinceId}
|
||||
|
||||
pbCities = append(pbCities, &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Id: int64(city.ValueId),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
@@ -192,7 +192,7 @@ func (this *RegionCityService) FindEnabledRegionCity(ctx context.Context, req *p
|
||||
|
||||
return &pb.FindEnabledRegionCityResponse{
|
||||
RegionCity: &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Id: int64(city.ValueId),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
@@ -223,7 +223,7 @@ func (this *RegionCityService) FindRegionCity(ctx context.Context, req *pb.FindR
|
||||
|
||||
return &pb.FindRegionCityResponse{
|
||||
RegionCity: &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Id: int64(city.ValueId),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
|
||||
@@ -40,13 +40,14 @@ func (this *RegionCountryService) FindAllEnabledRegionCountries(ctx context.Cont
|
||||
}
|
||||
|
||||
result = append(result, &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Id: int64(country.ValueId),
|
||||
Name: country.Name,
|
||||
Codes: country.DecodeCodes(),
|
||||
Pinyin: pinyinStrings,
|
||||
CustomName: country.CustomName,
|
||||
CustomCodes: country.DecodeCustomCodes(),
|
||||
DisplayName: country.DisplayName(),
|
||||
IsCommon: country.IsCommon,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledRegionCountriesResponse{
|
||||
@@ -74,7 +75,7 @@ func (this *RegionCountryService) FindEnabledRegionCountry(ctx context.Context,
|
||||
}
|
||||
|
||||
return &pb.FindEnabledRegionCountryResponse{RegionCountry: &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Id: int64(country.ValueId),
|
||||
Name: country.Name,
|
||||
Codes: country.DecodeCodes(),
|
||||
CustomName: country.CustomName,
|
||||
@@ -110,13 +111,14 @@ func (this *RegionCountryService) FindAllRegionCountries(ctx context.Context, re
|
||||
}
|
||||
|
||||
result = append(result, &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Id: int64(country.ValueId),
|
||||
Name: country.Name,
|
||||
Codes: country.DecodeCodes(),
|
||||
Pinyin: pinyinStrings,
|
||||
CustomName: country.CustomName,
|
||||
CustomCodes: country.DecodeCustomCodes(),
|
||||
DisplayName: country.DisplayName(),
|
||||
IsCommon: country.IsCommon,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllRegionCountriesResponse{
|
||||
@@ -143,12 +145,13 @@ func (this *RegionCountryService) FindRegionCountry(ctx context.Context, req *pb
|
||||
}
|
||||
|
||||
return &pb.FindRegionCountryResponse{RegionCountry: &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Id: int64(country.ValueId),
|
||||
Name: country.Name,
|
||||
Codes: country.DecodeCodes(),
|
||||
CustomName: country.CustomName,
|
||||
CustomCodes: country.DecodeCustomCodes(),
|
||||
DisplayName: country.DisplayName(),
|
||||
IsCommon: country.IsCommon,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ func (this *RegionProviderService) FindAllEnabledRegionProviders(ctx context.Con
|
||||
var pbProviders = []*pb.RegionProvider{}
|
||||
for _, provider := range providers {
|
||||
pbProviders = append(pbProviders, &pb.RegionProvider{
|
||||
Id: int64(provider.Id),
|
||||
Id: int64(provider.ValueId),
|
||||
Name: provider.Name,
|
||||
Codes: provider.DecodeCodes(),
|
||||
CustomName: provider.CustomName,
|
||||
@@ -65,7 +65,7 @@ func (this *RegionProviderService) FindEnabledRegionProvider(ctx context.Context
|
||||
|
||||
return &pb.FindEnabledRegionProviderResponse{
|
||||
RegionProvider: &pb.RegionProvider{
|
||||
Id: int64(provider.Id),
|
||||
Id: int64(provider.ValueId),
|
||||
Name: provider.Name,
|
||||
Codes: provider.DecodeCodes(),
|
||||
CustomName: provider.CustomName,
|
||||
@@ -91,7 +91,7 @@ func (this *RegionProviderService) FindAllRegionProviders(ctx context.Context, r
|
||||
var pbProviders = []*pb.RegionProvider{}
|
||||
for _, provider := range providers {
|
||||
pbProviders = append(pbProviders, &pb.RegionProvider{
|
||||
Id: int64(provider.Id),
|
||||
Id: int64(provider.ValueId),
|
||||
Name: provider.Name,
|
||||
Codes: provider.DecodeCodes(),
|
||||
CustomName: provider.CustomName,
|
||||
@@ -125,7 +125,7 @@ func (this *RegionProviderService) FindRegionProvider(ctx context.Context, req *
|
||||
|
||||
return &pb.FindRegionProviderResponse{
|
||||
RegionProvider: &pb.RegionProvider{
|
||||
Id: int64(provider.Id),
|
||||
Id: int64(provider.ValueId),
|
||||
Name: provider.Name,
|
||||
Codes: provider.DecodeCodes(),
|
||||
CustomName: provider.CustomName,
|
||||
|
||||
@@ -29,7 +29,7 @@ func (this *RegionProvinceService) FindAllEnabledRegionProvincesWithCountryId(ct
|
||||
result := []*pb.RegionProvince{}
|
||||
for _, province := range provinces {
|
||||
result = append(result, &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
CustomName: province.CustomName,
|
||||
@@ -64,7 +64,7 @@ func (this *RegionProvinceService) FindEnabledRegionProvince(ctx context.Context
|
||||
|
||||
return &pb.FindEnabledRegionProvinceResponse{
|
||||
RegionProvince: &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
CustomName: province.CustomName,
|
||||
@@ -91,7 +91,7 @@ func (this *RegionProvinceService) FindAllRegionProvincesWithRegionCountryId(ctx
|
||||
var result = []*pb.RegionProvince{}
|
||||
for _, province := range provinces {
|
||||
result = append(result, &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
CustomName: province.CustomName,
|
||||
@@ -125,7 +125,7 @@ func (this *RegionProvinceService) FindRegionProvince(ctx context.Context, req *
|
||||
|
||||
return &pb.FindRegionProvinceResponse{
|
||||
RegionProvince: &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
CustomName: province.CustomName,
|
||||
|
||||
@@ -48,7 +48,7 @@ func (this *RegionTownService) FindAllRegionTowns(ctx context.Context, req *pb.F
|
||||
}
|
||||
|
||||
pbCity = &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Id: int64(city.ValueId),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
CustomName: city.CustomName,
|
||||
@@ -58,7 +58,7 @@ func (this *RegionTownService) FindAllRegionTowns(ctx context.Context, req *pb.F
|
||||
}
|
||||
|
||||
pbTowns = append(pbTowns, &pb.RegionTown{
|
||||
Id: int64(town.Id),
|
||||
Id: int64(town.ValueId),
|
||||
Name: town.Name,
|
||||
Codes: town.DecodeCodes(),
|
||||
RegionCityId: int64(town.CityId),
|
||||
@@ -95,7 +95,7 @@ func (this *RegionTownService) FindAllRegionTownsWithRegionCityId(ctx context.Co
|
||||
var pbCity = &pb.RegionCity{Id: cityId}
|
||||
|
||||
pbTowns = append(pbTowns, &pb.RegionTown{
|
||||
Id: int64(town.Id),
|
||||
Id: int64(town.ValueId),
|
||||
Name: town.Name,
|
||||
Codes: town.DecodeCodes(),
|
||||
RegionCityId: int64(town.CityId),
|
||||
@@ -131,7 +131,7 @@ func (this *RegionTownService) FindRegionTown(ctx context.Context, req *pb.FindR
|
||||
|
||||
return &pb.FindRegionTownResponse{
|
||||
RegionTown: &pb.RegionTown{
|
||||
Id: int64(town.Id),
|
||||
Id: int64(town.ValueId),
|
||||
Name: town.Name,
|
||||
Codes: town.DecodeCodes(),
|
||||
RegionCityId: int64(town.CityId),
|
||||
|
||||
@@ -9,13 +9,17 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"net"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
@@ -184,6 +188,505 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe
|
||||
return &pb.CreateServerResponse{ServerId: serverId}, nil
|
||||
}
|
||||
|
||||
// CreateBasicHTTPServer 快速创建基本的HTTP网站
|
||||
func (this *ServerService) CreateBasicHTTPServer(ctx context.Context, req *pb.CreateBasicHTTPServerRequest) (*pb.CreateBasicHTTPServerResponse, error) {
|
||||
adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 集群
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
|
||||
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.NodeClusterId = nodeClusterId
|
||||
} else if adminId > 0 && req.UserId > 0 && req.NodeClusterId <= 0 {
|
||||
// check user
|
||||
existUser, err := models.SharedUserDAO.Exist(tx, req.UserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existUser {
|
||||
return nil, errors.New("user id '" + types.String(req.UserId) + "' not found")
|
||||
}
|
||||
|
||||
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.NodeClusterId = nodeClusterId
|
||||
}
|
||||
|
||||
if req.NodeClusterId <= 0 {
|
||||
return nil, errors.New("invalid 'nodeClusterId'")
|
||||
}
|
||||
|
||||
if len(req.Domains) == 0 {
|
||||
return nil, errors.New("'domains' should not be empty")
|
||||
}
|
||||
var serverNames = []*serverconfigs.ServerNameConfig{}
|
||||
for _, domain := range req.Domains {
|
||||
domain = strings.ToLower(domain)
|
||||
if !domainutils.ValidateDomainFormat(domain) {
|
||||
return nil, errors.New("invalid domain format '" + domain + "'")
|
||||
}
|
||||
|
||||
// 检查域名是否已存在
|
||||
existServerName, err := models.SharedServerDAO.ExistServerNameInCluster(tx, req.NodeClusterId, domain, 0, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existServerName {
|
||||
return nil, errors.New("domain '" + domain + "' already created by other server")
|
||||
}
|
||||
|
||||
serverNames = append(serverNames, &serverconfigs.ServerNameConfig{Name: domain})
|
||||
}
|
||||
serverNamesJSON, err := json.Marshal(serverNames)
|
||||
if err != nil {
|
||||
return nil, errors.New("encode 'serverNames' failed: " + err.Error())
|
||||
}
|
||||
|
||||
// 是否需要审核
|
||||
var isAuditing = false
|
||||
var auditingServerNamesJSON = []byte("[]")
|
||||
if userId > 0 {
|
||||
// 如果域名不为空的时候需要审核
|
||||
if len(serverNamesJSON) > 0 && string(serverNamesJSON) != "[]" {
|
||||
globalConfig, err := models.SharedSysSettingDAO.ReadGlobalConfig(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if globalConfig != nil && globalConfig.HTTPAll.DomainAuditingIsOn {
|
||||
isAuditing = true
|
||||
serverNamesJSON = []byte("[]")
|
||||
auditingServerNamesJSON = serverNamesJSON
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP
|
||||
var httpConfig = &serverconfigs.HTTPProtocolConfig{
|
||||
BaseProtocol: serverconfigs.BaseProtocol{
|
||||
IsOn: true,
|
||||
Listen: []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: "http",
|
||||
PortRange: "80",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
httpJSON, err := json.Marshal(httpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// HTTPS
|
||||
var certRefs = []*sslconfigs.SSLCertRef{}
|
||||
for _, certId := range req.SslCertIds {
|
||||
// 检查所有权
|
||||
if userId > 0 {
|
||||
err = models.SharedSSLCertDAO.CheckUserCert(tx, certId, userId)
|
||||
if err != nil {
|
||||
return nil, errors.New("check cert permission failed: " + err.Error())
|
||||
}
|
||||
} else {
|
||||
existCert, err := models.SharedSSLCertDAO.Exist(tx, certId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existCert {
|
||||
return nil, errors.New("cert '" + types.String(certId) + "' not found")
|
||||
}
|
||||
}
|
||||
|
||||
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
})
|
||||
}
|
||||
certRefsJSON, err := json.Marshal(certRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sslPolicyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, req.UserId, false, false, "TLS 1.0", certRefsJSON, nil, false, 0, nil, false, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{
|
||||
BaseProtocol: serverconfigs.BaseProtocol{
|
||||
IsOn: true,
|
||||
Listen: []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: "https",
|
||||
PortRange: "443",
|
||||
},
|
||||
},
|
||||
},
|
||||
SSLPolicyRef: &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyId,
|
||||
},
|
||||
}
|
||||
httpsJSON, err := json.Marshal(httpsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Reverse Proxy
|
||||
var reverseProxyScheduleConfig = &serverconfigs.SchedulingConfig{
|
||||
Code: "random",
|
||||
Options: nil,
|
||||
}
|
||||
reverseProxyScheduleJSON, err := json.Marshal(reverseProxyScheduleConfig)
|
||||
|
||||
var primaryOrigins = []*serverconfigs.OriginRef{}
|
||||
for _, originAddr := range req.OriginAddrs {
|
||||
u, err := url.Parse(originAddr)
|
||||
if err != nil {
|
||||
return nil, errors.New("parse origin address '" + originAddr + "' failed: " + err.Error())
|
||||
}
|
||||
if len(u.Scheme) == 0 || (u.Scheme != "http" && u.Scheme != "https" /** 特意不支持大写形式 **/) {
|
||||
return nil, errors.New("invalid scheme in origin address '" + originAddr + "'")
|
||||
}
|
||||
|
||||
if len(u.Host) == 0 {
|
||||
return nil, errors.New("invalid host address '" + originAddr + "', contains no host")
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
if err != nil {
|
||||
err = nil // ignore error
|
||||
|
||||
if domainutils.ValidateDomainFormat(u.Host) { // host with no port
|
||||
host = u.Host
|
||||
port = ""
|
||||
} else {
|
||||
return nil, errors.New("invalid host address '" + originAddr + "', invalid host format")
|
||||
}
|
||||
}
|
||||
|
||||
if len(port) == 0 {
|
||||
switch u.Scheme {
|
||||
case "http":
|
||||
port = "80"
|
||||
case "https":
|
||||
port = "443"
|
||||
}
|
||||
}
|
||||
|
||||
var addr = &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: serverconfigs.Protocol(u.Scheme),
|
||||
Host: host,
|
||||
PortRange: port,
|
||||
}
|
||||
addrJSON, err := json.Marshal(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, req.UserId, "", addrJSON, nil, "", 10, true, nil, nil, nil, 0, 0, nil, nil, u.Host, false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
primaryOrigins = append(primaryOrigins, &serverconfigs.OriginRef{
|
||||
IsOn: true,
|
||||
OriginId: originId,
|
||||
})
|
||||
}
|
||||
primaryOriginsJSON, err := json.Marshal(primaryOrigins)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reverseProxyId, err := models.SharedReverseProxyDAO.CreateReverseProxy(tx, adminId, req.UserId, reverseProxyScheduleJSON, primaryOriginsJSON, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reverseProxyJSON, err := json.Marshal(&serverconfigs.ReverseProxyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
ReverseProxyId: reverseProxyId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Web
|
||||
webId, err := models.SharedHTTPWebDAO.CreateWeb(tx, adminId, req.UserId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Enable websocket
|
||||
if req.EnableWebsocket {
|
||||
websocketId, err := models.SharedHTTPWebsocketDAO.CreateWebsocket(tx, nil, true, nil, true, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
websocketRef, err := json.Marshal(&serverconfigs.HTTPWebsocketRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
WebsocketId: websocketId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = models.SharedHTTPWebDAO.UpdateWebsocket(tx, webId, websocketRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// finally, we create ...
|
||||
serverId, err := models.SharedServerDAO.CreateServer(tx, adminId, req.UserId, serverconfigs.ServerTypeHTTPProxy, req.Domains[0], "", serverNamesJSON, isAuditing, auditingServerNamesJSON, httpJSON, httpsJSON, nil, nil, nil, nil, webId, reverseProxyJSON, req.NodeClusterId, nil, nil, nil, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateBasicHTTPServerResponse{ServerId: serverId}, nil
|
||||
}
|
||||
|
||||
// CreateBasicTCPServer 快速创建基本的TCP网站
|
||||
func (this *ServerService) CreateBasicTCPServer(ctx context.Context, req *pb.CreateBasicTCPServerRequest) (*pb.CreateBasicTCPServerResponse, error) {
|
||||
adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 集群
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
|
||||
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.NodeClusterId = nodeClusterId
|
||||
} else if adminId > 0 && req.UserId > 0 && req.NodeClusterId <= 0 {
|
||||
// check user
|
||||
existUser, err := models.SharedUserDAO.Exist(tx, req.UserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existUser {
|
||||
return nil, errors.New("user id '" + types.String(req.UserId) + "' not found")
|
||||
}
|
||||
|
||||
nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.NodeClusterId = nodeClusterId
|
||||
}
|
||||
|
||||
if req.NodeClusterId <= 0 {
|
||||
return nil, errors.New("invalid 'nodeClusterId'")
|
||||
}
|
||||
|
||||
// 检查用户权限
|
||||
if userId > 0 {
|
||||
features, err := models.SharedUserDAO.FindUserFeatures(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var canSpecifyTCPPort = false
|
||||
for _, feature := range features {
|
||||
if feature.Code == "server.tcp.port" {
|
||||
canSpecifyTCPPort = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !canSpecifyTCPPort {
|
||||
if len(req.TcpPorts) > 0 || len(req.TlsPorts) > 0 {
|
||||
return nil, errors.New("no permission to specify tcp/tls ports")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.TcpPorts) == 0 || len(req.TlsPorts) == 0 {
|
||||
// TODO 未来支持自动创建端口
|
||||
return nil, errors.New("no ports valid")
|
||||
}
|
||||
|
||||
// TCP
|
||||
var tcpConfig = &serverconfigs.HTTPProtocolConfig{
|
||||
BaseProtocol: serverconfigs.BaseProtocol{
|
||||
IsOn: true,
|
||||
Listen: []*serverconfigs.NetworkAddressConfig{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, port := range req.TcpPorts {
|
||||
existPort, err := models.SharedServerDAO.CheckPortIsUsing(tx, req.NodeClusterId, "tcp", int(port), 0, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existPort {
|
||||
return nil, errors.New("port '" + types.String(port) + "' already used by other server")
|
||||
}
|
||||
|
||||
tcpConfig.BaseProtocol.Listen = append(tcpConfig.BaseProtocol.Listen, &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: "tcp",
|
||||
PortRange: types.String(port),
|
||||
})
|
||||
}
|
||||
|
||||
tcpJSON, err := json.Marshal(tcpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TLS
|
||||
var tlsConfig = &serverconfigs.HTTPSProtocolConfig{
|
||||
BaseProtocol: serverconfigs.BaseProtocol{
|
||||
IsOn: true,
|
||||
Listen: []*serverconfigs.NetworkAddressConfig{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, port := range req.TlsPorts {
|
||||
existPort, err := models.SharedServerDAO.CheckPortIsUsing(tx, req.NodeClusterId, "tcp", int(port), 0, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existPort {
|
||||
return nil, errors.New("port '" + types.String(port) + "' already used by other server")
|
||||
}
|
||||
|
||||
tlsConfig.BaseProtocol.Listen = append(tlsConfig.BaseProtocol.Listen, &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: "tls",
|
||||
PortRange: types.String(port),
|
||||
})
|
||||
}
|
||||
|
||||
var certRefs = []*sslconfigs.SSLCertRef{}
|
||||
for _, certId := range req.SslCertIds {
|
||||
// 检查所有权
|
||||
if userId > 0 {
|
||||
err = models.SharedSSLCertDAO.CheckUserCert(tx, certId, userId)
|
||||
if err != nil {
|
||||
return nil, errors.New("check cert permission failed: " + err.Error())
|
||||
}
|
||||
} else {
|
||||
existCert, err := models.SharedSSLCertDAO.Exist(tx, certId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !existCert {
|
||||
return nil, errors.New("cert '" + types.String(certId) + "' not found")
|
||||
}
|
||||
}
|
||||
|
||||
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
})
|
||||
}
|
||||
certRefsJSON, err := json.Marshal(certRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sslPolicyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, req.UserId, false, false, "TLS 1.0", certRefsJSON, nil, false, 0, nil, false, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyId,
|
||||
}
|
||||
|
||||
tlsJSON, err := json.Marshal(tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Reverse Proxy
|
||||
var reverseProxyScheduleConfig = &serverconfigs.SchedulingConfig{
|
||||
Code: "random",
|
||||
Options: nil,
|
||||
}
|
||||
reverseProxyScheduleJSON, err := json.Marshal(reverseProxyScheduleConfig)
|
||||
|
||||
var primaryOrigins = []*serverconfigs.OriginRef{}
|
||||
for _, originAddr := range req.OriginAddrs {
|
||||
u, err := url.Parse(originAddr)
|
||||
if err != nil {
|
||||
return nil, errors.New("parse origin address '" + originAddr + "' failed: " + err.Error())
|
||||
}
|
||||
if len(u.Scheme) == 0 || (u.Scheme != "tcp" && u.Scheme != "tls" && u.Scheme != "ssl" /** 特意不支持大写形式 **/) {
|
||||
return nil, errors.New("invalid scheme in origin address '" + originAddr + "'")
|
||||
}
|
||||
|
||||
if len(u.Host) == 0 {
|
||||
return nil, errors.New("invalid host address '" + originAddr + "', contains no host")
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
if err != nil || len(host) == 0 || len(port) == 0 {
|
||||
err = nil // ignore error
|
||||
|
||||
return nil, errors.New("invalid host address '" + originAddr + "', invalid host format")
|
||||
}
|
||||
|
||||
if u.Scheme == "ssl" {
|
||||
u.Scheme = "tls"
|
||||
}
|
||||
|
||||
var addr = &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: serverconfigs.Protocol(u.Scheme),
|
||||
Host: host,
|
||||
PortRange: port,
|
||||
}
|
||||
addrJSON, err := json.Marshal(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, req.UserId, "", addrJSON, nil, "", 10, true, nil, nil, nil, 0, 0, nil, nil, "", false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
primaryOrigins = append(primaryOrigins, &serverconfigs.OriginRef{
|
||||
IsOn: true,
|
||||
OriginId: originId,
|
||||
})
|
||||
}
|
||||
primaryOriginsJSON, err := json.Marshal(primaryOrigins)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reverseProxyId, err := models.SharedReverseProxyDAO.CreateReverseProxy(tx, adminId, req.UserId, reverseProxyScheduleJSON, primaryOriginsJSON, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reverseProxyJSON, err := json.Marshal(&serverconfigs.ReverseProxyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
ReverseProxyId: reverseProxyId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// finally, we create ...
|
||||
serverId, err := models.SharedServerDAO.CreateServer(tx, adminId, req.UserId, serverconfigs.ServerTypeTCPProxy, "TCP Service", "", nil, false, nil, nil, nil, tcpJSON, tlsJSON, nil, nil, 0, reverseProxyJSON, req.NodeClusterId, nil, nil, nil, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateBasicTCPServerResponse{ServerId: serverId}, nil
|
||||
}
|
||||
|
||||
// UpdateServerBasic 修改服务基本信息
|
||||
func (this *ServerService) UpdateServerBasic(ctx context.Context, req *pb.UpdateServerBasicRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验请求
|
||||
@@ -798,6 +1301,14 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
|
||||
order = "trafficOutAsc"
|
||||
} else if req.TrafficOutDesc {
|
||||
order = "trafficOutDesc"
|
||||
} else if req.RequestsAsc {
|
||||
order = "requestsAsc"
|
||||
} else if req.RequestsDesc {
|
||||
order = "requestsDesc"
|
||||
} else if req.AttackRequestsAsc {
|
||||
order = "attackRequestsAsc"
|
||||
} else if req.AttackRequestsDesc {
|
||||
order = "attackRequestsDesc"
|
||||
}
|
||||
|
||||
servers, err := models.SharedServerDAO.ListEnabledServersMatch(tx, req.Offset, req.Size, req.ServerGroupId, req.Keyword, req.UserId, req.NodeClusterId, req.AuditingFlag, utils.SplitStrings(req.ProtocolFamily, ","), order)
|
||||
@@ -915,11 +1426,13 @@ func (this *ServerService) ListEnabledServersMatch(ctx context.Context, req *pb.
|
||||
Id: int64(server.ClusterId),
|
||||
Name: clusterName,
|
||||
},
|
||||
ServerGroups: pbGroups,
|
||||
UserId: int64(server.UserId),
|
||||
User: pbUser,
|
||||
BandwidthTime: server.BandwidthTime,
|
||||
BandwidthBytes: int64(server.BandwidthBytes),
|
||||
ServerGroups: pbGroups,
|
||||
UserId: int64(server.UserId),
|
||||
User: pbUser,
|
||||
BandwidthTime: server.BandwidthTime,
|
||||
BandwidthBytes: int64(server.BandwidthBytes),
|
||||
CountRequests: int64(server.CountRequests),
|
||||
CountAttackRequests: int64(server.CountAttackRequests),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -65,12 +65,12 @@ func init() {
|
||||
for _, stat := range m {
|
||||
// 更新服务的带宽峰值
|
||||
if stat.ServerId > 0 {
|
||||
err := models.SharedServerBandwidthStatDAO.UpdateServerBandwidth(tx, stat.UserId, stat.ServerId, stat.NodeRegionId, stat.Day, stat.TimeAt, stat.Bytes, stat.TotalBytes, stat.CachedBytes, stat.AttackBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests)
|
||||
err = models.SharedServerBandwidthStatDAO.UpdateServerBandwidth(tx, stat.UserId, stat.ServerId, stat.NodeRegionId, stat.Day, stat.TimeAt, stat.Bytes, stat.TotalBytes, stat.CachedBytes, stat.AttackBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerBandwidthStatService", "dump bandwidth stats failed: "+err.Error())
|
||||
}
|
||||
|
||||
err = models.SharedServerDAO.UpdateServerBandwidth(tx, stat.ServerId, stat.Day+stat.TimeAt, stat.Bytes)
|
||||
err = models.SharedServerDAO.UpdateServerBandwidth(tx, stat.ServerId, stat.Day+stat.TimeAt, stat.Bytes, stat.CountRequests, stat.CountAttackRequests)
|
||||
if err != nil {
|
||||
remotelogs.Error("ServerBandwidthStatService", "update server bandwidth failed: "+err.Error())
|
||||
}
|
||||
|
||||
@@ -483,6 +483,7 @@ func (this *ServerGroupService) FindEnabledServerGroupConfigInfo(ctx context.Con
|
||||
result.HasAccessLogConfig = webConfig != nil && webConfig.AccessLogRef != nil && webConfig.AccessLogRef.IsPrior
|
||||
result.HasStatConfig = webConfig != nil && webConfig.StatRef != nil && webConfig.StatRef.IsPrior
|
||||
result.HasCompressionConfig = webConfig != nil && webConfig.Compression != nil && webConfig.Compression.IsPrior
|
||||
result.HasOptimizationConfig = webConfig != nil && webConfig.Optimization != nil && webConfig.Optimization.IsPrior
|
||||
result.HasWebsocketConfig = webConfig != nil && webConfig.WebsocketRef != nil && webConfig.WebsocketRef.IsPrior
|
||||
result.HasRequestHeadersConfig = webConfig != nil && webConfig.RequestHeaderPolicyRef != nil && webConfig.RequestHeaderPolicyRef.IsPrior
|
||||
result.HasResponseHeadersConfig = webConfig != nil && webConfig.ResponseHeaderPolicyRef != nil && webConfig.ResponseHeaderPolicyRef.IsPrior
|
||||
|
||||
@@ -62,15 +62,15 @@ func (this *ServerRegionCityMonthlyStatService) FindTopServerRegionCityMonthlySt
|
||||
continue
|
||||
}
|
||||
pbStat.RegionCountry = &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Id: int64(country.ValueId),
|
||||
Name: country.DisplayName(),
|
||||
}
|
||||
pbStat.RegionProvince = &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.DisplayName(),
|
||||
}
|
||||
pbStat.RegionCity = &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Id: int64(city.ValueId),
|
||||
Name: city.DisplayName(),
|
||||
}
|
||||
pbStats = append(pbStats, pbStat)
|
||||
|
||||
@@ -46,7 +46,7 @@ func (this *ServerRegionCountryMonthlyStatService) FindTopServerRegionCountryMon
|
||||
continue
|
||||
}
|
||||
pbStat.RegionCountry = &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Id: int64(country.ValueId),
|
||||
Name: country.DisplayName(),
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func (this *ServerRegionProviderMonthlyStatService) FindTopServerRegionProviderM
|
||||
continue
|
||||
}
|
||||
pbStat.RegionProvider = &pb.RegionProvider{
|
||||
Id: int64(provider.Id),
|
||||
Id: int64(provider.ValueId),
|
||||
Name: provider.DisplayName(),
|
||||
}
|
||||
pbStats = append(pbStats, pbStat)
|
||||
|
||||
@@ -52,11 +52,11 @@ func (this *ServerRegionProvinceMonthlyStatService) FindTopServerRegionProvinceM
|
||||
continue
|
||||
}
|
||||
pbStat.RegionCountry = &pb.RegionCountry{
|
||||
Id: int64(country.Id),
|
||||
Id: int64(country.ValueId),
|
||||
Name: country.DisplayName(),
|
||||
}
|
||||
pbStat.RegionProvince = &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Id: int64(province.ValueId),
|
||||
Name: province.DisplayName(),
|
||||
}
|
||||
pbStats = append(pbStats, pbStat)
|
||||
|
||||
@@ -44,7 +44,7 @@ func (this *SSLPolicyService) CreateSSLPolicy(ctx context.Context, req *pb.Creat
|
||||
// TODO
|
||||
}
|
||||
|
||||
policyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, userId, req.Http2Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
|
||||
policyId, err := models.SharedSSLPolicyDAO.CreatePolicy(tx, adminId, userId, req.Http2Enabled, req.Http3Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -63,13 +63,13 @@ func (this *SSLPolicyService) UpdateSSLPolicy(ctx context.Context, req *pb.Updat
|
||||
var tx = this.NullTx()
|
||||
|
||||
if userId > 0 {
|
||||
err := models.SharedSSLPolicyDAO.CheckUserPolicy(tx, userId, req.SslPolicyId)
|
||||
err = models.SharedSSLPolicyDAO.CheckUserPolicy(tx, userId, req.SslPolicyId)
|
||||
if err != nil {
|
||||
return nil, errors.New("check ssl policy failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedSSLPolicyDAO.UpdatePolicy(tx, req.SslPolicyId, req.Http2Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
|
||||
err = models.SharedSSLPolicyDAO.UpdatePolicy(tx, req.SslPolicyId, req.Http2Enabled, req.Http3Enabled, req.MinVersion, req.SslCertsJSON, req.HstsJSON, req.OcspIsOn, req.ClientAuthType, req.ClientCACertsJSON, req.CipherSuitesIsOn, req.CipherSuites)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -261,6 +261,7 @@ func (this *UserService) FindEnabledUser(ctx context.Context, req *pb.FindEnable
|
||||
IsEnterpriseIdentified: isEnterpriseIdentified,
|
||||
BandwidthAlgo: user.BandwidthAlgo,
|
||||
OtpLogin: pbOtpAuth,
|
||||
Lang: user.Lang,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,13 @@ func (this *Setup) Run() error {
|
||||
}
|
||||
for _, db := range config.DBs {
|
||||
// 可以同时运行多条语句
|
||||
db.Dsn += "&multiStatements=true"
|
||||
if !strings.Contains(db.Dsn, "multiStatements=") {
|
||||
if strings.Contains(db.Dsn, "?") {
|
||||
db.Dsn += "&multiStatements=true"
|
||||
} else {
|
||||
db.Dsn += "?multiStatements=true"
|
||||
}
|
||||
}
|
||||
}
|
||||
dbConfig, ok := config.DBs[Tea.Env]
|
||||
if !ok {
|
||||
|
||||
49857
internal/setup/sql.json
49857
internal/setup/sql.json
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user