@ -2,6 +2,7 @@ package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper ;
import cn.axzo.basics.common.constant.enums.DeleteEnum ;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum ;
import cn.axzo.basics.common.util.TreeUtil ;
import cn.axzo.basics.profiles.api.UserProfileServiceApi ;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto ;
@ -11,10 +12,12 @@ import cn.axzo.tyr.client.common.enums.FeatureResourceType;
import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum ;
import cn.axzo.tyr.client.model.enums.RolePermissionTagEnum ;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq ;
import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq ;
import cn.axzo.tyr.client.model.req.PageElementFeatureResourceRelationReq ;
import cn.axzo.tyr.client.model.req.PageElementReq ;
import cn.axzo.tyr.client.model.req.ResourceSyncReq ;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode ;
import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp ;
import cn.axzo.tyr.client.model.res.PageElementFeatureResourceRelationResp ;
import cn.axzo.tyr.client.model.res.PageElementResp ;
import cn.axzo.tyr.server.config.MqProducer ;
import cn.axzo.tyr.server.event.payload.RolePermissionCreatedPayload ;
import cn.axzo.tyr.server.event.payload.SaasFeatureResourceUpsertPayload ;
@ -32,7 +35,8 @@ import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelationOperateL
import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation ;
import cn.axzo.tyr.server.repository.entity.SaasRole ;
import cn.axzo.tyr.server.service.FeatureResourceSyncService ;
import cn.axzo.tyr.server.service.SaasFeatureResourceService ;
import cn.axzo.tyr.server.service.SaasPageElementFeatureResourceRelationService ;
import cn.axzo.tyr.server.service.SaasPageElementService ;
import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService ;
import cn.axzo.tyr.server.util.RpcInternalUtil ;
import cn.azxo.framework.common.constatns.Constants ;
@ -49,6 +53,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils ;
import org.apache.commons.lang3.StringUtils ;
import org.slf4j.MDC ;
import org.springframework.beans.BeanUtils ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.beans.factory.annotation.Qualifier ;
import org.springframework.stereotype.Service ;
@ -98,7 +103,8 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
private final SaasPgroupPermissionRelationOperateLogService saasPgroupPermissionRelationOperateLogService ;
private final UserProfileServiceApi userProfileServiceApi ;
private final SaasFeatureResourceService saasFeatureResourceService ;
private final SaasPageElementFeatureResourceRelationService saasPageElementFeatureResourceRelationService ;
private final SaasPageElementService saasPageElementService ;
@Qualifier ( " asyncExecutor " )
@Autowired
@ -139,6 +145,8 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
}
Map < Long , List < FeatureResourceTreeNode . Role > > featureResourceRoleCodeMap = getFeatureResourceRoleCodeMap ( allFeatureResourceIds ) ;
Map < String , List < PageElementFeatureResourceRelationResp > > pageElementMap = listPageElement ( resourceList ) ;
List < FeatureResourceTreeNode > dtoList = BeanMapper . copyList ( resourceList , FeatureResourceTreeNode . class ) ;
dtoList . forEach ( e - > {
List < FeatureResourceTreeNode . Role > roles = featureResourceRoleCodeMap . get ( e . getId ( ) ) ;
@ -150,20 +158,60 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
. distinct ( )
. collect ( Collectors . toList ( ) ) ) ;
e . setRoles ( roles ) ;
e . setPageElementFeatureResourceRelationResps ( pageElementMap . get ( e . getUniCode ( ) ) ) ;
} ) ;
return TreeUtil . buildTree ( dtoList ) ;
}
private Map < String , List < PageElementFeatureResourceRelationResp > > listPageElement ( List < SaasFeatureResource > resourceList ) {
if ( CollectionUtils . isEmpty ( resourceList ) ) {
return Collections . emptyMap ( ) ;
}
Set < String > uniCodes = resourceList . stream ( )
. map ( SaasFeatureResource : : getUniCode )
. collect ( Collectors . toSet ( ) ) ;
PageElementFeatureResourceRelationReq pageElementFeatureResourceRelationReq = PageElementFeatureResourceRelationReq . builder ( )
. featureResourceUniCodes ( uniCodes )
. needPageElement ( true )
. build ( ) ;
List < PageElementFeatureResourceRelationResp > pageElementFeatureResourceRelations = saasPageElementFeatureResourceRelationService . list ( pageElementFeatureResourceRelationReq ) ;
return pageElementFeatureResourceRelations . stream ( )
. filter ( e - > e . getPageElement ( ) ! = null )
. collect ( Collectors . groupingBy ( PageElementFeatureResourceRelationResp : : getFeatureResourceUniCode ) ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class )
public void syncFromBase ( ResourceSyncReq req ) {
/ / TODO 删除代码 , 同步处理 , 但是改的比较多
req . setTraceId ( MDC . get ( Constants . CTX_LOG_ID_MDC ) ) ;
if ( req . getIds ( ) . size ( ) > 1 ) {
/ / 超过一个异步处理
CompletableFuture . runAsync ( ( ) - > doSyncFromBase ( req ) , asyncExecutor ) . whenComplete ( ( t , ex ) - > saasFeatureResourceCacheService . clearCache ( ) ) ;
/ / 同步这里不要求效率 , 没有角色id , 全部刷新 , 也不容易找这个
Event event = Event . builder ( )
. targetType ( ROLE_PERMISSION_TARGET_TYPE )
. eventCode ( ROLE_PERMISSION_CREATED . getEventCode ( ) )
. data ( RolePermissionCreatedPayload . builder ( )
. build ( ) )
. build ( ) ;
mqProducer . send ( event ) ;
return ;
}
doSyncFromBase ( req ) ;
/ / 同步这里不要求效率 , 没有角色id , 全部刷新 , 也不容易找这个
Event event = Event . builder ( )
. targetType ( ROLE_PERMISSION_TARGET_TYPE )
. eventCode ( ROLE_PERMISSION_CREATED . getEventCode ( ) )
. data ( RolePermissionCreatedPayload . builder ( )
. build ( ) )
. build ( ) ;
mqProducer . send ( event ) ;
saasFeatureResourceCacheService . clearCache ( ) ;
}
@ -173,13 +221,14 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
/ / 处理数据缓存 : 避免同级节点上级重复处理 - 上级code查询
final Map < Long , String > codeCache = new ConcurrentHashMap < > ( ) ;
Set < Long > syncedRoleFeatureResourceIds = Sets . newConcurrentHashSet ( ) ;
Set < Long > syncedPageElementFeatureResourceIds = Sets . newConcurrentHashSet ( ) ;
Set < String > terminals = Sets . newHashSet ( ) ;
try {
for ( Long id : req . getIds ( ) ) {
/ / 获取基准环境配置数据 : 同步某个ID的数据 需要同步处理它所有上级及下级组件
List < FeatureResourceTreeNode > syncList = RpcInternalUtil . rpcProcessor ( ( ) - > baseFeatureResourceApi . getSyncTreeById ( id ) ,
" get base sync tree by id " , id ) . getData ( ) ;
syncResourceProcess ( syncList , codeCache , req . getOperatorId ( ) , operateDos , syncedRoleFeatureResourceIds );
syncResourceProcess ( syncList , codeCache , req . getOperatorId ( ) , operateDos , syncedRoleFeatureResourceIds , syncedPageElementFeatureResourceIds );
terminals . addAll ( syncList . stream ( )
. map ( FeatureResourceTreeNode : : getTerminal )
. collect ( Collectors . toSet ( ) ) ) ;
@ -236,7 +285,8 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
}
private void syncResourceProcess ( List < FeatureResourceTreeNode > syncList , Map < Long , String > codeCache , Long operatorId ,
List < RelationOperateLogResourceBindRoleDO > operateDos , Set < Long > syncedRoleFeatureResourceIds ) {
List < RelationOperateLogResourceBindRoleDO > operateDos , Set < Long > syncedRoleFeatureResourceIds ,
Set < Long > syncedPageElementFeatureResourceIds ) {
for ( FeatureResourceTreeNode treeNode : syncList ) {
if ( codeCache . containsKey ( treeNode . getId ( ) ) ) {
@ -244,7 +294,7 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
log . info ( " already sync resource:{} " , treeNode . getId ( ) ) ;
/ / 递归子节点
if ( CollectionUtils . isNotEmpty ( treeNode . getChildren ( ) ) ) {
syncResourceProcess ( treeNode . getChildren ( ) , codeCache , operatorId , operateDos , syncedRoleFeatureResourceIds );
syncResourceProcess ( treeNode . getChildren ( ) , codeCache , operatorId , operateDos , syncedRoleFeatureResourceIds , syncedRoleFeatureResourceIds );
}
continue ;
}
@ -305,9 +355,13 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
operateDos . add ( logResourceBindRoleDO ) ;
}
RelationOperateLogResourceBindRoleDO relationOperateLogResourceBindRoleDO = syncPageElement ( baseResource , treeNode , operatorId , syncedPageElementFeatureResourceIds ) ;
if ( Objects . nonNull ( relationOperateLogResourceBindRoleDO ) ) {
operateDos . add ( relationOperateLogResourceBindRoleDO ) ;
}
/ / 递归子节点
if ( CollectionUtils . isNotEmpty ( treeNode . getChildren ( ) ) ) {
syncResourceProcess ( treeNode . getChildren ( ) , codeCache , operatorId , operateDos , syncedRoleFeatureResourceIds ) ;
syncResourceProcess ( treeNode . getChildren ( ) , codeCache , operatorId , operateDos , syncedRoleFeatureResourceIds , syncedPageElementFeatureResourceIds );
}
}
}
@ -408,15 +462,73 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
logResourceBindRoleDO . setRoleCodes ( saasRoles . stream ( ) . filter ( e - > existRoleIds . contains ( e . getId ( ) ) ) . map ( SaasRole : : getRoleCode ) . collect ( Collectors . toList ( ) ) ) ;
}
return logResourceBindRoleDO ;
}
/ / 同步这里不要求效率 , 没有角色id , 全部刷新 , 也不容易找这个
Event event = Event . builder ( )
. targetType ( ROLE_PERMISSION_TARGET_TYPE )
. eventCode ( ROLE_PERMISSION_CREATED . getEventCode ( ) )
. data ( RolePermissionCreatedPayload . builder ( )
. build ( ) )
private RelationOperateLogResourceBindRoleDO syncPageElement ( SaasFeatureResource featureResource ,
FeatureResourceTreeNode treeNode ,
Long operatorId ,
Set < Long > syncedPageElementFeatureResourceIds ) {
if ( Objects . isNull ( featureResource ) ) {
return null ;
}
/ / 同一FeatureResource如果已经处理过前端资源同步 , 不再进行再次处理 。
if ( syncedPageElementFeatureResourceIds . contains ( featureResource . getId ( ) ) ) {
log . warn ( " sync role bind has handled,feature resource id:{} " , featureResource . getId ( ) ) ;
return null ;
}
syncedPageElementFeatureResourceIds . add ( featureResource . getId ( ) ) ;
/ / 先清除资源绑定的角色 @20240723 产品武艳华要求资源绑定的前端资源以PRE角色为准 ;
List < PageElementFeatureResourceRelationResp > oldData = saasPageElementFeatureResourceRelationService . list ( PageElementFeatureResourceRelationReq . builder ( )
. featureResourceUniCodes ( Sets . newHashSet ( featureResource . getUniCode ( ) ) )
. build ( ) ) ;
if ( CollectionUtils . isNotEmpty ( oldData ) ) {
log . warn ( " sync menu delete PageElementFeatureResourceRelation operateId:{} featureResourceId:{}, PageElementFeatureResourceRelationIds:{} " , operatorId , featureResource . getId ( ) , oldData . stream ( ) . map ( PageElementFeatureResourceRelationResp : : getId ) . collect ( Collectors . toList ( ) ) ) ;
saasPageElementFeatureResourceRelationDao . lambdaUpdate ( )
. in ( SaasPageElementFeatureResourceRelation : : getId , Lists . transform ( oldData , PageElementFeatureResourceRelationResp : : getId ) )
. set ( SaasPageElementFeatureResourceRelation : : getUpdateBy , operatorId )
. set ( SaasPageElementFeatureResourceRelation : : getIsDelete , TableIsDeleteEnum . DELETE . value )
. update ( ) ;
}
/ / 操作日志
RelationOperateLogResourceBindRoleDO logResourceBindRoleDO = RelationOperateLogResourceBindRoleDO . builder ( )
. uniCode ( featureResource . getUniCode ( ) )
. build ( ) ;
mqProducer . send ( event ) ;
Set < String > pageElementCodes = CollectionUtils . emptyIfNull ( treeNode . getPageElementFeatureResourceRelationResps ( ) ) . stream ( )
. map ( PageElementFeatureResourceRelationResp : : getPageElementCode )
. filter ( StringUtils : : isNotBlank )
. collect ( Collectors . toSet ( ) ) ;
if ( CollectionUtils . isEmpty ( pageElementCodes ) ) {
return logResourceBindRoleDO ;
}
Set < String > localPageElementCodes = saasPageElementService . list ( PageElementReq . builder ( )
. codes ( pageElementCodes )
. build ( ) )
. stream ( )
. map ( PageElementResp : : getCode )
. collect ( Collectors . toSet ( ) ) ;
if ( CollectionUtils . isEmpty ( localPageElementCodes ) ) {
return logResourceBindRoleDO ;
}
/ / 只关联本地已经有的前端资源code
List < SaasPageElementFeatureResourceRelation > inserts = treeNode . getPageElementFeatureResourceRelationResps ( ) . stream ( )
. filter ( e - > localPageElementCodes . contains ( e . getPageElementCode ( ) ) )
. map ( e - > {
SaasPageElementFeatureResourceRelation result = SaasPageElementFeatureResourceRelation . builder ( ) . build ( ) ;
BeanUtils . copyProperties ( e , result ) ;
result . setId ( null ) ;
return result ;
} )
. collect ( Collectors . toList ( ) ) ;
saasPageElementFeatureResourceRelationDao . saveBatch ( inserts ) ;
return logResourceBindRoleDO ;
}
@ -475,6 +587,7 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
return null ;
}
return saasRoles . stream ( )
. filter ( Objects : : nonNull )
. map ( role - > PermissionGroupRoleWrapper . builder ( )
. featureId ( e . getFeatureId ( ) )
. roleCode ( role . getRoleCode ( ) )