add logic and menu service
This commit is contained in:
parent
ef4ad92e35
commit
79a9746447
|
@ -0,0 +1,80 @@
|
|||
package aeusadmin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/internal/logic"
|
||||
"git.nobla.cn/golang/rest"
|
||||
"git.nobla.cn/golang/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Formatter struct {
|
||||
db *gorm.DB
|
||||
user *logic.User
|
||||
department *logic.Department
|
||||
role *logic.Role
|
||||
menu *logic.Menu
|
||||
}
|
||||
|
||||
func (f *Formatter) FormatUser(ctx context.Context, value, model any, scm *types.Schema) any {
|
||||
if values, err := f.user.GetLabels(ctx); err == nil {
|
||||
for _, row := range values {
|
||||
if row.Value == value {
|
||||
return fmt.Sprintf("%s(%s)", row.Label, row.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (f *Formatter) FormatDepartment(ctx context.Context, value, model any, scm *types.Schema) any {
|
||||
if values, err := f.department.GetLabels(ctx); err == nil {
|
||||
for _, row := range values {
|
||||
if row.Value == value {
|
||||
return row.Label
|
||||
}
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (f *Formatter) FormatRole(ctx context.Context, value, model any, scm *types.Schema) any {
|
||||
if values, err := f.role.GetLabels(ctx); err == nil {
|
||||
for _, row := range values {
|
||||
if row.Value == value {
|
||||
return row.Label
|
||||
}
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (f *Formatter) FormatMenu(ctx context.Context, value, model any, scm *types.Schema) any {
|
||||
if values, err := f.menu.GetLabels(ctx); err == nil {
|
||||
for _, row := range values {
|
||||
if row.Value == value {
|
||||
return row.Label
|
||||
}
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (f *Formatter) Register() {
|
||||
rest.DefaultFormatter.Register("user", f.FormatUser)
|
||||
rest.DefaultFormatter.Register("department", f.FormatDepartment)
|
||||
rest.DefaultFormatter.Register("role", f.FormatRole)
|
||||
rest.DefaultFormatter.Register("menu", f.FormatMenu)
|
||||
}
|
||||
|
||||
func NewFormatter(db *gorm.DB) *Formatter {
|
||||
return &Formatter{
|
||||
db: db,
|
||||
user: logic.NewUserLogic(db),
|
||||
department: logic.NewDepartmentLogic(db),
|
||||
role: logic.NewRoleLogic(db),
|
||||
menu: logic.NewMenuLogic(db),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
|
||||
"git.nobla.cn/golang/rest"
|
||||
"git.nobla.cn/golang/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Department struct {
|
||||
db *gorm.DB
|
||||
sqlDependency *dbcache.SqlDependency
|
||||
}
|
||||
|
||||
func (u *Department) RecursiveDepartment(ctx context.Context, parent int64, level int, departments []*models.Department) []*types.TypeValue[int64] {
|
||||
var (
|
||||
child []*types.TypeValue[int64]
|
||||
)
|
||||
values := make([]*types.TypeValue[int64], 0, len(departments))
|
||||
for _, dept := range departments {
|
||||
if dept.ParentId == parent {
|
||||
if level == 0 {
|
||||
values = append(values, &types.TypeValue[int64]{
|
||||
Label: dept.Name,
|
||||
Value: dept.Id,
|
||||
})
|
||||
} else {
|
||||
values = append(values, &types.TypeValue[int64]{
|
||||
Label: strings.Repeat("--", level) + dept.Name,
|
||||
Value: dept.Id,
|
||||
})
|
||||
}
|
||||
child = u.RecursiveDepartment(ctx, dept.Id, level+1, departments)
|
||||
if len(child) > 0 {
|
||||
for _, row := range child {
|
||||
values = append(values, row)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// GetLevelLabels 获取层级标签
|
||||
func (u *Department) GetLevelLabels(ctx context.Context) (values []*types.TypeValue[int64], err error) {
|
||||
values, err = dbcache.TryCache(ctx, fmt.Sprintf("department:level:labels"), func(tx *gorm.DB) ([]*types.TypeValue[int64], error) {
|
||||
var values []*models.Department
|
||||
if err = tx.Find(&values).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return u.RecursiveDepartment(ctx, 0, 0, values), nil
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// GetLabels 获取用户标签
|
||||
func (u *Department) GetLabels(ctx context.Context) (values []*types.TypeValue[int64], err error) {
|
||||
values, err = dbcache.TryCache(ctx, fmt.Sprintf("department:labels"), func(tx *gorm.DB) ([]*types.TypeValue[int64], error) {
|
||||
return rest.ModelTypes[int64](ctx, tx, &models.Department{}, "", "name", "id")
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDepartments 获取部门列表
|
||||
func (u *Department) GetDepartments(ctx context.Context) (values []*models.Department, err error) {
|
||||
values, err = dbcache.TryCache(ctx, fmt.Sprintf("department:list"), func(tx *gorm.DB) ([]*models.Department, error) {
|
||||
var items []*models.Department
|
||||
err = tx.Find(&items).Error
|
||||
return items, err
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func NewDepartmentLogic(db *gorm.DB) *Department {
|
||||
return &Department{
|
||||
db: db,
|
||||
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM departments"),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
|
||||
"git.nobla.cn/golang/rest"
|
||||
"git.nobla.cn/golang/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Menu struct {
|
||||
db *gorm.DB
|
||||
sqlDependency *dbcache.SqlDependency
|
||||
}
|
||||
|
||||
func (u *Menu) GetMenus(ctx context.Context) (values []*models.Menu, err error) {
|
||||
return dbcache.TryCache(ctx, "menus", func(tx *gorm.DB) ([]*models.Menu, error) {
|
||||
var items []*models.Menu
|
||||
err = tx.Order("`position`,`id` ASC").Find(&items).Error
|
||||
return items, err
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
}
|
||||
|
||||
func (u *Menu) GetLabels(ctx context.Context) (values []*types.TypeValue[string], err error) {
|
||||
return dbcache.TryCache(ctx, fmt.Sprintf("menu:labels"), func(tx *gorm.DB) ([]*types.TypeValue[string], error) {
|
||||
return rest.ModelTypes[string](ctx, tx, &models.Menu{}, "", "label", "name")
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
}
|
||||
|
||||
func NewMenuLogic(db *gorm.DB) *Menu {
|
||||
return &Menu{
|
||||
db: db,
|
||||
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM menus"),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
|
||||
"git.nobla.cn/golang/rest"
|
||||
"git.nobla.cn/golang/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Role struct {
|
||||
db *gorm.DB
|
||||
sqlDependency *dbcache.SqlDependency
|
||||
permissionSqlDependency *dbcache.SqlDependency
|
||||
}
|
||||
|
||||
func (u *Role) GetLabels(ctx context.Context) (values []*types.TypeValue[string], err error) {
|
||||
values, err = dbcache.TryCache(ctx, fmt.Sprintf("role:labels"), func(tx *gorm.DB) ([]*types.TypeValue[string], error) {
|
||||
return rest.ModelTypes[string](ctx, tx, &models.Role{}, "", "label", "name")
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func (u *Role) GetPermissions(ctx context.Context, role string) (values []*models.Permission, err error) {
|
||||
values, err = dbcache.TryCache(ctx, fmt.Sprintf("role:permissions-items:%s", role), func(tx *gorm.DB) ([]*models.Permission, error) {
|
||||
var items []*models.Permission
|
||||
if role == "" {
|
||||
err = tx.Find(&items).Error
|
||||
} else {
|
||||
err = tx.
|
||||
Where("`permission` IN (SELECT `permission` FROM role_permissions WHERE `role` = ?)", role).
|
||||
Find(&items).Error
|
||||
}
|
||||
return items, err
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.permissionSqlDependency),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func NewRoleLogic(db *gorm.DB) *Role {
|
||||
return &Role{
|
||||
db: db,
|
||||
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM roles"),
|
||||
permissionSqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM permissions"),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
|
||||
"git.nobla.cn/golang/rest"
|
||||
"git.nobla.cn/golang/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
db *gorm.DB
|
||||
sqlDependency *dbcache.SqlDependency
|
||||
}
|
||||
|
||||
// GetPermissions 获取用户权限
|
||||
func (u *User) GetPermissions(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(u.db))
|
||||
return
|
||||
}
|
||||
|
||||
// GetLabels 获取用户标签
|
||||
func (u *User) GetLabels(ctx context.Context) (values []*types.TypeValue[string], err error) {
|
||||
values, err = dbcache.TryCache(ctx, fmt.Sprintf("user:labels"), func(tx *gorm.DB) ([]*types.TypeValue[string], error) {
|
||||
return rest.ModelTypes[string](ctx, tx, &models.User{}, "", "username", "uid")
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// GeUsers 获取部门列表
|
||||
func (u *User) GeUsers(ctx context.Context) (values []*models.User, err error) {
|
||||
values, err = dbcache.TryCache(ctx, fmt.Sprintf("user:list"), func(tx *gorm.DB) ([]*models.User, error) {
|
||||
var items []*models.User
|
||||
err = tx.Find(&items).Error
|
||||
return items, err
|
||||
},
|
||||
dbcache.WithDB(u.db),
|
||||
dbcache.WithDependency(u.sqlDependency),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func NewUserLogic(db *gorm.DB) *User {
|
||||
return &User{
|
||||
db: db,
|
||||
sqlDependency: dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM users"),
|
||||
}
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
package defaults
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -84,46 +81,3 @@ func init() {
|
|||
systemDepartment.Description = ""
|
||||
defaultDepartments = append(defaultDepartments, systemDepartment)
|
||||
}
|
||||
|
||||
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 (
|
||||
n int64
|
||||
)
|
||||
for _, row := range defaultMenus {
|
||||
if err = MergeMenu(db, row); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if db.Model(&models.Role{}).Count(&n); n == 0 {
|
||||
db.Create(defaultRoles)
|
||||
permissions := make([]*models.Permission, 0)
|
||||
db.Find(&permissions)
|
||||
for _, row := range defaultRoles {
|
||||
items := make([]*models.RolePermission, 0)
|
||||
for _, perm := range permissions {
|
||||
item := &models.RolePermission{}
|
||||
item.Role = row.Name
|
||||
item.Permission = perm.Permission
|
||||
items = append(items, item)
|
||||
}
|
||||
db.Save(items)
|
||||
}
|
||||
}
|
||||
|
||||
if db.Model(&models.Department{}).Count(&n); n == 0 {
|
||||
db.Create(defaultDepartments)
|
||||
}
|
||||
if db.Model(&models.User{}).Count(&n); n == 0 {
|
||||
db.Create(defaultUsers)
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package migrate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Menu 合并菜单
|
||||
func Menu(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
|
||||
}
|
||||
|
||||
// Permission 合并权限数据
|
||||
func Permission(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
|
||||
}
|
||||
|
||||
// Default 合并初始化数据集
|
||||
func Default(db *gorm.DB) (err error) {
|
||||
var (
|
||||
n int64
|
||||
)
|
||||
for _, row := range defaultMenus {
|
||||
if err = Menu(db, row); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if db.Model(&models.Role{}).Count(&n); n == 0 {
|
||||
db.Create(defaultRoles)
|
||||
permissions := make([]*models.Permission, 0)
|
||||
db.Find(&permissions)
|
||||
for _, row := range defaultRoles {
|
||||
items := make([]*models.RolePermission, 0)
|
||||
for _, perm := range permissions {
|
||||
item := &models.RolePermission{}
|
||||
item.Role = row.Name
|
||||
item.Permission = perm.Permission
|
||||
items = append(items, item)
|
||||
}
|
||||
db.Save(items)
|
||||
}
|
||||
}
|
||||
|
||||
if db.Model(&models.Department{}).Count(&n); n == 0 {
|
||||
db.Create(defaultDepartments)
|
||||
}
|
||||
if db.Model(&models.User{}).Count(&n); n == 0 {
|
||||
db.Create(defaultUsers)
|
||||
}
|
||||
return
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -17,7 +17,7 @@ message Menu {
|
|||
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"菜单ID"}];
|
||||
int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
|
||||
int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
|
||||
string parent = 4 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",comment:"父级菜单"}];
|
||||
string parent = 4 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",live:"type:dropdown;url:/menu/level-labels",format:"menu",comment:"父级菜单"}];
|
||||
string name = 5 [(aeus.field)={gorm:"index;size:60",props:"readonly:update",rule:"unique;required",comment: "组件名称"},(validate.rules).string = {max_len: 60}];
|
||||
string label = 6 [(aeus.field)={gorm:"size:120",rule:"required",comment: "菜单标题"},(validate.rules).string = {max_len: 120}];
|
||||
string uri = 7 [(aeus.field)={gorm:"size:512",rule:"required",scenarios:"create;update;view;export",comment: "菜单链接"},(validate.rules).string = {max_len: 512}];
|
||||
|
@ -26,6 +26,7 @@ message Menu {
|
|||
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}];
|
||||
int64 position = 13 [(aeus.field)={comment:"排序",scenarios:"create;update"}];
|
||||
}
|
||||
|
||||
// Role 角色模型定义
|
||||
|
@ -47,9 +48,11 @@ message Permission {
|
|||
table: "permissions"
|
||||
};
|
||||
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment: "权限ID"}];
|
||||
string menu = 2 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "所属菜单"}];
|
||||
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",rule:"required",comment: "权限标题"},(validate.rules).string = {max_len: 60}];
|
||||
int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
|
||||
int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
|
||||
string menu = 4 [(aeus.field)={gorm:"index;size:60",format:"menu",rule:"required",comment: "所属菜单"}];
|
||||
string permission = 5 [(aeus.field)={gorm:"index;size:60",rule:"required",comment: "权限名称"},(validate.rules).string = {max_len: 60}];
|
||||
string label = 6 [(aeus.field)={gorm:"size:60",rule:"required",comment: "权限标题"},(validate.rules).string = {max_len: 60}];
|
||||
}
|
||||
|
||||
// RolePermission 角色权限关联表
|
||||
|
@ -92,7 +95,7 @@ message Department {
|
|||
int64 id = 1 [(aeus.field) = {gorm:"primaryKey",comment:"ID"}];
|
||||
int64 created_at = 2 [(aeus.field)={scenarios:"view;export",comment:"创建时间"}];
|
||||
int64 updated_at = 3 [(aeus.field)={gorm:"index",scenarios:"view;export",comment:"更新时间"}];
|
||||
int64 parent_id = 4 [(aeus.field)={format:"department",comment:"父级部门"}];
|
||||
int64 parent_id = 4 [(aeus.field)={live:"type:dropdown;url:/department/level-labels",format:"department",comment:"父级部门"}];
|
||||
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",scenarios:"create;update;view;export;list",format:"textarea",comment: "备注说明"},(validate.rules).string = {max_len: 1024}];
|
||||
}
|
||||
|
@ -289,6 +292,13 @@ message DepartmentLabelValue {
|
|||
int64 value = 2;
|
||||
}
|
||||
|
||||
message DepartmentUserValue {
|
||||
string label = 1;
|
||||
string value = 2;
|
||||
bool isuser = 3;
|
||||
repeated DepartmentUserValue children = 4;
|
||||
}
|
||||
|
||||
message GetDepartmentLabelRequest {
|
||||
}
|
||||
|
||||
|
@ -296,6 +306,26 @@ message GetDepartmentLabelResponse {
|
|||
repeated DepartmentLabelValue data = 1;
|
||||
}
|
||||
|
||||
message GetDepartmentUserRequest {
|
||||
}
|
||||
|
||||
message GetDepartmentUserResponse {
|
||||
repeated DepartmentUserValue data = 1;
|
||||
}
|
||||
|
||||
message DepartmentLevelValue {
|
||||
string label = 1;
|
||||
int64 value = 2;
|
||||
repeated DepartmentLevelValue children = 4;
|
||||
}
|
||||
|
||||
message GetDepartmentLevelLabelsRequest {
|
||||
}
|
||||
|
||||
message GetDepartmentLevelLabelsResponse {
|
||||
repeated DepartmentLevelValue data = 1;
|
||||
}
|
||||
|
||||
service DepartmentService {
|
||||
// 获取部门标签
|
||||
rpc GetDepartmentLabels(GetDepartmentLabelRequest) returns (GetDepartmentLabelResponse) {
|
||||
|
@ -303,6 +333,16 @@ service DepartmentService {
|
|||
get: "/department/labels"
|
||||
};
|
||||
}
|
||||
rpc GetDepartmentUsers(GetDepartmentUserRequest) returns (GetDepartmentUserResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/department/users"
|
||||
};
|
||||
}
|
||||
rpc GetDepartmentLevelLabels(GetDepartmentLevelLabelsRequest) returns (GetDepartmentLevelLabelsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/department/level-labels"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message GetRoleLabelRequest {
|
||||
|
@ -352,6 +392,27 @@ service RoleService {
|
|||
}
|
||||
}
|
||||
|
||||
message MenuLevelValue {
|
||||
string label = 1;
|
||||
string value = 2;
|
||||
repeated MenuLevelValue children = 4;
|
||||
}
|
||||
|
||||
message GetMenuLevelLabelsRequest {
|
||||
}
|
||||
|
||||
message GetMenuLevelLabelsResponse {
|
||||
repeated MenuLevelValue data = 1;
|
||||
}
|
||||
|
||||
service MenuService {
|
||||
rpc GetMenuLevelLabels(GetMenuLevelLabelsRequest) returns (GetMenuLevelLabelsResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/menu/level-labels"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message LoginRequest {
|
||||
string username = 1;
|
||||
|
|
|
@ -368,6 +368,8 @@ var UserService_ServiceDesc = grpc.ServiceDesc{
|
|||
|
||||
const (
|
||||
DepartmentService_GetDepartmentLabels_FullMethodName = "/organize.DepartmentService/GetDepartmentLabels"
|
||||
DepartmentService_GetDepartmentUsers_FullMethodName = "/organize.DepartmentService/GetDepartmentUsers"
|
||||
DepartmentService_GetDepartmentLevelLabels_FullMethodName = "/organize.DepartmentService/GetDepartmentLevelLabels"
|
||||
)
|
||||
|
||||
// DepartmentServiceClient is the client API for DepartmentService service.
|
||||
|
@ -376,6 +378,8 @@ const (
|
|||
type DepartmentServiceClient interface {
|
||||
// 获取部门标签
|
||||
GetDepartmentLabels(ctx context.Context, in *GetDepartmentLabelRequest, opts ...grpc.CallOption) (*GetDepartmentLabelResponse, error)
|
||||
GetDepartmentUsers(ctx context.Context, in *GetDepartmentUserRequest, opts ...grpc.CallOption) (*GetDepartmentUserResponse, error)
|
||||
GetDepartmentLevelLabels(ctx context.Context, in *GetDepartmentLevelLabelsRequest, opts ...grpc.CallOption) (*GetDepartmentLevelLabelsResponse, error)
|
||||
}
|
||||
|
||||
type departmentServiceClient struct {
|
||||
|
@ -396,12 +400,34 @@ func (c *departmentServiceClient) GetDepartmentLabels(ctx context.Context, in *G
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *departmentServiceClient) GetDepartmentUsers(ctx context.Context, in *GetDepartmentUserRequest, opts ...grpc.CallOption) (*GetDepartmentUserResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetDepartmentUserResponse)
|
||||
err := c.cc.Invoke(ctx, DepartmentService_GetDepartmentUsers_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *departmentServiceClient) GetDepartmentLevelLabels(ctx context.Context, in *GetDepartmentLevelLabelsRequest, opts ...grpc.CallOption) (*GetDepartmentLevelLabelsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetDepartmentLevelLabelsResponse)
|
||||
err := c.cc.Invoke(ctx, DepartmentService_GetDepartmentLevelLabels_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DepartmentServiceServer is the server API for DepartmentService service.
|
||||
// All implementations must embed UnimplementedDepartmentServiceServer
|
||||
// for forward compatibility.
|
||||
type DepartmentServiceServer interface {
|
||||
// 获取部门标签
|
||||
GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error)
|
||||
GetDepartmentUsers(context.Context, *GetDepartmentUserRequest) (*GetDepartmentUserResponse, error)
|
||||
GetDepartmentLevelLabels(context.Context, *GetDepartmentLevelLabelsRequest) (*GetDepartmentLevelLabelsResponse, error)
|
||||
mustEmbedUnimplementedDepartmentServiceServer()
|
||||
}
|
||||
|
||||
|
@ -415,6 +441,12 @@ type UnimplementedDepartmentServiceServer struct{}
|
|||
func (UnimplementedDepartmentServiceServer) GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentLabels not implemented")
|
||||
}
|
||||
func (UnimplementedDepartmentServiceServer) GetDepartmentUsers(context.Context, *GetDepartmentUserRequest) (*GetDepartmentUserResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentUsers not implemented")
|
||||
}
|
||||
func (UnimplementedDepartmentServiceServer) GetDepartmentLevelLabels(context.Context, *GetDepartmentLevelLabelsRequest) (*GetDepartmentLevelLabelsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetDepartmentLevelLabels not implemented")
|
||||
}
|
||||
func (UnimplementedDepartmentServiceServer) mustEmbedUnimplementedDepartmentServiceServer() {}
|
||||
func (UnimplementedDepartmentServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
|
@ -454,6 +486,42 @@ func _DepartmentService_GetDepartmentLabels_Handler(srv interface{}, ctx context
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _DepartmentService_GetDepartmentUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetDepartmentUserRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DepartmentServiceServer).GetDepartmentUsers(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: DepartmentService_GetDepartmentUsers_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DepartmentServiceServer).GetDepartmentUsers(ctx, req.(*GetDepartmentUserRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _DepartmentService_GetDepartmentLevelLabels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetDepartmentLevelLabelsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DepartmentServiceServer).GetDepartmentLevelLabels(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: DepartmentService_GetDepartmentLevelLabels_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DepartmentServiceServer).GetDepartmentLevelLabels(ctx, req.(*GetDepartmentLevelLabelsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// DepartmentService_ServiceDesc is the grpc.ServiceDesc for DepartmentService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
|
@ -465,6 +533,14 @@ var DepartmentService_ServiceDesc = grpc.ServiceDesc{
|
|||
MethodName: "GetDepartmentLabels",
|
||||
Handler: _DepartmentService_GetDepartmentLabels_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetDepartmentUsers",
|
||||
Handler: _DepartmentService_GetDepartmentUsers_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetDepartmentLevelLabels",
|
||||
Handler: _DepartmentService_GetDepartmentLevelLabels_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "organize.proto",
|
||||
|
@ -652,6 +728,108 @@ var RoleService_ServiceDesc = grpc.ServiceDesc{
|
|||
Metadata: "organize.proto",
|
||||
}
|
||||
|
||||
const (
|
||||
MenuService_GetMenuLevelLabels_FullMethodName = "/organize.MenuService/GetMenuLevelLabels"
|
||||
)
|
||||
|
||||
// MenuServiceClient is the client API for MenuService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type MenuServiceClient interface {
|
||||
GetMenuLevelLabels(ctx context.Context, in *GetMenuLevelLabelsRequest, opts ...grpc.CallOption) (*GetMenuLevelLabelsResponse, error)
|
||||
}
|
||||
|
||||
type menuServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewMenuServiceClient(cc grpc.ClientConnInterface) MenuServiceClient {
|
||||
return &menuServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *menuServiceClient) GetMenuLevelLabels(ctx context.Context, in *GetMenuLevelLabelsRequest, opts ...grpc.CallOption) (*GetMenuLevelLabelsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetMenuLevelLabelsResponse)
|
||||
err := c.cc.Invoke(ctx, MenuService_GetMenuLevelLabels_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MenuServiceServer is the server API for MenuService service.
|
||||
// All implementations must embed UnimplementedMenuServiceServer
|
||||
// for forward compatibility.
|
||||
type MenuServiceServer interface {
|
||||
GetMenuLevelLabels(context.Context, *GetMenuLevelLabelsRequest) (*GetMenuLevelLabelsResponse, error)
|
||||
mustEmbedUnimplementedMenuServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedMenuServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedMenuServiceServer struct{}
|
||||
|
||||
func (UnimplementedMenuServiceServer) GetMenuLevelLabels(context.Context, *GetMenuLevelLabelsRequest) (*GetMenuLevelLabelsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetMenuLevelLabels not implemented")
|
||||
}
|
||||
func (UnimplementedMenuServiceServer) mustEmbedUnimplementedMenuServiceServer() {}
|
||||
func (UnimplementedMenuServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeMenuServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MenuServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeMenuServiceServer interface {
|
||||
mustEmbedUnimplementedMenuServiceServer()
|
||||
}
|
||||
|
||||
func RegisterMenuServiceServer(s grpc.ServiceRegistrar, srv MenuServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedMenuServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&MenuService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _MenuService_GetMenuLevelLabels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetMenuLevelLabelsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MenuServiceServer).GetMenuLevelLabels(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MenuService_GetMenuLevelLabels_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MenuServiceServer).GetMenuLevelLabels(ctx, req.(*GetMenuLevelLabelsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// MenuService_ServiceDesc is the grpc.ServiceDesc for MenuService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var MenuService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "organize.MenuService",
|
||||
HandlerType: (*MenuServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetMenuLevelLabels",
|
||||
Handler: _MenuService_GetMenuLevelLabels_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "organize.proto",
|
||||
}
|
||||
|
||||
const (
|
||||
AuthService_Login_FullMethodName = "/organize.AuthService/Login"
|
||||
AuthService_Logout_FullMethodName = "/organize.AuthService/Logout"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
|
||||
// source: organize.proto
|
||||
// date: 2025-06-17 18:12:28
|
||||
// date: 2025-06-18 14:37:24
|
||||
|
||||
package pb
|
||||
|
||||
|
@ -28,6 +28,10 @@ type UserServiceHttpServer interface {
|
|||
|
||||
type DepartmentServiceHttpServer interface {
|
||||
GetDepartmentLabels(context.Context, *GetDepartmentLabelRequest) (*GetDepartmentLabelResponse, error)
|
||||
|
||||
GetDepartmentUsers(context.Context, *GetDepartmentUserRequest) (*GetDepartmentUserResponse, error)
|
||||
|
||||
GetDepartmentLevelLabels(context.Context, *GetDepartmentLevelLabelsRequest) (*GetDepartmentLevelLabelsResponse, error)
|
||||
}
|
||||
|
||||
type RoleServiceHttpServer interface {
|
||||
|
@ -38,6 +42,10 @@ type RoleServiceHttpServer interface {
|
|||
SaveRolePermission(context.Context, *SaveRolePermissionRequest) (*SaveRolePermissionResponse, error)
|
||||
}
|
||||
|
||||
type MenuServiceHttpServer interface {
|
||||
GetMenuLevelLabels(context.Context, *GetMenuLevelLabelsRequest) (*GetMenuLevelLabelsResponse, error)
|
||||
}
|
||||
|
||||
type AuthServiceHttpServer interface {
|
||||
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
||||
|
||||
|
@ -212,6 +220,38 @@ func handleDepartmentServiceGetDepartmentLabels(s DepartmentServiceHttpServer) h
|
|||
}
|
||||
}
|
||||
|
||||
func handleDepartmentServiceGetDepartmentUsers(s DepartmentServiceHttpServer) http.HandleFunc {
|
||||
return func(ctx *http.Context) (err error) {
|
||||
req := &GetDepartmentUserRequest{}
|
||||
|
||||
if res, err := s.GetDepartmentUsers(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 handleDepartmentServiceGetDepartmentLevelLabels(s DepartmentServiceHttpServer) http.HandleFunc {
|
||||
return func(ctx *http.Context) (err error) {
|
||||
req := &GetDepartmentLevelLabelsRequest{}
|
||||
|
||||
if res, err := s.GetDepartmentLevelLabels(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 {
|
||||
|
@ -272,6 +312,22 @@ func handleRoleServiceSaveRolePermission(s RoleServiceHttpServer) http.HandleFun
|
|||
}
|
||||
}
|
||||
|
||||
func handleMenuServiceGetMenuLevelLabels(s MenuServiceHttpServer) http.HandleFunc {
|
||||
return func(ctx *http.Context) (err error) {
|
||||
req := &GetMenuLevelLabelsRequest{}
|
||||
|
||||
if res, err := s.GetMenuLevelLabels(ctx.Context(), req); err != nil {
|
||||
if er, ok := err.(*errors.Error); ok {
|
||||
return ctx.Error(er.Code, er.Message)
|
||||
} else {
|
||||
return ctx.Error(errors.Unavailable, err.Error())
|
||||
}
|
||||
} else {
|
||||
return ctx.Success(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleAuthServiceLogin(s AuthServiceHttpServer) http.HandleFunc {
|
||||
return func(ctx *http.Context) (err error) {
|
||||
req := &LoginRequest{}
|
||||
|
@ -358,6 +414,12 @@ func RegisterDepartmentServiceRouter(hs *http.Server, s DepartmentServiceHttpSer
|
|||
// Register handle GetDepartmentLabels route
|
||||
hs.GET("/department/labels", handleDepartmentServiceGetDepartmentLabels(s))
|
||||
|
||||
// Register handle GetDepartmentUsers route
|
||||
hs.GET("/department/users", handleDepartmentServiceGetDepartmentUsers(s))
|
||||
|
||||
// Register handle GetDepartmentLevelLabels route
|
||||
hs.GET("/department/level-labels", handleDepartmentServiceGetDepartmentLevelLabels(s))
|
||||
|
||||
}
|
||||
|
||||
func RegisterRoleServiceRouter(hs *http.Server, s RoleServiceHttpServer) {
|
||||
|
@ -373,6 +435,13 @@ func RegisterRoleServiceRouter(hs *http.Server, s RoleServiceHttpServer) {
|
|||
|
||||
}
|
||||
|
||||
func RegisterMenuServiceRouter(hs *http.Server, s MenuServiceHttpServer) {
|
||||
|
||||
// Register handle GetMenuLevelLabels route
|
||||
hs.GET("/menu/level-labels", handleMenuServiceGetMenuLevelLabels(s))
|
||||
|
||||
}
|
||||
|
||||
func RegisterAuthServiceRouter(hs *http.Server, s AuthServiceHttpServer) {
|
||||
|
||||
// Register handle Login route
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by protoc-gen-go-aeus. DO NOT EDIT.
|
||||
// source: organize.proto
|
||||
// date: 2025-06-17 18:12:28
|
||||
// date: 2025-06-18 14:37:24
|
||||
|
||||
package pb
|
||||
|
||||
|
@ -12,7 +12,7 @@ type MenuModel struct {
|
|||
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"菜单ID"`
|
||||
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
|
||||
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
|
||||
Parent string `json:"parent" yaml:"parent" xml:"parent" gorm:"index;size:60" comment:"父级菜单" props:"readonly:update"`
|
||||
Parent string `json:"parent" yaml:"parent" xml:"parent" gorm:"index;size:60" comment:"父级菜单" format:"menu" props:"readonly:update" live:"type:dropdown;url:/menu/level-labels"`
|
||||
Name string `json:"name" yaml:"name" xml:"name" gorm:"index;size:60" comment:"组件名称" props:"readonly:update" rule:"unique;required"`
|
||||
Label string `json:"label" yaml:"label" xml:"label" gorm:"size:120" comment:"菜单标题" rule:"required"`
|
||||
Uri string `json:"uri" yaml:"uri" xml:"uri" gorm:"size:512" comment:"菜单链接" scenarios:"create;update;view;export" rule:"required"`
|
||||
|
@ -21,6 +21,7 @@ type MenuModel struct {
|
|||
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"`
|
||||
Position int64 `json:"position" yaml:"position" xml:"position" comment:"排序" scenarios:"create;update"`
|
||||
}
|
||||
|
||||
func (m *MenuModel) TableName() string {
|
||||
|
@ -40,6 +41,7 @@ func (m *MenuModel) FromValue(x *Menu) {
|
|||
m.Hidden = x.Hidden
|
||||
m.Public = x.Public
|
||||
m.Description = x.Description
|
||||
m.Position = x.Position
|
||||
}
|
||||
|
||||
func (m *MenuModel) ToValue() (x *Menu) {
|
||||
|
@ -56,6 +58,7 @@ func (m *MenuModel) ToValue() (x *Menu) {
|
|||
x.Hidden = m.Hidden
|
||||
x.Public = m.Public
|
||||
x.Description = m.Description
|
||||
x.Position = m.Position
|
||||
return x
|
||||
}
|
||||
|
||||
|
@ -76,7 +79,7 @@ func (m *MenuModel) Delete(db *gorm.DB) (err error) {
|
|||
}
|
||||
|
||||
func (m *MenuModel) Find(db *gorm.DB, pk any) (err error) {
|
||||
return db.Where("description=?", pk).First(m).Error
|
||||
return db.Where("position=?", pk).First(m).Error
|
||||
}
|
||||
|
||||
func (m *MenuModel) FindOne(db *gorm.DB, query any, args ...any) (err error) {
|
||||
|
@ -158,7 +161,9 @@ func NewRoleModel() *RoleModel {
|
|||
|
||||
type PermissionModel struct {
|
||||
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"权限ID"`
|
||||
Menu string `json:"menu" yaml:"menu" xml:"menu" gorm:"index;size:60" comment:"所属菜单" rule:"required"`
|
||||
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
|
||||
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
|
||||
Menu string `json:"menu" yaml:"menu" xml:"menu" gorm:"index;size:60" comment:"所属菜单" format:"menu" rule:"required"`
|
||||
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" comment:"权限标题" rule:"required"`
|
||||
}
|
||||
|
@ -169,6 +174,8 @@ func (m *PermissionModel) TableName() string {
|
|||
|
||||
func (m *PermissionModel) FromValue(x *Permission) {
|
||||
m.Id = x.Id
|
||||
m.CreatedAt = x.CreatedAt
|
||||
m.UpdatedAt = x.UpdatedAt
|
||||
m.Menu = x.Menu
|
||||
m.Permission = x.Permission
|
||||
m.Label = x.Label
|
||||
|
@ -177,6 +184,8 @@ func (m *PermissionModel) FromValue(x *Permission) {
|
|||
func (m *PermissionModel) ToValue() (x *Permission) {
|
||||
x = &Permission{}
|
||||
x.Id = m.Id
|
||||
x.CreatedAt = m.CreatedAt
|
||||
x.UpdatedAt = m.UpdatedAt
|
||||
x.Menu = m.Menu
|
||||
x.Permission = m.Permission
|
||||
x.Label = m.Label
|
||||
|
@ -367,7 +376,7 @@ type DepartmentModel struct {
|
|||
Id int64 `json:"id" yaml:"id" xml:"id" gorm:"primaryKey" comment:"ID"`
|
||||
CreatedAt int64 `json:"created_at" yaml:"createdAt" xml:"createdAt" comment:"创建时间" scenarios:"view;export"`
|
||||
UpdatedAt int64 `json:"updated_at" yaml:"updatedAt" xml:"updatedAt" gorm:"index" comment:"更新时间" scenarios:"view;export"`
|
||||
ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" comment:"父级部门" format:"department"`
|
||||
ParentId int64 `json:"parent_id" yaml:"parentId" xml:"parentId" comment:"父级部门" format:"department" live:"type:dropdown;url:/department/level-labels"`
|
||||
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" comment:"备注说明" scenarios:"create;update;view;export;list" format:"textarea"`
|
||||
}
|
||||
|
|
|
@ -2,12 +2,9 @@ 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-admin/internal/logic"
|
||||
"git.nobla.cn/golang/aeus/middleware/auth"
|
||||
"git.nobla.cn/golang/aeus/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
@ -15,22 +12,9 @@ import (
|
|||
|
||||
type PermissionChecker struct {
|
||||
db *gorm.DB
|
||||
logic *logic.User
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -43,7 +27,7 @@ func (p *PermissionChecker) CheckPermission(ctx context.Context, permission stri
|
|||
return
|
||||
}
|
||||
}
|
||||
if ps, err = p.getUserPermissions(ctx, uid); err != nil {
|
||||
if ps, err = p.logic.GetPermissions(ctx, uid); err != nil {
|
||||
return
|
||||
}
|
||||
if !slices.Contains(ps, permission) {
|
||||
|
@ -55,5 +39,6 @@ func (p *PermissionChecker) CheckPermission(ctx context.Context, permission stri
|
|||
func NewPermissionChecker(db *gorm.DB) *PermissionChecker {
|
||||
return &PermissionChecker{
|
||||
db: db,
|
||||
logic: logic.NewUserLogic(db),
|
||||
}
|
||||
}
|
||||
|
|
35
server.go
35
server.go
|
@ -11,7 +11,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/defaults"
|
||||
"git.nobla.cn/golang/aeus-admin/migrate"
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"git.nobla.cn/golang/aeus-admin/pkg/dbcache"
|
||||
adminTypes "git.nobla.cn/golang/aeus-admin/types"
|
||||
|
@ -100,30 +100,11 @@ func checkModelMenu(db *gorm.DB, viewPath string, apiPrefix string, model *rest.
|
|||
func checkModelPermission(db *gorm.DB, menuName string, scene string, model *rest.Model, translate Translate) (permissionModel *models.Permission, err error) {
|
||||
permissionModel = &models.Permission{}
|
||||
permission := model.Permission(scene)
|
||||
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 = scene
|
||||
label := scene
|
||||
if translate != nil {
|
||||
permissionModel.Label = translate.Permission(model, scene, permissionModel.Label)
|
||||
}
|
||||
permissionModel.Permission = permission
|
||||
err = db.Create(permissionModel).Error
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
label = translate.Permission(model, scene, label)
|
||||
}
|
||||
permissionModel, err = migrate.Permission(db, menuName, permission, label)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -148,7 +129,7 @@ func checkModel(opts *options, model *rest.Model) (err error) {
|
|||
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 {
|
||||
if _, err = migrate.Permission(tx, menuModel.Name, k, v); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
@ -287,7 +268,6 @@ func AutoMigrate(ctx context.Context, db *gorm.DB, model any, cbs ...Option) (er
|
|||
}
|
||||
|
||||
func registerRESTRoute(domain string, db *gorm.DB, hs *http.Server) {
|
||||
|
||||
handleListSchemas := func(ctx *http.Context) (err error) {
|
||||
var (
|
||||
schemas []*restTypes.Schema
|
||||
|
@ -390,7 +370,7 @@ func Init(ctx context.Context, cbs ...Option) (err error) {
|
|||
registerRESTRoute(opts.domain, opts.db, opts.httpServer)
|
||||
}
|
||||
if !opts.disableDefault {
|
||||
if err = defaults.Generate(opts.db); err != nil {
|
||||
if err = migrate.Default(opts.db); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -398,5 +378,8 @@ func Init(ctx context.Context, cbs ...Option) (err error) {
|
|||
//启用操作记录
|
||||
NewActivityRecorder(ctx, opts.db).Recoder()
|
||||
}
|
||||
|
||||
//注册渲染器
|
||||
NewFormatter(opts.db).Register()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
|
@ -20,6 +23,19 @@ type (
|
|||
secret []byte
|
||||
method string
|
||||
ttl int64
|
||||
turnstileValidateUrl string
|
||||
turnstileSiteKey string
|
||||
}
|
||||
|
||||
turnstileRequest struct {
|
||||
Secret string `json:"secret"`
|
||||
Response string `json:"response"`
|
||||
}
|
||||
turnstileResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Hostname string `json:"hostname"`
|
||||
ErrorCodes []string `json:"error-codes"`
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
AuthOption func(o *authOptions)
|
||||
|
@ -41,6 +57,16 @@ func WithAuthSecret(secret []byte) AuthOption {
|
|||
}
|
||||
}
|
||||
|
||||
func WithAuthTranslate(key, url string) AuthOption {
|
||||
return func(o *authOptions) {
|
||||
o.turnstileSiteKey = key
|
||||
if url == "" {
|
||||
url = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
|
||||
}
|
||||
o.turnstileValidateUrl = url
|
||||
}
|
||||
}
|
||||
|
||||
func WithAuthMethod(method string) AuthOption {
|
||||
return func(o *authOptions) {
|
||||
o.method = method
|
||||
|
@ -53,12 +79,56 @@ func WithAuthTTL(ttl int64) AuthOption {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *AuthService) turnstileValidate(ctx context.Context, token string) (err error) {
|
||||
var (
|
||||
buf []byte
|
||||
req *http.Request
|
||||
res *http.Response
|
||||
)
|
||||
if s.opts.turnstileSiteKey == "" || s.opts.turnstileValidateUrl == "" {
|
||||
return nil
|
||||
}
|
||||
payload := &turnstileRequest{
|
||||
Secret: s.opts.turnstileSiteKey,
|
||||
Response: token,
|
||||
}
|
||||
if buf, err = json.Marshal(payload); err != nil {
|
||||
return
|
||||
}
|
||||
if req, err = http.NewRequestWithContext(ctx, http.MethodPost, s.opts.turnstileValidateUrl, bytes.NewReader(buf)); err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if res, err = http.DefaultClient.Do(req); err != nil {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return errors.Format(errors.Unavailable, "turnstile validate failed")
|
||||
}
|
||||
result := &turnstileResponse{}
|
||||
if err = json.NewDecoder(res.Body).Decode(result); err != nil {
|
||||
return
|
||||
}
|
||||
if !result.Success {
|
||||
if len(result.ErrorCodes) == 0 {
|
||||
err = errors.Format(errors.Unavailable, "turnstile validate failed")
|
||||
} else {
|
||||
err = errors.Format(errors.Unavailable, result.ErrorCodes[0])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (res *pb.LoginResponse, err error) {
|
||||
model := &models.User{}
|
||||
tx := s.opts.db.WithContext(ctx)
|
||||
if err = req.Validate(); err != nil {
|
||||
return nil, errors.Format(errors.Invalid, err.Error())
|
||||
}
|
||||
if err = s.turnstileValidate(ctx, req.Token); err != nil {
|
||||
return nil, errors.Format(errors.Invalid, err.Error())
|
||||
}
|
||||
if err = model.FindOne(tx, "uid=?", req.Username); err != nil {
|
||||
return nil, errors.ErrAccessDenied
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@ package service
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/internal/logic"
|
||||
"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/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
@ -18,6 +20,8 @@ type (
|
|||
|
||||
DepartmentService struct {
|
||||
opts *departmentOptions
|
||||
logic *logic.Department
|
||||
user *logic.User
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -29,24 +33,87 @@ func WithDepartmentDB(db *gorm.DB) DepartmentOption {
|
|||
|
||||
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,
|
||||
var values []*types.TypeValue[int64]
|
||||
if values, err = s.logic.GetLabels(ctx); err == nil {
|
||||
res.Data = make([]*pb.DepartmentLabelValue, 0, len(values))
|
||||
for _, row := range values {
|
||||
res.Data = append(res.Data, &pb.DepartmentLabelValue{
|
||||
Label: row.Label,
|
||||
Value: row.Value,
|
||||
})
|
||||
}
|
||||
return items, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
},
|
||||
dbcache.WithDB(s.opts.db),
|
||||
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM departments")),
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DepartmentService) recursiveDepartmentUser(parent int64, departments []*models.Department, users []*models.User) []*pb.DepartmentUserValue {
|
||||
values := make([]*pb.DepartmentUserValue, 0, len(departments))
|
||||
for _, row := range departments {
|
||||
if row.ParentId == parent {
|
||||
item := &pb.DepartmentUserValue{
|
||||
Label: row.Name,
|
||||
Value: strconv.FormatInt(row.Id, 10),
|
||||
Children: make([]*pb.DepartmentUserValue, 0),
|
||||
}
|
||||
item.Children = append(item.Children, s.recursiveDepartmentUser(row.Id, departments, users)...)
|
||||
for _, v := range users {
|
||||
if v.DeptId == row.Id {
|
||||
item.Children = append(item.Children, &pb.DepartmentUserValue{
|
||||
Label: fmt.Sprintf("%s(%s)", v.Username, v.Uid),
|
||||
Value: v.Uid,
|
||||
Isuser: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
values = append(values, item)
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
func (s *DepartmentService) recursiveDepartmentLevel(parent int64, departments []*models.Department) []*pb.DepartmentLevelValue {
|
||||
values := make([]*pb.DepartmentLevelValue, 0, len(departments))
|
||||
for _, row := range departments {
|
||||
if row.ParentId == parent {
|
||||
item := &pb.DepartmentLevelValue{
|
||||
Label: row.Name,
|
||||
Value: row.Id,
|
||||
Children: make([]*pb.DepartmentLevelValue, 0),
|
||||
}
|
||||
item.Children = append(item.Children, s.recursiveDepartmentLevel(row.Id, departments)...)
|
||||
values = append(values, item)
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
func (s *DepartmentService) GetDepartmentUsers(ctx context.Context, req *pb.GetDepartmentUserRequest) (res *pb.GetDepartmentUserResponse, err error) {
|
||||
var (
|
||||
users []*models.User
|
||||
departments []*models.Department
|
||||
)
|
||||
if departments, err = s.logic.GetDepartments(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if users, err = s.user.GeUsers(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
res = &pb.GetDepartmentUserResponse{
|
||||
Data: s.recursiveDepartmentUser(0, departments, users),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DepartmentService) GetDepartmentLevelLabels(ctx context.Context, req *pb.GetDepartmentLevelLabelsRequest) (res *pb.GetDepartmentLevelLabelsResponse, err error) {
|
||||
var (
|
||||
departments []*models.Department
|
||||
)
|
||||
if departments, err = s.logic.GetDepartments(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
res = &pb.GetDepartmentLevelLabelsResponse{
|
||||
Data: s.recursiveDepartmentLevel(0, departments),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -57,5 +124,7 @@ func NewDepartmentService(cbs ...DepartmentOption) *DepartmentService {
|
|||
}
|
||||
return &DepartmentService{
|
||||
opts: opts,
|
||||
user: logic.NewUserLogic(opts.db),
|
||||
logic: logic.NewDepartmentLogic(opts.db),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/internal/logic"
|
||||
"git.nobla.cn/golang/aeus-admin/models"
|
||||
"git.nobla.cn/golang/aeus-admin/pb"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type (
|
||||
menuOptions struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
MenuOption func(o *menuOptions)
|
||||
|
||||
MenuService struct {
|
||||
opts *menuOptions
|
||||
logic *logic.Menu
|
||||
}
|
||||
)
|
||||
|
||||
func WithMenuDB(db *gorm.DB) MenuOption {
|
||||
return func(o *menuOptions) {
|
||||
o.db = db
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MenuService) recursiveMenuLevel(parent string, items []*models.Menu) []*pb.MenuLevelValue {
|
||||
values := make([]*pb.MenuLevelValue, 0, len(items))
|
||||
for _, row := range items {
|
||||
if row.Parent == parent {
|
||||
item := &pb.MenuLevelValue{
|
||||
Label: row.Label,
|
||||
Value: row.Name,
|
||||
Children: make([]*pb.MenuLevelValue, 0),
|
||||
}
|
||||
item.Children = append(item.Children, s.recursiveMenuLevel(row.Name, items)...)
|
||||
values = append(values, item)
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
func (s *MenuService) GetMenuLevelLabels(ctx context.Context, req *pb.GetMenuLevelLabelsRequest) (res *pb.GetMenuLevelLabelsResponse, err error) {
|
||||
var (
|
||||
items []*models.Menu
|
||||
)
|
||||
if items, err = s.logic.GetMenus(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
res = &pb.GetMenuLevelLabelsResponse{
|
||||
Data: s.recursiveMenuLevel("", items),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func NewMenuService(cbs ...MenuOption) *MenuService {
|
||||
opts := &menuOptions{}
|
||||
for _, cb := range cbs {
|
||||
cb(opts)
|
||||
}
|
||||
return &MenuService{
|
||||
opts: opts,
|
||||
logic: logic.NewMenuLogic(opts.db),
|
||||
}
|
||||
}
|
|
@ -2,11 +2,11 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/internal/logic"
|
||||
"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/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
@ -18,6 +18,7 @@ type (
|
|||
|
||||
RoleService struct {
|
||||
opts *roleOptions
|
||||
logic *logic.Role
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -29,24 +30,16 @@ func WithRoleDB(db *gorm.DB) RoleOption {
|
|||
|
||||
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,
|
||||
var values []*types.TypeValue[string]
|
||||
if values, err = s.logic.GetLabels(ctx); err == nil {
|
||||
res.Data = make([]*pb.LabelValue, 0, len(values))
|
||||
for _, row := range values {
|
||||
res.Data = append(res.Data, &pb.LabelValue{
|
||||
Label: row.Label,
|
||||
Value: row.Value,
|
||||
})
|
||||
}
|
||||
return items, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
},
|
||||
dbcache.WithDB(s.opts.db),
|
||||
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT MAX(`updated_at`) FROM roles")),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -90,5 +83,6 @@ func NewRoleService(cbs ...RoleOption) *RoleService {
|
|||
}
|
||||
return &RoleService{
|
||||
opts: opts,
|
||||
logic: logic.NewRoleLogic(opts.db),
|
||||
}
|
||||
}
|
||||
|
|
108
service/user.go
108
service/user.go
|
@ -3,13 +3,16 @@ package service
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.nobla.cn/golang/aeus-admin/internal/logic"
|
||||
"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"
|
||||
"git.nobla.cn/golang/rest/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
@ -21,6 +24,10 @@ type (
|
|||
UserOption func(o *userOptions)
|
||||
|
||||
UserService struct {
|
||||
user *logic.User
|
||||
menu *logic.Menu
|
||||
role *logic.Role
|
||||
department *logic.Department
|
||||
opts *userOptions
|
||||
}
|
||||
)
|
||||
|
@ -87,12 +94,6 @@ func (s *UserService) recursiveNestedMenu(ctx context.Context, parent string, pe
|
|||
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
|
||||
|
@ -103,28 +104,28 @@ func (s *UserService) GetMenus(ctx context.Context, req *pb.GetMenuRequest) (res
|
|||
}
|
||||
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{}
|
||||
var (
|
||||
userModel *models.User
|
||||
menus []*models.Menu
|
||||
)
|
||||
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 {
|
||||
if menus, err = s.menu.GetMenus(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roleName := userModel.Role
|
||||
if userModel.Admin {
|
||||
permissions = make([]*models.Permission, 0)
|
||||
if err = tx.Find(&permissions).Error; err != nil {
|
||||
roleName = ""
|
||||
}
|
||||
if permissions, err = s.role.GetPermissions(ctx, roleName); 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
|
||||
return s.recursiveNestedMenu(ctx, "", req.Permission, menus, permissions), nil
|
||||
},
|
||||
dbcache.WithDB(s.opts.db),
|
||||
dbcache.WithDependency(dbcache.NewSqlDependency("SELECT `updated_at` FROM users WHERE `uid`=?", uid)),
|
||||
dbcache.WithCacheDuration(time.Second*10),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
@ -145,7 +146,6 @@ func (s *UserService) GetProfile(ctx context.Context, req *pb.GetProfileRequest)
|
|||
},
|
||||
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
|
||||
}
|
||||
|
@ -213,41 +213,59 @@ func (s *UserService) GetPermissions(ctx context.Context, req *pb.GetPermissionR
|
|||
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))
|
||||
res.Permissions, err = s.user.GetPermissions(ctx, req.Uid)
|
||||
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,
|
||||
var values []*types.TypeValue[string]
|
||||
if values, err = s.user.GetLabels(ctx); err == nil {
|
||||
res.Data = make([]*pb.LabelValue, 0, len(values))
|
||||
for _, row := range values {
|
||||
res.Data = append(res.Data, &pb.LabelValue{
|
||||
Label: row.Label,
|
||||
Value: row.Value,
|
||||
})
|
||||
}
|
||||
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) DepartmentUserNested(ctx context.Context) []*types.NestedValue[string] {
|
||||
var (
|
||||
err error
|
||||
users []*models.User
|
||||
departments []*models.Department
|
||||
)
|
||||
|
||||
if departments, err = s.department.GetDepartments(ctx); err != nil {
|
||||
return nil
|
||||
}
|
||||
if users, err = s.user.GeUsers(ctx); err != nil {
|
||||
return nil
|
||||
}
|
||||
depts := s.department.RecursiveDepartment(ctx, 0, 0, departments)
|
||||
values := make([]*types.NestedValue[string], 0)
|
||||
for _, dept := range depts {
|
||||
v := &types.NestedValue[string]{
|
||||
Label: dept.Label,
|
||||
Value: strconv.FormatInt(dept.Value, 10),
|
||||
Children: make([]*types.NestedValue[string], 0),
|
||||
}
|
||||
for _, user := range users {
|
||||
if strconv.FormatInt(user.DeptId, 10) == v.Value {
|
||||
v.Children = append(v.Children, &types.NestedValue[string]{
|
||||
Label: fmt.Sprintf("%s(%s)", user.Username, user.Uid),
|
||||
Value: user.Uid,
|
||||
})
|
||||
}
|
||||
}
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -281,5 +299,9 @@ func NewUserService(cbs ...UserOption) *UserService {
|
|||
}
|
||||
return &UserService{
|
||||
opts: opts,
|
||||
user: logic.NewUserLogic(opts.db),
|
||||
role: logic.NewRoleLogic(opts.db),
|
||||
menu: logic.NewMenuLogic(opts.db),
|
||||
department: logic.NewDepartmentLogic(opts.db),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue