feat:(REQ-2720) 增加角色权限、产品权限事件和消费缓存
This commit is contained in:
parent
eb73fc41b4
commit
e7c6dd2f92
@ -9,6 +9,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ -30,4 +31,13 @@ public class PageProductFeatureRelationReq implements IPageReq {
|
||||
|
||||
@CriteriaField(field = "id", operator = Operator.IN)
|
||||
private List<Long> ids;
|
||||
|
||||
/**
|
||||
* 产品 ID
|
||||
*/
|
||||
@CriteriaField(field = "productModuleId", operator = Operator.IN)
|
||||
private Set<Long> productModuleIds;
|
||||
|
||||
@CriteriaField(field = "type", operator = Operator.EQ)
|
||||
private Integer type;
|
||||
}
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
package cn.axzo.tyr.server.config;
|
||||
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventProducer;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RefreshScope
|
||||
public class MqProducer {
|
||||
|
||||
@Autowired
|
||||
private EventProducer<?> eventProducer;
|
||||
|
||||
@Value("${sendMq}")
|
||||
private Boolean sendMq;
|
||||
|
||||
public void send(Event event){
|
||||
log.info(JSON.toJSONString(event));
|
||||
if(sendMq != null && !sendMq){
|
||||
return;
|
||||
}
|
||||
//生产消息
|
||||
eventProducer.send(event);
|
||||
}
|
||||
|
||||
public void sendBatch(List<Event> events){
|
||||
events.forEach(this::send);
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,25 @@ public class RocketMQEventConfiguration {
|
||||
consumeMode = ConsumeMode.ORDERLY,
|
||||
nameServer = "${rocketmq.name-server}"
|
||||
)
|
||||
public static class DefaultListener extends BaseListener implements RocketMQListener<MessageExt> {
|
||||
public static class ThronesListener extends BaseListener implements RocketMQListener<MessageExt> {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@Override
|
||||
public void onMessage(MessageExt message) {
|
||||
super.onEvent(message, eventConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(topic = "topic_tyr_${spring.profiles.active}",
|
||||
consumerGroup = "GID_topic_tyr_${spring.application.name}_${spring.profiles.active}",
|
||||
consumeMode = ConsumeMode.ORDERLY,
|
||||
nameServer = "${rocketmq.name-server}"
|
||||
)
|
||||
public static class TyrListener extends BaseListener implements RocketMQListener<MessageExt> {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
|
||||
@ -0,0 +1,193 @@
|
||||
package cn.axzo.tyr.server.event.inner;
|
||||
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||
import cn.axzo.framework.rocketmq.EventHandler;
|
||||
import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq;
|
||||
import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq;
|
||||
import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp;
|
||||
import cn.axzo.tyr.server.event.payload.ProductPermissionCreatedPayload;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasFeature;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation;
|
||||
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
|
||||
import cn.axzo.tyr.server.service.ProductPermissionCacheService;
|
||||
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE;
|
||||
import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.OLD_FEATURE;
|
||||
|
||||
/**
|
||||
* 缓存产品的权限
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CacheProductPermissionHandler implements EventHandler, InitializingBean {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
@Autowired
|
||||
private ProductPermissionCacheService productPermissionCacheService;
|
||||
@Autowired
|
||||
private ProductFeatureRelationService productFeatureRelationService;
|
||||
@Autowired
|
||||
private SaasFeatureResourceService saasFeatureResourceService;
|
||||
@Autowired
|
||||
private SaasFeatureDao saasFeatureDao;
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event, EventConsumer.Context context) {
|
||||
log.info("begin cached product permission handler rocketmq event: {}", event);
|
||||
ProductPermissionCreatedPayload payload = event.normalizedData(ProductPermissionCreatedPayload.class);
|
||||
|
||||
if (CollectionUtils.isEmpty(payload.getProductModuleIds())) {
|
||||
return;
|
||||
}
|
||||
|
||||
PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder()
|
||||
.productModuleIds(payload.getProductModuleIds())
|
||||
.build();
|
||||
List<SaasProductModuleFeatureRelation> productFeatures = productFeatureRelationService.list(pageProductFeatureRelationReq);
|
||||
|
||||
if (CollectionUtils.isEmpty(productFeatures)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<ProductPermissionCacheService.ProductPermission> productPermissions = resolveProductPermissions(productFeatures);
|
||||
|
||||
if (CollectionUtils.isEmpty(productPermissions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProductPermissionCacheService.StoreProductPermissionParam storeProductPermissionParam = ProductPermissionCacheService.StoreProductPermissionParam.builder()
|
||||
.productPermissions(productPermissions)
|
||||
.build();
|
||||
productPermissionCacheService.store(storeProductPermissionParam);
|
||||
|
||||
log.info("end cached product permission handler rocketmq event: {}", event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
eventConsumer.registerHandler(EventTypeEnum.PRODUCT_PERMISSION_CREATED.getEventCode(), this);
|
||||
}
|
||||
|
||||
public List<ProductPermissionCacheService.ProductPermission> resolveProductPermissions(List<SaasProductModuleFeatureRelation> productPermissions) {
|
||||
if (CollectionUtils.isEmpty(productPermissions)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Map<Long, SaasFeatureResourceResp> featureResources = listSaasFeatureResource(productPermissions);
|
||||
|
||||
Map<Long, SaasFeature> saasFeatures = listSaasFeature(productPermissions);
|
||||
|
||||
return productPermissions.stream()
|
||||
.collect(Collectors.groupingBy(SaasProductModuleFeatureRelation::getProductModuleId))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(e -> {
|
||||
List<SaasProductModuleFeatureRelation> productFeatureRelations = e.getValue();
|
||||
|
||||
if (CollectionUtils.isEmpty(productFeatureRelations)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ProductPermissionCacheService.PermissionDTO> permissions = productFeatureRelations.stream()
|
||||
.map(relation -> {
|
||||
if (Objects.equals(relation.getType(), NEW_FEATURE)) {
|
||||
SaasFeatureResourceResp featureResource = featureResources.get(relation.getFeatureId());
|
||||
if (Objects.isNull(featureResource) || CollectionUtils.isEmpty(featureResource.getFeatureCodes())) {
|
||||
return null;
|
||||
}
|
||||
return featureResource.getFeatureCodes().stream()
|
||||
.map(featureCode -> ProductPermissionCacheService.PermissionDTO.builder()
|
||||
.featureId(featureResource.getId())
|
||||
.featureCode(featureCode)
|
||||
.featureType(featureResource.getFeatureType())
|
||||
.terminal(featureResource.getTerminal())
|
||||
.cooperateType(relation.getDictCode())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
SaasFeature saasFeature = saasFeatures.get(relation.getFeatureId());
|
||||
if (Objects.isNull(saasFeature)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Lists.newArrayList(ProductPermissionCacheService.PermissionDTO.builder()
|
||||
.featureId(saasFeature.getId())
|
||||
.featureCode(saasFeature.getFeatureCode())
|
||||
.featureType(saasFeature.getFeatureType())
|
||||
.terminal(saasFeature.getTerminal())
|
||||
.cooperateType(relation.getDictCode())
|
||||
.build());
|
||||
})
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(permissions)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ProductPermissionCacheService.ProductPermission.builder()
|
||||
.productId(e.getKey())
|
||||
.permissions(permissions)
|
||||
.build();
|
||||
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
private Map<Long, SaasFeatureResourceResp> listSaasFeatureResource(List<SaasProductModuleFeatureRelation> productPermissions) {
|
||||
|
||||
List<Long> featureIds = productPermissions.stream()
|
||||
.filter(e -> Objects.equals(e.getType(), NEW_FEATURE))
|
||||
.map(SaasProductModuleFeatureRelation::getFeatureId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(featureIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder()
|
||||
.ids(featureIds)
|
||||
.needFeatureCodes(true)
|
||||
.build();
|
||||
return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream()
|
||||
.collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity()));
|
||||
}
|
||||
|
||||
private Map<Long, SaasFeature> listSaasFeature(List<SaasProductModuleFeatureRelation> productPermissions) {
|
||||
|
||||
List<Long> featureIds = productPermissions.stream()
|
||||
.filter(e -> Objects.equals(e.getType(), OLD_FEATURE))
|
||||
.map(SaasProductModuleFeatureRelation::getFeatureId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(featureIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
return saasFeatureDao.listByIds(featureIds).stream()
|
||||
.collect(Collectors.toMap(SaasFeature::getId, Function.identity()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,189 @@
|
||||
package cn.axzo.tyr.server.event.inner;
|
||||
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||
import cn.axzo.framework.rocketmq.EventHandler;
|
||||
import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq;
|
||||
import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp;
|
||||
import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes;
|
||||
import cn.axzo.tyr.client.model.res.SaasRoleRes;
|
||||
import cn.axzo.tyr.server.event.payload.RolePermissionCreatedPayload;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasFeature;
|
||||
import cn.axzo.tyr.server.service.RolePermissionCacheService;
|
||||
import cn.axzo.tyr.server.service.RoleService;
|
||||
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE;
|
||||
import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.OLD_FEATURE;
|
||||
|
||||
/**
|
||||
* 缓存角色的权限
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CacheRolePermissionHandler implements EventHandler, InitializingBean {
|
||||
|
||||
@Autowired
|
||||
private EventConsumer eventConsumer;
|
||||
@Autowired
|
||||
private RolePermissionCacheService rolePermissionCacheService;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
@Autowired
|
||||
private SaasFeatureResourceService saasFeatureResourceService;
|
||||
@Autowired
|
||||
private SaasFeatureDao saasFeatureDao;
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event, EventConsumer.Context context) {
|
||||
log.info("begin cached role permission handler rocketmq event: {}", event);
|
||||
RolePermissionCreatedPayload payload = event.normalizedData(RolePermissionCreatedPayload.class);
|
||||
|
||||
if (CollectionUtils.isEmpty(payload.getRoleIds())) {
|
||||
return;
|
||||
}
|
||||
|
||||
RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder()
|
||||
.roleIds(Lists.newArrayList(payload.getRoleIds()))
|
||||
.needPermissionRelation(true)
|
||||
.build();
|
||||
List<SaasRoleRes> roles = roleService.list(listSaasRoleParam);
|
||||
|
||||
if (CollectionUtils.isEmpty(roles)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<RolePermissionCacheService.RolePermission> rolePermissions = resolveRolePermission(roles);
|
||||
|
||||
if (CollectionUtils.isEmpty(rolePermissions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RolePermissionCacheService.StoreRolePermissionParam storeRolePermissionParam = RolePermissionCacheService.StoreRolePermissionParam.builder()
|
||||
.rolePermissions(rolePermissions)
|
||||
.build();
|
||||
rolePermissionCacheService.store(storeRolePermissionParam);
|
||||
log.info("end cached role permission handler rocketmq event: {}", event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
eventConsumer.registerHandler(EventTypeEnum.ROLE_PERMISSION_CREATED.getEventCode(), this);
|
||||
}
|
||||
|
||||
public List<RolePermissionCacheService.RolePermission> resolveRolePermission(List<SaasRoleRes> roles) {
|
||||
|
||||
|
||||
Map<Long, SaasFeatureResourceResp> featureResources = listSaasFeatureResource(roles);
|
||||
|
||||
Map<Long, SaasFeature> saasFeatures = listSaasFeature(roles);
|
||||
|
||||
return roles.stream()
|
||||
.map(e -> {
|
||||
if (CollectionUtils.isEmpty(e.getPermissionRelations())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<RolePermissionCacheService.PermissionDTO> permissions = e.getPermissionRelations().stream()
|
||||
.map(permissionRelation -> {
|
||||
if (Objects.equals(permissionRelation.getType(), NEW_FEATURE)) {
|
||||
SaasFeatureResourceResp featureResource = featureResources.get(permissionRelation.getFeatureId());
|
||||
if (Objects.isNull(featureResource) || CollectionUtils.isEmpty(featureResource.getFeatureCodes())) {
|
||||
return null;
|
||||
}
|
||||
return featureResource.getFeatureCodes().stream()
|
||||
.map(featureCode -> RolePermissionCacheService.PermissionDTO.builder()
|
||||
.featureId(featureResource.getId())
|
||||
.featureCode(featureCode)
|
||||
.featureType(featureResource.getFeatureType())
|
||||
.terminal(featureResource.getTerminal())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
SaasFeature saasFeature = saasFeatures.get(permissionRelation.getFeatureId());
|
||||
if (Objects.isNull(saasFeature)) {
|
||||
return null;
|
||||
}
|
||||
return Lists.newArrayList(RolePermissionCacheService.PermissionDTO.builder()
|
||||
.featureId(saasFeature.getId())
|
||||
.featureCode(saasFeature.getFeatureCode())
|
||||
.featureType(saasFeature.getFeatureType())
|
||||
.terminal(saasFeature.getTerminal())
|
||||
.build());
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(permissions)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return RolePermissionCacheService.RolePermission.builder()
|
||||
.roleId(e.getId())
|
||||
.permissions(permissions)
|
||||
.build();
|
||||
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
private Map<Long, SaasFeatureResourceResp> listSaasFeatureResource(List<SaasRoleRes> roles) {
|
||||
|
||||
List<Long> featureIds = roles.stream()
|
||||
.filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations()))
|
||||
.map(SaasRoleRes::getPermissionRelations)
|
||||
.flatMap(Collection::stream)
|
||||
.filter(e -> Objects.equals(e.getType(), NEW_FEATURE))
|
||||
.map(SaasPermissionRelationRes::getFeatureId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(featureIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder()
|
||||
.ids(featureIds)
|
||||
.needFeatureCodes(true)
|
||||
.build();
|
||||
return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream()
|
||||
.collect(Collectors.toMap(SaasFeatureResourceResp::getId, Function.identity()));
|
||||
}
|
||||
|
||||
private Map<Long, SaasFeature> listSaasFeature(List<SaasRoleRes> roles) {
|
||||
|
||||
List<Long> featureIds = roles.stream()
|
||||
.filter(e -> !CollectionUtils.isEmpty(e.getPermissionRelations()))
|
||||
.map(SaasRoleRes::getPermissionRelations)
|
||||
.flatMap(Collection::stream)
|
||||
.filter(e -> Objects.equals(e.getType(), OLD_FEATURE))
|
||||
.map(SaasPermissionRelationRes::getFeatureId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(featureIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
return saasFeatureDao.listByIds(featureIds).stream()
|
||||
.collect(Collectors.toMap(SaasFeature::getId, Function.identity()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.axzo.tyr.server.event.inner;
|
||||
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum EventTypeEnum {
|
||||
|
||||
PRODUCT_PERMISSION_CREATED("product-permission", "product-permission-created", "产品权限添加"),
|
||||
ROLE_PERMISSION_CREATED("role-permission", "role-permission-created", "角色权限添加"),
|
||||
;
|
||||
|
||||
EventTypeEnum(String model, String name, String desc) {
|
||||
this.eventCode = Event.EventCode.builder()
|
||||
.module(model)
|
||||
.name(name)
|
||||
.build();
|
||||
this.model = model;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
private String model;
|
||||
private String name;
|
||||
private String desc;
|
||||
private Event.EventCode eventCode;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package cn.axzo.tyr.server.event.payload;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 产品权限点做了更新,没有发送相关权限点消息,是因为日志太大,只能消费的时候实时查询
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ProductPermissionCreatedPayload implements Serializable {
|
||||
|
||||
private Set<Long> productModuleIds;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package cn.axzo.tyr.server.event.payload;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* 角色权限点做了更新,没有发送相关权限点消息,是因为日志太大,只能消费的时候实时查询
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RolePermissionCreatedPayload implements Serializable {
|
||||
|
||||
private Set<Long> roleIds;
|
||||
|
||||
}
|
||||
@ -6,14 +6,29 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ProductPermissionCacheService {
|
||||
|
||||
List<PermissionDTO> list(ListProductPermissionParam param);
|
||||
/**
|
||||
* 查询产品的权限信息
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
Map<Long, List<PermissionDTO>> list(ListProductPermissionParam param);
|
||||
|
||||
/**
|
||||
* 存储产品的权限信息
|
||||
* @param param
|
||||
*/
|
||||
void store(StoreProductPermissionParam param);
|
||||
|
||||
|
||||
/**
|
||||
* 产品是否有缓存权限
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
List<Long> hasProductIds(HasProductPermissionParam param);
|
||||
|
||||
@Data
|
||||
@ -47,7 +62,9 @@ public interface ProductPermissionCacheService {
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
class ListProductPermissionParam {
|
||||
private List<Long> productIds;
|
||||
private Set<Long> productIds;
|
||||
|
||||
private Set<String> featureCodes;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ -57,12 +74,17 @@ public interface ProductPermissionCacheService {
|
||||
class PermissionDTO {
|
||||
|
||||
/**
|
||||
* 产品关联的字典 Code 原值
|
||||
* 协同关系类型
|
||||
* 原saas_product_module_feature_relation.dictCode
|
||||
*/
|
||||
private String dictCode;
|
||||
private String cooperateType;
|
||||
|
||||
private Long featureId;
|
||||
|
||||
private String featureCode;
|
||||
|
||||
private String terminal;
|
||||
|
||||
private Integer featureType;
|
||||
}
|
||||
}
|
||||
@ -6,12 +6,13 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface RolePermissionCacheService {
|
||||
|
||||
|
||||
List<PermissionDTO> list(ListRolePermissionParam param);
|
||||
Map<Long, List<PermissionDTO>> list(ListRolePermissionParam param);
|
||||
|
||||
/**
|
||||
* redisKey:roleId
|
||||
@ -53,7 +54,9 @@ public interface RolePermissionCacheService {
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
class ListRolePermissionParam {
|
||||
private List<Long> roleIds;
|
||||
private Set<Long> roleIds;
|
||||
|
||||
private Set<String> featureCodes;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ -80,5 +83,7 @@ public interface RolePermissionCacheService {
|
||||
* 资源所属端
|
||||
*/
|
||||
private String terminal;
|
||||
|
||||
private Integer featureType;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import cn.axzo.foundation.dao.support.converter.PageConverter;
|
||||
import cn.axzo.foundation.dao.support.mysql.QueryWrapperHelper;
|
||||
import cn.axzo.foundation.page.PageResp;
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
||||
import cn.axzo.thrones.client.saas.ServicePkgClient;
|
||||
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
|
||||
@ -15,6 +16,8 @@ import cn.axzo.tyr.client.model.product.ProductFeatureRelationUpdateReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO;
|
||||
import cn.axzo.tyr.client.model.req.FeatureIdPair;
|
||||
import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq;
|
||||
import cn.axzo.tyr.server.config.MqProducer;
|
||||
import cn.axzo.tyr.server.event.payload.ProductPermissionCreatedPayload;
|
||||
import cn.axzo.tyr.server.repository.dao.ProductModuleDao;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
||||
@ -50,6 +53,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.tyr.server.event.inner.EventTypeEnum.PRODUCT_PERMISSION_CREATED;
|
||||
import static cn.axzo.tyr.server.util.RpcInternalUtil.checkAndGetData;
|
||||
|
||||
/**
|
||||
@ -68,6 +72,9 @@ public class ProductFeatureRelationServiceImpl extends ServiceImpl<SaasProductMo
|
||||
private final SaasFeatureDao saasFeatureDao;
|
||||
private final ProductModuleDao productModuleDao;
|
||||
private final SaasFeatureResourceDao saasFeatureResourceDao;
|
||||
private final MqProducer mqProducer;
|
||||
|
||||
private static final String TARGET_TYPE = "productModuleId";
|
||||
|
||||
@Override
|
||||
public ApiResult<List<ProductFeatureRelationVO>> featureList(ProductFeatureRelationSearchReq req) {
|
||||
@ -115,6 +122,8 @@ public class ProductFeatureRelationServiceImpl extends ServiceImpl<SaasProductMo
|
||||
.filter(CollectionUtil::isNotEmpty).flatMap(List::stream).collect(Collectors.toSet());
|
||||
if (CollectionUtil.isEmpty(allFeatureResourceIds)) {
|
||||
log.warn("product has no featureResourceIds to bind.");
|
||||
// 产品的权限点可能会被清空,也需要发送mq
|
||||
sendProductPermissionCreatedMsg(req);
|
||||
return;
|
||||
}
|
||||
Map<Long, SaasFeatureResource> resourceMap = saasFeatureResourceDao.lambdaQuery()
|
||||
@ -137,6 +146,27 @@ public class ProductFeatureRelationServiceImpl extends ServiceImpl<SaasProductMo
|
||||
saveList.add(relation);
|
||||
}));
|
||||
saasProductModuleFeatureRelationDao.saveBatch(saveList);
|
||||
|
||||
sendProductPermissionCreatedMsg(req);
|
||||
}
|
||||
|
||||
private void sendProductPermissionCreatedMsg(List<ProductFeatureRelationUpdateReq> req) {
|
||||
|
||||
if (CollectionUtils.isEmpty(req)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<Long> productModuleIds = req.stream()
|
||||
.map(ProductFeatureRelationUpdateReq::getProductModuleId)
|
||||
.collect(Collectors.toSet());
|
||||
Event event = Event.builder()
|
||||
.targetType(TARGET_TYPE)
|
||||
.eventCode(PRODUCT_PERMISSION_CREATED.getEventCode())
|
||||
.data(ProductPermissionCreatedPayload.builder()
|
||||
.productModuleIds(productModuleIds)
|
||||
.build())
|
||||
.build();
|
||||
mqProducer.send(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -326,7 +356,7 @@ public class ProductFeatureRelationServiceImpl extends ServiceImpl<SaasProductMo
|
||||
public List<SaasProductModuleFeatureRelation> list(PageProductFeatureRelationReq param) {
|
||||
return PageConverter.drainAll(pageNumber -> {
|
||||
param.setPage(pageNumber);
|
||||
param.setPageSize(500);
|
||||
param.setPageSize(1000);
|
||||
return page(param);
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,25 +2,36 @@ package cn.axzo.tyr.server.service.impl;
|
||||
|
||||
import cn.axzo.foundation.exception.Axssert;
|
||||
import cn.axzo.pokonyan.config.redis.RedisClient;
|
||||
import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq;
|
||||
import cn.axzo.tyr.server.event.inner.CacheProductPermissionHandler;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation;
|
||||
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
|
||||
import cn.axzo.tyr.server.service.ProductPermissionCacheService;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.SessionCallback;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -33,24 +44,75 @@ public class ProductPermissionCacheServiceImpl implements ProductPermissionCache
|
||||
private static final String PRODUCT_PERMISSION_KEY = "product:permission:%s";
|
||||
|
||||
@Autowired
|
||||
protected StringRedisTemplate redisTemplate;
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
@Autowired
|
||||
private ProductFeatureRelationService productFeatureRelationService;
|
||||
@Autowired
|
||||
private CacheProductPermissionHandler cacheProductPermissionHandler;
|
||||
|
||||
/** 产品权限缓存过期时间 **/
|
||||
@Value("${product.permission.expire:180}")
|
||||
private Long expireInDays;
|
||||
|
||||
@Override
|
||||
public List<PermissionDTO> list(ListProductPermissionParam param) {
|
||||
public Map<Long, List<PermissionDTO>> list(ListProductPermissionParam param) {
|
||||
|
||||
if (CollectionUtils.isEmpty(param.getProductIds())) {
|
||||
return Collections.emptyList();
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<Long, List<PermissionDTO>> permissionCached = listProductPermissionCached(param);
|
||||
|
||||
Set<String> redisKeys = param.getProductIds().stream()
|
||||
.map(this::getKey)
|
||||
.collect(Collectors.toSet());
|
||||
fillCacheProductPermissions(param, permissionCached);
|
||||
|
||||
Set<String> redisValues = redisTemplate.opsForSet().union(redisKeys);
|
||||
return permissionCached;
|
||||
}
|
||||
|
||||
return redisValues.stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(value -> JSONObject.parseObject(value, PermissionDTO.class))
|
||||
.collect(Collectors.toList());
|
||||
private Map<Long, List<PermissionDTO>> listProductPermissionCached(ListProductPermissionParam param) {
|
||||
|
||||
List<Object> redisValues = redisTemplate.executePipelined(new SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object execute(RedisOperations operations) throws DataAccessException {
|
||||
|
||||
for (Long productId : param.getProductIds()) {
|
||||
String redisKey = getKey(productId);
|
||||
|
||||
if (CollectionUtils.isEmpty(param.getFeatureCodes())) {
|
||||
RedisClient.HashOps.hGetAll(redisKey);
|
||||
} else {
|
||||
RedisClient.HashOps.hMultiGet(redisKey, Lists.newArrayList(param.getFeatureCodes()));
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return Streams.zip(param.getProductIds().stream(),
|
||||
redisValues.stream(),
|
||||
(productId, redisValue) -> {
|
||||
|
||||
if (Objects.isNull(redisValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(param.getFeatureCodes())) {
|
||||
List<PermissionDTO> permissions = (List<PermissionDTO>) ((Map) redisValue).values().stream()
|
||||
.flatMap(e -> JSONArray.parseArray(JSONArray.toJSONString(e), PermissionDTO.class).stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Pair.of(productId, permissions);
|
||||
}
|
||||
|
||||
List<PermissionDTO> permissions = (List<PermissionDTO>) ((List) redisValue).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.flatMap(e -> JSONArray.parseArray((String) e, PermissionDTO.class).stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Pair.of(productId, permissions);
|
||||
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,12 +127,14 @@ public class ProductPermissionCacheServiceImpl implements ProductPermissionCache
|
||||
for (ProductPermission productPermission : param.getProductPermissions()) {
|
||||
String redisKey = getKey(productPermission.getProductId());
|
||||
|
||||
String[] redisValues = productPermission.getPermissions().stream()
|
||||
.map(JSONObject::toJSONString)
|
||||
.toArray(String[]::new);
|
||||
Map<String, String> redisValues = productPermission.getPermissions().stream()
|
||||
.collect(Collectors.groupingBy(PermissionDTO::getFeatureCode))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> JSONObject.toJSONString(e.getValue())));
|
||||
|
||||
RedisClient.SetOps.sAdd(redisKey, redisValues);
|
||||
redisTemplate.expire(redisKey, 4, TimeUnit.DAYS);
|
||||
RedisClient.HashOps.hPutAll(redisKey, redisValues);
|
||||
redisTemplate.expire(redisKey, expireInDays, TimeUnit.DAYS);
|
||||
log.info("succeed to store product permission: redisKey:{} value:{}", redisKey, redisValues);
|
||||
}
|
||||
return null;
|
||||
@ -100,7 +164,61 @@ public class ProductPermissionCacheServiceImpl implements ProductPermissionCache
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装在缓存中没有查询到权限的产品
|
||||
* @param param
|
||||
* @param permissionCached
|
||||
*/
|
||||
private void fillCacheProductPermissions(ListProductPermissionParam param,
|
||||
Map<Long, List<PermissionDTO>> permissionCached) {
|
||||
|
||||
Sets.SetView<Long> difference = Sets.difference(param.getProductIds(), permissionCached.keySet());
|
||||
if (difference.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PageProductFeatureRelationReq pageProductFeatureRelationReq = PageProductFeatureRelationReq.builder()
|
||||
.productModuleIds(difference)
|
||||
.build();
|
||||
List<SaasProductModuleFeatureRelation> productPermissions = productFeatureRelationService.list(pageProductFeatureRelationReq);
|
||||
|
||||
List<ProductPermission> productPermissionsCache = cacheProductPermissionHandler.resolveProductPermissions(productPermissions);
|
||||
if (CollectionUtils.isEmpty(productPermissionsCache)) return;
|
||||
|
||||
StoreProductPermissionParam storeWorkspaceProductParam = StoreProductPermissionParam.builder()
|
||||
.productPermissions(productPermissionsCache)
|
||||
.build();
|
||||
store(storeWorkspaceProductParam);
|
||||
|
||||
Map<Long, List<PermissionDTO>> productPermissionMap = productPermissionsCache.stream()
|
||||
.collect(Collectors.toMap(ProductPermission::getProductId, ProductPermission::getPermissions));
|
||||
permissionCached.putAll(productPermissionMap);
|
||||
}
|
||||
|
||||
private String getKey(Object... params) {
|
||||
return String.format(PRODUCT_PERMISSION_KEY, params);
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
static class PermissionWrapper {
|
||||
|
||||
/**
|
||||
* 协同关系类型
|
||||
* 原saas_product_module_feature_relation.dictCode
|
||||
*/
|
||||
private String cooperateType;
|
||||
|
||||
private Long featureId;
|
||||
|
||||
private String featureCode;
|
||||
|
||||
private String terminal;
|
||||
|
||||
private Integer featureType;
|
||||
|
||||
private Long productId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,14 +2,20 @@ package cn.axzo.tyr.server.service.impl;
|
||||
|
||||
import cn.axzo.foundation.exception.Axssert;
|
||||
import cn.axzo.pokonyan.config.redis.RedisClient;
|
||||
import cn.axzo.tyr.client.model.res.SaasRoleRes;
|
||||
import cn.axzo.tyr.server.event.inner.CacheRolePermissionHandler;
|
||||
import cn.axzo.tyr.server.service.RolePermissionCacheService;
|
||||
import cn.axzo.tyr.server.service.RoleService;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
@ -20,8 +26,8 @@ import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -35,23 +41,73 @@ public class RolePermissionCacheServiceImpl implements RolePermissionCacheServic
|
||||
|
||||
@Autowired
|
||||
protected StringRedisTemplate redisTemplate;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
@Autowired
|
||||
private CacheRolePermissionHandler cacheRolePermissionHandler;
|
||||
|
||||
|
||||
/** 角色权限缓存过期时间 **/
|
||||
@Value("${role.permission.expire:180}")
|
||||
private Long expireInDays;
|
||||
|
||||
@Override
|
||||
public List<PermissionDTO> list(ListRolePermissionParam param) {
|
||||
public Map<Long, List<PermissionDTO>> list(ListRolePermissionParam param) {
|
||||
if (CollectionUtils.isEmpty(param.getRoleIds())) {
|
||||
return Collections.emptyList();
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Set<String> redisKeys = param.getRoleIds().stream()
|
||||
.map(this::getKey)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, List<PermissionDTO>> permissions = listRolePermissionCached(param);
|
||||
|
||||
// 聚合是因为角色的权限点有重复,网络io压力大
|
||||
Set<String> redisValues = redisTemplate.opsForSet().union(redisKeys);
|
||||
return redisValues.stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(value -> JSONObject.parseObject(value, PermissionDTO.class))
|
||||
.collect(Collectors.toList());
|
||||
fillCacheRolePermissions(param, permissions);
|
||||
return permissions;
|
||||
}
|
||||
|
||||
|
||||
private Map<Long, List<PermissionDTO>> listRolePermissionCached(ListRolePermissionParam param) {
|
||||
|
||||
List<Object> redisValues = redisTemplate.executePipelined(new SessionCallback<Object>() {
|
||||
@Override
|
||||
public Object execute(RedisOperations operations) throws DataAccessException {
|
||||
|
||||
for (Long roleId : param.getRoleIds()) {
|
||||
String redisKey = getKey(roleId);
|
||||
if (CollectionUtils.isEmpty(param.getFeatureCodes())) {
|
||||
RedisClient.HashOps.hGetAll(redisKey);
|
||||
} else {
|
||||
RedisClient.HashOps.hMultiGet(redisKey, Lists.newArrayList(param.getFeatureCodes()));
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return Streams.zip(param.getRoleIds().stream(),
|
||||
redisValues.stream(),
|
||||
(roleId, redisValue) -> {
|
||||
|
||||
if (Objects.isNull(redisValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(param.getFeatureCodes())) {
|
||||
|
||||
List<PermissionDTO> permissions = (List<PermissionDTO>) ((Map) redisValue).values().stream()
|
||||
.flatMap(e -> JSONArray.parseArray(JSONArray.toJSONString(e), PermissionDTO.class).stream())
|
||||
.collect(Collectors.toList());
|
||||
return Pair.of(roleId, permissions);
|
||||
}
|
||||
|
||||
List<PermissionDTO> permissions = (List<PermissionDTO>) ((List) redisValue).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.flatMap(e -> JSONArray.parseArray((String) e, PermissionDTO.class).stream())
|
||||
.collect(Collectors.toList());
|
||||
return Pair.of(roleId, permissions);
|
||||
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,12 +122,14 @@ public class RolePermissionCacheServiceImpl implements RolePermissionCacheServic
|
||||
for (RolePermission rolePermission : param.getRolePermissions()) {
|
||||
String redisKey = getKey(rolePermission.getRoleId());
|
||||
|
||||
String[] redisValues = rolePermission.getPermissions().stream()
|
||||
.map(JSONObject::toJSONString)
|
||||
.toArray(String[]::new);
|
||||
Map<String, String> redisValues = rolePermission.getPermissions().stream()
|
||||
.collect(Collectors.groupingBy(PermissionDTO::getFeatureCode))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> JSONObject.toJSONString(e.getValue())));
|
||||
|
||||
RedisClient.SetOps.sAdd(redisKey, redisValues);
|
||||
redisTemplate.expire(redisKey, 4, TimeUnit.DAYS);
|
||||
RedisClient.HashOps.hPutAll(redisKey, redisValues);
|
||||
redisTemplate.expire(redisKey, expireInDays, TimeUnit.DAYS);
|
||||
log.info("succeed to store role permission: redisKey:{} value:{}", redisKey, redisValues);
|
||||
}
|
||||
return null;
|
||||
@ -100,6 +158,45 @@ public class RolePermissionCacheServiceImpl implements RolePermissionCacheServic
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装在缓存中没有查询到权限的角色权限
|
||||
* @param param
|
||||
* @param permissionCached
|
||||
*/
|
||||
private void fillCacheRolePermissions(ListRolePermissionParam param,
|
||||
Map<Long, List<PermissionDTO>> permissionCached) {
|
||||
|
||||
Sets.SetView<Long> difference = Sets.difference(param.getRoleIds(), permissionCached.keySet());
|
||||
if (difference.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder()
|
||||
.roleIds(Lists.newArrayList(difference))
|
||||
.needPermissionRelation(true)
|
||||
.build();
|
||||
List<SaasRoleRes> roles = roleService.list(listSaasRoleParam);
|
||||
|
||||
if (CollectionUtils.isEmpty(roles)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<RolePermission> rolePermissions = cacheRolePermissionHandler.resolveRolePermission(roles);
|
||||
|
||||
if (CollectionUtils.isEmpty(rolePermissions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
StoreRolePermissionParam storeRolePermissionParam = StoreRolePermissionParam.builder()
|
||||
.rolePermissions(rolePermissions)
|
||||
.build();
|
||||
store(storeRolePermissionParam);
|
||||
|
||||
Map<Long, List<PermissionDTO>> rolePermissionMap = rolePermissions.stream()
|
||||
.collect(Collectors.toMap(RolePermission::getRoleId, RolePermission::getPermissions));
|
||||
permissionCached.putAll(rolePermissionMap);
|
||||
}
|
||||
|
||||
private String getKey(Object... params) {
|
||||
return String.format(ROLE_PERMISSION_KEY, params);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user