diff --git a/build/.gitignore b/build/.gitignore deleted file mode 100644 index a7d94920..00000000 --- a/build/.gitignore +++ /dev/null @@ -1 +0,0 @@ -configs/api.yaml \ No newline at end of file diff --git a/build/configs/.gitignore b/build/configs/.gitignore new file mode 100644 index 00000000..237771ba --- /dev/null +++ b/build/configs/.gitignore @@ -0,0 +1,2 @@ +api.yaml +db.yaml \ No newline at end of file diff --git a/build/configs/db.template.yaml b/build/configs/db.template.yaml new file mode 100644 index 00000000..d98fcf07 --- /dev/null +++ b/build/configs/db.template.yaml @@ -0,0 +1,11 @@ +default: + db: "dev" + prefix: "" + +dbs: + dev: + driver: "mysql" + dsn: "root:123456@tcp(127.0.0.1:3306)/db_shield?charset=utf8mb4&timeout=30s" + prefix: "shield" + models: + package: internal/web/models diff --git a/build/logs/.gitignore b/build/logs/.gitignore new file mode 100644 index 00000000..bf0824e5 --- /dev/null +++ b/build/logs/.gitignore @@ -0,0 +1 @@ +*.log \ No newline at end of file diff --git a/cmd/edge-api/main.go b/cmd/edge-api/main.go index 8275c0fc..fc0970c2 100644 --- a/cmd/edge-api/main.go +++ b/cmd/edge-api/main.go @@ -2,9 +2,17 @@ package main import ( "github.com/TeaOSLab/EdgeAPI/internal/apis" + "github.com/TeaOSLab/EdgeAPI/internal/apps" + teaconst "github.com/TeaOSLab/EdgeAPI/internal/const" _ "github.com/iwind/TeaGo/bootstrap" ) func main() { - apis.NewAPINode().Start() + app := apps.NewAppCmd() + app.Version(teaconst.Version) + app.Product(teaconst.ProductName) + app.Usage(teaconst.ProcessName + " [start|stop|restart]") + app.Run(func() { + apis.NewAPINode().Start() + }) } diff --git a/cmd/tt/main.go b/cmd/tt/main.go new file mode 100644 index 00000000..5e1a5af6 --- /dev/null +++ b/cmd/tt/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "bufio" + "bytes" + "fmt" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/cmd" + _ "github.com/iwind/TeaGo/dbs/commands" + "github.com/iwind/TeaGo/lists" + "os" + "path/filepath" + "time" +) + +// TeaTool工具 +func main() { + r := bufio.NewReader(os.Stdin) + lastCommand := "" + + for { + time.Sleep(400 * time.Millisecond) + fmt.Print("> ") + + line, _, err := r.ReadLine() + if err != nil { + continue + } + + command := string(bytes.TrimSpace(line)) + + // 命令帮助 + if len(command) == 0 || command == "help" || command == "h" || command == "?" || command == "/?" { + lastCommand = command + fmt.Println("TeaTool commands:") + commands := cmd.AllCommands() + + // 对命令代码进行排序 + codes := []string{} + for code := range commands { + codes = append(codes, code) + } + + lists.Sort(codes, func(i int, j int) bool { + code1 := codes[i] + code2 := codes[j] + return code1 < code2 + }) + + //输出 + for _, code := range codes { + ptr := commands[code] + fmt.Println(" ", code+"\n\t\t"+ptr.Name()) + } + continue + } + + if command == "retry" || command == "!!" /** csh like **/ || command == "!-1" /** csh like **/ { + command = lastCommand + fmt.Println("retry '" + command + "'") + } + lastCommand = command + + found := cmd.Try(cmd.ParseArgs(command)) + if !found { + fmt.Println("command '" + command + "' not found") + } + } +} + +// 重置Root +func init() { + webIsSet := false + if !Tea.IsTesting() { + exePath, err := os.Executable() + if err != nil { + exePath = os.Args[0] + } + link, err := filepath.EvalSymlinks(exePath) + if err == nil { + exePath = link + } + fullPath, err := filepath.Abs(exePath) + if err == nil { + Tea.UpdateRoot(filepath.Dir(filepath.Dir(fullPath))) + } + } else { + pwd, ok := os.LookupEnv("PWD") + if ok { + webIsSet = true + Tea.SetPublicDir(pwd + Tea.DS + "web" + Tea.DS + "public") + Tea.SetViewsDir(pwd + Tea.DS + "web" + Tea.DS + "views") + Tea.SetTmpDir(pwd + Tea.DS + "web" + Tea.DS + "tmp") + + Tea.Root = pwd + Tea.DS + "build" + } + } + + if !webIsSet { + Tea.SetPublicDir(Tea.Root + Tea.DS + "web" + Tea.DS + "public") + Tea.SetViewsDir(Tea.Root + Tea.DS + "web" + Tea.DS + "views") + Tea.SetTmpDir(Tea.Root + Tea.DS + "web" + Tea.DS + "tmp") + } + Tea.SetConfigDir(Tea.Root + Tea.DS + "configs") + + _ = os.Setenv("GOPATH", filepath.Dir(Tea.Root)) +} diff --git a/go.mod b/go.mod index 48ec9a6c..838415c7 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,10 @@ module github.com/TeaOSLab/EdgeAPI go 1.14 require ( + github.com/go-sql-driver/mysql v1.5.0 github.com/go-yaml/yaml v2.1.0+incompatible - github.com/golang/protobuf v1.4.1 - github.com/iwind/TeaGo v0.0.0-20200720020412-96dbe21b81d4 + github.com/golang/protobuf v1.4.2 + github.com/iwind/TeaGo v0.0.0-20200722034406-6bf13920e40d github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect google.golang.org/grpc v1.30.0 diff --git a/go.sum b/go.sum index 85c4572f..badd2892 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,11 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/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/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -23,6 +28,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -30,13 +37,24 @@ github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iwind/TeaGo v0.0.0-20200720020412-96dbe21b81d4 h1:893FbgV8PRV/rCqEAtpifgAmsIYTDrZruWHMWIw4+x8= github.com/iwind/TeaGo v0.0.0-20200720020412-96dbe21b81d4/go.mod h1:taNzU+Tt7Axz5t1v8pEV7xRuioNJxbMeMAbDVQpxq20= +github.com/iwind/TeaGo v0.0.0-20200722010955-47dd648dc761 h1:70Iaf6iVF4CiH1P5Au3hqile/2Ea0XIkR4SPpdiaKI0= +github.com/iwind/TeaGo v0.0.0-20200722010955-47dd648dc761/go.mod h1:zjM7k+b+Jthhf0T0fKwuF0iy4TWb5SsU1gmKR2l+OmE= +github.com/iwind/TeaGo v0.0.0-20200722034406-6bf13920e40d h1:W//0gTbKQ44b3gHNz1/fMiKEu+mM5t5O3py4kJscSa0= +github.com/iwind/TeaGo v0.0.0-20200722034406-6bf13920e40d/go.mod h1:zjM7k+b+Jthhf0T0fKwuF0iy4TWb5SsU1gmKR2l+OmE= 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20= github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -47,19 +65,31 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -85,12 +115,16 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/apis/api_node.go b/internal/apis/api_node.go index 278f360d..3f9b29b0 100644 --- a/internal/apis/api_node.go +++ b/internal/apis/api_node.go @@ -3,6 +3,7 @@ package apis import ( "errors" "github.com/TeaOSLab/EdgeAPI/internal/configs" + "github.com/TeaOSLab/EdgeAPI/internal/rpc/admin" "github.com/TeaOSLab/EdgeAPI/internal/rpc/dns" "github.com/TeaOSLab/EdgeAPI/internal/rpc/log" "github.com/TeaOSLab/EdgeAPI/internal/rpc/monitor" @@ -10,6 +11,7 @@ import ( "github.com/TeaOSLab/EdgeAPI/internal/rpc/provider" "github.com/TeaOSLab/EdgeAPI/internal/rpc/stat" "github.com/TeaOSLab/EdgeAPI/internal/rpc/user" + "github.com/TeaOSLab/EdgeAPI/internal/utils" "github.com/iwind/TeaGo/logs" "google.golang.org/grpc" "net" @@ -36,6 +38,9 @@ func (this *APINode) Start() { } sharedAPIConfig = config + // 设置rlimit + _ = utils.SetRLimit(1024 * 1024) + // 监听RPC服务 logs.Println("[API]start rpc: " + config.RPC.Listen) err = this.listenRPC() @@ -59,6 +64,7 @@ func (this *APINode) listenRPC() error { provider.RegisterServiceServer(rpcServer, &provider.Service{}) stat.RegisterServiceServer(rpcServer, &stat.Service{}) user.RegisterServiceServer(rpcServer, &user.Service{}) + admin.RegisterServiceServer(rpcServer, &admin.Service{}) err = rpcServer.Serve(listener) if err != nil { return errors.New("[API]start rpc failed: " + err.Error()) diff --git a/internal/apps/app_cmd.go b/internal/apps/app_cmd.go new file mode 100644 index 00000000..7e671515 --- /dev/null +++ b/internal/apps/app_cmd.go @@ -0,0 +1,234 @@ +package apps + +import ( + "fmt" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/logs" + "os" + "os/exec" + "runtime" + "strconv" + "time" +) + +// App命令帮助 +type AppCmd struct { + product string + version string + usage string + options []*CommandHelpOption + appendStrings []string + + directives []*Directive +} + +func NewAppCmd() *AppCmd { + return &AppCmd{} +} + +type CommandHelpOption struct { + Code string + Description string +} + +// 产品 +func (this *AppCmd) Product(product string) *AppCmd { + this.product = product + return this +} + +// 版本 +func (this *AppCmd) Version(version string) *AppCmd { + this.version = version + return this +} + +// 使用方法 +func (this *AppCmd) Usage(usage string) *AppCmd { + this.usage = usage + return this +} + +// 选项 +func (this *AppCmd) Option(code string, description string) *AppCmd { + this.options = append(this.options, &CommandHelpOption{ + Code: code, + Description: description, + }) + return this +} + +// 附加内容 +func (this *AppCmd) Append(appendString string) *AppCmd { + this.appendStrings = append(this.appendStrings, appendString) + return this +} + +// 打印 +func (this *AppCmd) Print() { + fmt.Println(this.product + " v" + this.version) + + usage := this.usage + fmt.Println("Usage:", "\n "+usage) + + if len(this.options) > 0 { + fmt.Println("") + fmt.Println("Options:") + + spaces := 20 + max := 40 + for _, option := range this.options { + l := len(option.Code) + if l < max && l > spaces { + spaces = l + 4 + } + } + + for _, option := range this.options { + if len(option.Code) > max { + fmt.Println("") + fmt.Println(" " + option.Code) + option.Code = "" + } + + fmt.Printf(" %-"+strconv.Itoa(spaces)+"s%s\n", option.Code, ": "+option.Description) + } + } + + if len(this.appendStrings) > 0 { + fmt.Println("") + for _, s := range this.appendStrings { + fmt.Println(s) + } + } +} + +// 添加指令 +func (this *AppCmd) On(arg string, callback func()) { + this.directives = append(this.directives, &Directive{ + Arg: arg, + Callback: callback, + }) +} + +// 运行 +func (this *AppCmd) Run(main func()) { + // 获取参数 + args := os.Args[1:] + if len(args) > 0 { + switch args[0] { + case "-v", "version", "-version", "--version": + this.runVersion() + return + case "?", "help", "-help", "h", "-h": + this.runHelp() + return + case "start": + this.runStart() + return + case "stop": + this.runStop() + return + case "restart": + this.runRestart() + return + case "status": + this.runStatus() + return + } + + // 查找指令 + for _, directive := range this.directives { + if directive.Arg == args[0] { + directive.Callback() + return + } + } + + fmt.Println("unknown command '" + args[0] + "'") + + return + } + + // 记录PID + _ = this.writePid() + + // 日志 + writer := new(LogWriter) + writer.Init() + logs.SetWriter(writer) + + // 运行主函数 + main() +} + +// 版本号 +func (this *AppCmd) runVersion() { + fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH+")") +} + +// 帮助 +func (this *AppCmd) runHelp() { + this.Print() +} + +// 启动 +func (this *AppCmd) runStart() { + proc := this.checkPid() + if proc != nil { + fmt.Println(this.product+" already started, pid:", proc.Pid) + return + } + + cmd := exec.Command(os.Args[0]) + err := cmd.Start() + if err != nil { + fmt.Println(this.product+" start failed:", err.Error()) + return + } + + fmt.Println(this.product+" started ok, pid:", cmd.Process.Pid) +} + +// 停止 +func (this *AppCmd) runStop() { + proc := this.checkPid() + if proc == nil { + fmt.Println(this.product + " not started yet") + return + } + + // 停止进程 + _ = proc.Kill() + + // 在Windows上经常不能及时释放资源 + _ = DeletePid(Tea.Root + "/bin/pid") + fmt.Println(this.product+" stopped ok, pid:", proc.Pid) +} + +// 重启 +func (this *AppCmd) runRestart() { + this.runStop() + time.Sleep(1 * time.Second) + this.runStart() +} + +// 状态 +func (this *AppCmd) runStatus() { + proc := this.checkPid() + if proc == nil { + fmt.Println(this.product + " not started yet") + } else { + fmt.Println(this.product + " is running, pid: " + fmt.Sprintf("%d", proc.Pid)) + } +} + +// 检查PID +func (this *AppCmd) checkPid() *os.Process { + return CheckPid(Tea.Root + "/bin/pid") +} + +// 写入PID +func (this *AppCmd) writePid() error { + return WritePid(Tea.Root + "/bin/pid") +} diff --git a/internal/apps/directive.go b/internal/apps/directive.go new file mode 100644 index 00000000..9df644ec --- /dev/null +++ b/internal/apps/directive.go @@ -0,0 +1,6 @@ +package apps + +type Directive struct { + Arg string + Callback func() +} diff --git a/internal/apps/file_others.go b/internal/apps/file_others.go new file mode 100644 index 00000000..73bf2fec --- /dev/null +++ b/internal/apps/file_others.go @@ -0,0 +1,17 @@ +// +build !windows + +package apps + +import ( + "os" + "syscall" +) + +// lock file +func LockFile(fp *os.File) error { + return syscall.Flock(int(fp.Fd()), syscall.LOCK_EX|syscall.LOCK_NB) +} + +func UnlockFile(fp *os.File) error { + return syscall.Flock(int(fp.Fd()), syscall.LOCK_UN) +} diff --git a/internal/apps/file_windows.go b/internal/apps/file_windows.go new file mode 100644 index 00000000..fa2028f2 --- /dev/null +++ b/internal/apps/file_windows.go @@ -0,0 +1,17 @@ +// +build windows + +package apps + +import ( + "errors" + "os" +) + +// lock file +func LockFile(fp *os.File) error { + return errors.New("not implemented on windows") +} + +func UnlockFile(fp *os.File) error { + return errors.New("not implemented on windows") +} diff --git a/internal/apps/log_writer.go b/internal/apps/log_writer.go new file mode 100644 index 00000000..ac45c5a7 --- /dev/null +++ b/internal/apps/log_writer.go @@ -0,0 +1,51 @@ +package apps + +import ( + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/files" + "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/utils/time" + "log" +) + +type LogWriter struct { + fileAppender *files.Appender +} + +func (this *LogWriter) Init() { + // 创建目录 + dir := files.NewFile(Tea.LogDir()) + if !dir.Exists() { + err := dir.Mkdir() + if err != nil { + log.Println("[error]" + err.Error()) + } + } + + logFile := files.NewFile(Tea.LogFile("run.log")) + + // 打开要写入的日志文件 + appender, err := logFile.Appender() + if err != nil { + logs.Error(err) + } else { + this.fileAppender = appender + } +} + +func (this *LogWriter) Write(message string) { + log.Println(message) + + if this.fileAppender != nil { + _, err := this.fileAppender.AppendString(timeutil.Format("Y/m/d H:i:s ") + message + "\n") + if err != nil { + log.Println("[error]" + err.Error()) + } + } +} + +func (this *LogWriter) Close() { + if this.fileAppender != nil { + _ = this.fileAppender.Close() + } +} diff --git a/internal/apps/pid.go b/internal/apps/pid.go new file mode 100644 index 00000000..d5076ee3 --- /dev/null +++ b/internal/apps/pid.go @@ -0,0 +1,113 @@ +package apps + +import ( + "fmt" + "github.com/iwind/TeaGo/types" + "io/ioutil" + "os" + "runtime" +) + +var pidFileList = []*os.File{} + +// 检查Pid +func CheckPid(path string) *os.Process { + // windows上打开的文件是不能删除的 + if runtime.GOOS == "windows" { + if os.Remove(path) == nil { + return nil + } + } + + file, err := os.Open(path) + if err != nil { + return nil + } + + defer func() { + _ = file.Close() + }() + + // 是否能取得Lock + err = LockFile(file) + if err == nil { + _ = UnlockFile(file) + return nil + } + + pidBytes, err := ioutil.ReadAll(file) + if err != nil { + return nil + } + pid := types.Int(string(pidBytes)) + + if pid <= 0 { + return nil + } + + proc, _ := os.FindProcess(pid) + return proc +} + +// 写入Pid +func WritePid(path string) error { + fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) + if err != nil { + return err + } + + if runtime.GOOS != "windows" { + err = LockFile(fp) + if err != nil { + return err + } + } + pidFileList = append(pidFileList, fp) // hold the file pointers + + _, err = fp.WriteString(fmt.Sprintf("%d", os.Getpid())) + if err != nil { + return err + } + + return nil +} + +// 写入Ppid +func WritePpid(path string) error { + fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) + if err != nil { + return err + } + + if runtime.GOOS != "windows" { + err = LockFile(fp) + if err != nil { + return err + } + } + pidFileList = append(pidFileList, fp) // hold the file pointers + + _, err = fp.WriteString(fmt.Sprintf("%d", os.Getppid())) + if err != nil { + return err + } + + return nil +} + +// 删除Pid +func DeletePid(path string) error { + _, err := os.Stat(path) + if err != nil { + if !os.IsNotExist(err) { + return nil + } + return err + } + + for _, fp := range pidFileList { + _ = UnlockFile(fp) + _ = fp.Close() + } + return os.Remove(path) +} diff --git a/internal/const/const.go b/internal/const/const.go new file mode 100644 index 00000000..56527acb --- /dev/null +++ b/internal/const/const.go @@ -0,0 +1,16 @@ +package teaconst + +const ( + Version = "0.0.1" + + ProductName = "Edge API" + ProcessName = "edge-api" + ProductNameZH = "Edge" + + Role = "api" + + EncryptKey = "8f983f4d69b83aaa0d74b21a212f6967" + EncryptMethod = "aes-256-cfb" + + ErrServer = "服务器出了点小问题,请稍后重试" +) diff --git a/internal/db/models/admin_dao.go b/internal/db/models/admin_dao.go new file mode 100644 index 00000000..261b24b8 --- /dev/null +++ b/internal/db/models/admin_dao.go @@ -0,0 +1,84 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + AdminStateEnabled = 1 // 已启用 + AdminStateDisabled = 0 // 已禁用 +) + +type AdminDAO dbs.DAO + +func NewAdminDAO() *AdminDAO { + return dbs.NewDAO(&AdminDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeAdmins", + Model: new(Admin), + PkName: "id", + }, + }).(*AdminDAO) +} + +var SharedAdminDAO = NewAdminDAO() + +// 启用条目 +func (this *AdminDAO) EnableAdmin(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", AdminStateEnabled). + Update() +} + +// 禁用条目 +func (this *AdminDAO) DisableAdmin(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", AdminStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *AdminDAO) FindEnabledAdmin(id uint32) (*Admin, error) { + result, err := this.Query(). + Pk(id). + Attr("state", AdminStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*Admin), err +} + +// 检查管理员是否存在 +func (this *AdminDAO) ExistEnabledAdmin(adminId int) (bool, error) { + return this.Query(). + Pk(adminId). + State(AdminStateEnabled). + Exist() +} + +// 获取管理员名称 +func (this *AdminDAO) FindAdminFullname(adminId int) (string, error) { + return this.Query(). + Pk(adminId). + Result("fullname"). + FindStringCol("") +} + +// 检查用户名、密码 +func (this *AdminDAO) CheckAdminPassword(username string, encryptedPassword string) (int, error) { + if len(username) == 0 || len(encryptedPassword) == 0 { + return 0, nil + } + return this.Query(). + Attr("username", username). + Attr("password", encryptedPassword). + Attr("state", AdminStateEnabled). + ResultPk(). + FindIntCol(0) +} diff --git a/internal/db/models/admin_dao_test.go b/internal/db/models/admin_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/admin_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/admin_model.go b/internal/db/models/admin_model.go new file mode 100644 index 00000000..e77e0f13 --- /dev/null +++ b/internal/db/models/admin_model.go @@ -0,0 +1,28 @@ +package models + +// 管理员 +type Admin struct { + Id uint32 `field:"id"` // ID + Username string `field:"username"` // 用户名 + Password string `field:"password"` // 密码 + Fullname string `field:"fullname"` // 全名 + IsSuper uint8 `field:"isSuper"` // 是否为超级管理员 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + UpdatedAt uint32 `field:"updatedAt"` // 修改时间 + State uint8 `field:"state"` // 状态 +} + +type AdminOperator struct { + Id interface{} // ID + Username interface{} // 用户名 + Password interface{} // 密码 + Fullname interface{} // 全名 + IsSuper interface{} // 是否为超级管理员 + CreatedAt interface{} // 创建时间 + UpdatedAt interface{} // 修改时间 + State interface{} // 状态 +} + +func NewAdminOperator() *AdminOperator { + return &AdminOperator{} +} diff --git a/internal/db/models/admin_model_ext.go b/internal/db/models/admin_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/admin_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/db/models/api_token_dao.go b/internal/db/models/api_token_dao.go new file mode 100644 index 00000000..a5b3daf0 --- /dev/null +++ b/internal/db/models/api_token_dao.go @@ -0,0 +1,68 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + ApiTokenStateEnabled = 1 // 已启用 + ApiTokenStateDisabled = 0 // 已禁用 +) + +type ApiTokenDAO dbs.DAO + +func NewApiTokenDAO() *ApiTokenDAO { + return dbs.NewDAO(&ApiTokenDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeApiTokens", + Model: new(ApiToken), + PkName: "id", + }, + }).(*ApiTokenDAO) +} + +var SharedApiTokenDAO = NewApiTokenDAO() + +// 启用条目 +func (this *ApiTokenDAO) EnableApiToken(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ApiTokenStateEnabled). + Update() +} + +// 禁用条目 +func (this *ApiTokenDAO) DisableApiToken(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ApiTokenStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *ApiTokenDAO) FindEnabledApiToken(id uint32) (*ApiToken, error) { + result, err := this.Query(). + Pk(id). + Attr("state", ApiTokenStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*ApiToken), err +} + +// 获取节点Token信息 +// TODO 需要添加缓存 +func (this *ApiTokenDAO) FindEnabledTokenWithNode(nodeId string) (*ApiToken, error) { + one, err := this.Query(). + Attr("nodeId", nodeId). + State(ApiTokenStateEnabled). + Find() + if one != nil { + return one.(*ApiToken), nil + } + return nil, err +} diff --git a/internal/db/models/api_token_dao_test.go b/internal/db/models/api_token_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/api_token_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/api_token_model.go b/internal/db/models/api_token_model.go new file mode 100644 index 00000000..9f0fcd6f --- /dev/null +++ b/internal/db/models/api_token_model.go @@ -0,0 +1,22 @@ +package models + +// API令牌管理 +type ApiToken struct { + Id uint32 `field:"id"` // ID + NodeId string `field:"nodeId"` // 节点ID + Secret string `field:"secret"` // 节点密钥 + Role string `field:"role"` // 节点角色 + State uint8 `field:"state"` // 状态 +} + +type ApiTokenOperator struct { + Id interface{} // ID + NodeId interface{} // 节点ID + Secret interface{} // 节点密钥 + Role interface{} // 节点角色 + State interface{} // 状态 +} + +func NewApiTokenOperator() *ApiTokenOperator { + return &ApiTokenOperator{} +} diff --git a/internal/db/models/init.go b/internal/db/models/init.go new file mode 100644 index 00000000..9b0b5705 --- /dev/null +++ b/internal/db/models/init.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/iwind/TeaGo/bootstrap" +) diff --git a/internal/db/models/log_dao.go b/internal/db/models/log_dao.go new file mode 100644 index 00000000..cafc9a0c --- /dev/null +++ b/internal/db/models/log_dao.go @@ -0,0 +1,31 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +type LogDAO dbs.DAO + +func NewLogDAO() *LogDAO { + return dbs.NewDAO(&LogDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeLogs", + Model: new(Log), + PkName: "id", + }, + }).(*LogDAO) +} + +var SharedLogDAO = NewLogDAO() + +// 创建管理员日志 +func (this *LogDAO) CreateAdminLog(adminId int, level string, description string, action string, ip string) error { + op := NewLogOperator() + op.AdminId, op.Level, op.Description, op.Action, op.Ip = adminId, level, description, action, ip + op.Type = LogTypeAdmin + _, err := this.Save(op) + return err +} diff --git a/internal/db/models/log_dao_test.go b/internal/db/models/log_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/log_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/log_model.go b/internal/db/models/log_model.go new file mode 100644 index 00000000..261f5403 --- /dev/null +++ b/internal/db/models/log_model.go @@ -0,0 +1,32 @@ +package models + +// 操作日志 +type Log struct { + Id uint32 `field:"id"` // ID + Level string `field:"level"` // 级别 + Description string `field:"description"` // 描述 + CreatedAt uint32 `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 +} + +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 +} + +func NewLogOperator() *LogOperator { + return &LogOperator{} +} diff --git a/internal/db/models/node_cluster_dao.go b/internal/db/models/node_cluster_dao.go new file mode 100644 index 00000000..b665b51b --- /dev/null +++ b/internal/db/models/node_cluster_dao.go @@ -0,0 +1,74 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + NodeClusterStateEnabled = 1 // 已启用 + NodeClusterStateDisabled = 0 // 已禁用 +) + +type NodeClusterDAO dbs.DAO + +func NewNodeClusterDAO() *NodeClusterDAO { + return dbs.NewDAO(&NodeClusterDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeNodeClusters", + Model: new(NodeCluster), + PkName: "id", + }, + }).(*NodeClusterDAO) +} + +var SharedNodeClusterDAO = NewNodeClusterDAO() + +// 启用条目 +func (this *NodeClusterDAO) EnableNodeCluster(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeClusterStateEnabled). + Update() +} + +// 禁用条目 +func (this *NodeClusterDAO) DisableNodeCluster(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeClusterStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *NodeClusterDAO) FindEnabledNodeCluster(id uint32) (*NodeCluster, error) { + result, err := this.Query(). + Pk(id). + Attr("state", NodeClusterStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*NodeCluster), err +} + +// 根据主键查找名称 +func (this *NodeClusterDAO) FindNodeClusterName(id uint32) (string, error) { + return this.Query(). + Pk(id). + Result("name"). + FindStringCol("") +} + +// 查找所有可用的集群 +func (this *NodeClusterDAO) FindAllEnableClusters() (result []*NodeCluster, err error) { + _, err = this.Query(). + State(NodeClusterStateEnabled). + Slice(&result). + Desc("order"). + DescPk(). + FindAll() + return +} diff --git a/internal/db/models/node_cluster_dao_test.go b/internal/db/models/node_cluster_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/node_cluster_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/node_cluster_model.go b/internal/db/models/node_cluster_model.go new file mode 100644 index 00000000..a2256ea1 --- /dev/null +++ b/internal/db/models/node_cluster_model.go @@ -0,0 +1,22 @@ +package models + +// 节点集群 +type NodeCluster struct { + Id uint32 `field:"id"` // ID + Name string `field:"name"` // 名称 + Order uint32 `field:"order"` // 排序 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + State uint8 `field:"state"` // 状态 +} + +type NodeClusterOperator struct { + Id interface{} // ID + Name interface{} // 名称 + Order interface{} // 排序 + CreatedAt interface{} // 创建时间 + State interface{} // 状态 +} + +func NewNodeClusterOperator() *NodeClusterOperator { + return &NodeClusterOperator{} +} diff --git a/internal/db/models/node_dao.go b/internal/db/models/node_dao.go new file mode 100644 index 00000000..3f6468da --- /dev/null +++ b/internal/db/models/node_dao.go @@ -0,0 +1,64 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + NodeStateEnabled = 1 // 已启用 + NodeStateDisabled = 0 // 已禁用 +) + +type NodeDAO dbs.DAO + +func NewNodeDAO() *NodeDAO { + return dbs.NewDAO(&NodeDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeNodes", + Model: new(Node), + PkName: "id", + }, + }).(*NodeDAO) +} + +var SharedNodeDAO = NewNodeDAO() + +// 启用条目 +func (this *NodeDAO) EnableNode(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeStateEnabled). + Update() +} + +// 禁用条目 +func (this *NodeDAO) DisableNode(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *NodeDAO) FindEnabledNode(id uint32) (*Node, error) { + result, err := this.Query(). + Pk(id). + Attr("state", NodeStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*Node), err +} + +// 根据主键查找名称 +func (this *NodeDAO) FindNodeName(id uint32) (string, error) { + name, err := this.Query(). + Pk(id). + Result("name"). + FindCol("") + return name.(string), err +} diff --git a/internal/db/models/node_dao_test.go b/internal/db/models/node_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/node_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/node_grant_dao.go b/internal/db/models/node_grant_dao.go new file mode 100644 index 00000000..4a413076 --- /dev/null +++ b/internal/db/models/node_grant_dao.go @@ -0,0 +1,64 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + NodeGrantStateEnabled = 1 // 已启用 + NodeGrantStateDisabled = 0 // 已禁用 +) + +type NodeGrantDAO dbs.DAO + +func NewNodeGrantDAO() *NodeGrantDAO { + return dbs.NewDAO(&NodeGrantDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeNodeGrants", + Model: new(NodeGrant), + PkName: "id", + }, + }).(*NodeGrantDAO) +} + +var SharedNodeGrantDAO = NewNodeGrantDAO() + +// 启用条目 +func (this *NodeGrantDAO) EnableNodeGrant(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeGrantStateEnabled). + Update() +} + +// 禁用条目 +func (this *NodeGrantDAO) DisableNodeGrant(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeGrantStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *NodeGrantDAO) FindEnabledNodeGrant(id uint32) (*NodeGrant, error) { + result, err := this.Query(). + Pk(id). + Attr("state", NodeGrantStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*NodeGrant), err +} + +// 根据主键查找名称 +func (this *NodeGrantDAO) FindNodeGrantName(id uint32) (string, error) { + name, err := this.Query(). + Pk(id). + Result("name"). + FindCol("") + return name.(string), err +} diff --git a/internal/db/models/node_grant_dao_test.go b/internal/db/models/node_grant_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/node_grant_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/node_grant_model.go b/internal/db/models/node_grant_model.go new file mode 100644 index 00000000..d6fada94 --- /dev/null +++ b/internal/db/models/node_grant_model.go @@ -0,0 +1,30 @@ +package models + +// +type NodeGrant struct { + Id uint32 `field:"id"` // ID + Name string `field:"name"` // 名称 + Username string `field:"username"` // 用户名 + Password string `field:"password"` // 密码 + Su uint8 `field:"su"` // 是否需要su + PrivateKey string `field:"privateKey"` // 密钥 + Description string `field:"description"` // 备注 + NodeId uint32 `field:"nodeId"` // 专有节点 + State uint8 `field:"state"` // 状态 +} + +type NodeGrantOperator struct { + Id interface{} // ID + Name interface{} // 名称 + Username interface{} // 用户名 + Password interface{} // 密码 + Su interface{} // 是否需要su + PrivateKey interface{} // 密钥 + Description interface{} // 备注 + NodeId interface{} // 专有节点 + State interface{} // 状态 +} + +func NewNodeGrantOperator() *NodeGrantOperator { + return &NodeGrantOperator{} +} diff --git a/internal/db/models/node_grant_model_ext.go b/internal/db/models/node_grant_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/node_grant_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/db/models/node_group_dao.go b/internal/db/models/node_group_dao.go new file mode 100644 index 00000000..28f5a69c --- /dev/null +++ b/internal/db/models/node_group_dao.go @@ -0,0 +1,64 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + NodeGroupStateEnabled = 1 // 已启用 + NodeGroupStateDisabled = 0 // 已禁用 +) + +type NodeGroupDAO dbs.DAO + +func NewNodeGroupDAO() *NodeGroupDAO { + return dbs.NewDAO(&NodeGroupDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeNodeGroups", + Model: new(NodeGroup), + PkName: "id", + }, + }).(*NodeGroupDAO) +} + +var SharedNodeGroupDAO = NewNodeGroupDAO() + +// 启用条目 +func (this *NodeGroupDAO) EnableNodeGroup(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeGroupStateEnabled). + Update() +} + +// 禁用条目 +func (this *NodeGroupDAO) DisableNodeGroup(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeGroupStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *NodeGroupDAO) FindEnabledNodeGroup(id uint32) (*NodeGroup, error) { + result, err := this.Query(). + Pk(id). + Attr("state", NodeGroupStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*NodeGroup), err +} + +// 根据主键查找名称 +func (this *NodeGroupDAO) FindNodeGroupName(id uint32) (string, error) { + name, err := this.Query(). + Pk(id). + Result("name"). + FindCol("") + return name.(string), err +} diff --git a/internal/db/models/node_group_dao_test.go b/internal/db/models/node_group_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/node_group_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/node_group_model.go b/internal/db/models/node_group_model.go new file mode 100644 index 00000000..26d3ec8b --- /dev/null +++ b/internal/db/models/node_group_model.go @@ -0,0 +1,22 @@ +package models + +// 节点分组 +type NodeGroup struct { + Id uint32 `field:"id"` // ID + Name string `field:"name"` // 名称 + Order uint32 `field:"order"` // 排序 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + State uint8 `field:"state"` // 状态 +} + +type NodeGroupOperator struct { + Id interface{} // ID + Name interface{} // 名称 + Order interface{} // 排序 + CreatedAt interface{} // 创建时间 + State interface{} // 状态 +} + +func NewNodeGroupOperator() *NodeGroupOperator { + return &NodeGroupOperator{} +} diff --git a/internal/db/models/node_login_dao.go b/internal/db/models/node_login_dao.go new file mode 100644 index 00000000..596b934d --- /dev/null +++ b/internal/db/models/node_login_dao.go @@ -0,0 +1,64 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + NodeLoginStateEnabled = 1 // 已启用 + NodeLoginStateDisabled = 0 // 已禁用 +) + +type NodeLoginDAO dbs.DAO + +func NewNodeLoginDAO() *NodeLoginDAO { + return dbs.NewDAO(&NodeLoginDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeNodeLogins", + Model: new(NodeLogin), + PkName: "id", + }, + }).(*NodeLoginDAO) +} + +var SharedNodeLoginDAO = NewNodeLoginDAO() + +// 启用条目 +func (this *NodeLoginDAO) EnableNodeLogin(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeLoginStateEnabled). + Update() +} + +// 禁用条目 +func (this *NodeLoginDAO) DisableNodeLogin(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", NodeLoginStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *NodeLoginDAO) FindEnabledNodeLogin(id uint32) (*NodeLogin, error) { + result, err := this.Query(). + Pk(id). + Attr("state", NodeLoginStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*NodeLogin), err +} + +// 根据主键查找名称 +func (this *NodeLoginDAO) FindNodeLoginName(id uint32) (string, error) { + name, err := this.Query(). + Pk(id). + Result("name"). + FindCol("") + return name.(string), err +} diff --git a/internal/db/models/node_login_dao_test.go b/internal/db/models/node_login_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/node_login_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/node_login_model.go b/internal/db/models/node_login_model.go new file mode 100644 index 00000000..19a69b06 --- /dev/null +++ b/internal/db/models/node_login_model.go @@ -0,0 +1,24 @@ +package models + +// +type NodeLogin struct { + Id uint32 `field:"id"` // ID + NodeId uint32 `field:"nodeId"` // 节点ID + Name string `field:"name"` // 名称 + Type string `field:"type"` // 类型:ssh,agent + Params string `field:"params"` // 配置参数 + State uint8 `field:"state"` // 状态 +} + +type NodeLoginOperator struct { + Id interface{} // ID + NodeId interface{} // 节点ID + Name interface{} // 名称 + Type interface{} // 类型:ssh,agent + Params interface{} // 配置参数 + State interface{} // 状态 +} + +func NewNodeLoginOperator() *NodeLoginOperator { + return &NodeLoginOperator{} +} diff --git a/internal/db/models/node_login_model_ext.go b/internal/db/models/node_login_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/node_login_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/db/models/node_model.go b/internal/db/models/node_model.go new file mode 100644 index 00000000..0b26550b --- /dev/null +++ b/internal/db/models/node_model.go @@ -0,0 +1,34 @@ +package models + +// 节点 +type Node struct { + Id uint32 `field:"id"` // ID + NodeId string `field:"nodeId"` // 节点ID + Secret string `field:"secret"` // 密钥 + Name string `field:"name"` // 节点名 + Code string `field:"code"` // 代号 + ClusterId uint32 `field:"clusterId"` // 集群ID + RegionId uint32 `field:"regionId"` // 区域ID + GroupId uint32 `field:"groupId"` // 分组ID + CreatedAt uint32 `field:"createdAt"` // 创建时间 + Status string `field:"status"` // 最新的状态 + State uint8 `field:"state"` // 状态 +} + +type NodeOperator struct { + Id interface{} // ID + NodeId interface{} // 节点ID + Secret interface{} // 密钥 + Name interface{} // 节点名 + Code interface{} // 代号 + ClusterId interface{} // 集群ID + RegionId interface{} // 区域ID + GroupId interface{} // 分组ID + CreatedAt interface{} // 创建时间 + Status interface{} // 最新的状态 + State interface{} // 状态 +} + +func NewNodeOperator() *NodeOperator { + return &NodeOperator{} +} diff --git a/internal/db/models/node_model_ext.go b/internal/db/models/node_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/node_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/db/models/notify_levels.go b/internal/db/models/notify_levels.go new file mode 100644 index 00000000..dbccd6e8 --- /dev/null +++ b/internal/db/models/notify_levels.go @@ -0,0 +1,11 @@ +package models + +const ( + LevelDebug = "debug" + LevelInfo = "info" + LevelWarning = "warning" + LevelError = "error" + + LogTypeAdmin = "admin" + LogTypeUser = "user" +) diff --git a/internal/db/models/provider_dao.go b/internal/db/models/provider_dao.go new file mode 100644 index 00000000..2cc28b3b --- /dev/null +++ b/internal/db/models/provider_dao.go @@ -0,0 +1,55 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + ProviderStateEnabled = 1 // 已启用 + ProviderStateDisabled = 0 // 已禁用 +) + +type ProviderDAO dbs.DAO + +func NewProviderDAO() *ProviderDAO { + return dbs.NewDAO(&ProviderDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeProviders", + Model: new(Provider), + PkName: "id", + }, + }).(*ProviderDAO) +} + +var SharedProviderDAO = NewProviderDAO() + +// 启用条目 +func (this *ProviderDAO) EnableProvider(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ProviderStateEnabled). + Update() +} + +// 禁用条目 +func (this *ProviderDAO) DisableProvider(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ProviderStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *ProviderDAO) FindEnabledProvider(id uint32) (*Provider, error) { + result, err := this.Query(). + Pk(id). + Attr("state", ProviderStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*Provider), err +} diff --git a/internal/db/models/provider_dao_test.go b/internal/db/models/provider_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/provider_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/provider_model.go b/internal/db/models/provider_model.go new file mode 100644 index 00000000..471288be --- /dev/null +++ b/internal/db/models/provider_model.go @@ -0,0 +1,26 @@ +package models + +// 供应商 +type Provider struct { + Id uint32 `field:"id"` // ID + Username string `field:"username"` // 用户名 + Password string `field:"password"` // 密码 + Fullname string `field:"fullname"` // 真实姓名 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + UpdatedAt uint32 `field:"updatedAt"` // 修改时间 + State uint8 `field:"state"` // 状态 +} + +type ProviderOperator struct { + Id interface{} // ID + Username interface{} // 用户名 + Password interface{} // 密码 + Fullname interface{} // 真实姓名 + CreatedAt interface{} // 创建时间 + UpdatedAt interface{} // 修改时间 + State interface{} // 状态 +} + +func NewProviderOperator() *ProviderOperator { + return &ProviderOperator{} +} diff --git a/internal/db/models/server_dao.go b/internal/db/models/server_dao.go new file mode 100644 index 00000000..5c776491 --- /dev/null +++ b/internal/db/models/server_dao.go @@ -0,0 +1,55 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + ServerStateEnabled = 1 // 已启用 + ServerStateDisabled = 0 // 已禁用 +) + +type ServerDAO dbs.DAO + +func NewServerDAO() *ServerDAO { + return dbs.NewDAO(&ServerDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeServers", + Model: new(Server), + PkName: "id", + }, + }).(*ServerDAO) +} + +var SharedServerDAO = NewServerDAO() + +// 启用条目 +func (this *ServerDAO) EnableServer(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ServerStateEnabled). + Update() +} + +// 禁用条目 +func (this *ServerDAO) DisableServer(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ServerStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *ServerDAO) FindEnabledServer(id uint32) (*Server, error) { + result, err := this.Query(). + Pk(id). + Attr("state", ServerStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*Server), err +} diff --git a/internal/db/models/server_dao_test.go b/internal/db/models/server_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/server_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/server_group_dao.go b/internal/db/models/server_group_dao.go new file mode 100644 index 00000000..653f5949 --- /dev/null +++ b/internal/db/models/server_group_dao.go @@ -0,0 +1,64 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + ServerGroupStateEnabled = 1 // 已启用 + ServerGroupStateDisabled = 0 // 已禁用 +) + +type ServerGroupDAO dbs.DAO + +func NewServerGroupDAO() *ServerGroupDAO { + return dbs.NewDAO(&ServerGroupDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeServerGroups", + Model: new(ServerGroup), + PkName: "id", + }, + }).(*ServerGroupDAO) +} + +var SharedServerGroupDAO = NewServerGroupDAO() + +// 启用条目 +func (this *ServerGroupDAO) EnableServerGroup(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ServerGroupStateEnabled). + Update() +} + +// 禁用条目 +func (this *ServerGroupDAO) DisableServerGroup(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", ServerGroupStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *ServerGroupDAO) FindEnabledServerGroup(id uint32) (*ServerGroup, error) { + result, err := this.Query(). + Pk(id). + Attr("state", ServerGroupStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*ServerGroup), err +} + +// 根据主键查找名称 +func (this *ServerGroupDAO) FindServerGroupName(id uint32) (string, error) { + name, err := this.Query(). + Pk(id). + Result("name"). + FindCol("") + return name.(string), err +} diff --git a/internal/db/models/server_group_dao_test.go b/internal/db/models/server_group_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/server_group_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/server_group_model.go b/internal/db/models/server_group_model.go new file mode 100644 index 00000000..6dec8d83 --- /dev/null +++ b/internal/db/models/server_group_model.go @@ -0,0 +1,26 @@ +package models + +// 服务分组 +type ServerGroup struct { + Id uint32 `field:"id"` // ID + AdminId uint32 `field:"adminId"` // 管理员ID + UserId uint32 `field:"userId"` // 用户ID + Name string `field:"name"` // 名称 + Order uint32 `field:"order"` // 排序 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + State uint8 `field:"state"` // 状态 +} + +type ServerGroupOperator struct { + Id interface{} // ID + AdminId interface{} // 管理员ID + UserId interface{} // 用户ID + Name interface{} // 名称 + Order interface{} // 排序 + CreatedAt interface{} // 创建时间 + State interface{} // 状态 +} + +func NewServerGroupOperator() *ServerGroupOperator { + return &ServerGroupOperator{} +} diff --git a/internal/db/models/server_model.go b/internal/db/models/server_model.go new file mode 100644 index 00000000..25b94714 --- /dev/null +++ b/internal/db/models/server_model.go @@ -0,0 +1,32 @@ +package models + +// 服务 +type Server struct { + Id uint32 `field:"id"` // ID + UserId uint32 `field:"userId"` // 用户ID + AdminId uint32 `field:"adminId"` // 管理员ID + GroupIds string `field:"groupIds"` // 分组ID列表 + Config string `field:"config"` // 服务配置,自动生成 + IncludeNodes string `field:"includeNodes"` // 部署条件 + ExcludeNodes string `field:"excludeNodes"` // 节点排除条件 + Version uint32 `field:"version"` // 版本号 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + State uint8 `field:"state"` // 状态 +} + +type ServerOperator struct { + Id interface{} // ID + UserId interface{} // 用户ID + AdminId interface{} // 管理员ID + GroupIds interface{} // 分组ID列表 + Config interface{} // 服务配置,自动生成 + IncludeNodes interface{} // 部署条件 + ExcludeNodes interface{} // 节点排除条件 + Version interface{} // 版本号 + CreatedAt interface{} // 创建时间 + State interface{} // 状态 +} + +func NewServerOperator() *ServerOperator { + return &ServerOperator{} +} diff --git a/internal/db/models/server_model_ext.go b/internal/db/models/server_model_ext.go new file mode 100644 index 00000000..2640e7f9 --- /dev/null +++ b/internal/db/models/server_model_ext.go @@ -0,0 +1 @@ +package models diff --git a/internal/db/models/user_dao.go b/internal/db/models/user_dao.go new file mode 100644 index 00000000..3641a723 --- /dev/null +++ b/internal/db/models/user_dao.go @@ -0,0 +1,55 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" + "github.com/iwind/TeaGo/Tea" + "github.com/iwind/TeaGo/dbs" +) + +const ( + UserStateEnabled = 1 // 已启用 + UserStateDisabled = 0 // 已禁用 +) + +type UserDAO dbs.DAO + +func NewUserDAO() *UserDAO { + return dbs.NewDAO(&UserDAO{ + DAOObject: dbs.DAOObject{ + DB: Tea.Env, + Table: "edgeUsers", + Model: new(User), + PkName: "id", + }, + }).(*UserDAO) +} + +var SharedUserDAO = NewUserDAO() + +// 启用条目 +func (this *UserDAO) EnableUser(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", UserStateEnabled). + Update() +} + +// 禁用条目 +func (this *UserDAO) DisableUser(id uint32) (rowsAffected int64, err error) { + return this.Query(). + Pk(id). + Set("state", UserStateDisabled). + Update() +} + +// 查找启用中的条目 +func (this *UserDAO) FindEnabledUser(id uint32) (*User, error) { + result, err := this.Query(). + Pk(id). + Attr("state", UserStateEnabled). + Find() + if result == nil { + return nil, err + } + return result.(*User), err +} diff --git a/internal/db/models/user_dao_test.go b/internal/db/models/user_dao_test.go new file mode 100644 index 00000000..97c24b56 --- /dev/null +++ b/internal/db/models/user_dao_test.go @@ -0,0 +1,5 @@ +package models + +import ( + _ "github.com/go-sql-driver/mysql" +) diff --git a/internal/db/models/user_model.go b/internal/db/models/user_model.go new file mode 100644 index 00000000..cc1c2839 --- /dev/null +++ b/internal/db/models/user_model.go @@ -0,0 +1,26 @@ +package models + +// +type User struct { + Id uint32 `field:"id"` // ID + Username string `field:"username"` // 用户名 + Password string `field:"password"` // 密码 + Fullname string `field:"fullname"` // 真实姓名 + CreatedAt uint32 `field:"createdAt"` // 创建时间 + UpdatedAt uint32 `field:"updatedAt"` // 修改时间 + State uint8 `field:"state"` // 状态 +} + +type UserOperator struct { + Id interface{} // ID + Username interface{} // 用户名 + Password interface{} // 密码 + Fullname interface{} // 真实姓名 + CreatedAt interface{} // 创建时间 + UpdatedAt interface{} // 修改时间 + State interface{} // 状态 +} + +func NewUserOperator() *UserOperator { + return &UserOperator{} +} diff --git a/internal/encrypt/magic_key.go b/internal/encrypt/magic_key.go new file mode 100644 index 00000000..bf610ef6 --- /dev/null +++ b/internal/encrypt/magic_key.go @@ -0,0 +1,41 @@ +package encrypt + +import ( + "github.com/iwind/TeaGo/logs" +) + +const ( + MagicKey = "f1c8eafb543f03023e97b7be864a4e9b" +) + +// 加密特殊信息 +func MagicKeyEncode(data []byte) []byte { + method, err := NewMethodInstance("aes-256-cfb", MagicKey, MagicKey[:16]) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + + dst, err := method.Encrypt(data) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + return dst +} + +// 解密特殊信息 +func MagicKeyDecode(data []byte) []byte { + method, err := NewMethodInstance("aes-256-cfb", MagicKey, MagicKey[:16]) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + + src, err := method.Decrypt(data) + if err != nil { + logs.Println("[MagicKeyEncode]" + err.Error()) + return data + } + return src +} diff --git a/internal/encrypt/magic_key_test.go b/internal/encrypt/magic_key_test.go new file mode 100644 index 00000000..2d182def --- /dev/null +++ b/internal/encrypt/magic_key_test.go @@ -0,0 +1,11 @@ +package encrypt + +import "testing" + +func TestMagicKeyEncode(t *testing.T) { + dst := MagicKeyEncode([]byte("Hello,World")) + t.Log("dst:", string(dst)) + + src := MagicKeyDecode(dst) + t.Log("src:", string(src)) +} diff --git a/internal/encrypt/method.go b/internal/encrypt/method.go new file mode 100644 index 00000000..a939b977 --- /dev/null +++ b/internal/encrypt/method.go @@ -0,0 +1,12 @@ +package encrypt + +type MethodInterface interface { + // 初始化 + Init(key []byte, iv []byte) error + + // 加密 + Encrypt(src []byte) (dst []byte, err error) + + // 解密 + Decrypt(dst []byte) (src []byte, err error) +} diff --git a/internal/encrypt/method_aes_128_cfb.go b/internal/encrypt/method_aes_128_cfb.go new file mode 100644 index 00000000..6f3eab45 --- /dev/null +++ b/internal/encrypt/method_aes_128_cfb.go @@ -0,0 +1,73 @@ +package encrypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" +) + +type AES128CFBMethod struct { + iv []byte + block cipher.Block +} + +func (this *AES128CFBMethod) Init(key, iv []byte) error { + // 判断key是否为32长度 + l := len(key) + if l > 16 { + key = key[:16] + } else if l < 16 { + key = append(key, bytes.Repeat([]byte{' '}, 16-l)...) + } + + // 判断iv长度 + l2 := len(iv) + if l2 > aes.BlockSize { + iv = iv[:aes.BlockSize] + } else if l2 < aes.BlockSize { + iv = append(iv, bytes.Repeat([]byte{' '}, aes.BlockSize-l2)...) + } + + this.iv = iv + + // block + block, err := aes.NewCipher(key) + if err != nil { + return err + } + this.block = block + + return nil +} + +func (this *AES128CFBMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + dst = make([]byte, len(src)) + encrypter := cipher.NewCFBEncrypter(this.block, this.iv) + encrypter.XORKeyStream(dst, src) + + return +} + +func (this *AES128CFBMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + src = make([]byte, len(dst)) + encrypter := cipher.NewCFBDecrypter(this.block, this.iv) + encrypter.XORKeyStream(src, dst) + + return +} diff --git a/internal/encrypt/method_aes_128_cfb_test.go b/internal/encrypt/method_aes_128_cfb_test.go new file mode 100644 index 00000000..9e1b8f74 --- /dev/null +++ b/internal/encrypt/method_aes_128_cfb_test.go @@ -0,0 +1,92 @@ +package encrypt + +import ( + "runtime" + "strings" + "testing" +) + +func TestAES128CFBMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("aes-128-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src = make([]byte, len(src)) + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} + +func TestAES128CFBMethod_Encrypt2(t *testing.T) { + method, err := NewMethodInstance("aes-128-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + + sources := [][]byte{} + + { + a := []byte{1} + _, err = method.Encrypt(a) + if err != nil { + t.Fatal(err) + } + } + + for i := 0; i < 10; i++ { + src := []byte(strings.Repeat("Hello", 1)) + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + + sources = append(sources, dst) + } + + { + + a := []byte{1} + _, err = method.Decrypt(a) + if err != nil { + t.Fatal(err) + } + } + + for _, dst := range sources { + dst2 := append([]byte{}, dst...) + src2 := make([]byte, len(dst2)) + src2, err := method.Decrypt(dst2) + if err != nil { + t.Fatal(err) + } + t.Log(string(src2)) + } +} + +func BenchmarkAES128CFBMethod_Encrypt(b *testing.B) { + runtime.GOMAXPROCS(1) + + method, err := NewMethodInstance("aes-128-cfb", "abc", "123") + if err != nil { + b.Fatal(err) + } + + src := []byte(strings.Repeat("Hello", 1024)) + for i := 0; i < b.N; i++ { + dst, err := method.Encrypt(src) + if err != nil { + b.Fatal(err) + } + _ = dst + } +} diff --git a/internal/encrypt/method_aes_192_cfb.go b/internal/encrypt/method_aes_192_cfb.go new file mode 100644 index 00000000..1ac4be36 --- /dev/null +++ b/internal/encrypt/method_aes_192_cfb.go @@ -0,0 +1,74 @@ +package encrypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" +) + +type AES192CFBMethod struct { + block cipher.Block + iv []byte +} + +func (this *AES192CFBMethod) Init(key, iv []byte) error { + // 判断key是否为24长度 + l := len(key) + if l > 24 { + key = key[:24] + } else if l < 24 { + key = append(key, bytes.Repeat([]byte{' '}, 24-l)...) + } + + block, err := aes.NewCipher(key) + if err != nil { + return err + } + this.block = block + + // 判断iv长度 + l2 := len(iv) + if l2 > aes.BlockSize { + iv = iv[:aes.BlockSize] + } else if l2 < aes.BlockSize { + iv = append(iv, bytes.Repeat([]byte{' '}, aes.BlockSize-l2)...) + } + + this.iv = iv + + return nil +} + +func (this *AES192CFBMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + dst = make([]byte, len(src)) + + encrypter := cipher.NewCFBEncrypter(this.block, this.iv) + encrypter.XORKeyStream(dst, src) + + return +} + +func (this *AES192CFBMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + src = make([]byte, len(dst)) + + decrypter := cipher.NewCFBDecrypter(this.block, this.iv) + decrypter.XORKeyStream(src, dst) + + return +} diff --git a/internal/encrypt/method_aes_192_cfb_test.go b/internal/encrypt/method_aes_192_cfb_test.go new file mode 100644 index 00000000..968b3965 --- /dev/null +++ b/internal/encrypt/method_aes_192_cfb_test.go @@ -0,0 +1,45 @@ +package encrypt + +import ( + "runtime" + "strings" + "testing" +) + +func TestAES192CFBMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("aes-192-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} + +func BenchmarkAES192CFBMethod_Encrypt(b *testing.B) { + runtime.GOMAXPROCS(1) + + method, err := NewMethodInstance("aes-192-cfb", "abc", "123") + if err != nil { + b.Fatal(err) + } + + src := []byte(strings.Repeat("Hello", 1024)) + for i := 0; i < b.N; i++ { + dst, err := method.Encrypt(src) + if err != nil { + b.Fatal(err) + } + _ = dst + } +} diff --git a/internal/encrypt/method_aes_256_cfb.go b/internal/encrypt/method_aes_256_cfb.go new file mode 100644 index 00000000..fb266f68 --- /dev/null +++ b/internal/encrypt/method_aes_256_cfb.go @@ -0,0 +1,72 @@ +package encrypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" +) + +type AES256CFBMethod struct { + block cipher.Block + iv []byte +} + +func (this *AES256CFBMethod) Init(key, iv []byte) error { + // 判断key是否为32长度 + l := len(key) + if l > 32 { + key = key[:32] + } else if l < 32 { + key = append(key, bytes.Repeat([]byte{' '}, 32-l)...) + } + + block, err := aes.NewCipher(key) + if err != nil { + return err + } + this.block = block + + // 判断iv长度 + l2 := len(iv) + if l2 > aes.BlockSize { + iv = iv[:aes.BlockSize] + } else if l2 < aes.BlockSize { + iv = append(iv, bytes.Repeat([]byte{' '}, aes.BlockSize-l2)...) + } + this.iv = iv + + return nil +} + +func (this *AES256CFBMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + dst = make([]byte, len(src)) + + encrypter := cipher.NewCFBEncrypter(this.block, this.iv) + encrypter.XORKeyStream(dst, src) + + return +} + +func (this *AES256CFBMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + + defer func() { + err = RecoverMethodPanic(recover()) + }() + + src = make([]byte, len(dst)) + decrypter := cipher.NewCFBDecrypter(this.block, this.iv) + decrypter.XORKeyStream(src, dst) + + return +} diff --git a/internal/encrypt/method_aes_256_cfb_test.go b/internal/encrypt/method_aes_256_cfb_test.go new file mode 100644 index 00000000..a694e496 --- /dev/null +++ b/internal/encrypt/method_aes_256_cfb_test.go @@ -0,0 +1,42 @@ +package encrypt + +import "testing" + +func TestAES256CFBMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("aes-256-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} + +func TestAES256CFBMethod_Encrypt2(t *testing.T) { + method, err := NewMethodInstance("aes-256-cfb", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} diff --git a/internal/encrypt/method_raw.go b/internal/encrypt/method_raw.go new file mode 100644 index 00000000..b9fb0b9d --- /dev/null +++ b/internal/encrypt/method_raw.go @@ -0,0 +1,26 @@ +package encrypt + +type RawMethod struct { +} + +func (this *RawMethod) Init(key, iv []byte) error { + return nil +} + +func (this *RawMethod) Encrypt(src []byte) (dst []byte, err error) { + if len(src) == 0 { + return + } + dst = make([]byte, len(src)) + copy(dst, src) + return +} + +func (this *RawMethod) Decrypt(dst []byte) (src []byte, err error) { + if len(dst) == 0 { + return + } + src = make([]byte, len(dst)) + copy(src, dst) + return +} diff --git a/internal/encrypt/method_raw_test.go b/internal/encrypt/method_raw_test.go new file mode 100644 index 00000000..b9403f65 --- /dev/null +++ b/internal/encrypt/method_raw_test.go @@ -0,0 +1,23 @@ +package encrypt + +import "testing" + +func TestRawMethod_Encrypt(t *testing.T) { + method, err := NewMethodInstance("raw", "abc", "123") + if err != nil { + t.Fatal(err) + } + src := []byte("Hello, World") + dst, err := method.Encrypt(src) + if err != nil { + t.Fatal(err) + } + dst = dst[:len(src)] + t.Log("dst:", string(dst)) + + src, err = method.Decrypt(dst) + if err != nil { + t.Fatal(err) + } + t.Log("src:", string(src)) +} diff --git a/internal/encrypt/method_utils.go b/internal/encrypt/method_utils.go new file mode 100644 index 00000000..99879ad5 --- /dev/null +++ b/internal/encrypt/method_utils.go @@ -0,0 +1,43 @@ +package encrypt + +import ( + "errors" + "reflect" +) + +var methods = map[string]reflect.Type{ + "raw": reflect.TypeOf(new(RawMethod)).Elem(), + "aes-128-cfb": reflect.TypeOf(new(AES128CFBMethod)).Elem(), + "aes-192-cfb": reflect.TypeOf(new(AES192CFBMethod)).Elem(), + "aes-256-cfb": reflect.TypeOf(new(AES256CFBMethod)).Elem(), +} + +func NewMethodInstance(method string, key string, iv string) (MethodInterface, error) { + valueType, ok := methods[method] + if !ok { + return nil, errors.New("method '" + method + "' not found") + } + instance, ok := reflect.New(valueType).Interface().(MethodInterface) + if !ok { + return nil, errors.New("method '" + method + "' must implement MethodInterface") + } + err := instance.Init([]byte(key), []byte(iv)) + return instance, err +} + +func RecoverMethodPanic(err interface{}) error { + if err != nil { + s, ok := err.(string) + if ok { + return errors.New(s) + } + + e, ok := err.(error) + if ok { + return e + } + + return errors.New("unknown error") + } + return nil +} diff --git a/internal/encrypt/method_utils_test.go b/internal/encrypt/method_utils_test.go new file mode 100644 index 00000000..faf7e1d4 --- /dev/null +++ b/internal/encrypt/method_utils_test.go @@ -0,0 +1,8 @@ +package encrypt + +import "testing" + +func TestFindMethodInstance(t *testing.T) { + t.Log(NewMethodInstance("a", "b", "")) + t.Log(NewMethodInstance("aes-256-cfb", "123456", "")) +} diff --git a/internal/rpc/admin/service.go b/internal/rpc/admin/service.go new file mode 100644 index 00000000..f05ee4c8 --- /dev/null +++ b/internal/rpc/admin/service.go @@ -0,0 +1,181 @@ +package admin + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + teaconst "github.com/TeaOSLab/EdgeAPI/internal/const" + "github.com/TeaOSLab/EdgeAPI/internal/db/models" + "github.com/TeaOSLab/EdgeAPI/internal/encrypt" + "github.com/TeaOSLab/EdgeAPI/internal/utils" + "github.com/iwind/TeaGo/maps" + "google.golang.org/grpc/metadata" + "time" +) + +type Service struct { + debug bool +} + +func (this *Service) Login(ctx context.Context, req *LoginRequest) (*LoginResponse, error) { + _, err := this.validateRequest(ctx) + if err != nil { + return nil, err + } + + if len(req.Username) == 0 || len(req.Password) == 0 { + return &LoginResponse{ + AdminId: 0, + IsOk: false, + Message: "请输入正确的用户名密码", + }, nil + } + + adminId, err := models.SharedAdminDAO.CheckAdminPassword(req.Username, req.Password) + if err != nil { + utils.PrintError(err) + return nil, err + } + + if adminId <= 0 { + return &LoginResponse{ + AdminId: 0, + IsOk: false, + Message: "请输入正确的用户名密码", + }, nil + } + + return &LoginResponse{ + AdminId: int64(adminId), + IsOk: true, + }, nil +} + +func (this *Service) CreateLog(ctx context.Context, req *CreateLogRequest) (*CreateLogResponse, error) { + adminId, err := this.validateAdminRequest(ctx) + if err != nil { + return nil, err + } + err = models.SharedLogDAO.CreateAdminLog(adminId, req.Level, req.Description, req.Action, req.Ip) + return &CreateLogResponse{ + IsOk: err != nil, + }, err +} + +func (this *Service) CheckAdminExists(ctx context.Context, req *CheckAdminExistsRequest) (*CheckAdminExistsResponse, error) { + _, err := this.validateRequest(ctx) + if err != nil { + return nil, err + } + + if req.AdminId <= 0 { + return &CheckAdminExistsResponse{ + IsOk: false, + }, nil + } + + ok, err := models.SharedAdminDAO.ExistEnabledAdmin(int(req.AdminId)) + if err != nil { + return nil, err + } + + return &CheckAdminExistsResponse{ + IsOk: ok, + }, nil +} + +func (this *Service) FindAdminFullname(ctx context.Context, req *FindAdminNameRequest) (*FindAdminNameResponse, error) { + _, err := this.validateRequest(ctx) + if err != nil { + return nil, err + } + + fullname, err := models.SharedAdminDAO.FindAdminFullname(int(req.AdminId)) + if err != nil { + utils.PrintError(err) + return nil, err + } + + return &FindAdminNameResponse{ + Fullname: fullname, + }, nil +} + +func (this *Service) validateRequest(ctx context.Context) (adminId int, err error) { + var md metadata.MD + var ok bool + if this.debug { + md, ok = metadata.FromOutgoingContext(ctx) + } else { + md, ok = metadata.FromIncomingContext(ctx) + } + if !ok { + return 0, errors.New("context: need 'nodeId'") + } + nodeIds := md.Get("nodeid") + if len(nodeIds) == 0 || len(nodeIds[0]) == 0 { + return 0, errors.New("context: need 'nodeId'") + } + nodeId := nodeIds[0] + + // 获取Node信息 + apiToken, err := models.SharedApiTokenDAO.FindEnabledTokenWithNode(nodeId) + if err != nil { + utils.PrintError(err) + return 0, err + } + if apiToken == nil { + return 0, errors.New("can not find token from node id: " + err.Error()) + } + + tokens := md.Get("token") + if len(tokens) == 0 || len(tokens[0]) == 0 { + return 0, errors.New("context: need 'token'") + } + token := tokens[0] + + data, err := base64.StdEncoding.DecodeString(token) + if err != nil { + return 0, err + } + + method, err := encrypt.NewMethodInstance(teaconst.EncryptMethod, apiToken.Secret, nodeId) + if err != nil { + utils.PrintError(err) + return 0, err + } + data, err = method.Decrypt(data) + if err != nil { + return 0, err + } + if len(data) == 0 { + return 0, errors.New("invalid token") + } + + m := maps.Map{} + err = json.Unmarshal(data, &m) + if err != nil { + return 0, errors.New("decode token error: " + err.Error()) + } + + timestamp := m.GetInt64("timestamp") + if time.Now().Unix()-timestamp > 600 { + // 请求超过10分钟认为超时 + return 0, errors.New("authenticate timeout") + } + + adminId = m.GetInt("adminId") + return +} + +func (this *Service) validateAdminRequest(ctx context.Context) (adminId int, err error) { + adminId, err = this.validateRequest(ctx) + if err != nil { + return 0, err + } + if adminId <= 0 { + return 0, errors.New("invalid admin id") + } + return +} diff --git a/internal/rpc/admin/service.pb.go b/internal/rpc/admin/service.pb.go index fa5d1efe..60aa673e 100644 --- a/internal/rpc/admin/service.pb.go +++ b/internal/rpc/admin/service.pb.go @@ -33,6 +33,9 @@ type LoginRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` } func (x *LoginRequest) Reset() { @@ -67,10 +70,28 @@ func (*LoginRequest) Descriptor() ([]byte, []int) { return file_admin_service_proto_rawDescGZIP(), []int{0} } +func (x *LoginRequest) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *LoginRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + type LoginResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + AdminId int64 `protobuf:"varint,1,opt,name=adminId,proto3" json:"adminId,omitempty"` + IsOk bool `protobuf:"varint,2,opt,name=isOk,proto3" json:"isOk,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` } func (x *LoginResponse) Reset() { @@ -105,19 +126,400 @@ func (*LoginResponse) Descriptor() ([]byte, []int) { return file_admin_service_proto_rawDescGZIP(), []int{1} } +func (x *LoginResponse) GetAdminId() int64 { + if x != nil { + return x.AdminId + } + return 0 +} + +func (x *LoginResponse) GetIsOk() bool { + if x != nil { + return x.IsOk + } + return false +} + +func (x *LoginResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type CreateLogRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Level string `protobuf:"bytes,1,opt,name=level,proto3" json:"level,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Action string `protobuf:"bytes,3,opt,name=action,proto3" json:"action,omitempty"` + Ip string `protobuf:"bytes,4,opt,name=ip,proto3" json:"ip,omitempty"` +} + +func (x *CreateLogRequest) Reset() { + *x = CreateLogRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateLogRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateLogRequest) ProtoMessage() {} + +func (x *CreateLogRequest) ProtoReflect() protoreflect.Message { + mi := &file_admin_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateLogRequest.ProtoReflect.Descriptor instead. +func (*CreateLogRequest) Descriptor() ([]byte, []int) { + return file_admin_service_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateLogRequest) GetLevel() string { + if x != nil { + return x.Level + } + return "" +} + +func (x *CreateLogRequest) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *CreateLogRequest) GetAction() string { + if x != nil { + return x.Action + } + return "" +} + +func (x *CreateLogRequest) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +type CreateLogResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsOk bool `protobuf:"varint,1,opt,name=isOk,proto3" json:"isOk,omitempty"` +} + +func (x *CreateLogResponse) Reset() { + *x = CreateLogResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateLogResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateLogResponse) ProtoMessage() {} + +func (x *CreateLogResponse) ProtoReflect() protoreflect.Message { + mi := &file_admin_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateLogResponse.ProtoReflect.Descriptor instead. +func (*CreateLogResponse) Descriptor() ([]byte, []int) { + return file_admin_service_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateLogResponse) GetIsOk() bool { + if x != nil { + return x.IsOk + } + return false +} + +type CheckAdminExistsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AdminId int64 `protobuf:"varint,1,opt,name=adminId,proto3" json:"adminId,omitempty"` +} + +func (x *CheckAdminExistsRequest) Reset() { + *x = CheckAdminExistsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckAdminExistsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckAdminExistsRequest) ProtoMessage() {} + +func (x *CheckAdminExistsRequest) ProtoReflect() protoreflect.Message { + mi := &file_admin_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckAdminExistsRequest.ProtoReflect.Descriptor instead. +func (*CheckAdminExistsRequest) Descriptor() ([]byte, []int) { + return file_admin_service_proto_rawDescGZIP(), []int{4} +} + +func (x *CheckAdminExistsRequest) GetAdminId() int64 { + if x != nil { + return x.AdminId + } + return 0 +} + +type CheckAdminExistsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsOk bool `protobuf:"varint,1,opt,name=isOk,proto3" json:"isOk,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *CheckAdminExistsResponse) Reset() { + *x = CheckAdminExistsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckAdminExistsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckAdminExistsResponse) ProtoMessage() {} + +func (x *CheckAdminExistsResponse) ProtoReflect() protoreflect.Message { + mi := &file_admin_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckAdminExistsResponse.ProtoReflect.Descriptor instead. +func (*CheckAdminExistsResponse) Descriptor() ([]byte, []int) { + return file_admin_service_proto_rawDescGZIP(), []int{5} +} + +func (x *CheckAdminExistsResponse) GetIsOk() bool { + if x != nil { + return x.IsOk + } + return false +} + +func (x *CheckAdminExistsResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type FindAdminNameRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AdminId int64 `protobuf:"varint,1,opt,name=adminId,proto3" json:"adminId,omitempty"` +} + +func (x *FindAdminNameRequest) Reset() { + *x = FindAdminNameRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FindAdminNameRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindAdminNameRequest) ProtoMessage() {} + +func (x *FindAdminNameRequest) ProtoReflect() protoreflect.Message { + mi := &file_admin_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FindAdminNameRequest.ProtoReflect.Descriptor instead. +func (*FindAdminNameRequest) Descriptor() ([]byte, []int) { + return file_admin_service_proto_rawDescGZIP(), []int{6} +} + +func (x *FindAdminNameRequest) GetAdminId() int64 { + if x != nil { + return x.AdminId + } + return 0 +} + +type FindAdminNameResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Fullname string `protobuf:"bytes,1,opt,name=fullname,proto3" json:"fullname,omitempty"` +} + +func (x *FindAdminNameResponse) Reset() { + *x = FindAdminNameResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_admin_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FindAdminNameResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindAdminNameResponse) ProtoMessage() {} + +func (x *FindAdminNameResponse) ProtoReflect() protoreflect.Message { + mi := &file_admin_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FindAdminNameResponse.ProtoReflect.Descriptor instead. +func (*FindAdminNameResponse) Descriptor() ([]byte, []int) { + return file_admin_service_proto_rawDescGZIP(), []int{7} +} + +func (x *FindAdminNameResponse) GetFullname() string { + if x != nil { + return x.Fullname + } + return "" +} + var File_admin_service_proto protoreflect.FileDescriptor var file_admin_service_proto_rawDesc = []byte{ 0x0a, 0x13, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x0e, 0x0a, 0x0c, - 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, - 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x3f, 0x0a, - 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x6c, 0x6f, 0x67, 0x69, - 0x6e, 0x12, 0x13, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x4c, - 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x09, - 0x5a, 0x07, 0x2e, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x46, 0x0a, 0x0c, + 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x22, 0x57, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, + 0x73, 0x4f, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x72, 0x0a, + 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x70, 0x22, 0x27, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x22, 0x33, 0x0a, 0x17, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, + 0x48, 0x0a, 0x18, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x45, 0x78, 0x69, + 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, + 0x73, 0x4f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x30, 0x0a, 0x14, 0x46, 0x69, 0x6e, + 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x33, 0x0a, 0x15, 0x46, + 0x69, 0x6e, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, + 0x32, 0xaa, 0x02, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x05, + 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x13, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x40, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x12, + 0x17, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x45, 0x78, 0x69, 0x73, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x45, 0x78, 0x69, 0x73, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x11, 0x66, + 0x69, 0x6e, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x46, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x1b, 0x2e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4e, + 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x09, 0x5a, + 0x07, 0x2e, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -132,16 +534,28 @@ func file_admin_service_proto_rawDescGZIP() []byte { return file_admin_service_proto_rawDescData } -var file_admin_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_admin_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_admin_service_proto_goTypes = []interface{}{ - (*LoginRequest)(nil), // 0: admin.LoginRequest - (*LoginResponse)(nil), // 1: admin.LoginResponse + (*LoginRequest)(nil), // 0: admin.LoginRequest + (*LoginResponse)(nil), // 1: admin.LoginResponse + (*CreateLogRequest)(nil), // 2: admin.CreateLogRequest + (*CreateLogResponse)(nil), // 3: admin.CreateLogResponse + (*CheckAdminExistsRequest)(nil), // 4: admin.CheckAdminExistsRequest + (*CheckAdminExistsResponse)(nil), // 5: admin.CheckAdminExistsResponse + (*FindAdminNameRequest)(nil), // 6: admin.FindAdminNameRequest + (*FindAdminNameResponse)(nil), // 7: admin.FindAdminNameResponse } var file_admin_service_proto_depIdxs = []int32{ 0, // 0: admin.Service.login:input_type -> admin.LoginRequest - 1, // 1: admin.Service.login:output_type -> admin.LoginResponse - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type + 2, // 1: admin.Service.createLog:input_type -> admin.CreateLogRequest + 4, // 2: admin.Service.checkAdminExists:input_type -> admin.CheckAdminExistsRequest + 6, // 3: admin.Service.findAdminFullname:input_type -> admin.FindAdminNameRequest + 1, // 4: admin.Service.login:output_type -> admin.LoginResponse + 3, // 5: admin.Service.createLog:output_type -> admin.CreateLogResponse + 5, // 6: admin.Service.checkAdminExists:output_type -> admin.CheckAdminExistsResponse + 7, // 7: admin.Service.findAdminFullname:output_type -> admin.FindAdminNameResponse + 4, // [4:8] is the sub-list for method output_type + 0, // [0:4] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name @@ -177,6 +591,78 @@ func file_admin_service_proto_init() { return nil } } + file_admin_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateLogRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateLogResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckAdminExistsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckAdminExistsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FindAdminNameRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_admin_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FindAdminNameResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -184,7 +670,7 @@ func file_admin_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_admin_service_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, @@ -210,7 +696,14 @@ const _ = grpc.SupportPackageIsVersion6 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type ServiceClient interface { + // 登录 Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) + // 创建操作日志 + CreateLog(ctx context.Context, in *CreateLogRequest, opts ...grpc.CallOption) (*CreateLogResponse, error) + // 检查管理员是否存在 + CheckAdminExists(ctx context.Context, in *CheckAdminExistsRequest, opts ...grpc.CallOption) (*CheckAdminExistsResponse, error) + // 获取管理员名称 + FindAdminFullname(ctx context.Context, in *FindAdminNameRequest, opts ...grpc.CallOption) (*FindAdminNameResponse, error) } type serviceClient struct { @@ -230,9 +723,43 @@ func (c *serviceClient) Login(ctx context.Context, in *LoginRequest, opts ...grp return out, nil } +func (c *serviceClient) CreateLog(ctx context.Context, in *CreateLogRequest, opts ...grpc.CallOption) (*CreateLogResponse, error) { + out := new(CreateLogResponse) + err := c.cc.Invoke(ctx, "/admin.Service/createLog", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *serviceClient) CheckAdminExists(ctx context.Context, in *CheckAdminExistsRequest, opts ...grpc.CallOption) (*CheckAdminExistsResponse, error) { + out := new(CheckAdminExistsResponse) + err := c.cc.Invoke(ctx, "/admin.Service/checkAdminExists", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *serviceClient) FindAdminFullname(ctx context.Context, in *FindAdminNameRequest, opts ...grpc.CallOption) (*FindAdminNameResponse, error) { + out := new(FindAdminNameResponse) + err := c.cc.Invoke(ctx, "/admin.Service/findAdminFullname", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ServiceServer is the server API for Service service. type ServiceServer interface { + // 登录 Login(context.Context, *LoginRequest) (*LoginResponse, error) + // 创建操作日志 + CreateLog(context.Context, *CreateLogRequest) (*CreateLogResponse, error) + // 检查管理员是否存在 + CheckAdminExists(context.Context, *CheckAdminExistsRequest) (*CheckAdminExistsResponse, error) + // 获取管理员名称 + FindAdminFullname(context.Context, *FindAdminNameRequest) (*FindAdminNameResponse, error) } // UnimplementedServiceServer can be embedded to have forward compatible implementations. @@ -242,6 +769,15 @@ type UnimplementedServiceServer struct { func (*UnimplementedServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") } +func (*UnimplementedServiceServer) CreateLog(context.Context, *CreateLogRequest) (*CreateLogResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateLog not implemented") +} +func (*UnimplementedServiceServer) CheckAdminExists(context.Context, *CheckAdminExistsRequest) (*CheckAdminExistsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckAdminExists not implemented") +} +func (*UnimplementedServiceServer) FindAdminFullname(context.Context, *FindAdminNameRequest) (*FindAdminNameResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FindAdminFullname not implemented") +} func RegisterServiceServer(s *grpc.Server, srv ServiceServer) { s.RegisterService(&_Service_serviceDesc, srv) @@ -265,6 +801,60 @@ func _Service_Login_Handler(srv interface{}, ctx context.Context, dec func(inter return interceptor(ctx, in, info, handler) } +func _Service_CreateLog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateLogRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServiceServer).CreateLog(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/admin.Service/CreateLog", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServiceServer).CreateLog(ctx, req.(*CreateLogRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Service_CheckAdminExists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckAdminExistsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServiceServer).CheckAdminExists(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/admin.Service/CheckAdminExists", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServiceServer).CheckAdminExists(ctx, req.(*CheckAdminExistsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Service_FindAdminFullname_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FindAdminNameRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServiceServer).FindAdminFullname(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/admin.Service/FindAdminFullname", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServiceServer).FindAdminFullname(ctx, req.(*FindAdminNameRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Service_serviceDesc = grpc.ServiceDesc{ ServiceName: "admin.Service", HandlerType: (*ServiceServer)(nil), @@ -273,6 +863,18 @@ var _Service_serviceDesc = grpc.ServiceDesc{ MethodName: "login", Handler: _Service_Login_Handler, }, + { + MethodName: "createLog", + Handler: _Service_CreateLog_Handler, + }, + { + MethodName: "checkAdminExists", + Handler: _Service_CheckAdminExists_Handler, + }, + { + MethodName: "findAdminFullname", + Handler: _Service_FindAdminFullname_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "admin/service.proto", diff --git a/internal/rpc/admin/service.proto b/internal/rpc/admin/service.proto index 776ef5ce..80ead3dd 100644 --- a/internal/rpc/admin/service.proto +++ b/internal/rpc/admin/service.proto @@ -1,18 +1,64 @@ syntax = "proto3"; +option go_package = "./admin"; package admin; -option go_package = "./admin"; - service Service { + // 登录 rpc login (LoginRequest) returns (LoginResponse) { } + + // 创建操作日志 + rpc createLog (CreateLogRequest) returns (CreateLogResponse) { + } + + // 检查管理员是否存在 + rpc checkAdminExists (CheckAdminExistsRequest) returns (CheckAdminExistsResponse) { + + } + + // 获取管理员名称 + rpc findAdminFullname (FindAdminNameRequest) returns (FindAdminNameResponse) { + + } } message LoginRequest { - + string username = 1; + string password = 2; } message LoginResponse { + int64 adminId = 1; + bool isOk = 2; + string message = 3; +} -} \ No newline at end of file +message CreateLogRequest { + string level = 1; + string description = 2; + string action = 3; + string ip = 4; +} + +message CreateLogResponse { + bool isOk = 1; +} + +message CheckAdminExistsRequest { + int64 adminId = 1; +} + +message CheckAdminExistsResponse { + bool isOk = 1; + string message = 2; +} + + +message FindAdminNameRequest { + int64 adminId = 1; +} + +message FindAdminNameResponse { + string fullname = 1; +} diff --git a/internal/rpc/admin/service_test.go b/internal/rpc/admin/service_test.go new file mode 100644 index 00000000..4589259f --- /dev/null +++ b/internal/rpc/admin/service_test.go @@ -0,0 +1,68 @@ +package admin + +import ( + "context" + "encoding/base64" + teaconst "github.com/TeaOSLab/EdgeAPI/internal/const" + "github.com/TeaOSLab/EdgeAPI/internal/encrypt" + "github.com/iwind/TeaGo/assert" + "github.com/iwind/TeaGo/maps" + stringutil "github.com/iwind/TeaGo/utils/string" + "google.golang.org/grpc/metadata" + "testing" + "time" +) + +func TestService_Login(t *testing.T) { + a := assert.NewAssertion(t) + service := &Service{ + debug: true, + } + resp, err := service.Login(testCtx(t), &LoginRequest{ + Username: "admin", + Password: stringutil.Md5("123456"), + }) + if err != nil { + t.Fatal(err) + } + a.LogJSON(resp) +} + +func TestService_CreateLog(t *testing.T) { + service := &Service{debug: true} + + resp, err := service.CreateLog(testCtx(t), &CreateLogRequest{ + Level: "info", + Description: "这是一个测试日志", + Action: "/login", + Ip: "127.0.0.1", + }) + if err != nil { + t.Fatal(err) + } + t.Log(resp) +} + +func testCtx(t *testing.T) context.Context { + ctx := context.Background() + nodeId := "H6sjDf779jimnVPnBFSgZxvr6Ca0wQ0z" + + token := maps.Map{ + "timestamp": time.Now().Unix(), + "adminId": 1, + } + data := token.AsJSON() + + method, err := encrypt.NewMethodInstance(teaconst.EncryptMethod, "hMHjmEng0SIcT3yiA3HIoUjogwAC9cur", nodeId) + if err != nil { + t.Fatal(err) + } + data, err = method.Encrypt(data) + if err != nil { + t.Fatal(err) + } + tokenString := base64.StdEncoding.EncodeToString(data) + + ctx = metadata.AppendToOutgoingContext(ctx, "nodeId", nodeId, "token", tokenString) + return ctx +} diff --git a/internal/rpc/node/service.go b/internal/rpc/node/service.go index 45231966..dfa6af99 100644 --- a/internal/rpc/node/service.go +++ b/internal/rpc/node/service.go @@ -8,7 +8,9 @@ import ( type Service struct { } -func (this *Service) Node(context.Context, *NodeRequest) (*NodeResponse, error) { +func (this *Service) Config(ctx context.Context, req *ConfigRequest) (*ConfigResponse, error) { logs.Println("you called me") - return &NodeResponse{}, nil + return &ConfigResponse{ + Id: req.NodeId, + }, nil } diff --git a/internal/rpc/node/service.pb.go b/internal/rpc/node/service.pb.go index 864016a4..629cd5bf 100644 --- a/internal/rpc/node/service.pb.go +++ b/internal/rpc/node/service.pb.go @@ -29,14 +29,16 @@ const ( // of the legacy proto package is being used. const _ = proto.ProtoPackageIsVersion4 -type NodeRequest struct { +type ConfigRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + NodeId string `protobuf:"bytes,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"` } -func (x *NodeRequest) Reset() { - *x = NodeRequest{} +func (x *ConfigRequest) Reset() { + *x = ConfigRequest{} if protoimpl.UnsafeEnabled { mi := &file_node_service_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -44,13 +46,13 @@ func (x *NodeRequest) Reset() { } } -func (x *NodeRequest) String() string { +func (x *ConfigRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*NodeRequest) ProtoMessage() {} +func (*ConfigRequest) ProtoMessage() {} -func (x *NodeRequest) ProtoReflect() protoreflect.Message { +func (x *ConfigRequest) ProtoReflect() protoreflect.Message { mi := &file_node_service_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -62,19 +64,28 @@ func (x *NodeRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use NodeRequest.ProtoReflect.Descriptor instead. -func (*NodeRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use ConfigRequest.ProtoReflect.Descriptor instead. +func (*ConfigRequest) Descriptor() ([]byte, []int) { return file_node_service_proto_rawDescGZIP(), []int{0} } -type NodeResponse struct { +func (x *ConfigRequest) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +type ConfigResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` } -func (x *NodeResponse) Reset() { - *x = NodeResponse{} +func (x *ConfigResponse) Reset() { + *x = ConfigResponse{} if protoimpl.UnsafeEnabled { mi := &file_node_service_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -82,13 +93,13 @@ func (x *NodeResponse) Reset() { } } -func (x *NodeResponse) String() string { +func (x *ConfigResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*NodeResponse) ProtoMessage() {} +func (*ConfigResponse) ProtoMessage() {} -func (x *NodeResponse) ProtoReflect() protoreflect.Message { +func (x *ConfigResponse) ProtoReflect() protoreflect.Message { mi := &file_node_service_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -100,23 +111,33 @@ func (x *NodeResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use NodeResponse.ProtoReflect.Descriptor instead. -func (*NodeResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use ConfigResponse.ProtoReflect.Descriptor instead. +func (*ConfigResponse) Descriptor() ([]byte, []int) { return file_node_service_proto_rawDescGZIP(), []int{1} } +func (x *ConfigResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + var File_node_service_proto protoreflect.FileDescriptor var file_node_service_proto_rawDesc = []byte{ 0x0a, 0x12, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x0d, 0x0a, 0x0b, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x3a, 0x0a, 0x07, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x11, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x12, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x27, 0x0a, 0x0d, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, + 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, + 0x65, 0x49, 0x64, 0x22, 0x20, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x32, 0x40, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x13, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x14, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x6e, 0x6f, 0x64, + 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -133,12 +154,12 @@ func file_node_service_proto_rawDescGZIP() []byte { var file_node_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_node_service_proto_goTypes = []interface{}{ - (*NodeRequest)(nil), // 0: node.NodeRequest - (*NodeResponse)(nil), // 1: node.NodeResponse + (*ConfigRequest)(nil), // 0: node.ConfigRequest + (*ConfigResponse)(nil), // 1: node.ConfigResponse } var file_node_service_proto_depIdxs = []int32{ - 0, // 0: node.Service.node:input_type -> node.NodeRequest - 1, // 1: node.Service.node:output_type -> node.NodeResponse + 0, // 0: node.Service.config:input_type -> node.ConfigRequest + 1, // 1: node.Service.config:output_type -> node.ConfigResponse 1, // [1:2] is the sub-list for method output_type 0, // [0:1] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -153,7 +174,7 @@ func file_node_service_proto_init() { } if !protoimpl.UnsafeEnabled { file_node_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeRequest); i { + switch v := v.(*ConfigRequest); i { case 0: return &v.state case 1: @@ -165,7 +186,7 @@ func file_node_service_proto_init() { } } file_node_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeResponse); i { + switch v := v.(*ConfigResponse); i { case 0: return &v.state case 1: @@ -209,7 +230,7 @@ const _ = grpc.SupportPackageIsVersion6 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type ServiceClient interface { - Node(ctx context.Context, in *NodeRequest, opts ...grpc.CallOption) (*NodeResponse, error) + Config(ctx context.Context, in *ConfigRequest, opts ...grpc.CallOption) (*ConfigResponse, error) } type serviceClient struct { @@ -220,9 +241,9 @@ func NewServiceClient(cc grpc.ClientConnInterface) ServiceClient { return &serviceClient{cc} } -func (c *serviceClient) Node(ctx context.Context, in *NodeRequest, opts ...grpc.CallOption) (*NodeResponse, error) { - out := new(NodeResponse) - err := c.cc.Invoke(ctx, "/node.Service/node", in, out, opts...) +func (c *serviceClient) Config(ctx context.Context, in *ConfigRequest, opts ...grpc.CallOption) (*ConfigResponse, error) { + out := new(ConfigResponse) + err := c.cc.Invoke(ctx, "/node.Service/config", in, out, opts...) if err != nil { return nil, err } @@ -231,35 +252,35 @@ func (c *serviceClient) Node(ctx context.Context, in *NodeRequest, opts ...grpc. // ServiceServer is the server API for Service service. type ServiceServer interface { - Node(context.Context, *NodeRequest) (*NodeResponse, error) + Config(context.Context, *ConfigRequest) (*ConfigResponse, error) } // UnimplementedServiceServer can be embedded to have forward compatible implementations. type UnimplementedServiceServer struct { } -func (*UnimplementedServiceServer) Node(context.Context, *NodeRequest) (*NodeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Node not implemented") +func (*UnimplementedServiceServer) Config(context.Context, *ConfigRequest) (*ConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Config not implemented") } func RegisterServiceServer(s *grpc.Server, srv ServiceServer) { s.RegisterService(&_Service_serviceDesc, srv) } -func _Service_Node_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(NodeRequest) +func _Service_Config_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConfigRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ServiceServer).Node(ctx, in) + return srv.(ServiceServer).Config(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/node.Service/Node", + FullMethod: "/node.Service/Config", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServiceServer).Node(ctx, req.(*NodeRequest)) + return srv.(ServiceServer).Config(ctx, req.(*ConfigRequest)) } return interceptor(ctx, in, info, handler) } @@ -269,8 +290,8 @@ var _Service_serviceDesc = grpc.ServiceDesc{ HandlerType: (*ServiceServer)(nil), Methods: []grpc.MethodDesc{ { - MethodName: "node", - Handler: _Service_Node_Handler, + MethodName: "config", + Handler: _Service_Config_Handler, }, }, Streams: []grpc.StreamDesc{}, diff --git a/internal/rpc/node/service.proto b/internal/rpc/node/service.proto index f269c21e..e706eb20 100644 --- a/internal/rpc/node/service.proto +++ b/internal/rpc/node/service.proto @@ -5,15 +5,15 @@ package node; option go_package = "./node"; service Service { - rpc node (NodeRequest) returns (NodeResponse) { + rpc config (ConfigRequest) returns (ConfigResponse) { } } -message NodeRequest { - +message ConfigRequest { + string nodeId = 1; } -message NodeResponse { - +message ConfigResponse { + string id = 1; } \ No newline at end of file diff --git a/internal/tests/grpc_test.go b/internal/tests/grpc_test.go index 2142e733..8e41d384 100644 --- a/internal/tests/grpc_test.go +++ b/internal/tests/grpc_test.go @@ -3,6 +3,7 @@ package tests import ( "context" "encoding/json" + "github.com/TeaOSLab/EdgeAPI/internal/rpc/admin" nodepb "github.com/TeaOSLab/EdgeAPI/internal/rpc/node" pb "github.com/TeaOSLab/EdgeAPI/internal/tests/helloworld" "google.golang.org/grpc" @@ -42,6 +43,7 @@ func TestTCPServer(t *testing.T) { s := grpc.NewServer() pb.RegisterGreeterServer(s, &server{}) nodepb.RegisterServiceServer(s, &nodepb.Service{}) + admin.RegisterServiceServer(s, &admin.Service{}) err = s.Serve(listener) if err != nil { @@ -89,7 +91,7 @@ func TestTCPClient_Node(t *testing.T) { ctx := context.Background() ctx = metadata.AppendToOutgoingContext(ctx, "name", "liu", "age", "20") - reply, err := c.Node(ctx, &nodepb.NodeRequest{ + reply, err := c.Config(ctx, &nodepb.ConfigRequest{ }) if err != nil { t.Fatal(err) diff --git a/internal/tests/helper_test.go b/internal/tests/helper_test.go new file mode 100644 index 00000000..0d1e0d08 --- /dev/null +++ b/internal/tests/helper_test.go @@ -0,0 +1,10 @@ +package tests + +import ( + "github.com/iwind/TeaGo/rands" + "testing" +) + +func TestRandString(t *testing.T) { + t.Log(rands.HexString(32)) +} diff --git a/internal/utils/errors.go b/internal/utils/errors.go new file mode 100644 index 00000000..a54dddab --- /dev/null +++ b/internal/utils/errors.go @@ -0,0 +1,8 @@ +package utils + +import "github.com/iwind/TeaGo/logs" + +func PrintError(err error) { + // TODO 记录调用的文件名、行数 + logs.Println("[ERROR]" + err.Error()) +} diff --git a/internal/utils/rlimit_darwin.go b/internal/utils/rlimit_darwin.go new file mode 100644 index 00000000..af493c74 --- /dev/null +++ b/internal/utils/rlimit_darwin.go @@ -0,0 +1,29 @@ +// +build darwin + +package utils + +import ( + "syscall" +) + +// set resource limit +func SetRLimit(limit uint64) error { + rLimit := &syscall.Rlimit{} + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rLimit) + if err != nil { + return err + } + + if rLimit.Cur < limit { + rLimit.Cur = limit + } + if rLimit.Max < limit { + rLimit.Max = limit + } + return syscall.Setrlimit(syscall.RLIMIT_NOFILE, rLimit) +} + +// set best resource limit value +func SetSuitableRLimit() { + SetRLimit(4096 * 100) // 1M=100Files +} diff --git a/internal/utils/rlimit_linux.go b/internal/utils/rlimit_linux.go new file mode 100644 index 00000000..a33d8e54 --- /dev/null +++ b/internal/utils/rlimit_linux.go @@ -0,0 +1,29 @@ +// +build linux + +package utils + +import ( + "syscall" +) + +// set resource limit +func SetRLimit(limit uint64) error { + rLimit := &syscall.Rlimit{} + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rLimit) + if err != nil { + return err + } + + if rLimit.Cur < limit { + rLimit.Cur = limit + } + if rLimit.Max < limit { + rLimit.Max = limit + } + return syscall.Setrlimit(syscall.RLIMIT_NOFILE, rLimit) +} + +// set best resource limit value +func SetSuitableRLimit() { + SetRLimit(4096 * 100) // 1M=100Files +} diff --git a/internal/utils/rlimit_others.go b/internal/utils/rlimit_others.go new file mode 100644 index 00000000..6047f6e1 --- /dev/null +++ b/internal/utils/rlimit_others.go @@ -0,0 +1,13 @@ +// +build !linux,!darwin + +package utils + +// set resource limit +func SetRLimit(limit uint64) error { + return nil +} + +// set best resource limit value +func SetSuitableRLimit() { + +}