- admin 模块重命名 system 模块
This commit is contained in:
23
system/pom.xml
Normal file
23
system/pom.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>mall-parent</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>system</artifactId>
|
||||
<name>system</name>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>system-application</module>
|
||||
<module>system-sdk</module>
|
||||
<module>system-service-api</module>
|
||||
<module>system-service-impl</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
||||
103
system/system-application/pom.xml
Normal file
103
system/system-application/pom.xml
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>system</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>admin-application</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>system-service-impl</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>system-sdk</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>common-framework</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>de.codecentric</groupId>-->
|
||||
<!--<artifactId>spring-boot-admin-starter-server</artifactId>-->
|
||||
<!--<version>2.1.3</version>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>de.codecentric</groupId>-->
|
||||
<!--<artifactId>spring-boot-admin-server-ui</artifactId>-->
|
||||
<!--<version>2.1.3</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.qiniu</groupId>
|
||||
<artifactId>qiniu-java-sdk</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 提供给 mapstruct 使用 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<!-- 打包 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.mall.admin.application;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.admin"})
|
||||
//@EnableAdminServer
|
||||
public class AdminApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext ctx = SpringApplication.run(AdminApplication.class, args);
|
||||
// Object bean = ctx.getBean("test");
|
||||
// System.out.println(AopUtils.getTargetClass(bean));
|
||||
|
||||
// System.out.println(bean);
|
||||
|
||||
// ConfigurableApplicationContext ctx =
|
||||
// System.out.println(); // TODO 后面去掉,这里是临时的
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package cn.iocoder.mall.admin.application.config;
|
||||
|
||||
import cn.iocoder.common.framework.config.GlobalExceptionHandler;
|
||||
import cn.iocoder.common.framework.servlet.CorsFilter;
|
||||
import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor;
|
||||
import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
|
||||
AdminSecurityInterceptor.class})
|
||||
public class MVCConfiguration implements WebMvcConfigurer {
|
||||
|
||||
// @Autowired
|
||||
// private UserSecurityInterceptor securityInterceptor;
|
||||
|
||||
@Autowired
|
||||
private AdminSecurityInterceptor adminSecurityInterceptor;
|
||||
@Autowired
|
||||
private AdminAccessLogInterceptor adminAccessLogInterceptor;
|
||||
|
||||
@Value("${auth.ignore-urls}")
|
||||
private Set<String> ignoreUrls;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// registry.addInterceptor(securityInterceptor).addPathPatterns("/user/**", "/admin/**"); // 只拦截我们定义的接口
|
||||
registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
|
||||
registry.addInterceptor(adminSecurityInterceptor.setIgnoreUrls(ignoreUrls)).addPathPatterns("/admins/**")
|
||||
.excludePathPatterns("/admins/passport/login"); // 排除登陆接口
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// 解决 swagger-ui.html 的访问,参考自 https://stackoverflow.com/questions/43545540/swagger-ui-no-mapping-found-for-http-request 解决
|
||||
registry.addResourceHandler("swagger-ui.html**").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
|
||||
registry.addResourceHandler("webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<CorsFilter> corsFilter() {
|
||||
FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
|
||||
registrationBean.setFilter(new CorsFilter());
|
||||
registrationBean.addUrlPatterns("/*");
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.mall.admin.application.config;
|
||||
|
||||
import com.qiniu.util.Auth;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class QiniuConfiguration {
|
||||
|
||||
@Value("${qiniu.access-key}")
|
||||
private String accessKey;
|
||||
@Value("${qiniu.secret-key}")
|
||||
private String secretKey;
|
||||
|
||||
@Bean
|
||||
public Auth auth() {
|
||||
return Auth.create(accessKey, secretKey);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.iocoder.mall.admin.application.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2 // TODO 生产环境时,禁用掉。
|
||||
public class SwaggerConfiguration {
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.admin.application.controller"))
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("管理员子系统")
|
||||
.description("管理员子系统")
|
||||
.termsOfServiceUrl("http://www.iocoder.cn")
|
||||
.version("1.0.0")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package cn.iocoder.mall.admin.application.controller.admins;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.AdminService;
|
||||
import cn.iocoder.mall.admin.api.ResourceService;
|
||||
import cn.iocoder.mall.admin.api.RoleService;
|
||||
import cn.iocoder.mall.admin.api.bo.AdminPageBO;
|
||||
import cn.iocoder.mall.admin.api.bo.ResourceBO;
|
||||
import cn.iocoder.mall.admin.api.bo.RoleBO;
|
||||
import cn.iocoder.mall.admin.api.constant.ResourceConstants;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminPageDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminUpdateDTO;
|
||||
import cn.iocoder.mall.admin.application.convert.AdminConvert;
|
||||
import cn.iocoder.mall.admin.application.convert.ResourceConvert;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminMenuTreeNodeVO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminPageVO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminRoleVO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminVO;
|
||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("admins/admin")
|
||||
@Api("管理员模块")
|
||||
public class AdminController {
|
||||
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private ResourceService resourceService;
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private AdminService adminService;
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private RoleService roleService;
|
||||
|
||||
// =========== 当前管理员相关的资源 API ===========
|
||||
|
||||
// TODO 功能:当前管理员
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@GetMapping("/menu_resource_tree")
|
||||
@ApiOperation(value = "获得当前登陆的管理员拥有的菜单权限", notes = "以树结构返回")
|
||||
public CommonResult<List<AdminMenuTreeNodeVO>> menuResourceTree() {
|
||||
List<ResourceBO> resources = resourceService.getResourcesByTypeAndRoleIds(ResourceConstants.TYPE_MENU, AdminSecurityContextHolder.getContext().getRoleIds());
|
||||
// 创建 AdminMenuTreeNodeVO Map
|
||||
// Map<Integer, AdminMenuTreeNodeVO> treeNodeMap = resources.stream().collect(Collectors.toMap(ResourceBO::getId, ResourceConvert.INSTANCE::convert));
|
||||
Map<Integer, AdminMenuTreeNodeVO> treeNodeMap = new LinkedHashMap<>(); // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。
|
||||
resources.stream().sorted(Comparator.comparing(ResourceBO::getSort)).forEach(resourceBO -> treeNodeMap.put(resourceBO.getId(), ResourceConvert.INSTANCE.convert(resourceBO)));
|
||||
// 处理父子关系
|
||||
treeNodeMap.values().stream()
|
||||
.filter(node -> !node.getPid().equals(ResourceConstants.PID_ROOT))
|
||||
.forEach((childNode) -> {
|
||||
// 获得父节点
|
||||
AdminMenuTreeNodeVO parentNode = treeNodeMap.get(childNode.getPid());
|
||||
if (parentNode.getChildren() == null) { // 初始化 children 数组
|
||||
parentNode.setChildren(new ArrayList<>());
|
||||
}
|
||||
// 将自己添加到父节点中
|
||||
parentNode.getChildren().add(childNode);
|
||||
});
|
||||
// 获得到所有的根节点
|
||||
List<AdminMenuTreeNodeVO> rootNodes = treeNodeMap.values().stream()
|
||||
.filter(node -> node.getPid().equals(ResourceConstants.PID_ROOT))
|
||||
// .sorted(Comparator.comparing(AdminMenuTreeNodeVO::getSort))
|
||||
.collect(Collectors.toList());
|
||||
return CommonResult.success(rootNodes);
|
||||
}
|
||||
|
||||
@GetMapping("/url_resource_list")
|
||||
@ApiOperation(value = "获得当前登陆的管理员拥有的 URL 权限列表")
|
||||
// @ApiModelProperty(value = "data", example = "['/admin/role/add', '/admin/role/update']") 没效果
|
||||
public CommonResult<Set<String>> urlResourceList() {
|
||||
List<ResourceBO> resources = resourceService.getResourcesByTypeAndRoleIds(ResourceConstants.TYPE_URL, AdminSecurityContextHolder.getContext().getRoleIds());
|
||||
return CommonResult.success(resources.stream().map(ResourceBO::getHandler).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
// =========== 管理员管理 API ===========
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation(value = "管理员分页")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "nickname", value = "昵称,模糊匹配", example = "小王"),
|
||||
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
|
||||
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
|
||||
})
|
||||
public CommonResult<AdminPageVO> page(@RequestParam(value = "nickname", required = false) String nickname,
|
||||
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||
CommonResult<AdminPageBO> result = adminService.getAdminPage(new AdminPageDTO().setNickname(nickname).setPageNo(pageNo).setPageSize(pageSize));
|
||||
return AdminConvert.INSTANCE.convert(result);
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@ApiOperation(value = "创建管理员")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "username", value = "账号", required = true, example = "15601691300"),
|
||||
@ApiImplicitParam(name = "nickname", value = "昵称", required = true, example = "小王"),
|
||||
@ApiImplicitParam(name = "password", value = "密码", required = true, example = "buzhidao"),
|
||||
})
|
||||
public CommonResult<AdminVO> add(@RequestParam("username") String username,
|
||||
@RequestParam("nickname") String nickname,
|
||||
@RequestParam("password") String password) {
|
||||
AdminAddDTO adminAddDTO = new AdminAddDTO().setUsername(username).setNickname(nickname).setPassword(password);
|
||||
return AdminConvert.INSTANCE.convert2(adminService.addAdmin(AdminSecurityContextHolder.getContext().getAdminId(), adminAddDTO));
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@ApiOperation(value = "更新管理员")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "管理员编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "username", value = "账号", required = true, example = "15601691300"),
|
||||
@ApiImplicitParam(name = "nickname", value = "昵称", required = true, example = "小王"),
|
||||
@ApiImplicitParam(name = "password", value = "密码", example = "buzhidao"),
|
||||
})
|
||||
public CommonResult<Boolean> update(@RequestParam("id") Integer id,
|
||||
@RequestParam("username") String username,
|
||||
@RequestParam("nickname") String nickname,
|
||||
@RequestParam(value = "password", required = false) String password) {
|
||||
AdminUpdateDTO adminUpdateDTO = new AdminUpdateDTO().setId(id).setUsername(username).setNickname(nickname).setPassword(password);
|
||||
return adminService.updateAdmin(AdminSecurityContextHolder.getContext().getAdminId(), adminUpdateDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/update_status")
|
||||
@ApiOperation(value = "更新管理员状态")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "管理员编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "status", value = "状态。1 - 开启;2 - 禁用", required = true, example = "1"),
|
||||
})
|
||||
public CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id,
|
||||
@RequestParam("status") Integer status) {
|
||||
return adminService.updateAdminStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@ApiOperation(value = "删除管理员")
|
||||
@ApiImplicitParam(name = "id", value = "管理员编号", required = true, example = "1")
|
||||
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
|
||||
return adminService.deleteAdmin(AdminSecurityContextHolder.getContext().getAdminId(), id);
|
||||
}
|
||||
|
||||
@GetMapping("/role_list")
|
||||
@ApiOperation(value = "指定管理员拥有的角色列表")
|
||||
@ApiImplicitParam(name = "id", value = "管理员编号", required = true, example = "1")
|
||||
public CommonResult<List<AdminRoleVO>> roleList(@RequestParam("id") Integer id) {
|
||||
// 获得管理员拥有的角色集合
|
||||
Set<Integer> adminRoleIdSet = roleService.getRoleList(id).getData();
|
||||
// 获得所有角色数组
|
||||
List<RoleBO> allRoleList = roleService.getRoleList().getData();
|
||||
// 转换出返回结果
|
||||
List<AdminRoleVO> result = AdminConvert.INSTANCE.convert(allRoleList);
|
||||
// 设置每个角色是否赋予给改管理员
|
||||
result.forEach(adminRoleVO -> adminRoleVO.setAssigned(adminRoleIdSet.contains(adminRoleVO.getId())));
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
@PostMapping("/assign_role")
|
||||
@ApiOperation(value = "分配给管理员角色")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "管理员编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "roleIds", value = "角色编号集合", required = true, example = "1,2,3"),
|
||||
})
|
||||
public CommonResult<Boolean> assignRole(@RequestParam("id") Integer id,
|
||||
@RequestParam("roleIds")Set<Integer> roleIds) {
|
||||
return adminService.assignRole(AdminSecurityContextHolder.getContext().getAdminId(), id, roleIds);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package cn.iocoder.mall.admin.application.controller.admins;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.DataDictService;
|
||||
import cn.iocoder.mall.admin.api.bo.DataDictBO;
|
||||
import cn.iocoder.mall.admin.api.dto.DataDictAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.DataDictUpdateDTO;
|
||||
import cn.iocoder.mall.admin.application.convert.DataDictConvert;
|
||||
import cn.iocoder.mall.admin.application.vo.DataDictEnumVO;
|
||||
import cn.iocoder.mall.admin.application.vo.DataDictVO;
|
||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("admins/data_dict")
|
||||
@Api("数据字典模块")
|
||||
public class DataDictController {
|
||||
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private DataDictService dataDictService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation(value = "数据字典全列表")
|
||||
public CommonResult<List<DataDictVO>> list() {
|
||||
CommonResult<List<DataDictBO>> result = dataDictService.selectDataDictList();
|
||||
return DataDictConvert.INSTANCE.convert(result);
|
||||
}
|
||||
|
||||
@GetMapping("/tree")
|
||||
@ApiOperation(value = "数据字典树结构", notes = "该接口返回的信息更为精简。一般用于前端缓存数据字典到本地。")
|
||||
public CommonResult<List<DataDictEnumVO>> tree() {
|
||||
// 查询数据字典全列表
|
||||
CommonResult<List<DataDictBO>> result = dataDictService.selectDataDictList();
|
||||
if (result.isError()) {
|
||||
return CommonResult.error(result);
|
||||
}
|
||||
// 构建基于 enumValue 聚合的 Multimap
|
||||
ImmutableListMultimap<String, DataDictBO> dataDictMap = Multimaps.index(result.getData(), DataDictBO::getEnumValue); // KEY 是 enumValue ,VALUE 是 DataDictBO 数组
|
||||
// 构建返回结果
|
||||
List<DataDictEnumVO> dataDictEnumVOs = new ArrayList<>(dataDictMap.size());
|
||||
dataDictMap.keys().forEach(enumValue -> {
|
||||
DataDictEnumVO dataDictEnumVO = new DataDictEnumVO().setEnumValue(enumValue)
|
||||
.setValues(DataDictConvert.INSTANCE.convert2(dataDictMap.get(enumValue)));
|
||||
dataDictEnumVOs.add(dataDictEnumVO);
|
||||
});
|
||||
return CommonResult.success(dataDictEnumVOs);
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@ApiOperation(value = "创建数据字典")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "enumValue", value = "大类枚举值", required = true, example = "gender"),
|
||||
@ApiImplicitParam(name = "value", value = "小类数值", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "displayName", value = "展示名", required = true, example = "男"),
|
||||
@ApiImplicitParam(name = "sort", required = true, value = "排序值", defaultValue = "10"),
|
||||
@ApiImplicitParam(name = "memo", value = "备注", example = "你猜我猜不猜"),
|
||||
})
|
||||
public CommonResult<DataDictVO> add(@RequestParam("enumValue") String enumValue,
|
||||
@RequestParam("value") String value,
|
||||
@RequestParam("displayName") String displayName,
|
||||
@RequestParam("sort") Integer sort,
|
||||
@RequestParam(value = "memo", required = false) String memo) {
|
||||
// 创建 DataDictAddDTO 对象
|
||||
DataDictAddDTO dataDictAddDTO = new DataDictAddDTO().setEnumValue(enumValue).setValue(value).setDisplayName(displayName)
|
||||
.setSort(sort).setMemo(memo);
|
||||
// 保存数据字典
|
||||
CommonResult<DataDictBO> result = dataDictService.addDataDict(AdminSecurityContextHolder.getContext().getAdminId(), dataDictAddDTO);
|
||||
// 返回结果
|
||||
return DataDictConvert.INSTANCE.convert2(result);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@ApiOperation(value = "更新数据字典")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "100"),
|
||||
@ApiImplicitParam(name = "value", value = "小类数值", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "displayName", value = "展示名", required = true, example = "男"),
|
||||
@ApiImplicitParam(name = "sort", required = true, value = "排序值", defaultValue = "10"),
|
||||
@ApiImplicitParam(name = "memo", value = "备注", example = "你猜我猜不猜"),
|
||||
})
|
||||
public CommonResult<Boolean> update(@RequestParam("id") Integer id,
|
||||
@RequestParam("value") String value,
|
||||
@RequestParam("displayName") String displayName,
|
||||
@RequestParam("sort") Integer sort,
|
||||
@RequestParam(value = "memo", required = false) String memo) {
|
||||
// 创建 DataDictAddDTO 对象
|
||||
DataDictUpdateDTO dataDictUpdateDTO = new DataDictUpdateDTO().setId(id).setValue(value).setDisplayName(displayName)
|
||||
.setSort(sort).setMemo(memo);
|
||||
// 更新数据字典
|
||||
return dataDictService.updateDataDict(AdminSecurityContextHolder.getContext().getAdminId(), dataDictUpdateDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@ApiOperation(value = "删除数据字典")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "100")
|
||||
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
|
||||
return dataDictService.deleteDataDict(AdminSecurityContextHolder.getContext().getAdminId(), id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.mall.admin.application.controller.admins;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import com.qiniu.util.Auth;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("admins/file")
|
||||
@Api("文件模块")
|
||||
public class FileController {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Autowired
|
||||
private Auth auth;
|
||||
@Value("${qiniu.bucket}")
|
||||
private String bucket;
|
||||
|
||||
@GetMapping("/get_qiniu_token")
|
||||
public CommonResult<String> getQiniuToken() {
|
||||
String token = auth.uploadToken(bucket);
|
||||
logger.info("[qiniu_token][token({}) get]", token);
|
||||
return CommonResult.success(token);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package cn.iocoder.mall.admin.application.controller.admins;
|
||||
|
||||
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.application.convert.PassportConvert;
|
||||
import cn.iocoder.mall.admin.application.vo.PassportLoginVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("admins/passport")
|
||||
@Api("Admin Passport 模块")
|
||||
public class PassportController {
|
||||
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private OAuth2Service oauth2Service;
|
||||
|
||||
@PostMapping("/login")
|
||||
@ApiOperation(value = "手机号 + 密码登陆")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "username", value = "账号", required = true, example = "15601691300"),
|
||||
@ApiImplicitParam(name = "password", value = "密码", required = true, example = "future")
|
||||
})
|
||||
public CommonResult<PassportLoginVO> login(@RequestParam("username") String username,
|
||||
@RequestParam("password") String password) {
|
||||
CommonResult<OAuth2AccessTokenBO> result = oauth2Service.getAccessToken(username, password);
|
||||
return PassportConvert.INSTANCE.convert(result);
|
||||
}
|
||||
|
||||
// TODO 功能 logout
|
||||
|
||||
// TODO 功能 refresh_token
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package cn.iocoder.mall.admin.application.controller.admins;
|
||||
|
||||
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.ResourceConstants;
|
||||
import cn.iocoder.mall.admin.api.dto.ResourceAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.ResourceUpdateDTO;
|
||||
import cn.iocoder.mall.admin.application.convert.ResourceConvert;
|
||||
import cn.iocoder.mall.admin.application.vo.ResourceTreeNodeVO;
|
||||
import cn.iocoder.mall.admin.application.vo.ResourceVO;
|
||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("admins/resource")
|
||||
@Api("资源模块")
|
||||
public class ResourceController {
|
||||
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private ResourceService resourceService;
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@GetMapping("/tree")
|
||||
@ApiOperation(value = "获得所有资源,按照树形结构返回")
|
||||
public CommonResult<List<ResourceTreeNodeVO>> tree() {
|
||||
List<ResourceBO> resources = resourceService.getResourcesByType(null);
|
||||
// 创建 AdminMenuTreeNodeVO Map
|
||||
Map<Integer, ResourceTreeNodeVO> treeNodeMap = resources.stream().collect(Collectors.toMap(ResourceBO::getId, ResourceConvert.INSTANCE::convert2));
|
||||
// 处理父子关系
|
||||
treeNodeMap.values().stream()
|
||||
.filter(node -> !node.getPid().equals(ResourceConstants.PID_ROOT))
|
||||
.forEach((childNode) -> {
|
||||
// 获得父节点
|
||||
ResourceTreeNodeVO parentNode = treeNodeMap.get(childNode.getPid());
|
||||
if (parentNode.getChildren() == null) { // 初始化 children 数组
|
||||
parentNode.setChildren(new ArrayList<>());
|
||||
}
|
||||
// 将自己添加到父节点中
|
||||
parentNode.getChildren().add(childNode);
|
||||
});
|
||||
// 获得到所有的根节点
|
||||
List<ResourceTreeNodeVO> rootNodes = treeNodeMap.values().stream()
|
||||
.filter(node -> node.getPid().equals(ResourceConstants.PID_ROOT))
|
||||
.sorted(Comparator.comparing(ResourceTreeNodeVO::getSort))
|
||||
.collect(Collectors.toList());
|
||||
return CommonResult.success(rootNodes);
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@ApiOperation(value = "创建资源", notes = "例如说,菜单资源,Url 资源")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "name", value = "资源名字(标识)", required = true, example = "admin/info"),
|
||||
@ApiImplicitParam(name = "type", value = "资源类型。1 代表【菜单】;2 代表【Url】", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "sort", value = "排序", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "displayName", value = "菜单展示名", required = true, example = "商品管理"),
|
||||
@ApiImplicitParam(name = "pid", value = "父级资源编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "handler", value = "操作", example = "/order/list"),
|
||||
})
|
||||
public CommonResult<ResourceVO> add(@RequestParam("name") String name,
|
||||
@RequestParam("type") Integer type,
|
||||
@RequestParam("sort") Integer sort,
|
||||
@RequestParam("displayName") String displayName,
|
||||
@RequestParam("pid") Integer pid,
|
||||
@RequestParam(value = "handler", required = false) String handler) {
|
||||
ResourceAddDTO resourceAddDTO = new ResourceAddDTO().setName(name).setType(type).setSort(sort)
|
||||
.setDisplayName(displayName).setPid(pid).setHandler(handler);
|
||||
return ResourceConvert.INSTANCE.convert3(resourceService.addResource(AdminSecurityContextHolder.getContext().getAdminId(), resourceAddDTO));
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@ApiOperation(value = "更新资源")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "资源编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "name", value = "资源名字(标识)", required = true, example = "admin/info"),
|
||||
@ApiImplicitParam(name = "sort", value = "排序", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "displayName", value = "菜单展示名", required = true, example = "商品管理"),
|
||||
@ApiImplicitParam(name = "pid", value = "父级资源编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "handler", value = "操作", example = "/order/list"),
|
||||
})
|
||||
public CommonResult<Boolean> update(@RequestParam("id") Integer id,
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("sort") Integer sort,
|
||||
@RequestParam("displayName") String displayName,
|
||||
@RequestParam("pid") Integer pid,
|
||||
@RequestParam(value = "handler", required = false) String handler) {
|
||||
ResourceUpdateDTO resourceUpdateDTO = new ResourceUpdateDTO().setId(id).setName(name).setSort(sort).setDisplayName(displayName).setPid(pid).setHandler(handler);
|
||||
return resourceService.updateResource(AdminSecurityContextHolder.getContext().getAdminId(), resourceUpdateDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@ApiOperation(value = "删除资源")
|
||||
@ApiImplicitParam(name = "id", value = "资源编号", required = true, example = "1")
|
||||
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
|
||||
return resourceService.deleteResource(AdminSecurityContextHolder.getContext().getAdminId(), id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package cn.iocoder.mall.admin.application.controller.admins;
|
||||
|
||||
import cn.iocoder.common.framework.util.CollectionUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.ResourceService;
|
||||
import cn.iocoder.mall.admin.api.RoleService;
|
||||
import cn.iocoder.mall.admin.api.bo.ResourceBO;
|
||||
import cn.iocoder.mall.admin.api.bo.RolePageBO;
|
||||
import cn.iocoder.mall.admin.api.constant.ResourceConstants;
|
||||
import cn.iocoder.mall.admin.api.dto.RoleAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.RolePageDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.RoleUpdateDTO;
|
||||
import cn.iocoder.mall.admin.application.convert.ResourceConvert;
|
||||
import cn.iocoder.mall.admin.application.convert.RoleConvert;
|
||||
import cn.iocoder.mall.admin.application.vo.RolePageVO;
|
||||
import cn.iocoder.mall.admin.application.vo.RoleResourceTreeNodeVO;
|
||||
import cn.iocoder.mall.admin.application.vo.RoleVO;
|
||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("admins/role")
|
||||
public class RoleController {
|
||||
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private RoleService roleService;
|
||||
@Reference(validation = "true")
|
||||
@Autowired // TODO Dubbo 2.7.2 移除 bug
|
||||
private ResourceService resourceService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation(value = "角色分页")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "name", value = "角色名,模糊匹配", required = true, example = "系统管理员"),
|
||||
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
|
||||
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
|
||||
})
|
||||
public CommonResult<RolePageVO> page(@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||
CommonResult<RolePageBO> result = roleService.getRolePage(new RolePageDTO().setName(name).setPageNo(pageNo).setPageSize(pageSize));
|
||||
return RoleConvert.INSTANCE.convert2(result);
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@ApiOperation(value = "创建角色")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "name", value = "角色", required = true, example = "系统管理员"),
|
||||
})
|
||||
public CommonResult<RoleVO> add(@RequestParam("name") String name) {
|
||||
RoleAddDTO roleAddDTO = new RoleAddDTO().setName(name);
|
||||
return RoleConvert.INSTANCE.convert(roleService.addRole(AdminSecurityContextHolder.getContext().getAdminId(), roleAddDTO));
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@ApiOperation(value = "更新角色")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "name", value = "角色名", required = true, example = "系统管理员"),
|
||||
})
|
||||
public CommonResult<Boolean> update(@RequestParam("id") Integer id,
|
||||
@RequestParam("name") String name) {
|
||||
RoleUpdateDTO roleUpdateDTO = new RoleUpdateDTO().setId(id).setName(name);
|
||||
return roleService.updateRole(AdminSecurityContextHolder.getContext().getAdminId(), roleUpdateDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@ApiOperation(value = "删除角色")
|
||||
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1")
|
||||
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
|
||||
return roleService.deleteRole(AdminSecurityContextHolder.getContext().getAdminId(), id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@GetMapping("/resource_tree")
|
||||
@ApiOperation(value = "获得角色拥有的菜单权限", notes = "以树结构返回")
|
||||
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1")
|
||||
public CommonResult<List<RoleResourceTreeNodeVO>> resourceTree(@RequestParam("id") Integer id) {
|
||||
// 芋艿:此处,严格来说可以在校验下角色是否存在。不过呢,校验了也没啥意义,因为一般不存在这个情况,且不会有业务上的影响。并且,反倒多了一次 rpc 调用。
|
||||
// 第一步,获得角色拥有的资源数组
|
||||
Set<Integer> roleResources = resourceService.getResourcesByTypeAndRoleIds(null, CollectionUtil.asSet(id))
|
||||
.stream().map(ResourceBO::getId).collect(Collectors.toSet());
|
||||
// 第二步,获得资源树
|
||||
List<ResourceBO> allResources = resourceService.getResourcesByType(null);
|
||||
// 创建 AdminMenuTreeNodeVO Map
|
||||
Map<Integer, RoleResourceTreeNodeVO> treeNodeMap = allResources.stream().collect(Collectors.toMap(ResourceBO::getId, ResourceConvert.INSTANCE::convert4));
|
||||
// 处理父子关系
|
||||
treeNodeMap.values().stream()
|
||||
.filter(node -> !node.getPid().equals(ResourceConstants.PID_ROOT))
|
||||
.forEach((childNode) -> {
|
||||
// 获得父节点
|
||||
RoleResourceTreeNodeVO parentNode = treeNodeMap.get(childNode.getPid());
|
||||
if (parentNode.getChildren() == null) { // 初始化 children 数组
|
||||
parentNode.setChildren(new ArrayList<>());
|
||||
}
|
||||
// 将自己添加到父节点中
|
||||
parentNode.getChildren().add(childNode);
|
||||
});
|
||||
// 获得到所有的根节点
|
||||
List<RoleResourceTreeNodeVO> rootNodes = treeNodeMap.values().stream()
|
||||
.filter(node -> node.getPid().equals(ResourceConstants.PID_ROOT))
|
||||
.sorted(Comparator.comparing(RoleResourceTreeNodeVO::getSort))
|
||||
.collect(Collectors.toList());
|
||||
// 第三步,设置角色是否有该角色
|
||||
treeNodeMap.values().forEach(nodeVO -> nodeVO.setAssigned(roleResources.contains(nodeVO.getId())));
|
||||
// 返回结果
|
||||
return CommonResult.success(rootNodes);
|
||||
}
|
||||
|
||||
@PostMapping("/assign_resource")
|
||||
@ApiOperation(value = "分配角色资源")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "resourceIds", value = "资源数组", required = true, example = "1,2,3"),
|
||||
})
|
||||
public CommonResult<Boolean> assignResource(@RequestParam("id") Integer id,
|
||||
@RequestParam(value = "resourceIds", required = false) Set<Integer> resourceIds) {
|
||||
return roleService.assignResource(AdminSecurityContextHolder.getContext().getAdminId(), id, resourceIds);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.mall.admin.application.convert;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.AdminBO;
|
||||
import cn.iocoder.mall.admin.api.bo.AdminPageBO;
|
||||
import cn.iocoder.mall.admin.api.bo.RoleBO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminInfoVO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminPageVO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminRoleVO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminVO;
|
||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContext;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AdminConvert {
|
||||
|
||||
AdminConvert INSTANCE = Mappers.getMapper(AdminConvert.class);
|
||||
|
||||
@Mappings({})
|
||||
AdminInfoVO convert(AdminSecurityContext adminSecurityContext);
|
||||
|
||||
@Mappings({})
|
||||
AdminVO convert(AdminBO adminBO);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<AdminVO> convert2(CommonResult<AdminBO> result);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<AdminPageVO> convert(CommonResult<AdminPageBO> result);
|
||||
|
||||
@Mappings({})
|
||||
List<AdminRoleVO> convert(List<RoleBO> roleList);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.mall.admin.application.convert;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.DataDictBO;
|
||||
import cn.iocoder.mall.admin.application.vo.DataDictVO;
|
||||
import cn.iocoder.mall.admin.application.vo.DataDictValueVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface DataDictConvert {
|
||||
|
||||
DataDictConvert INSTANCE = Mappers.getMapper(DataDictConvert.class);
|
||||
|
||||
@Mappings({})
|
||||
DataDictVO convert(DataDictBO dataDictBO);
|
||||
|
||||
@Mappings({})
|
||||
List<DataDictVO> convert(List<DataDictBO> dataDictBOs);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<List<DataDictVO>> convert(CommonResult<List<DataDictBO>> result);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<DataDictVO> convert2(CommonResult<DataDictBO> result);
|
||||
|
||||
@Mappings({})
|
||||
List<DataDictValueVO> convert2(List<DataDictBO> dataDictBOs);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
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.application.vo.PassportLoginVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface PassportConvert {
|
||||
|
||||
PassportConvert INSTANCE = Mappers.getMapper(PassportConvert.class);
|
||||
|
||||
@Mappings({})
|
||||
PassportLoginVO convert(OAuth2AccessTokenBO oauth2AccessTokenBO);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<PassportLoginVO> convert(CommonResult<OAuth2AccessTokenBO> oauth2AccessTokenBO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.mall.admin.application.convert;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.ResourceBO;
|
||||
import cn.iocoder.mall.admin.application.vo.AdminMenuTreeNodeVO;
|
||||
import cn.iocoder.mall.admin.application.vo.ResourceTreeNodeVO;
|
||||
import cn.iocoder.mall.admin.application.vo.ResourceVO;
|
||||
import cn.iocoder.mall.admin.application.vo.RoleResourceTreeNodeVO;
|
||||
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);
|
||||
|
||||
@Mappings({})
|
||||
ResourceTreeNodeVO convert2(ResourceBO resourceBO);
|
||||
|
||||
@Mappings({})
|
||||
RoleResourceTreeNodeVO convert4(ResourceBO resourceBO);
|
||||
|
||||
@Mappings({})
|
||||
ResourceVO convert3(ResourceBO resourceBO);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<ResourceVO> convert3(CommonResult<ResourceBO> resourceBO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.mall.admin.application.convert;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.RoleBO;
|
||||
import cn.iocoder.mall.admin.api.bo.RolePageBO;
|
||||
import cn.iocoder.mall.admin.application.vo.RolePageVO;
|
||||
import cn.iocoder.mall.admin.application.vo.RoleVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface RoleConvert {
|
||||
|
||||
RoleConvert INSTANCE = Mappers.getMapper(RoleConvert.class);
|
||||
|
||||
@Mappings({})
|
||||
RoleVO convert(RoleBO roleBO);
|
||||
|
||||
@Mappings({})
|
||||
List<RoleVO> convert(List<RoleBO> roleBO);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<RoleVO> convert(CommonResult<RoleBO> resourceBO);
|
||||
|
||||
@Mappings({})
|
||||
CommonResult<RolePageVO> convert2(CommonResult<RolePageBO> resourceBO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@ApiModel("管理员信息 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminInfoVO {
|
||||
|
||||
@ApiModelProperty(value = "管理员比那好", required = true, example = "1")
|
||||
private Integer adminId;
|
||||
@ApiModelProperty(value = "角色编号的数组", required = true, example = "[1, 2]")
|
||||
private Set<Integer> roleIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理员拥有的菜单 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminMenuTreeNodeVO {
|
||||
|
||||
@ApiModelProperty(value = "菜单编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
// @ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
|
||||
// private String name;
|
||||
@ApiModelProperty(value = "菜单操作", required = true, example = "/order/list")
|
||||
private String handler;
|
||||
@ApiModelProperty(value = "父菜单编号", required = true, example = "1", notes = "如果无父菜单,则值为 0")
|
||||
private Integer pid;
|
||||
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||
private Integer sort;
|
||||
@ApiModelProperty(value = "菜单展示名", required = true, example = "商品管理")
|
||||
private String displayName;
|
||||
@ApiModelProperty(value = "子节点数组")
|
||||
private List<AdminMenuTreeNodeVO> children;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理员分页 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminPageVO {
|
||||
|
||||
@ApiModelProperty(value = "管理员数组")
|
||||
private List<AdminVO> list;
|
||||
@ApiModelProperty(value = "管理员总数")
|
||||
private Integer total;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("管理员拥有的角色 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminRoleVO {
|
||||
|
||||
@ApiModelProperty(value = "角色编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "角色名字", required = true, example = "系统管理员")
|
||||
private String name;
|
||||
@ApiModelProperty(value = "是否授权", required = true, example = "true")
|
||||
private Boolean assigned;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理员 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminVO {
|
||||
|
||||
@ApiModelProperty(value = "管理员编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "登陆账号", required = true, example = "15601691300")
|
||||
private String username;
|
||||
@ApiModelProperty(value = "昵称", required = true, example = "小王")
|
||||
private String nickname;
|
||||
@ApiModelProperty(value = "账号状态", required = true, example = "1")
|
||||
private Integer status;
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("数据字典枚举 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DataDictEnumVO {
|
||||
|
||||
@ApiModelProperty(value = "大类枚举值", required = true, example = "gender")
|
||||
private String enumValue;
|
||||
@ApiModelProperty(value = "小类数值数组", required = true)
|
||||
private List<DataDictValueVO> values;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("数据字典 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DataDictVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "大类枚举值", required = true, example = "gender")
|
||||
private String enumValue;
|
||||
@ApiModelProperty(value = "小类数值", required = true, example = "1")
|
||||
private String value;
|
||||
@ApiModelProperty(value = "展示名", required = true, example = "男")
|
||||
private String displayName;
|
||||
@ApiModelProperty(value = "排序值", required = true, example = "10")
|
||||
private Integer sort;
|
||||
@ApiModelProperty(value = "备注", example = "你猜")
|
||||
private String memo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("数据字典枚举值 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DataDictValueVO {
|
||||
|
||||
@ApiModelProperty(value = "小类数值", required = true, example = "1")
|
||||
private String value;
|
||||
@ApiModelProperty(value = "展示名", required = true, example = "男")
|
||||
private String displayName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("登陆结果 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PassportLoginVO {
|
||||
|
||||
@ApiModelProperty(value = "访问令牌", required = true, example = "2e3d7635c15e47e997611707a237859f")
|
||||
private String accessToken;
|
||||
@ApiModelProperty(value = "刷新令牌", required = true, example = "d091e7c35bbb4313b0f557a6ef23d033")
|
||||
private String refreshToken;
|
||||
@ApiModelProperty(value = "过期时间,单位:秒", required = true, example = "2879")
|
||||
private Integer expiresIn;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("资源树结构 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ResourceTreeNodeVO {
|
||||
|
||||
@ApiModelProperty(value = "资源编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "资源名字(标识)", required = true, example = "商品管理")
|
||||
private String name;
|
||||
@ApiModelProperty(value = "资源类型", required = true, example = "1")
|
||||
private Integer type;
|
||||
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||
private Integer sort;
|
||||
@ApiModelProperty(value = "菜单展示名", required = true, example = "商品管理")
|
||||
private String displayName;
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
@ApiModelProperty(value = "父级资源编号", required = true, example = "1", notes = "如果无父资源,则值为 0")
|
||||
private Integer pid;
|
||||
@ApiModelProperty(value = "操作", required = true, example = "/order/list")
|
||||
private String handler;
|
||||
@ApiModelProperty(value = "子节点数组")
|
||||
private List<ResourceTreeNodeVO> children;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("资源 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ResourceVO {
|
||||
|
||||
@ApiModelProperty(value = "资源编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "资源名字(标识)", required = true, example = "商品管理")
|
||||
private String name;
|
||||
@ApiModelProperty(value = "资源类型", required = true, example = "1")
|
||||
private Integer type;
|
||||
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||
private Integer sort;
|
||||
@ApiModelProperty(value = "菜单展示名", required = true, example = "商品管理")
|
||||
private String displayName;
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
@ApiModelProperty(value = "父级资源编号", required = true, example = "1", notes = "如果无父资源,则值为 0")
|
||||
private Integer pid;
|
||||
@ApiModelProperty(value = "操作", required = true, example = "/order/list")
|
||||
private String handler;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("角色分页 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RolePageVO {
|
||||
|
||||
@ApiModelProperty(value = "角色数组")
|
||||
private List<RoleVO> roles;
|
||||
@ApiModelProperty(value = "角色总数")
|
||||
private Integer count;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("角色拥有的资源 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RoleResourceTreeNodeVO {
|
||||
|
||||
@ApiModelProperty(value = "菜单编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
// @ApiModelProperty(value = "菜单名", required = true, example = "商品管理")
|
||||
// private String name;
|
||||
@ApiModelProperty(value = "菜单操作", required = true, example = "/order/list")
|
||||
private String handler;
|
||||
@ApiModelProperty(value = "父菜单编号", required = true, example = "1", notes = "如果无父菜单,则值为 0")
|
||||
private Integer pid;
|
||||
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||
private Integer sort;
|
||||
@ApiModelProperty(value = "菜单展示名", required = true, example = "商品管理")
|
||||
private String displayName;
|
||||
@ApiModelProperty(value = "子节点数组")
|
||||
private List<RoleResourceTreeNodeVO> children;
|
||||
@ApiModelProperty(value = "是否授权", required = true, example = "true")
|
||||
private Boolean assigned;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.mall.admin.application.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("角色 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RoleVO {
|
||||
|
||||
@ApiModelProperty(value = "角色编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "角色名字", required = true, example = "系统管理员")
|
||||
private String name;
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
client:
|
||||
enabled: true
|
||||
url: http://127.0.0.1:18097
|
||||
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "*"
|
||||
server:
|
||||
port: 19083 # 配置独立端口。而该端口,不使用 nginx 对外暴露,从而不配置安全认证。也就是说,内网环境可访问,外网环境不可访问。当然,这么做的前提是,认为内网安全。
|
||||
@@ -0,0 +1,19 @@
|
||||
spring:
|
||||
application:
|
||||
name: admin-application
|
||||
|
||||
# server
|
||||
server:
|
||||
port: 18083
|
||||
servlet:
|
||||
context-path: /admin-api/
|
||||
|
||||
# auth
|
||||
auth:
|
||||
ignore-urls: /admin-api/admins/admin/passport/login, /admin-api/admins/file/get_qiniu_token
|
||||
|
||||
# qiniu
|
||||
qiniu:
|
||||
access-key: YldfyUC7OewoWM63TPYTairqnq8GMJvNek9EGoID
|
||||
secret-key: zZ7Q8wwZRyaklVvkyLmVydA4WygOBqtc_gTYzalS
|
||||
bucket: onemall
|
||||
52
system/system-sdk/pom.xml
Normal file
52
system/system-sdk/pom.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>system</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>system-sdk</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>5.1.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>5.1.5.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>common-framework</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>system-service-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.mall.admin.sdk.context;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Security 上下文
|
||||
*/
|
||||
public class AdminSecurityContext {
|
||||
|
||||
private final Integer adminId;
|
||||
private final Set<Integer> roleIds;
|
||||
|
||||
public AdminSecurityContext(Integer adminId, Set<Integer> roleIds) {
|
||||
this.adminId = adminId;
|
||||
this.roleIds = roleIds;
|
||||
}
|
||||
|
||||
public Integer getAdminId() {
|
||||
return adminId;
|
||||
}
|
||||
|
||||
public Set<Integer> getRoleIds() {
|
||||
return roleIds;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.mall.admin.sdk.context;
|
||||
|
||||
/**
|
||||
* {@link AdminSecurityContext} Holder
|
||||
*
|
||||
* 参考 spring security 的 ThreadLocalSecurityContextHolderStrategy 类,简单实现。
|
||||
*/
|
||||
public class AdminSecurityContextHolder {
|
||||
|
||||
private static final ThreadLocal<AdminSecurityContext> securityContext = new ThreadLocal<AdminSecurityContext>();
|
||||
|
||||
public static void setContext(AdminSecurityContext context) {
|
||||
securityContext.set(context);
|
||||
}
|
||||
|
||||
public static AdminSecurityContext getContext() {
|
||||
AdminSecurityContext ctx = securityContext.get();
|
||||
// 为空时,设置一个空的进去
|
||||
if (ctx == null) {
|
||||
ctx = new AdminSecurityContext(null, null);
|
||||
securityContext.set(ctx);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
securityContext.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.iocoder.mall.admin.sdk.dict;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author Sin
|
||||
* @time 2019-04-16 20:43
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class Bean {
|
||||
|
||||
@DictVal(dicKey = "gender", dicValue = "1")
|
||||
private String gender;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.iocoder.mall.admin.sdk.dict;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 字典转换
|
||||
*
|
||||
* @author Sin
|
||||
* @time 2019-04-16 20:22
|
||||
*/
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DictVal {
|
||||
|
||||
/**
|
||||
* 字典的 key
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String dicKey();
|
||||
/**
|
||||
* 字典 value
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String dicValue();
|
||||
/**
|
||||
* - 暂时只有 dictDisplayName 字典值转换为 dictDisplayName 给用户界面
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String mode() default "dictDisplayName";
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.admin.sdk.dict;
|
||||
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* {@link DictVal} 处理器
|
||||
*
|
||||
* @author Sin
|
||||
* @time 2019-04-16 20:43
|
||||
*/
|
||||
public class DictValProcessor {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void processor(Class<?> clazz) {
|
||||
// ReflectionUtils.ann
|
||||
// clazz.getFi
|
||||
// ReflectionUtils
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package cn.iocoder.mall.admin.sdk.interceptor;
|
||||
|
||||
import cn.iocoder.common.framework.util.HttpUtil;
|
||||
import cn.iocoder.mall.admin.api.AdminAccessLogService;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 访问日志拦截器
|
||||
*/
|
||||
@Component
|
||||
public class AdminAccessLogInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private static final ThreadLocal<Date> START_TIME = new ThreadLocal<>();
|
||||
/**
|
||||
* 管理员编号
|
||||
*/
|
||||
private static final ThreadLocal<Integer> ADMIN_ID = new ThreadLocal<>();
|
||||
|
||||
@Reference(lazy = true)
|
||||
@Autowired(required = false) // TODO 芋艿,初始化时,会存在 spring boot 启动时,服务无法引用的情况,先暂时这么解决。
|
||||
private AdminAccessLogService adminAccessLogService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
// 记录当前时间
|
||||
START_TIME.set(new Date());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
if (adminAccessLogService == null) {
|
||||
throw new IllegalStateException("AdminAccessLogService 服务未引入成功");
|
||||
}
|
||||
AdminAccessLogAddDTO accessLog = new AdminAccessLogAddDTO();
|
||||
try {
|
||||
accessLog.setAdminId(ADMIN_ID.get());
|
||||
if (accessLog.getAdminId() == null) {
|
||||
accessLog.setAdminId(AdminAccessLogAddDTO.ADMIN_ID_NULL);
|
||||
}
|
||||
accessLog.setUri(request.getRequestURI()); // TODO 提升:如果想要优化,可以使用 Swagger 的 @ApiOperation 注解。
|
||||
accessLog.setQueryString(HttpUtil.buildQueryString(request));
|
||||
accessLog.setMethod(request.getMethod());
|
||||
accessLog.setUserAgent(HttpUtil.getUserAgent(request));
|
||||
accessLog.setIp(HttpUtil.getIp(request));
|
||||
accessLog.setStartTime(START_TIME.get());
|
||||
accessLog.setResponseTime((int) (System.currentTimeMillis() - accessLog.getStartTime().getTime()));// 默认响应时间设为0
|
||||
adminAccessLogService.addAdminAccessLog(accessLog);
|
||||
// TODO 提升:暂时不考虑 ELK 的方案。而是基于 MySQL 存储。如果访问日志比较多,需要定期归档。
|
||||
} catch (Throwable th) {
|
||||
logger.error("[afterCompletion][插入管理员访问日志({}) 发生异常({})", JSON.toJSONString(accessLog), ExceptionUtils.getRootCauseMessage(th));
|
||||
} finally {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAdminId(Integer adminId) {
|
||||
ADMIN_ID.set(adminId);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
START_TIME.remove();
|
||||
ADMIN_ID.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package cn.iocoder.mall.admin.sdk.interceptor;
|
||||
|
||||
import cn.iocoder.common.framework.exception.ServiceException;
|
||||
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 org.apache.dubbo.config.annotation.Reference;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 安全拦截器
|
||||
*/
|
||||
@Component
|
||||
public class AdminSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
@Reference(validation = "true")
|
||||
@Autowired(required = false) // TODO 芋艿,初始化时,会存在 spring boot 启动时,服务无法引用的情况,先暂时这么解决。
|
||||
private OAuth2Service oauth2Service;
|
||||
/**
|
||||
* 忽略的 URL 集合,即无需经过认证
|
||||
*/
|
||||
private Set<String> ignoreUrls;
|
||||
|
||||
public AdminSecurityInterceptor setIgnoreUrls(Set<String> ignoreUrls) {
|
||||
this.ignoreUrls = ignoreUrls;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
// 校验访问令牌是否正确。若正确,返回授权信息
|
||||
String accessToken = HttpUtil.obtainAccess(request);
|
||||
OAuth2AuthenticationBO authentication = null;
|
||||
if (accessToken != null) {
|
||||
CommonResult<OAuth2AuthenticationBO> result = oauth2Service.checkToken(accessToken);
|
||||
if (result.isError()) { // TODO 芋艿,如果访问的地址无需登录,这里也不用抛异常
|
||||
throw new ServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
authentication = result.getData();
|
||||
// 添加到 AdminSecurityContext
|
||||
AdminSecurityContext context = new AdminSecurityContext(authentication.getAdminId(), authentication.getRoleIds());
|
||||
AdminSecurityContextHolder.setContext(context);
|
||||
// 同时也记录管理员编号到 AdminAccessLogInterceptor 中。因为:
|
||||
// AdminAccessLogInterceptor 需要在 AdminSecurityInterceptor 之前执行,这样记录的访问日志才健全
|
||||
// AdminSecurityInterceptor 执行后,会移除 AdminSecurityContext 信息,这就导致 AdminAccessLogInterceptor 无法获得管理员编号
|
||||
// 因此,这里需要进行记录
|
||||
if (authentication.getAdminId() != null) {
|
||||
AdminAccessLogInterceptor.setAdminId(authentication.getAdminId());
|
||||
}
|
||||
} else {
|
||||
String url = request.getRequestURI();
|
||||
if (ignoreUrls != null && !ignoreUrls.contains(url)) { // TODO 临时写死。非登陆接口,必须已经认证身份,不允许匿名访问
|
||||
throw new ServiceException(AdminErrorCodeEnum.OAUTH_NOT_LOGIN.getCode(), AdminErrorCodeEnum.OAUTH_NOT_LOGIN.getMessage());
|
||||
}
|
||||
}
|
||||
// 校验是否需要已授权
|
||||
checkPermission(request, authentication);
|
||||
// 返回成功
|
||||
return super.preHandle(request, response, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
// 清空 SecurityContext
|
||||
AdminSecurityContextHolder.clear();
|
||||
}
|
||||
|
||||
private void checkPermission(HttpServletRequest request, OAuth2AuthenticationBO authentication) {
|
||||
Integer adminId = authentication != null ? authentication.getAdminId() : null;
|
||||
Set<Integer> roleIds = authentication != null ? authentication.getRoleIds() : null;
|
||||
String url = request.getRequestURI();
|
||||
CommonResult<Boolean> result = oauth2Service.checkPermission(adminId, roleIds, url);
|
||||
if (result.isError()) {
|
||||
throw new ServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 提供 SDK 给其它服务,使用如下功能:
|
||||
*
|
||||
* 1. 通过 {@link cn.iocoder.mall.admin.sdk.interceptor.UserSecurityInterceptor} 拦截器,实现需要登陆 URL 的鉴权
|
||||
*/
|
||||
package cn.iocoder.mall.admin.sdk;
|
||||
41
system/system-service-api/pom.xml
Normal file
41
system/system-service-api/pom.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>system</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>system-service-api</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>common-framework</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-jdk8</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package cn.iocoder.mall.admin.api;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
|
||||
|
||||
/**
|
||||
* 管理员访问日志 Service 接口
|
||||
*/
|
||||
public interface AdminAccessLogService {
|
||||
|
||||
CommonResult<Boolean> addAdminAccessLog(AdminAccessLogAddDTO adminAccessLogAddDTO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.mall.admin.api;
|
||||
|
||||
import cn.iocoder.common.framework.constant.CommonStatusEnum;
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.AdminBO;
|
||||
import cn.iocoder.mall.admin.api.bo.AdminPageBO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminPageDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminUpdateDTO;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 管理员 Service 接口
|
||||
*/
|
||||
public interface AdminService {
|
||||
|
||||
CommonResult<AdminPageBO> getAdminPage(AdminPageDTO adminPageDTO);
|
||||
|
||||
CommonResult<AdminBO> addAdmin(Integer adminId, AdminAddDTO adminAddDTO);
|
||||
|
||||
CommonResult<Boolean> updateAdmin(Integer adminId, AdminUpdateDTO adminUpdateDTO);
|
||||
|
||||
CommonResult<Boolean> updateAdminStatus(Integer adminId, Integer updateAdminId,
|
||||
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") Integer status);
|
||||
|
||||
CommonResult<Boolean> deleteAdmin(Integer adminId, Integer updateAdminId);
|
||||
|
||||
CommonResult<Boolean> assignRole(Integer adminId, Integer updateAdminId, Set<Integer> roleIds);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.iocoder.mall.admin.api;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.DataDictBO;
|
||||
import cn.iocoder.mall.admin.api.dto.DataDictAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.DataDictUpdateDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface DataDictService {
|
||||
|
||||
CommonResult<List<DataDictBO>> selectDataDictList();
|
||||
|
||||
CommonResult<DataDictBO> addDataDict(Integer adminId, DataDictAddDTO dataDictAddDTO);
|
||||
|
||||
CommonResult<Boolean> updateDataDict(Integer adminId, DataDictUpdateDTO dataDictUpdateDTO);
|
||||
|
||||
CommonResult<Boolean> deleteDataDict(Integer adminId, Integer dataDictId);
|
||||
|
||||
/**
|
||||
* 获取字典值 - 单个
|
||||
*
|
||||
* 注意: dictValue:Object 为了方便调用,会自动转换为 dictValue:String
|
||||
*
|
||||
* @param dictKey
|
||||
* @param dictValue
|
||||
* @return
|
||||
*/
|
||||
CommonResult<DataDictBO> getDataDict(String dictKey, Object dictValue);
|
||||
CommonResult<List<DataDictBO>> getDataDict(String dictKey);
|
||||
|
||||
/**
|
||||
* 获取字典值 - 多个
|
||||
*
|
||||
* 注意:dictValueList:? 为了方便调用,会自动转换为 Set:String
|
||||
*
|
||||
* @param dictKey
|
||||
* @param dictValueList
|
||||
* @return
|
||||
*/
|
||||
CommonResult<List<DataDictBO>> getDataDictList(String dictKey, Collection<?> dictValueList);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.mall.admin.api;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.OAuth2AccessTokenBO;
|
||||
import cn.iocoder.mall.admin.api.bo.OAuth2AuthenticationBO;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface OAuth2Service {
|
||||
|
||||
CommonResult<OAuth2AccessTokenBO> getAccessToken(String username, String password);
|
||||
|
||||
/**
|
||||
* 校验访问令牌,获取身份信息( 不包括 accessToken 等等 )
|
||||
*
|
||||
* @param accessToken 访问令牌
|
||||
* @return 授权信息
|
||||
*/
|
||||
CommonResult<OAuth2AuthenticationBO> checkToken(String accessToken);
|
||||
|
||||
/**
|
||||
* 校验权限(鉴权)
|
||||
*
|
||||
* @param adminId 管理员编号
|
||||
* @param roleIds 管理员拥有的角色编号的集合
|
||||
* @param url 指定 URL
|
||||
* @return 是否有权限
|
||||
*/
|
||||
CommonResult<Boolean> checkPermission(Integer adminId, Set<Integer> roleIds, String url);
|
||||
|
||||
// TODO @see 刷新 token
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.mall.admin.api;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.ResourceBO;
|
||||
import cn.iocoder.mall.admin.api.dto.ResourceAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.ResourceUpdateDTO;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ResourceService {
|
||||
|
||||
/**
|
||||
* 查询指定类型 + 指定角色的资源列表
|
||||
*
|
||||
* @param type 指定类型。可以为空,此时不作为过滤条件
|
||||
* @param roleIds 指定角色的数组。
|
||||
* @return 资源列表
|
||||
*/
|
||||
List<ResourceBO> getResourcesByTypeAndRoleIds(@Nullable Integer type, Set<Integer> roleIds);
|
||||
|
||||
/**
|
||||
* 查询指定类型的资源列表
|
||||
*
|
||||
* @param type 指定类型。可以为空,此时不做为过滤条件
|
||||
* @return 资源列表
|
||||
*/
|
||||
List<ResourceBO> getResourcesByType(@Nullable Integer type);
|
||||
|
||||
CommonResult<ResourceBO> addResource(Integer adminId, ResourceAddDTO resourceAddDTO);
|
||||
|
||||
CommonResult<Boolean> updateResource(Integer adminId, ResourceUpdateDTO resourceUpdateDTO);
|
||||
|
||||
CommonResult<Boolean> deleteResource(Integer adminId, Integer resourceId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.mall.admin.api;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.bo.RoleBO;
|
||||
import cn.iocoder.mall.admin.api.bo.RolePageBO;
|
||||
import cn.iocoder.mall.admin.api.dto.RoleAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.RolePageDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.RoleUpdateDTO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface RoleService {
|
||||
|
||||
CommonResult<RolePageBO> getRolePage(RolePageDTO rolePageDTO);
|
||||
|
||||
/**
|
||||
* 获得指定管理员拥有的角色编号数组
|
||||
*
|
||||
* @param adminId 指定管理员
|
||||
* @return 角色编号数组
|
||||
*/
|
||||
CommonResult<Set<Integer>> getRoleList(Integer adminId);
|
||||
|
||||
/**
|
||||
* @return 返回角色列表
|
||||
*/
|
||||
CommonResult<List<RoleBO>> getRoleList();
|
||||
|
||||
CommonResult<RoleBO> addRole(Integer adminId, RoleAddDTO roleAddDTO);
|
||||
|
||||
CommonResult<Boolean> updateRole(Integer adminId, RoleUpdateDTO roleUpdateDTO);
|
||||
|
||||
CommonResult<Boolean> deleteRole(Integer adminId, Integer roleId);
|
||||
|
||||
CommonResult<Boolean> assignResource(Integer adminId, Integer roleId, Set<Integer> resourceIds);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 管理员 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 管理员编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 登陆账号
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String nickname;
|
||||
/**
|
||||
* 账号状态
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理员分页 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminPageBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 管理员数组
|
||||
*/
|
||||
private List<AdminBO> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 数据字典 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DataDictBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 大类枚举值
|
||||
*/
|
||||
private String enumValue;
|
||||
/**
|
||||
* 小类数值
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
private String displayName;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* OAUTH2 AccessToken BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
private String accessToken;
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
private String refreshToken;
|
||||
/**
|
||||
* 过期时间,单位:秒。
|
||||
*/
|
||||
private Integer expiresIn;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* OAUTH2 认证 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AuthenticationBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 管理员编号
|
||||
*/
|
||||
private Integer adminId;
|
||||
/**
|
||||
* 角色编号数组
|
||||
*/
|
||||
private Set<Integer> roleIds;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 资源 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ResourceBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 资源编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 资源名字(标识)
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 资源类型
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
private String displayName;
|
||||
/**
|
||||
* 添加时间
|
||||
*/
|
||||
private Date createTime;
|
||||
/**
|
||||
* 父级资源编号
|
||||
*/
|
||||
private Integer pid;
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
private String handler;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 角色 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RoleBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 角色编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 角色名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 添加时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.admin.api.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色分页 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RolePageBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 角色数组
|
||||
*/
|
||||
private List<RoleBO> roles;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.iocoder.mall.admin.api.constant;
|
||||
|
||||
public class AdminConstants {
|
||||
|
||||
public static final String USERNAME_ADMIN = "admin";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package cn.iocoder.mall.admin.api.constant;
|
||||
|
||||
/**
|
||||
* 错误码枚举类
|
||||
*
|
||||
* 管理员系统,使用 1-002-000-000 段
|
||||
*/
|
||||
public enum AdminErrorCodeEnum {
|
||||
|
||||
// ========== OAUTH2 模块 ==========
|
||||
OAUTH2_UNKNOWN(1002001000, "未知错误"), // 预留
|
||||
// OAUTH2_INVALID_GRANT_BAD_CREDENTIALS(1001001001, "密码不正确"), // 暂时没用到
|
||||
// OAUTH2_INVALID_GRANT_USERNAME_NOT_FOUND(1001001002, "账号不存在"), // 暂时没用到
|
||||
// OAUTH2_INVALID_GRANT(1001001010, ""), // 预留
|
||||
OAUTH_INVALID_TOKEN_NOT_FOUND(1002001011, "访问令牌不存在"),
|
||||
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, ""), // 预留
|
||||
|
||||
// ========== 管理员模块 1002002000 ==========
|
||||
ADMIN_USERNAME_NOT_REGISTERED(1002002000, "账号不存在"),
|
||||
ADMIN_PASSWORD_ERROR(1002002001, "密码不正确"),
|
||||
ADMIN_IS_DISABLE(1002002002, "账号被禁用"),
|
||||
ADMIN_USERNAME_EXISTS(1002002002, "账号已经存在"),
|
||||
ADMIN_STATUS_EQUALS(1002002003, "账号已经是该状态"),
|
||||
ADMIN_DELETE_ONLY_DISABLE(1002002004, "只有关闭的账号才可以删除"),
|
||||
ADMIN_ADMIN_STATUS_CAN_NOT_UPDATE(1002002005, "管理员的账号状态不允许变更"),
|
||||
|
||||
// ========== 资源模块 1002003000 ==========
|
||||
RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
|
||||
RESOURCE_PARENT_NOT_EXISTS(1002003001, "父资源不存在"),
|
||||
RESOURCE_PARENT_ERROR(1002003002, "不能设置自己为父资源"),
|
||||
RESOURCE_NOT_EXISTS(1002003003, "资源不存在"),
|
||||
RESOURCE_EXISTS_CHILDREN(1002003004, "存在子资源,无法删除"),
|
||||
|
||||
// ========== 角色模块 1002004000 ==========
|
||||
ROLE_NOT_EXISTS(1002004000, "角色不存在"),
|
||||
ROLE_ASSIGN_RESOURCE_NOT_EXISTS(1002004001, "分配角色资源时,有资源不存在"),
|
||||
|
||||
// ========== 数据字典模块 1002005000 ==========
|
||||
DATA_DICT_EXISTS(1002005000, "该数据字典已经存在"),
|
||||
DATA_DICT_NOT_EXISTS(1002005001, "该数据字典不存在"),
|
||||
|
||||
;
|
||||
|
||||
private final int code;
|
||||
private final String message;
|
||||
|
||||
AdminErrorCodeEnum(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.mall.admin.api.constant;
|
||||
|
||||
/**
|
||||
* 资源类型
|
||||
*/
|
||||
public interface ResourceConstants {
|
||||
|
||||
/**
|
||||
* 类型 - 菜单
|
||||
*/
|
||||
Integer TYPE_MENU = 1;
|
||||
/**
|
||||
* 类型 - URL
|
||||
*/
|
||||
Integer TYPE_URL = 2;
|
||||
|
||||
/**
|
||||
* 父资源编号 - 根节点
|
||||
*/
|
||||
Integer PID_ROOT = 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 管理员访问日志添加 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminAccessLogAddDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 管理员编号 - 空
|
||||
*/
|
||||
public static final Integer ADMIN_ID_NULL = 0;
|
||||
|
||||
/**
|
||||
* 管理员编号.
|
||||
*
|
||||
* 当管理员为空时,该值为0
|
||||
*/
|
||||
@NotNull(message = "管理员编号不能为空")
|
||||
private Integer adminId;
|
||||
/**
|
||||
* 访问地址
|
||||
*/
|
||||
@NotNull(message = "访问地址不能为空")
|
||||
private String uri;
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
@NotNull(message = "请求参数不能为空")
|
||||
private String queryString;
|
||||
/**
|
||||
* http 方法
|
||||
*/
|
||||
@NotNull(message = "http 请求方法不能为空")
|
||||
private String method;
|
||||
/**
|
||||
* User Agent
|
||||
*/
|
||||
@NotNull(message = "User-Agent 不能为空")
|
||||
private String userAgent;
|
||||
/**
|
||||
* ip
|
||||
*/
|
||||
@NotNull(message = "ip 不能为空")
|
||||
private String ip;
|
||||
/**
|
||||
* 请求时间
|
||||
*/
|
||||
@NotNull(message = "请求时间不能为空")
|
||||
private Date startTime;
|
||||
/**
|
||||
* 响应时长 -- 毫秒级
|
||||
*/
|
||||
@NotNull(message = "响应时长不能为空")
|
||||
private Integer responseTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
/**
|
||||
* 管理员添加 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminAddDTO {
|
||||
|
||||
/**
|
||||
* 登陆账号
|
||||
*/
|
||||
@NotEmpty(message = "登陆账号不能为空")
|
||||
@Length(min = 6, max = 16, message = "账号长度为 6-16 位")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||
private String username;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@NotEmpty(message = "昵称不能为空")
|
||||
@Length(max = 10, message = "昵称长度最大为 10 位")
|
||||
private String nickname;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@NotEmpty(message = "密码不能为空")
|
||||
@Length(min = 6, max = 16, message = "密码长度为 6-16 位")
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 管理员分页 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminPageDTO {
|
||||
|
||||
/**
|
||||
* 昵称,模糊匹配
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
@NotNull(message = "页码不能为空")
|
||||
private Integer pageNo;
|
||||
@NotNull(message = "每页条数不能为空")
|
||||
private Integer pageSize;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
/**
|
||||
* 管理员更新 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminUpdateDTO {
|
||||
|
||||
/**
|
||||
* 管理员编号
|
||||
*/
|
||||
@NotNull(message = "管理员编号不能为空")
|
||||
private Integer id;
|
||||
/**
|
||||
* 登陆账号
|
||||
*/
|
||||
@NotEmpty(message = "登陆账号不能为空")
|
||||
@Length(min = 6, max = 16, message = "账号长度为 6-16 位")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||
private String username;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@NotEmpty(message = "昵称不能为空")
|
||||
@Length(max = 10, message = "昵称长度最大为 10 位")
|
||||
private String nickname;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@Length(min = 6, max = 16, message = "密码长度为 6-16 位")
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 数据字典添加 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DataDictAddDTO {
|
||||
|
||||
/**
|
||||
* 大类枚举值
|
||||
*/
|
||||
@NotEmpty(message = "大类枚举值不能为空")
|
||||
private String enumValue;
|
||||
/**
|
||||
* 小类数值
|
||||
*/
|
||||
@NotEmpty(message = "小类数值不能为空")
|
||||
private String value;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
@NotEmpty(message = "展示名不能为空")
|
||||
private String displayName;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
@NotNull(message = "排序值不能为空")
|
||||
private Integer sort;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 数据字典更新 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DataDictUpdateDTO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Integer id;
|
||||
/**
|
||||
* 小类数值
|
||||
*/
|
||||
@NotEmpty(message = "小类数值不能为空")
|
||||
private String value;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
@NotEmpty(message = "展示名不能为空")
|
||||
private String displayName;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
@NotNull(message = "排序值不能为空")
|
||||
private Integer sort;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 资源添加 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ResourceAddDTO {
|
||||
|
||||
/**
|
||||
* 资源名字(标识)
|
||||
*/
|
||||
@NotEmpty(message = "资源名字不能为空")
|
||||
private String name;
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
@NotNull(message = "类型不能为空")
|
||||
private Integer type;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
@NotNull(message = "类型不能为空")
|
||||
private Integer sort;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
@NotEmpty(message = "资源名字不能为空")
|
||||
private String displayName;
|
||||
/**
|
||||
* 父资源编号
|
||||
*/
|
||||
private Integer pid;
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
private String handler;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 资源更新 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ResourceUpdateDTO {
|
||||
|
||||
/**
|
||||
* 资源编号
|
||||
*/
|
||||
@NotNull(message = "资源编号不能为空")
|
||||
private Integer id;
|
||||
/**
|
||||
* 资源名字(标识)
|
||||
*/
|
||||
@NotEmpty(message = "资源名字不能为空")
|
||||
private String name;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
@NotNull(message = "类型不能为空")
|
||||
private Integer sort;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
@NotEmpty(message = "资源名字不能为空")
|
||||
private String displayName;
|
||||
/**
|
||||
* 父资源编号
|
||||
*/
|
||||
private Integer pid;
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
private String handler;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* 角色添加 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RoleAddDTO {
|
||||
|
||||
/**
|
||||
* 角色名字(标识)
|
||||
*/
|
||||
@NotEmpty(message = "角色名字不能为空")
|
||||
private String name;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 角色分页 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RolePageDTO {
|
||||
|
||||
private Integer pageNo;
|
||||
private Integer pageSize;
|
||||
private String name;
|
||||
|
||||
public Integer getPageNo() {
|
||||
return pageNo;
|
||||
}
|
||||
|
||||
public RolePageDTO setPageNo(Integer pageNo) {
|
||||
this.pageNo = pageNo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public RolePageDTO setPageSize(Integer pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public RolePageDTO setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.admin.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 角色添加 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RoleUpdateDTO {
|
||||
|
||||
/**
|
||||
* 角色编号
|
||||
*/
|
||||
@NotNull(message = "角色编号不能为空")
|
||||
private Integer id;
|
||||
/**
|
||||
* 角色名字(标识)
|
||||
*/
|
||||
@NotEmpty(message = "角色名字不能为空")
|
||||
private String name;
|
||||
|
||||
}
|
||||
69
system/system-service-impl/pom.xml
Normal file
69
system/system-service-impl/pom.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>system</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>system-service-impl</artifactId>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>system-service-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-framework</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-recipes</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 提供给 mapstruct 使用 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.mall.admin.config;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@MapperScan("cn.iocoder.mall.admin.dao") // 扫描对应的 Mapper 接口
|
||||
@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理。为什么使用 proxyTargetClass 参数,参见 https://blog.csdn.net/huang_550/article/details/76492600
|
||||
public class DatabaseConfiguration {
|
||||
|
||||
// 数据源,使用 HikariCP
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.mall.admin.config;
|
||||
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
|
||||
@Configuration
|
||||
public class ServiceExceptionConfiguration {
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class) // 可参考 https://www.cnblogs.com/ssslinppp/p/7607509.html
|
||||
public void initMessages() {
|
||||
// 从 service_exception_message.properties 加载错误码的方案
|
||||
// Properties properties;
|
||||
// try {
|
||||
// properties = PropertiesLoaderUtils.loadAllProperties("classpath:service_exception_message.properties");
|
||||
// } catch (IOException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
for (AdminErrorCodeEnum item : AdminErrorCodeEnum.values()) {
|
||||
ServiceExceptionUtil.put(item.getCode(), item.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.mall.admin.convert;
|
||||
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
|
||||
import cn.iocoder.mall.admin.dataobject.AdminAccessLogDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface AdminAccessLogConvert {
|
||||
|
||||
AdminAccessLogConvert INSTANCE = Mappers.getMapper(AdminAccessLogConvert.class);
|
||||
|
||||
@Mappings({})
|
||||
AdminAccessLogDO convert(AdminAccessLogAddDTO adminAccessLogAddDTO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.mall.admin.convert;
|
||||
|
||||
import cn.iocoder.mall.admin.api.bo.AdminBO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminUpdateDTO;
|
||||
import cn.iocoder.mall.admin.dataobject.AdminDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AdminConvert {
|
||||
|
||||
AdminConvert INSTANCE = Mappers.getMapper(AdminConvert.class);
|
||||
|
||||
@Mappings({})
|
||||
AdminBO convert(AdminDO adminDO);
|
||||
|
||||
@Mappings({})
|
||||
AdminDO convert(AdminAddDTO adminAddDTO);
|
||||
|
||||
@Mappings({})
|
||||
AdminDO convert(AdminUpdateDTO adminUpdateDTO);
|
||||
|
||||
@Mappings({})
|
||||
List<AdminBO> convert(List<AdminDO> adminBOs);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.admin.convert;
|
||||
|
||||
import cn.iocoder.mall.admin.api.bo.DataDictBO;
|
||||
import cn.iocoder.mall.admin.api.dto.DataDictAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.DataDictUpdateDTO;
|
||||
import cn.iocoder.mall.admin.dataobject.DataDictDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface DataDictConvert {
|
||||
|
||||
DataDictConvert INSTANCE = Mappers.getMapper(DataDictConvert.class);
|
||||
|
||||
DataDictDO convert(DataDictAddDTO dataDictAddDTO);
|
||||
|
||||
DataDictDO convert(DataDictUpdateDTO dataDictUpdateDTO);
|
||||
|
||||
DataDictBO convert(DataDictDO dataDictDO);
|
||||
|
||||
List<DataDictBO> convert(List<DataDictDO> dataDictDOs);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.mall.admin.convert;
|
||||
|
||||
import cn.iocoder.mall.admin.api.bo.OAuth2AccessTokenBO;
|
||||
import cn.iocoder.mall.admin.api.bo.OAuth2AuthenticationBO;
|
||||
import cn.iocoder.mall.admin.dataobject.AdminRoleDO;
|
||||
import cn.iocoder.mall.admin.dataobject.OAuth2AccessTokenDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mapper
|
||||
public interface OAuth2Convert {
|
||||
|
||||
OAuth2Convert INSTANCE = Mappers.getMapper(OAuth2Convert.class);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "id", target = "accessToken")
|
||||
})
|
||||
OAuth2AccessTokenBO convertToAccessToken(OAuth2AccessTokenDO oauth2AccessTokenDO);
|
||||
|
||||
default OAuth2AccessTokenBO convertToAccessTokenWithExpiresIn(OAuth2AccessTokenDO oauth2AccessTokenDO) {
|
||||
return this.convertToAccessToken(oauth2AccessTokenDO)
|
||||
.setExpiresIn(Math.max((int) ((oauth2AccessTokenDO.getExpiresTime().getTime() - System.currentTimeMillis()) / 1000), 0));
|
||||
}
|
||||
|
||||
@Mappings({})
|
||||
OAuth2AuthenticationBO convertToAuthentication(OAuth2AccessTokenDO oauth2AccessTokenDO);
|
||||
|
||||
default OAuth2AuthenticationBO convertToAuthentication(OAuth2AccessTokenDO oauth2AccessTokenDO, List<AdminRoleDO> adminRoleDOs) {
|
||||
return convertToAuthentication(oauth2AccessTokenDO)
|
||||
.setRoleIds(adminRoleDOs.stream().map(AdminRoleDO::getRoleId).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.mall.admin.convert;
|
||||
|
||||
import cn.iocoder.mall.admin.api.bo.ResourceBO;
|
||||
import cn.iocoder.mall.admin.api.dto.ResourceAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.ResourceUpdateDTO;
|
||||
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<ResourceBO> convert(List<ResourceDO> resourceDOs);
|
||||
|
||||
@Mappings({})
|
||||
ResourceDO convert(ResourceAddDTO resourceAddDTO);
|
||||
|
||||
@Mappings({})
|
||||
ResourceDO convert(ResourceUpdateDTO resourceUpdateDTO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.mall.admin.convert;
|
||||
|
||||
import cn.iocoder.mall.admin.api.bo.RoleBO;
|
||||
import cn.iocoder.mall.admin.api.dto.RoleAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.RoleUpdateDTO;
|
||||
import cn.iocoder.mall.admin.dataobject.RoleDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface RoleConvert {
|
||||
|
||||
RoleConvert INSTANCE = Mappers.getMapper(RoleConvert.class);
|
||||
|
||||
@Mappings({})
|
||||
RoleDO convert(RoleAddDTO roleAddDTO);
|
||||
|
||||
@Mappings({})
|
||||
RoleDO convert(RoleUpdateDTO roleUpdateDTO);
|
||||
|
||||
@Mappings({})
|
||||
RoleBO convert(RoleDO roleDO);
|
||||
|
||||
@Mappings({})
|
||||
List<RoleBO> convert(List<RoleDO> roleDOs);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.AdminAccessLogDO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AdminAccessLogMapper {
|
||||
|
||||
void insert(AdminAccessLogDO entity);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.AdminDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface AdminMapper {
|
||||
|
||||
AdminDO selectById(@Param("id") Integer id);
|
||||
|
||||
AdminDO selectByUsername(@Param("username") String username);
|
||||
|
||||
List<AdminDO> selectListByNicknameLike(@Param("nickname") String nickname,
|
||||
@Param("offset") Integer offset,
|
||||
@Param("limit") Integer limit);
|
||||
|
||||
Integer selectCountByNicknameLike(@Param("nickname") String nickname);
|
||||
|
||||
void insert(AdminDO admin);
|
||||
|
||||
int update(AdminDO admin);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.AdminRoleDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface AdminRoleMapper {
|
||||
|
||||
List<AdminRoleDO> selectByAdminId(@Param("adminId") Integer adminId);
|
||||
|
||||
int updateToDeletedByAdminId(@Param("adminId") Integer adminId);
|
||||
|
||||
int updateToDeletedByRoleId(@Param("roleId") Integer roleId);
|
||||
|
||||
void insertList(@Param("adminRoleDOs") List<AdminRoleDO> adminRoleDOs);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.DataDictDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface DataDictMapper {
|
||||
|
||||
DataDictDO selectById(@Param("id") Integer id);
|
||||
|
||||
DataDictDO selectByEnumValueAndValue(
|
||||
@Param("enumValue") String enumValue,
|
||||
@Param("value") String value
|
||||
);
|
||||
|
||||
List<DataDictDO> selectByEnumValueAndValues(
|
||||
@Param("enumValue") String enumValue,
|
||||
@Param("values") Collection<String> values
|
||||
);
|
||||
|
||||
List<DataDictDO> selectByEnumValue(
|
||||
@Param("enumValue") String enumValue
|
||||
);
|
||||
|
||||
List<DataDictDO> selectList();
|
||||
|
||||
void insert(DataDictDO dataDict);
|
||||
|
||||
int update(DataDictDO dataDict);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.OAuth2AccessTokenDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface OAuth2AccessTokenMapper {
|
||||
|
||||
void insert(OAuth2AccessTokenDO entity);
|
||||
|
||||
OAuth2AccessTokenDO selectByTokenId(@Param("id") String id);
|
||||
|
||||
int updateToInvalidByAdminId(@Param("adminId") Integer adminId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.OAuth2RefreshTokenDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface OAuth2RefreshTokenMapper {
|
||||
|
||||
void insert(OAuth2RefreshTokenDO entity);
|
||||
|
||||
int updateToInvalidByAdminId(@Param("adminId") Integer adminId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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<ResourceDO> selectListByTypeAndRoleIds(@Param("type") Integer type,
|
||||
@Param("roleIds") Set<Integer> roleIds);
|
||||
|
||||
List<ResourceDO> selectListByType(@Param("type") Integer type);
|
||||
|
||||
ResourceDO selectByName(@Param("name") String name);
|
||||
|
||||
ResourceDO selectById(@Param("id") Integer id);
|
||||
|
||||
List<ResourceDO> selectListByIds(@Param("ids") Set<Integer> ids);
|
||||
|
||||
void insert(ResourceDO resource);
|
||||
|
||||
int update(ResourceDO resource);
|
||||
|
||||
int selectCountByPid(@Param("pid") Integer pid);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.RoleDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Repository
|
||||
public interface RoleMapper {
|
||||
|
||||
void insert(RoleDO roleDO);
|
||||
|
||||
int update(RoleDO roleDO);
|
||||
|
||||
RoleDO selectById(@Param("id") Integer id);
|
||||
|
||||
List<RoleDO> selectListByNameLike(@Param("name") String name,
|
||||
@Param("offset") Integer offset,
|
||||
@Param("limit") Integer limit);
|
||||
|
||||
Integer selectCountByNameLike(@Param("name") String name);
|
||||
|
||||
List<RoleDO> selectListByIds(@Param("ids") Set<Integer> ids);
|
||||
|
||||
List<RoleDO> selectList();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.mall.admin.dao;
|
||||
|
||||
import cn.iocoder.mall.admin.dataobject.RoleResourceDO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface RoleResourceMapper {
|
||||
|
||||
int insertList(@Param("roleResources") List<RoleResourceDO> resourceDOs);
|
||||
|
||||
List<RoleResourceDO> selectByResourceHandler(@Param("resourceHandler") String resourceHandler);
|
||||
|
||||
List<RoleResourceDO> selectByResourceId(@Param("resourceId") Integer resourceId);
|
||||
|
||||
int updateToDeletedByResourceId(@Param("resourceId") Integer resourceId);
|
||||
|
||||
int updateToDeletedByRoleId(@Param("roleId") Integer roleId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 管理员访问日志 DO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminAccessLogDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 管理员编号.
|
||||
*
|
||||
* 当管理员为空时,该值为0
|
||||
*/
|
||||
private Integer adminId;
|
||||
/**
|
||||
* 访问地址
|
||||
*/
|
||||
private String uri;
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
private String queryString;
|
||||
/**
|
||||
* http 方法
|
||||
*/
|
||||
private String method;
|
||||
/**
|
||||
* userAgent
|
||||
*/
|
||||
private String userAgent;
|
||||
/**
|
||||
* ip
|
||||
*/
|
||||
private String ip;
|
||||
/**
|
||||
* 请求时间
|
||||
*/
|
||||
private Date startTime;
|
||||
/**
|
||||
* 响应时长 -- 毫秒级
|
||||
*/
|
||||
private Integer responseTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 管理员实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 管理员编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 登陆账号
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String nickname;
|
||||
/**
|
||||
* 密码
|
||||
*
|
||||
* TODO 芋艿 暂时最简单的 MD5
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 账号状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* {@link AdminDO} 和 {@link RoleDO} 的关联表
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminRoleDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 管理员编号(外键:{@link AdminDO}
|
||||
*/
|
||||
private Integer adminId;
|
||||
/**
|
||||
* 角色编号(外键:{@link RoleDO}
|
||||
*/
|
||||
private Integer roleId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 数据字典
|
||||
*
|
||||
* 使用 {@link #enumValue} 作为聚合。例如说:
|
||||
*
|
||||
* enumValue :gender 性别
|
||||
* value:1 男
|
||||
* value:2 女
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DataDictDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 大类枚举值
|
||||
*/
|
||||
private String enumValue;
|
||||
/**
|
||||
* 小类数值
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
private String displayName;
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String memo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* OAUTH2 AccessToken
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenDO {
|
||||
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
private String refreshToken;
|
||||
/**
|
||||
* 管理员比那好
|
||||
*/
|
||||
private Integer adminId;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Date expiresTime;
|
||||
/**
|
||||
* 是否有效
|
||||
*/
|
||||
private Boolean valid;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public OAuth2AccessTokenDO setId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public OAuth2AccessTokenDO setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getAdminId() {
|
||||
return adminId;
|
||||
}
|
||||
|
||||
public OAuth2AccessTokenDO setAdminId(Integer adminId) {
|
||||
this.adminId = adminId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Date getExpiresTime() {
|
||||
return expiresTime;
|
||||
}
|
||||
|
||||
public OAuth2AccessTokenDO setExpiresTime(Date expiresTime) {
|
||||
this.expiresTime = expiresTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
public OAuth2AccessTokenDO setValid(Boolean valid) {
|
||||
this.valid = valid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public OAuth2AccessTokenDO setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*
|
||||
* idx_uid
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2RefreshTokenDO {
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer adminId;
|
||||
/**
|
||||
* 是否有效
|
||||
*/
|
||||
private Boolean valid;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Date expiresTime;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 资源实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ResourceDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 资源类型 - 菜单
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Integer TYPE_MENU = 1;
|
||||
/**
|
||||
* 资源类型 - 操作
|
||||
*
|
||||
* 例如,按钮。
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Integer TYPE_OPERATION = 2;
|
||||
|
||||
/**
|
||||
* 资源编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 资源名字(标识)
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 资源类型
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 展示名
|
||||
*/
|
||||
private String displayName;
|
||||
/**
|
||||
* 添加时间
|
||||
*/
|
||||
private Date createTime;
|
||||
/**
|
||||
* 父级资源编号(外键:{@link ResourceDO#id})
|
||||
*/
|
||||
private Integer pid;
|
||||
/**
|
||||
* 操作
|
||||
*
|
||||
* 当资源类型为【菜单】时,handler 配置为界面 URL ,或者前端组件名
|
||||
* 当资源类型为【URL】时,handler 配置为后端 URL 。举个例子,如果有一个「创建管理员」的表单,那么前端界面上的按钮可以根据这个 url 判断是否展示,后端接收到该 url 的请求时会判断是否有权限。
|
||||
*/
|
||||
private String handler;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 角色实体
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RoleDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 角色编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.admin.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* {@link RoleDO} 和 {@link ResourceDO} 的关联表
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RoleResourceDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 角色编号(外键:{@link RoleDO}
|
||||
*/
|
||||
private Integer roleId;
|
||||
/**
|
||||
* 资源编号(外键:{@link ResourceDO}
|
||||
*/
|
||||
private Integer resourceId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package cn.iocoder.mall.admin.service;
|
||||
|
||||
import cn.iocoder.common.framework.util.StringUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.admin.api.AdminAccessLogService;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
|
||||
import cn.iocoder.mall.admin.convert.AdminAccessLogConvert;
|
||||
import cn.iocoder.mall.admin.dao.AdminAccessLogMapper;
|
||||
import cn.iocoder.mall.admin.dataobject.AdminAccessLogDO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Service
|
||||
@org.apache.dubbo.config.annotation.Service(validation = "true")
|
||||
public class AdminAccessLogServiceImpl implements AdminAccessLogService {
|
||||
|
||||
/**
|
||||
* 请求参数最大长度。
|
||||
*/
|
||||
private static final Integer QUERY_STRING_MAX_LENGTH = 4096;
|
||||
/**
|
||||
* 请求地址最大长度。
|
||||
*/
|
||||
private static final Integer URI_MAX_LENGTH = 4096;
|
||||
/**
|
||||
* User-Agent 最大长度。
|
||||
*/
|
||||
private static final Integer USER_AGENT_MAX_LENGTH = 1024;
|
||||
|
||||
@Autowired
|
||||
private AdminAccessLogMapper adminAccessLogMapper;
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> addAdminAccessLog(AdminAccessLogAddDTO adminAccessLogAddDTO) {
|
||||
// 创建 AdminAccessLogDO
|
||||
AdminAccessLogDO accessLog = AdminAccessLogConvert.INSTANCE.convert(adminAccessLogAddDTO);
|
||||
accessLog.setCreateTime(new Date());
|
||||
// 截取最大长度
|
||||
if (accessLog.getUri().length() > URI_MAX_LENGTH) {
|
||||
accessLog.setUri(StringUtil.substring(accessLog.getUri(), URI_MAX_LENGTH));
|
||||
}
|
||||
if (accessLog.getQueryString().length() > QUERY_STRING_MAX_LENGTH) {
|
||||
accessLog.setQueryString(StringUtil.substring(accessLog.getQueryString(), QUERY_STRING_MAX_LENGTH));
|
||||
}
|
||||
if (accessLog.getUserAgent().length() > USER_AGENT_MAX_LENGTH) {
|
||||
accessLog.setUserAgent(StringUtil.substring(accessLog.getUserAgent(), USER_AGENT_MAX_LENGTH));
|
||||
}
|
||||
// 插入
|
||||
adminAccessLogMapper.insert(accessLog);
|
||||
// 返回成功
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package cn.iocoder.mall.admin.service;
|
||||
|
||||
import cn.iocoder.common.framework.constant.CommonStatusEnum;
|
||||
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
||||
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.bo.AdminBO;
|
||||
import cn.iocoder.mall.admin.api.bo.AdminPageBO;
|
||||
import cn.iocoder.mall.admin.api.constant.AdminConstants;
|
||||
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminAddDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminPageDTO;
|
||||
import cn.iocoder.mall.admin.api.dto.AdminUpdateDTO;
|
||||
import cn.iocoder.mall.admin.convert.AdminConvert;
|
||||
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 cn.iocoder.mall.admin.dataobject.RoleDO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@org.apache.dubbo.config.annotation.Service(validation = "true")
|
||||
public class AdminServiceImpl implements AdminService {
|
||||
|
||||
@Autowired
|
||||
private AdminMapper adminMapper;
|
||||
@Autowired
|
||||
private AdminRoleMapper adminRoleMapper;
|
||||
|
||||
@Autowired
|
||||
private OAuth2ServiceImpl oAuth2Service;
|
||||
@Autowired
|
||||
private RoleServiceImpl roleService;
|
||||
|
||||
public CommonResult<AdminDO> validAdmin(String username, String password) {
|
||||
AdminDO admin = adminMapper.selectByUsername(username);
|
||||
// 账号不存在
|
||||
if (admin == null) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
|
||||
}
|
||||
// 密码不正确
|
||||
if (encodePassword(password).equals(admin.getPassword())) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_PASSWORD_ERROR.getCode());
|
||||
}
|
||||
// 账号被禁用
|
||||
if (CommonStatusEnum.DISABLE.getValue().equals(admin.getStatus())) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_IS_DISABLE.getCode());
|
||||
}
|
||||
// 校验成功,返回管理员。并且,去掉一些非关键字段,考虑安全性。
|
||||
admin.setPassword(null);
|
||||
admin.setStatus(null);
|
||||
return CommonResult.success(admin);
|
||||
}
|
||||
|
||||
public List<AdminRoleDO> getAdminRoles(Integer adminId) {
|
||||
return adminRoleMapper.selectByAdminId(adminId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<AdminPageBO> getAdminPage(AdminPageDTO adminPageDTO) {
|
||||
AdminPageBO adminPage = new AdminPageBO();
|
||||
// 查询分页数据
|
||||
int offset = (adminPageDTO.getPageNo() - 1) * adminPageDTO.getPageSize();
|
||||
adminPage.setList(AdminConvert.INSTANCE.convert(adminMapper.selectListByNicknameLike(adminPageDTO.getNickname(),
|
||||
offset, adminPageDTO.getPageSize())));
|
||||
// 查询分页总数
|
||||
adminPage.setTotal(adminMapper.selectCountByNicknameLike(adminPageDTO.getNickname()));
|
||||
return CommonResult.success(adminPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<AdminBO> addAdmin(Integer adminId, AdminAddDTO adminAddDTO) {
|
||||
// 校验账号唯一
|
||||
if (adminMapper.selectByUsername(adminAddDTO.getUsername()) != null) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_EXISTS.getCode());
|
||||
}
|
||||
// 保存到数据库
|
||||
AdminDO admin = AdminConvert.INSTANCE.convert(adminAddDTO)
|
||||
.setPassword(encodePassword(adminAddDTO.getPassword())) // 加密密码
|
||||
.setStatus(CommonStatusEnum.ENABLE.getValue());
|
||||
admin.setCreateTime(new Date());
|
||||
admin.setDeleted(DeletedStatusEnum.DELETED_NO.getValue());
|
||||
adminMapper.insert(admin);
|
||||
// TODO 插入操作日志
|
||||
// 返回成功
|
||||
return CommonResult.success(AdminConvert.INSTANCE.convert(admin));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> updateAdmin(Integer adminId, AdminUpdateDTO adminUpdateDTO) {
|
||||
// 校验账号存在
|
||||
if (adminMapper.selectById(adminUpdateDTO.getId()) == null) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
|
||||
}
|
||||
// 校验账号唯一
|
||||
AdminDO usernameAdmin = adminMapper.selectByUsername(adminUpdateDTO.getUsername());
|
||||
if (usernameAdmin != null && !usernameAdmin.getId().equals(adminUpdateDTO.getId())) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_EXISTS.getCode());
|
||||
}
|
||||
// 更新到数据库
|
||||
AdminDO updateAdmin = AdminConvert.INSTANCE.convert(adminUpdateDTO);
|
||||
adminMapper.update(updateAdmin);
|
||||
// TODO 插入操作日志
|
||||
// 返回成功
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommonResult<Boolean> updateAdminStatus(Integer adminId, Integer updateAdminId, Integer status) {
|
||||
// 校验账号存在
|
||||
AdminDO admin = adminMapper.selectById(updateAdminId);
|
||||
if (admin == null) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
|
||||
}
|
||||
if (AdminConstants.USERNAME_ADMIN.equals(admin.getUsername())) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_ADMIN_STATUS_CAN_NOT_UPDATE.getCode());
|
||||
}
|
||||
// 如果状态相同,则返回错误
|
||||
if (status.equals(admin.getStatus())) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_STATUS_EQUALS.getCode());
|
||||
}
|
||||
// 更新管理员状态
|
||||
AdminDO updateAdmin = new AdminDO().setId(updateAdminId).setStatus(status);
|
||||
adminMapper.update(updateAdmin);
|
||||
// 如果是关闭管理员,则标记 token 失效。否则,管理员还可以继续蹦跶
|
||||
if (CommonStatusEnum.DISABLE.getValue().equals(status)) {
|
||||
oAuth2Service.removeToken(updateAdminId);
|
||||
}
|
||||
// TODO 插入操作日志
|
||||
// 返回成功
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommonResult<Boolean> deleteAdmin(Integer adminId, Integer updateAdminId) {
|
||||
// 校验账号存在
|
||||
AdminDO admin = adminMapper.selectById(updateAdminId);
|
||||
if (admin == null) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
|
||||
}
|
||||
// 只有禁用的账号才可以删除
|
||||
if (CommonStatusEnum.ENABLE.getValue().equals(admin.getStatus())) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_DELETE_ONLY_DISABLE.getCode());
|
||||
}
|
||||
// 标记删除 AdminDO
|
||||
AdminDO updateAdmin = new AdminDO().setId(updateAdminId);
|
||||
updateAdmin.setDeleted(DeletedStatusEnum.DELETED_YES.getValue());
|
||||
adminMapper.update(updateAdmin);
|
||||
// 标记删除 AdminRole
|
||||
adminRoleMapper.updateToDeletedByAdminId(updateAdminId);
|
||||
// TODO 插入操作日志
|
||||
// 返回成功
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommonResult<Boolean> assignRole(Integer adminId, Integer updateAdminId, Set<Integer> roleIds) {
|
||||
// 校验账号存在
|
||||
AdminDO admin = adminMapper.selectById(updateAdminId);
|
||||
if (admin == null) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
|
||||
}
|
||||
// 校验是否有不存在的角色
|
||||
List<RoleDO> roles = roleService.getRoles(roleIds);
|
||||
if (roles.size() != roleIds.size()) {
|
||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ROLE_ASSIGN_RESOURCE_NOT_EXISTS.getCode());
|
||||
}
|
||||
// TODO 芋艿,这里先简单实现。即方式是,删除老的分配的角色关系,然后添加新的分配的角色关系
|
||||
// 标记管理员角色源关系都为删除
|
||||
adminRoleMapper.updateToDeletedByAdminId(updateAdminId);
|
||||
// 创建 RoleResourceDO 数组,并插入到数据库
|
||||
if (!roleIds.isEmpty()) {
|
||||
List<AdminRoleDO> adminRoleDOs = roleIds.stream().map(roleId -> {
|
||||
AdminRoleDO roleResource = new AdminRoleDO().setAdminId(updateAdminId).setRoleId(roleId);
|
||||
roleResource.setCreateTime(new Date());
|
||||
roleResource.setDeleted(DeletedStatusEnum.DELETED_NO.getValue());
|
||||
return roleResource;
|
||||
}).collect(Collectors.toList());
|
||||
adminRoleMapper.insertList(adminRoleDOs);
|
||||
}
|
||||
// TODO 插入操作日志
|
||||
// 返回成功
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
private String encodePassword(String password) {
|
||||
return DigestUtils.md5DigestAsHex(password.getBytes());
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user