From 37b4055924b81c76e20c3444c33500d3bfcb8123 Mon Sep 17 00:00:00 2001 From: denghui <1016848185@qq.com> Date: Tue, 27 May 2025 15:46:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20jwt=E3=80=81=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E5=8A=A0=E5=AF=86=E3=80=81casbin=20=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 7 -- api/auth/v1/auth.go | 1 + api/hello/hello.go | 15 --- api/hello/v1/hello.go | 12 -- go.mod | 48 +++++--- go.sum | 113 ++++++++++++----- hack/config.yaml | 8 +- hack/hack-cli.mk | 20 --- hack/hack.mk | 75 ------------ internal/cmd/cmd.go | 16 ++- internal/controller/hello/hello.go | 5 - internal/controller/hello/hello_new.go | 15 --- internal/controller/hello/hello_v1_hello.go | 13 -- internal/middleware/casbin.go | 27 ++++ internal/middleware/exit.go | 14 +++ internal/packed/packed.go | 6 + main.go | 3 +- manifest/config/config.yaml | 21 +++- manifest/config/rbac_model.conf | 14 +++ .../deploy/kustomize/base/deployment.yaml | 21 ---- .../deploy/kustomize/base/kustomization.yaml | 8 -- manifest/deploy/kustomize/base/service.yaml | 12 -- .../kustomize/overlays/develop/configmap.yaml | 14 --- .../overlays/develop/deployment.yaml | 10 -- .../overlays/develop/kustomization.yaml | 14 --- manifest/docker/Dockerfile | 16 --- manifest/docker/docker.sh | 8 -- manifest/i18n/.gitkeep | 0 manifest/protobuf/.keep-if-necessary | 0 resource/public/html/.gitkeep | 0 resource/public/plugin/.gitkeep | 0 resource/public/resource/css/.gitkeep | 0 resource/public/resource/image/.gitkeep | 0 resource/public/resource/js/.gitkeep | 0 resource/template/.gitkeep | 0 utility/.gitkeep | 0 utility/ecode/common.go | 15 +++ utility/ecode/ecode.go | 58 +++++++++ utility/encrypt/password.go | 46 +++++++ utility/encrypt/phone.go | 77 ++++++++++++ utility/jwt/jwt.go | 115 ++++++++++++++++++ utility/myCasbin/casbin.go | 64 ++++++++++ utility/openid.go | 32 +++++ 43 files changed, 618 insertions(+), 325 deletions(-) delete mode 100644 Makefile create mode 100644 api/auth/v1/auth.go delete mode 100644 api/hello/hello.go delete mode 100644 api/hello/v1/hello.go delete mode 100644 hack/hack-cli.mk delete mode 100644 hack/hack.mk delete mode 100644 internal/controller/hello/hello.go delete mode 100644 internal/controller/hello/hello_new.go delete mode 100644 internal/controller/hello/hello_v1_hello.go create mode 100644 internal/middleware/casbin.go create mode 100644 internal/middleware/exit.go create mode 100644 manifest/config/rbac_model.conf delete mode 100644 manifest/deploy/kustomize/base/deployment.yaml delete mode 100644 manifest/deploy/kustomize/base/kustomization.yaml delete mode 100644 manifest/deploy/kustomize/base/service.yaml delete mode 100644 manifest/deploy/kustomize/overlays/develop/configmap.yaml delete mode 100644 manifest/deploy/kustomize/overlays/develop/deployment.yaml delete mode 100644 manifest/deploy/kustomize/overlays/develop/kustomization.yaml delete mode 100644 manifest/docker/Dockerfile delete mode 100644 manifest/docker/docker.sh delete mode 100644 manifest/i18n/.gitkeep delete mode 100644 manifest/protobuf/.keep-if-necessary delete mode 100644 resource/public/html/.gitkeep delete mode 100644 resource/public/plugin/.gitkeep delete mode 100644 resource/public/resource/css/.gitkeep delete mode 100644 resource/public/resource/image/.gitkeep delete mode 100644 resource/public/resource/js/.gitkeep delete mode 100644 resource/template/.gitkeep delete mode 100644 utility/.gitkeep create mode 100644 utility/ecode/common.go create mode 100644 utility/ecode/ecode.go create mode 100644 utility/encrypt/password.go create mode 100644 utility/encrypt/phone.go create mode 100644 utility/jwt/jwt.go create mode 100644 utility/myCasbin/casbin.go create mode 100644 utility/openid.go diff --git a/Makefile b/Makefile deleted file mode 100644 index 2a6e6e9..0000000 --- a/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -ROOT_DIR = $(shell pwd) -NAMESPACE = "default" -DEPLOY_NAME = "template-single" -DOCKER_NAME = "template-single" - -include ./hack/hack-cli.mk -include ./hack/hack.mk \ No newline at end of file diff --git a/api/auth/v1/auth.go b/api/auth/v1/auth.go new file mode 100644 index 0000000..b7b1f99 --- /dev/null +++ b/api/auth/v1/auth.go @@ -0,0 +1 @@ +package v1 diff --git a/api/hello/hello.go b/api/hello/hello.go deleted file mode 100644 index 3515877..0000000 --- a/api/hello/hello.go +++ /dev/null @@ -1,15 +0,0 @@ -// ================================================================================= -// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. -// ================================================================================= - -package hello - -import ( - "context" - - "server/api/hello/v1" -) - -type IHelloV1 interface { - Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) -} diff --git a/api/hello/v1/hello.go b/api/hello/v1/hello.go deleted file mode 100644 index b4dd233..0000000 --- a/api/hello/v1/hello.go +++ /dev/null @@ -1,12 +0,0 @@ -package v1 - -import ( - "github.com/gogf/gf/v2/frame/g" -) - -type HelloReq struct { - g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"` -} -type HelloRes struct { - g.Meta `mime:"text/html" example:"string"` -} diff --git a/go.mod b/go.mod index 1ac2450..f4f52f0 100644 --- a/go.mod +++ b/go.mod @@ -1,28 +1,48 @@ module server -go 1.18 +go 1.22 -require github.com/gogf/gf/v2 v2.7.1 +toolchain go1.24.2 require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/casbin/casbin/v2 v2.105.0 + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0 + github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0 + github.com/gogf/gf/v2 v2.9.0 + github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/hailaz/gf-casbin-adapter/v2 v2.8.1 + golang.org/x/crypto v0.30.0 +) + +require ( + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect + github.com/casbin/govaluate v1.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect - github.com/magiconair/properties v1.8.7 // indirect + github.com/magiconair/properties v1.8.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/redis/go-redis/v9 v9.7.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index c1d3bdc..f6ff37f 100644 --- a/go.sum +++ b/go.sum @@ -1,52 +1,109 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= +github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/casbin/casbin/v2 v2.105.0 h1:dLj5P6pLApBRat9SADGiLxLZjiDPvA1bsPkyV4PGx6I= +github.com/casbin/casbin/v2 v2.105.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco= +github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc= +github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/gogf/gf/v2 v2.7.1 h1:Ukp7vzwh6VKnivEEx/xiMc61dL1HVZqCCHl//3GBRxc= -github.com/gogf/gf/v2 v2.7.1/go.mod h1:3oyGjyLHtSSo8kQ57Nj1TPdUNc0e2HS0A2J+KkXoW+I= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0 h1:1f7EeD0lfPHoXfaJDSL7cxRcSRelbsAKgF3MGXY+Uyo= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0/go.mod h1:tToO1PjGkLIR+9DbJ0wrKicYma0H/EUHXOpwel6Dw+0= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0 h1:EEZqu1PNRSmm+7Cqm9A/8+ObgfbMzhE1ps9Z3LD7HgM= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0/go.mod h1:LHrxY+2IzNTHVTPG/s5yaz1VmXbj+CQ7Hr5SeVkHiTw= +github.com/gogf/gf/v2 v2.9.0 h1:semN5Q5qGjDQEv4620VzxcJzJlSD07gmyJ9Sy9zfbHk= +github.com/gogf/gf/v2 v2.9.0/go.mod h1:sWGQw+pLILtuHmbOxoe0D+0DdaXxbleT57axOLH2vKI= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/hailaz/gf-casbin-adapter/v2 v2.8.1 h1:ZFIlfQAYmrL2Fe6/dZz6vCA5hYK0NxhnoKMQpbklgqc= +github.com/hailaz/gf-casbin-adapter/v2 v2.8.1/go.mod h1:Jk91dRBZuMVjBMu2oQmqMRc6xuL5V+rzgHeFWvI+wlg= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/hack/config.yaml b/hack/config.yaml index 83c7dc6..bb811f0 100644 --- a/hack/config.yaml +++ b/hack/config.yaml @@ -4,10 +4,6 @@ gfcli: gen: dao: - - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" + - link: "mysql:root:MSms0427@tcp(127.0.0.1:3306)/arenax" descriptionTag: true - - docker: - build: "-a amd64 -s linux -p temp -ew" - tagPrefixes: - - my.image.pub/my-app \ No newline at end of file + tablesEx: "casbin_rule" \ No newline at end of file diff --git a/hack/hack-cli.mk b/hack/hack-cli.mk deleted file mode 100644 index f4e2ad2..0000000 --- a/hack/hack-cli.mk +++ /dev/null @@ -1,20 +0,0 @@ - -# Install/Update to the latest CLI tool. -.PHONY: cli -cli: - @set -e; \ - wget -O gf \ - https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \ - chmod +x gf && \ - ./gf install -y && \ - rm ./gf - - -# Check and install CLI tool. -.PHONY: cli.install -cli.install: - @set -e; \ - gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \ - echo "GoFame CLI is not installed, start proceeding auto installation..."; \ - make cli; \ - fi; \ No newline at end of file diff --git a/hack/hack.mk b/hack/hack.mk deleted file mode 100644 index 2f68179..0000000 --- a/hack/hack.mk +++ /dev/null @@ -1,75 +0,0 @@ -.DEFAULT_GOAL := build - -# Update GoFrame and its CLI to latest stable version. -.PHONY: up -up: cli.install - @gf up -a - -# Build binary using configuration from hack/config.yaml. -.PHONY: build -build: cli.install - @gf build -ew - -# Parse api and generate controller/sdk. -.PHONY: ctrl -ctrl: cli.install - @gf gen ctrl - -# Generate Go files for DAO/DO/Entity. -.PHONY: dao -dao: cli.install - @gf gen dao - -# Parse current project go files and generate enums go file. -.PHONY: enums -enums: cli.install - @gf gen enums - -# Generate Go files for Service. -.PHONY: service -service: cli.install - @gf gen service - - -# Build docker image. -.PHONY: image -image: cli.install - $(eval _TAG = $(shell git rev-parse --short HEAD)) -ifneq (, $(shell git status --porcelain 2>/dev/null)) - $(eval _TAG = $(_TAG).dirty) -endif - $(eval _TAG = $(if ${TAG}, ${TAG}, $(_TAG))) - $(eval _PUSH = $(if ${PUSH}, ${PUSH}, )) - @gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG}; - - -# Build docker image and automatically push to docker repo. -.PHONY: image.push -image.push: cli.install - @make image PUSH=-p; - - -# Deploy image and yaml to current kubectl environment. -.PHONY: deploy -deploy: cli.install - $(eval _TAG = $(if ${TAG}, ${TAG}, develop)) - - @set -e; \ - mkdir -p $(ROOT_DIR)/temp/kustomize;\ - cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\ - kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\ - kubectl apply -f $(ROOT_DIR)/temp/kustomize.yaml; \ - if [ $(DEPLOY_NAME) != "" ]; then \ - kubectl patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \ - fi; - - -# Parsing protobuf files and generating go files. -.PHONY: pb -pb: cli.install - @gf gen pb - -# Generate protobuf files for database tables. -.PHONY: pbentity -pbentity: cli.install - @gf gen pbentity \ No newline at end of file diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 99a8a76..3707294 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -2,12 +2,10 @@ package cmd import ( "context" - "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gcmd" - - "server/internal/controller/hello" + "server/internal/middleware" ) var ( @@ -19,9 +17,15 @@ var ( s := g.Server() s.Group("/", func(group *ghttp.RouterGroup) { group.Middleware(ghttp.MiddlewareHandlerResponse) - group.Bind( - hello.NewV1(), - ) + group.Bind() + group.Group("/x", func(group *ghttp.RouterGroup) { + group.Middleware( + middleware.Auth, + middleware.Casbin, + middleware.Response, + ) + group.Bind() + }) }) s.Run() return nil diff --git a/internal/controller/hello/hello.go b/internal/controller/hello/hello.go deleted file mode 100644 index f72082f..0000000 --- a/internal/controller/hello/hello.go +++ /dev/null @@ -1,5 +0,0 @@ -// ================================================================================= -// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. -// ================================================================================= - -package hello diff --git a/internal/controller/hello/hello_new.go b/internal/controller/hello/hello_new.go deleted file mode 100644 index 040ab22..0000000 --- a/internal/controller/hello/hello_new.go +++ /dev/null @@ -1,15 +0,0 @@ -// ================================================================================= -// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. -// ================================================================================= - -package hello - -import ( - "server/api/hello" -) - -type ControllerV1 struct{} - -func NewV1() hello.IHelloV1 { - return &ControllerV1{} -} diff --git a/internal/controller/hello/hello_v1_hello.go b/internal/controller/hello/hello_v1_hello.go deleted file mode 100644 index 0e4d190..0000000 --- a/internal/controller/hello/hello_v1_hello.go +++ /dev/null @@ -1,13 +0,0 @@ -package hello - -import ( - "context" - "github.com/gogf/gf/v2/frame/g" - - "server/api/hello/v1" -) - -func (c *ControllerV1) Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) { - g.RequestFromCtx(ctx).Response.Writeln("Hello World!") - return -} diff --git a/internal/middleware/casbin.go b/internal/middleware/casbin.go new file mode 100644 index 0000000..6cd3f56 --- /dev/null +++ b/internal/middleware/casbin.go @@ -0,0 +1,27 @@ +package middleware + +import ( + "github.com/gogf/gf/v2/net/ghttp" + "server/utility/ecode" + "server/utility/myCasbin" +) + +// Casbin 是用于访问权限控制的中间件。 +// +// 该中间件基于 Casbin 权限控制框架,校验当前用户是否有权访问指定的 URL 和请求方法。 +// 用户权限从请求上下文中的 "permission" 字段获取,该字段通常由前置中间件(如 Auth)注入。 +// +// 参数: +// +// r *ghttp.Request - 当前的 HTTP 请求对象,由框架自动传入。 +// +// 行为: +// - 如果权限验证未通过:终止请求,返回权限不足的错误(ecode.Denied)。 +// - 如果权限验证通过:继续执行后续中间件或处理逻辑。 +func Casbin(r *ghttp.Request) { + permission := r.GetCtxVar("permission").String() + if !myCasbin.GetMyCasbin().HasPermission(permission, r.URL.Path, r.Method) { + Exit(r, ecode.Denied) + } + r.Middleware.Next() +} diff --git a/internal/middleware/exit.go b/internal/middleware/exit.go new file mode 100644 index 0000000..dba705b --- /dev/null +++ b/internal/middleware/exit.go @@ -0,0 +1,14 @@ +package middleware + +import ( + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/net/ghttp" +) + +func Exit(r *ghttp.Request, err error) { + r.Response.WriteJsonExit(ghttp.DefaultHandlerResponse{ + Code: gerror.Code(err).Code(), + Message: gerror.Code(err).Message(), + Data: nil, + }) +} diff --git a/internal/packed/packed.go b/internal/packed/packed.go index e20ab1e..6693def 100644 --- a/internal/packed/packed.go +++ b/internal/packed/packed.go @@ -1 +1,7 @@ package packed + +import ( + _ "github.com/gogf/gf/contrib/drivers/mysql/v2" + _ "github.com/gogf/gf/contrib/nosql/redis/v2" + _ "server/utility/myCasbin" +) diff --git a/main.go b/main.go index de63f9e..4b32593 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,8 @@ package main import ( - _ "server/internal/packed" - "github.com/gogf/gf/v2/os/gctx" + _ "server/internal/packed" "server/internal/cmd" ) diff --git a/manifest/config/config.yaml b/manifest/config/config.yaml index 5fe97a7..4c3a01e 100644 --- a/manifest/config/config.yaml +++ b/manifest/config/config.yaml @@ -1,15 +1,28 @@ -# https://goframe.org/docs/web/server-config-file-template +# Server configuration. server: address: ":8000" openapiPath: "/api.json" swaggerPath: "/swagger" -# https://goframe.org/docs/core/glog-config +# Logger configuration. logger: level : "all" stdout: true -# https://goframe.org/docs/core/gdb-config-file +# Database configuration. database: + logger: + level: "all" + stdout: true default: - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" \ No newline at end of file + link: "mysql:root:MSms0427@tcp(127.0.0.1:3306)/dealxuetest?loc=Local&charset=utf8mb4" + debug: true + +# Redis configuration. +redis: + default: + address: "127.0.0.1:6379" + +# Casbin model +casbin: + modelPath: "./manifest/config/rbac_model.conf" \ No newline at end of file diff --git a/manifest/config/rbac_model.conf b/manifest/config/rbac_model.conf new file mode 100644 index 0000000..872871d --- /dev/null +++ b/manifest/config/rbac_model.conf @@ -0,0 +1,14 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act, desc + +[role_definition] +g = _, _ + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act) diff --git a/manifest/deploy/kustomize/base/deployment.yaml b/manifest/deploy/kustomize/base/deployment.yaml deleted file mode 100644 index 28f1d69..0000000 --- a/manifest/deploy/kustomize/base/deployment.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: template-single - labels: - app: template-single -spec: - replicas: 1 - selector: - matchLabels: - app: template-single - template: - metadata: - labels: - app: template-single - spec: - containers: - - name : main - image: template-single - imagePullPolicy: Always - diff --git a/manifest/deploy/kustomize/base/kustomization.yaml b/manifest/deploy/kustomize/base/kustomization.yaml deleted file mode 100644 index 302d92d..0000000 --- a/manifest/deploy/kustomize/base/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- deployment.yaml -- service.yaml - - - diff --git a/manifest/deploy/kustomize/base/service.yaml b/manifest/deploy/kustomize/base/service.yaml deleted file mode 100644 index 608771c..0000000 --- a/manifest/deploy/kustomize/base/service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: template-single -spec: - ports: - - port: 80 - protocol: TCP - targetPort: 8000 - selector: - app: template-single - diff --git a/manifest/deploy/kustomize/overlays/develop/configmap.yaml b/manifest/deploy/kustomize/overlays/develop/configmap.yaml deleted file mode 100644 index 3b1d0af..0000000 --- a/manifest/deploy/kustomize/overlays/develop/configmap.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: template-single-configmap -data: - config.yaml: | - server: - address: ":8000" - openapiPath: "/api.json" - swaggerPath: "/swagger" - - logger: - level : "all" - stdout: true diff --git a/manifest/deploy/kustomize/overlays/develop/deployment.yaml b/manifest/deploy/kustomize/overlays/develop/deployment.yaml deleted file mode 100644 index 04e4851..0000000 --- a/manifest/deploy/kustomize/overlays/develop/deployment.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: template-single -spec: - template: - spec: - containers: - - name : main - image: template-single:develop \ No newline at end of file diff --git a/manifest/deploy/kustomize/overlays/develop/kustomization.yaml b/manifest/deploy/kustomize/overlays/develop/kustomization.yaml deleted file mode 100644 index 4731c47..0000000 --- a/manifest/deploy/kustomize/overlays/develop/kustomization.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- ../../base -- configmap.yaml - -patchesStrategicMerge: -- deployment.yaml - -namespace: default - - - diff --git a/manifest/docker/Dockerfile b/manifest/docker/Dockerfile deleted file mode 100644 index d3abe8f..0000000 --- a/manifest/docker/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM loads/alpine:3.8 - -############################################################################### -# INSTALLATION -############################################################################### - -ENV WORKDIR /app -ADD resource $WORKDIR/ -ADD ./temp/linux_amd64/main $WORKDIR/main -RUN chmod +x $WORKDIR/main - -############################################################################### -# START -############################################################################### -WORKDIR $WORKDIR -CMD ./main diff --git a/manifest/docker/docker.sh b/manifest/docker/docker.sh deleted file mode 100644 index ff393f9..0000000 --- a/manifest/docker/docker.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# This shell is executed before docker build. - - - - - diff --git a/manifest/i18n/.gitkeep b/manifest/i18n/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/manifest/protobuf/.keep-if-necessary b/manifest/protobuf/.keep-if-necessary deleted file mode 100644 index e69de29..0000000 diff --git a/resource/public/html/.gitkeep b/resource/public/html/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/resource/public/plugin/.gitkeep b/resource/public/plugin/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/resource/public/resource/css/.gitkeep b/resource/public/resource/css/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/resource/public/resource/image/.gitkeep b/resource/public/resource/image/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/resource/public/resource/js/.gitkeep b/resource/public/resource/js/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/resource/template/.gitkeep b/resource/template/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/utility/.gitkeep b/utility/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/utility/ecode/common.go b/utility/ecode/common.go new file mode 100644 index 0000000..a6ad342 --- /dev/null +++ b/utility/ecode/common.go @@ -0,0 +1,15 @@ +package ecode + +var ( + OK = New(0, "操作成功") + Sub = New(1, "") // 自定义错误信息 + Fail = New(2, "服务器内部错误") + InvalidOperation = New(3, "非法的操作请求") + Params = New(4, "请求参数错误") + Logout = New(5, "用户未登录") + Disabled = New(6, "账户已被禁用") + Denied = New(7, "没有权限执行该操作") + Auth = New(1000, "账户名或密码不正确") + Password = New(1001, "密码不正确") + EmailExist = New(1002, "该邮箱已被注册") +) diff --git a/utility/ecode/ecode.go b/utility/ecode/ecode.go new file mode 100644 index 0000000..be4db1f --- /dev/null +++ b/utility/ecode/ecode.go @@ -0,0 +1,58 @@ +package ecode + +import ( + "fmt" + "github.com/gogf/gf/v2/errors/gcode" +) + +type Error struct { + code int + message string + sub string + params []interface{} +} + +func New(code int, message string) Error { + return Error{ + code: code, + message: message, + } +} + +func (e Error) Params(params ...interface{}) Error { + e.params = append(e.params, params...) + return e +} + +func (e Error) Error() string { + return e.Message() +} + +func (e Error) Sub(sub string) Error { + e.sub = sub + return e +} + +func (e Error) Message() string { + if e.message != "" && len(e.params) > 0 { + e.message = fmt.Sprintf(e.message, e.params...) + } + if e.sub != "" { + if e.message != "" { + if len(e.params) > 0 { + e.message = fmt.Sprintf(e.message, e.params...) + } + return fmt.Sprintf("%s:%s", e.message, e.sub) + } + return e.sub + } + return e.message +} + +func (e Error) Code() gcode.Code { + return gcode.New(e.code, e.Message(), "customer") +} + +func (e Error) Detail() interface{} { + return "customer" +} diff --git a/utility/encrypt/password.go b/utility/encrypt/password.go new file mode 100644 index 0000000..4a9cb55 --- /dev/null +++ b/utility/encrypt/password.go @@ -0,0 +1,46 @@ +package utility + +import ( + "golang.org/x/crypto/bcrypt" +) + +// EncryptPassword 使用 bcrypt 算法对明文密码进行加密。 +// +// 参数: +// - password: 明文密码字符串。 +// +// 返回值: +// - 加密后的密码哈希(string)。 +// - 可能出现的错误(error)。 +// +// 示例: +// +// hashed, err := EncryptPassword("mySecret123") +// if err != nil { +// // 处理错误 +// } +func EncryptPassword(password string) (string, error) { + // 使用 bcrypt 的默认成本因子(10)进行加密 + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return "", err + } + return string(hashedPassword), nil +} + +// ComparePassword 比较明文密码与加密后的密码哈希是否匹配。 +// +// 参数: +// - hashedPassword: 已加密的密码哈希。 +// - password: 用户输入的明文密码。 +// +// 返回值: +// - 如果匹配返回 true,否则返回 false。 +// +// 示例: +// +// match := ComparePassword(storedHash, "userInput") +func ComparePassword(hashedPassword, password string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) + return err == nil +} diff --git a/utility/encrypt/phone.go b/utility/encrypt/phone.go new file mode 100644 index 0000000..93c7bd8 --- /dev/null +++ b/utility/encrypt/phone.go @@ -0,0 +1,77 @@ +package utility + +import ( + "golang.org/x/crypto/bcrypt" + "regexp" + "strings" +) + +// ValidatePhoneNumber 校验手机号格式是否为中国大陆合法手机号。 +// 去除空格后匹配以 1 开头的 11 位数字,第二位为 3~9。 +// +// 参数: +// - phone: 需要验证的手机号字符串。 +// +// 返回: +// - true 表示格式合法,false 表示格式不合法。 +func ValidatePhoneNumber(phone string) bool { + phone = strings.ReplaceAll(phone, " ", "") + pattern := `^1[3-9]\d{9}$` + matched, err := regexp.MatchString(pattern, phone) + if err != nil { + return false + } + return matched +} + +// EncryptPhoneNumber 加密手机号字符串。 +// 使用 bcrypt 进行加密,适合需要不可逆存储的场景。 +// ⚠️ 注意:加密结果无法解密,仅能做比对用途。 +// +// 参数: +// - phone: 待加密的手机号(需合法)。 +// +// 返回: +// - 加密后的哈希字符串;如果手机号无效或加密失败,返回空字符串。 +func EncryptPhoneNumber(phone string) string { + if !ValidatePhoneNumber(phone) { + return "" + } + hashedPhone, err := bcrypt.GenerateFromPassword([]byte(phone), bcrypt.DefaultCost) + if err != nil { + return "" + } + return string(hashedPhone) +} + +// MaskPhoneNumber 对手机号进行脱敏处理。 +// 中间四位将被替换为星号,以保护用户隐私。 +// +// 参数: +// - phone: 原始手机号字符串(需合法)。 +// +// 返回: +// - 脱敏后的手机号,如 138****1234;如果手机号无效,则返回原始输入。 +func MaskPhoneNumber(phone string) string { + if !ValidatePhoneNumber(phone) { + return phone + } + return phone[:3] + "****" + phone[7:] +} + +// ComparePhoneNumber 比较明文手机号与加密后的哈希是否匹配。 +// 用于验证用户输入的手机号是否与加密存储的值一致。 +// +// 参数: +// - hashedPhone: 使用 bcrypt 加密后的手机号哈希。 +// - phone: 用户输入的明文手机号(需合法)。 +// +// 返回: +// - true 表示匹配成功;false 表示不匹配或格式错误。 +func ComparePhoneNumber(hashedPhone, phone string) bool { + if !ValidatePhoneNumber(phone) { + return false + } + err := bcrypt.CompareHashAndPassword([]byte(hashedPhone), []byte(phone)) + return err == nil +} diff --git a/utility/jwt/jwt.go b/utility/jwt/jwt.go new file mode 100644 index 0000000..14a2af3 --- /dev/null +++ b/utility/jwt/jwt.go @@ -0,0 +1,115 @@ +package jwt + +import ( + "server/utility/ecode" + "strings" + "time" + + "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" +) + +var ( + // secretKey 是用于签名 JWT 的密钥。应替换为更加安全的密钥并妥善保管。 + secretKey = []byte("1a40c1d5b7a1b0f0f835e0b24ca292a6") + + // issuer 表示签发者信息,作为 JWT 标准字段的一部分。 + issuer = "arenax.com" +) + +type ( + // TokenIn 表示生成 JWT 所需的输入参数。 + // + // 字段: + // - UserId: 用户 ID; + // - Permission: 权限标识; + // - ExpireTime: token 过期时间(可选)。 + TokenIn struct { + UserId int // 用户 ID + Permission string // 权限标识 + ExpireTime time.Duration // 令牌有效期 + } + + // TokenOut 表示从 JWT 中解析出的用户信息。 + // + // 字段: + // - UserId: 用户 ID; + // - Permission: 权限标识; + // - JTI: JWT 的唯一标识。 + TokenOut struct { + UserId int // 用户 ID + Permission string // 权限标识 + JTI string // JWT 唯一标识 + } + + // jwtClaims 自定义 JWT 的声明体结构,嵌入标准声明字段。 + jwtClaims struct { + UserId int `json:"user_id"` // 用户 ID + Permission string `json:"permission"` // 权限标识 + JTI string `json:"jti"` // 唯一标识 + jwt.RegisteredClaims + } +) + +// GenerateToken 生成带有自定义权限和过期时间的 JWT 字符串。 +// +// 参数: +// - in: 包含用户 ID、权限、过期时间等信息的 TokenIn 对象。 +// +// 返回: +// - 生成的 JWT 字符串; +// - 若出错则返回错误信息。 +func GenerateToken(in *TokenIn) (string, error) { + expire := in.ExpireTime + if expire <= 0 { + expire = 2 * time.Hour + } + + claims := jwtClaims{ + UserId: in.UserId, + Permission: in.Permission, + JTI: uuid.NewString(), + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(expire)), + IssuedAt: jwt.NewNumericDate(time.Now()), + NotBefore: jwt.NewNumericDate(time.Now()), + Issuer: issuer, + }, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(secretKey) +} + +// ParseToken 解析并验证 JWT 字符串并返回对应的用户信息。 +// 自动去除开头的 "Bearer " 前缀。 +// +// 参数: +// - tokenString: 需要解析的 JWT 字符串。 +// +// 返回: +// - 解析后的 TokenOut 对象; +// - 若失败则返回相应的错误信息。 +func ParseToken(tokenString string) (*TokenOut, error) { + if strings.HasPrefix(tokenString, "Bearer ") { + tokenString = strings.TrimPrefix(tokenString, "Bearer ") + } + + token, err := jwt.ParseWithClaims(tokenString, &jwtClaims{}, func(token *jwt.Token) (interface{}, error) { + return secretKey, nil + }) + if err != nil { + return nil, ecode.Fail.Sub("解析 token 出现异常") + } + + claims, ok := token.Claims.(*jwtClaims) + if !ok || !token.Valid { + return nil, ecode.InvalidOperation.Sub("无效的 Token") + } + + return &TokenOut{ + UserId: claims.UserId, + Permission: claims.Permission, + JTI: claims.JTI, + }, nil +} diff --git a/utility/myCasbin/casbin.go b/utility/myCasbin/casbin.go new file mode 100644 index 0000000..4e47ef2 --- /dev/null +++ b/utility/myCasbin/casbin.go @@ -0,0 +1,64 @@ +package myCasbin + +import ( + "context" + "github.com/casbin/casbin/v2" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/glog" + "github.com/hailaz/gf-casbin-adapter/v2" + "sync" +) + +type myCasbin struct { + *casbin.Enforcer +} + +var ( + instance *myCasbin + once sync.Once +) + +func init() { + ctx := context.Background() + once.Do(func() { + modelPath := g.Config().MustGet(ctx, "casbin.modelPath").String() + enforcer, err := casbin.NewEnforcer(modelPath, adapter.NewAdapter( + adapter.Options{ + GDB: g.DB(), + FieldName: &adapter.FieldName{PType: "p_type"}, + }, + )) + if err != nil { + glog.Errorf(ctx, "init casbin error: %v", err) + } + + instance = &myCasbin{Enforcer: enforcer} + }) + glog.Infof(ctx, "init casbin success") +} + +func GetMyCasbin() *myCasbin { + if instance == nil { + panic("casbin not init") + } + return instance +} + +// HasPermission 判断给定的权限标识是否拥有访问指定 URL 和方法的权限。 +// +// 参数: +// - permission: 权限标识(如角色名或用户 ID) +// - url: 请求的路径(如 "/api/user/list") +// - method: HTTP 请求方法(如 "GET", "POST") +// +// 返回: +// - access: 如果有权限则为 true;否则为 false。 +// - 若校验过程中发生错误,将记录日志并返回 false。 +func (m *myCasbin) HasPermission(permission, url, method string) (access bool) { + enforce, err := m.Enforcer.Enforce(permission, url, method) + if err != nil { + glog.Errorf(context.Background(), "enforce error: %v", err) + return + } + return enforce +} diff --git a/utility/openid.go b/utility/openid.go new file mode 100644 index 0000000..d7863df --- /dev/null +++ b/utility/openid.go @@ -0,0 +1,32 @@ +package utility + +import ( + "fmt" + "math/rand" + "strings" + "time" +) + +// GenerateUserID 根据传入的用户类型生成唯一的用户ID。 +// 用户ID格式为:_<16位数字字符串>,例如:QQ_2025052712345678。 +// 前缀由 userType 参数指定(例如 "qq"、"wx"),自动转换为大写。 +// 数字部分由当前时间戳与随机数拼接而成,确保唯一性。 +// +// 参数: +// - userType: 用户类型,如 "qq" 或 "wx" +// +// 返回值: +// - string: 格式为 <大写前缀>_<16位唯一数字> 的用户ID +func GenerateUserID(userType string) string { + prefix := strings.ToUpper(userType) + + timestamp := fmt.Sprintf("%d", time.Now().UnixNano()) + core := timestamp[:12] + + rand.Seed(time.Now().UnixNano()) + suffix := fmt.Sprintf("%04d", rand.Intn(10000)) + + idNum := core + suffix + + return fmt.Sprintf("%s_%s", prefix, idNum) +}