package org.beangle.security.monitor.impl;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.beangle.commons.collection.MapUtil;
import org.beangle.commons.collection.SetUtil;
import org.beangle.model.persist.impl.BaseServiceImpl;
import org.beangle.security.Group;
import org.beangle.security.Resource;
import org.beangle.security.User;
import org.beangle.security.monitor.AuthorityManager;
import org.beangle.security.service.AuthorityService;
import org.beangle.security.service.ResourceService;
import org.beangle.security.service.UserService;
public class DefaultAuthorityManager extends BaseServiceImpl implements AuthorityManager {
/** [userId,groupIds[]] */
protected Map<Long, Long[]> userGroupIds = MapUtil.newHashMap();
/** [groupId,parentGroupId] */
protected Map<Long, Long> parentGroupIds = MapUtil.newHashMap();
/** 用户组权限 [groupId,actionIdSet] */
protected Map<Long, Set<Long>> authorities = MapUtil.newHashMap();
/** 公开资源name */
protected Set<String> publicResources;
/** 公有资源id */
protected Set<Long> protectedResourceIds;
/** 所有资源map [resourceName,resourceId] */
protected Map<String, Long> resourceMap;
/** 授权服务 */
protected AuthorityService authorityService;
/** 资源服务 */
protected ResourceService resourceService;
/** 用户服务 */
protected UserService userService;
private boolean expired = true;
public boolean isPublic(String resourceName) {
loadResourceNecessary();
return publicResources.contains(resourceName);
}
/**
* 资源是否被授权<br>
* 1)检查是否是属于公有资源<br>
* 2)检查用户组权限<br>
*/
public boolean isAuthorized(Long userId, String resourceName) {
loadResourceNecessary();
Long resourceId = (Long) resourceMap.get(resourceName);
if (null == resourceId) {
return false;
}
if (protectedResourceIds.contains(resourceId)) {
return true;
}
Long[] groupIds = userGroupIds.get(userId);
if (null == groupIds) {
return false;
}
for (int i = 0; i < groupIds.length; i++) {
if (isAuthorizedByGroup(groupIds[i], resourceId)) {
return true;
}
}
return false;
}
/**
* 判断组内是否含有该资源
*
* @param groupId
* @param resourceId
* @return
*/
private boolean isAuthorizedByGroup(Long groupId, Long resourceId) {
Set<Long> actions = authorities.get(groupId);
boolean success = (null != actions && actions.contains(resourceId));
if (success) {
return success;
} else {
Long parentId = parentGroupIds.get(groupId);
if (null != parentId) {
return isAuthorizedByGroup(parentId, resourceId);
} else {
return false;
}
}
}
public void registerAuthorities(Long userId) {
User user = (User) entityDao.get(User.class, userId);
Set<Group> groups = userService.getGroups(user);
Long[] groupIds = new Long[groups.size()];
int i = 0;
for (final Group group : groups) {
registerGroupAuthorities(group);
groupIds[i++] = group.getId();
}
userGroupIds.put(user.getId(), groupIds);
}
public void registerGroupAuthorities(Group group) {
Set<Long> ra = authorityService.getResourceIds(group);
authorities.put(group.getId(), ra);
if (null != group.getParent()) {
parentGroupIds.put(group.getId(), group.getParent().getId());
registerGroupAuthorities(group.getParent());
}
logger.debug("add authorities for group:{} resource:{}", group.getName(), ra);
}
public void removeAuthorities(Long userId) {
logger.debug("remove authorities for userId:{}", userId);
if (null != userId) {
userGroupIds.remove(userId);
}
}
public void loadResourceNecessary() {
if (expired) {
synchronized (this) {
if (!expired)
return;
refreshCache();
}
}
}
/**
* 加载三类资源
*/
public void refreshCache() {
resourceMap = MapUtil.newHashMap();
publicResources = SetUtil.newHashSet();
protectedResourceIds = SetUtil.newHashSet();
List<Resource> resources = resourceService.getResources();
for (final Resource resource : resources) {
if (resource.getScope() == Resource.Scope.PUBLIC) {
publicResources.add(resource.getName());
} else if (resource.getScope() == Resource.Scope.PROTECTED) {
protectedResourceIds.add(resource.getId());
}
resourceMap.put(resource.getName(), resource.getId());
}
expired = false;
logger.info("public resources loaded:{}", publicResources);
}
public Set<String> getPublicResources() {
return publicResources;
}
public void setPublicResources(Set<String> ignoreResources) {
this.publicResources = ignoreResources;
}
public void setAuthorityService(AuthorityService authorityService) {
this.authorityService = authorityService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
public void setResourceService(ResourceService resourceService) {
this.resourceService = resourceService;
}
}