角色启用/禁用、用户设置角色后刷新权限缓存

This commit is contained in:
interestinglife41 2021-08-20 16:01:24 +08:00
parent cddd34093f
commit 69af9b638e
12 changed files with 287 additions and 32 deletions

View File

@ -11,7 +11,8 @@
ok 移除管理员的数据源授权功能;
ok 移除通配符授权特性;
系统添加缓存支持:
实现postProcessGet加载共享属性值
ok 角色启用/禁用、用户设置角色时刷新权限缓存;
ok 实现postProcessGet加载共享属性值
ok 服务层API内部引入缓存特性
ok 系统缓存统一改为Caffeine移除Guava以减少程序包大小
ok 标签卡添加横排设置选项,简化配置项;

View File

@ -0,0 +1,49 @@
/*
* Copyright 2018 datagear.tech
*
* Licensed under the LGPLv3 license:
* http://www.gnu.org/licenses/lgpl-3.0.html
*/
package org.datagear.management.service;
import org.datagear.management.domain.Role;
import org.datagear.management.domain.User;
/**
* 授权监听器
* <p>
* 主要用于处理授权变更事件比如清空或者重新加载缓存
* </p>
*
* @author datagear@163.com
*
*/
public interface AuthorizationListener
{
/**
* 指定资源的授权已更新
* <p>
* 当直接修改了指定资源的授权信息后将触发此事件
* </p>
*
* @param resourceType
* @param resources
*/
void authorizationUpdated(String resourceType, String... resources);
/**
* 未知量的资源的权限已更新
* <p>
* 数据权限不仅与直接授权相关还与下列操作相关
* </p>
* <ul>
* <li>角色{@linkplain Role}启用禁用</li>
* <li>用户{@linkplain User}绑定解绑角色</li>
* </ul>
* <p>
* 当上述操作后将触发此事件
* </p>
*/
void permissionUpdated();
}

View File

@ -24,7 +24,8 @@ import org.datagear.persistence.Query;
* @param <ID>
* @param <T>
*/
public interface DataPermissionEntityService<ID, T extends DataPermissionEntity<ID>> extends EntityService<ID, T>
public interface DataPermissionEntityService<ID, T extends DataPermissionEntity<ID>>
extends EntityService<ID, T>, AuthorizationListener
{
/** 数据权限参数当前用户参考commonDataPermissionSqls.xml */
String DATA_PERMISSION_PARAM_CURRENT_USER = "DP_CURRENT_USER";
@ -197,14 +198,4 @@ public interface DataPermissionEntityService<ID, T extends DataPermissionEntity<
* @throws PermissionDeniedException
*/
T getByStringId(User user, String id) throws PermissionDeniedException;
/**
* 指定ID的实体权限更新事件通知
* <p>
* 此方法通常用于清除或者重新加载权限缓存
* </p>
*
* @param ids
*/
void permissionUpdated(String... ids);
}

View File

@ -206,10 +206,19 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
}
@Override
public void permissionUpdated(String... ids)
public void authorizationUpdated(String resourceType, String... resources)
{
for (String id : ids)
this.permissionCache.evictImmediately(toPermissionCacheKeyOfStr(id));
if (!getResourceType().equals(resourceType))
return;
for (String res : resources)
this.permissionCache.evictImmediately(toPermissionCacheKeyOfStr(res));
}
@Override
public void permissionUpdated()
{
this.permissionCache.invalidate();
}
protected void setDataFilterParam(Map<String, Object> params, String dataFilter)

View File

@ -7,6 +7,7 @@
package org.datagear.management.service.impl;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -744,6 +745,24 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
return StringUtil.isEmpty(obj);
}
/**
* 如果元素不为{@code null}才将其添加至集合
*
* @param <E>
* @param collection
* @param element
* @return
*/
protected <E> boolean addIfNonNull(Collection<E> collection, E element)
{
if (element == null)
return false;
collection.add(element);
return true;
}
/**
* 字符串是否为空
*

View File

@ -0,0 +1,34 @@
/*
* Copyright 2018 datagear.tech
*
* Licensed under the LGPLv3 license:
* http://www.gnu.org/licenses/lgpl-3.0.html
*/
package org.datagear.management.service.impl;
import org.datagear.management.service.AuthorizationListener;
/**
* {@linkplain AuthorizationListener}相关类
*
* @author datagear@163.com
*
*/
public interface AuthorizationListenerAware
{
/**
* 获取{@linkplain AuthorizationListener}
*
* @return 可能为{@code null}
*/
AuthorizationListener getAuthorizationListener();
/**
* 设置{@linkplain AuthorizationListener}
*
* @param authorizationListener
* 允许为{@code null}
*/
void setAuthorizationListener(AuthorizationListener authorizationListener);
}

View File

@ -15,6 +15,7 @@ import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.Authorization;
import org.datagear.management.domain.DataPermissionEntity;
import org.datagear.management.domain.User;
import org.datagear.management.service.AuthorizationListener;
import org.datagear.management.service.AuthorizationService;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.management.util.dialect.MbSqlDialect;
@ -27,12 +28,14 @@ import org.mybatis.spring.SqlSessionTemplate;
*
*/
public class AuthorizationServiceImpl extends AbstractMybatisEntityService<String, Authorization>
implements AuthorizationService
implements AuthorizationService, AuthorizationListenerAware
{
protected static final String SQL_NAMESPACE = Authorization.class.getName();
private List<? extends DataPermissionEntityService<?, ?>> resourceServices;
private AuthorizationListener authorizationListener = null;
public AuthorizationServiceImpl()
{
super();
@ -62,11 +65,23 @@ public class AuthorizationServiceImpl extends AbstractMybatisEntityService<Strin
this.resourceServices = resourceServices;
}
@Override
public AuthorizationListener getAuthorizationListener()
{
return authorizationListener;
}
@Override
public void setAuthorizationListener(AuthorizationListener authorizationListener)
{
this.authorizationListener = authorizationListener;
}
@Override
public void add(Authorization entity)
{
super.add(entity);
permissionUpdated(entity.getResourceType(), entity.getResource());
authorizationUpdated(entity.getResourceType(), entity.getResource());
}
@Override
@ -75,7 +90,7 @@ public class AuthorizationServiceImpl extends AbstractMybatisEntityService<Strin
Authorization authorization = getById(id);
if (authorization != null)
permissionUpdated(authorization.getResourceType(), authorization.getResource());
authorizationUpdated(authorization.getResourceType(), authorization.getResource());
return super.deleteById(id);
}
@ -110,7 +125,7 @@ public class AuthorizationServiceImpl extends AbstractMybatisEntityService<Strin
int count = updateMybatis("deleteByIdsForResource", params);
if (count > 0)
permissionUpdated(resourceType, resource);
authorizationUpdated(resourceType, resource);
return count;
}
@ -125,7 +140,7 @@ public class AuthorizationServiceImpl extends AbstractMybatisEntityService<Strin
int count = updateMybatis("deleteByResource", params);
if (count > 0)
permissionUpdated(resourceType, resources);
authorizationUpdated(resourceType, resources);
return count;
}
@ -159,12 +174,10 @@ public class AuthorizationServiceImpl extends AbstractMybatisEntityService<Strin
return context;
}
protected void permissionUpdated(String resourceType, String... resources)
protected void authorizationUpdated(String resourceType, String... resources)
{
DataPermissionEntityService<?, ?> resourceService = getResourceService(resourceType);
if (resourceService != null)
resourceService.permissionUpdated(resources);
if (this.authorizationListener != null)
this.authorizationListener.authorizationUpdated(resourceType, resources);
}
/**

View File

@ -0,0 +1,64 @@
/*
* Copyright 2018 datagear.tech
*
* Licensed under the LGPLv3 license:
* http://www.gnu.org/licenses/lgpl-3.0.html
*/
package org.datagear.management.service.impl;
import java.util.Collection;
import org.datagear.management.service.AuthorizationListener;
/**
* 打包一起的{@linkplain AuthorizationListener}
*
* @author datagear@163.com
*
*/
public class BundleAuthorizationListener implements AuthorizationListener
{
private Collection<AuthorizationListener> authorizationListeners = null;
public BundleAuthorizationListener()
{
super();
}
public BundleAuthorizationListener(Collection<AuthorizationListener> authorizationListeners)
{
super();
this.authorizationListeners = authorizationListeners;
}
public Collection<AuthorizationListener> getAuthorizationListeners()
{
return authorizationListeners;
}
public void setAuthorizationListeners(Collection<AuthorizationListener> authorizationListeners)
{
this.authorizationListeners = authorizationListeners;
}
@Override
public void authorizationUpdated(String resourceType, String... resources)
{
if (this.authorizationListeners == null)
return;
for (AuthorizationListener al : this.authorizationListeners)
al.authorizationUpdated(resourceType, resources);
}
@Override
public void permissionUpdated()
{
if (this.authorizationListeners == null)
return;
for (AuthorizationListener al : this.authorizationListeners)
al.permissionUpdated();
}
}

View File

@ -359,6 +359,8 @@ public class HtmlChartWidgetEntityServiceImpl
if (chartDataSetVOs == null || chartDataSetVOs.length == 0)
return;
List<ChartDataSetVO> list = new ArrayList<ChartDataSetVO>(chartDataSetVOs.length);
for (int i = 0; i < chartDataSetVOs.length; i++)
{
ChartDataSetVO vo = chartDataSetVOs[i];
@ -372,6 +374,8 @@ public class HtmlChartWidgetEntityServiceImpl
dataSet = this.dataSetEntityService.getById(dataSetId);
vo.setDataSet(dataSet);
addIfNonNull(list, (vo.getDataSet() == null ? null : vo));
}
}

View File

@ -13,6 +13,7 @@ import java.util.Map;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.Role;
import org.datagear.management.service.AuthorizationListener;
import org.datagear.management.service.DeleteBuiltinRoleDeniedException;
import org.datagear.management.service.RoleService;
import org.datagear.management.util.dialect.MbSqlDialect;
@ -24,10 +25,13 @@ import org.mybatis.spring.SqlSessionTemplate;
* @author datagear@163.com
*
*/
public class RoleServiceImpl extends AbstractMybatisEntityService<String, Role> implements RoleService
public class RoleServiceImpl extends AbstractMybatisEntityService<String, Role>
implements RoleService, AuthorizationListenerAware
{
protected static final String SQL_NAMESPACE = Role.class.getName();
private AuthorizationListener authorizationListener = null;
public RoleServiceImpl()
{
super();
@ -43,6 +47,18 @@ public class RoleServiceImpl extends AbstractMybatisEntityService<String, Role>
super(sqlSessionTemplate, dialect);
}
@Override
public AuthorizationListener getAuthorizationListener()
{
return authorizationListener;
}
@Override
public void setAuthorizationListener(AuthorizationListener authorizationListener)
{
this.authorizationListener = authorizationListener;
}
@Override
public List<Role> getByIds(String... ids)
{
@ -54,13 +70,29 @@ public class RoleServiceImpl extends AbstractMybatisEntityService<String, Role>
return roles;
}
@Override
protected boolean update(Role entity, Map<String, Object> params)
{
boolean updated = super.update(entity, params);
if (updated && this.authorizationListener != null)
this.authorizationListener.permissionUpdated();
return updated;
}
@Override
protected boolean deleteById(String id, Map<String, Object> params)
{
if (Role.isBuiltinRole(id))
throw new DeleteBuiltinRoleDeniedException(id);
return super.deleteById(id, params);
boolean deleted = super.deleteById(id, params);
if (deleted && this.authorizationListener != null)
this.authorizationListener.permissionUpdated();
return deleted;
}
@Override

View File

@ -16,6 +16,7 @@ import java.util.Set;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.Role;
import org.datagear.management.domain.User;
import org.datagear.management.service.AuthorizationListener;
import org.datagear.management.service.RoleService;
import org.datagear.management.service.UserService;
import org.datagear.management.util.dialect.MbSqlDialect;
@ -28,7 +29,8 @@ import org.mybatis.spring.SqlSessionTemplate;
* @author datagear@163.com
*
*/
public class UserServiceImpl extends AbstractMybatisEntityService<String, User> implements UserService
public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
implements UserService, AuthorizationListenerAware
{
protected static final String SQL_NAMESPACE = User.class.getName();
@ -36,6 +38,8 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
private UserPasswordEncoder userPasswordEncoder = null;
private AuthorizationListener authorizationListener = null;
public UserServiceImpl()
{
super();
@ -75,6 +79,18 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
this.userPasswordEncoder = userPasswordEncoder;
}
@Override
public AuthorizationListener getAuthorizationListener()
{
return authorizationListener;
}
@Override
public void setAuthorizationListener(AuthorizationListener authorizationListener)
{
this.authorizationListener = authorizationListener;
}
@Override
public User getByName(String name)
{
@ -148,8 +164,13 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
Boolean ignoreRole = (Boolean) params.get("ignoreRole");
if (ignoreRole == null || !ignoreRole.booleanValue())
{
saveUserRoles(entity);
if (this.authorizationListener != null)
this.authorizationListener.permissionUpdated();
}
return updated;
}
@ -230,7 +251,7 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
for (Role role : roles)
{
role = this.roleService.getById(role.getId());
rolesNew.add(role);
addIfNonNull(rolesNew, role);
}
obj.setRoles(rolesNew);

View File

@ -51,6 +51,7 @@ import org.datagear.dataexchange.support.SqlDataExportService;
import org.datagear.dataexchange.support.SqlDataImportService;
import org.datagear.management.dbversion.DbVersionManager;
import org.datagear.management.service.AnalysisProjectService;
import org.datagear.management.service.AuthorizationListener;
import org.datagear.management.service.AuthorizationService;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.management.service.DataSetEntityService;
@ -64,7 +65,9 @@ import org.datagear.management.service.UserService;
import org.datagear.management.service.impl.AbstractMybatisDataPermissionEntityService;
import org.datagear.management.service.impl.AbstractMybatisEntityService;
import org.datagear.management.service.impl.AnalysisProjectServiceImpl;
import org.datagear.management.service.impl.AuthorizationListenerAware;
import org.datagear.management.service.impl.AuthorizationServiceImpl;
import org.datagear.management.service.impl.BundleAuthorizationListener;
import org.datagear.management.service.impl.DataSetEntityServiceImpl;
import org.datagear.management.service.impl.DataSetResDirectoryServiceImpl;
import org.datagear.management.service.impl.HtmlChartWidgetEntityServiceImpl;
@ -742,6 +745,7 @@ public class CoreConfig implements ApplicationListener<ContextRefreshedEvent>
ApplicationContext context = event.getApplicationContext();
initAuthorizationResourceServices(context);
initAuthorizationListenerAwares(context);
initServiceCaches(context);
initDevotedDataExchangeServices(context);
}
@ -752,9 +756,23 @@ public class CoreConfig implements ApplicationListener<ContextRefreshedEvent>
Map<String, DataPermissionEntityService> dataPermissionEntityServices = context
.getBeansOfType(DataPermissionEntityService.class);
List<DataPermissionEntityService<?, ?>> resourceServices = this.authorizationResourceServices();
for (DataPermissionEntityService<?, ?> dps : dataPermissionEntityServices.values())
resourceServices.add(dps);
@SuppressWarnings("unchecked")
List<DataPermissionEntityService> resourceServices = (List) this.authorizationResourceServices();
resourceServices.addAll(dataPermissionEntityServices.values());
}
protected void initAuthorizationListenerAwares(ApplicationContext context)
{
Map<String, AuthorizationListener> listenerMap = context.getBeansOfType(AuthorizationListener.class);
List<AuthorizationListener> listenerList = new ArrayList<AuthorizationListener>(
listenerMap.size());
listenerList.addAll(listenerMap.values());
AuthorizationListener listener = new BundleAuthorizationListener(listenerList);
Map<String, AuthorizationListenerAware> awareMap = context.getBeansOfType(AuthorizationListenerAware.class);
for (AuthorizationListenerAware aware : awareMap.values())
aware.setAuthorizationListener(listener);
}
@SuppressWarnings("rawtypes")