/* ================================================================== * Created [2009-4-27 下午11:32:55] by Jon.King * ================================================================== * TSS * ================================================================== * mailTo:jinpujun@hotmail.com * Copyright (c) Jon.King, 2009-2012 * ================================================================== */ package com.jinhe.tss.um.service.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import com.jinhe.tss.component.support.persistence.entityaop.DecodeUtil; import com.jinhe.tss.core.common.progress.Progress; import com.jinhe.tss.core.common.progress.Progressable; import com.jinhe.tss.core.exception.BusinessException; import com.jinhe.tss.core.sso.Environment; import com.jinhe.tss.core.util.BeanUtil; import com.jinhe.tss.core.util.EasyUtils; import com.jinhe.tss.core.util.InfoEncoder; import com.jinhe.tss.um.UMConstants; import com.jinhe.tss.um.dao.IApplicationDao; import com.jinhe.tss.um.dao.IGroupDao; import com.jinhe.tss.um.dao.IGroupUserDao; import com.jinhe.tss.um.dao.IRoleDao; import com.jinhe.tss.um.dao.IUserDao; import com.jinhe.tss.um.entity.Application; import com.jinhe.tss.um.entity.Group; import com.jinhe.tss.um.entity.GroupUser; import com.jinhe.tss.um.entity.RoleGroup; import com.jinhe.tss.um.entity.User; import com.jinhe.tss.um.permission.PermissionHelper; import com.jinhe.tss.um.permission.ResourcePermission; import com.jinhe.tss.um.service.IGroupService; public class GroupService implements IGroupService, Progressable{ @Autowired private IGroupDao groupDao; @Autowired private IRoleDao roleDao; @Autowired private IUserDao userDao; @Autowired private IGroupUserDao groupUserDao; @Autowired private ResourcePermission resourcePermission; @Autowired private IApplicationDao applicationDao; public Group getGroupById(Long id) { return groupDao.getEntity(id); } public List<User> findUsersByGroupId(Long groupId) { return groupDao.getUsersByGroupId(groupId); } public List<?> findRolesByGroupId(Long groupId) { return groupDao.findRolesByGroupId(groupId); } public List<?> findEditableRolesByOperatorId() { return roleDao.getEditableRoles(); } public Object[] findGroups() { Long operatorId = Environment.getOperatorId(); List<Object> mainAndAssistantGroups = new ArrayList<Object>(); mainAndAssistantGroups.addAll(groupDao.getGroupsByType(Group.MAIN_GROUP_TYPE, operatorId)); mainAndAssistantGroups.addAll(groupDao.getGroupsByType(Group.ASSISTANT_GROUP_TYPE, operatorId)); Object[] objs = getOtherGroupsByOperationId(UMConstants.GROUP_VIEW_OPERRATION); return new Object[]{ mainAndAssistantGroups, objs[0], objs[1], objs[2] }; } public Object[] getAssistGroupsByOperationId(String operationId) { return getGroupsByGroupTypeAndOperationId(Group.ASSISTANT_GROUP_TYPE, operationId); } public Object[] getMainGroupsByOperationId(String operationId) { return getGroupsByGroupTypeAndOperationId(Group.MAIN_GROUP_TYPE, operationId); } private Object[] getGroupsByGroupTypeAndOperationId(Integer groupType, String operationId) { Long operatorId = Environment.getOperatorId(); List<?> groups = groupDao.getGroupsByType(groupType, operatorId, operationId); List<Long> groupIds = new ArrayList<Long>(); for( Object temp : groups ){ Group group = (Group) temp; groupIds.add(group.getId()); } List<?> parentGroups = groupDao.getParentGroupByGroupIds(groupType, groupIds, operatorId, UMConstants.GROUP_VIEW_OPERRATION); return new Object[]{groupIds, parentGroups}; } public Object[] getOtherGroupsByOperationId(String operationId) { Long operatorId = Environment.getOperatorId(); List<?> groups = groupDao.getGroupsByType(Group.OTHER_GROUP_TYPE, operatorId, operationId); Group otherAppGroupRoot = null; List<Group> otherGroups = new ArrayList<Group>(); for( Object temp : groups ){ Group group = (Group) temp; if(UMConstants.OTHER_APPLICATION_GROUP_ID.equals(group.getId())) { otherAppGroupRoot = group; // 其他用户组 continue; } otherGroups.add(group); } List<?> appIds = resourcePermission.getResourceIds(UMConstants.TSS_APPLICATION_ID, UMConstants.APPLICATION_RESOURCE_TYPE_ID, UMConstants.APPLICATION_VIEW_OPERRATION, operatorId); List<?> apps = applicationDao.getApplications(appIds, UMConstants.OTHER_SYSTEM_APP); // 应用系统类型 return new Object[]{otherAppGroupRoot, otherGroups, apps}; } public Object[] getGroupsUnderAppByOperationId(String operationId, String applicationId){ List<?> groups = groupDao.getGroupsByType(Group.OTHER_GROUP_TYPE, Environment.getOperatorId(), operationId); Group otherAppGroupRoot = null; List<Group> otherGroups = new ArrayList<Group>(); for( Object temp : groups ){ Group group = (Group) temp; if(UMConstants.OTHER_APPLICATION_GROUP_ID.equals(group.getId())) { otherAppGroupRoot = group; // 其他用户组 continue; } otherGroups.add(group); } List<Application> apps = new ArrayList<Application>(); apps.add(applicationDao.getApplication(applicationId)); return new Object[]{otherAppGroupRoot, otherGroups, apps}; } public void createNewGroup(Group group, String userIdsStr, String roleIdsStr) { Long parentId = group.getParentId(); group.setSeqNo(groupDao.getNextSeqNo(parentId)); group.setDisabled(groupDao.getEntity(parentId).getDisabled()); groupDao.saveGroup(group); saveGroupToUser(group.getId(), userIdsStr); saveGroupToRole(group.getId(), roleIdsStr); } public void editExistGroup(Group group, String userIdsStr, String roleIdsStr) { groupDao.saveGroup(group); // 其他用户组只是简单的编辑组的属性,也不改变关系,所以不能调用saveGroupToRole 和 saveGroupToUser if (Group.OTHER_GROUP_TYPE.equals(group.getGroupType())) return; saveGroupToRole(group.getId(), roleIdsStr); // 主用户组中组对用户的关系不能随便更改,所以不能调用saveGroupToUser if (Group.MAIN_GROUP_TYPE.equals(group.getGroupType())) return; // 只有辅助用户组可以选择组对应的用户(group2UserExistTree有效),可以调用saveGroupToUser方法 saveGroupToUser(group.getId(), userIdsStr); } /** 组对用户:先把该组对应的用户都找到,再把提交上来的用户和找到的数据比较,多的做增加操作。 */ private void saveGroupToUser(Long groupId, String userIdsStr) { List<?> group2Users = groupDao.findGroup2UserByGroupId(groupId); Map<Long, Object> historyMap = new HashMap<Long, Object>(); //把老的组对用户记录做成一个map,以"userId"为key for (Object temp : group2Users) { GroupUser groupUser = (GroupUser) temp; historyMap.put(groupUser.getUserId(), groupUser); } if ( !EasyUtils.isNullOrEmpty(userIdsStr) ) { String[] userIds = userIdsStr.split(","); for (String temp : userIds) { // 如果historyMap里面没有,则新增用户组对用户的关系;如果historyMap里面有,则从历史记录中移出;剩下的将被删除 Long userId = Long.valueOf(temp); if (historyMap.remove(userId) == null) { GroupUser group2User = new GroupUser(userId, groupId, groupUserDao.getNextSeqNo(groupId)); groupUserDao.create(group2User); } } } // historyMap中剩下的就是该删除的了 groupDao.deleteAll(historyMap.values()); } /** 组对角色。先把该组对应的角色都找到,再把提交上来的用户和找到的数据比较,多的做增加操作 */ private void saveGroupToRole(Long groupId, String roleIdsStr) { List<?> group2Roles = groupDao.findGroup2RoleByGroupId(groupId); Map<Long, Object> historyMap = new HashMap<Long, Object>();// 把老的组对角色记录做成一个map,以"roleId"为key for (Object temp : group2Roles) { RoleGroup roleGroup = (RoleGroup) temp; historyMap.put(roleGroup.getRoleId(), roleGroup); } if ( !EasyUtils.isNullOrEmpty(roleIdsStr) ) { String[] roleIds = roleIdsStr.split(","); for (String temp : roleIds) { // 如果historyMap里面没有,则新增用户组对角色的关系; 如果historyMap里面有,则从历史记录中移出;剩下的将被删除 Long roleId = Long.valueOf(temp); if (historyMap.remove(roleId) == null) { RoleGroup role2Group = new RoleGroup(); role2Group.setRoleId(roleId); role2Group.setGroupId(groupId); groupDao.createObject(role2Group); } } } // historyMap中剩下的就是该删除的了 groupDao.deleteAll(historyMap.values()); } public void moveGroup(Long groupId, Long toGroupId) { Group group = groupDao.getEntity(groupId); if (toGroupId.equals(group.getParentId())) return; //向自己的父节点移动,等于没有移动 if(groupDao.getParentsById(toGroupId).contains(group)) { throw new BusinessException("不能向自己里面的节点移动"); // 节点向自己或者自己的子节点 } group.setSeqNo(groupDao.getNextSeqNo(toGroupId)); group.setParentId(toGroupId); String oldDecode = group.getDecode(); //移动的oldDecode值肯定非null groupDao.moveGroup(group); //被拦截调整整个移动枝的decode值, 同时拦截资源补齐调整 // 移动后组的decode值改变了,需修复组下(包括子组)所有对应用户(GroupUser)的decode值。 String decode = group.getDecode(); List<?> list = groupDao.getEntities("from GroupUser o where o.decode like ?", oldDecode + "%" ); DecodeUtil.repairSubNodeDecode(list, oldDecode, decode); groupDao.flush(); //如果移动到的组是停用状态,则停用所有移动过来的组和里面的用户。(如果用户自己在移动的组中,则有可能把自己停用掉,允许这么做。) Group toGroup = groupDao.getEntity(toGroupId); if (UMConstants.TRUE.equals(toGroup.getDisabled()) && UMConstants.FALSE.equals(group.getDisabled())) { stopGroup(groupId); } } public void sortGroup(Long groupId, Long toGroupId, int direction) { Group sourceGroup = groupDao.getEntity(groupId); Long parentId = sourceGroup.getParentId(); // 要对父节点有排序权限才能够对此节点排序 String resourceTypeId = Group.getResourceType(sourceGroup.getGroupType()); List<?> parentOperations = PermissionHelper.getInstance().getOperationsByResource(resourceTypeId, parentId, Environment.getOperatorId()); if(!parentOperations.contains(UMConstants.GROUP_SORT_OPERRATION)) { throw new BusinessException("您对这一层树没有排序权限,排序失败!"); } List<Group> relationalGroups = groupDao.sort(groupId, toGroupId, direction); /* 排序后多个同级多个组(包括组下的子组)的decode值发生了变化,GroupUser的decode也需要跟着重新生成。 * 此处循环一次只维护当前组下的用户(GroupUser)decode值,不包括子组的。 */ for(Group temp : relationalGroups) { List<?> list = groupDao.getEntities("from GroupUser o where o.groupId = ?", temp.getId() ); // 排序后各几点的层级不变,老的decode和新的decode长度一致。 String decode = temp.getDecode(); DecodeUtil.repairSubNodeDecode(list, decode, decode); } groupDao.flush(); } public List<Group> copyGroup(Long groupId, Long toGroupId, boolean isCascadeUser) { Group copyGroup = groupDao.getEntity(groupId);// 获得将要拷贝的用户组 groupDao.evict(copyGroup); Group toGroup = null; if (toGroupId == null) {// 复制其他用户组的第一层节点,没有parentGroupId。临时造一个group出来 toGroup = new Group(); toGroup.setId(UMConstants.OTHER_APPLICATION_GROUP_ID); toGroup.setApplicationId(copyGroup.getApplicationId()); toGroup.setGroupType(copyGroup.getGroupType()); } else { toGroup = groupDao.getEntity(toGroupId);// 获得拷贝到的用户组 } /* 判断用户有没有拷贝用户组和用户的权限 */ checkCopyGroupPrivilege(copyGroup, toGroup); boolean isCopyInTheSameLevel = toGroup.getId().equals(copyGroup.getParentId()); // 是否同层复制 List<?> groups = groupDao.getVisibleSubGroups(groupId); Map<Long, Long> idMapping = new HashMap<Long, Long>(); // key:原组的id -- value:新组的id List<Group> result = new ArrayList<Group>(); for ( Object temp : groups ) { Group group = (Group) temp; Long sourceGroupId = group.getId(); // 新组复制之前的原组Id groupDao.evict(group); group.setId(null); group.setApplicationId(toGroup.getApplicationId()); group.setGroupType(toGroup.getGroupType()); group.setDisabled(toGroup.getDisabled()); if (sourceGroupId.equals(copyGroup.getId())) { group.setSeqNo(groupDao.getNextSeqNo(toGroup.getId())); group.setParentId(toGroup.getId()); if(isCopyInTheSameLevel) { group.setName(UMConstants.COPY_PREFIX_NAME + copyGroup.getName()); // 同层下复制,需要给组名添加前缀,以免重名 } } else { group.setParentId(idMapping.get(group.getParentId())); } group = groupDao.saveGroup(group); idMapping.put(sourceGroupId, group.getId()); result.add(group); } //只有从其他组复制到主用户组的时候才及联复制用户 !!!!!! if(isCascadeUser) { List<User> users = groupDao.getUsersByGroupIds(idMapping.keySet()); for (User otherUser : users) { User mainUser = new User(); BeanUtil.copy(mainUser, otherUser); mainUser.setId(null); mainUser.setApplicationId(UMConstants.TSS_APPLICATION_ID); mainUser.setAppUserId(null); mainUser.setDisabled(toGroup.getDisabled()); // 如果复制到的组是停用状态,则停用所有复制过来的组和里面的用户。无需判断权限。 mainUser = userDao.create(mainUser); otherUser.setAppUserId(mainUser.getId()); userDao.update(otherUser); // 新建一个用户组对应用户关系 saveGroupUser(idMapping.get(otherUser.getGroupId()), mainUser.getId()); } } return result; } /** 判断用户有没有拷贝用户组和用户的权限 */ private void checkCopyGroupPrivilege(Group copyGroup, Group toGroup) { String resourceTypeId = copyGroup.getResourceType(); // 将其他用户组复制到主用户组 if( !copyGroup.getGroupType().equals(toGroup.getGroupType()) ){ resourceTypeId = UMConstants.MAINGROUP_RESOURCE_TYPE_ID; // 主用户组资源id } //如果是复制,则toGroup为copyGroup父节点 List<?> parentOperations = PermissionHelper.getInstance().getOperationsByResource(resourceTypeId, toGroup.getId(), Environment.getOperatorId()); if(!parentOperations.contains(UMConstants.GROUP_ADD_OPERRATION)) { throw new BusinessException("对父组(即复制到的目标节点)没有新增权限,不能复制此节点!"); } } /** * 保存组对用户关系,并在groupUserDao中进行补齐。 * 对用户的权限信息也在groupUserDao.saveGroupUser方法中补齐。 */ private void saveGroupUser(Long groupId, Long userId) { GroupUser groupUser = new GroupUser(userId, groupId, groupUserDao.getNextSeqNo(groupId)); groupUserDao.saveGroupUser(groupUser); } public List<Group> copyGroup2OtherApp(Long groupId, Long appId){ Application application = applicationDao.getEntity(appId); List<?> groups = groupDao.getVisibleSubGroups(groupId); Map<Long, Long> idMapping = new HashMap<Long, Long>(); // key:原组的id -- value:新组的id List<Group> result = new ArrayList<Group>(); for (int i = 0; i < groups.size(); i++) { Group group = (Group) groups.get(i); Long sourceGroupId = group.getId(); // 新组复制之前的原组Id groupDao.evict(group); group.setId(null); group.setApplicationId(application.getApplicationId()); if (sourceGroupId.equals(groupId)) { group.setSeqNo(groupDao.getNextSeqNo(UMConstants.OTHER_APPLICATION_GROUP_ID)); group.setParentId(UMConstants.OTHER_APPLICATION_GROUP_ID); } else { group.setParentId(idMapping.get(group.getParentId())); } group = groupDao.saveGroup(group); idMapping.put(sourceGroupId, group.getId()); result.add(group); } return result; } public void startOrStopGroup(String applicationId, Long groupId, Integer disabled, Integer groupType) { String resourceTypeId = Group.getResourceType(groupType); if (UMConstants.TRUE.equals(disabled)) { // 停用 String operationId = UMConstants.GROUP_DISABLE_OPERRATION; if (!checkSubGroupsPermission(applicationId, groupId, resourceTypeId, operationId)) { throw new BusinessException("您对停用节点下的某些资源(用户组)没有停用操作权限,不能停用此节点!"); } stopGroup(groupId); } else { // 启用一个组,该组的父节点也得全部启用 List<?> groups = groupDao.getParentsById(groupId); String operationId = UMConstants.GROUP_ENABLE_OPERRATION; List<?> canDoGroups = resourcePermission.getParentResourceIds(applicationId, resourceTypeId, groupId, operationId, Environment.getOperatorId()); if (groups.size() > canDoGroups.size()) { throw new BusinessException("节点之上有用户组没有启用操作权限,不能启用此节点!"); } for(Iterator<?> it = groups.iterator();it.hasNext();){ Group group = (Group) it.next(); if(group.getDisabled().equals(UMConstants.TRUE)) { group.setDisabled(UMConstants.FALSE); groupDao.update(group); } } } } // 停用组以及组下的子组和所有的用户 private void stopGroup(Long groupId) { Group group = groupDao.getEntity(groupId); groupDao.executeHQL("update Group set disabled = ? where decode like ?", UMConstants.TRUE, group.getDecode() + "%"); /* * 停用主用户组和其他用户组需要停用组下的用户。停用辅助用户组不停用用户,因为辅助用户组当中的用户是从主用户组中选取的. * 停用其它用户组用户无需判断权限;停用主用户组用户上面已经判断过了。 */ Integer groupType = group.getGroupType(); if (Group.MAIN_GROUP_TYPE.equals(groupType) || Group.OTHER_GROUP_TYPE.equals(groupType)) { List<User> users = groupDao.getUsersByGroupIdDeeply(groupId); for( User user : users) { if(!UMConstants.TRUE.equals(user.getDisabled())){ user.setDisabled(UMConstants.TRUE); } } } } public void deleteGroup(String applicationId, Long groupId, Integer groupType) { if(groupDao.isOperatorInGroup(groupId, Environment.getOperatorId())) throw new BusinessException("当前用户在要操作的组中,不能删除此节点!"); Group group = groupDao.getEntity(groupId); String resourceTypeId = Group.getResourceType(groupType); String operationId = UMConstants.GROUP_DEL_OPERRATION; if ( !checkSubGroupsPermission(applicationId, groupId, resourceTypeId, operationId) ) { throw new BusinessException("没有删除用户组权限,不能删除此节点!"); } // 辅助用户组里面的用户都是从主用户组选过来的,所以删除的时候只是删除辅助用户组的结构,里面的用户是不删的 if ( Group.ASSISTANT_GROUP_TYPE.equals(groupType) ) {// 辅助用户组 groupDao.removeAssistmentGroup(group); } else {// 删除主用户组和其他用户组 groupDao.removeGroup(group); } } // 判断对所有子节点是否都拥有指定的操作权限 private boolean checkSubGroupsPermission(String applicationId, Long groupId, String resourceTypeId, String operationId) { List<?> allGroups = groupDao.getChildrenById(groupId); List<?> canDoGroups = resourcePermission.getSubResourceIds(applicationId, resourceTypeId, groupId, operationId, Environment.getOperatorId()); //如果将要操作的数量==能够操作的数量,说明对所有组都有操作权限,则返回true return allGroups.size() == canDoGroups.size(); } public void setPasswordRule(Long groupId, Long ruleId){ List<?> groups = groupDao.getVisibleSubGroups(groupId); for(Object temp : groups){ Group group = (Group) temp; group.setPasswordRuleId(ruleId); groupDao.saveGroup(group); } List<User> users = groupDao.getUsersByGroupIdDeeply(groupId); for(User user : users){ user.setPasswordRuleId(ruleId); userDao.update(user); } } //-------------------------------------用户组从其它用户组导入到主用户组,加入进度条显示------------------------------------------ public Map<String, Object> getImportGroupData(Long groupId, Long toGroupId){ Group copyGroup = getGroupById(groupId); groupDao.evict(copyGroup); Group toGroup = getGroupById(toGroupId); checkCopyGroupPrivilege(copyGroup, toGroup); List<?> groups = groupDao.getVisibleSubGroups(groupId); List<Long> groupIds = new ArrayList<Long>(); for (int i = 0; i < groups.size(); i++) { Group group = (Group) groups.get(i); groupIds.add(group.getId()); } List<User> users = groupDao.getUsersByGroupIds(groupIds); Map<String, Object> paramsMap = new HashMap<String, Object>(); paramsMap.put("groupId", groupId); paramsMap.put("toGroup", toGroup); paramsMap.put("groups", groups); paramsMap.put("users", users); return paramsMap; } public void execute(Map<String, Object> paramsMap, Progress progress) { Long groupId = (Long)paramsMap.get("groupId"); Group toGroup = (Group)paramsMap.get("toGroup"); List<?> groups = (List<?>)paramsMap.get("groups"); List<?> users = (List<?>)paramsMap.get("users"); Map<Long, Long> idMapping = copyGroup(groupId, groups, toGroup, progress); copyUser(users, idMapping, progress); } private Map<Long, Long> copyGroup(Long groupId, List<?> groups, Group toGroup, Progress progress){ Map<Long, Long> idMapping = new HashMap<Long, Long>(); // key:原组的id -- value:新组的id for (int i = 0; i < groups.size(); i++) { Group group = (Group) groups.get(i); Long sourceGroupId = group.getId(); // 新组复制之前的原组Id groupDao.evict(group); group.setId(null); group.setApplicationId(toGroup.getApplicationId()); group.setGroupType(toGroup.getGroupType()); if (sourceGroupId.equals(groupId)) { group.setSeqNo(groupDao.getNextSeqNo(toGroup.getId())); group.setParentId(toGroup.getId()); } else { group.setParentId(idMapping.get(group.getParentId())); } group = groupDao.saveGroup(group); idMapping.put(sourceGroupId, group.getId()); updateProgressInfo(progress, groups.size(), i); } return idMapping; } private void copyUser(List<?> users, Map<Long, Long> idMapping, Progress progress){ for (int i = 0; i < users.size(); i++) { User otherUser = (User) users.get(i); User mainGroupUser = new User(); BeanUtil.copy(mainGroupUser, otherUser); mainGroupUser.setId(null); mainGroupUser.setApplicationId(UMConstants.TSS_APPLICATION_ID); mainGroupUser.setAppUserId(null); String password = InfoEncoder.string2MD5(mainGroupUser.getLoginName() + "_" + mainGroupUser.getPassword()); mainGroupUser.setPassword(password); //加密密码 mainGroupUser = userDao.create(mainGroupUser); //设置主用户组和其它用户组用户的对应关系 otherUser.setAppUserId(mainGroupUser.getId()); userDao.create(otherUser); // 新建一个用户组对应用户关系 saveGroupUser(idMapping.get(otherUser.getGroupId()), mainGroupUser.getId()); updateProgressInfo(progress, users.size(), i); } } /** * 更新进度信息 */ private void updateProgressInfo(Progress progress, long total, int index){ groupDao.flush(); index = index + 1; // index 从0开始计数 if(index % 20 == 0) { progress.add(20); // 每复制20个更新一次进度信息 } else if(index == total) { progress.add(index % 20); // 如果已经同步完,则将总数除以20取余数做为本次完成个数来更新进度信息 } } }