sync: 同步 v1.0.4 开源代码并脱敏
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
package rolesync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/consts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/dao"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/library/rolepolicy"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/model"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/model/do"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/model/entity"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func SyncInheritedRole(ctx context.Context, message *model.AgentRoleSyncMessage) error {
|
||||
if message == nil || message.SourceRoleId <= 0 || message.SourceDeptId <= 0 || message.TenantId == "" {
|
||||
return gerror.New("invalid agent role sync message")
|
||||
}
|
||||
template, templateErr := rolepolicy.Template(ctx)
|
||||
if templateErr != nil {
|
||||
return templateErr
|
||||
}
|
||||
if message.TemplateRole && (template == nil || message.SourceRoleId != template.RoleId) {
|
||||
message.Superseded = true
|
||||
return nil
|
||||
}
|
||||
if template != nil && message.SourceRoleId == template.RoleId && message.SourceDeptId == template.DeptId && (message.TenantId == template.TenantId || message.TenantId == "") {
|
||||
return syncTemplateRoles(ctx, template, message)
|
||||
}
|
||||
if template != nil {
|
||||
message.Superseded = true
|
||||
return nil
|
||||
}
|
||||
var source *entity.SysRole
|
||||
sourceModel := dao.SysRole.Ctx(ctx).Master().Where(dao.SysRole.Columns().RoleId, message.SourceRoleId)
|
||||
if message.TenantId != "" {
|
||||
sourceModel = sourceModel.Where(dao.SysRole.Columns().TenantId, message.TenantId)
|
||||
}
|
||||
if err := sourceModel.Scan(&source); err != nil {
|
||||
return err
|
||||
}
|
||||
if source == nil || source.IsPass != 1 || source.DeletedAt != nil {
|
||||
message.Superseded = true
|
||||
return nil
|
||||
}
|
||||
if message.SourceDeptId > 0 && message.SourceDeptId != source.DeptId {
|
||||
return gerror.New("role sync source department changed")
|
||||
}
|
||||
var children []*entity.SysDept
|
||||
if err := dao.SysDept.Ctx(ctx).Master().
|
||||
Where(dao.SysDept.Columns().TenantId, source.TenantId).
|
||||
Where(dao.SysDept.Columns().ParentId, source.DeptId).
|
||||
Where(dao.SysDept.Columns().DeptType, 1).
|
||||
Scan(&children); err != nil {
|
||||
return err
|
||||
}
|
||||
failed := 0
|
||||
if len(message.ChildDeptIds) == 0 {
|
||||
message.TotalCount = len(children)
|
||||
message.SuccessCount = 0
|
||||
}
|
||||
failedDeptIds := make([]int64, 0)
|
||||
var firstErr error
|
||||
for _, child := range children {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(message.ChildDeptIds) > 0 && !slices.Contains(message.ChildDeptIds, child.DeptId) {
|
||||
continue
|
||||
}
|
||||
err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
return syncInheritedRoleChildrenTx(ctx, tx, message.SourceRoleId, source.TenantId, source.DeptId, message.ActorId, child.DeptId)
|
||||
})
|
||||
if err != nil {
|
||||
failed++
|
||||
failedDeptIds = append(failedDeptIds, child.DeptId)
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
g.Log().Warningf(ctx, "agent role sync child failed, sourceRoleId:%d, childDeptId:%d, err:%v", source.RoleId, child.DeptId, err)
|
||||
} else {
|
||||
message.SuccessCount++
|
||||
}
|
||||
}
|
||||
message.ChildDeptIds = failedDeptIds
|
||||
message.FailedCount = len(failedDeptIds)
|
||||
if firstErr != nil {
|
||||
return gerror.Wrapf(firstErr, "agent role sync failed for %d of %d children", failed, len(children))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncInheritedRoleChildrenTx(ctx context.Context, tx gdb.TX, sourceRoleID int64, tenantId string, sourceDeptId, actorId, childDeptId int64) error {
|
||||
if sourceRoleID == 0 {
|
||||
return nil
|
||||
}
|
||||
var source *entity.SysRole
|
||||
sourceModel := tx.Ctx(ctx).Model(dao.SysRole.Table()).Where(dao.SysRole.Columns().RoleId, sourceRoleID)
|
||||
if tenantId != "" {
|
||||
sourceModel = sourceModel.Where(dao.SysRole.Columns().TenantId, tenantId)
|
||||
}
|
||||
if !strings.EqualFold(g.DB().GetConfig().Type, "sqlite") {
|
||||
sourceModel = sourceModel.LockUpdate()
|
||||
}
|
||||
if err := sourceModel.Scan(&source); err != nil {
|
||||
return err
|
||||
}
|
||||
if source == nil || source.RoleId == 0 || source.DeletedAt != nil || source.IsPass != 1 {
|
||||
return nil
|
||||
}
|
||||
if sourceDeptId > 0 && source.DeptId != sourceDeptId {
|
||||
return gerror.New("role sync source department changed")
|
||||
}
|
||||
var childDepts []*entity.SysDept
|
||||
childDeptModel := tx.Ctx(ctx).Model(dao.SysDept.Table()).Where(dao.SysDept.Columns().TenantId, source.TenantId).Where(dao.SysDept.Columns().ParentId, source.DeptId).Where(dao.SysDept.Columns().DeptType, 1).Where(dao.SysDept.Columns().DeptId, childDeptId)
|
||||
if !strings.EqualFold(g.DB().GetConfig().Type, "sqlite") {
|
||||
childDeptModel = childDeptModel.LockUpdate()
|
||||
}
|
||||
if err := childDeptModel.Scan(&childDepts); err != nil {
|
||||
return err
|
||||
}
|
||||
var menus []*entity.SysRoleMenu
|
||||
if err := tx.Ctx(ctx).Model(dao.SysRoleMenu.Table()).Where(dao.SysRoleMenu.Columns().RoleId, sourceRoleID).OrderAsc(dao.SysRoleMenu.Columns().MenuId).Scan(&menus); err != nil {
|
||||
return err
|
||||
}
|
||||
menuIDs := make([]int64, 0, len(menus))
|
||||
for _, menu := range menus {
|
||||
menuIDs = append(menuIDs, menu.MenuId)
|
||||
}
|
||||
allowed, err := rolepolicy.RestrictMenus(ctx, source.TenantId, source.DeptId, menuIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
template, templateErr := rolepolicy.Template(ctx)
|
||||
if templateErr != nil {
|
||||
return templateErr
|
||||
}
|
||||
filtered := make([]*entity.SysRoleMenu, 0, len(menus))
|
||||
for _, menu := range menus {
|
||||
if slices.Contains(allowed, menu.MenuId) {
|
||||
copy := *menu
|
||||
if template != nil {
|
||||
copy.DataScope = consts.SysRoleMenuDataScopeRole
|
||||
}
|
||||
filtered = append(filtered, ©)
|
||||
}
|
||||
}
|
||||
menus = filtered
|
||||
for _, childDept := range childDepts {
|
||||
var children []*entity.SysRole
|
||||
if err := tx.Ctx(ctx).Model(dao.SysRole.Table()+" r").
|
||||
Fields("r.*").
|
||||
Where("r.tenant_id", source.TenantId).
|
||||
Where("r.dept_id", childDept.DeptId).
|
||||
Where("r.created_dept", source.DeptId).
|
||||
Where("r.role_id", childDept.DeptRole).
|
||||
Scan(&children); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(children) > 1 {
|
||||
return gerror.Newf("multiple inherited roles in department %d for role %d", childDept.DeptId, source.RoleId)
|
||||
}
|
||||
if len(children) == 0 {
|
||||
var legacy *entity.SysRole
|
||||
if childDept.DeptRole > 0 {
|
||||
if err := tx.Ctx(ctx).Model(dao.SysRole.Table()).
|
||||
Where(dao.SysRole.Columns().RoleId, childDept.DeptRole).
|
||||
Where(dao.SysRole.Columns().DeptId, childDept.DeptId).
|
||||
Where(dao.SysRole.Columns().TenantId, source.TenantId).
|
||||
Scan(&legacy); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if legacy != nil && legacy.RoleId > 0 {
|
||||
if legacy.CreatedDept != source.DeptId || legacy.RoleKey != source.RoleKey {
|
||||
return gerror.Newf("cannot identify inherited role for department %d", childDept.DeptId)
|
||||
}
|
||||
children = []*entity.SysRole{legacy}
|
||||
} else {
|
||||
if childDept.DeptRole > 0 {
|
||||
return gerror.Newf("missing default role for department %d", childDept.DeptId)
|
||||
}
|
||||
return gerror.Newf("missing default role for department %d", childDept.DeptId)
|
||||
}
|
||||
}
|
||||
for _, child := range children {
|
||||
if _, err := tx.Ctx(ctx).Model(dao.SysRole.Table()).Where(dao.SysRole.Columns().RoleId, child.RoleId).Data(do.SysRole{RoleName: strings.TrimSpace(source.RoleName), RoleKey: source.RoleKey, RoleSort: source.RoleSort, DataScope: source.DataScope, MenuCheckStrictly: source.MenuCheckStrictly, DeptCheckStrictly: source.DeptCheckStrictly, Status: source.Status, Remark: source.Remark, UpdatedBy: actorId}).OmitNil().Update(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.Ctx(ctx).Model(dao.SysRoleMenu.Table()).Where(dao.SysRoleMenu.Columns().RoleId, child.RoleId).Delete(); err != nil {
|
||||
return err
|
||||
}
|
||||
menuData := make([]*do.SysRoleMenu, 0, len(menus))
|
||||
for _, menu := range menus {
|
||||
menuData = append(menuData, &do.SysRoleMenu{TenantId: source.TenantId, RoleId: child.RoleId, MenuId: menu.MenuId, DataScope: menu.DataScope})
|
||||
}
|
||||
if len(menuData) > 0 {
|
||||
if _, err := tx.Ctx(ctx).Model(dao.SysRoleMenu.Table()).Data(menuData).OmitNil().Batch(200).Insert(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user