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, } }