package com.ctrip.framework.apollo.portal.spi.defaultimpl;
import com.ctrip.framework.apollo.portal.component.config.PortalConfig;
import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;
import com.ctrip.framework.apollo.portal.entity.po.Permission;
import com.ctrip.framework.apollo.portal.entity.po.Role;
import com.ctrip.framework.apollo.portal.entity.po.RolePermission;
import com.ctrip.framework.apollo.portal.entity.po.UserRole;
import com.ctrip.framework.apollo.portal.repository.PermissionRepository;
import com.ctrip.framework.apollo.portal.repository.RolePermissionRepository;
import com.ctrip.framework.apollo.portal.repository.RoleRepository;
import com.ctrip.framework.apollo.portal.repository.UserRoleRepository;
import com.ctrip.framework.apollo.portal.service.RolePermissionService;
import com.google.common.base.Preconditions;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
/**
* Created by timothy on 2017/4/26.
*/
public class DefaultRolePermissionService implements RolePermissionService {
@Autowired
private RoleRepository roleRepository;
@Autowired
private RolePermissionRepository rolePermissionRepository;
@Autowired
private UserRoleRepository userRoleRepository;
@Autowired
private PermissionRepository permissionRepository;
@Autowired
private PortalConfig portalConfig;
/**
* Create role with permissions, note that role name should be unique
*/
@Transactional
public Role createRoleWithPermissions(Role role, Set<Long> permissionIds) {
Role current = findRoleByRoleName(role.getRoleName());
Preconditions.checkState(current == null, "Role %s already exists!", role.getRoleName());
Role createdRole = roleRepository.save(role);
if (!CollectionUtils.isEmpty(permissionIds)) {
Iterable<RolePermission> rolePermissions = FluentIterable.from(permissionIds).transform(
permissionId -> {
RolePermission rolePermission = new RolePermission();
rolePermission.setRoleId(createdRole.getId());
rolePermission.setPermissionId(permissionId);
rolePermission.setDataChangeCreatedBy(createdRole.getDataChangeCreatedBy());
rolePermission.setDataChangeLastModifiedBy(createdRole.getDataChangeLastModifiedBy());
return rolePermission;
});
rolePermissionRepository.save(rolePermissions);
}
return createdRole;
}
/**
* Assign role to users
*
* @return the users assigned roles
*/
@Transactional
public Set<String> assignRoleToUsers(String roleName, Set<String> userIds,
String operatorUserId) {
Role role = findRoleByRoleName(roleName);
Preconditions.checkState(role != null, "Role %s doesn't exist!", roleName);
List<UserRole> existedUserRoles =
userRoleRepository.findByUserIdInAndRoleId(userIds, role.getId());
Set<String> existedUserIds =
FluentIterable.from(existedUserRoles).transform(userRole -> userRole.getUserId()).toSet();
Set<String> toAssignUserIds = Sets.difference(userIds, existedUserIds);
Iterable<UserRole> toCreate = FluentIterable.from(toAssignUserIds).transform(userId -> {
UserRole userRole = new UserRole();
userRole.setRoleId(role.getId());
userRole.setUserId(userId);
userRole.setDataChangeCreatedBy(operatorUserId);
userRole.setDataChangeLastModifiedBy(operatorUserId);
return userRole;
});
userRoleRepository.save(toCreate);
return toAssignUserIds;
}
/**
* Remove role from users
*/
@Transactional
public void removeRoleFromUsers(String roleName, Set<String> userIds, String operatorUserId) {
Role role = findRoleByRoleName(roleName);
Preconditions.checkState(role != null, "Role %s doesn't exist!", roleName);
List<UserRole> existedUserRoles =
userRoleRepository.findByUserIdInAndRoleId(userIds, role.getId());
for (UserRole userRole : existedUserRoles) {
userRole.setDeleted(true);
userRole.setDataChangeLastModifiedTime(new Date());
userRole.setDataChangeLastModifiedBy(operatorUserId);
}
userRoleRepository.save(existedUserRoles);
}
/**
* Query users with role
*/
public Set<UserInfo> queryUsersWithRole(String roleName) {
Role role = findRoleByRoleName(roleName);
if (role == null) {
return Collections.emptySet();
}
List<UserRole> userRoles = userRoleRepository.findByRoleId(role.getId());
Set<UserInfo> users = FluentIterable.from(userRoles).transform(userRole -> {
UserInfo userInfo = new UserInfo();
userInfo.setUserId(userRole.getUserId());
return userInfo;
}).toSet();
return users;
}
/**
* Find role by role name, note that roleName should be unique
*/
public Role findRoleByRoleName(String roleName) {
return roleRepository.findTopByRoleName(roleName);
}
/**
* Check whether user has the permission
*/
public boolean userHasPermission(String userId, String permissionType, String targetId) {
Permission permission =
permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId);
if (permission == null) {
return false;
}
if (isSuperAdmin(userId)) {
return true;
}
List<UserRole> userRoles = userRoleRepository.findByUserId(userId);
if (CollectionUtils.isEmpty(userRoles)) {
return false;
}
Set<Long> roleIds =
FluentIterable.from(userRoles).transform(userRole -> userRole.getRoleId()).toSet();
List<RolePermission> rolePermissions = rolePermissionRepository.findByRoleIdIn(roleIds);
if (CollectionUtils.isEmpty(rolePermissions)) {
return false;
}
for (RolePermission rolePermission : rolePermissions) {
if (rolePermission.getPermissionId() == permission.getId()) {
return true;
}
}
return false;
}
public boolean isSuperAdmin(String userId) {
return portalConfig.superAdmins().contains(userId);
}
/**
* Create permission, note that permissionType + targetId should be unique
*/
@Transactional
public Permission createPermission(Permission permission) {
String permissionType = permission.getPermissionType();
String targetId = permission.getTargetId();
Permission current =
permissionRepository.findTopByPermissionTypeAndTargetId(permissionType, targetId);
Preconditions.checkState(current == null,
"Permission with permissionType %s targetId %s already exists!", permissionType, targetId);
return permissionRepository.save(permission);
}
/**
* Create permissions, note that permissionType + targetId should be unique
*/
@Transactional
public Set<Permission> createPermissions(Set<Permission> permissions) {
Multimap<String, String> targetIdPermissionTypes = HashMultimap.create();
for (Permission permission : permissions) {
targetIdPermissionTypes.put(permission.getTargetId(), permission.getPermissionType());
}
for (String targetId : targetIdPermissionTypes.keySet()) {
Collection<String> permissionTypes = targetIdPermissionTypes.get(targetId);
List<Permission> current =
permissionRepository.findByPermissionTypeInAndTargetId(permissionTypes, targetId);
Preconditions.checkState(CollectionUtils.isEmpty(current),
"Permission with permissionType %s targetId %s already exists!", permissionTypes,
targetId);
}
Iterable<Permission> results = permissionRepository.save(permissions);
return FluentIterable.from(results).toSet();
}
}