Compare commits

...

2 Commits

Author SHA1 Message Date
Yavolte 56d50536fc add db cache and permission checker 2025-06-17 17:13:53 +08:00
Yavolte c40bf36de3 update service 2025-06-16 11:37:57 +08:00
27 changed files with 6434 additions and 762 deletions

View File

@ -1 +1,2 @@
# third_party # 权限配置

View File

@ -1,13 +1,17 @@
package defaults package defaults
import ( import (
"errors"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"gorm.io/gorm" "gorm.io/gorm"
) )
var ( var (
defaultRoles = []*models.Role{} defaultRoles = []*models.Role{}
defaultUsers = []*models.User{} defaultUsers = []*models.User{}
defaultMenus = []*models.Menu{}
defaultDepartments = []*models.Department{}
) )
func init() { func init() {
@ -19,23 +23,86 @@ func init() {
adminUser := &models.User{} adminUser := &models.User{}
adminUser.Uid = "admin" adminUser.Uid = "admin"
adminUser.Username = "admin" adminUser.Username = "管理员"
adminUser.Password = "admin" adminUser.Password = "admin"
adminUser.Role = "admin" adminUser.Role = "admin"
adminUser.Admin = true adminUser.Admin = true
adminUser.DeptId = 1
guestUser := &models.User{} guestUser := &models.User{}
guestUser.Uid = "guest" guestUser.Uid = "test"
guestUser.Username = "guest" guestUser.Username = "测试人员"
guestUser.Password = "guest" guestUser.Password = "test"
guestUser.Role = "admin" guestUser.Role = "admin"
guestUser.DeptId = 1
defaultUsers = append(defaultUsers, adminUser, guestUser) defaultUsers = append(defaultUsers, adminUser, guestUser)
dashboardMenu := &models.Menu{}
dashboardMenu.Icon = "dashboard"
dashboardMenu.Label = "系统首页"
dashboardMenu.Name = "Dashboard"
dashboardMenu.Public = true
dashboardMenu.Uri = "/dashboard"
dashboardMenu.ViewPath = "../views/dashboard/Index.vue"
orgMenu := &models.Menu{}
orgMenu.Icon = "org"
orgMenu.Label = "组织机构"
orgMenu.Name = "Organize"
orgMenu.Public = true
orgMenu.Uri = "/organize"
profileMenu := &models.Menu{}
profileMenu.Label = "个人信息"
profileMenu.Name = "OrganizeUserProfile"
profileMenu.Public = true
profileMenu.Hidden = true
profileMenu.Parent = "Organize"
profileMenu.Uri = "/organize/user/profile"
profileMenu.ViewPath = "../views/organize/user/Profile.vue"
settingMenu := &models.Menu{}
settingMenu.Icon = "connect"
settingMenu.Label = "系统设置"
settingMenu.Name = "System"
settingMenu.Public = true
settingMenu.Uri = "/system"
schemaMenu := &models.Menu{}
schemaMenu.Label = "字段设置"
schemaMenu.Parent = "System"
schemaMenu.Name = "SystemSchema"
schemaMenu.Uri = "/system/schemas"
schemaMenu.Public = true
schemaMenu.Hidden = true
schemaMenu.ViewPath = "../views/system/schema/Index.vue"
defaultMenus = append(defaultMenus, dashboardMenu, orgMenu, settingMenu, profileMenu, schemaMenu)
systemDepartment := &models.Department{}
systemDepartment.Name = "系统部门"
systemDepartment.Description = ""
defaultDepartments = append(defaultDepartments, systemDepartment)
} }
func Init(db *gorm.DB) (err error) { func MergeMenu(db *gorm.DB, model *models.Menu) (err error) {
if err = db.Where("name = ?", model.Name).First(model).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
err = db.Create(model).Error
}
}
return
}
func Generate(db *gorm.DB) (err error) {
var ( var (
n int64 n int64
) )
for _, row := range defaultMenus {
if err = MergeMenu(db, row); err != nil {
return
}
}
if db.Model(&models.Role{}).Count(&n); n == 0 { if db.Model(&models.Role{}).Count(&n); n == 0 {
db.Create(defaultRoles) db.Create(defaultRoles)
permissions := make([]*models.Permission, 0) permissions := make([]*models.Permission, 0)
@ -45,12 +112,16 @@ func Init(db *gorm.DB) (err error) {
for _, perm := range permissions { for _, perm := range permissions {
item := &models.RolePermission{} item := &models.RolePermission{}
item.Role = row.Name item.Role = row.Name
item.PermissionId = perm.Id item.Permission = perm.Permission
items = append(items, item) items = append(items, item)
} }
db.Save(items) db.Save(items)
} }
} }
if db.Model(&models.Department{}).Count(&n); n == 0 {
db.Create(defaultDepartments)
}
if db.Model(&models.User{}).Count(&n); n == 0 { if db.Model(&models.User{}).Count(&n); n == 0 {
db.Create(defaultUsers) db.Create(defaultUsers)
} }

6
go.mod
View File

@ -16,11 +16,15 @@ require (
require ( require (
github.com/golang-jwt/jwt/v5 v5.2.2 github.com/golang-jwt/jwt/v5 v5.2.2
github.com/mssola/useragent v1.0.0
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
google.golang.org/grpc v1.72.2 google.golang.org/grpc v1.72.2
) )
replace git.nobla.cn/golang/aeus v0.0.7 => /Users/yavolte/Workspace/golang/aeus replace (
git.nobla.cn/golang/aeus v0.0.7 => /Users/yavolte/Workspace/golang/aeus
git.nobla.cn/golang/rest v0.1.1 => /Users/yavolte/Workspace/golang/rest
)
require ( require (
filippo.io/edwards25519 v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect

4
go.sum
View File

@ -2,8 +2,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= 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 h1:sFVCA7vKc8dPUd0cxzwExOSPX2mmMh2IuwL6cYS1pBc=
git.nobla.cn/golang/kos v0.1.32/go.mod h1:35Z070+5oB39WcVrh5DDlnVeftL/Ccmscw2MZFe9fUg= 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 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= 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 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
@ -67,6 +65,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mssola/useragent v1.0.0 h1:WRlDpXyxHDNfvZaPEut5Biveq86Ze4o4EMffyMxmH5o=
github.com/mssola/useragent v1.0.0/go.mod h1:hz9Cqz4RXusgg1EdI4Al0INR62kP7aPSRNHnpU+b85Y=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= 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/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View File

@ -19,6 +19,9 @@ func (t *ZH) Menu(model *rest.Model, label string) string {
if _, ok := model.Value().Interface().(models.Role); ok { if _, ok := model.Value().Interface().(models.Role); ok {
return "角色管理" return "角色管理"
} }
if _, ok := model.Value().Interface().(models.Login); ok {
return "登录记录"
}
if _, ok := model.Value().Interface().(models.Permission); ok { if _, ok := model.Value().Interface().(models.Permission); ok {
return "权限管理" return "权限管理"
} }
@ -28,6 +31,9 @@ func (t *ZH) Menu(model *rest.Model, label string) string {
if _, ok := model.Value().Interface().(models.RolePermission); ok { if _, ok := model.Value().Interface().(models.RolePermission); ok {
return "角色权限" return "角色权限"
} }
if _, ok := model.Value().Interface().(models.Setting); ok {
return "参数设置"
}
return label return label
} }

View File

@ -1,6 +1,10 @@
package models package models
import "git.nobla.cn/golang/aeus-admin/pb" import (
"git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/types"
restTypes "git.nobla.cn/golang/rest/types"
)
type ( type (
User struct { User struct {
@ -9,6 +13,9 @@ type (
Menu struct { Menu struct {
pb.MenuModel pb.MenuModel
} }
Login struct {
pb.LoginModel
}
Department struct { Department struct {
pb.DepartmentModel pb.DepartmentModel
} }
@ -21,4 +28,98 @@ type (
RolePermission struct { RolePermission struct {
pb.RolePermissionModel pb.RolePermissionModel
} }
Setting struct {
pb.SettingModel
}
) )
func (m *User) GetMenu() *types.Menu {
return &types.Menu{
Name: "OrganizeUser",
Parent: "Organize",
}
}
func (m *Login) GetMenu() *types.Menu {
return &types.Menu{
Name: "OrganizeLogin",
Parent: "Organize",
}
}
func (m *Login) Scenario() []string {
return []string{restTypes.ScenarioList}
}
func (m *Menu) GetMenu() *types.Menu {
return &types.Menu{
Name: "OrganizeMenu",
Parent: "Organize",
}
}
func (m *Menu) ModelPermissions() map[string]string {
return map[string]string{
"organize:permission:list": "权限",
}
}
func (m *Department) GetMenu() *types.Menu {
return &types.Menu{
Name: "OrganizeDepartment",
Parent: "Organize",
}
}
func (m *Role) GetMenu() *types.Menu {
return &types.Menu{
Name: "OrganizeRole",
Parent: "Organize",
}
}
func (m *Role) ModelPermissions() map[string]string {
return map[string]string{
"organize:role_permission:list": "权限",
}
}
func (m *Permission) GetMenu() *types.Menu {
return &types.Menu{
Name: "OrganizePermission",
Parent: "Organize",
Hidden: true,
Uri: "/organize/menu/permission/:id",
ViewPath: "../views/organize/menu/Permission.vue",
}
}
func (m *Permission) GetPermission(s string) string {
return "organize:permission:list"
}
func (m *RolePermission) GetMenu() *types.Menu {
return &types.Menu{
Name: "OrganizeRolePermission",
Parent: "Organize",
Hidden: true,
Uri: "/organize/role/permission/:id",
ViewPath: "../views/organize/role/Permission.vue",
}
}
func (m *RolePermission) GetPermission(s string) string {
return "organize:role_permission:list"
}
func (m *Setting) GetMenu() *types.Menu {
return &types.Menu{
Name: "SystemSetting",
Parent: "System",
}
}
func (m *Setting) ModuleName() string {
return "system"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,15 +14,18 @@ message Menu {
option (aeus.rest) = { option (aeus.rest) = {
table: "menus" table: "menus"
}; };
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"菜单ID"}];
int64 parent_id = 2; int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
string name = 3 [(aeus.field)={gorm:"index;size:60"},(validate.rules).string = {max_len: 60}]; int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
string label = 4 [(aeus.field)={gorm:"size:120"},(validate.rules).string = {max_len: 120}]; string parent = 4 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",comment:"父级菜单"}];
string uri = 5 [(aeus.field)={gorm:"size:512"},(validate.rules).string = {max_len: 512}]; string name = 5 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",rule:"unique;required",comment: "组件名称"},(validate.rules).string = {max_len: 60}];
string view_path = 6 [(aeus.field)={gorm:"size:512"},(validate.rules).string = {max_len: 512}]; string label = 6 [(aeus.field)={gorm:"size:120",rule:"required",comment: "菜单标题"},(validate.rules).string = {max_len: 120}];
string icon = 7 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; string uri = 7 [(aeus.field)={gorm:"size:512",rule:"required",scenarios:"create;update;view;export",comment: "菜单链接"},(validate.rules).string = {max_len: 512}];
bool hidden = 8; string view_path = 8 [(aeus.field)={gorm:"size:512",scenarios:"create;update;view;export",comment: "视图路径"},(validate.rules).string = {max_len: 512}];
bool public = 9; string icon = 9 [(aeus.field)={gorm:"size:60",scenarios:"create;update;view;export",comment: "菜单图标"},(validate.rules).string = {max_len: 60}];
bool hidden = 10 [(aeus.field)={scenarios:"create;update;view;export",comment:"是否隐藏"}];
bool public = 11 [(aeus.field)={scenarios:"create;update;view;export",comment:"是否公开"}];
string description = 12 [(aeus.field)={gorm:"size:1024",scenarios:"create;update;view;export;list",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
} }
// Role // Role
@ -30,10 +33,12 @@ message Role {
option (aeus.rest) = { option (aeus.rest) = {
table: "roles" table: "roles"
}; };
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment: "角色ID"}];
string name = 2 [(aeus.field)={gorm:"index;size:60"},(validate.rules).string = {max_len: 60}]; int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
string label = 3 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
string description = 4 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}]; string name = 4 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",comment: "角色名称"},(validate.rules).string = {max_len: 60}];
string label = 5 [(aeus.field)={gorm:"size:60",comment: "角色标题"},(validate.rules).string = {max_len: 60}];
string description = 6 [(aeus.field)={gorm:"size:1024",scenarios:"list;create;update;export",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
} }
// Permission // Permission
@ -41,10 +46,10 @@ message Permission {
option (aeus.rest) = { option (aeus.rest) = {
table: "permissions" table: "permissions"
}; };
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment: "权限ID"}];
int64 menu_id = 2 [(aeus.field)={gorm:"index"}]; string menu = 2 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "所属菜单"}];
string permission = 3 [(aeus.field)={gorm:"index;size:60"},(validate.rules).string = {max_len: 60}]; string permission = 3 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "权限名称"},(validate.rules).string = {max_len: 60}];
string label = 4 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; string label = 4 [(aeus.field)={gorm:"size:60",rule:"required",comment: "权限标题"},(validate.rules).string = {max_len: 60}];
} }
// RolePermission // RolePermission
@ -52,9 +57,9 @@ message RolePermission {
option (aeus.rest) = { option (aeus.rest) = {
table: "role_permissions" table: "role_permissions"
}; };
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment: "ID"}];
string role = 2 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; string role = 2 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "角色"},(validate.rules).string = {max_len: 60}];
int64 permission_id = 3; string permission = 3 [(aeus.field)={gorm:"size:60",rule:"required",comment: "权限"}];
} }
// User // User
@ -62,20 +67,21 @@ message User {
option (aeus.rest) = { option (aeus.rest) = {
table: "users" table: "users"
}; };
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment: "ID"}];
int64 created_at = 2; int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
int64 updated_at = 3; int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
string uid = 4 [(aeus.field) = {gorm:"index;size:20"},(validate.rules).string = {min_len: 5, max_len: 20}]; string uid = 4 [(aeus.field) = {gorm:"index;size:20",rule:"required;unique;regexp:^[a-zA-Z0-9]{3,8}$",props:"readonly:update",comment: "用户工号"},(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 username = 5 [(aeus.field)={gorm:"size:20",rule:"required",comment: "用户名称"},(validate.rules).string = {min_len: 5, max_len: 20}];
string role = 6 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; string role = 6 [(aeus.field)={gorm:"size:60;not null;default:''",rule:"required",format:"role",live:"type:dropdown;url:/role/labels",comment: "所属角色"},(validate.rules).string = {max_len: 60}];
bool admin = 7; bool admin = 7 [(aeus.field)={scenarios:"create",comment:"管理员"}];
int64 dept_id = 8 [(aeus.field) = {gorm:"not null;default:0"}]; string status = 8 [(aeus.field)={scenarios:"create,update,list,search",gorm:"size:20;default:normal",enum:"normal:正常;disable:禁用",comment:"状态"}];
string tag = 9 [ (aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; int64 dept_id = 9 [(aeus.field) = {gorm:"not null;default:0",rule:"required",live:"type:dropdown;url:/department/labels",format:"department",comment: "所属部门"}];
string password = 10 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; string tag = 10 [ (aeus.field)={gorm:"size:60",scenarios:"list;create;update",dropdown:"created;filterable;default_first",live:"type:dropdown;url:/user/tags",comment: "用户标签"},(validate.rules).string = {max_len: 60}];
string email = 11 [(aeus.field)={gorm:"size:60"},(validate.rules).string = {max_len: 60}]; string password = 11 [(aeus.field)={gorm:"size:60",rule:"required",scenarios:"create",comment: "用户密码"},(validate.rules).string = {max_len: 60}];
string avatar = 12 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}]; string email = 12 [(aeus.field)={gorm:"size:60",scenarios:"create;update;view;list;export",comment: "用户邮箱"},(validate.rules).string = {max_len: 60}];
string gender = 13 [(aeus.field)={gorm:"size:20;default:man"},(validate.rules).string = {max_len: 20}]; string avatar = 13 [(aeus.field)={gorm:"size:1024",scenarios:"view",comment: "用户头像"},(validate.rules).string = {max_len: 1024}];
string description = 14 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}]; string gender = 14 [(aeus.field)={gorm:"size:20;default:man",rule:"required",scenarios:"list;create;update;view;export",enum:"man:男;woman:女;other:其他",comment: "用户性别"},(validate.rules).string = {max_len: 20}];
string description = 15 [(aeus.field)={gorm:"size:1024",format:"textarea",scenarios:"create;update;view;export",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
} }
// Department // Department
@ -83,14 +89,47 @@ message Department {
option (aeus.rest) = { option (aeus.rest) = {
table: "departments" table: "departments"
}; };
int64 id = 1 [(aeus.field) = {gorm:"primaryKey"}]; int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
int64 created_at = 2; int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
int64 updated_at = 3; int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
int64 parent_id = 4; int64 parent_id = 4 [(aeus.field)={format:"department",comment:"父级部门"}];
string name = 5 [(aeus.field)={gorm:"size:20"},(validate.rules).string = {max_len: 20}]; string name = 5 [(aeus.field)={gorm:"size:20",rule:"required",comment: "部门名称"},(validate.rules).string = {max_len: 20}];
string description = 6 [(aeus.field)={gorm:"size:1024"},(validate.rules).string = {max_len: 1024}]; string description = 6 [(aeus.field)={gorm:"size:1024",scenarios:"create;update;view;export;list",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
} }
message Login {
option (aeus.rest) = {
table: "logins"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
int64 created_at = 2 [(aeus.field)={scenarios:"list;search;view;export",comment:"登录时间"}];
string uid = 4 [(aeus.field)={gorm:"index;size:20",rule:"required",props:"readonly:update",format:"user",comment: "用户工号"},(validate.rules).string = {min_len: 5, max_len: 20}];
string ip = 5 [(aeus.field)={gorm:"size:128",scenarios:"list;search;view;export",comment: "登录地址"}];
string browser = 6 [(aeus.field)={gorm:"size:128",scenarios:"list;view;export",comment: "浏览器"}];
string os = 7 [(aeus.field)={gorm:"size:128",scenarios:"list;view;export",comment: "操作系统"}];
string platform = 8 [(aeus.field)={gorm:"size:128",scenarios:"list;view;export",comment: "系统平台"}];
string access_token = 9 [(aeus.field)={gorm:"size:1024",scenarios:"list;view;export",comment: "访问令牌"}];
string user_agent = 10 [(aeus.field)={gorm:"size:1024",scenarios:"list;view;export",comment: "用户代理"}];
}
// Setting
message Setting {
option (aeus.rest) = {
table: "settings"
};
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
int64 created_at = 2 [(aeus.field)={scenarios:"search;view;export",comment:"创建时间"}];
int64 updated_at = 3 [(aeus.field)={scenarios:"search;view;export",comment:"更新时间"}];
string name = 4 [(aeus.field)={gorm:"size:60",rule:"required",props:"readonly:update",comment: "配置项"},(validate.rules).string = {max_len: 20}];
string value = 5 [(aeus.field)={gorm:"size:512",rule:"required",format:"textarea",comment: "配置值"},(validate.rules).string = {max_len: 512}];
string description = 6 [(aeus.field)={gorm:"size:1024",format:"textarea",scenarios:"create;update;view;export",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
}
message LabelValue {
string label = 1;
string value = 2;
}
message PermissionItem { message PermissionItem {
string value = 1; string value = 1;
@ -105,8 +144,9 @@ message MenuItem {
bool hidden = 4; bool hidden = 4;
bool public = 5; bool public = 5;
string route = 6; string route = 6;
repeated PermissionItem permissions = 7; string view = 7;
repeated MenuItem children = 8; repeated PermissionItem permissions = 8;
repeated MenuItem children = 9;
} }
// //
@ -119,15 +159,6 @@ message GetMenuResponse {
repeated MenuItem data = 1; repeated MenuItem data = 1;
} }
//
service MenuService {
rpc GetMenus(GetMenuRequest) returns (GetMenuResponse) {
option (google.api.http) = {
get: "/api/menu"
};
}
}
// //
message GetProfileRequest { message GetProfileRequest {
@ -167,25 +198,144 @@ message UpdateProfileResponse {
string uid = 1; string uid = 1;
} }
message GetPermissionRequest {
string uid = 1;
}
message GetPermissionResponse {
string uid = 1;
repeated string permissions = 2;
}
message GetUserLabelRequest {
}
message GetUserLabelResponse {
repeated LabelValue data = 1;
}
message GetUserTagRequest {
}
message GetUserTagResponse {
repeated LabelValue data = 1;
}
// //
service ProfileService { service UserService {
//
rpc GetMenus(GetMenuRequest) returns (GetMenuResponse) {
option (google.api.http) = {
get: "/user/menus"
};
}
//
rpc GetProfile(GetProfileRequest) returns (GetProfileResponse) { rpc GetProfile(GetProfileRequest) returns (GetProfileResponse) {
option (google.api.http) = { option (google.api.http) = {
get: "/user/profile" get: "/user/profile"
}; };
} }
//
rpc UpdateProfile(UpdateProfileRequest) returns (UpdateProfileResponse) { rpc UpdateProfile(UpdateProfileRequest) returns (UpdateProfileResponse) {
option (google.api.http) = { option (google.api.http) = {
put: "/user/profile" put: "/user/profile"
body: "*" body: "*"
}; };
} }
//
rpc ResetPassword(ResetPasswordRequest) returns (ResetPasswordResponse) { rpc ResetPassword(ResetPasswordRequest) returns (ResetPasswordResponse) {
option (google.api.http) = { option (google.api.http) = {
post: "/user/reset-password" post: "/user/reset-password"
body: "*" body: "*"
}; };
} }
//
rpc GetPermissions(GetPermissionRequest) returns (GetPermissionResponse) {
option (google.api.http) = {
get: "/user/permissions"
};
}
//
rpc GetUserLabels(GetUserLabelRequest) returns (GetUserLabelResponse) {
option (google.api.http) = {
get: "/user/labels"
};
}
//
rpc GetUserTags(GetUserTagRequest) returns (GetUserTagResponse) {
option (google.api.http) = {
get: "/user/tags"
};
}
}
message DepartmentLabelValue {
string label = 1;
int64 value = 2;
}
message GetDepartmentLabelRequest {
}
message GetDepartmentLabelResponse {
repeated DepartmentLabelValue data = 1;
}
service DepartmentService {
//
rpc GetDepartmentLabels(GetDepartmentLabelRequest) returns (GetDepartmentLabelResponse) {
option (google.api.http) = {
get: "/department/labels"
};
}
}
message GetRoleLabelRequest {
}
message GetRoleLabelResponse {
repeated LabelValue data = 1;
}
message GetRolePermissionRequest {
string role = 1;
}
message GetRolePermissionResponse {
string role = 1;
repeated string permissions = 2;
}
message SaveRolePermissionRequest {
string role = 1;
repeated string permissions = 2;
}
message SaveRolePermissionResponse {
string role = 1;
}
service RoleService {
//
rpc GetRoleLabels(GetRoleLabelRequest) returns (GetRoleLabelResponse) {
option (google.api.http) = {
get: "/role/labels"
};
}
//
rpc GetRolePermissions(GetRolePermissionRequest) returns (GetRolePermissionResponse) {
option (google.api.http) = {
get: "/role/permissions"
};
}
rpc SaveRolePermission(SaveRolePermissionRequest) returns (SaveRolePermissionResponse) {
option (google.api.http) = {
post: "/role/permissions"
body: "*"
};
}
} }
@ -224,4 +374,23 @@ service AuthService {
body: "*" body: "*"
}; };
} }
}
message SettingItem {
string name = 1;
string value = 2;
}
message GetSettingRequest{}
message GetSettingResponse{
repeated SettingItem data = 1;
}
service SettingService {
rpc GetSetting(GetSettingRequest) returns (GetSettingResponse) {
option (google.api.http) = {
get: "/system/setting"
};
}
} }

View File

@ -19,105 +19,347 @@ import (
const _ = grpc.SupportPackageIsVersion9 const _ = grpc.SupportPackageIsVersion9
const ( const (
MenuService_GetMenus_FullMethodName = "/organize.MenuService/GetMenus" UserService_GetMenus_FullMethodName = "/organize.UserService/GetMenus"
UserService_GetProfile_FullMethodName = "/organize.UserService/GetProfile"
UserService_UpdateProfile_FullMethodName = "/organize.UserService/UpdateProfile"
UserService_ResetPassword_FullMethodName = "/organize.UserService/ResetPassword"
UserService_GetPermissions_FullMethodName = "/organize.UserService/GetPermissions"
UserService_GetUserLabels_FullMethodName = "/organize.UserService/GetUserLabels"
UserService_GetUserTags_FullMethodName = "/organize.UserService/GetUserTags"
) )
// MenuServiceClient is the client API for MenuService service. // UserServiceClient is the client API for UserService 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. // 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 { type UserServiceClient interface {
// 获取用户菜单
GetMenus(ctx context.Context, in *GetMenuRequest, opts ...grpc.CallOption) (*GetMenuResponse, error) GetMenus(ctx context.Context, in *GetMenuRequest, opts ...grpc.CallOption) (*GetMenuResponse, error)
// 获取用户信息
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)
// 获取用户权限
GetPermissions(ctx context.Context, in *GetPermissionRequest, opts ...grpc.CallOption) (*GetPermissionResponse, error)
// 获取用户标签
GetUserLabels(ctx context.Context, in *GetUserLabelRequest, opts ...grpc.CallOption) (*GetUserLabelResponse, error)
// 获取用户标签
GetUserTags(ctx context.Context, in *GetUserTagRequest, opts ...grpc.CallOption) (*GetUserTagResponse, error)
} }
type menuServiceClient struct { type userServiceClient struct {
cc grpc.ClientConnInterface cc grpc.ClientConnInterface
} }
func NewMenuServiceClient(cc grpc.ClientConnInterface) MenuServiceClient { func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient {
return &menuServiceClient{cc} return &userServiceClient{cc}
} }
func (c *menuServiceClient) GetMenus(ctx context.Context, in *GetMenuRequest, opts ...grpc.CallOption) (*GetMenuResponse, error) { func (c *userServiceClient) GetMenus(ctx context.Context, in *GetMenuRequest, opts ...grpc.CallOption) (*GetMenuResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetMenuResponse) out := new(GetMenuResponse)
err := c.cc.Invoke(ctx, MenuService_GetMenus_FullMethodName, in, out, cOpts...) err := c.cc.Invoke(ctx, UserService_GetMenus_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return out, nil return out, nil
} }
// MenuServiceServer is the server API for MenuService service. func (c *userServiceClient) GetProfile(ctx context.Context, in *GetProfileRequest, opts ...grpc.CallOption) (*GetProfileResponse, error) {
// All implementations must embed UnimplementedMenuServiceServer cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
// for forward compatibility. out := new(GetProfileResponse)
// err := c.cc.Invoke(ctx, UserService_GetProfile_FullMethodName, in, out, cOpts...)
// 菜单服务 if err != nil {
type MenuServiceServer interface { return nil, err
GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error) }
mustEmbedUnimplementedMenuServiceServer() return out, nil
} }
// UnimplementedMenuServiceServer must be embedded to have func (c *userServiceClient) 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, UserService_UpdateProfile_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) 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, UserService_ResetPassword_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) GetPermissions(ctx context.Context, in *GetPermissionRequest, opts ...grpc.CallOption) (*GetPermissionResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetPermissionResponse)
err := c.cc.Invoke(ctx, UserService_GetPermissions_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) GetUserLabels(ctx context.Context, in *GetUserLabelRequest, opts ...grpc.CallOption) (*GetUserLabelResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetUserLabelResponse)
err := c.cc.Invoke(ctx, UserService_GetUserLabels_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *userServiceClient) GetUserTags(ctx context.Context, in *GetUserTagRequest, opts ...grpc.CallOption) (*GetUserTagResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetUserTagResponse)
err := c.cc.Invoke(ctx, UserService_GetUserTags_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// UserServiceServer is the server API for UserService service.
// All implementations must embed UnimplementedUserServiceServer
// for forward compatibility.
//
// 用户服务
type UserServiceServer interface {
// 获取用户菜单
GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error)
// 获取用户信息
GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error)
// 更新用户信息
UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error)
// 重置用户密码
ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error)
// 获取用户权限
GetPermissions(context.Context, *GetPermissionRequest) (*GetPermissionResponse, error)
// 获取用户标签
GetUserLabels(context.Context, *GetUserLabelRequest) (*GetUserLabelResponse, error)
// 获取用户标签
GetUserTags(context.Context, *GetUserTagRequest) (*GetUserTagResponse, error)
mustEmbedUnimplementedUserServiceServer()
}
// UnimplementedUserServiceServer must be embedded to have
// forward compatible implementations. // forward compatible implementations.
// //
// NOTE: this should be embedded by value instead of pointer to avoid a nil // NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called. // pointer dereference when methods are called.
type UnimplementedMenuServiceServer struct{} type UnimplementedUserServiceServer struct{}
func (UnimplementedMenuServiceServer) GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error) { func (UnimplementedUserServiceServer) GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMenus not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetMenus not implemented")
} }
func (UnimplementedMenuServiceServer) mustEmbedUnimplementedMenuServiceServer() {} func (UnimplementedUserServiceServer) GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error) {
func (UnimplementedMenuServiceServer) testEmbeddedByValue() {} return nil, status.Errorf(codes.Unimplemented, "method GetProfile not implemented")
}
func (UnimplementedUserServiceServer) UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateProfile not implemented")
}
func (UnimplementedUserServiceServer) ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ResetPassword not implemented")
}
func (UnimplementedUserServiceServer) GetPermissions(context.Context, *GetPermissionRequest) (*GetPermissionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPermissions not implemented")
}
func (UnimplementedUserServiceServer) GetUserLabels(context.Context, *GetUserLabelRequest) (*GetUserLabelResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUserLabels not implemented")
}
func (UnimplementedUserServiceServer) GetUserTags(context.Context, *GetUserTagRequest) (*GetUserTagResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUserTags not implemented")
}
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
// UnsafeMenuServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeUserServiceServer 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 // Use of this interface is not recommended, as added methods to UserServiceServer will
// result in compilation errors. // result in compilation errors.
type UnsafeMenuServiceServer interface { type UnsafeUserServiceServer interface {
mustEmbedUnimplementedMenuServiceServer() mustEmbedUnimplementedUserServiceServer()
} }
func RegisterMenuServiceServer(s grpc.ServiceRegistrar, srv MenuServiceServer) { func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) {
// If the following call pancis, it indicates UnimplementedMenuServiceServer was // If the following call pancis, it indicates UnimplementedUserServiceServer was
// embedded by pointer and is nil. This will cause panics if an // embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization // unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O. // time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue() t.testEmbeddedByValue()
} }
s.RegisterService(&MenuService_ServiceDesc, srv) s.RegisterService(&UserService_ServiceDesc, srv)
} }
func _MenuService_GetMenus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _UserService_GetMenus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetMenuRequest) in := new(GetMenuRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
if interceptor == nil { if interceptor == nil {
return srv.(MenuServiceServer).GetMenus(ctx, in) return srv.(UserServiceServer).GetMenus(ctx, in)
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: MenuService_GetMenus_FullMethodName, FullMethod: UserService_GetMenus_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MenuServiceServer).GetMenus(ctx, req.(*GetMenuRequest)) return srv.(UserServiceServer).GetMenus(ctx, req.(*GetMenuRequest))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
// MenuService_ServiceDesc is the grpc.ServiceDesc for MenuService service. func _UserService_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.(UserServiceServer).GetProfile(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_GetProfile_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).GetProfile(ctx, req.(*GetProfileRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_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.(UserServiceServer).UpdateProfile(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_UpdateProfile_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).UpdateProfile(ctx, req.(*UpdateProfileRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_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.(UserServiceServer).ResetPassword(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_ResetPassword_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).ResetPassword(ctx, req.(*ResetPasswordRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_GetPermissions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPermissionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).GetPermissions(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_GetPermissions_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).GetPermissions(ctx, req.(*GetPermissionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_GetUserLabels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUserLabelRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).GetUserLabels(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_GetUserLabels_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).GetUserLabels(ctx, req.(*GetUserLabelRequest))
}
return interceptor(ctx, in, info, handler)
}
func _UserService_GetUserTags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUserTagRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UserServiceServer).GetUserTags(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UserService_GetUserTags_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UserServiceServer).GetUserTags(ctx, req.(*GetUserTagRequest))
}
return interceptor(ctx, in, info, handler)
}
// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
var MenuService_ServiceDesc = grpc.ServiceDesc{ var UserService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.MenuService", ServiceName: "organize.UserService",
HandlerType: (*MenuServiceServer)(nil), HandlerType: (*UserServiceServer)(nil),
Methods: []grpc.MethodDesc{ Methods: []grpc.MethodDesc{
{ {
MethodName: "GetMenus", MethodName: "GetMenus",
Handler: _MenuService_GetMenus_Handler, Handler: _UserService_GetMenus_Handler,
},
{
MethodName: "GetProfile",
Handler: _UserService_GetProfile_Handler,
},
{
MethodName: "UpdateProfile",
Handler: _UserService_UpdateProfile_Handler,
},
{
MethodName: "ResetPassword",
Handler: _UserService_ResetPassword_Handler,
},
{
MethodName: "GetPermissions",
Handler: _UserService_GetPermissions_Handler,
},
{
MethodName: "GetUserLabels",
Handler: _UserService_GetUserLabels_Handler,
},
{
MethodName: "GetUserTags",
Handler: _UserService_GetUserTags_Handler,
}, },
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
@ -125,181 +367,285 @@ var MenuService_ServiceDesc = grpc.ServiceDesc{
} }
const ( const (
ProfileService_GetProfile_FullMethodName = "/organize.ProfileService/GetProfile" DepartmentService_GetDepartmentLabels_FullMethodName = "/organize.DepartmentService/GetDepartmentLabels"
ProfileService_UpdateProfile_FullMethodName = "/organize.ProfileService/UpdateProfile"
ProfileService_ResetPassword_FullMethodName = "/organize.ProfileService/ResetPassword"
) )
// ProfileServiceClient is the client API for ProfileService service. // DepartmentServiceClient is the client API for DepartmentService 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. // 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 DepartmentServiceClient interface {
// 用户服务 // 获取部门标签
type ProfileServiceClient interface { GetDepartmentLabels(ctx context.Context, in *GetDepartmentLabelRequest, opts ...grpc.CallOption) (*GetDepartmentLabelResponse, error)
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 { type departmentServiceClient struct {
cc grpc.ClientConnInterface cc grpc.ClientConnInterface
} }
func NewProfileServiceClient(cc grpc.ClientConnInterface) ProfileServiceClient { func NewDepartmentServiceClient(cc grpc.ClientConnInterface) DepartmentServiceClient {
return &profileServiceClient{cc} return &departmentServiceClient{cc}
} }
func (c *profileServiceClient) GetProfile(ctx context.Context, in *GetProfileRequest, opts ...grpc.CallOption) (*GetProfileResponse, error) { func (c *departmentServiceClient) GetDepartmentLabels(ctx context.Context, in *GetDepartmentLabelRequest, opts ...grpc.CallOption) (*GetDepartmentLabelResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetProfileResponse) out := new(GetDepartmentLabelResponse)
err := c.cc.Invoke(ctx, ProfileService_GetProfile_FullMethodName, in, out, cOpts...) err := c.cc.Invoke(ctx, DepartmentService_GetDepartmentLabels_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return out, nil return out, nil
} }
func (c *profileServiceClient) UpdateProfile(ctx context.Context, in *UpdateProfileRequest, opts ...grpc.CallOption) (*UpdateProfileResponse, error) { // DepartmentServiceServer is the server API for DepartmentService service.
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) // All implementations must embed UnimplementedDepartmentServiceServer
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. // for forward compatibility.
// type DepartmentServiceServer interface {
// 用户服务 // 获取部门标签
type ProfileServiceServer interface { GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error)
GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error) mustEmbedUnimplementedDepartmentServiceServer()
UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error)
ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error)
mustEmbedUnimplementedProfileServiceServer()
} }
// UnimplementedProfileServiceServer must be embedded to have // UnimplementedDepartmentServiceServer must be embedded to have
// forward compatible implementations. // forward compatible implementations.
// //
// NOTE: this should be embedded by value instead of pointer to avoid a nil // NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called. // pointer dereference when methods are called.
type UnimplementedProfileServiceServer struct{} type UnimplementedDepartmentServiceServer struct{}
func (UnimplementedProfileServiceServer) GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error) { func (UnimplementedDepartmentServiceServer) GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetProfile not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentLabels not implemented")
} }
func (UnimplementedProfileServiceServer) UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error) { func (UnimplementedDepartmentServiceServer) mustEmbedUnimplementedDepartmentServiceServer() {}
return nil, status.Errorf(codes.Unimplemented, "method UpdateProfile not implemented") func (UnimplementedDepartmentServiceServer) testEmbeddedByValue() {}
}
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. // UnsafeDepartmentServiceServer 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 // Use of this interface is not recommended, as added methods to DepartmentServiceServer will
// result in compilation errors. // result in compilation errors.
type UnsafeProfileServiceServer interface { type UnsafeDepartmentServiceServer interface {
mustEmbedUnimplementedProfileServiceServer() mustEmbedUnimplementedDepartmentServiceServer()
} }
func RegisterProfileServiceServer(s grpc.ServiceRegistrar, srv ProfileServiceServer) { func RegisterDepartmentServiceServer(s grpc.ServiceRegistrar, srv DepartmentServiceServer) {
// If the following call pancis, it indicates UnimplementedProfileServiceServer was // If the following call pancis, it indicates UnimplementedDepartmentServiceServer was
// embedded by pointer and is nil. This will cause panics if an // embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization // unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O. // time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue() t.testEmbeddedByValue()
} }
s.RegisterService(&ProfileService_ServiceDesc, srv) s.RegisterService(&DepartmentService_ServiceDesc, srv)
} }
func _ProfileService_GetProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _DepartmentService_GetDepartmentLabels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetProfileRequest) in := new(GetDepartmentLabelRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
return nil, err return nil, err
} }
if interceptor == nil { if interceptor == nil {
return srv.(ProfileServiceServer).GetProfile(ctx, in) return srv.(DepartmentServiceServer).GetDepartmentLabels(ctx, in)
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: ProfileService_GetProfile_FullMethodName, FullMethod: DepartmentService_GetDepartmentLabels_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProfileServiceServer).GetProfile(ctx, req.(*GetProfileRequest)) return srv.(DepartmentServiceServer).GetDepartmentLabels(ctx, req.(*GetDepartmentLabelRequest))
} }
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _ProfileService_UpdateProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { // DepartmentService_ServiceDesc is the grpc.ServiceDesc for DepartmentService service.
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, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
var ProfileService_ServiceDesc = grpc.ServiceDesc{ var DepartmentService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.ProfileService", ServiceName: "organize.DepartmentService",
HandlerType: (*ProfileServiceServer)(nil), HandlerType: (*DepartmentServiceServer)(nil),
Methods: []grpc.MethodDesc{ Methods: []grpc.MethodDesc{
{ {
MethodName: "GetProfile", MethodName: "GetDepartmentLabels",
Handler: _ProfileService_GetProfile_Handler, Handler: _DepartmentService_GetDepartmentLabels_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "organize.proto",
}
const (
RoleService_GetRoleLabels_FullMethodName = "/organize.RoleService/GetRoleLabels"
RoleService_GetRolePermissions_FullMethodName = "/organize.RoleService/GetRolePermissions"
RoleService_SaveRolePermission_FullMethodName = "/organize.RoleService/SaveRolePermission"
)
// RoleServiceClient is the client API for RoleService 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 RoleServiceClient interface {
// 获取角色标签
GetRoleLabels(ctx context.Context, in *GetRoleLabelRequest, opts ...grpc.CallOption) (*GetRoleLabelResponse, error)
// 获取角色权限
GetRolePermissions(ctx context.Context, in *GetRolePermissionRequest, opts ...grpc.CallOption) (*GetRolePermissionResponse, error)
SaveRolePermission(ctx context.Context, in *SaveRolePermissionRequest, opts ...grpc.CallOption) (*SaveRolePermissionResponse, error)
}
type roleServiceClient struct {
cc grpc.ClientConnInterface
}
func NewRoleServiceClient(cc grpc.ClientConnInterface) RoleServiceClient {
return &roleServiceClient{cc}
}
func (c *roleServiceClient) GetRoleLabels(ctx context.Context, in *GetRoleLabelRequest, opts ...grpc.CallOption) (*GetRoleLabelResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetRoleLabelResponse)
err := c.cc.Invoke(ctx, RoleService_GetRoleLabels_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *roleServiceClient) GetRolePermissions(ctx context.Context, in *GetRolePermissionRequest, opts ...grpc.CallOption) (*GetRolePermissionResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetRolePermissionResponse)
err := c.cc.Invoke(ctx, RoleService_GetRolePermissions_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *roleServiceClient) SaveRolePermission(ctx context.Context, in *SaveRolePermissionRequest, opts ...grpc.CallOption) (*SaveRolePermissionResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SaveRolePermissionResponse)
err := c.cc.Invoke(ctx, RoleService_SaveRolePermission_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// RoleServiceServer is the server API for RoleService service.
// All implementations must embed UnimplementedRoleServiceServer
// for forward compatibility.
type RoleServiceServer interface {
// 获取角色标签
GetRoleLabels(context.Context, *GetRoleLabelRequest) (*GetRoleLabelResponse, error)
// 获取角色权限
GetRolePermissions(context.Context, *GetRolePermissionRequest) (*GetRolePermissionResponse, error)
SaveRolePermission(context.Context, *SaveRolePermissionRequest) (*SaveRolePermissionResponse, error)
mustEmbedUnimplementedRoleServiceServer()
}
// UnimplementedRoleServiceServer 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 UnimplementedRoleServiceServer struct{}
func (UnimplementedRoleServiceServer) GetRoleLabels(context.Context, *GetRoleLabelRequest) (*GetRoleLabelResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRoleLabels not implemented")
}
func (UnimplementedRoleServiceServer) GetRolePermissions(context.Context, *GetRolePermissionRequest) (*GetRolePermissionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRolePermissions not implemented")
}
func (UnimplementedRoleServiceServer) SaveRolePermission(context.Context, *SaveRolePermissionRequest) (*SaveRolePermissionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SaveRolePermission not implemented")
}
func (UnimplementedRoleServiceServer) mustEmbedUnimplementedRoleServiceServer() {}
func (UnimplementedRoleServiceServer) testEmbeddedByValue() {}
// UnsafeRoleServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to RoleServiceServer will
// result in compilation errors.
type UnsafeRoleServiceServer interface {
mustEmbedUnimplementedRoleServiceServer()
}
func RegisterRoleServiceServer(s grpc.ServiceRegistrar, srv RoleServiceServer) {
// If the following call pancis, it indicates UnimplementedRoleServiceServer 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(&RoleService_ServiceDesc, srv)
}
func _RoleService_GetRoleLabels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRoleLabelRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RoleServiceServer).GetRoleLabels(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RoleService_GetRoleLabels_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RoleServiceServer).GetRoleLabels(ctx, req.(*GetRoleLabelRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RoleService_GetRolePermissions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRolePermissionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RoleServiceServer).GetRolePermissions(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RoleService_GetRolePermissions_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RoleServiceServer).GetRolePermissions(ctx, req.(*GetRolePermissionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RoleService_SaveRolePermission_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SaveRolePermissionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RoleServiceServer).SaveRolePermission(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RoleService_SaveRolePermission_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RoleServiceServer).SaveRolePermission(ctx, req.(*SaveRolePermissionRequest))
}
return interceptor(ctx, in, info, handler)
}
// RoleService_ServiceDesc is the grpc.ServiceDesc for RoleService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var RoleService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.RoleService",
HandlerType: (*RoleServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetRoleLabels",
Handler: _RoleService_GetRoleLabels_Handler,
}, },
{ {
MethodName: "UpdateProfile", MethodName: "GetRolePermissions",
Handler: _ProfileService_UpdateProfile_Handler, Handler: _RoleService_GetRolePermissions_Handler,
}, },
{ {
MethodName: "ResetPassword", MethodName: "SaveRolePermission",
Handler: _ProfileService_ResetPassword_Handler, Handler: _RoleService_SaveRolePermission_Handler,
}, },
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
@ -449,3 +795,105 @@ var AuthService_ServiceDesc = grpc.ServiceDesc{
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "organize.proto", Metadata: "organize.proto",
} }
const (
SettingService_GetSetting_FullMethodName = "/organize.SettingService/GetSetting"
)
// SettingServiceClient is the client API for SettingService 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 SettingServiceClient interface {
GetSetting(ctx context.Context, in *GetSettingRequest, opts ...grpc.CallOption) (*GetSettingResponse, error)
}
type settingServiceClient struct {
cc grpc.ClientConnInterface
}
func NewSettingServiceClient(cc grpc.ClientConnInterface) SettingServiceClient {
return &settingServiceClient{cc}
}
func (c *settingServiceClient) GetSetting(ctx context.Context, in *GetSettingRequest, opts ...grpc.CallOption) (*GetSettingResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetSettingResponse)
err := c.cc.Invoke(ctx, SettingService_GetSetting_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// SettingServiceServer is the server API for SettingService service.
// All implementations must embed UnimplementedSettingServiceServer
// for forward compatibility.
type SettingServiceServer interface {
GetSetting(context.Context, *GetSettingRequest) (*GetSettingResponse, error)
mustEmbedUnimplementedSettingServiceServer()
}
// UnimplementedSettingServiceServer 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 UnimplementedSettingServiceServer struct{}
func (UnimplementedSettingServiceServer) GetSetting(context.Context, *GetSettingRequest) (*GetSettingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSetting not implemented")
}
func (UnimplementedSettingServiceServer) mustEmbedUnimplementedSettingServiceServer() {}
func (UnimplementedSettingServiceServer) testEmbeddedByValue() {}
// UnsafeSettingServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to SettingServiceServer will
// result in compilation errors.
type UnsafeSettingServiceServer interface {
mustEmbedUnimplementedSettingServiceServer()
}
func RegisterSettingServiceServer(s grpc.ServiceRegistrar, srv SettingServiceServer) {
// If the following call pancis, it indicates UnimplementedSettingServiceServer 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(&SettingService_ServiceDesc, srv)
}
func _SettingService_GetSetting_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetSettingRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SettingServiceServer).GetSetting(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SettingService_GetSetting_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SettingServiceServer).GetSetting(ctx, req.(*GetSettingRequest))
}
return interceptor(ctx, in, info, handler)
}
// SettingService_ServiceDesc is the grpc.ServiceDesc for SettingService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var SettingService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "organize.SettingService",
HandlerType: (*SettingServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetSetting",
Handler: _SettingService_GetSetting_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "organize.proto",
}

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-aeus. DO NOT EDIT. // Code generated by protoc-gen-go-aeus. DO NOT EDIT.
// source: organize.proto // source: organize.proto
// date: 2025-06-13 11:10:07 // date: 2025-06-17 15:01:15
package pb package pb
@ -10,16 +10,32 @@ import (
"git.nobla.cn/golang/aeus/pkg/errors" "git.nobla.cn/golang/aeus/pkg/errors"
) )
type MenuServiceHttpServer interface { type UserServiceHttpServer interface {
GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error) GetMenus(context.Context, *GetMenuRequest) (*GetMenuResponse, error)
}
type ProfileServiceHttpServer interface {
GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error) GetProfile(context.Context, *GetProfileRequest) (*GetProfileResponse, error)
UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error) UpdateProfile(context.Context, *UpdateProfileRequest) (*UpdateProfileResponse, error)
ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error) ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error)
GetPermissions(context.Context, *GetPermissionRequest) (*GetPermissionResponse, error)
GetUserLabels(context.Context, *GetUserLabelRequest) (*GetUserLabelResponse, error)
GetUserTags(context.Context, *GetUserTagRequest) (*GetUserTagResponse, error)
}
type DepartmentServiceHttpServer interface {
GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error)
}
type RoleServiceHttpServer interface {
GetRoleLabels(context.Context, *GetRoleLabelRequest) (*GetRoleLabelResponse, error)
GetRolePermissions(context.Context, *GetRolePermissionRequest) (*GetRolePermissionResponse, error)
SaveRolePermission(context.Context, *SaveRolePermissionRequest) (*SaveRolePermissionResponse, error)
} }
type AuthServiceHttpServer interface { type AuthServiceHttpServer interface {
@ -28,7 +44,13 @@ type AuthServiceHttpServer interface {
Logout(context.Context, *LogoutRequest) (*LogoutResponse, error) Logout(context.Context, *LogoutRequest) (*LogoutResponse, error)
} }
func handleMenuServiceGetMenus(s MenuServiceHttpServer) http.HandleFunc { type SettingServiceHttpServer interface {
GetSetting(context.Context, *GetSettingRequest) (*GetSettingResponse, error)
}
// 获取用户菜单
func handleUserServiceGetMenus(s UserServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) { return func(ctx *http.Context) (err error) {
req := &GetMenuRequest{} req := &GetMenuRequest{}
@ -48,7 +70,9 @@ func handleMenuServiceGetMenus(s MenuServiceHttpServer) http.HandleFunc {
} }
} }
func handleProfileServiceGetProfile(s ProfileServiceHttpServer) http.HandleFunc { // 获取用户信息
func handleUserServiceGetProfile(s UserServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) { return func(ctx *http.Context) (err error) {
req := &GetProfileRequest{} req := &GetProfileRequest{}
@ -68,7 +92,9 @@ func handleProfileServiceGetProfile(s ProfileServiceHttpServer) http.HandleFunc
} }
} }
func handleProfileServiceUpdateProfile(s ProfileServiceHttpServer) http.HandleFunc { // 更新用户信息
func handleUserServiceUpdateProfile(s UserServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) { return func(ctx *http.Context) (err error) {
req := &UpdateProfileRequest{} req := &UpdateProfileRequest{}
@ -88,7 +114,9 @@ func handleProfileServiceUpdateProfile(s ProfileServiceHttpServer) http.HandleFu
} }
} }
func handleProfileServiceResetPassword(s ProfileServiceHttpServer) http.HandleFunc { // 重置用户密码
func handleUserServiceResetPassword(s UserServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) { return func(ctx *http.Context) (err error) {
req := &ResetPasswordRequest{} req := &ResetPasswordRequest{}
@ -108,6 +136,142 @@ func handleProfileServiceResetPassword(s ProfileServiceHttpServer) http.HandleFu
} }
} }
// 获取用户权限
func handleUserServiceGetPermissions(s UserServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetPermissionRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.GetPermissions(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 handleUserServiceGetUserLabels(s UserServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetUserLabelRequest{}
if res, err := s.GetUserLabels(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 handleUserServiceGetUserTags(s UserServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetUserTagRequest{}
if res, err := s.GetUserTags(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 handleDepartmentServiceGetDepartmentLabels(s DepartmentServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetDepartmentLabelRequest{}
if res, err := s.GetDepartmentLabels(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 handleRoleServiceGetRoleLabels(s RoleServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetRoleLabelRequest{}
if res, err := s.GetRoleLabels(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 handleRoleServiceGetRolePermissions(s RoleServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetRolePermissionRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.GetRolePermissions(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 handleRoleServiceSaveRolePermission(s RoleServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &SaveRolePermissionRequest{}
if err := ctx.Bind(req); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
if res, err := s.SaveRolePermission(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 { func handleAuthServiceLogin(s AuthServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) { return func(ctx *http.Context) (err error) {
req := &LoginRequest{} req := &LoginRequest{}
@ -148,23 +312,64 @@ func handleAuthServiceLogout(s AuthServiceHttpServer) http.HandleFunc {
} }
} }
func RegisterMenuServiceRouter(hs *http.Server, s MenuServiceHttpServer) { func handleSettingServiceGetSetting(s SettingServiceHttpServer) http.HandleFunc {
return func(ctx *http.Context) (err error) {
req := &GetSettingRequest{}
if res, err := s.GetSetting(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 RegisterUserServiceRouter(hs *http.Server, s UserServiceHttpServer) {
// Register handle GetMenus route // Register handle GetMenus route
hs.GET("/api/menu", handleMenuServiceGetMenus(s)) hs.GET("/user/menus", handleUserServiceGetMenus(s))
// Register handle GetProfile route
hs.GET("/user/profile", handleUserServiceGetProfile(s))
// Register handle UpdateProfile route
hs.PUT("/user/profile", handleUserServiceUpdateProfile(s))
// Register handle ResetPassword route
hs.POST("/user/reset-password", handleUserServiceResetPassword(s))
// Register handle GetPermissions route
hs.GET("/user/permissions", handleUserServiceGetPermissions(s))
// Register handle GetUserLabels route
hs.GET("/user/labels", handleUserServiceGetUserLabels(s))
// Register handle GetUserTags route
hs.GET("/user/tags", handleUserServiceGetUserTags(s))
} }
func RegisterProfileServiceRouter(hs *http.Server, s ProfileServiceHttpServer) { func RegisterDepartmentServiceRouter(hs *http.Server, s DepartmentServiceHttpServer) {
// Register handle GetProfile route // Register handle GetDepartmentLabels route
hs.GET("/user/profile", handleProfileServiceGetProfile(s)) hs.GET("/department/labels", handleDepartmentServiceGetDepartmentLabels(s))
// Register handle UpdateProfile route }
hs.PUT("/user/profile", handleProfileServiceUpdateProfile(s))
// Register handle ResetPassword route func RegisterRoleServiceRouter(hs *http.Server, s RoleServiceHttpServer) {
hs.POST("/user/reset-password", handleProfileServiceResetPassword(s))
// Register handle GetRoleLabels route
hs.GET("/role/labels", handleRoleServiceGetRoleLabels(s))
// Register handle GetRolePermissions route
hs.GET("/role/permissions", handleRoleServiceGetRolePermissions(s))
// Register handle SaveRolePermission route
hs.POST("/role/permissions", handleRoleServiceSaveRolePermission(s))
} }
@ -177,3 +382,10 @@ func RegisterAuthServiceRouter(hs *http.Server, s AuthServiceHttpServer) {
hs.POST("/passport/logout", handleAuthServiceLogout(s)) hs.POST("/passport/logout", handleAuthServiceLogout(s))
} }
func RegisterSettingServiceRouter(hs *http.Server, s SettingServiceHttpServer) {
// Register handle GetSetting route
hs.GET("/system/setting", handleSettingServiceGetSetting(s))
}

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-aeus. DO NOT EDIT. // Code generated by protoc-gen-go-aeus. DO NOT EDIT.
// source: organize.proto // source: organize.proto
// date: 2025-06-13 11:10:07 // date: 2025-06-17 15:01:15
package pb package pb
@ -9,15 +9,18 @@ import (
) )
type MenuModel struct { type MenuModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"菜单ID"`
ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" gorm:"column:parent_id"` CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60"` UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:120"` Parent string `json:"parent" yaml:"parent" xml:"parent" gorm:"index;size:60" comment:"父级菜单" props:"readonly:update"`
Uri string `json:"uri" yaml:"uri" xml:"uri" gorm:"size:512"` Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60" comment:"组件名称" props:"readonly:update" rule:"unique;required"`
ViewPath string `json:"view_path" yaml:"viewPath" xml:"viewPath" gorm:"size:512"` Label string `json:"label" yaml:"label" xml:"label" gorm:"size:120" comment:"菜单标题" rule:"required"`
Icon string `json:"icon" yaml:"icon" xml:"icon" gorm:"size:60"` Uri string `json:"uri" yaml:"uri" xml:"uri" gorm:"size:512" comment:"菜单链接" scenarios:"create;update;view;export" rule:"required"`
Hidden bool `json:"hidden" yaml:"hidden" xml:"hidden" gorm:"column:hidden"` ViewPath string `json:"view_path" yaml:"viewPath" xml:"viewPath" gorm:"size:512" comment:"视图路径" scenarios:"create;update;view;export"`
Public bool `json:"public" yaml:"public" xml:"public" gorm:"column:public"` Icon string `json:"icon" yaml:"icon" xml:"icon" gorm:"size:60" comment:"菜单图标" scenarios:"create;update;view;export"`
Hidden bool `json:"hidden" yaml:"hidden" xml:"hidden" comment:"是否隐藏" scenarios:"create;update;view;export"`
Public bool `json:"public" yaml:"public" xml:"public" comment:"是否公开" scenarios:"create;update;view;export"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export;list" format:"textarea"`
} }
func (m *MenuModel) TableName() string { func (m *MenuModel) TableName() string {
@ -26,7 +29,9 @@ func (m *MenuModel) TableName() string {
func (m *MenuModel) FromValue(x *Menu) { func (m *MenuModel) FromValue(x *Menu) {
m.Id = x.Id m.Id = x.Id
m.ParentId = x.ParentId m.CreatedAt = x.CreatedAt
m.UpdatedAt = x.UpdatedAt
m.Parent = x.Parent
m.Name = x.Name m.Name = x.Name
m.Label = x.Label m.Label = x.Label
m.Uri = x.Uri m.Uri = x.Uri
@ -34,12 +39,15 @@ func (m *MenuModel) FromValue(x *Menu) {
m.Icon = x.Icon m.Icon = x.Icon
m.Hidden = x.Hidden m.Hidden = x.Hidden
m.Public = x.Public m.Public = x.Public
m.Description = x.Description
} }
func (m *MenuModel) ToValue() (x *Menu) { func (m *MenuModel) ToValue() (x *Menu) {
x = &Menu{} x = &Menu{}
x.Id = m.Id x.Id = m.Id
x.ParentId = m.ParentId x.CreatedAt = m.CreatedAt
x.UpdatedAt = m.UpdatedAt
x.Parent = m.Parent
x.Name = m.Name x.Name = m.Name
x.Label = m.Label x.Label = m.Label
x.Uri = m.Uri x.Uri = m.Uri
@ -47,6 +55,7 @@ func (m *MenuModel) ToValue() (x *Menu) {
x.Icon = m.Icon x.Icon = m.Icon
x.Hidden = m.Hidden x.Hidden = m.Hidden
x.Public = m.Public x.Public = m.Public
x.Description = m.Description
return x return x
} }
@ -67,7 +76,7 @@ func (m *MenuModel) Delete(db *gorm.DB) (err error) {
} }
func (m *MenuModel) Find(db *gorm.DB, pk any) (err error) { func (m *MenuModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("icon=?", pk).First(m).Error return db.Where("description=?", pk).First(m).Error
} }
func (m *MenuModel) FindOne(db *gorm.DB, query any, args ...any) (err error) { func (m *MenuModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
@ -83,10 +92,12 @@ func NewMenuModel() *MenuModel {
} }
type RoleModel struct { type RoleModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"角色ID"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60"` CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60"` UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024"` Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60" comment:"角色名称" props:"readonly:update"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60" comment:"角色标题"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"list;create;update;export" format:"textarea"`
} }
func (m *RoleModel) TableName() string { func (m *RoleModel) TableName() string {
@ -95,6 +106,8 @@ func (m *RoleModel) TableName() string {
func (m *RoleModel) FromValue(x *Role) { func (m *RoleModel) FromValue(x *Role) {
m.Id = x.Id m.Id = x.Id
m.CreatedAt = x.CreatedAt
m.UpdatedAt = x.UpdatedAt
m.Name = x.Name m.Name = x.Name
m.Label = x.Label m.Label = x.Label
m.Description = x.Description m.Description = x.Description
@ -103,6 +116,8 @@ func (m *RoleModel) FromValue(x *Role) {
func (m *RoleModel) ToValue() (x *Role) { func (m *RoleModel) ToValue() (x *Role) {
x = &Role{} x = &Role{}
x.Id = m.Id x.Id = m.Id
x.CreatedAt = m.CreatedAt
x.UpdatedAt = m.UpdatedAt
x.Name = m.Name x.Name = m.Name
x.Label = m.Label x.Label = m.Label
x.Description = m.Description x.Description = m.Description
@ -142,10 +157,10 @@ func NewRoleModel() *RoleModel {
} }
type PermissionModel struct { type PermissionModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"权限ID"`
MenuId int64 `json:"menu_id" yaml:"menuId" xml:"menuId" gorm:"index"` Menu string `json:"menu" yaml:"menu" xml:"menu" gorm:"index;size:60" comment:"所属菜单" rule:"required"`
Permission string `json:"permission" yaml:"permission" xml:"permission" gorm:"index;size:60"` Permission string `json:"permission" yaml:"permission" xml:"permission" gorm:"index;size:60" comment:"权限名称" rule:"required"`
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60"` Label string `json:"label" yaml:"label" xml:"label" gorm:"size:60" comment:"权限标题" rule:"required"`
} }
func (m *PermissionModel) TableName() string { func (m *PermissionModel) TableName() string {
@ -154,7 +169,7 @@ func (m *PermissionModel) TableName() string {
func (m *PermissionModel) FromValue(x *Permission) { func (m *PermissionModel) FromValue(x *Permission) {
m.Id = x.Id m.Id = x.Id
m.MenuId = x.MenuId m.Menu = x.Menu
m.Permission = x.Permission m.Permission = x.Permission
m.Label = x.Label m.Label = x.Label
} }
@ -162,7 +177,7 @@ func (m *PermissionModel) FromValue(x *Permission) {
func (m *PermissionModel) ToValue() (x *Permission) { func (m *PermissionModel) ToValue() (x *Permission) {
x = &Permission{} x = &Permission{}
x.Id = m.Id x.Id = m.Id
x.MenuId = m.MenuId x.Menu = m.Menu
x.Permission = m.Permission x.Permission = m.Permission
x.Label = m.Label x.Label = m.Label
return x return x
@ -201,9 +216,9 @@ func NewPermissionModel() *PermissionModel {
} }
type RolePermissionModel struct { type RolePermissionModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
Role string `json:"role" yaml:"role" xml:"role" gorm:"size:60"` Role string `json:"role" yaml:"role" xml:"role" gorm:"index;size:60" comment:"角色" rule:"required"`
PermissionId int64 `json:"permission_id" yaml:"permissionId" xml:"permissionId" gorm:"column:permission_id"` Permission string `json:"permission" yaml:"permission" xml:"permission" gorm:"size:60" comment:"权限" rule:"required"`
} }
func (m *RolePermissionModel) TableName() string { func (m *RolePermissionModel) TableName() string {
@ -213,14 +228,14 @@ func (m *RolePermissionModel) TableName() string {
func (m *RolePermissionModel) FromValue(x *RolePermission) { func (m *RolePermissionModel) FromValue(x *RolePermission) {
m.Id = x.Id m.Id = x.Id
m.Role = x.Role m.Role = x.Role
m.PermissionId = x.PermissionId m.Permission = x.Permission
} }
func (m *RolePermissionModel) ToValue() (x *RolePermission) { func (m *RolePermissionModel) ToValue() (x *RolePermission) {
x = &RolePermission{} x = &RolePermission{}
x.Id = m.Id x.Id = m.Id
x.Role = m.Role x.Role = m.Role
x.PermissionId = m.PermissionId x.Permission = m.Permission
return x return x
} }
@ -241,7 +256,7 @@ func (m *RolePermissionModel) Delete(db *gorm.DB) (err error) {
} }
func (m *RolePermissionModel) Find(db *gorm.DB, pk any) (err error) { func (m *RolePermissionModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("role=?", pk).First(m).Error return db.Where("permission=?", pk).First(m).Error
} }
func (m *RolePermissionModel) FindOne(db *gorm.DB, query any, args ...any) (err error) { func (m *RolePermissionModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
@ -257,20 +272,21 @@ func NewRolePermissionModel() *RolePermissionModel {
} }
type UserModel struct { type UserModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" gorm:"column:created_at"` CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"column:updated_at"` UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
Uid string `json:"uid" yaml:"uid" xml:"uid" gorm:"index;size:20"` Uid string `json:"uid" yaml:"uid" xml:"uid" gorm:"index;size:20" comment:"用户工号" props:"readonly:update" rule:"required;unique;regexp:^[a-zA-Z0-9]{3,8}$"`
Username string `json:"username" yaml:"username" xml:"username" gorm:"size:20"` Username string `json:"username" yaml:"username" xml:"username" gorm:"size:20" comment:"用户名称" rule:"required"`
Role string `json:"role" yaml:"role" xml:"role" gorm:"size:60"` Role string `json:"role" yaml:"role" xml:"role" gorm:"size:60;not null;default:''" comment:"所属角色" format:"role" rule:"required" live:"type:dropdown;url:/role/labels"`
Admin bool `json:"admin" yaml:"admin" xml:"admin" gorm:"column:admin"` Admin bool `json:"admin" yaml:"admin" xml:"admin" comment:"管理员" scenarios:"create"`
DeptId int64 `json:"dept_id" yaml:"deptId" xml:"deptId" gorm:"not null;default:0"` Status string `json:"status" yaml:"status" xml:"status" gorm:"size:20;default:normal" comment:"状态" scenarios:"create,update,list,search" enum:"normal:正常;disable:禁用"`
Tag string `json:"tag" yaml:"tag" xml:"tag" gorm:"size:60"` DeptId int64 `json:"dept_id" yaml:"deptId" xml:"deptId" gorm:"not null;default:0" comment:"所属部门" format:"department" rule:"required" live:"type:dropdown;url:/department/labels"`
Password string `json:"password" yaml:"password" xml:"password" gorm:"size:60"` Tag string `json:"tag" yaml:"tag" xml:"tag" gorm:"size:60" comment:"用户标签" scenarios:"list;create;update" live:"type:dropdown;url:/user/tags" dropdown:"created;filterable;default_first"`
Email string `json:"email" yaml:"email" xml:"email" gorm:"size:60"` Password string `json:"password" yaml:"password" xml:"password" gorm:"size:60" comment:"用户密码" scenarios:"create" rule:"required"`
Avatar string `json:"avatar" yaml:"avatar" xml:"avatar" gorm:"size:1024"` Email string `json:"email" yaml:"email" xml:"email" gorm:"size:60" comment:"用户邮箱" scenarios:"create;update;view;list;export"`
Gender string `json:"gender" yaml:"gender" xml:"gender" gorm:"size:20;default:man"` Avatar string `json:"avatar" yaml:"avatar" xml:"avatar" gorm:"size:1024" comment:"用户头像" scenarios:"view"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024"` Gender string `json:"gender" yaml:"gender" xml:"gender" gorm:"size:20;default:man" comment:"用户性别" scenarios:"list;create;update;view;export" rule:"required" enum:"man:男;woman:女;other:其他"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export" format:"textarea"`
} }
func (m *UserModel) TableName() string { func (m *UserModel) TableName() string {
@ -285,6 +301,7 @@ func (m *UserModel) FromValue(x *User) {
m.Username = x.Username m.Username = x.Username
m.Role = x.Role m.Role = x.Role
m.Admin = x.Admin m.Admin = x.Admin
m.Status = x.Status
m.DeptId = x.DeptId m.DeptId = x.DeptId
m.Tag = x.Tag m.Tag = x.Tag
m.Password = x.Password m.Password = x.Password
@ -303,6 +320,7 @@ func (m *UserModel) ToValue() (x *User) {
x.Username = m.Username x.Username = m.Username
x.Role = m.Role x.Role = m.Role
x.Admin = m.Admin x.Admin = m.Admin
x.Status = m.Status
x.DeptId = m.DeptId x.DeptId = m.DeptId
x.Tag = m.Tag x.Tag = m.Tag
x.Password = m.Password x.Password = m.Password
@ -346,12 +364,12 @@ func NewUserModel() *UserModel {
} }
type DepartmentModel struct { type DepartmentModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey"` Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" gorm:"column:created_at"` CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"column:updated_at"` UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" gorm:"column:parent_id"` ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" comment:"父级部门" format:"department"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"size:20"` Name string `json:"name" yaml:"name" xml:"name" gorm:"size:20" comment:"部门名称" rule:"required"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024"` Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export;list" format:"textarea"`
} }
func (m *DepartmentModel) TableName() string { func (m *DepartmentModel) TableName() string {
@ -409,3 +427,142 @@ func (m *DepartmentModel) FindAll(db *gorm.DB, query any, args ...any) (err erro
func NewDepartmentModel() *DepartmentModel { func NewDepartmentModel() *DepartmentModel {
return &DepartmentModel{} return &DepartmentModel{}
} }
type LoginModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"登录时间" scenarios:"list;search;view;export"`
Uid string `json:"uid" yaml:"uid" xml:"uid" gorm:"index;size:20" comment:"用户工号" format:"user" props:"readonly:update" rule:"required"`
Ip string `json:"ip" yaml:"ip" xml:"ip" gorm:"size:128" comment:"登录地址" scenarios:"list;search;view;export"`
Browser string `json:"browser" yaml:"browser" xml:"browser" gorm:"size:128" comment:"浏览器" scenarios:"list;view;export"`
Os string `json:"os" yaml:"os" xml:"os" gorm:"size:128" comment:"操作系统" scenarios:"list;view;export"`
Platform string `json:"platform" yaml:"platform" xml:"platform" gorm:"size:128" comment:"系统平台" scenarios:"list;view;export"`
AccessToken string `json:"access_token" yaml:"accessToken" xml:"accessToken" gorm:"size:1024" comment:"访问令牌" scenarios:"list;view;export"`
UserAgent string `json:"user_agent" yaml:"userAgent" xml:"userAgent" gorm:"size:1024" comment:"用户代理" scenarios:"list;view;export"`
}
func (m *LoginModel) TableName() string {
return "logins"
}
func (m *LoginModel) FromValue(x *Login) {
m.Id = x.Id
m.CreatedAt = x.CreatedAt
m.Uid = x.Uid
m.Ip = x.Ip
m.Browser = x.Browser
m.Os = x.Os
m.Platform = x.Platform
m.AccessToken = x.AccessToken
m.UserAgent = x.UserAgent
}
func (m *LoginModel) ToValue() (x *Login) {
x = &Login{}
x.Id = m.Id
x.CreatedAt = m.CreatedAt
x.Uid = m.Uid
x.Ip = m.Ip
x.Browser = m.Browser
x.Os = m.Os
x.Platform = m.Platform
x.AccessToken = m.AccessToken
x.UserAgent = m.UserAgent
return x
}
func (m *LoginModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *LoginModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *LoginModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *LoginModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *LoginModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("user_agent=?", pk).First(m).Error
}
func (m *LoginModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *LoginModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewLoginModel() *LoginModel {
return &LoginModel{}
}
type SettingModel struct {
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"search;view;export"`
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" comment:"更新时间" scenarios:"search;view;export"`
Name string `json:"name" yaml:"name" xml:"name" gorm:"size:60" comment:"配置项" props:"readonly:update" rule:"required"`
Value string `json:"value" yaml:"value" xml:"value" gorm:"size:512" comment:"配置值" format:"textarea" rule:"required"`
Description string `json:"description" yaml:"description" xml:"description" gorm:"size:1024" comment:"备注说明" scenarios:"create;update;view;export" format:"textarea"`
}
func (m *SettingModel) TableName() string {
return "settings"
}
func (m *SettingModel) FromValue(x *Setting) {
m.Id = x.Id
m.CreatedAt = x.CreatedAt
m.UpdatedAt = x.UpdatedAt
m.Name = x.Name
m.Value = x.Value
m.Description = x.Description
}
func (m *SettingModel) ToValue() (x *Setting) {
x = &Setting{}
x.Id = m.Id
x.CreatedAt = m.CreatedAt
x.UpdatedAt = m.UpdatedAt
x.Name = m.Name
x.Value = m.Value
x.Description = m.Description
return x
}
func (m *SettingModel) Create(db *gorm.DB) (err error) {
return db.Create(m).Error
}
func (m *SettingModel) UpdateColumn(db *gorm.DB, column string, value any) (err error) {
return db.Model(m).UpdateColumn(column, value).Error
}
func (m *SettingModel) Save(db *gorm.DB) (err error) {
return db.Save(m).Error
}
func (m *SettingModel) Delete(db *gorm.DB) (err error) {
return db.Delete(m).Error
}
func (m *SettingModel) Find(db *gorm.DB, pk any) (err error) {
return db.Where("description=?", pk).First(m).Error
}
func (m *SettingModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).First(m).Error
}
func (m *SettingModel) FindAll(db *gorm.DB, query any, args ...any) (err error) {
return db.Where(query, args...).Find(m).Error
}
func NewSettingModel() *SettingModel {
return &SettingModel{}
}

59
permission.go 100644
View File

@ -0,0 +1,59 @@
package aeusadmin
import (
"context"
"fmt"
"slices"
"time"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/aeus/middleware/auth"
"git.nobla.cn/golang/aeus/pkg/errors"
"gorm.io/gorm"
)
type PermissionChecker struct {
db *gorm.DB
}
func (p *PermissionChecker) getUserPermissions(ctx context.Context, uid string) (permissions []string, err error) {
permissions, err = dbcache.TryCache(ctx, fmt.Sprintf("user:permissions:%s", uid), func(tx *gorm.DB) ([]string, error) {
var ss []string
err = tx.Select("permission").Model(&models.RolePermission{}).
Joins("LEFT JOIN users on users.role = role_permissions.role").
Where("users.uid = ?", uid).
Pluck("permission", &ss).
Error
return ss, err
}, dbcache.WithCacheDuration(time.Minute), dbcache.WithDB(p.db))
return
}
func (p *PermissionChecker) CheckPermission(ctx context.Context, permission string) (err error) {
var (
uid string
ps []string
)
if claims, ok := auth.FromContext(ctx); !ok {
return errors.ErrAccessDenied
} else {
if uid, err = claims.GetSubject(); err != nil {
return
}
}
if ps, err = p.getUserPermissions(ctx, uid); err != nil {
return
}
if !slices.Contains(ps, permission) {
err = errors.ErrPermissionDenied
}
return
}
func NewPermissionChecker(db *gorm.DB) *PermissionChecker {
return &PermissionChecker{
db: db,
}
}

View File

@ -0,0 +1,113 @@
package dbcache
import (
"context"
"time"
"git.nobla.cn/golang/aeus/pkg/cache"
"git.nobla.cn/golang/aeus/pkg/errors"
"golang.org/x/sync/singleflight"
"gorm.io/gorm"
)
var singleInstance singleflight.Group
type (
CacheOptions struct {
db *gorm.DB
cache cache.Cache
dependency CacheDependency
cacheDuration time.Duration
}
CacheOption func(o *CacheOptions)
cacheEntry[T any] struct {
Value T
CompareValue string
CreatedAt int64
}
)
func WithDB(db *gorm.DB) CacheOption {
return func(o *CacheOptions) {
o.db = db
}
}
func WithCache(c cache.Cache) CacheOption {
return func(o *CacheOptions) {
o.cache = c
}
}
func WithCacheDuration(d time.Duration) CacheOption {
return func(o *CacheOptions) {
o.cacheDuration = d
}
}
func WithDependency(d CacheDependency) CacheOption {
return func(o *CacheOptions) {
o.dependency = d
}
}
// TryCache 尝试从缓存中获取数据
func TryCache[T any](ctx context.Context, key string, f func(tx *gorm.DB) (T, error), cbs ...CacheOption) (result T, err error) {
var (
none T
value any
val any
hasDependValue bool
dependValue string
)
opts := &CacheOptions{
cache: cache.Default(),
cacheDuration: time.Minute * 10,
}
for _, cb := range cbs {
cb(opts)
}
if opts.db == nil {
return none, errors.Format(errors.Unavailable, "db instance unavailable")
}
//从缓存加载数据
if value, err = opts.cache.Get(ctx, key); err == nil {
if entry, ok := value.(*cacheEntry[T]); ok {
if time.Now().Unix()-entry.CreatedAt <= 1 {
return entry.Value, nil
}
if opts.dependency == nil {
return entry.Value, nil
}
if dependValue, err = opts.dependency.GetValue(ctx, opts.db); err == nil {
hasDependValue = true
if entry.CompareValue == dependValue {
return entry.Value, nil
} else {
opts.cache.Delete(ctx, key)
}
}
}
}
//从数据库加载数据
tx := opts.db.WithContext(ctx)
if val, err, _ = singleInstance.Do(key, func() (any, error) {
if result, err = f(tx); err == nil {
if !hasDependValue && opts.dependency != nil {
dependValue, err = opts.dependency.GetValue(ctx, tx)
}
opts.cache.Put(ctx, key, &cacheEntry[T]{
CompareValue: dependValue,
Value: result,
CreatedAt: time.Now().Unix(),
}, opts.cacheDuration)
}
return result, err
}); err != nil {
return none, err
} else {
return val.(T), err
}
}

View File

@ -0,0 +1,29 @@
package dbcache
import (
"context"
"gorm.io/gorm"
)
type CacheDependency interface {
GetValue(ctx context.Context, tx *gorm.DB) (value string, err error)
}
type SqlDependency struct {
dependSQL string
dependArgs []any
}
func (d *SqlDependency) GetValue(ctx context.Context, tx *gorm.DB) (value string, err error) {
var dependValue string
err = tx.Raw(d.dependSQL, d.dependArgs...).Scan(&dependValue).Error
return dependValue, err
}
func NewSqlDependency(dependSQL string, dependArgs ...any) *SqlDependency {
return &SqlDependency{
dependSQL: dependSQL,
dependArgs: dependArgs,
}
}

288
server.go
View File

@ -2,56 +2,104 @@ package aeusadmin
import ( import (
"context" "context"
"fmt"
"html/template"
"os"
"path" "path"
"reflect"
"strconv"
"strings"
"git.nobla.cn/golang/aeus-admin/defaults" "git.nobla.cn/golang/aeus-admin/defaults"
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
adminTypes "git.nobla.cn/golang/aeus-admin/types"
"git.nobla.cn/golang/aeus/pkg/errors" "git.nobla.cn/golang/aeus/pkg/errors"
"git.nobla.cn/golang/aeus/pkg/pool"
"git.nobla.cn/golang/aeus/transport/http"
"git.nobla.cn/golang/rest" "git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/inflector" "git.nobla.cn/golang/rest/inflector"
"git.nobla.cn/golang/rest/types" "git.nobla.cn/golang/rest/types"
restTypes "git.nobla.cn/golang/rest/types"
"gorm.io/gorm" "gorm.io/gorm"
) )
// getModels 获取预定义的模型列表 // getModels 获取预定义的模型列表
func getModels() []any { func getModels() []any {
return []any{ return []any{
&models.User{},
&models.Role{},
&models.Menu{},
&models.Department{}, &models.Department{},
&models.Role{},
&models.User{},
&models.Menu{},
&models.Login{},
&models.Permission{}, &models.Permission{},
&models.RolePermission{}, &models.RolePermission{},
&models.Setting{},
} }
} }
// checkModelMenu 检查模型菜单 // checkModelMenu 检查模型菜单
func checkModelMenu(db *gorm.DB, viewPath string, model *rest.Model, translate Translate) (value *models.Menu, err error) { func checkModelMenu(db *gorm.DB, viewPath string, apiPrefix string, model *rest.Model, translate Translate) (value *models.Menu, err error) {
menuName := inflector.Camelize(model.Naming().ModuleName) + inflector.Camelize(model.Naming().Singular) refVal := reflect.New(model.Value().Type()).Interface()
value = &models.Menu{} if v, ok := refVal.(adminTypes.MenuModel); ok {
if err = db.Where("name = ?", menuName).First(value).Error; err != nil { row := v.GetMenu()
if errors.Is(err, gorm.ErrRecordNotFound) { value = &models.Menu{}
value.Name = menuName if row.Name == "" {
value.ParentId = 0 row.Name = inflector.Camelize(model.Naming().ModuleName) + inflector.Camelize(model.Naming().Singular)
value.ViewPath = path.Join(viewPath, model.ModuleName(), model.Naming().Singular, "Index.vue") }
value.Label = inflector.Camel2words(model.Naming().Pluralize) if err = db.Where("name = ?", row.Name).First(value).Error; err != nil {
if translate != nil { if errors.Is(err, gorm.ErrRecordNotFound) {
value.Label = translate.Menu(model, value.Label) if row.Parent != "" {
value.Parent = row.Parent
}
value.Name = row.Name
value.Hidden = row.Hidden
value.Icon = row.Icon
value.Label = row.Label
value.Uri = row.Uri
value.ViewPath = row.ViewPath
if value.Label == "" {
value.Label = inflector.Camel2words(model.Naming().Pluralize)
if translate != nil {
value.Label = translate.Menu(model, value.Label)
}
}
if value.Uri == "" {
value.Uri = strings.TrimPrefix(model.Uri(types.ScenarioList), apiPrefix)
}
if value.ViewPath == "" {
value.ViewPath = path.Join(viewPath, model.ModuleName(), model.Naming().Singular, "Index.vue")
}
err = db.Create(value).Error
}
}
} else {
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.Parent = ""
value.Label = inflector.Camel2words(model.Naming().Pluralize)
if translate != nil {
value.Label = translate.Menu(model, value.Label)
}
value.Uri = strings.TrimPrefix(model.Uri(types.ScenarioList), apiPrefix)
value.ViewPath = path.Join(viewPath, model.ModuleName(), model.Naming().Singular, "Index.vue")
err = db.Create(value).Error
} }
value.Uri = model.Uri(types.ScenarioList)
err = db.Create(value).Error
} }
} }
return return
} }
// checkModelPermission 检查模型权限是否写入到数据库 // checkModelPermission 检查模型权限是否写入到数据库
func checkModelPermission(db *gorm.DB, menuId int64, scene string, model *rest.Model, translate Translate) (permissionModel *models.Permission, err error) { func checkModelPermission(db *gorm.DB, menuName string, scene string, model *rest.Model, translate Translate) (permissionModel *models.Permission, err error) {
permissionModel = &models.Permission{} permissionModel = &models.Permission{}
permission := model.Permission(scene) permission := model.Permission(scene)
if err = db.Where("permission = ?", permission).First(permissionModel).Error; err != nil { if err = db.Where("permission = ? AND menu = ?", permission, menuName).First(permissionModel).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
permissionModel.MenuId = menuId permissionModel.Menu = menuName
permissionModel.Label = scene permissionModel.Label = scene
if translate != nil { if translate != nil {
permissionModel.Label = translate.Permission(model, scene, permissionModel.Label) permissionModel.Label = translate.Permission(model, scene, permissionModel.Label)
@ -63,19 +111,41 @@ func checkModelPermission(db *gorm.DB, menuId int64, scene string, model *rest.M
return return
} }
func replaceModelPermission(db *gorm.DB, menuName string, permission string, label string) (permissionModel *models.Permission, err error) {
permissionModel = &models.Permission{}
if err = db.Where("permission = ? AND menu = ?", permission, menuName).First(permissionModel).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
permissionModel.Menu = menuName
permissionModel.Label = label
permissionModel.Permission = permission
err = db.Create(permissionModel).Error
}
}
return
}
// checkModel 检查模型 // checkModel 检查模型
func checkModel(opts *options, model *rest.Model) (err error) { func checkModel(opts *options, model *rest.Model) (err error) {
var ( var (
menuModel *models.Menu menuModel *models.Menu
) )
tx := opts.db.Begin() tx := opts.db.Begin()
if menuModel, err = checkModelMenu(tx, opts.viewPath, model, opts.translate); err != nil { if menuModel, err = checkModelMenu(tx, opts.viewPrefix, opts.apiPrefix, model, opts.translate); err != nil {
tx.Rollback() tx.Rollback()
return return
} }
for _, s := range defaultScenarios { for _, s := range defaultScenarios {
if model.HasScenario(s) { if model.HasScenario(s) {
if _, err = checkModelPermission(tx, menuModel.Id, s, model, opts.translate); err != nil { if _, err = checkModelPermission(tx, menuModel.Name, s, model, opts.translate); err != nil {
tx.Rollback()
return
}
}
}
modelValue := reflect.New(model.Value().Type()).Interface()
if v, ok := modelValue.(adminTypes.PerrmissionModule); ok {
for k, v := range v.ModelPermissions() {
if _, err = replaceModelPermission(tx, menuModel.Name, k, v); err != nil {
tx.Rollback() tx.Rollback()
return return
} }
@ -85,6 +155,58 @@ func checkModel(opts *options, model *rest.Model) (err error) {
return return
} }
// generateVueFile 生成Vue文件
func generateVueFile(prefix string, apiPrefix string, mv *rest.Model) (err error) {
refVal := reflect.New(mv.Value().Type()).Interface()
if v, ok := refVal.(adminTypes.MenuModel); ok {
instance := v.GetMenu()
if instance != nil {
if instance.Hidden {
return
}
}
}
filename := path.Join(prefix, mv.Naming().ModuleName, mv.Naming().Singular, "Index.vue")
if _, err = os.Stat(filename); err == nil {
return
}
dirname := path.Dir(filename)
if _, err = os.Stat(dirname); err != nil {
if err = os.MkdirAll(dirname, os.ModePerm); err != nil {
return
}
}
var (
editable bool
temp *template.Template
)
if temp, err = template.New("vue").Parse(vueTemplate); err != nil {
return
}
permissions := make(map[string]string)
for _, s := range defaultScenarios {
if mv.HasScenario(s) {
if s == types.ScenarioCreate || s == types.ScenarioUpdate {
editable = true
}
permissions[s] = mv.Permission(s)
}
}
data := &vueTemplateData{
ModuleName: mv.ModuleName(),
TableName: mv.TableName(),
Permissions: permissions,
Readonly: !editable,
ApiPrefix: strings.TrimPrefix(apiPrefix, "/"),
}
writer := pool.GetBuffer()
defer pool.PutBuffer(writer)
if err = temp.Execute(writer, data); err != nil {
return
}
return os.WriteFile(filename, writer.Bytes(), 0644)
}
// initREST 初始化REST模块 // initREST 初始化REST模块
func initREST(ctx context.Context, o *options) (err error) { func initREST(ctx context.Context, o *options) (err error) {
tx := o.db tx := o.db
@ -94,6 +216,9 @@ func initREST(ctx context.Context, o *options) (err error) {
opts := make([]rest.Option, 0) opts := make([]rest.Option, 0)
opts = append(opts, o.restOpts...) opts = append(opts, o.restOpts...)
opts = append(opts, rest.WithDB(tx)) opts = append(opts, rest.WithDB(tx))
if o.apiPrefix != "" {
opts = append(opts, rest.WithUriPrefix(o.apiPrefix))
}
if err = rest.Init(opts...); err != nil { if err = rest.Init(opts...); err != nil {
return return
} }
@ -104,15 +229,24 @@ func initREST(ctx context.Context, o *options) (err error) {
} }
// initRBAC 初始化权限控制, 用于生成角色权限相关的信息 // initRBAC 初始化权限控制, 用于生成角色权限相关的信息
func initRBAC(ctx context.Context, o *options) (err error) { func initModels(ctx context.Context, o *options) (err error) {
var mv *rest.Model var mv *rest.Model
for _, v := range getModels() { for _, v := range getModels() {
if mv, err = rest.AutoMigrate(ctx, v); err != nil { moduleName := o.moduleName
if mm, ok := v.(adminTypes.ModuleModel); ok {
moduleName = mm.ModuleName()
}
if mv, err = rest.AutoMigrate(ctx, v, rest.WithModuleName(moduleName)); err != nil {
return return
} else { } else {
if err = checkModel(o, mv); err != nil { if err = checkModel(o, mv); err != nil {
return return
} }
if o.vuePath != "" {
if err = generateVueFile(o.vuePath, o.apiPrefix, mv); err != nil {
return
}
}
} }
} }
return return
@ -124,22 +258,124 @@ func AutoMigrate(ctx context.Context, db *gorm.DB, model any, cbs ...Option) (er
mv *rest.Model mv *rest.Model
) )
opts := newOptions(cbs...) opts := newOptions(cbs...)
if mv, err = rest.AutoMigrate(ctx, model); err != nil { if mm, ok := model.(adminTypes.ModuleModel); ok {
moduleName := mm.ModuleName()
opts.restOpts = append(opts.restOpts, rest.WithModuleName(moduleName))
}
if mv, err = rest.AutoMigrate(ctx, model, opts.restOpts...); err != nil {
return return
} }
err = checkModel(opts, mv) err = checkModel(opts, mv)
return return
} }
func registerRESTRoute(domain string, db *gorm.DB, hs *http.Server) {
handleListSchemas := func(ctx *http.Context) (err error) {
var (
schemas []*restTypes.Schema
)
scenario := ctx.Request().URL.Query().Get("scenario")
if scenario == "" {
schemas, err = dbcache.TryCache(
ctx.Request().Context(),
fmt.Sprintf("rest:schems:%s:%s", ctx.Param("module"), ctx.Param("table")),
func(tx *gorm.DB) ([]*restTypes.Schema, error) {
return rest.GetSchemas(
ctx.Request().Context(),
tx,
"",
ctx.Param("module"),
ctx.Param("table"),
)
},
dbcache.WithDB(db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM `schemas`")),
)
} else {
schemas, err = dbcache.TryCache(
ctx.Request().Context(),
fmt.Sprintf("rest:schems:%s:%s", ctx.Param("module"), ctx.Param("table")),
func(tx *gorm.DB) ([]*restTypes.Schema, error) {
return rest.VisibleSchemas(
ctx.Request().Context(),
db.WithContext(ctx.Request().Context()),
"",
ctx.Param("module"),
ctx.Param("table"),
scenario,
)
},
dbcache.WithDB(db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM `schemas`")),
)
}
if err != nil {
return ctx.Error(errors.NotFound, err.Error())
} else {
return ctx.Success(schemas)
}
}
handleUpdateSchemas := func(ctx *http.Context) (err error) {
schemas := make([]*restTypes.Schema, 0)
if err = ctx.Bind(&schemas); err != nil {
return ctx.Error(errors.Invalid, err.Error())
}
for i := range schemas {
schemas[i].Domain = domain
}
if err = db.WithContext(ctx.Request().Context()).Transaction(func(tx *gorm.DB) (errTx error) {
for _, row := range schemas {
if errTx = tx.Save(row).Error; errTx != nil {
return
}
}
return
}); err == nil {
return ctx.Success(map[string]interface{}{
"count": len(schemas),
"state": "success",
})
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
}
handleDeleteSchema := func(ctx *http.Context) (err error) {
id, _ := strconv.Atoi(ctx.Param("id"))
model := &restTypes.Schema{Id: uint64(id)}
if err = db.WithContext(ctx.Request().Context()).Delete(model).Error; err == nil {
return ctx.Success(map[string]any{
"id": id,
})
} else {
return ctx.Error(errors.Unavailable, err.Error())
}
}
hs.GET("/rest/schema/:module/:table", handleListSchemas)
hs.PUT("/rest/schema/:module/:table", handleUpdateSchemas)
hs.DELETE("/rest/schema/:id", handleDeleteSchema)
}
// Init 初始化模块 // Init 初始化模块
func Init(ctx context.Context, cbs ...Option) (err error) { func Init(ctx context.Context, cbs ...Option) (err error) {
opts := newOptions(cbs...) opts := newOptions(cbs...)
if err = initREST(ctx, opts); err != nil { if err = initREST(ctx, opts); err != nil {
return return
} }
if err = initRBAC(ctx, opts); err != nil { if err = initModels(ctx, opts); err != nil {
return return
} }
err = defaults.Init(opts.db) if opts.httpServer != nil {
registerRESTRoute(opts.domain, opts.db, opts.httpServer)
}
if !opts.disableDefault {
if err = defaults.Generate(opts.db); err != nil {
return
}
}
return return
} }

View File

@ -7,8 +7,10 @@ import (
"git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb" "git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/types" "git.nobla.cn/golang/aeus-admin/types"
"git.nobla.cn/golang/aeus/metadata"
"git.nobla.cn/golang/aeus/pkg/errors" "git.nobla.cn/golang/aeus/pkg/errors"
jwt "github.com/golang-jwt/jwt/v5" jwt "github.com/golang-jwt/jwt/v5"
"github.com/mssola/useragent"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -58,11 +60,13 @@ func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (res *pb.
return nil, errors.Format(errors.Invalid, err.Error()) return nil, errors.Format(errors.Invalid, err.Error())
} }
if err = model.FindOne(tx, "uid=?", req.Username); err != nil { if err = model.FindOne(tx, "uid=?", req.Username); err != nil {
return return nil, errors.ErrAccessDenied
}
if model.Status != types.UserStatusNormal {
return nil, errors.ErrAccessDenied
} }
if model.Password != req.Password { if model.Password != req.Password {
err = errors.ErrAccessDenied return nil, errors.ErrAccessDenied
return
} }
claims := types.Claims{ claims := types.Claims{
Uid: model.Uid, Uid: model.Uid,
@ -71,12 +75,26 @@ func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (res *pb.
ExpirationAt: time.Now().Add(time.Second * time.Duration(s.opts.ttl)).Unix(), ExpirationAt: time.Now().Add(time.Second * time.Duration(s.opts.ttl)).Unix(),
} }
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
res = &pb.LoginResponse{} res = &pb.LoginResponse{}
if res.Token, err = token.SignedString(s.opts.secret); err == nil { if res.Token, err = token.SignedString(s.opts.secret); err == nil {
res.Uid = model.Uid res.Uid = model.Uid
res.Username = model.Username res.Username = model.Username
res.Expires = s.opts.ttl res.Expires = s.opts.ttl
} }
loginModel := &models.Login{}
loginModel.Uid = model.Uid
loginModel.AccessToken = res.Token
md := metadata.FromContext(ctx)
if userAgent, ok := md.Get("User-Agent"); ok {
ua := useragent.New(userAgent)
loginModel.Os = ua.OS()
loginModel.Platform = ua.Platform()
loginModel.UserAgent = userAgent
browser, browserVersion := ua.Browser()
loginModel.Browser = browser + "/" + browserVersion
tx.Save(loginModel)
}
return return
} }

View File

@ -0,0 +1,61 @@
package service
import (
"context"
"fmt"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"gorm.io/gorm"
)
type (
departmentOptions struct {
db *gorm.DB
}
DepartmentOption func(o *departmentOptions)
DepartmentService struct {
opts *departmentOptions
}
)
func WithDepartmentDB(db *gorm.DB) DepartmentOption {
return func(o *departmentOptions) {
o.db = db
}
}
func (s *DepartmentService) GetDepartmentLabels(ctx context.Context, req *pb.GetDepartmentLabelRequest) (res *pb.GetDepartmentLabelResponse, err error) {
res = &pb.GetDepartmentLabelResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("department:labels"), func(tx *gorm.DB) ([]*pb.DepartmentLabelValue, error) {
values := make([]*models.Department, 0)
if err = tx.Find(&values).Error; err == nil {
items := make([]*pb.DepartmentLabelValue, 0, len(values))
for _, v := range values {
items = append(items, &pb.DepartmentLabelValue{
Label: v.Name,
Value: v.Id,
})
}
return items, nil
} else {
return nil, err
}
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM departments")),
)
return
}
func NewDepartmentService(cbs ...DepartmentOption) *DepartmentService {
opts := &departmentOptions{}
for _, cb := range cbs {
cb(opts)
}
return &DepartmentService{
opts: opts,
}
}

View File

@ -1,113 +0,0 @@
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,
}
}

View File

@ -1,113 +0,0 @@
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,
}
}

94
service/role.go 100644
View File

@ -0,0 +1,94 @@
package service
import (
"context"
"fmt"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"gorm.io/gorm"
)
type (
roleOptions struct {
db *gorm.DB
}
RoleOption func(o *roleOptions)
RoleService struct {
opts *roleOptions
}
)
func WithRoleDB(db *gorm.DB) RoleOption {
return func(o *roleOptions) {
o.db = db
}
}
func (s *RoleService) GetRoleLabels(ctx context.Context, req *pb.GetRoleLabelRequest) (res *pb.GetRoleLabelResponse, err error) {
res = &pb.GetRoleLabelResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("role:labels"), func(tx *gorm.DB) ([]*pb.LabelValue, error) {
values := make([]*models.Role, 0)
if err = tx.Find(&values).Error; err == nil {
items := make([]*pb.LabelValue, 0, len(values))
for _, v := range values {
items = append(items, &pb.LabelValue{
Label: v.Label,
Value: v.Name,
})
}
return items, nil
} else {
return nil, err
}
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM roles")),
)
return
}
func (s *RoleService) GetRolePermissions(ctx context.Context, req *pb.GetRolePermissionRequest) (res *pb.GetRolePermissionResponse, err error) {
var permissions []string
if err = s.opts.db.WithContext(ctx).Model(&models.RolePermission{}).Where("role=?", req.Role).Pluck("permission", &permissions).Error; err != nil {
return
}
res = &pb.GetRolePermissionResponse{
Role: req.Role,
Permissions: permissions,
}
return
}
func (s *RoleService) SaveRolePermission(ctx context.Context, req *pb.SaveRolePermissionRequest) (res *pb.SaveRolePermissionResponse, err error) {
tx := s.opts.db.WithContext(ctx).Begin()
tx.Where("role = ?", req.Role).Delete(&models.RolePermission{})
values := make([]*models.RolePermission, 0)
for _, permission := range req.Permissions {
item := &models.RolePermission{}
item.Role = req.Role
item.Permission = permission
values = append(values, item)
}
if err = tx.Save(values).Error; err == nil {
tx.Commit()
} else {
tx.Rollback()
}
res = &pb.SaveRolePermissionResponse{
Role: req.Role,
}
return
}
func NewRoleService(cbs ...RoleOption) *RoleService {
opts := &roleOptions{}
for _, cb := range cbs {
cb(opts)
}
return &RoleService{
opts: opts,
}
}

51
service/setting.go 100644
View File

@ -0,0 +1,51 @@
package service
import (
"context"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"gorm.io/gorm"
)
type (
settingOptions struct {
db *gorm.DB
}
SettingOption func(o *settingOptions)
)
type SettingService struct {
opts *settingOptions
}
func WithSettingDB(db *gorm.DB) SettingOption {
return func(o *settingOptions) {
o.db = db
}
}
func (s *SettingService) GetSetting(ctx context.Context, req *pb.GetSettingRequest) (res *pb.GetSettingResponse, err error) {
tx := s.opts.db.WithContext(ctx)
values := make([]*models.Setting, 0)
if err = tx.Find(&values).Error; err != nil {
return
}
res = &pb.GetSettingResponse{
Data: make([]*pb.SettingItem, 0, len(values)),
}
for _, v := range values {
res.Data = append(res.Data, &pb.SettingItem{
Name: v.Name,
Value: v.Value,
})
}
return
}
func NewSettingService(cbs ...SettingOption) *SettingService {
opts := &settingOptions{}
for _, cb := range cbs {
cb(opts)
}
return &SettingService{}
}

285
service/user.go 100644
View File

@ -0,0 +1,285 @@
package service
import (
"context"
"fmt"
"time"
"git.nobla.cn/golang/aeus-admin/models"
"git.nobla.cn/golang/aeus-admin/pb"
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
"git.nobla.cn/golang/aeus/middleware/auth"
"git.nobla.cn/golang/aeus/pkg/errors"
"gorm.io/gorm"
)
type (
userOptions struct {
db *gorm.DB
}
UserOption func(o *userOptions)
UserService struct {
opts *userOptions
}
)
func WithUserDB(db *gorm.DB) UserOption {
return func(o *userOptions) {
o.db = db
}
}
func (s *UserService) getUidFromContext(ctx context.Context) (string, error) {
if claims, ok := auth.FromContext(ctx); !ok {
return "", errors.ErrAccessDenied
} else {
return claims.GetSubject()
}
}
func (s *UserService) hasPermission(menuName string, permissions []*models.Permission) bool {
for _, permission := range permissions {
if permission.Menu == menuName {
return true
}
}
return false
}
func (s *UserService) getPermissions(menuName string, permissions []*models.Permission) []*pb.PermissionItem {
ss := make([]*pb.PermissionItem, 0, 10)
for _, permission := range permissions {
if permission.Menu == menuName {
ss = append(ss, &pb.PermissionItem{
Value: permission.Permission,
Label: permission.Label,
})
}
}
return ss
}
func (s *UserService) recursiveNestedMenu(ctx context.Context, parent string, perm bool, menus []*models.Menu, permissions []*models.Permission) []*pb.MenuItem {
values := make([]*pb.MenuItem, 0)
for _, row := range menus {
if row.Parent == parent {
if !row.Public && !s.hasPermission(row.Name, permissions) {
continue
}
v := &pb.MenuItem{
Label: row.Label,
Name: row.Name,
Icon: row.Icon,
Hidden: row.Hidden,
Route: row.Uri,
Public: row.Public,
View: row.ViewPath,
Children: s.recursiveNestedMenu(ctx, row.Name, perm, menus, permissions),
}
if perm {
v.Permissions = s.getPermissions(row.Name, permissions)
}
values = append(values, v)
}
}
return values
}
func (s *UserService) getRolePermissions(db *gorm.DB, role string) (permissions []*models.Permission, err error) {
permissions = make([]*models.Permission, 0)
err = db.Where("permission IN (SELECT permission FROM role_permissions WHERE role = ?)", role).Find(&permissions).Error
return
}
func (s *UserService) GetMenus(ctx context.Context, req *pb.GetMenuRequest) (res *pb.GetMenuResponse, err error) {
var (
uid string
permissions []*models.Permission
)
if uid, err = s.getUidFromContext(ctx); err != nil {
return
}
res = &pb.GetMenuResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:menu:%s:%v", uid, req.Permission), func(tx *gorm.DB) ([]*pb.MenuItem, error) {
userModel := &models.User{}
if err = tx.Where("uid=?", uid).First(userModel).Error; err != nil {
return nil, err
}
items := make([]*models.Menu, 0)
if err = tx.Find(&items).Error; err != nil {
return nil, err
}
if userModel.Admin {
permissions = make([]*models.Permission, 0)
if err = tx.Find(&permissions).Error; err != nil {
return nil, err
}
} else {
if permissions, err = s.getRolePermissions(tx, userModel.Role); err != nil {
return nil, err
}
}
return s.recursiveNestedMenu(ctx, "", req.Permission, items, permissions), nil
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT `updated_at` FROM users WHERE `uid`=?", uid)),
)
return
}
func (s *UserService) 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, err = dbcache.TryCache(ctx, fmt.Sprintf("user:profile:%s", req.Uid), func(tx *gorm.DB) (*pb.GetProfileResponse, error) {
profile := &pb.GetProfileResponse{}
err = tx.Table("users AS u").
Select("u.uid as uid", "u.username", "u.avatar", "u.email", "u.description", "u.role", "u.admin").
Where("u.uid=? ", req.Uid).
First(profile).Error
return profile, err
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT `updated_at` FROM users WHERE `uid`=?", req.Uid)),
// dbcache.WithDepend("SELECT `updated_at` FROM users WHERE `uid`=?", req.Uid),
)
return
}
func (s *UserService) 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 *UserService) 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 (s *UserService) GetPermissions(ctx context.Context, req *pb.GetPermissionRequest) (res *pb.GetPermissionResponse, err error) {
if req.Uid == "" {
if req.Uid, err = s.getUidFromContext(ctx); err != nil {
return
}
}
res = &pb.GetPermissionResponse{
Uid: req.Uid,
}
res.Permissions, err = dbcache.TryCache(ctx, fmt.Sprintf("user:permissions:%s", req.Uid), func(tx *gorm.DB) ([]string, error) {
var ss []string
err = tx.Select("permission").Model(&models.RolePermission{}).
Joins("LEFT JOIN users on users.role = role_permissions.role").
Where("users.uid = ?", req.Uid).
Pluck("permission", &ss).
Error
return ss, err
}, dbcache.WithCacheDuration(time.Minute), dbcache.WithDB(s.opts.db))
return
}
func (s *UserService) GetUserLabels(ctx context.Context, req *pb.GetUserLabelRequest) (res *pb.GetUserLabelResponse, err error) {
res = &pb.GetUserLabelResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:labels"), func(tx *gorm.DB) ([]*pb.LabelValue, error) {
values := make([]*models.User, 0)
if err = tx.Find(&values).Error; err == nil {
items := make([]*pb.LabelValue, 0, len(values))
for _, v := range values {
items = append(items, &pb.LabelValue{
Label: v.Username,
Value: v.Uid,
})
}
return items, nil
} else {
return nil, err
}
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM users")),
)
return
}
func (s *UserService) GetUserTags(ctx context.Context, req *pb.GetUserTagRequest) (res *pb.GetUserTagResponse, err error) {
res = &pb.GetUserTagResponse{}
res.Data, err = dbcache.TryCache(ctx, fmt.Sprintf("user:tags"), func(tx *gorm.DB) ([]*pb.LabelValue, error) {
values := make([]*models.User, 0)
if err = tx.Select("DISTINCT(`tag`) AS `tag`").Find(&values).Error; err == nil {
items := make([]*pb.LabelValue, 0, len(values))
for _, v := range values {
if v.Tag == "" {
continue
}
items = append(items, &pb.LabelValue{
Label: v.Tag,
Value: v.Tag,
})
}
return items, nil
} else {
return nil, err
}
},
dbcache.WithDB(s.opts.db),
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM users")),
)
return
}
func NewUserService(cbs ...UserOption) *UserService {
opts := &userOptions{}
for _, cb := range cbs {
cb(opts)
}
return &UserService{
opts: opts,
}
}

50
template.go 100644
View File

@ -0,0 +1,50 @@
package aeusadmin
var (
vueTemplate = `
<template>
<viewer
:title="title"
:module-name="moduleName"
:table-name="tableName"
:apiPrefix="apiPrefix"
:permissions="permissions"
:disable-toolbar="false"
default-sortable="id"
{{if .Readonly}}:readonly="true"{{end}}
>
</viewer>
</template>
<script setup>
import Viewer from '@/components/fragment/Viewer.vue';
import { computed } from 'vue';
const props = defineProps({
title: {
type: String,
}
})
const permissions = computed(() => {
return {
{{range $key, $value := .Permissions}}{{$key}}: "{{$value}}",
{{end}}
}
})
const apiPrefix = computed(() => {
return '{{.ApiPrefix}}'
})
const moduleName = computed(() => {
return '{{.ModuleName}}'
})
const tableName = computed(() => {
return '{{.TableName}}'
})
</script>
`
)

View File

@ -1,6 +1,7 @@
package aeusadmin package aeusadmin
import ( import (
"git.nobla.cn/golang/aeus/transport/http"
"git.nobla.cn/golang/rest" "git.nobla.cn/golang/rest"
"git.nobla.cn/golang/rest/types" "git.nobla.cn/golang/rest/types"
"gorm.io/gorm" "gorm.io/gorm"
@ -13,18 +14,22 @@ var (
types.ScenarioUpdate, types.ScenarioUpdate,
types.ScenarioDelete, types.ScenarioDelete,
types.ScenarioView, types.ScenarioView,
types.ScenarioImport,
types.ScenarioExport, types.ScenarioExport,
} }
) )
type ( type (
options struct { options struct {
db *gorm.DB db *gorm.DB
moduleName string domain string
viewPath string moduleName string
translate Translate apiPrefix string //接口前缀
restOpts []rest.Option viewPrefix string //生成菜单View的前缀路径
vuePath string //生成Vue文件的路径,如果指定了启动的时候会自动生成Vue的文件
translate Translate
disableDefault bool
httpServer *http.Server
restOpts []rest.Option
} }
Option func(*options) Option func(*options)
@ -33,6 +38,22 @@ type (
Menu(model *rest.Model, label string) string Menu(model *rest.Model, label string) string
Permission(model *rest.Model, scene string, label string) string Permission(model *rest.Model, scene string, label string) string
} }
MenuBuild interface {
Label(model *rest.Model) string
Title(model *rest.Model) string
Icon(model *rest.Model) string
Uri(model *rest.Model) string
ViewPath(model *rest.Model) string
}
vueTemplateData struct {
ModuleName string
TableName string
ApiPrefix string
Readonly bool
Permissions map[string]string
}
) )
func WithDB(db *gorm.DB) Option { func WithDB(db *gorm.DB) Option {
@ -41,15 +62,33 @@ func WithDB(db *gorm.DB) Option {
} }
} }
func WithoutDefault() Option {
return func(o *options) {
o.disableDefault = true
}
}
func WithHttpServer(server *http.Server) Option {
return func(o *options) {
o.httpServer = server
}
}
func WithApiPrefix(apiPrefix string) Option {
return func(o *options) {
o.apiPrefix = apiPrefix
}
}
func WithModuleName(moduleName string) Option { func WithModuleName(moduleName string) Option {
return func(o *options) { return func(o *options) {
o.moduleName = moduleName o.moduleName = moduleName
} }
} }
func WithViewPath(viewPath string) Option { func WithViewPrefix(viewPath string) Option {
return func(o *options) { return func(o *options) {
o.viewPath = viewPath o.viewPrefix = viewPath
} }
} }
@ -65,9 +104,17 @@ func WithRestOptions(opts ...rest.Option) Option {
} }
} }
func WithVuePath(path string) Option {
return func(o *options) {
o.vuePath = path
}
}
func newOptions(opts ...Option) *options { func newOptions(opts ...Option) *options {
o := &options{ o := &options{
viewPath: "views", viewPrefix: "views",
moduleName: "organize",
domain: "localhost",
} }
for _, opt := range opts { for _, opt := range opts {
opt(o) opt(o)

23
types/model.go 100644
View File

@ -0,0 +1,23 @@
package types
type Menu struct {
Parent string `json:"parent"`
Name string `json:"name"`
Label string `json:"label"`
Uri string `json:"uri"`
ViewPath string `json:"view_path"`
Icon string `json:"icon"`
Hidden bool `json:"hidden"`
}
type MenuModel interface {
GetMenu() *Menu
}
type ModuleModel interface {
ModuleName() string
}
type PerrmissionModule interface {
ModelPermissions() map[string]string
}

5
types/types.go 100644
View File

@ -0,0 +1,5 @@
package types
const (
UserStatusNormal = "normal"
)