diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/AdminApplication.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/AdminApplication.java similarity index 88% rename from admin/admin-application/src/main/java/cn/iocoder/mall/admin/AdminApplication.java rename to admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/AdminApplication.java index 46385f023..5513088f7 100644 --- a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/AdminApplication.java +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/AdminApplication.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.admin; +package cn.iocoder.mall.admin.application; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/config/MVCConfiguration.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/config/MVCConfiguration.java similarity index 97% rename from admin/admin-application/src/main/java/cn/iocoder/mall/admin/config/MVCConfiguration.java rename to admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/config/MVCConfiguration.java index 1de4d78a9..f052bb8a6 100644 --- a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/config/MVCConfiguration.java +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/config/MVCConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.admin.config; +package cn.iocoder.mall.admin.application.config; import cn.iocoder.common.framework.config.GlobalExceptionHandler; import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor; diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/config/SwaggerConfiguration.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/config/SwaggerConfiguration.java similarity index 95% rename from admin/admin-application/src/main/java/cn/iocoder/mall/admin/config/SwaggerConfiguration.java rename to admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/config/SwaggerConfiguration.java index a6b26cd2b..eae66c317 100644 --- a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/config/SwaggerConfiguration.java +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/config/SwaggerConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.admin.config; +package cn.iocoder.mall.admin.application.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/controller/AdminController.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/AdminController.java similarity index 50% rename from admin/admin-application/src/main/java/cn/iocoder/mall/admin/controller/AdminController.java rename to admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/AdminController.java index 4e08f3f7c..0c7248cdf 100644 --- a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/controller/AdminController.java +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/AdminController.java @@ -1,6 +1,9 @@ -package cn.iocoder.mall.admin.controller; +package cn.iocoder.mall.admin.application.controller; import cn.iocoder.common.framework.vo.CommonResult; +import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder; +import cn.iocoder.mall.admin.application.convert.AdminConvert; +import cn.iocoder.mall.admin.application.vo.AdminInfoVO; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -12,8 +15,8 @@ import org.springframework.web.bind.annotation.RestController; public class AdminController { @GetMapping("/info") - public CommonResult info() { - return null; + public CommonResult info() { + return CommonResult.success(AdminConvert.INSTANCE.convert(AdminSecurityContextHolder.getContext())); } } \ No newline at end of file diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/controller/PassportController.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/PassportController.java similarity index 89% rename from admin/admin-application/src/main/java/cn/iocoder/mall/admin/controller/PassportController.java rename to admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/PassportController.java index 4e5c5ef7f..e2cc2bdd3 100644 --- a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/controller/PassportController.java +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/PassportController.java @@ -1,10 +1,10 @@ -package cn.iocoder.mall.admin.controller; +package cn.iocoder.mall.admin.application.controller; import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.mall.admin.api.OAuth2Service; import cn.iocoder.mall.admin.api.bo.OAuth2AccessTokenBO; -import cn.iocoder.mall.admin.convert.PassportConvert; -import cn.iocoder.mall.admin.vo.PassportLoginVO; +import cn.iocoder.mall.admin.application.convert.PassportConvert; +import cn.iocoder.mall.admin.application.vo.PassportLoginVO; import com.alibaba.dubbo.config.annotation.Reference; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/ResourceController.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/ResourceController.java new file mode 100644 index 000000000..1316a6b25 --- /dev/null +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/controller/ResourceController.java @@ -0,0 +1,61 @@ +package cn.iocoder.mall.admin.application.controller; + +import cn.iocoder.common.framework.vo.CommonResult; +import cn.iocoder.mall.admin.api.ResourceService; +import cn.iocoder.mall.admin.api.bo.ResourceBO; +import cn.iocoder.mall.admin.api.constant.ResourceType; +import cn.iocoder.mall.admin.application.convert.ResourceConvert; +import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder; +import cn.iocoder.mall.admin.application.vo.AdminMenuTreeNodeVO; +import com.alibaba.dubbo.config.annotation.Reference; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("admin/resource") +@Api("资源模块") +public class ResourceController { + + @Reference + private ResourceService resourceService; + + @GetMapping("/admin_menu_tree") + @ApiOperation(value = "获得管理员拥有的菜单权限", notes = "以树结构返回") + public CommonResult> adminMenuTree() { + List resources = resourceService.getResourceByTypeAndRoleIds(ResourceType.MENU, AdminSecurityContextHolder.getContext().getRoleIds()); + // 创建 AdminMenuTreeNodeVO Map + Map treeNodeMap = resources.stream().collect(Collectors.toMap(ResourceBO::getId, ResourceConvert.INSTANCE::convert)); + // 处理父子关系 + treeNodeMap.values().stream().filter(node -> { + return node.getPid() != 0; // TODO magic number + }).forEach((childNode) -> { + // 获得父节点 + AdminMenuTreeNodeVO parentNode = treeNodeMap.get(childNode.getPid()); + if (parentNode.getChildren() == null) { // 初始化 children 数组 + parentNode.setChildren(new ArrayList<>()); + } + // 将自己添加到父节点中 + parentNode.getChildren().add(childNode); + }); + // 获得到所有的根节点 + List rootNodes = treeNodeMap.values().stream().filter(node -> { + return node.getPid() == 0; // TODO magic number + }).collect(Collectors.toList()); + return CommonResult.success(rootNodes); + } + + @GetMapping("/admin_url_list") + @ApiOperation(value = "获得管理员拥有的 URL 权限列表") + public CommonResult adminUrlList() { + return null; + } + +} \ No newline at end of file diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/AdminConvert.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/AdminConvert.java new file mode 100644 index 000000000..a97eb25ae --- /dev/null +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/AdminConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.mall.admin.application.convert; + +import cn.iocoder.mall.admin.sdk.context.AdminSecurityContext; +import cn.iocoder.mall.admin.application.vo.AdminInfoVO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AdminConvert { + + AdminConvert INSTANCE = Mappers.getMapper(AdminConvert.class); + + @Mappings({}) + AdminInfoVO convert(AdminSecurityContext adminSecurityContext); + +} \ No newline at end of file diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/convert/PassportConvert.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/PassportConvert.java similarity index 82% rename from admin/admin-application/src/main/java/cn/iocoder/mall/admin/convert/PassportConvert.java rename to admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/PassportConvert.java index 1572dfbfd..35389ac90 100644 --- a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/convert/PassportConvert.java +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/PassportConvert.java @@ -1,8 +1,8 @@ -package cn.iocoder.mall.admin.convert; +package cn.iocoder.mall.admin.application.convert; import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.mall.admin.api.bo.OAuth2AccessTokenBO; -import cn.iocoder.mall.admin.vo.PassportLoginVO; +import cn.iocoder.mall.admin.application.vo.PassportLoginVO; import org.mapstruct.Mapper; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/ResourceConvert.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/ResourceConvert.java new file mode 100644 index 000000000..71ac94cc6 --- /dev/null +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/convert/ResourceConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.mall.admin.application.convert; + +import cn.iocoder.mall.admin.api.bo.ResourceBO; +import cn.iocoder.mall.admin.application.vo.AdminMenuTreeNodeVO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface ResourceConvert { + + ResourceConvert INSTANCE = Mappers.getMapper(ResourceConvert.class); + + @Mappings({}) + AdminMenuTreeNodeVO convert(ResourceBO resourceBO); + +} diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/AdminInfoVO.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/AdminInfoVO.java new file mode 100644 index 000000000..25cf0e545 --- /dev/null +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/AdminInfoVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.mall.admin.application.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.Set; + +@ApiModel("管理员信息 VO") +public class AdminInfoVO { + + @ApiModelProperty(value = "管理员比那好", required = true, example = "1") + private Integer adminId; + @ApiModelProperty(value = "角色编号的数组", required = true, example = "[1, 2]") + private Set roleIds; + + public Integer getAdminId() { + return adminId; + } + + public AdminInfoVO setAdminId(Integer adminId) { + this.adminId = adminId; + return this; + } + + public Set getRoleIds() { + return roleIds; + } + + public AdminInfoVO setRoleIds(Set roleIds) { + this.roleIds = roleIds; + return this; + } + +} \ No newline at end of file diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/AdminMenuTreeNodeVO.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/AdminMenuTreeNodeVO.java new file mode 100644 index 000000000..39faf1f18 --- /dev/null +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/AdminMenuTreeNodeVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.mall.admin.application.vo; + +import java.util.List; + +public class AdminMenuTreeNodeVO { + + /** + * 菜单编号 + */ + private Integer id; + /** + * 彩蛋名 + */ + private String name; + /** + * 操作 + */ + private String handler; + /** + * 父菜单编号 + */ + private Integer pid; + /** + * 子节点数组 + */ + private List children; + + public Integer getId() { + return id; + } + + public AdminMenuTreeNodeVO setId(Integer id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public AdminMenuTreeNodeVO setName(String name) { + this.name = name; + return this; + } + + public String getHandler() { + return handler; + } + + public AdminMenuTreeNodeVO setHandler(String handler) { + this.handler = handler; + return this; + } + + public List getChildren() { + return children; + } + + public AdminMenuTreeNodeVO setChildren(List children) { + this.children = children; + return this; + } + + public Integer getPid() { + return pid; + } + + public AdminMenuTreeNodeVO setPid(Integer pid) { + this.pid = pid; + return this; + } +} diff --git a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/vo/PassportLoginVO.java b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/PassportLoginVO.java similarity index 96% rename from admin/admin-application/src/main/java/cn/iocoder/mall/admin/vo/PassportLoginVO.java rename to admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/PassportLoginVO.java index b1376bcde..7913f4c3f 100644 --- a/admin/admin-application/src/main/java/cn/iocoder/mall/admin/vo/PassportLoginVO.java +++ b/admin/admin-application/src/main/java/cn/iocoder/mall/admin/application/vo/PassportLoginVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.admin.vo; +package cn.iocoder.mall.admin.application.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; diff --git a/admin/admin-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java b/admin/admin-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java index 18a6fefb2..bfc580613 100644 --- a/admin/admin-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java +++ b/admin/admin-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java @@ -5,6 +5,7 @@ import cn.iocoder.common.framework.util.HttpUtil; import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.mall.admin.api.OAuth2Service; import cn.iocoder.mall.admin.api.bo.OAuth2AuthenticationBO; +import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum; import cn.iocoder.mall.admin.sdk.context.AdminSecurityContext; import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder; import com.alibaba.dubbo.config.annotation.Reference; @@ -38,6 +39,11 @@ public class AdminSecurityInterceptor extends HandlerInterceptorAdapter { // 添加到 AdminSecurityContext AdminSecurityContext context = new AdminSecurityContext(authentication.getAdminId(), authentication.getRoleIds()); AdminSecurityContextHolder.setContext(context); + } else { + String url = request.getRequestURI(); + if (!url.equals("/admin/passport/login")) { // TODO 临时写死。非登陆接口,必须已经认证身份,不允许匿名访问 + throw new ServiceException(AdminErrorCodeEnum.OAUTH_NOT_LOGIN.getCode(), AdminErrorCodeEnum.OAUTH_NOT_LOGIN.getMessage()); + } } // 校验是否需要已授权 checkPermission(request, authentication); diff --git a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/ResourceService.java b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/ResourceService.java new file mode 100644 index 000000000..4baeaa912 --- /dev/null +++ b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/ResourceService.java @@ -0,0 +1,12 @@ +package cn.iocoder.mall.admin.api; + +import cn.iocoder.mall.admin.api.bo.ResourceBO; + +import java.util.List; +import java.util.Set; + +public interface ResourceService { + + List getResourceByTypeAndRoleIds(Integer type, Set roleIds); + +} \ No newline at end of file diff --git a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/ResourceBO.java b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/ResourceBO.java new file mode 100644 index 000000000..ca6d79bc9 --- /dev/null +++ b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/ResourceBO.java @@ -0,0 +1,115 @@ +package cn.iocoder.mall.admin.api.bo; + +import java.util.Date; + +/** + * 资源 BO + */ +public class ResourceBO { + + /** + * 资源编号 + */ + private Integer id; + /** + * 资源名字(标识) + */ + private String name; + /** + * 资源类型 + */ + private Integer type; + /** + * 排序 + */ + private Integer sort; + /** + * 展示名 + */ + private String displayName; + /** + * 添加时间 + */ + private Date createTime; + /** + * 父级资源编号 + */ + private Integer pid; + /** + * 操作 + */ + private String handler; + + public Integer getId() { + return id; + } + + public ResourceBO setId(Integer id) { + this.id = id; + return this; + } + + public String getName() { + return name; + } + + public ResourceBO setName(String name) { + this.name = name; + return this; + } + + public Integer getType() { + return type; + } + + public ResourceBO setType(Integer type) { + this.type = type; + return this; + } + + public Integer getSort() { + return sort; + } + + public ResourceBO setSort(Integer sort) { + this.sort = sort; + return this; + } + + public String getDisplayName() { + return displayName; + } + + public ResourceBO setDisplayName(String displayName) { + this.displayName = displayName; + return this; + } + + public Date getCreateTime() { + return createTime; + } + + public ResourceBO setCreateTime(Date createTime) { + this.createTime = createTime; + return this; + } + + public Integer getPid() { + return pid; + } + + public ResourceBO setPid(Integer pid) { + this.pid = pid; + return this; + } + + public String getHandler() { + return handler; + } + + public ResourceBO setHandler(String handler) { + this.handler = handler; + return this; + } + +} \ No newline at end of file diff --git a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java index 85d445641..3c17cc666 100644 --- a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java +++ b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/AdminErrorCodeEnum.java @@ -16,6 +16,7 @@ public enum AdminErrorCodeEnum { OAUTH_INVALID_TOKEN_EXPIRED(1002001012, "访问令牌已过期"), OAUTH_INVALID_TOKEN_INVALID(1002001013, "访问令牌已失效"), OAUTH_INVALID_PERMISSION(1002001014, "没有该操作权限"), // TODO 芋艿,临时放在 OAUTH2 模块,理论来说,OAUTH2 只做认证,不做鉴权。 + OAUTH_NOT_LOGIN(1002001015, "账号未登陆"), OAUTH_INVALID_TOKEN(1002001020, ""), // 预留 diff --git a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/ResourceType.java b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/ResourceType.java new file mode 100644 index 000000000..1b87eca00 --- /dev/null +++ b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/constant/ResourceType.java @@ -0,0 +1,17 @@ +package cn.iocoder.mall.admin.api.constant; + +/** + * 资源类型 + */ +public interface ResourceType { + + /** + * 彩蛋 + */ + Integer MENU = 1; + /** + * URL + */ + Integer URL = 2; + +} \ No newline at end of file diff --git a/admin/admin-service-impl/pom.xml b/admin/admin-service-impl/pom.xml index 578ae0764..f8c288848 100644 --- a/admin/admin-service-impl/pom.xml +++ b/admin/admin-service-impl/pom.xml @@ -49,6 +49,12 @@ ${org.mapstruct.version} + + com.google.guava + guava + 27.0.1-jre + + diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/convert/ResourceConvert.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/convert/ResourceConvert.java new file mode 100644 index 000000000..093ddf9a6 --- /dev/null +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/convert/ResourceConvert.java @@ -0,0 +1,22 @@ +package cn.iocoder.mall.admin.convert; + +import cn.iocoder.mall.admin.api.bo.ResourceBO; +import cn.iocoder.mall.admin.dataobject.ResourceDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface ResourceConvert { + + ResourceConvert INSTANCE = Mappers.getMapper(ResourceConvert.class); + + @Mappings({}) + ResourceBO convert(ResourceDO resourceDO); + + @Mappings({}) + List convert(List resourceDOs); + +} \ No newline at end of file diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dao/ResourceMapper.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dao/ResourceMapper.java new file mode 100644 index 000000000..7b68eed41 --- /dev/null +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dao/ResourceMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.mall.admin.dao; + +import cn.iocoder.mall.admin.dataobject.ResourceDO; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Set; + +@Repository +public interface ResourceMapper { + + ResourceDO selectByTypeAndHandler(@Param("type") Integer type, + @Param("handler") String handler); + + List selectListByTypeAndRoleIds(@Param("type") Integer type, + @Param("roleIds") Set roleIds); + +} \ No newline at end of file diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dao/RoleResourceMapper.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dao/RoleResourceMapper.java index 92f882c06..25daf33ce 100644 --- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dao/RoleResourceMapper.java +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dao/RoleResourceMapper.java @@ -11,4 +11,6 @@ public interface RoleResourceMapper { List selectByResourceHandler(@Param("resourceHandler") String resourceHandler); + List selectRoleByResourceId(@Param("resourceId") Integer resourceId); + } \ No newline at end of file diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/ResourceDO.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/ResourceDO.java index b8b278263..79c887add 100644 --- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/ResourceDO.java +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/ResourceDO.java @@ -1,21 +1,25 @@ package cn.iocoder.mall.admin.dataobject; +import cn.iocoder.common.framework.dataobject.BaseDO; + import java.util.Date; /** * 资源实体 */ -public class ResourceDO { +public class ResourceDO extends BaseDO { /** * 资源类型 - 菜单 */ + @Deprecated public static final Integer TYPE_MENU = 1; /** * 资源类型 - 操作 * * 例如,按钮。 */ + @Deprecated public static final Integer TYPE_OPERATION = 2; /** @@ -23,7 +27,7 @@ public class ResourceDO { */ private Integer id; /** - * 资源名字 + * 资源名字(标识) */ private String name; /** @@ -50,7 +54,7 @@ public class ResourceDO { * 操作 * * 当资源类型为【菜单】时,handler 配置为界面 URL ,或者前端组件名 - * 当资源类型为【操作】时,handler 配置为后端 URL 。举个例子,如果有一个「创建管理员」的表单,那么前端界面上的按钮可以根据这个 url 判断是否展示,后端接收到该 url 的请求时会判断是否有权限。 + * 当资源类型为【URL】时,handler 配置为后端 URL 。举个例子,如果有一个「创建管理员」的表单,那么前端界面上的按钮可以根据这个 url 判断是否展示,后端接收到该 url 的请求时会判断是否有权限。 */ private String handler; diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java index 64033c463..16a5594fb 100644 --- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java @@ -4,9 +4,9 @@ import cn.iocoder.common.framework.util.ServiceExceptionUtil; import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.mall.admin.api.AdminService; import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum; +import cn.iocoder.mall.admin.dataobject.AdminDO; import cn.iocoder.mall.admin.dao.AdminMapper; import cn.iocoder.mall.admin.dao.AdminRoleMapper; -import cn.iocoder.mall.admin.dataobject.AdminDO; import cn.iocoder.mall.admin.dataobject.AdminRoleDO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/OAuth2ServiceImpl.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/OAuth2ServiceImpl.java index 27734f4fa..e827e2a43 100644 --- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/OAuth2ServiceImpl.java +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/OAuth2ServiceImpl.java @@ -14,7 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.UUID; @Service @com.alibaba.dubbo.config.annotation.Service @@ -39,6 +42,8 @@ public class OAuth2ServiceImpl implements OAuth2Service { private OAuth2RefreshTokenMapper oauth2RefreshTokenMapper; @Autowired private RoleServiceImpl roleService; + @Autowired + private ResourceServiceImpl resourceService; @Override public CommonResult getAccessToken(String username, String password) { @@ -76,15 +81,17 @@ public class OAuth2ServiceImpl implements OAuth2Service { @Override public CommonResult checkPermission(Integer adminId, Set roleIds, String url) { - // 避免传入的是空集合 - if (roleIds == null) { - roleIds = Collections.emptySet(); - } - // 校验权限 - List roleResourceDOs = roleService.getRoleByResourceHandler(url); - if (roleResourceDOs.isEmpty()) { // 任何角色,都可以访问。TODO 后面调整下,如果未配置的资源,直接不校验权限 + // 如果未配置该资源,说明无需权限控制。 + ResourceDO resource = resourceService.getResourceByTypeAndHandler(ResourceDO.TYPE_OPERATION, url); + if (resource == null) { return CommonResult.success(true); } + // 资源存在,结果无角色,说明没有权限。 + if (roleIds == null || roleIds.isEmpty()) { + return ServiceExceptionUtil.error(AdminErrorCodeEnum.OAUTH_INVALID_PERMISSION.getCode()); + } + // 校验是否有资源对应的角色,即 RBAC 。 + List roleResourceDOs = roleService.getRoleByResourceId(resource.getId()); for (RoleResourceDO roleResourceDO : roleResourceDOs) { if (roleIds.contains(roleResourceDO.getRoleId())) { return CommonResult.success(true); diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/ResourceServiceImpl.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/ResourceServiceImpl.java new file mode 100644 index 000000000..7f796065c --- /dev/null +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/ResourceServiceImpl.java @@ -0,0 +1,34 @@ +package cn.iocoder.mall.admin.service; + +import cn.iocoder.mall.admin.api.ResourceService; +import cn.iocoder.mall.admin.api.bo.ResourceBO; +import cn.iocoder.mall.admin.convert.ResourceConvert; +import cn.iocoder.mall.admin.dao.ResourceMapper; +import cn.iocoder.mall.admin.dataobject.ResourceDO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +@Service +@com.alibaba.dubbo.config.annotation.Service +public class ResourceServiceImpl implements ResourceService { + + @Autowired + private ResourceMapper resourceMapper; + + public ResourceDO getResourceByTypeAndHandler(Integer type, String handler) { + return resourceMapper.selectByTypeAndHandler(type, handler); + } + + @Override + public List getResourceByTypeAndRoleIds(Integer type, Set roleIds) { + if (roleIds == null || roleIds.isEmpty()) { + return Collections.emptyList(); + } + return ResourceConvert.INSTANCE.convert(resourceMapper.selectListByTypeAndRoleIds(type, roleIds)); + } + +} \ No newline at end of file diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java index 22aace4d9..70c2313ad 100644 --- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java +++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/RoleServiceImpl.java @@ -19,4 +19,8 @@ public class RoleServiceImpl implements RoleService { return roleResourceMapper.selectByResourceHandler(resourceHandler); } + public List getRoleByResourceId(Integer resourceId) { + return roleResourceMapper.selectRoleByResourceId(resourceId); + } + } \ No newline at end of file diff --git a/admin/admin-service-impl/src/main/resources/mapper/ResourceMapper.xml b/admin/admin-service-impl/src/main/resources/mapper/ResourceMapper.xml new file mode 100644 index 000000000..eeb7caeaa --- /dev/null +++ b/admin/admin-service-impl/src/main/resources/mapper/ResourceMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/admin/admin-service-impl/src/main/resources/mapper/RoleResourceMapper.xml b/admin/admin-service-impl/src/main/resources/mapper/RoleResourceMapper.xml index b351fccff..7cebdd0fe 100644 --- a/admin/admin-service-impl/src/main/resources/mapper/RoleResourceMapper.xml +++ b/admin/admin-service-impl/src/main/resources/mapper/RoleResourceMapper.xml @@ -18,4 +18,11 @@ AND r.id = rr.resource_id + + \ No newline at end of file diff --git a/common/common-framework/pom.xml b/common/common-framework/pom.xml index 2a6830d67..8ffb4f056 100644 --- a/common/common-framework/pom.xml +++ b/common/common-framework/pom.xml @@ -44,6 +44,11 @@ jackson-annotations 2.9.7 + + + + + diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/SysErrorCodeEnum.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/SysErrorCodeEnum.java index 8c79c1579..d0ddbbed1 100644 --- a/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/SysErrorCodeEnum.java +++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/SysErrorCodeEnum.java @@ -9,7 +9,6 @@ public enum SysErrorCodeEnum { SYS_ERROR(2001001000, "服务端发生异常"), MISSING_REQUEST_PARAM_ERROR(2001001001, "参数缺失"), - ; private final int code; diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/dataobject/BaseDO.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/dataobject/BaseDO.java new file mode 100644 index 000000000..51e3ee09e --- /dev/null +++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/dataobject/BaseDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.common.framework.dataobject; + +import java.util.Date; + +/** + * 基础实体对象 + */ +public class BaseDO { + + /** + * 创建时间 + */ + private Date createTime; + /** + * 最后更新时间 + */ + private Date updateTime; + private Boolean deleted; + + public Date getCreateTime() { + return createTime; + } + + public BaseDO setCreateTime(Date createTime) { + this.createTime = createTime; + return this; + } + + public Date getUpdateTime() { + return updateTime; + } + + public BaseDO setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + return this; + } + + public Boolean getDeleted() { + return deleted; + } + + public BaseDO setDeleted(Boolean deleted) { + this.deleted = deleted; + return this; + } + +} \ No newline at end of file