1. 迁移角色相关逻辑

2. admin-web 接入角色新接口
This commit is contained in:
YunaiV 2020-04-29 21:57:09 +08:00
parent 0763551d6d
commit e4048f8716
36 changed files with 221 additions and 186 deletions

View File

@ -2,9 +2,9 @@ import { message } from 'antd';
import { arrayToStringParams } from '../../utils/request.qs';
import { buildTreeNode, findAllNodes, findCheckedKeys } from '../../utils/tree.utils';
import {
queryRoleResourceTree,
roleAssignResource,
} from '../../services/admin';
authorizationRoleResourceTree,
authorizationRoleAssignResource,
} from '../../services/system';
import {
rolePage,
roleAdd,
@ -83,9 +83,9 @@ export default {
payload: true,
});
const response = yield call(queryRoleResourceTree, payload);
const response = yield call(authorizationRoleResourceTree, payload);
const roleResourceTree = response.data;
const roleTreeData = buildTreeNode(roleResourceTree, 'displayName', 'id');
const roleTreeData = buildTreeNode(roleResourceTree, 'name', 'id');
const checkedKeys = findCheckedKeys(roleResourceTree);
yield put({
@ -102,13 +102,13 @@ export default {
});
},
*roleAssignResource({ payload }, { call }) {
const { id, resourceIds, roleTreeData } = payload;
const { roleId, resourceIds, roleTreeData } = payload;
const assignNodes = findAllNodes(resourceIds, roleTreeData);
const params = {
id,
roleId,
resourceIds: arrayToStringParams(assignNodes),
};
const response = yield call(roleAssignResource, params);
const response = yield call(authorizationRoleAssignResource, params);
if (response.code === 0) {
message.info('操作成功!');
}

View File

@ -168,7 +168,7 @@ class RoleList extends PureComponent {
dispatch({
type: 'roleList/queryRoleAssign',
payload: {
id: record.id,
roleId: record.id,
},
});
this.setState({
@ -200,7 +200,7 @@ class RoleList extends PureComponent {
dispatch({
type: 'roleList/roleAssignResource',
payload: {
id: roleAssignRecord.id,
roleId: roleAssignRecord.id,
resourceIds: data.checkedKeys,
roleTreeData: data.roleTreeData,
},

View File

@ -82,28 +82,14 @@ export async function deptTreeAll() {
});
}
// resource
// role
export async function queryRoleResourceTree(params) {
return request(`/admin-api/admins/role/resource_tree?${stringify(params)}`, {
method: 'GET',
});
}
export async function roleAssignResource(params) {
return request(`/admin-api/admins/role/assign_resource?${stringify(params)}`, {
method: 'POST',
body: {
...params,
},
});
}
// dictionary

View File

@ -24,6 +24,19 @@ export async function authorizationResourcePermissions(params) {
});
}
export async function authorizationRoleResourceTree(params) {
return request(`/system-api/admins/authorization/role_resource_tree?${stringify(params)}`, {
method: 'GET',
});
}
export async function authorizationRoleAssignResource(params) {
return request(`/system-api/admins/authorization/assign_role_resource?${stringify(params)}`, {
method: 'POST',
body: {},
});
}
// ========== Resource 模块 ==========
export async function resourceTree(params) {

View File

@ -7,7 +7,7 @@ import java.io.Serializable;
public final class CommonResult<T> implements Serializable {
public static Integer CODE_SUCCESS = 0;
private static Integer CODE_SUCCESS = 0;
/**
* 错误码
@ -93,4 +93,5 @@ public final class CommonResult<T> implements Serializable {
", data=" + data +
'}';
}
}

View File

@ -52,7 +52,6 @@ public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable {
ROLE_NOT_EXISTS(1002004000, "角色不存在"),
ROLE_NAME_DUPLICATE(1002004001, "已经存在名为【{}}】的角色"),
ROLE_CODE_DUPLICATE(1002004002, "已经存在编码为【{}}】的角色"),
// ROLE_ASSIGN_RESOURCE_NOT_EXISTS(1002004001, "分配角色资源时,有资源不存在"),
// ========== 数据字典模块 1002005000 ==========
// DATA_DICT_EXISTS(1002005000, "该数据字典已经存在"),
@ -77,6 +76,7 @@ public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable {
// ========== 授权模块 1002008000 ==========
AUTHORIZATION_PERMISSION_DENY(1002008001, "没有该操作权限"),
AUTHORIZATION_DEMO_PERMISSION_DENY(1002008002, "演示账号暂不允许写操作。欢迎加入我们的交流群http://t.cn/EKEr5WE"),
AUTHORIZATION_ROLE_ASSIGN_RESOURCE_NOT_EXISTS(1002004001, "分配角色资源时,有资源不存在"),
;

View File

@ -6,16 +6,16 @@ import lombok.experimental.Accessors;
import java.util.Date;
/**
* TODO 注释
* 认证模块 - 认证结果 BO
*/
@Data
@Accessors(chain = true)
public class OAuth2AccessTokenBO {
public class OAuth2AuthenticateBO {
/**
* 访问令牌
*/
private String id;
private String accessToken;
/**
* 刷新令牌
*/

View File

@ -1,6 +1,6 @@
package cn.iocoder.mall.system.biz.bo.user;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import lombok.Data;
import lombok.experimental.Accessors;
@ -13,6 +13,6 @@ public class UserAuthenticateBO {
private UserBO user;
private OAuth2AccessTokenBO token;
private OAuth2AuthenticateBO token;
}

View File

@ -1,6 +1,6 @@
package cn.iocoder.mall.system.biz.convert.oauth2;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@ -10,6 +10,6 @@ public interface OAuth2Convert {
OAuth2Convert INSTANCE = Mappers.getMapper(OAuth2Convert.class);
OAuth2AccessTokenBO convert(OAuth2AccessTokenDO bean);
OAuth2AuthenticateBO convert(OAuth2AccessTokenDO bean);
}

View File

@ -1,6 +1,6 @@
package cn.iocoder.mall.system.biz.convert.user;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.bo.user.UserAuthenticateBO;
import cn.iocoder.mall.system.biz.bo.user.UserBO;
import cn.iocoder.mall.system.biz.dataobject.user.UserDO;
@ -15,7 +15,7 @@ public interface UserConvert {
@Mapping(source = "userBO", target = "user")
@Mapping(source = "accessTokenBO", target = "token")
UserAuthenticateBO convert(UserBO userBO, OAuth2AccessTokenBO accessTokenBO);
UserAuthenticateBO convert(UserBO userBO, OAuth2AuthenticateBO accessTokenBO);
UserBO convert(UserDO bean);

View File

@ -30,6 +30,11 @@ public interface ResourceMapper extends BaseMapper<ResourceDO> {
.eqIfPresent("type", type));
}
default int selectCountByIdsAndType(Collection<Integer> ids, Integer type) {
return selectCount(new QueryWrapperX<ResourceDO>().inIfPresent("id", ids)
.eqIfPresent("type", type));
}
default int selectCountByPid(Integer pid) {
return selectCount(new QueryWrapper<ResourceDO>().eq("pid", pid));
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.mall.system.biz.dto.authorization;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Set;
/**
* 授权模块 - 分配角色资源 DTO
*/
@Data
@Accessors(chain = true)
public class AuthorizationAssignRoleResourceDTO {
@NotNull(message = "管理员编号不能为空")
private Integer adminId;
@NotNull(message = "角色编号不能为空")
private Integer roleId;
/**
* 资源编号数组
*/
private Set<Integer> resourceIds;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.mall.system.biz.dto.authorization;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Collection;
/**
* 资源模块 - 获得资源总数 DTO
*/
@Data
@Accessors(chain = true)
public class ResourceCountDTO {
/**
* 资源编号数组
*/
private Collection<Integer> ids;
/**
* 资源类型
*/
private Integer type;
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.mall.system.biz.service.authorization;
import cn.iocoder.common.framework.exception.ServiceException;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationAssignRoleResourceDTO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationCheckPermissionsDTO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetRoleResourcesDTO;
@ -50,4 +51,10 @@ public interface AuthorizationService {
*/
Set<Integer> getRoleResources(AuthorizationGetRoleResourcesDTO getRoleResourcesDTO);
/**
* 给指定权限授予权限如果更新失败则抛出 {@link ServiceException} 异常
*
* @param assignRoleResourceDTO 授予权限 DTO
*/
void assignRoleResource(AuthorizationAssignRoleResourceDTO assignRoleResourceDTO);
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.mall.system.biz.service.authorization;
import cn.iocoder.common.framework.util.CollectionUtil;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.mall.mybatis.enums.DeletedStatusEnum;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
import cn.iocoder.mall.system.biz.dao.authorization.AccountRoleMapper;
@ -9,6 +10,7 @@ import cn.iocoder.mall.system.biz.dao.authorization.RoleResourceMapper;
import cn.iocoder.mall.system.biz.dataobject.authorization.AccountRoleDO;
import cn.iocoder.mall.system.biz.dataobject.authorization.RoleResourceDO;
import cn.iocoder.mall.system.biz.dto.authorization.*;
import cn.iocoder.mall.system.biz.enums.SystemErrorCodeEnum;
import cn.iocoder.mall.system.biz.event.authorization.ResourceDeleteEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -16,6 +18,7 @@ import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.mall.system.biz.enums.SystemErrorCodeEnum.AUTHORIZATION_PERMISSION_DENY;
@ -128,6 +131,37 @@ public class AuthorizationServiceImpl implements AuthorizationService {
return CollectionUtil.convertSet(roleResourceDOs, RoleResourceDO::getResourceId);
}
@Override
public void assignRoleResource(AuthorizationAssignRoleResourceDTO assignRoleResourceDTO) {
Integer roleId = assignRoleResourceDTO.getRoleId();
Set<Integer> resourceIds = assignRoleResourceDTO.getResourceIds();
// 校验角色是否存在
if (roleService.getRole(roleId) == null) {
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.ROLE_NOT_EXISTS.getCode());
}
// 校验是否有不存在的资源
if (!CollectionUtil.isEmpty(resourceIds)) {
int dbResourceSize = resourceService.countResource(new ResourceCountDTO().setIds(resourceIds));
if (resourceIds.size() != dbResourceSize) {
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.AUTHORIZATION_ROLE_ASSIGN_RESOURCE_NOT_EXISTS.getCode());
}
}
// TODO 芋艿这里先简单实现即方式是删除老的分配的资源关系然后添加新的分配的资源关系
// 标记角色原资源关系都为删除
roleResourceMapper.deleteByRoleId(roleId);
// 创建 RoleResourceDO 数组并插入到数据库
if (!CollectionUtil.isEmpty(resourceIds)) {
List<RoleResourceDO> roleResources = resourceIds.stream().map(resourceId -> {
RoleResourceDO roleResource = new RoleResourceDO().setRoleId(roleId).setResourceId(resourceId);
roleResource.setCreateTime(new Date());
roleResource.setDeleted(DeletedStatusEnum.DELETED_NO.getValue());
return roleResource;
}).collect(Collectors.toList());
roleResourceMapper.insertList(roleResources);
}
// TODO 插入操作日志
}
@EventListener
public void handleResourceDeleteEvent(ResourceDeleteEvent event) {
roleResourceMapper.deleteByResourceId(event.getId());

View File

@ -17,6 +17,8 @@ public interface ResourceService {
List<ResourceBO> getResources(ResourceGetListDTO getListDTO);
int countResource(ResourceCountDTO countDTO);
/**
* 获得资源树
*

View File

@ -43,6 +43,11 @@ public class ResourceServiceImpl implements ResourceService {
return ResourceConvert.INSTANCE.convertList(resourceDOs);
}
@Override
public int countResource(ResourceCountDTO countDTO) {
return resourceMapper.selectCountByIdsAndType(countDTO.getIds(), countDTO.getType());
}
@Override
public List<ResourceTreeNodeBO> getResourceTree(ResourceGetTreeDTO getTreeDTO) {
// 获得对应的资源列表

View File

@ -15,6 +15,8 @@ import java.util.List;
*/
public interface RoleService {
RoleBO getRole(Integer id);
List<RoleBO> getRoleList(Collection<Integer> ids);
PageResult<RoleBO> getRolePage(RolePageDTO pageDTO);

View File

@ -15,7 +15,6 @@ import cn.iocoder.mall.system.biz.dto.authorization.RoleUpdateDTO;
import cn.iocoder.mall.system.biz.enums.SystemErrorCodeEnum;
import cn.iocoder.mall.system.biz.enums.authorization.RoleCodeEnum;
import cn.iocoder.mall.system.biz.event.authorization.ResourceDeleteEvent;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@ -34,16 +33,19 @@ public class RoleServiceImpl implements RoleService {
@Autowired
private RoleMapper roleMapper;
@Override
public RoleBO getRole(Integer id) {
return RoleConvert.INSTANCE.convert(roleMapper.selectById(id));
}
@Override
public List<RoleBO> getRoleList(Collection<Integer> ids) {
List<RoleDO> roleDOs = roleMapper.selectBatchIds(ids);
return RoleConvert.INSTANCE.convertList(roleDOs);
return RoleConvert.INSTANCE.convertList(roleMapper.selectBatchIds(ids));
}
@Override
public PageResult<RoleBO> getRolePage(RolePageDTO pageDTO) {
IPage<RoleDO> pageResult = roleMapper.selectPage(pageDTO);
return RoleConvert.INSTANCE.convertPage(pageResult);
return RoleConvert.INSTANCE.convertPage(roleMapper.selectPage(pageDTO));
}
@Override
@ -94,9 +96,9 @@ public class RoleServiceImpl implements RoleService {
}
// 更新到数据库标记删除
roleMapper.deleteById(roleDeleteDTO.getId());
// TODO 插入操作日志
// 发布角色删除事件方便清理关联表
eventPublisher.publishEvent(new ResourceDeleteEvent(this, roleDeleteDTO.getId()));
// TODO 插入操作日志
}
/**

View File

@ -1,6 +1,6 @@
package cn.iocoder.mall.system.biz.service.oauth2;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2AccessTokenAuthenticateDTO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2MobileCodeAuthenticateDTO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO;
@ -10,10 +10,10 @@ import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO;
*/
public interface OAuth2Service {
OAuth2AccessTokenBO authenticate(OAuth2UsernameAuthenticateDTO authenticateDTO);
OAuth2AuthenticateBO authenticate(OAuth2UsernameAuthenticateDTO authenticateDTO);
OAuth2AccessTokenBO authenticate(OAuth2MobileCodeAuthenticateDTO authenticateDTO);
OAuth2AuthenticateBO authenticate(OAuth2MobileCodeAuthenticateDTO authenticateDTO);
OAuth2AccessTokenBO authenticate(OAuth2AccessTokenAuthenticateDTO authenticateDTO);
OAuth2AuthenticateBO authenticate(OAuth2AccessTokenAuthenticateDTO authenticateDTO);
}

View File

@ -4,7 +4,7 @@ import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.util.ValidationUtil;
import cn.iocoder.mall.system.biz.bo.account.AccountBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.convert.oauth2.OAuth2Convert;
import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2AccessTokenMapper;
import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2RefreshTokenMapper;
@ -53,7 +53,7 @@ public class OAuth2ServiceImpl implements OAuth2Service {
@Override
@Transactional
public OAuth2AccessTokenBO authenticate(OAuth2UsernameAuthenticateDTO authenticateDTO) {
public OAuth2AuthenticateBO authenticate(OAuth2UsernameAuthenticateDTO authenticateDTO) {
// 获得账号
AccountBO accountBO = accountService.getByUsername(authenticateDTO.getUsername());
if (accountBO == null) {
@ -73,7 +73,7 @@ public class OAuth2ServiceImpl implements OAuth2Service {
@Override
@Transactional
public OAuth2AccessTokenBO authenticate(OAuth2MobileCodeAuthenticateDTO authenticateDTO) {
public OAuth2AuthenticateBO authenticate(OAuth2MobileCodeAuthenticateDTO authenticateDTO) {
// 校验手机格式
if (!ValidationUtil.isMobile(authenticateDTO.getMobile())) {
throw ServiceExceptionUtil.exception(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "手机格式不正确"); // TODO 有点搓
@ -98,7 +98,7 @@ public class OAuth2ServiceImpl implements OAuth2Service {
}
@Override
public OAuth2AccessTokenBO authenticate(OAuth2AccessTokenAuthenticateDTO authenticateDTO) {
public OAuth2AuthenticateBO authenticate(OAuth2AccessTokenAuthenticateDTO authenticateDTO) {
OAuth2AccessTokenDO oauth2AccessTokenDO = oauth2AccessTokenMapper.selectById(authenticateDTO.getAccessToken());
if (oauth2AccessTokenDO == null) { // 不存在
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.OAUTH2_ACCESS_TOKEN_NOT_FOUND.getCode());

View File

@ -1,7 +1,7 @@
package cn.iocoder.mall.system.biz.service.user;
import cn.iocoder.mall.mybatis.enums.DeletedStatusEnum;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.bo.user.UserAuthenticateBO;
import cn.iocoder.mall.system.biz.bo.user.UserBO;
import cn.iocoder.mall.system.biz.convert.user.UserConvert;
@ -26,7 +26,7 @@ public class UserServiceImpl implements UserService {
@Transactional
public UserAuthenticateBO authenticate(OAuth2MobileCodeAuthenticateDTO authenticateDTO) {
// 执行认证
OAuth2AccessTokenBO accessTokenBO = oAuth2Service.authenticate(authenticateDTO);
OAuth2AuthenticateBO accessTokenBO = oAuth2Service.authenticate(authenticateDTO);
// 获得用户
UserDO userDO = userMapper.selectById(accessTokenBO.getAccountId());
if (userDO == null) {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.mall.admin.dao.RoleResourceMapper">
<mapper namespace="cn.iocoder.mall.system.biz.dao.authorization.RoleResourceMapper">
<insert id="insertList">
INSERT INTO role_resource (

View File

@ -5,6 +5,7 @@ import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.security.core.context.AdminSecurityContextHolder;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationAssignRoleResourceDTO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetResourcesByAccountIdDTO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationGetRoleResourcesDTO;
import cn.iocoder.mall.system.biz.dto.authorization.ResourceGetTreeDTO;
@ -12,6 +13,7 @@ import cn.iocoder.mall.system.biz.enums.authorization.ResourceTypeEnum;
import cn.iocoder.mall.system.biz.service.authorization.AuthorizationService;
import cn.iocoder.mall.system.biz.service.authorization.ResourceService;
import cn.iocoder.mall.system.rest.convert.authorization.AdminsAuthorizationConvert;
import cn.iocoder.mall.system.rest.request.authorization.AdminsAuthorizationAssignRoleResourceRequest;
import cn.iocoder.mall.system.rest.response.authorization.AdminsAuthorizationMenuTreeResponse;
import cn.iocoder.mall.system.rest.response.authorization.AdminsAuthorizationRoleResourceTreeResponse;
import io.swagger.annotations.Api;
@ -19,10 +21,7 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
@ -55,10 +54,10 @@ public class AdminsAuthorizationController {
return CommonResult.success(resources.stream().map(ResourceBO::getRoute).collect(Collectors.toSet()));
}
@GetMapping("/role_tree")
@GetMapping("/role_resource_tree")
@ApiOperation(value = "获得角色拥有的菜单权限", notes = "以树结构返回。注意,返回的资源树是完整的结构,会标记每个资源节点是否被角色所拥有")
@ApiImplicitParam(name = "roleId", value = "角色编号", required = true, example = "1")
public CommonResult<List<AdminsAuthorizationRoleResourceTreeResponse>> roleTree(@RequestParam("roleId") Integer roleId) {
public CommonResult<List<AdminsAuthorizationRoleResourceTreeResponse>> roleResourceTree(@RequestParam("roleId") Integer roleId) {
// 1. 获得完整的资源树
List<ResourceTreeNodeBO> resourceTreeNodeBOs = resourceService.getResourceTree(new ResourceGetTreeDTO());
// 2. 获得角色拥有的子树
@ -67,4 +66,13 @@ public class AdminsAuthorizationController {
return CommonResult.success(AdminsAuthorizationConvert.INSTANCE.convertList(resourceTreeNodeBOs, roleResourceIds));
}
@PostMapping("/assign_role_resource")
@ApiOperation(value = "分配角色资源")
public CommonResult<Boolean> assignRoleResource(AdminsAuthorizationAssignRoleResourceRequest request) {
AuthorizationAssignRoleResourceDTO authorizationAssignRoleResourceDTO = AdminsAuthorizationConvert.INSTANCE.convert(request)
.setAdminId(AdminSecurityContextHolder.getAdminId());
authorizationService.assignRoleResource(authorizationAssignRoleResourceDTO);
return CommonResult.success(true);
}
}

View File

@ -70,11 +70,6 @@ public class AdminsRoleController {
}
//
// @PostMapping("/assign_role")
// @ApiOperation(value = "分配角色资源")
// public CommonResult<Boolean> assignRole(RoleAssignRoleDTO roleAssignRoleDTO) {
// return success(roleService.assignRoleRole(AdminSecurityContextHolder.getContext().getAdminId(), roleAssignRoleDTO));
// }
}

View File

@ -5,7 +5,7 @@ import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.security.core.annotation.RequiresNone;
import cn.iocoder.mall.system.biz.bo.admin.AdminBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO;
import cn.iocoder.mall.system.biz.service.admin.AdminService;
import cn.iocoder.mall.system.biz.service.oauth2.OAuth2Service;
@ -37,7 +37,7 @@ public class AdminsOAuth2Controller {
public CommonResult<AdminsOAuth2AuthenticateResponse> usernameAuthenticate(AdminsOAuth2UsernameAuthenticateRequest request) {
// 执行认证
OAuth2UsernameAuthenticateDTO authenticateDTO = AdminsOAuth2Convert.INSTANCE.convert(request);
OAuth2AccessTokenBO accessTokenBO = oauth2Service.authenticate(authenticateDTO);
OAuth2AuthenticateBO accessTokenBO = oauth2Service.authenticate(authenticateDTO);
// 获得 Admin 信息
AdminBO adminBO = adminService.getAdmin(accessTokenBO.getAccountId());
if (adminBO == null) {

View File

@ -2,6 +2,8 @@ package cn.iocoder.mall.system.rest.convert.authorization;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceBO;
import cn.iocoder.mall.system.biz.bo.authorization.ResourceTreeNodeBO;
import cn.iocoder.mall.system.biz.dto.authorization.AuthorizationAssignRoleResourceDTO;
import cn.iocoder.mall.system.rest.request.authorization.AdminsAuthorizationAssignRoleResourceRequest;
import cn.iocoder.mall.system.rest.response.authorization.AdminsAuthorizationMenuTreeResponse;
import cn.iocoder.mall.system.rest.response.authorization.AdminsAuthorizationRoleResourceTreeResponse;
import org.mapstruct.Mapper;
@ -32,18 +34,22 @@ public interface AdminsAuthorizationConvert {
List<AdminsAuthorizationMenuTreeResponse> convertList(List<ResourceTreeNodeBO> beans);
default List<AdminsAuthorizationRoleResourceTreeResponse> convertList(List<ResourceTreeNodeBO> beans, Set<Integer> roleResourceIds) {
if (beans == null) {
return null;
}
List<AdminsAuthorizationRoleResourceTreeResponse> responses = new ArrayList<>(beans.size());
for (ResourceTreeNodeBO bean : beans) {
// 转换
AdminsAuthorizationRoleResourceTreeResponse response = this.convert2(bean);
response.setAssign(roleResourceIds.contains(bean.getNode().getId()));
response.setAssigned(roleResourceIds.contains(bean.getNode().getId()));
// 递归子节点
this.convertList(bean.getChildren(), roleResourceIds);
response.setChildren(this.convertList(bean.getChildren(), roleResourceIds));
// 添加到结果
responses.add(response);
}
return responses;
}
AuthorizationAssignRoleResourceDTO convert(AdminsAuthorizationAssignRoleResourceRequest request);
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.mall.system.rest.convert.oauth2;
import cn.iocoder.mall.system.biz.bo.admin.AdminBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO;
import cn.iocoder.mall.system.rest.request.oauth2.AdminsOAuth2UsernameAuthenticateRequest;
import cn.iocoder.mall.system.rest.response.oauth2.AdminsOAuth2AuthenticateResponse;
@ -20,6 +20,6 @@ public interface AdminsOAuth2Convert {
@Mapping(source = "accessTokenBO.id", target = "token.accessToken")
@Mapping(source = "accessTokenBO.refreshToken", target = "token.refreshToken")
@Mapping(source = "accessTokenBO.expiresTime", target = "token.expiresTime")
AdminsOAuth2AuthenticateResponse convert(AdminBO adminBO, OAuth2AccessTokenBO accessTokenBO);
AdminsOAuth2AuthenticateResponse convert(AdminBO adminBO, OAuth2AuthenticateBO accessTokenBO);
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.mall.system.rest.request.authorization;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.util.Set;
@ApiModel(value = "管理员 - 授权模块 - 分配角色资源 Request")
@Data
@Accessors(chain = true)
public class AdminsAuthorizationAssignRoleResourceRequest {
@ApiModelProperty(value = "角色编号", required = true, example = "1")
@NotNull(message = "角色编号不能为空")
private Integer roleId;
@ApiModelProperty(value = "资源编号数组", example = "1,2")
private Set<Integer> resourceIds;
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.mall.system.rest.request.authorization;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ApiModel("管理员 - 角色模块 - 修改角色 Request")
@Data
@Accessors(chain = true)
public class RoleUpdateDTO {
@ApiModelProperty(value = "角色编号", required = true, example = "123")
@NotNull(message = "角色编号不能为空")
private Integer id;
@ApiModelProperty(value = "角色名字", required = true, example = "系统管理员")
@NotEmpty(message = "角色名字不能为空")
private String name;
@ApiModelProperty(value = "角色编码", example = "SUPER_ADMIN")
private String code;
}

View File

@ -7,7 +7,7 @@ import lombok.experimental.Accessors;
import java.util.List;
@ApiModel(value = "管理员 - 授权模块 - 菜单资源树", description = "一般用于首页菜单树")
@ApiModel(value = "管理员 - 授权模块 - 菜单资源树 Response", description = "一般用于首页菜单树")
@Data
@Accessors(chain = true)
public class AdminsAuthorizationMenuTreeResponse {

View File

@ -7,7 +7,7 @@ import lombok.experimental.Accessors;
import java.util.List;
@ApiModel(value = "管理员 - 授权模块 - 角色拥有的资源树")
@ApiModel(value = "管理员 - 授权模块 - 角色拥有的资源树 Response")
@Data
@Accessors(chain = true)
public class AdminsAuthorizationRoleResourceTreeResponse {
@ -17,7 +17,7 @@ public class AdminsAuthorizationRoleResourceTreeResponse {
@ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
private String name;
@ApiModelProperty(value = "是否分配", required = true, notes = "即角色是否拥有该资源")
private Boolean assign;
private Boolean assigned;
/**
* 子节点数组
*/

View File

@ -7,7 +7,7 @@ import lombok.experimental.Accessors;
import java.util.List;
@ApiModel("管理员 - 授权模块 - 菜单资源树")
@ApiModel("管理员 - 授权模块 - 菜单资源树 Response")
@Data
@Accessors(chain = true)
public class AdminsResourceTreeResponse {

View File

@ -1,6 +1,6 @@
package cn.iocoder.mall.system.rpc.convert.oauth2;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2AccessTokenAuthenticateDTO;
import cn.iocoder.mall.system.rpc.request.oauth2.OAuth2AccessTokenAuthenticateRequest;
import cn.iocoder.mall.system.rpc.response.oauth2.OAuth2AccessTokenResponse;
@ -14,6 +14,6 @@ public interface OAuth2Convert {
OAuth2AccessTokenAuthenticateDTO convert(OAuth2AccessTokenAuthenticateRequest authenticateRequest);
OAuth2AccessTokenResponse convert(OAuth2AccessTokenBO bean);
OAuth2AccessTokenResponse convert(OAuth2AuthenticateBO bean);
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.mall.system.rpc.rpc.oauth2;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AuthenticateBO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2AccessTokenAuthenticateDTO;
import cn.iocoder.mall.system.biz.service.oauth2.OAuth2Service;
import cn.iocoder.mall.system.rpc.api.oauth2.OAuth2RPC;
@ -21,7 +21,7 @@ public class OAuth2RPCImpl implements OAuth2RPC {
public CommonResult<OAuth2AccessTokenResponse> authenticate(OAuth2AccessTokenAuthenticateRequest authenticateRequest) {
// 执行认证
OAuth2AccessTokenAuthenticateDTO authenticateDTO = OAuth2Convert.INSTANCE.convert(authenticateRequest);
OAuth2AccessTokenBO accessTokenBO = oauth2Service.authenticate(authenticateDTO);
OAuth2AuthenticateBO accessTokenBO = oauth2Service.authenticate(authenticateDTO);
// 返回结果
OAuth2AccessTokenResponse accessTokenResponse = OAuth2Convert.INSTANCE.convert(accessTokenBO);
return CommonResult.success(accessTokenResponse);

View File

@ -1,79 +0,0 @@
package cn.iocoder.mall.admin.service;
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
import cn.iocoder.common.framework.util.CollectionUtil;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.system.api.RoleService;
import cn.iocoder.mall.system.api.bo.role.RoleBO;
import cn.iocoder.mall.system.api.constant.AdminErrorCodeEnum;
import cn.iocoder.mall.system.api.dto.role.RoleAddDTO;
import cn.iocoder.mall.system.api.dto.role.RoleAssignResourceDTO;
import cn.iocoder.mall.system.api.dto.role.RoleUpdateDTO;
import cn.iocoder.mall.admin.convert.RoleConvert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
@Service
@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.RoleService.version}")
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleResourceMapper roleResourceMapper;
@Autowired
private AdminRoleMapper adminRoleMapper;
@Autowired
private ResourceServiceImpl resourceService;
public List<RoleResourceDO> getRoleByResourceId(Integer resourceId) {
return roleResourceMapper.selectListByResourceId(resourceId);
}
@Override
@Transactional
public Boolean assignRoleResource(Integer adminId, RoleAssignResourceDTO roleAssignResourceDTO) {
Integer roleId = roleAssignResourceDTO.getId();
Set<Integer> resourceIds = roleAssignResourceDTO.getResourceIds();
// 校验角色是否存在
if (roleMapper.selectById(roleAssignResourceDTO.getId()) == null) {
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.RESOURCE_NOT_EXISTS.getCode());
}
// 校验是否有不存在的资源
if (!CollectionUtil.isEmpty(resourceIds)) {
List<ResourceDO> resources = resourceService.getResources(resourceIds);
if (resources.size() != resourceIds.size()) {
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.ROLE_ASSIGN_RESOURCE_NOT_EXISTS.getCode());
}
}
// TODO 芋艿这里先简单实现即方式是删除老的分配的资源关系然后添加新的分配的资源关系
// 标记角色原资源关系都为删除
roleResourceMapper.deleteByRoleId(roleId);
// 创建 RoleResourceDO 数组并插入到数据库
if (!CollectionUtil.isEmpty(resourceIds)) {
List<RoleResourceDO> roleResources = resourceIds.stream().map(resourceId -> {
RoleResourceDO roleResource = new RoleResourceDO().setRoleId(roleId).setResourceId(resourceId);
roleResource.setCreateTime(new Date());
roleResource.setDeleted(DeletedStatusEnum.DELETED_NO.getValue());
return roleResource;
}).collect(Collectors.toList());
roleResourceMapper.insertList(roleResources);
}
// TODO 插入操作日志
// 返回成功
return true;
}
public List<RoleDO> getRoles(Set<Integer> roleIds) {
if (CollectionUtil.isEmpty(roleIds)) {
return Collections.emptyList();
}
return roleMapper.selectBatchIds(roleIds);
}
}