2021-06-07 17:22:07 +08:00
|
|
|
|
package application
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2023-11-07 21:05:21 +08:00
|
|
|
|
"context"
|
2023-10-12 21:50:55 +08:00
|
|
|
|
"mayfly-go/internal/common/consts"
|
2024-11-20 22:43:53 +08:00
|
|
|
|
"mayfly-go/internal/sys/application/dto"
|
2022-06-02 17:41:11 +08:00
|
|
|
|
"mayfly-go/internal/sys/domain/entity"
|
|
|
|
|
|
"mayfly-go/internal/sys/domain/repository"
|
2024-11-20 22:43:53 +08:00
|
|
|
|
"mayfly-go/internal/sys/imsg"
|
2023-10-26 17:15:49 +08:00
|
|
|
|
"mayfly-go/pkg/base"
|
|
|
|
|
|
"mayfly-go/pkg/errorx"
|
2024-04-28 23:45:57 +08:00
|
|
|
|
"mayfly-go/pkg/model"
|
2024-04-29 12:29:56 +08:00
|
|
|
|
"mayfly-go/pkg/utils/collx"
|
2023-07-21 17:07:04 +08:00
|
|
|
|
"mayfly-go/pkg/utils/stringx"
|
2021-06-07 17:22:07 +08:00
|
|
|
|
"strings"
|
2023-06-15 19:18:29 +08:00
|
|
|
|
"time"
|
2021-06-07 17:22:07 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2021-07-28 18:03:19 +08:00
|
|
|
|
type Resource interface {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
base.App[*entity.Resource]
|
2021-06-07 17:22:07 +08:00
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
Save(ctx context.Context, entity *entity.Resource) error
|
2021-06-07 17:22:07 +08:00
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
Delete(ctx context.Context, id uint64) error
|
2021-06-07 17:22:07 +08:00
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
ChangeStatus(ctx context.Context, resourceId uint64, status int8) error
|
2023-06-15 19:18:29 +08:00
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
Sort(ctx context.Context, re *entity.Resource) error
|
2023-06-15 19:18:29 +08:00
|
|
|
|
|
2023-10-26 17:15:49 +08:00
|
|
|
|
GetAccountResources(accountId uint64, toEntity any) error
|
2024-11-20 22:43:53 +08:00
|
|
|
|
|
|
|
|
|
|
GetResourceRoles(resourceId uint64) ([]*dto.ResourceRole, error)
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-09 18:26:08 +08:00
|
|
|
|
type resourceAppImpl struct {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
base.AppImpl[*entity.Resource, repository.Resource]
|
2024-04-28 23:45:57 +08:00
|
|
|
|
|
|
|
|
|
|
roleResourceRepo repository.RoleResource `inject:"RoleResourceRepo"`
|
2024-11-20 22:43:53 +08:00
|
|
|
|
roleApp Role `inject:"RoleApp"`
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-20 22:43:53 +08:00
|
|
|
|
var _ (Resource) = (*resourceAppImpl)(nil)
|
|
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
func (r *resourceAppImpl) Save(ctx context.Context, resource *entity.Resource) error {
|
2023-06-15 19:18:29 +08:00
|
|
|
|
// 更新操作
|
2021-06-07 17:22:07 +08:00
|
|
|
|
if resource.Id != 0 {
|
|
|
|
|
|
if resource.Code != "" {
|
2024-05-05 14:53:30 +08:00
|
|
|
|
oldRes, err := r.GetById(resource.Id, "Code")
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err != nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBiz("Resource does not exist")
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2021-06-07 17:22:07 +08:00
|
|
|
|
// 如果修改了code,则校验新code是否存在
|
|
|
|
|
|
if oldRes.Code != resource.Code {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
if err := r.checkCode(ctx, resource.Code); err != nil {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-07 21:05:21 +08:00
|
|
|
|
return r.UpdateById(ctx, resource)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成随机八位唯一标识符
|
2023-07-21 17:07:04 +08:00
|
|
|
|
ui := stringx.Rand(8)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
if pid := resource.Pid; pid != 0 {
|
2024-05-05 14:53:30 +08:00
|
|
|
|
pResource, err := r.GetById(uint64(pid))
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err != nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBiz("pid does not exist")
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2023-06-15 19:18:29 +08:00
|
|
|
|
resource.UiPath = pResource.UiPath + ui + entity.ResourceUiPathSp
|
2021-06-07 17:22:07 +08:00
|
|
|
|
} else {
|
2023-06-15 19:18:29 +08:00
|
|
|
|
resource.UiPath = ui + entity.ResourceUiPathSp
|
|
|
|
|
|
}
|
|
|
|
|
|
// 默认启用状态
|
|
|
|
|
|
if resource.Status == 0 {
|
|
|
|
|
|
resource.Status = entity.ResourceStatusEnable
|
|
|
|
|
|
}
|
2024-11-20 22:43:53 +08:00
|
|
|
|
if err := r.checkCode(ctx, resource.Code); err != nil {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
2023-06-15 19:18:29 +08:00
|
|
|
|
resource.Weight = int(time.Now().Unix())
|
2023-11-07 21:05:21 +08:00
|
|
|
|
return r.Insert(ctx, resource)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
func (r *resourceAppImpl) ChangeStatus(ctx context.Context, resourceId uint64, status int8) error {
|
2024-05-05 14:53:30 +08:00
|
|
|
|
resource, err := r.GetById(resourceId)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err != nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBiz("Resource does not exist")
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2023-06-15 19:18:29 +08:00
|
|
|
|
resource.Status = status
|
2023-10-26 17:15:49 +08:00
|
|
|
|
return r.GetRepo().UpdateByUiPathLike(resource)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
func (r *resourceAppImpl) Sort(ctx context.Context, sortResource *entity.Resource) error {
|
2024-05-05 14:53:30 +08:00
|
|
|
|
resource, err := r.GetById(sortResource.Id)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err != nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBiz("Resource does not exist")
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-06-15 19:18:29 +08:00
|
|
|
|
// 未改变父节点,则更新排序值即可
|
|
|
|
|
|
if sortResource.Pid == resource.Pid {
|
|
|
|
|
|
saveE := &entity.Resource{Weight: sortResource.Weight}
|
|
|
|
|
|
saveE.Id = sortResource.Id
|
2023-11-07 21:05:21 +08:00
|
|
|
|
return r.Save(ctx, saveE)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 若资源原本唯一标识路径为:xxxx/yyyy/zzzz/,则获取其父节点路径标识 xxxx/yyyy/ 与自身节点标识 zzzz/
|
|
|
|
|
|
splitStr := strings.Split(resource.UiPath, entity.ResourceUiPathSp)
|
|
|
|
|
|
// 获取 zzzz/
|
|
|
|
|
|
resourceUi := splitStr[len(splitStr)-2] + entity.ResourceUiPathSp
|
|
|
|
|
|
// 获取父资源路径 xxxx/yyyy/
|
|
|
|
|
|
var parentResourceUiPath string
|
|
|
|
|
|
if len(splitStr) > 2 {
|
|
|
|
|
|
parentResourceUiPath = strings.Split(resource.UiPath, resourceUi)[0]
|
|
|
|
|
|
} else {
|
|
|
|
|
|
parentResourceUiPath = resourceUi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
newParentResourceUiPath := ""
|
|
|
|
|
|
if sortResource.Pid != 0 {
|
2024-05-05 14:53:30 +08:00
|
|
|
|
newParentResource, err := r.GetById(uint64(sortResource.Pid))
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err != nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBiz("pid does not exist")
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2023-06-15 19:18:29 +08:00
|
|
|
|
newParentResourceUiPath = newParentResource.UiPath
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 17:15:49 +08:00
|
|
|
|
children := r.GetRepo().GetChildren(resource.UiPath)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
for _, v := range children {
|
|
|
|
|
|
if v.Id == sortResource.Id {
|
|
|
|
|
|
continue
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
2023-06-15 19:18:29 +08:00
|
|
|
|
updateUiPath := &entity.Resource{}
|
|
|
|
|
|
updateUiPath.Id = v.Id
|
|
|
|
|
|
if parentResourceUiPath == resourceUi {
|
|
|
|
|
|
updateUiPath.UiPath = newParentResourceUiPath + v.UiPath
|
|
|
|
|
|
} else {
|
|
|
|
|
|
updateUiPath.UiPath = strings.ReplaceAll(v.UiPath, parentResourceUiPath, newParentResourceUiPath)
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
2023-11-07 21:05:21 +08:00
|
|
|
|
r.Save(ctx, updateUiPath)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新零值使用map,因为pid=0表示根节点
|
2024-04-29 12:29:56 +08:00
|
|
|
|
updateMap := collx.M{
|
2023-06-15 19:18:29 +08:00
|
|
|
|
"pid": sortResource.Pid,
|
|
|
|
|
|
"weight": sortResource.Weight,
|
|
|
|
|
|
"ui_path": newParentResourceUiPath + resourceUi,
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
2023-06-15 19:18:29 +08:00
|
|
|
|
condition := new(entity.Resource)
|
|
|
|
|
|
condition.Id = sortResource.Id
|
2024-04-29 12:29:56 +08:00
|
|
|
|
return r.UpdateByCond(ctx, updateMap, condition)
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-20 22:43:53 +08:00
|
|
|
|
func (r *resourceAppImpl) checkCode(ctx context.Context, code string) error {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if strings.Contains(code, ",") {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBizI(ctx, imsg.ErrResourceCodeInvalid)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2024-04-28 23:45:57 +08:00
|
|
|
|
if r.CountByCond(&entity.Resource{Code: code}) != 0 {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBizI(ctx, imsg.ErrResourceCodeExist)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
return nil
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
func (r *resourceAppImpl) Delete(ctx context.Context, id uint64) error {
|
2024-05-05 14:53:30 +08:00
|
|
|
|
resource, err := r.GetById(id)
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err != nil {
|
2024-11-20 22:43:53 +08:00
|
|
|
|
return errorx.NewBiz("Resource does not exist")
|
2023-10-26 17:15:49 +08:00
|
|
|
|
}
|
2023-06-15 19:18:29 +08:00
|
|
|
|
|
|
|
|
|
|
// 删除当前节点及其所有子节点
|
2023-10-26 17:15:49 +08:00
|
|
|
|
children := r.GetRepo().GetChildren(resource.UiPath)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
for _, v := range children {
|
2023-11-07 21:05:21 +08:00
|
|
|
|
r.GetRepo().DeleteById(ctx, v.Id)
|
2023-06-15 19:18:29 +08:00
|
|
|
|
// 删除角色关联的资源信息
|
2024-04-28 23:45:57 +08:00
|
|
|
|
return r.roleResourceRepo.DeleteByCond(ctx, &entity.RoleResource{ResourceId: v.Id})
|
2023-06-15 19:18:29 +08:00
|
|
|
|
}
|
2023-10-26 17:15:49 +08:00
|
|
|
|
return nil
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 17:15:49 +08:00
|
|
|
|
func (r *resourceAppImpl) GetAccountResources(accountId uint64, toEntity any) error {
|
2023-10-12 21:50:55 +08:00
|
|
|
|
// 超级管理员返回所有
|
|
|
|
|
|
if accountId == consts.AdminId {
|
|
|
|
|
|
cond := &entity.Resource{
|
|
|
|
|
|
Status: entity.ResourceStatusEnable,
|
|
|
|
|
|
}
|
2024-05-05 14:53:30 +08:00
|
|
|
|
return r.ListByCondToAny(model.NewModelCond(cond).OrderByAsc("pid").OrderByAsc("weight"), toEntity)
|
2023-10-12 21:50:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 17:15:49 +08:00
|
|
|
|
return r.GetRepo().GetAccountResources(accountId, toEntity)
|
2021-06-07 17:22:07 +08:00
|
|
|
|
}
|
2024-11-20 22:43:53 +08:00
|
|
|
|
|
|
|
|
|
|
func (r *resourceAppImpl) GetResourceRoles(resourceId uint64) ([]*dto.ResourceRole, error) {
|
|
|
|
|
|
rr, err := r.roleApp.GetResourceRoles(resourceId)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
roleId2Rr := collx.ArrayToMap[*entity.RoleResource, uint64](rr, func(val *entity.RoleResource) uint64 { return val.RoleId })
|
|
|
|
|
|
|
|
|
|
|
|
roleIds := collx.MapKeys(roleId2Rr)
|
|
|
|
|
|
roles, err := r.roleApp.GetByIds(roleIds)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return collx.ArrayMap[*entity.Role, *dto.ResourceRole](roles, func(val *entity.Role) *dto.ResourceRole {
|
|
|
|
|
|
role := roleId2Rr[val.Id]
|
|
|
|
|
|
return &dto.ResourceRole{
|
|
|
|
|
|
RoleId: val.Id,
|
|
|
|
|
|
RoleName: val.Name,
|
|
|
|
|
|
RoleCode: val.Code,
|
|
|
|
|
|
RoleStatus: val.Status,
|
|
|
|
|
|
AllocateTime: role.CreateTime,
|
|
|
|
|
|
Assigner: role.Creator,
|
|
|
|
|
|
}
|
|
|
|
|
|
}), nil
|
|
|
|
|
|
}
|