init admin module

This commit is contained in:
Yavolte 2025-06-13 11:28:59 +08:00
commit 7ea74836aa
19 changed files with 6362 additions and 0 deletions

47
.gitignore vendored 100644
View File

@ -0,0 +1,47 @@
bin/
tests/
.svn/
.godeps
./build
.cover/
dist
_site
_posts
*.dat
.vscode
vendor
cmd/
third_party/
# Go.gitignore
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
storage
.idea
Makefile
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
profile
# vim stuff
*.sw[op]

1
README.md 100644
View File

@ -0,0 +1 @@
# third_party

View File

@ -0,0 +1,58 @@
package defaults
import (
"git.nobla.cn/golang/aeus-admin/models"
"gorm.io/gorm"
)
var (
defaultRoles = []*models.Role{}
defaultUsers = []*models.User{}
)
func init() {
adminRole := &models.Role{}
adminRole.Name = "admin"
adminRole.Label = "管理员"
adminRole.Description = "管理员角色"
defaultRoles = append(defaultRoles, adminRole)
adminUser := &models.User{}
adminUser.Uid = "admin"
adminUser.Username = "admin"
adminUser.Password = "admin"
adminUser.Role = "admin"
adminUser.Admin = true
guestUser := &models.User{}
guestUser.Uid = "guest"
guestUser.Username = "guest"
guestUser.Password = "guest"
guestUser.Role = "admin"
defaultUsers = append(defaultUsers, adminUser, guestUser)
}
func Init(db *gorm.DB) (err error) {
var (
n int64
)
if db.Model(&models.Role{}).Count(&n); n == 0 {
db.Create(defaultRoles)
permissions := make([]*models.Permission, 0)
db.Find(&permissions)
for _, row := range defaultRoles {
items := make([]*models.RolePermission, 0)
for _, perm := range permissions {
item := &models.RolePermission{}
item.Role = row.Name
item.PermissionId = perm.Id
items = append(items, item)
}
db.Save(items)
}
}
if db.Model(&models.User{}).Count(&n); n == 0 {
db.Create(defaultUsers)
}
return
}

59
go.mod 100644
View File

@ -0,0 +1,59 @@
module git.nobla.cn/golang/aeus-admin
go 1.23.0
toolchain go1.23.10
require (
git.nobla.cn/golang/aeus v0.0.7
git.nobla.cn/golang/rest v0.1.1
github.com/envoyproxy/protoc-gen-validate v1.2.1
golang.org/x/text v0.23.0 // indirect
google.golang.org/protobuf v1.36.6
gorm.io/driver/mysql v1.6.0
gorm.io/gorm v1.30.0
)
require (
github.com/golang-jwt/jwt/v5 v5.2.2
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
google.golang.org/grpc v1.72.2
)
replace git.nobla.cn/golang/aeus v0.0.7 => /Users/yavolte/Workspace/golang/aeus
require (
filippo.io/edwards25519 v1.1.0 // indirect
git.nobla.cn/golang/kos v0.1.32 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.10.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.23.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

135
go.sum 100644
View File

@ -0,0 +1,135 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.nobla.cn/golang/kos v0.1.32 h1:sFVCA7vKc8dPUd0cxzwExOSPX2mmMh2IuwL6cYS1pBc=
git.nobla.cn/golang/kos v0.1.32/go.mod h1:35Z070+5oB39WcVrh5DDlnVeftL/Ccmscw2MZFe9fUg=
git.nobla.cn/golang/rest v0.1.1 h1:xsGO/1rDrjcmpeZWv7k1sjqACurBQy5l9wVZ430w0tQ=
git.nobla.cn/golang/rest v0.1.1/go.mod h1:4viDk7VujDokpUeHQGbnSp2bkkVZEoIkWQIs/l/TTPQ=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
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/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
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/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

52
i18n/zh.go 100644
View File

@ -0,0 +1,52 @@
package i18n
import (
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types"
)
type ZH struct {
}
func (t *ZH) Menu(model *rest.Model, label string) string {
if _, ok := model.Value().Interface().(models.Menu); ok {
return "菜单管理"
}
if _, ok := model.Value().Interface().(models.User); ok {
return "用户管理"
}
if _, ok := model.Value().Interface().(models.Role); ok {
return "角色管理"
}
if _, ok := model.Value().Interface().(models.Permission); ok {
return "权限管理"
}
if _, ok := model.Value().Interface().(models.Department); ok {
return "部门管理"
}
if _, ok := model.Value().Interface().(models.RolePermission); ok {
return "角色权限"
}
return label
}
func (t *ZH) Permission(model *rest.Model, scene string, label string) string {
switch scene {
case types.ScenarioList:
return "查看"
case types.ScenarioCreate:
return "新增"
case types.ScenarioUpdate:
return "修改"
case types.ScenarioDelete:
return "删除"
case types.ScenarioView:
return "详情"
case types.ScenarioExport:
return "导出"
case types.ScenarioImport:
return "导入"
}
return label
}

24
models/model.go 100644
View File

@ -0,0 +1,24 @@
package models
import "git.nobla.cn/golang/aeus-admin/pb"
type (
User struct {
pb.UserModel
}
Menu struct {
pb.MenuModel
}
Department struct {
pb.DepartmentModel
}
Role struct {
pb.RoleModel
}
Permission struct {
pb.PermissionModel
}
RolePermission struct {
pb.RolePermissionModel
}
)

1642
pb/organize.pb.go 100644

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

227
pb/organize.proto 100644
View File

@ -0,0 +1,227 @@
syntax = "proto3";
package organize;
import "aeus/rest.proto";
import "validate/validate.proto";
import "google/protobuf/descriptor.proto";
import "google/api/annotations.proto";
option go_package = "git.nobla.cn/golang/aeis-admin/pb;pb";
// Menu
message Menu {
option (aeus.rest) = {
table: "menus"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}];
int64 parent_id = 2;
string name = 3 [(aeus.field)={gorm:"index;size:60"},(validate.rules).string = {max_len: 60}];
string label = 4 [(aeus.field)={gorm:"size:120"},(validate.rules).string = {max_len: 120}];
string uri = 5 [(aeus.field)={gorm:"size:512"},(validate.rules).string = {max_len: 512}];
string view_path = 6 [(aeus.field)={gorm:"size:512"},(validate.rules).string = {max_len: 512}];
string icon = 7 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
bool hidden = 8;
bool public = 9;
}
// Role
message Role {
option (aeus.rest) = {
table: "roles"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}];
string name = 2 [(aeus.field)={gorm:"index;size:60"},(validate.rules).string = {max_len: 60}];
string label = 3 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
string description = 4 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}];
}
// Permission
message Permission {
option (aeus.rest) = {
table: "permissions"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}];
int64 menu_id = 2 [(aeus.field)={gorm:"index"}];
string permission = 3 [(aeus.field)={gorm:"index;size:60"},(validate.rules).string = {max_len: 60}];
string label = 4 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
}
// RolePermission
message RolePermission {
option (aeus.rest) = {
table: "role_permissions"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}];
string role = 2 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
int64 permission_id = 3;
}
// User
message User {
option (aeus.rest) = {
table: "users"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}];
int64 created_at = 2;
int64 updated_at = 3;
string uid = 4 [(aeus.field) = {gorm:"index;size:20"},(validate.rules).string = {min_len: 5, max_len: 20}];
string username = 5 [(aeus.field)={gorm:"size:20"},(validate.rules).string = {min_len: 5, max_len: 20}];
string role = 6 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
bool admin = 7;
int64 dept_id = 8 [(aeus.field) = {gorm:"not null;default:0"}];
string tag = 9 [ (aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
string password = 10 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
string email = 11 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}];
string avatar = 12 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}];
string gender = 13 [(aeus.field)={gorm:"size:20;default:man"},(validate.rules).string = {max_len: 20}];
string description = 14 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}];
}
// Department
message Department {
option (aeus.rest) = {
table: "departments"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}];
int64 created_at = 2;
int64 updated_at = 3;
int64 parent_id = 4;
string name = 5 [(aeus.field)={gorm:"size:20"},(validate.rules).string = {max_len: 20}];
string description = 6 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}];
}
message PermissionItem {
string value = 1;
string label = 2;
}
// MenuItem
message MenuItem {
string label = 1;
string name = 2;
string icon = 3;
bool hidden = 4;
bool public = 5;
string route = 6;
repeated PermissionItem permissions = 7;
repeated MenuItem children = 8;
}
//
message GetMenuRequest {
bool permission = 1;
}
//
message GetMenuResponse {
repeated MenuItem data = 1;
}
//
service MenuService {
rpc GetMenus(GetMenuRequest) returns (GetMenuResponse) {
option (google.api.http) = {
get: "/api/menu"
};
}
}
//
message GetProfileRequest {
string uid = 1;
}
//
message GetProfileResponse {
string uid = 1;
string username = 2;
string role = 3;
string email = 4;
string avatar = 5;
bool admin = 6;
string description = 7;
}
message ResetPasswordRequest {
string uid = 1;
string old_password = 2;
string new_password = 3;
}
message ResetPasswordResponse {
string uid = 1;
}
message UpdateProfileRequest {
string uid = 1;
string username = 2;
string email = 4;
string avatar = 5;
string description = 7;
}
message UpdateProfileResponse {
string uid = 1;
}
//
service ProfileService {
rpc GetProfile(GetProfileRequest) returns (GetProfileResponse) {
option (google.api.http) = {
get: "/user/profile"
};
}
rpc UpdateProfile(UpdateProfileRequest) returns (UpdateProfileResponse) {
option (google.api.http) = {
put: "/user/profile"
body: "*"
};
}
rpc ResetPassword(ResetPasswordRequest) returns (ResetPasswordResponse) {
option (google.api.http) = {
post: "/user/reset-password"
body: "*"
};
}
}
message LoginRequest {
string username = 1;
string password = 2;
string token = 3;
}
message LoginResponse {
string uid = 1;
string username = 2;
string token = 3;
int64 expires = 4;
}
message LogoutRequest {
string token = 1;
}
message LogoutResponse {
string uid = 1;
}
//
service AuthService {
rpc Login(LoginRequest) returns (LoginResponse) {
option (google.api.http) = {
post: "/passport/login"
body: "*"
};
}
rpc Logout(LogoutRequest) returns (LogoutResponse) {
option (google.api.http) = {
post: "/passport/logout"
body: "*"
};
}
}

View File

@ -0,0 +1,451 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.3
// source: organize.proto
package pb
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
MenuService_GetMenus_FullMethodName = "/organize.MenuService/GetMenus"
)
// MenuServiceClient is the client API for MenuService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// 菜单服务
type MenuServiceClient interface {
GetMenus(ctx context.Context, in *GetMenuRequest, opts ...grpc.CallOption) (*GetMenuResponse, error)
}
type menuServiceClient struct {
cc grpc.ClientConnInterface
}
func NewMenuServiceClient(cc grpc.ClientConnInterface) MenuServiceClient {
return &menuServiceClient{cc}
}
func (c *menuServiceClient) GetMenus(ctx context.Context, in *GetMenuRequest, opts ...grpc.CallOption) (*GetMenuResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetMenuResponse)
err := c.cc.Invoke(ctx, MenuService_GetMenus_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// MenuServiceServer is the server API for MenuService service.
// All implementations must embed UnimplementedMenuServiceServer
// for forward compatibility.
//
// 菜单服务
type MenuServiceServer interface {
GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error)
mustEmbedUnimplementedMenuServiceServer()
}
// UnimplementedMenuServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedMenuServiceServer struct{}
func (UnimplementedMenuServiceServer) GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMenus not implemented")
}
func (UnimplementedMenuServiceServer) mustEmbedUnimplementedMenuServiceServer() {}
func (UnimplementedMenuServiceServer) testEmbeddedByValue() {}
// UnsafeMenuServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to MenuServiceServer will
// result in compilation errors.
type UnsafeMenuServiceServer interface {
mustEmbedUnimplementedMenuServiceServer()
}
func RegisterMenuServiceServer(s grpc.ServiceRegistrar, srv MenuServiceServer) {
// If the following call pancis, it indicates UnimplementedMenuServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&MenuService_ServiceDesc, srv)
}
func _MenuService_GetMenus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetMenuRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MenuServiceServer).GetMenus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: MenuService_GetMenus_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MenuServiceServer).GetMenus(ctx, req.(*GetMenuRequest))
}
return interceptor(ctx, in, info, handler)
}
// MenuService_ServiceDesc is the grpc.ServiceDesc for MenuService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var MenuService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.MenuService",
HandlerType: (*MenuServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetMenus",
Handler: _MenuService_GetMenus_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "organize.proto",
}
const (
ProfileService_GetProfile_FullMethodName = "/organize.ProfileService/GetProfile"
ProfileService_UpdateProfile_FullMethodName = "/organize.ProfileService/UpdateProfile"
ProfileService_ResetPassword_FullMethodName = "/organize.ProfileService/ResetPassword"
)
// ProfileServiceClient is the client API for ProfileService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// 用户服务
type ProfileServiceClient interface {
GetProfile(ctx context.Context, in *GetProfileRequest, opts ...grpc.CallOption) (*GetProfileResponse, error)
UpdateProfile(ctx context.Context, in *UpdateProfileRequest, opts ...grpc.CallOption) (*UpdateProfileResponse, error)
ResetPassword(ctx context.Context, in *ResetPasswordRequest, opts ...grpc.CallOption) (*ResetPasswordResponse, error)
}
type profileServiceClient struct {
cc grpc.ClientConnInterface
}
func NewProfileServiceClient(cc grpc.ClientConnInterface) ProfileServiceClient {
return &profileServiceClient{cc}
}
func (c *profileServiceClient) GetProfile(ctx context.Context, in *GetProfileRequest, opts ...grpc.CallOption) (*GetProfileResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetProfileResponse)
err := c.cc.Invoke(ctx, ProfileService_GetProfile_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *profileServiceClient) UpdateProfile(ctx context.Context, in *UpdateProfileRequest, opts ...grpc.CallOption) (*UpdateProfileResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UpdateProfileResponse)
err := c.cc.Invoke(ctx, ProfileService_UpdateProfile_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *profileServiceClient) ResetPassword(ctx context.Context, in *ResetPasswordRequest, opts ...grpc.CallOption) (*ResetPasswordResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ResetPasswordResponse)
err := c.cc.Invoke(ctx, ProfileService_ResetPassword_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ProfileServiceServer is the server API for ProfileService service.
// All implementations must embed UnimplementedProfileServiceServer
// for forward compatibility.
//
// 用户服务
type ProfileServiceServer interface {
GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error)
UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error)
ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error)
mustEmbedUnimplementedProfileServiceServer()
}
// UnimplementedProfileServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedProfileServiceServer struct{}
func (UnimplementedProfileServiceServer) GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetProfile not implemented")
}
func (UnimplementedProfileServiceServer) UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateProfile not implemented")
}
func (UnimplementedProfileServiceServer) ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ResetPassword not implemented")
}
func (UnimplementedProfileServiceServer) mustEmbedUnimplementedProfileServiceServer() {}
func (UnimplementedProfileServiceServer) testEmbeddedByValue() {}
// UnsafeProfileServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ProfileServiceServer will
// result in compilation errors.
type UnsafeProfileServiceServer interface {
mustEmbedUnimplementedProfileServiceServer()
}
func RegisterProfileServiceServer(s grpc.ServiceRegistrar, srv ProfileServiceServer) {
// If the following call pancis, it indicates UnimplementedProfileServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&ProfileService_ServiceDesc, srv)
}
func _ProfileService_GetProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetProfileRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProfileServiceServer).GetProfile(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ProfileService_GetProfile_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProfileServiceServer).GetProfile(ctx, req.(*GetProfileRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProfileService_UpdateProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateProfileRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProfileServiceServer).UpdateProfile(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ProfileService_UpdateProfile_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProfileServiceServer).UpdateProfile(ctx, req.(*UpdateProfileRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProfileService_ResetPassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ResetPasswordRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProfileServiceServer).ResetPassword(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ProfileService_ResetPassword_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProfileServiceServer).ResetPassword(ctx, req.(*ResetPasswordRequest))
}
return interceptor(ctx, in, info, handler)
}
// ProfileService_ServiceDesc is the grpc.ServiceDesc for ProfileService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ProfileService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.ProfileService",
HandlerType: (*ProfileServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetProfile",
Handler: _ProfileService_GetProfile_Handler,
},
{
MethodName: "UpdateProfile",
Handler: _ProfileService_UpdateProfile_Handler,
},
{
MethodName: "ResetPassword",
Handler: _ProfileService_ResetPassword_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "organize.proto",
}
const (
AuthService_Login_FullMethodName = "/organize.AuthService/Login"
AuthService_Logout_FullMethodName = "/organize.AuthService/Logout"
)
// AuthServiceClient is the client API for AuthService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// 授权服务
type AuthServiceClient interface {
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error)
}
type authServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient {
return &authServiceClient{cc}
}
func (c *authServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LoginResponse)
err := c.cc.Invoke(ctx, AuthService_Login_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LogoutResponse)
err := c.cc.Invoke(ctx, AuthService_Logout_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthServiceServer is the server API for AuthService service.
// All implementations must embed UnimplementedAuthServiceServer
// for forward compatibility.
//
// 授权服务
type AuthServiceServer interface {
Login(context.Context, *LoginRequest) (*LoginResponse, error)
Logout(context.Context, *LogoutRequest) (*LogoutResponse, error)
mustEmbedUnimplementedAuthServiceServer()
}
// UnimplementedAuthServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedAuthServiceServer struct{}
func (UnimplementedAuthServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedAuthServiceServer) Logout(context.Context, *LogoutRequest) (*LogoutResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented")
}
func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
func (UnimplementedAuthServiceServer) testEmbeddedByValue() {}
// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuthServiceServer will
// result in compilation errors.
type UnsafeAuthServiceServer interface {
mustEmbedUnimplementedAuthServiceServer()
}
func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) {
// If the following call pancis, it indicates UnimplementedAuthServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&AuthService_ServiceDesc, srv)
}
func _AuthService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LoginRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_Login_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Login(ctx, req.(*LoginRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LogoutRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Logout(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_Logout_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Logout(ctx, req.(*LogoutRequest))
}
return interceptor(ctx, in, info, handler)
}
// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AuthService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.AuthService",
HandlerType: (*AuthServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Login",
Handler: _AuthService_Login_Handler,
},
{
MethodName: "Logout",
Handler: _AuthService_Logout_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "organize.proto",
}

View File

@ -0,0 +1,179 @@
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
// source: organize.proto
// date: 2025-06-13 11:10:07
package pb
import (
"git.nobla.cn/golang/aeus/transport/http"
"context"
"git.nobla.cn/golang/aeus/pkg/errors"
)
type MenuServiceHttpServer interface {
GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error)
}
type ProfileServiceHttpServer interface {
GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error)
UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error)
ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error)
}
type AuthServiceHttpServer interface {
Login(context.Context, *LoginRequest) (*LoginResponse, error)
Logout(context.Context, *LogoutRequest) (*LogoutResponse, error)
}
func handleMenuServiceGetMenus(s MenuServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetMenuRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.GetMenus(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func handleProfileServiceGetProfile(s ProfileServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetProfileRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.GetProfile(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func handleProfileServiceUpdateProfile(s ProfileServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &UpdateProfileRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.UpdateProfile(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func handleProfileServiceResetPassword(s ProfileServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &ResetPasswordRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.ResetPassword(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func handleAuthServiceLogin(s AuthServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &LoginRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.Login(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func handleAuthServiceLogout(s AuthServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &LogoutRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.Logout(ctx.Context(), req); err != nil {
if er, ok := err.(*errors.Error); ok {
return ctx.Error(er.Code, er.Message)
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
} else {
return ctx.Success(res)
}
}
}
func RegisterMenuServiceRouter(hs *http.Server, s MenuServiceHttpServer) {
// Register handle GetMenus route
hs.GET("/api/menu", handleMenuServiceGetMenus(s))
}
func RegisterProfileServiceRouter(hs *http.Server, s ProfileServiceHttpServer) {
// Register handle GetProfile route
hs.GET("/user/profile", handleProfileServiceGetProfile(s))
// Register handle UpdateProfile route
hs.PUT("/user/profile", handleProfileServiceUpdateProfile(s))
// Register handle ResetPassword route
hs.POST("/user/reset-password", handleProfileServiceResetPassword(s))
}
func RegisterAuthServiceRouter(hs *http.Server, s AuthServiceHttpServer) {
// Register handle Login route
hs.POST("/passport/login", handleAuthServiceLogin(s))
// Register handle Logout route
hs.POST("/passport/logout", handleAuthServiceLogout(s))
}

View File

@ -0,0 +1,411 @@
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
// source: organize.proto
// date: 2025-06-13 11:10:07
package pb
import (
"gorm.io/gorm"
)
type MenuModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"`
ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" gorm:"column:parent_id"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:120"`
Uri string `json:"uri" yaml:"uri" xml:"uri" gorm:"size:512"`
ViewPath string `json:"view_path" yaml:"viewPath" xml:"viewPath" gorm:"size:512"`
Icon string `json:"icon" yaml:"icon" xml:"icon" gorm:"size:60"`
Hidden bool `json:"hidden" yaml:"hidden" xml:"hidden" gorm:"column:hidden"`
Public bool `json:"public" yaml:"public" xml:"public" gorm:"column:public"`
}
func (m *MenuModel) TableName() string {
return "menus"
}
func (m *MenuModel) FromValue(x *Menu) {
m.Id = x.Id
m.ParentId = x.ParentId
m.Name = x.Name
m.Label = x.Label
m.Uri = x.Uri
m.ViewPath = x.ViewPath
m.Icon = x.Icon
m.Hidden = x.Hidden
m.Public = x.Public
}
func (m *MenuModel) ToValue() (x *Menu) {
x = &Menu{}
x.Id = m.Id
x.ParentId = m.ParentId
x.Name = m.Name
x.Label = m.Label
x.Uri = m.Uri
x.ViewPath = m.ViewPath
x.Icon = m.Icon
x.Hidden = m.Hidden
x.Public = m.Public
return x
}
func (m *MenuModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *MenuModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *MenuModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *MenuModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *MenuModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("icon=?", pk).First(m).Error
}
func (m *MenuModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *MenuModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewMenuModel() *MenuModel {
return &MenuModel{}
}
type RoleModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024"`
}
func (m *RoleModel) TableName() string {
return "roles"
}
func (m *RoleModel) FromValue(x *Role) {
m.Id = x.Id
m.Name = x.Name
m.Label = x.Label
m.Description = x.Description
}
func (m *RoleModel) ToValue() (x *Role) {
x = &Role{}
x.Id = m.Id
x.Name = m.Name
x.Label = m.Label
x.Description = m.Description
return x
}
func (m *RoleModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *RoleModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *RoleModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *RoleModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *RoleModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("description=?", pk).First(m).Error
}
func (m *RoleModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *RoleModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewRoleModel() *RoleModel {
return &RoleModel{}
}
type PermissionModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"`
MenuId int64 `json:"menu_id" yaml:"menuId" xml:"menuId" gorm:"index"`
Permission string `json:"permission" yaml:"permission" xml:"permission" gorm:"index;size:60"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60"`
}
func (m *PermissionModel) TableName() string {
return "permissions"
}
func (m *PermissionModel) FromValue(x *Permission) {
m.Id = x.Id
m.MenuId = x.MenuId
m.Permission = x.Permission
m.Label = x.Label
}
func (m *PermissionModel) ToValue() (x *Permission) {
x = &Permission{}
x.Id = m.Id
x.MenuId = m.MenuId
x.Permission = m.Permission
x.Label = m.Label
return x
}
func (m *PermissionModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *PermissionModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *PermissionModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *PermissionModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *PermissionModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("label=?", pk).First(m).Error
}
func (m *PermissionModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *PermissionModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewPermissionModel() *PermissionModel {
return &PermissionModel{}
}
type RolePermissionModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"`
Role string `json:"role" yaml:"role" xml:"role" gorm:"size:60"`
PermissionId int64 `json:"permission_id" yaml:"permissionId" xml:"permissionId" gorm:"column:permission_id"`
}
func (m *RolePermissionModel) TableName() string {
return "role_permissions"
}
func (m *RolePermissionModel) FromValue(x *RolePermission) {
m.Id = x.Id
m.Role = x.Role
m.PermissionId = x.PermissionId
}
func (m *RolePermissionModel) ToValue() (x *RolePermission) {
x = &RolePermission{}
x.Id = m.Id
x.Role = m.Role
x.PermissionId = m.PermissionId
return x
}
func (m *RolePermissionModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *RolePermissionModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *RolePermissionModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *RolePermissionModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *RolePermissionModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("role=?", pk).First(m).Error
}
func (m *RolePermissionModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *RolePermissionModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewRolePermissionModel() *RolePermissionModel {
return &RolePermissionModel{}
}
type UserModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" gorm:"column:created_at"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"column:updated_at"`
Uid string `json:"uid" yaml:"uid" xml:"uid" gorm:"index;size:20"`
Username string `json:"username" yaml:"username" xml:"username" gorm:"size:20"`
Role string `json:"role" yaml:"role" xml:"role" gorm:"size:60"`
Admin bool `json:"admin" yaml:"admin" xml:"admin" gorm:"column:admin"`
DeptId int64 `json:"dept_id" yaml:"deptId" xml:"deptId" gorm:"not null;default:0"`
Tag string `json:"tag" yaml:"tag" xml:"tag" gorm:"size:60"`
Password string `json:"password" yaml:"password" xml:"password" gorm:"size:60"`
Email string `json:"email" yaml:"email" xml:"email" gorm:"size:60"`
Avatar string `json:"avatar" yaml:"avatar" xml:"avatar" gorm:"size:1024"`
Gender string `json:"gender" yaml:"gender" xml:"gender" gorm:"size:20;default:man"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024"`
}
func (m *UserModel) TableName() string {
return "users"
}
func (m *UserModel) FromValue(x *User) {
m.Id = x.Id
m.CreatedAt = x.CreatedAt
m.UpdatedAt = x.UpdatedAt
m.Uid = x.Uid
m.Username = x.Username
m.Role = x.Role
m.Admin = x.Admin
m.DeptId = x.DeptId
m.Tag = x.Tag
m.Password = x.Password
m.Email = x.Email
m.Avatar = x.Avatar
m.Gender = x.Gender
m.Description = x.Description
}
func (m *UserModel) ToValue() (x *User) {
x = &User{}
x.Id = m.Id
x.CreatedAt = m.CreatedAt
x.UpdatedAt = m.UpdatedAt
x.Uid = m.Uid
x.Username = m.Username
x.Role = m.Role
x.Admin = m.Admin
x.DeptId = m.DeptId
x.Tag = m.Tag
x.Password = m.Password
x.Email = m.Email
x.Avatar = m.Avatar
x.Gender = m.Gender
x.Description = m.Description
return x
}
func (m *UserModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *UserModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *UserModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *UserModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *UserModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("description=?", pk).First(m).Error
}
func (m *UserModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *UserModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewUserModel() *UserModel {
return &UserModel{}
}
type DepartmentModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" gorm:"column:created_at"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"column:updated_at"`
ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" gorm:"column:parent_id"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"size:20"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024"`
}
func (m *DepartmentModel) TableName() string {
return "departments"
}
func (m *DepartmentModel) FromValue(x *Department) {
m.Id = x.Id
m.CreatedAt = x.CreatedAt
m.UpdatedAt = x.UpdatedAt
m.ParentId = x.ParentId
m.Name = x.Name
m.Description = x.Description
}
func (m *DepartmentModel) ToValue() (x *Department) {
x = &Department{}
x.Id = m.Id
x.CreatedAt = m.CreatedAt
x.UpdatedAt = m.UpdatedAt
x.ParentId = m.ParentId
x.Name = m.Name
x.Description = m.Description
return x
}
func (m *DepartmentModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *DepartmentModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *DepartmentModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *DepartmentModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *DepartmentModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("description=?", pk).First(m).Error
}
func (m *DepartmentModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *DepartmentModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewDepartmentModel() *DepartmentModel {
return &DepartmentModel{}
}

145
server.go 100644
View File

@ -0,0 +1,145 @@
package aeusadmin
import (
"context"
"path"
"git.nobla.cn/golang/aeus-admin/defaults"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus/pkg/errors"
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/inflector"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm"
)
// getModels 获取预定义的模型列表
func getModels() []any {
return []any{
&models.User{},
&models.Role{},
&models.Menu{},
&models.Department{},
&models.Permission{},
&models.RolePermission{},
}
}
// checkModelMenu 检查模型菜单
func checkModelMenu(db *gorm.DB, viewPath string, model *rest.Model, translate Translate) (value *models.Menu, err error) {
menuName := inflector.Camelize(model.Naming().ModuleName) + inflector.Camelize(model.Naming().Singular)
value = &models.Menu{}
if err = db.Where("name = ?", menuName).First(value).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
value.Name = menuName
value.ParentId = 0
value.ViewPath = path.Join(viewPath, model.ModuleName(), model.Naming().Singular, "Index.vue")
value.Label = inflector.Camel2words(model.Naming().Pluralize)
if translate != nil {
value.Label = translate.Menu(model, value.Label)
}
value.Uri = model.Uri(types.ScenarioList)
err = db.Create(value).Error
}
}
return
}
// checkModelPermission 检查模型权限是否写入到数据库
func checkModelPermission(db *gorm.DB, menuId int64, scene string, model *rest.Model, translate Translate) (permissionModel *models.Permission, err error) {
permissionModel = &models.Permission{}
permission := model.Permission(scene)
if err = db.Where("permission = ?", permission).First(permissionModel).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
permissionModel.MenuId = menuId
permissionModel.Label = scene
if translate != nil {
permissionModel.Label = translate.Permission(model, scene, permissionModel.Label)
}
permissionModel.Permission = permission
err = db.Create(permissionModel).Error
}
}
return
}
// checkModel 检查模型
func checkModel(opts *options, model *rest.Model) (err error) {
var (
menuModel *models.Menu
)
tx := opts.db.Begin()
if menuModel, err = checkModelMenu(tx, opts.viewPath, model, opts.translate); err != nil {
tx.Rollback()
return
}
for _, s := range defaultScenarios {
if model.HasScenario(s) {
if _, err = checkModelPermission(tx, menuModel.Id, s, model, opts.translate); err != nil {
tx.Rollback()
return
}
}
}
tx.Commit()
return
}
// initREST 初始化REST模块
func initREST(ctx context.Context, o *options) (err error) {
tx := o.db
if tx == nil {
return errors.ErrUnavailable
}
opts := make([]rest.Option, 0)
opts = append(opts, o.restOpts...)
opts = append(opts, rest.WithDB(tx))
if err = rest.Init(opts...); err != nil {
return
}
if err = tx.AutoMigrate(getModels()...); err != nil {
return
}
return
}
// initRBAC 初始化权限控制, 用于生成角色权限相关的信息
func initRBAC(ctx context.Context, o *options) (err error) {
var mv *rest.Model
for _, v := range getModels() {
if mv, err = rest.AutoMigrate(ctx, v); err != nil {
return
} else {
if err = checkModel(o, mv); err != nil {
return
}
}
}
return
}
// AutoMigrate 自动生成一个模型的schema和权限的定义
func AutoMigrate(ctx context.Context, db *gorm.DB, model any, cbs ...Option) (err error) {
var (
mv *rest.Model
)
opts := newOptions(cbs...)
if mv, err = rest.AutoMigrate(ctx, model); err != nil {
return
}
err = checkModel(opts, mv)
return
}
// Init 初始化模块
func Init(ctx context.Context, cbs ...Option) (err error) {
opts := newOptions(cbs...)
if err = initREST(ctx, opts); err != nil {
return
}
if err = initRBAC(ctx, opts); err != nil {
return
}
err = defaults.Init(opts.db)
return
}

98
service/auth.go 100644
View File

@ -0,0 +1,98 @@
package service
import (
"context"
"time"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/types"
"git.nobla.cn/golang/aeus/pkg/errors"
jwt "github.com/golang-jwt/jwt/v5"
"gorm.io/gorm"
)
type (
authOptions struct {
db *gorm.DB
secret []byte
method string
ttl int64
}
AuthOption func(o *authOptions)
AuthService struct {
opts *authOptions
}
)
func WithAuthDB(db *gorm.DB) AuthOption {
return func(o *authOptions) {
o.db = db
}
}
func WithAuthSecret(secret []byte) AuthOption {
return func(o *authOptions) {
o.secret = secret
}
}
func WithAuthMethod(method string) AuthOption {
return func(o *authOptions) {
o.method = method
}
}
func WithAuthTTL(ttl int64) AuthOption {
return func(o *authOptions) {
o.ttl = ttl
}
}
func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (res *pb.LoginResponse, err error) {
model := &models.User{}
tx := s.opts.db.WithContext(ctx)
if err = req.Validate(); err != nil {
return nil, errors.Format(errors.Invalid, err.Error())
}
if err = model.FindOne(tx, "uid=?", req.Username); err != nil {
return
}
if model.Password != req.Password {
err = errors.ErrAccessDenied
return
}
claims := types.Claims{
Uid: model.Uid,
Role: model.Role,
IssuedAt: time.Now().Unix(),
ExpirationAt: time.Now().Add(time.Second * time.Duration(s.opts.ttl)).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
res = &pb.LoginResponse{}
if res.Token, err = token.SignedString(s.opts.secret); err == nil {
res.Uid = model.Uid
res.Username = model.Username
res.Expires = s.opts.ttl
}
return
}
func (s *AuthService) Logout(ctx context.Context, req *pb.LogoutRequest) (res *pb.LogoutResponse, err error) {
return
}
func NewAuthService(cbs ...AuthOption) *AuthService {
opts := &authOptions{
ttl: 7200,
}
for _, cb := range cbs {
cb(opts)
}
return &AuthService{
opts: opts,
}
}

113
service/menu.go 100644
View File

@ -0,0 +1,113 @@
package service
import (
"context"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/types"
"git.nobla.cn/golang/aeus/middleware/auth"
"git.nobla.cn/golang/aeus/pkg/errors"
"gorm.io/gorm"
)
type (
menuOptions struct {
db *gorm.DB
}
MenuOption func(o *menuOptions)
MenuService struct {
opts *menuOptions
}
)
func WithMenuDB(db *gorm.DB) MenuOption {
return func(o *menuOptions) {
o.db = db
}
}
func (s *MenuService) hasPermission(menuID int64, permissions []*models.Permission) bool {
for _, permission := range permissions {
if permission.MenuId == menuID {
return true
}
}
return false
}
func (s *MenuService) getPermissions(menuID int64, permissions []*models.Permission) []*pb.PermissionItem {
ss := make([]*pb.PermissionItem, 0, 10)
for _, permission := range permissions {
if permission.MenuId == menuID {
ss = append(ss, &pb.PermissionItem{
Value: permission.Permission,
Label: permission.Label,
})
}
}
return ss
}
func (s *MenuService) recursiveNestedMenu(ctx context.Context, parent int64, perm bool, menus []*models.Menu, permissions []*models.Permission) []*pb.MenuItem {
values := make([]*pb.MenuItem, 0)
for _, row := range menus {
if row.ParentId == parent {
if !row.Public && !s.hasPermission(row.Id, permissions) {
continue
}
v := &pb.MenuItem{
Label: row.Label,
Name: row.Name,
Icon: row.Icon,
Hidden: row.Hidden,
Route: row.Uri,
Children: s.recursiveNestedMenu(ctx, row.Id, perm, menus, permissions),
}
if perm {
v.Permissions = s.getPermissions(row.Id, permissions)
}
values = append(values, v)
}
}
return values
}
func (s *MenuService) GetRolePermissions(ctx context.Context, db *gorm.DB, role string) (permissions []*models.Permission, err error) {
permissions = make([]*models.Permission, 0)
err = db.Where("id IN (SELECT permission_id FROM role_permissions WHERE role = ?)", role).Find(&permissions).Error
return
}
func (s *MenuService) GetMenus(ctx context.Context, req *pb.GetMenuRequest) (res *pb.GetMenuResponse, err error) {
claims, ok := auth.FromContext(ctx)
if !ok {
return nil, errors.ErrAccessDenied
}
var (
permissions []*models.Permission
)
tx := s.opts.db.WithContext(ctx)
if claims, ok := claims.(*types.Claims); ok {
permissions, err = s.GetRolePermissions(ctx, tx, claims.Role)
}
values := make([]*models.Menu, 0)
if err = tx.Find(&values).Error; err != nil {
return
}
res = &pb.GetMenuResponse{
Data: s.recursiveNestedMenu(ctx, 0, req.Permission, values, permissions),
}
return
}
func NewMenuService(cbs ...MenuOption) *MenuService {
opts := &menuOptions{}
for _, cb := range cbs {
cb(opts)
}
return &MenuService{
opts: opts,
}
}

113
service/profile.go 100644
View File

@ -0,0 +1,113 @@
package service
import (
"context"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus/middleware/auth"
"git.nobla.cn/golang/aeus/pkg/errors"
"gorm.io/gorm"
)
type (
profileOptions struct {
db *gorm.DB
}
ProfileOption func(o *profileOptions)
ProfileService struct {
opts *profileOptions
}
)
func WithProfileDB(db *gorm.DB) ProfileOption {
return func(o *profileOptions) {
o.db = db
}
}
func (s *ProfileService) getUidFromContext(ctx context.Context) (string, error) {
if claims, ok := auth.FromContext(ctx); !ok {
return "", errors.ErrAccessDenied
} else {
return claims.GetSubject()
}
}
func (s *ProfileService) GetProfile(ctx context.Context, req *pb.GetProfileRequest) (res *pb.GetProfileResponse, err error) {
if req.Uid == "" {
if req.Uid, err = s.getUidFromContext(ctx); err != nil {
return
}
}
res = &pb.GetProfileResponse{}
tx := s.opts.db.WithContext(ctx)
err = tx.Table("users AS u").Select("u.uid as uid", "u.username", "u.avatar", "u.email", "u.description", "u.role_id as role").Where("u.uid=? ", req.Uid).First(res).Error
return
}
func (s *ProfileService) UpdateProfile(ctx context.Context, req *pb.UpdateProfileRequest) (res *pb.UpdateProfileResponse, err error) {
if req.Uid == "" {
if req.Uid, err = s.getUidFromContext(ctx); err != nil {
return
}
}
userModel := &models.User{}
tx := s.opts.db.WithContext(ctx)
if err = tx.Where("uid=?", req.Uid).First(userModel).Error; err != nil {
return
}
if req.Avatar != "" {
userModel.Avatar = req.Avatar
}
if req.Email != "" {
userModel.Email = req.Email
}
if req.Username != "" {
userModel.Username = req.Username
}
if req.Description != "" {
userModel.Description = req.Description
}
if err = tx.Save(userModel).Error; err == nil {
res = &pb.UpdateProfileResponse{
Uid: userModel.Uid,
}
}
return
}
func (s *ProfileService) ResetPassword(ctx context.Context, req *pb.ResetPasswordRequest) (res *pb.ResetPasswordResponse, err error) {
if req.Uid == "" {
if req.Uid, err = s.getUidFromContext(ctx); err != nil {
return
}
}
userModel := &models.User{}
tx := s.opts.db.WithContext(ctx)
if err = tx.Where("uid=?", req.Uid).First(userModel).Error; err != nil {
return
}
if userModel.Password == req.OldPassword {
if err = tx.Where("uid=?", req.Uid).Model(&models.User{}).UpdateColumn("password", req.NewPassword).Error; err == nil {
res = &pb.ResetPasswordResponse{
Uid: userModel.Uid,
}
}
} else {
err = errors.Format(errors.AccessDenied, "invalid old password")
}
return
}
func NewProfileService(cbs ...ProfileOption) *ProfileService {
opts := &profileOptions{}
for _, cb := range cbs {
cb(opts)
}
return &ProfileService{
opts: opts,
}
}

76
types.go 100644
View File

@ -0,0 +1,76 @@
package aeusadmin
import (
"git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types"
"gorm.io/gorm"
)
var (
defaultScenarios = []string{
types.ScenarioList,
types.ScenarioCreate,
types.ScenarioUpdate,
types.ScenarioDelete,
types.ScenarioView,
types.ScenarioImport,
types.ScenarioExport,
}
)
type (
options struct {
db *gorm.DB
moduleName string
viewPath string
translate Translate
restOpts []rest.Option
}
Option func(*options)
Translate interface {
Menu(model *rest.Model, label string) string
Permission(model *rest.Model, scene string, label string) string
}
)
func WithDB(db *gorm.DB) Option {
return func(o *options) {
o.db = db
}
}
func WithModuleName(moduleName string) Option {
return func(o *options) {
o.moduleName = moduleName
}
}
func WithViewPath(viewPath string) Option {
return func(o *options) {
o.viewPath = viewPath
}
}
func WithTranslate(t Translate) Option {
return func(o *options) {
o.translate = t
}
}
func WithRestOptions(opts ...rest.Option) Option {
return func(o *options) {
o.restOpts = opts
}
}
func newOptions(opts ...Option) *options {
o := &options{
viewPath: "views",
}
for _, opt := range opts {
opt(o)
}
return o
}

41
types/claims.go 100644
View File

@ -0,0 +1,41 @@
package types
import (
"time"
"github.com/golang-jwt/jwt/v5"
)
type Claims struct {
Uid string `json:"uid"`
Role string `json:"uro"`
Issuer string `json:"iss"`
IssuedAt int64 `json:"iat"`
ExpirationAt int64 `json:"exp"`
Audience []string `json:"aud,omitempty"`
}
func (c Claims) GetExpirationTime() (*jwt.NumericDate, error) {
d := jwt.NewNumericDate(time.Unix(c.ExpirationAt, 0))
return d, nil
}
func (c Claims) GetIssuedAt() (*jwt.NumericDate, error) {
return jwt.NewNumericDate(time.Unix(c.IssuedAt, 0)), nil
}
func (c Claims) GetNotBefore() (*jwt.NumericDate, error) {
return jwt.NewNumericDate(time.Unix(c.IssuedAt, 0)), nil
}
func (c Claims) GetIssuer() (string, error) {
return c.Issuer, nil
}
func (c Claims) GetSubject() (string, error) {
return c.Uid, nil
}
func (c Claims) GetAudience() (jwt.ClaimStrings, error) {
return jwt.ClaimStrings(c.Audience), nil
}