nunu-layout-admin/internal/service/admin.go

466 lines
13 KiB
Go
Raw Normal View History

2025-03-24 05:55:56 +00:00
package service
import (
"context"
"errors"
"github.com/duke-git/lancet/v2/convertor"
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
v1 "nunu-layout-admin/api/v1"
"nunu-layout-admin/internal/model"
"nunu-layout-admin/internal/repository"
"strings"
"time"
)
type AdminService interface {
Login(ctx context.Context, req *v1.LoginRequest) (string, error)
GetAdminUsers(ctx context.Context, req *v1.GetAdminUsersRequest) (*v1.GetAdminUsersResponseData, error)
GetAdminUser(ctx context.Context, uid uint) (*v1.GetAdminUserResponseData, error)
AdminUserUpdate(ctx context.Context, req *v1.AdminUserUpdateRequest) error
AdminUserCreate(ctx context.Context, req *v1.AdminUserCreateRequest) error
AdminUserDelete(ctx context.Context, id uint) error
GetUserPermissions(ctx context.Context, uid uint) (*v1.GetUserPermissionsData, error)
GetRolePermissions(ctx context.Context, role string) (*v1.GetRolePermissionsData, error)
UpdateRolePermission(ctx context.Context, req *v1.UpdateRolePermissionRequest) error
GetAdminMenus(ctx context.Context) (*v1.GetMenuResponseData, error)
GetMenus(ctx context.Context, uid uint) (*v1.GetMenuResponseData, error)
MenuUpdate(ctx context.Context, req *v1.MenuUpdateRequest) error
MenuCreate(ctx context.Context, req *v1.MenuCreateRequest) error
MenuDelete(ctx context.Context, id uint) error
GetRoles(ctx context.Context, req *v1.GetRoleListRequest) (*v1.GetRolesResponseData, error)
RoleUpdate(ctx context.Context, req *v1.RoleUpdateRequest) error
RoleCreate(ctx context.Context, req *v1.RoleCreateRequest) error
RoleDelete(ctx context.Context, id uint) error
GetApis(ctx context.Context, req *v1.GetApisRequest) (*v1.GetApisResponseData, error)
ApiUpdate(ctx context.Context, req *v1.ApiUpdateRequest) error
ApiCreate(ctx context.Context, req *v1.ApiCreateRequest) error
ApiDelete(ctx context.Context, id uint) error
}
func NewAdminService(
service *Service,
adminRepository repository.AdminRepository,
) AdminService {
return &adminService{
Service: service,
adminRepository: adminRepository,
}
}
type adminService struct {
*Service
adminRepository repository.AdminRepository
}
func (s *adminService) GetAdminUser(ctx context.Context, uid uint) (*v1.GetAdminUserResponseData, error) {
user, err := s.adminRepository.GetAdminUser(ctx, uid)
if err != nil {
return nil, err
}
roles, _ := s.adminRepository.GetUserRoles(ctx, uid)
return &v1.GetAdminUserResponseData{
Email: user.Email,
ID: user.ID,
Username: user.Username,
Nickname: user.Nickname,
Phone: user.Phone,
Roles: roles,
CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: user.UpdatedAt.Format("2006-01-02 15:04:05"),
}, nil
}
func (s *adminService) Login(ctx context.Context, req *v1.LoginRequest) (string, error) {
user, err := s.adminRepository.GetAdminUserByUsername(ctx, req.Username)
if err != nil {
if err == gorm.ErrRecordNotFound {
return "", v1.ErrUnauthorized
}
return "", v1.ErrInternalServerError
}
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
if err != nil {
return "", err
}
token, err := s.jwt.GenToken(user.ID, time.Now().Add(time.Hour*24*90))
if err != nil {
return "", err
}
return token, nil
}
func (s *adminService) GetAdminUsers(ctx context.Context, req *v1.GetAdminUsersRequest) (*v1.GetAdminUsersResponseData, error) {
list, total, err := s.adminRepository.GetAdminUsers(ctx, req)
if err != nil {
return nil, err
}
data := &v1.GetAdminUsersResponseData{
List: make([]v1.AdminUserDataItem, 0),
Total: total,
}
for _, user := range list {
roles, err := s.adminRepository.GetUserRoles(ctx, user.ID)
if err != nil {
s.logger.Error("GetUserRoles error", zap.Error(err))
continue
}
data.List = append(data.List, v1.AdminUserDataItem{
Email: user.Email,
ID: user.ID,
Nickname: user.Nickname,
Username: user.Username,
Phone: user.Phone,
Roles: roles,
CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: user.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
return data, nil
}
func (s *adminService) AdminUserUpdate(ctx context.Context, req *v1.AdminUserUpdateRequest) error {
old, _ := s.adminRepository.GetAdminUser(ctx, req.ID)
if req.Password != "" {
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
req.Password = string(hash)
} else {
req.Password = old.Password
}
err := s.adminRepository.UpdateUserRoles(ctx, req.ID, req.Roles)
if err != nil {
return err
}
return s.adminRepository.AdminUserUpdate(ctx, &model.AdminUser{
Model: gorm.Model{
ID: req.ID,
},
Email: req.Email,
Nickname: req.Nickname,
Phone: req.Phone,
Username: req.Username,
})
}
func (s *adminService) AdminUserCreate(ctx context.Context, req *v1.AdminUserCreateRequest) error {
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
req.Password = string(hash)
err = s.adminRepository.AdminUserCreate(ctx, &model.AdminUser{
Email: req.Email,
Nickname: req.Nickname,
Phone: req.Phone,
Username: req.Username,
Password: req.Password,
})
if err != nil {
return err
}
user, err := s.adminRepository.GetAdminUserByUsername(ctx, req.Username)
if err != nil {
return err
}
err = s.adminRepository.UpdateUserRoles(ctx, user.ID, req.Roles)
if err != nil {
return err
}
return err
}
func (s *adminService) AdminUserDelete(ctx context.Context, id uint) error {
// 删除用户角色
err := s.adminRepository.DeleteUserRoles(ctx, id)
if err != nil {
return err
}
return s.adminRepository.AdminUserDelete(ctx, id)
}
func (s *adminService) UpdateRolePermission(ctx context.Context, req *v1.UpdateRolePermissionRequest) error {
permissions := map[string]struct{}{}
for _, v := range req.List {
perm := strings.Split(v, model.PermSep)
if len(perm) == 2 {
permissions[v] = struct{}{}
}
}
return s.adminRepository.UpdateRolePermission(ctx, req.Role, permissions)
}
func (s *adminService) GetApis(ctx context.Context, req *v1.GetApisRequest) (*v1.GetApisResponseData, error) {
list, total, err := s.adminRepository.GetApis(ctx, req)
if err != nil {
return nil, err
}
groups, err := s.adminRepository.GetApiGroups(ctx)
if err != nil {
return nil, err
}
data := &v1.GetApisResponseData{
List: make([]v1.ApiDataItem, 0),
Total: total,
Groups: groups,
}
for _, api := range list {
data.List = append(data.List, v1.ApiDataItem{
CreatedAt: api.CreatedAt.Format("2006-01-02 15:04:05"),
Group: api.Group,
ID: api.ID,
Method: api.Method,
Name: api.Name,
Path: api.Path,
UpdatedAt: api.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
return data, nil
}
func (s *adminService) ApiUpdate(ctx context.Context, req *v1.ApiUpdateRequest) error {
return s.adminRepository.ApiUpdate(ctx, &model.Api{
Group: req.Group,
Method: req.Method,
Name: req.Name,
Path: req.Path,
Model: gorm.Model{
ID: req.ID,
},
})
}
func (s *adminService) ApiCreate(ctx context.Context, req *v1.ApiCreateRequest) error {
return s.adminRepository.ApiCreate(ctx, &model.Api{
Group: req.Group,
Method: req.Method,
Name: req.Name,
Path: req.Path,
})
}
func (s *adminService) ApiDelete(ctx context.Context, id uint) error {
return s.adminRepository.ApiDelete(ctx, id)
}
func (s *adminService) GetUserPermissions(ctx context.Context, uid uint) (*v1.GetUserPermissionsData, error) {
data := &v1.GetUserPermissionsData{
List: []string{},
}
list, err := s.adminRepository.GetUserPermissions(ctx, uid)
if err != nil {
return nil, err
}
for _, v := range list {
if len(v) == 3 {
data.List = append(data.List, strings.Join([]string{v[1], v[2]}, model.PermSep))
}
}
return data, nil
}
func (s *adminService) GetRolePermissions(ctx context.Context, role string) (*v1.GetRolePermissionsData, error) {
data := &v1.GetRolePermissionsData{
List: []string{},
}
list, err := s.adminRepository.GetRolePermissions(ctx, role)
if err != nil {
return nil, err
}
for _, v := range list {
if len(v) == 3 {
data.List = append(data.List, strings.Join([]string{v[1], v[2]}, model.PermSep))
}
}
return data, nil
}
func (s *adminService) MenuUpdate(ctx context.Context, req *v1.MenuUpdateRequest) error {
return s.adminRepository.MenuUpdate(ctx, &model.Menu{
Component: req.Component,
Icon: req.Icon,
KeepAlive: req.KeepAlive,
HideInMenu: req.HideInMenu,
Locale: req.Locale,
Weight: req.Weight,
Name: req.Name,
ParentID: req.ParentID,
Path: req.Path,
Redirect: req.Redirect,
Title: req.Title,
URL: req.URL,
Model: gorm.Model{
ID: req.ID,
},
})
}
func (s *adminService) MenuCreate(ctx context.Context, req *v1.MenuCreateRequest) error {
return s.adminRepository.MenuCreate(ctx, &model.Menu{
Component: req.Component,
Icon: req.Icon,
KeepAlive: req.KeepAlive,
HideInMenu: req.HideInMenu,
Locale: req.Locale,
Weight: req.Weight,
Name: req.Name,
ParentID: req.ParentID,
Path: req.Path,
Redirect: req.Redirect,
Title: req.Title,
URL: req.URL,
})
}
func (s *adminService) MenuDelete(ctx context.Context, id uint) error {
return s.adminRepository.MenuDelete(ctx, id)
}
func (s *adminService) GetMenus(ctx context.Context, uid uint) (*v1.GetMenuResponseData, error) {
menuList, err := s.adminRepository.GetMenuList(ctx)
if err != nil {
s.logger.WithContext(ctx).Error("GetMenuList error", zap.Error(err))
return nil, err
}
data := &v1.GetMenuResponseData{
List: make([]v1.MenuDataItem, 0),
}
// 获取权限的菜单
permissions, err := s.adminRepository.GetUserPermissions(ctx, uid)
if err != nil {
return nil, err
}
menuPermMap := map[string]struct{}{}
for _, permission := range permissions {
// 防呆设置,超管可以看到所有菜单
if convertor.ToString(uid) == model.AdminUserID {
menuPermMap[strings.TrimPrefix(permission[1], model.MenuResourcePrefix)] = struct{}{}
} else {
if len(permission) == 3 && strings.HasPrefix(permission[1], model.MenuResourcePrefix) {
menuPermMap[strings.TrimPrefix(permission[1], model.MenuResourcePrefix)] = struct{}{}
}
}
}
for _, menu := range menuList {
if _, ok := menuPermMap[menu.Path]; ok {
data.List = append(data.List, v1.MenuDataItem{
ID: menu.ID,
Name: menu.Name,
Title: menu.Title,
Path: menu.Path,
Component: menu.Component,
Redirect: menu.Redirect,
KeepAlive: menu.KeepAlive,
HideInMenu: menu.HideInMenu,
Locale: menu.Locale,
Weight: menu.Weight,
Icon: menu.Icon,
ParentID: menu.ParentID,
UpdatedAt: menu.UpdatedAt.Format("2006-01-02 15:04:05"),
URL: menu.URL,
})
}
}
return data, nil
}
func (s *adminService) GetAdminMenus(ctx context.Context) (*v1.GetMenuResponseData, error) {
menuList, err := s.adminRepository.GetMenuList(ctx)
if err != nil {
s.logger.WithContext(ctx).Error("GetMenuList error", zap.Error(err))
return nil, err
}
data := &v1.GetMenuResponseData{
List: make([]v1.MenuDataItem, 0),
}
for _, menu := range menuList {
data.List = append(data.List, v1.MenuDataItem{
ID: menu.ID,
Name: menu.Name,
Title: menu.Title,
Path: menu.Path,
Component: menu.Component,
Redirect: menu.Redirect,
KeepAlive: menu.KeepAlive,
HideInMenu: menu.HideInMenu,
Locale: menu.Locale,
Weight: menu.Weight,
Icon: menu.Icon,
ParentID: menu.ParentID,
UpdatedAt: menu.UpdatedAt.Format("2006-01-02 15:04:05"),
URL: menu.URL,
})
}
return data, nil
}
func (s *adminService) RoleUpdate(ctx context.Context, req *v1.RoleUpdateRequest) error {
return s.adminRepository.RoleUpdate(ctx, &model.Role{
Name: req.Name,
Sid: req.Sid,
Model: gorm.Model{
ID: req.ID,
},
})
}
func (s *adminService) RoleCreate(ctx context.Context, req *v1.RoleCreateRequest) error {
_, err := s.adminRepository.GetRoleBySid(ctx, req.Sid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return s.adminRepository.RoleCreate(ctx, &model.Role{
Name: req.Name,
Sid: req.Sid,
})
} else {
return err
}
}
return nil
}
func (s *adminService) RoleDelete(ctx context.Context, id uint) error {
old, err := s.adminRepository.GetRole(ctx, id)
if err != nil {
return err
}
if err := s.adminRepository.CasbinRoleDelete(ctx, old.Sid); err != nil {
return err
}
return s.adminRepository.RoleDelete(ctx, id)
}
func (s *adminService) GetRoles(ctx context.Context, req *v1.GetRoleListRequest) (*v1.GetRolesResponseData, error) {
list, total, err := s.adminRepository.GetRoles(ctx, req)
if err != nil {
return nil, err
}
data := &v1.GetRolesResponseData{
List: make([]v1.RoleDataItem, 0),
Total: total,
}
for _, role := range list {
data.List = append(data.List, v1.RoleDataItem{
ID: role.ID,
Name: role.Name,
Sid: role.Sid,
UpdatedAt: role.UpdatedAt.Format("2006-01-02 15:04:05"),
CreatedAt: role.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
return data, nil
}