Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
aea8cf5d60
@ -20,12 +20,14 @@ export default {
|
|||||||
type: 'changeLoginStatus',
|
type: 'changeLoginStatus',
|
||||||
payload: response,
|
payload: response,
|
||||||
});
|
});
|
||||||
|
|
||||||
yield put(routerRedux.replace('/'));
|
yield put(routerRedux.replace('/'));
|
||||||
|
|
||||||
// Login successfully
|
// Login successfully
|
||||||
if (response.code === 0) {
|
if (response.code === 0) {
|
||||||
|
|
||||||
// 保存 token 到 localStorage,发送请求的时候,会自动取 token 放到 header
|
// 保存 token 到 localStorage,发送请求的时候,会自动取 token 放到 header
|
||||||
setLoginToken(response.data.accessToken, response.data.refreshToken);
|
setLoginToken(response.data.token.accessToken, response.data.token.refreshToken);
|
||||||
// 此处直接设置为 admin、和 user 角色,因为暂时不做服务控制前段 角色
|
// 此处直接设置为 admin、和 user 角色,因为暂时不做服务控制前段 角色
|
||||||
setAuthority(['admin', 'user']);
|
setAuthority(['admin', 'user']);
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ public enum CommonStatusEnum implements IntArrayValuable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static boolean isValid(Integer status) {
|
public static boolean isValid(Integer status) {
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -19,10 +19,12 @@ public interface MallConstants {
|
|||||||
/**
|
/**
|
||||||
* 用户类型 - 用户
|
* 用户类型 - 用户
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
Integer USER_TYPE_USER = 1;
|
Integer USER_TYPE_USER = 1;
|
||||||
/**
|
/**
|
||||||
* 用户类型 - 管理员
|
* 用户类型 - 管理员
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
Integer USER_TYPE_ADMIN = 2;
|
Integer USER_TYPE_ADMIN = 2;
|
||||||
|
|
||||||
// HTTP Request Attr
|
// HTTP Request Attr
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package cn.iocoder.common.framework.constant;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局用户类型枚举
|
||||||
|
*/
|
||||||
|
public enum UserTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
USER(1, "用户"),
|
||||||
|
ADMIN(2, "管理员");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private Integer value;
|
||||||
|
/**
|
||||||
|
* 类型名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
UserTypeEnum(Integer value, String name) {
|
||||||
|
this.value = value;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserTypeEnum setValue(Integer value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserTypeEnum setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,4 +19,11 @@ public class QueryWrapperX<T> extends QueryWrapper<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryWrapperX<T> eqIfPresent(String column, Object val) {
|
||||||
|
if (val != null) {
|
||||||
|
return (QueryWrapperX<T>) super.eq(column, val);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package cn.iocoder.common.framework.util;
|
package cn.iocoder.common.framework.util;
|
||||||
|
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -30,4 +32,8 @@ public class CollectionUtil {
|
|||||||
return from.stream().collect(Collectors.toMap(keyFunc, item -> item));
|
return from.stream().collect(Collectors.toMap(keyFunc, item -> item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
|
||||||
|
return CollectionUtils.containsAny(source, candidates);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package cn.iocoder.mall.admin.application;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
|
||||||
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.admin"})
|
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.admin"})
|
||||||
@ -10,14 +9,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
|||||||
public class SystemApplication {
|
public class SystemApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
ConfigurableApplicationContext ctx = SpringApplication.run(SystemApplication.class, args);
|
SpringApplication.run(SystemApplication.class, args);
|
||||||
// Object bean = ctx.getBean("test");
|
|
||||||
// System.out.println(AopUtils.getTargetClass(bean));
|
|
||||||
|
|
||||||
// System.out.println(bean);
|
|
||||||
|
|
||||||
// ConfigurableApplicationContext ctx =
|
|
||||||
// System.out.println(); // TODO 后面去掉,这里是临时的
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import cn.iocoder.mall.admin.application.convert.ResourceConvert;
|
|||||||
import cn.iocoder.mall.admin.application.vo.admin.AdminMenuTreeNodeVO;
|
import cn.iocoder.mall.admin.application.vo.admin.AdminMenuTreeNodeVO;
|
||||||
import cn.iocoder.mall.admin.application.vo.admin.AdminRoleVO;
|
import cn.iocoder.mall.admin.application.vo.admin.AdminRoleVO;
|
||||||
import cn.iocoder.mall.admin.application.vo.admin.AdminVO;
|
import cn.iocoder.mall.admin.application.vo.admin.AdminVO;
|
||||||
|
import cn.iocoder.mall.admin.sdk.annotation.RequiresPermissions;
|
||||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
@ -86,6 +87,7 @@ public class AdminController {
|
|||||||
// =========== 管理员管理 API ===========
|
// =========== 管理员管理 API ===========
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
|
@RequiresPermissions("system.admin.page")
|
||||||
@ApiOperation(value = "管理员分页")
|
@ApiOperation(value = "管理员分页")
|
||||||
public CommonResult<PageResult<AdminVO>> page(AdminPageDTO adminPageDTO) {
|
public CommonResult<PageResult<AdminVO>> page(AdminPageDTO adminPageDTO) {
|
||||||
PageResult<AdminBO> page = adminService.getAdminPage(adminPageDTO);
|
PageResult<AdminBO> page = adminService.getAdminPage(adminPageDTO);
|
||||||
@ -128,9 +130,10 @@ public class AdminController {
|
|||||||
@ApiOperation(value = "指定管理员拥有的角色列表")
|
@ApiOperation(value = "指定管理员拥有的角色列表")
|
||||||
@ApiImplicitParam(name = "id", value = "管理员编号", required = true, example = "1")
|
@ApiImplicitParam(name = "id", value = "管理员编号", required = true, example = "1")
|
||||||
public CommonResult<List<AdminRoleVO>> roleList(@RequestParam("id") Integer id) {
|
public CommonResult<List<AdminRoleVO>> roleList(@RequestParam("id") Integer id) {
|
||||||
// 获得所有角色数组
|
// 获得所有角色列表
|
||||||
List<RoleBO> allRoleList = adminService.getRoleList(id);
|
List<RoleBO> allRoleList = roleService.getRoleList();
|
||||||
Set<Integer> adminRoleIdSet = CollectionUtil.convertSet(allRoleList, RoleBO::getId);
|
// 获得管理员的角色数组
|
||||||
|
Set<Integer> adminRoleIdSet = CollectionUtil.convertSet(adminService.getRoleList(id), RoleBO::getId);
|
||||||
// 转换出返回结果
|
// 转换出返回结果
|
||||||
List<AdminRoleVO> result = AdminConvert.INSTANCE.convert(allRoleList);
|
List<AdminRoleVO> result = AdminConvert.INSTANCE.convert(allRoleList);
|
||||||
// 设置每个角色是否赋予给改管理员
|
// 设置每个角色是否赋予给改管理员
|
||||||
|
@ -7,13 +7,12 @@ import cn.iocoder.mall.admin.api.dto.datadict.DataDictAddDTO;
|
|||||||
import cn.iocoder.mall.admin.api.dto.datadict.DataDictUpdateDTO;
|
import cn.iocoder.mall.admin.api.dto.datadict.DataDictUpdateDTO;
|
||||||
import cn.iocoder.mall.admin.application.convert.DataDictConvert;
|
import cn.iocoder.mall.admin.application.convert.DataDictConvert;
|
||||||
import cn.iocoder.mall.admin.application.vo.datadict.DataDictEnumVO;
|
import cn.iocoder.mall.admin.application.vo.datadict.DataDictEnumVO;
|
||||||
import cn.iocoder.mall.admin.application.vo.datadict.DataDictVO;
|
import cn.iocoder.mall.admin.sdk.annotation.RequiresPermissions;
|
||||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||||
import com.google.common.collect.ImmutableListMultimap;
|
import com.google.common.collect.ImmutableListMultimap;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiImplicitParams;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.apache.dubbo.config.annotation.Reference;
|
import org.apache.dubbo.config.annotation.Reference;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -21,6 +20,8 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("admins/data_dict")
|
@RequestMapping("admins/data_dict")
|
||||||
@Api("数据字典模块")
|
@Api("数据字典模块")
|
||||||
@ -31,21 +32,19 @@ public class DataDictController {
|
|||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@ApiOperation(value = "数据字典全列表")
|
@ApiOperation(value = "数据字典全列表")
|
||||||
public CommonResult<List<DataDictVO>> list() {
|
@RequiresPermissions("system.dataDict.list")
|
||||||
CommonResult<List<DataDictBO>> result = dataDictService.selectDataDictList();
|
public CommonResult<List<DataDictBO>> list() {
|
||||||
return DataDictConvert.INSTANCE.convert(result);
|
return success( dataDictService.selectDataDictList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/tree")
|
@GetMapping("/tree")
|
||||||
|
@RequiresPermissions({}) // 因为是通用的接口,所以无需权限标识
|
||||||
@ApiOperation(value = "数据字典树结构", notes = "该接口返回的信息更为精简。一般用于前端缓存数据字典到本地。")
|
@ApiOperation(value = "数据字典树结构", notes = "该接口返回的信息更为精简。一般用于前端缓存数据字典到本地。")
|
||||||
public CommonResult<List<DataDictEnumVO>> tree() {
|
public CommonResult<List<DataDictEnumVO>> tree() {
|
||||||
// 查询数据字典全列表
|
// 查询数据字典全列表
|
||||||
CommonResult<List<DataDictBO>> result = dataDictService.selectDataDictList();
|
List<DataDictBO> dataDicts = dataDictService.selectDataDictList();
|
||||||
if (result.isError()) {
|
|
||||||
return CommonResult.error(result);
|
|
||||||
}
|
|
||||||
// 构建基于 enumValue 聚合的 Multimap
|
// 构建基于 enumValue 聚合的 Multimap
|
||||||
ImmutableListMultimap<String, DataDictBO> dataDictMap = Multimaps.index(result.getData(), DataDictBO::getEnumValue); // KEY 是 enumValue ,VALUE 是 DataDictBO 数组
|
ImmutableListMultimap<String, DataDictBO> dataDictMap = Multimaps.index(dataDicts, DataDictBO::getEnumValue); // KEY 是 enumValue ,VALUE 是 DataDictBO 数组
|
||||||
// 构建返回结果
|
// 构建返回结果
|
||||||
List<DataDictEnumVO> dataDictEnumVOs = new ArrayList<>(dataDictMap.size());
|
List<DataDictEnumVO> dataDictEnumVOs = new ArrayList<>(dataDictMap.size());
|
||||||
dataDictMap.keys().forEach(enumValue -> {
|
dataDictMap.keys().forEach(enumValue -> {
|
||||||
@ -53,58 +52,29 @@ public class DataDictController {
|
|||||||
.setValues(DataDictConvert.INSTANCE.convert2(dataDictMap.get(enumValue)));
|
.setValues(DataDictConvert.INSTANCE.convert2(dataDictMap.get(enumValue)));
|
||||||
dataDictEnumVOs.add(dataDictEnumVO);
|
dataDictEnumVOs.add(dataDictEnumVO);
|
||||||
});
|
});
|
||||||
return CommonResult.success(dataDictEnumVOs);
|
return success(dataDictEnumVOs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
|
@RequiresPermissions("system.dataDict.add")
|
||||||
@ApiOperation(value = "创建数据字典")
|
@ApiOperation(value = "创建数据字典")
|
||||||
@ApiImplicitParams({
|
public CommonResult<DataDictBO> add(DataDictAddDTO dataDictAddDTO) {
|
||||||
@ApiImplicitParam(name = "enumValue", value = "大类枚举值", required = true, example = "gender"),
|
return success(dataDictService.addDataDict(AdminSecurityContextHolder.getContext().getAdminId(), dataDictAddDTO));
|
||||||
@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")
|
@PostMapping("/update")
|
||||||
|
@RequiresPermissions("system.dataDict.update")
|
||||||
@ApiOperation(value = "更新数据字典")
|
@ApiOperation(value = "更新数据字典")
|
||||||
@ApiImplicitParams({
|
public CommonResult<Boolean> update(DataDictUpdateDTO dataDictUpdateDTO) {
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "100"),
|
return success(dataDictService.updateDataDict(AdminSecurityContextHolder.getContext().getAdminId(), dataDictUpdateDTO));
|
||||||
@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")
|
@PostMapping("/delete")
|
||||||
|
@RequiresPermissions("system.dataDict.delete")
|
||||||
@ApiOperation(value = "删除数据字典")
|
@ApiOperation(value = "删除数据字典")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "100")
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "100")
|
||||||
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
|
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
|
||||||
return dataDictService.deleteDataDict(AdminSecurityContextHolder.getContext().getAdminId(), id);
|
return success(dataDictService.deleteDataDict(AdminSecurityContextHolder.getContext().getAdminId(), id));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
package cn.iocoder.mall.admin.application.controller.admins;
|
package cn.iocoder.mall.admin.application.controller.admins;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
|
import cn.iocoder.mall.admin.api.AdminService;
|
||||||
import cn.iocoder.mall.admin.api.OAuth2Service;
|
import cn.iocoder.mall.admin.api.OAuth2Service;
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
import cn.iocoder.mall.admin.api.bo.admin.AdminAuthenticationBO;
|
||||||
import cn.iocoder.mall.admin.application.convert.PassportConvert;
|
import cn.iocoder.mall.admin.api.dto.admin.AdminAuthenticationDTO;
|
||||||
import cn.iocoder.mall.admin.application.vo.PassportLoginVO;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
|
||||||
import io.swagger.annotations.ApiImplicitParams;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.apache.dubbo.config.annotation.Reference;
|
import org.apache.dubbo.config.annotation.Reference;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("admins/passport")
|
@RequestMapping("admins/passport")
|
||||||
@Api("Admin Passport 模块")
|
@Api("Admin Passport 模块")
|
||||||
@ -23,16 +22,13 @@ public class PassportController {
|
|||||||
@Reference(validation = "true", version = "${dubbo.provider.OAuth2Service.version}")
|
@Reference(validation = "true", version = "${dubbo.provider.OAuth2Service.version}")
|
||||||
private OAuth2Service oauth2Service;
|
private OAuth2Service oauth2Service;
|
||||||
|
|
||||||
|
@Reference(validation = "true", version = "${dubbo.provider.AdminService.version}")
|
||||||
|
private AdminService adminService;
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@ApiOperation(value = "手机号 + 密码登陆")
|
@ApiOperation(value = "手机号 + 密码登陆")
|
||||||
@ApiImplicitParams({
|
public CommonResult<AdminAuthenticationBO> login(AdminAuthenticationDTO adminAuthenticationDTO) {
|
||||||
@ApiImplicitParam(name = "username", value = "账号", required = true, example = "15601691300"),
|
return success(adminService.authentication(adminAuthenticationDTO));
|
||||||
@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 功能 logout
|
||||||
|
@ -17,7 +17,6 @@ import cn.iocoder.mall.admin.application.vo.role.RoleResourceTreeNodeVO;
|
|||||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiImplicitParams;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.apache.dubbo.config.annotation.Reference;
|
import org.apache.dubbo.config.annotation.Reference;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -101,10 +100,6 @@ public class RoleController {
|
|||||||
|
|
||||||
@PostMapping("/assign_resource")
|
@PostMapping("/assign_resource")
|
||||||
@ApiOperation(value = "分配角色资源")
|
@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(RoleAssignResourceDTO roleAssignResourceDTO) {
|
public CommonResult<Boolean> assignResource(RoleAssignResourceDTO roleAssignResourceDTO) {
|
||||||
return success(roleService.assignRoleResource(AdminSecurityContextHolder.getContext().getAdminId(), roleAssignResourceDTO));
|
return success(roleService.assignRoleResource(AdminSecurityContextHolder.getContext().getAdminId(), roleAssignResourceDTO));
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package cn.iocoder.mall.admin.application.convert;
|
package cn.iocoder.mall.admin.application.convert;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
|
||||||
import cn.iocoder.mall.admin.api.bo.datadict.DataDictBO;
|
import cn.iocoder.mall.admin.api.bo.datadict.DataDictBO;
|
||||||
import cn.iocoder.mall.admin.application.vo.datadict.DataDictVO;
|
import cn.iocoder.mall.admin.application.vo.datadict.DataDictEnumVO;
|
||||||
import cn.iocoder.mall.admin.application.vo.datadict.DataDictValueVO;
|
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mappings;
|
import org.mapstruct.Mappings;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
@ -16,18 +14,6 @@ public interface DataDictConvert {
|
|||||||
DataDictConvert INSTANCE = Mappers.getMapper(DataDictConvert.class);
|
DataDictConvert INSTANCE = Mappers.getMapper(DataDictConvert.class);
|
||||||
|
|
||||||
@Mappings({})
|
@Mappings({})
|
||||||
DataDictVO convert(DataDictBO dataDictBO);
|
List<DataDictEnumVO.Value> convert2(List<DataDictBO> dataDictBOs);
|
||||||
|
|
||||||
@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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,21 @@ public class DataDictEnumVO {
|
|||||||
|
|
||||||
@ApiModelProperty(value = "大类枚举值", required = true, example = "gender")
|
@ApiModelProperty(value = "大类枚举值", required = true, example = "gender")
|
||||||
private String enumValue;
|
private String enumValue;
|
||||||
|
|
||||||
@ApiModelProperty(value = "小类数值数组", required = true)
|
@ApiModelProperty(value = "小类数值数组", required = true)
|
||||||
private List<DataDictValueVO> values;
|
private List<Value> values;
|
||||||
|
|
||||||
|
@ApiModel("数据字典枚举值 VO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class Value {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "小类数值", required = true, example = "1")
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "展示名", required = true, example = "男")
|
||||||
|
private String displayName;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
package cn.iocoder.mall.admin.application.vo.datadict;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package cn.iocoder.mall.admin.application.vo.datadict;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
@ -26,6 +26,7 @@ public class RoleResourceTreeNodeVO {
|
|||||||
private String displayName;
|
private String displayName;
|
||||||
@ApiModelProperty(value = "子节点数组")
|
@ApiModelProperty(value = "子节点数组")
|
||||||
private List<RoleResourceTreeNodeVO> children;
|
private List<RoleResourceTreeNodeVO> children;
|
||||||
|
|
||||||
@ApiModelProperty(value = "是否授权", required = true, example = "true")
|
@ApiModelProperty(value = "是否授权", required = true, example = "true")
|
||||||
private Boolean assigned;
|
private Boolean assigned;
|
||||||
|
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package cn.iocoder.mall.admin.sdk.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参考 Shiro @RequiresPermissions 设计 http://shiro.apache.org/static/1.3.2/apidocs/org/apache/shiro/authz/annotation/RequiresPermissions.html
|
||||||
|
*
|
||||||
|
* 通过将该注解添加到 Controller 的方法上,进行授权鉴定
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Target({ElementType.METHOD}) // 暂时不支持 ElementType.TYPE ,因为没有场景
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface RequiresPermissions {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当有多个标识时,必须全部拥有权限,才可以操作
|
||||||
|
*
|
||||||
|
* @return 权限标识数组
|
||||||
|
*/
|
||||||
|
String[] value();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package cn.iocoder.mall.admin.sdk.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逻辑类型枚举
|
||||||
|
*/
|
||||||
|
public enum LogicalEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 并且
|
||||||
|
*/
|
||||||
|
AND,
|
||||||
|
/**
|
||||||
|
* 或者
|
||||||
|
*/
|
||||||
|
OR,
|
||||||
|
|
||||||
|
}
|
@ -1,26 +1,18 @@
|
|||||||
package cn.iocoder.mall.admin.sdk.context;
|
package cn.iocoder.mall.admin.sdk.context;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Security 上下文
|
* Security 上下文
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
public class AdminSecurityContext {
|
public class AdminSecurityContext {
|
||||||
|
|
||||||
private final Integer adminId;
|
private Integer adminId;
|
||||||
private final Set<Integer> roleIds;
|
private 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ public class AdminSecurityContextHolder {
|
|||||||
AdminSecurityContext ctx = SECURITY_CONTEXT.get();
|
AdminSecurityContext ctx = SECURITY_CONTEXT.get();
|
||||||
// 为空时,设置一个空的进去
|
// 为空时,设置一个空的进去
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
ctx = new AdminSecurityContext(null, null);
|
ctx = new AdminSecurityContext();
|
||||||
SECURITY_CONTEXT.set(ctx);
|
SECURITY_CONTEXT.set(ctx);
|
||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
|
@ -1,37 +1,48 @@
|
|||||||
package cn.iocoder.mall.admin.sdk.interceptor;
|
package cn.iocoder.mall.admin.sdk.interceptor;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.constant.MallConstants;
|
import cn.iocoder.common.framework.constant.UserTypeEnum;
|
||||||
import cn.iocoder.common.framework.exception.ServiceException;
|
import cn.iocoder.common.framework.exception.ServiceException;
|
||||||
import cn.iocoder.common.framework.util.HttpUtil;
|
import cn.iocoder.common.framework.util.HttpUtil;
|
||||||
import cn.iocoder.common.framework.util.MallUtil;
|
import cn.iocoder.common.framework.util.MallUtil;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.util.StringUtil;
|
||||||
|
import cn.iocoder.mall.admin.api.AdminService;
|
||||||
import cn.iocoder.mall.admin.api.OAuth2Service;
|
import cn.iocoder.mall.admin.api.OAuth2Service;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.admin.AdminAuthorizationBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
||||||
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.dto.oauth2.OAuth2GetTokenDTO;
|
||||||
|
import cn.iocoder.mall.admin.sdk.annotation.RequiresPermissions;
|
||||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContext;
|
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContext;
|
||||||
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
|
||||||
import org.apache.dubbo.config.annotation.Reference;
|
import org.apache.dubbo.config.annotation.Reference;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安全拦截器
|
* Admin 安全拦截器
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class AdminSecurityInterceptor extends HandlerInterceptorAdapter {
|
public class AdminSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||||
|
|
||||||
@Reference(validation = "true", version = "${dubbo.consumer.OAuth2Service.version:1.0.0}")
|
@Reference(validation = "true", version = "${dubbo.consumer.OAuth2Service.version:1.0.0}")
|
||||||
private OAuth2Service oauth2Service;
|
private OAuth2Service oauth2Service;
|
||||||
|
@Reference(validation = "true", version = "${dubbo.consumer.AdminService.version:1.0.0}")
|
||||||
|
private AdminService adminService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 忽略的 URL 集合,即无需经过认证
|
* 忽略的 URL 集合,即无需经过认证
|
||||||
|
*
|
||||||
|
* 对于 Admin 的系统,默认所有接口都需要进行认证
|
||||||
*/
|
*/
|
||||||
@Value("${admins.security.ignore_url:#{null}}")
|
@Value("${admins.security.ignore_urls:#{null}}")
|
||||||
private Set<String> ignoreUrls;
|
private Set<String> ignoreUrls;
|
||||||
|
|
||||||
public AdminSecurityInterceptor setIgnoreUrls(Set<String> ignoreUrls) {
|
public AdminSecurityInterceptor setIgnoreUrls(Set<String> ignoreUrls) {
|
||||||
@ -42,39 +53,46 @@ public class AdminSecurityInterceptor extends HandlerInterceptorAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
// 设置当前访问的用户类型。注意,即使未登陆,我们也认为是管理员
|
// 设置当前访问的用户类型。注意,即使未登陆,我们也认为是管理员
|
||||||
MallUtil.setUserType(request, MallConstants.USER_TYPE_ADMIN);
|
MallUtil.setUserType(request, UserTypeEnum.ADMIN.getValue());
|
||||||
// 校验访问令牌是否正确。若正确,返回授权信息
|
|
||||||
|
// 根据 accessToken 获得认证信息,判断是谁
|
||||||
String accessToken = HttpUtil.obtainAuthorization(request);
|
String accessToken = HttpUtil.obtainAuthorization(request);
|
||||||
OAuth2AuthenticationBO authentication = null;
|
OAuth2AuthenticationBO authentication = null;
|
||||||
if (accessToken != null) {
|
ServiceException serviceException = null;
|
||||||
CommonResult<OAuth2AuthenticationBO> result = oauth2Service.checkToken(accessToken);
|
if (StringUtil.hasText(accessToken)) {
|
||||||
// TODO sin 先临时跳过 认证
|
try {
|
||||||
// CommonResult<OAuth2AuthenticationBO> result = CommonResult.success(new OAuth2AuthenticationBO()
|
authentication = oauth2Service.getAuthentication(new OAuth2GetTokenDTO().setAccessToken(accessToken)
|
||||||
// .setAdminId(1)
|
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||||
// .setRoleIds(Sets.newHashSet(1, 2, 3, 4)));
|
} catch (ServiceException e) {
|
||||||
if (result.isError()) { // TODO 芋艿,如果访问的地址无需登录,这里也不用抛异常
|
serviceException = e;
|
||||||
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) {
|
|
||||||
MallUtil.setUserId(request, authentication.getAdminId());
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
// 进行鉴权
|
||||||
String url = request.getRequestURI();
|
String url = request.getRequestURI();
|
||||||
if (ignoreUrls != null && !ignoreUrls.contains(url)) { // TODO 临时写死。非登陆接口,必须已经认证身份,不允许匿名访问
|
boolean needAuthentication = ignoreUrls == null || !ignoreUrls.contains(url);
|
||||||
throw new ServiceException(AdminErrorCodeEnum.OAUTH_NOT_LOGIN.getCode(), AdminErrorCodeEnum.OAUTH_NOT_LOGIN.getMessage());
|
AdminAuthorizationBO authorization = null;
|
||||||
|
if (needAuthentication) {
|
||||||
|
if (serviceException != null) { // 认证失败,抛出上面认证失败的 ServiceException 异常
|
||||||
|
throw serviceException;
|
||||||
|
}
|
||||||
|
if (authentication == null) { // 无认证信息,抛出未登陆 ServiceException 异常
|
||||||
|
throw new ServiceException(AdminErrorCodeEnum.OAUTH2_NOT_LOGIN.getCode(), AdminErrorCodeEnum.OAUTH2_NOT_LOGIN.getMessage());
|
||||||
|
}
|
||||||
|
authorization = checkPermission(handler, authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 鉴权完成,初始化 AdminSecurityContext 上下文
|
||||||
|
AdminSecurityContext context = new AdminSecurityContext();
|
||||||
|
AdminSecurityContextHolder.setContext(context);
|
||||||
|
if (authentication != null) {
|
||||||
|
context.setAdminId(authentication.getUserId());
|
||||||
|
MallUtil.setUserId(request, authentication.getUserId()); // 记录到 request 中,避免 AdminSecurityContext 后续清理掉后,其它地方需要用到 userId
|
||||||
|
if (authorization != null) {
|
||||||
|
context.setRoleIds(authorization.getRoleIds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 校验是否需要已授权
|
|
||||||
// TODO sin 暂时不校验
|
|
||||||
// checkPermission(request, authentication);
|
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return super.preHandle(request, response, handler);
|
return super.preHandle(request, response, handler);
|
||||||
}
|
}
|
||||||
@ -85,14 +103,18 @@ public class AdminSecurityInterceptor extends HandlerInterceptorAdapter {
|
|||||||
AdminSecurityContextHolder.clear();
|
AdminSecurityContextHolder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPermission(HttpServletRequest request, OAuth2AuthenticationBO authentication) {
|
private AdminAuthorizationBO checkPermission(Object handler, OAuth2AuthenticationBO authentication) {
|
||||||
Integer adminId = authentication != null ? authentication.getAdminId() : null;
|
// 获得 @RequiresPermissions 注解
|
||||||
Set<Integer> roleIds = authentication != null ? authentication.getRoleIds() : null;
|
Assert.isTrue(handler instanceof HandlerMethod, "handler 必须是 HandlerMethod 类型");
|
||||||
String url = request.getRequestURI();
|
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||||
CommonResult<Boolean> result = oauth2Service.checkPermission(adminId, roleIds, url);
|
RequiresPermissions requiresPermissions = handlerMethod.getMethodAnnotation(RequiresPermissions.class);
|
||||||
if (result.isError()) {
|
// 执行校验
|
||||||
throw new ServiceException(result.getCode(), result.getMessage());
|
return adminService.checkPermissions(authentication.getUserId(),
|
||||||
|
requiresPermissions != null ? Arrays.asList(requiresPermissions.value()) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkPermission() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package cn.iocoder.mall.admin.api;
|
package cn.iocoder.mall.admin.api;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.vo.PageResult;
|
import cn.iocoder.common.framework.vo.PageResult;
|
||||||
import cn.iocoder.mall.admin.api.bo.role.RoleBO;
|
import cn.iocoder.mall.admin.api.bo.admin.AdminAuthenticationBO;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.admin.AdminAuthorizationBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.admin.AdminBO;
|
import cn.iocoder.mall.admin.api.bo.admin.AdminBO;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.role.RoleBO;
|
||||||
import cn.iocoder.mall.admin.api.dto.admin.*;
|
import cn.iocoder.mall.admin.api.dto.admin.*;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -14,6 +16,16 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public interface AdminService {
|
public interface AdminService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户认证。认证成功后,返回认证信息
|
||||||
|
*
|
||||||
|
* 实际上,就是用户名 + 密码登陆
|
||||||
|
*
|
||||||
|
* @param adminAuthenticationDTO 用户认证信息
|
||||||
|
* @return 认证信息
|
||||||
|
*/
|
||||||
|
AdminAuthenticationBO authentication(AdminAuthenticationDTO adminAuthenticationDTO);
|
||||||
|
|
||||||
PageResult<AdminBO> getAdminPage(AdminPageDTO adminPageDTO);
|
PageResult<AdminBO> getAdminPage(AdminPageDTO adminPageDTO);
|
||||||
|
|
||||||
AdminBO addAdmin(Integer adminId, AdminAddDTO adminAddDTO);
|
AdminBO addAdmin(Integer adminId, AdminAddDTO adminAddDTO);
|
||||||
@ -49,4 +61,13 @@ public interface AdminService {
|
|||||||
*/
|
*/
|
||||||
Boolean assignAdminRole(Integer adminId, AdminAssignRoleDTO adminAssignRoleDTO);
|
Boolean assignAdminRole(Integer adminId, AdminAssignRoleDTO adminAssignRoleDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断管理员是否有指定权限
|
||||||
|
*
|
||||||
|
* @param adminId 管理员
|
||||||
|
* @param permissions 权限数组
|
||||||
|
* @return 管理员授权信息
|
||||||
|
*/
|
||||||
|
AdminAuthorizationBO checkPermissions(Integer adminId, List<String> permissions);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface DataDictService {
|
public interface DataDictService {
|
||||||
|
|
||||||
CommonResult<List<DataDictBO>> selectDataDictList();
|
List<DataDictBO> selectDataDictList();
|
||||||
|
|
||||||
CommonResult<DataDictBO> addDataDict(Integer adminId, DataDictAddDTO dataDictAddDTO);
|
DataDictBO addDataDict(Integer adminId, DataDictAddDTO dataDictAddDTO);
|
||||||
|
|
||||||
CommonResult<Boolean> updateDataDict(Integer adminId, DataDictUpdateDTO dataDictUpdateDTO);
|
Boolean updateDataDict(Integer adminId, DataDictUpdateDTO dataDictUpdateDTO);
|
||||||
|
|
||||||
CommonResult<Boolean> deleteDataDict(Integer adminId, Integer dataDictId);
|
Boolean deleteDataDict(Integer adminId, Integer dataDictId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取字典值 - 单个
|
* 获取字典值 - 单个
|
||||||
@ -28,6 +28,7 @@ public interface DataDictService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
CommonResult<DataDictBO> getDataDict(String dictKey, Object dictValue);
|
CommonResult<DataDictBO> getDataDict(String dictKey, Object dictValue);
|
||||||
|
|
||||||
CommonResult<List<DataDictBO>> getDataDict(String dictKey);
|
CommonResult<List<DataDictBO>> getDataDict(String dictKey);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,33 +1,31 @@
|
|||||||
package cn.iocoder.mall.admin.api;
|
package cn.iocoder.mall.admin.api;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
||||||
|
import cn.iocoder.mall.admin.api.dto.oauth2.OAuth2CreateTokenDTO;
|
||||||
|
import cn.iocoder.mall.admin.api.dto.oauth2.OAuth2GetTokenDTO;
|
||||||
|
|
||||||
import java.util.Set;
|
/**
|
||||||
|
* Oauth2 服务接口
|
||||||
|
*/
|
||||||
public interface OAuth2Service {
|
public interface OAuth2Service {
|
||||||
|
|
||||||
CommonResult<OAuth2AccessTokenBO> getAccessToken(String username, String password);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验访问令牌,获取身份信息( 不包括 accessToken 等等 )
|
* 根据身份信息,创建 accessToken 信息
|
||||||
*
|
*
|
||||||
* @param accessToken 访问令牌
|
* @param oauth2CreateTokenDTO 身份信息 DTO
|
||||||
* @return 授权信息
|
* @return accessToken 信息
|
||||||
*/
|
*/
|
||||||
CommonResult<OAuth2AuthenticationBO> checkToken(String accessToken);
|
OAuth2AccessTokenBO createToken(OAuth2CreateTokenDTO oauth2CreateTokenDTO);
|
||||||
|
|
||||||
/**
|
|
||||||
* 校验权限(鉴权)
|
|
||||||
*
|
|
||||||
* @param adminId 管理员编号
|
|
||||||
* @param roleIds 管理员拥有的角色编号的集合
|
|
||||||
* @param url 指定 URL
|
|
||||||
* @return 是否有权限
|
|
||||||
*/
|
|
||||||
CommonResult<Boolean> checkPermission(Integer adminId, Set<Integer> roleIds, String url);
|
|
||||||
|
|
||||||
// TODO @see 刷新 token
|
// TODO @see 刷新 token
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 accessToken 获得身份信息
|
||||||
|
*
|
||||||
|
* @param oauth2GetTokenDTO accessToken 信息
|
||||||
|
* @return 身份信息
|
||||||
|
*/
|
||||||
|
OAuth2AuthenticationBO getAuthentication(OAuth2GetTokenDTO oauth2GetTokenDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.bo.admin;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@ApiModel("管理员认证 BO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class AdminAuthenticationBO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "管理员编号", required = true, example = "1")
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "昵称", required = true, example = "小王")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
private OAuth2AccessTokenBO token;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.bo.admin;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ApiModel("管理员授权 BO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class AdminAuthorizationBO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "管理员编号", required = true, example = "1")
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "角色编号数组", required = true, example = "1")
|
||||||
|
private Set<Integer> roleIds;
|
||||||
|
|
||||||
|
}
|
@ -1,28 +1,24 @@
|
|||||||
package cn.iocoder.mall.admin.api.bo.oauth2;
|
package cn.iocoder.mall.admin.api.bo.oauth2;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
@ApiModel("OAuth2 Token 信息 BO")
|
||||||
* OAUTH2 AccessToken BO
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class OAuth2AccessTokenBO implements Serializable {
|
public class OAuth2AccessTokenBO implements Serializable {
|
||||||
|
|
||||||
/**
|
@ApiModelProperty(value = "accessToken", required = true, example = "001e8f49b20e47f7b3a2de774497cd50")
|
||||||
* 访问令牌
|
|
||||||
*/
|
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
/**
|
|
||||||
* 刷新令牌
|
@ApiModelProperty(value = "refreshToken", required = true, example = "001e8f49b20e47f7b3a2de774497cd50")
|
||||||
*/
|
|
||||||
private String refreshToken;
|
private String refreshToken;
|
||||||
/**
|
|
||||||
* 过期时间,单位:秒。
|
@ApiModelProperty(value = "过期时间,单位:秒", required = true, example = "1024")
|
||||||
*/
|
|
||||||
private Integer expiresIn;
|
private Integer expiresIn;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,19 @@
|
|||||||
package cn.iocoder.mall.admin.api.bo.oauth2;
|
package cn.iocoder.mall.admin.api.bo.oauth2;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.io.Serializable;
|
@ApiModel("OAUTH2 认证 BO")
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OAUTH2 认证 BO
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class OAuth2AuthenticationBO implements Serializable {
|
public class OAuth2AuthenticationBO {
|
||||||
|
|
||||||
/**
|
@ApiModelProperty(value = "用户编号", required = true, example = "1")
|
||||||
* 管理员编号
|
private Integer userId;
|
||||||
*/
|
|
||||||
private Integer adminId;
|
@ApiModelProperty(value = "用户类型", required = true, example = "1", notes = "参考 UserTypeEnum 枚举")
|
||||||
/**
|
private Integer userType;
|
||||||
* 角色编号数组
|
|
||||||
*/
|
|
||||||
private Set<Integer> roleIds;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.bo.oauth2;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAUTH2 认证 BO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class OAuth2AuthenticationOldBO implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员编号
|
||||||
|
*/
|
||||||
|
private Integer adminId;
|
||||||
|
/**
|
||||||
|
* 角色编号数组
|
||||||
|
*/
|
||||||
|
private Set<Integer> roleIds;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -12,11 +12,11 @@ public enum AdminErrorCodeEnum {
|
|||||||
// OAUTH2_INVALID_GRANT_BAD_CREDENTIALS(1001001001, "密码不正确"), // 暂时没用到
|
// OAUTH2_INVALID_GRANT_BAD_CREDENTIALS(1001001001, "密码不正确"), // 暂时没用到
|
||||||
// OAUTH2_INVALID_GRANT_USERNAME_NOT_FOUND(1001001002, "账号不存在"), // 暂时没用到
|
// OAUTH2_INVALID_GRANT_USERNAME_NOT_FOUND(1001001002, "账号不存在"), // 暂时没用到
|
||||||
// OAUTH2_INVALID_GRANT(1001001010, ""), // 预留
|
// OAUTH2_INVALID_GRANT(1001001010, ""), // 预留
|
||||||
OAUTH_INVALID_TOKEN_NOT_FOUND(1002001011, "访问令牌不存在"),
|
OAUTH2_INVALID_TOKEN_NOT_FOUND(1002001011, "访问令牌不存在"),
|
||||||
OAUTH_INVALID_TOKEN_EXPIRED(1002001012, "访问令牌已过期"),
|
OAUTH2_INVALID_TOKEN_EXPIRED(1002001012, "访问令牌已过期"),
|
||||||
OAUTH_INVALID_TOKEN_INVALID(1002001013, "访问令牌已失效"),
|
OAUTH2_INVALID_TOKEN_INVALID(1002001013, "访问令牌已失效"),
|
||||||
OAUTH_INVALID_PERMISSION(1002001014, "没有该操作权限"), // TODO 芋艿,临时放在 OAUTH2 模块,理论来说,OAUTH2 只做认证,不做鉴权。
|
OAUTH2_NOT_LOGIN(1002001015, "账号未登陆"),
|
||||||
OAUTH_NOT_LOGIN(1002001015, "账号未登陆"),
|
OAUTH2_INVALID_TOKEN_ERROR_USER_TYPE(1002001016, "访问令牌用户类型不正确"),
|
||||||
|
|
||||||
OAUTH_INVALID_TOKEN(1002001020, ""), // 预留
|
OAUTH_INVALID_TOKEN(1002001020, ""), // 预留
|
||||||
|
|
||||||
@ -29,6 +29,7 @@ public enum AdminErrorCodeEnum {
|
|||||||
ADMIN_DELETE_ONLY_DISABLE(1002002004, "只有关闭的账号才可以删除"),
|
ADMIN_DELETE_ONLY_DISABLE(1002002004, "只有关闭的账号才可以删除"),
|
||||||
ADMIN_ADMIN_STATUS_CAN_NOT_UPDATE(1002002005, "管理员的账号状态不允许变更"),
|
ADMIN_ADMIN_STATUS_CAN_NOT_UPDATE(1002002005, "管理员的账号状态不允许变更"),
|
||||||
ADMIN_ASSIGN_ROLE_NOT_EXISTS(1002002006, "分配员工角色时,有角色不存在"),
|
ADMIN_ASSIGN_ROLE_NOT_EXISTS(1002002006, "分配员工角色时,有角色不存在"),
|
||||||
|
ADMIN_INVALID_PERMISSION(1002002007, "没有该操作权限"),
|
||||||
|
|
||||||
// ========== 资源模块 1002003000 ==========
|
// ========== 资源模块 1002003000 ==========
|
||||||
RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
|
RESOURCE_NAME_DUPLICATE(1002003000, "已经存在该名字的资源"),
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.constant;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源类型枚举
|
||||||
|
*/
|
||||||
|
public enum ResourceTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
MENU(1, "菜单"),
|
||||||
|
BUTTON(2, "按钮");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ResourceTypeEnum::getValue).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源类型
|
||||||
|
*/
|
||||||
|
private Integer value;
|
||||||
|
/**
|
||||||
|
* 资源类型名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
ResourceTypeEnum(Integer value, String name) {
|
||||||
|
this.value = value;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceTypeEnum setValue(Integer value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceTypeEnum setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,7 +17,7 @@ public class AdminAddDTO implements Serializable {
|
|||||||
|
|
||||||
@ApiModelProperty(value = "登陆账号", required = true, example = "15601691300")
|
@ApiModelProperty(value = "登陆账号", required = true, example = "15601691300")
|
||||||
@NotEmpty(message = "登陆账号不能为空")
|
@NotEmpty(message = "登陆账号不能为空")
|
||||||
@Length(min = 6, max = 16, message = "账号长度为 6-16 位")
|
@Length(min = 5, max = 16, message = "账号长度为 5-16 位")
|
||||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.dto.admin;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
@ApiModel("管理员认证 DTO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class AdminAuthenticationDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "登陆账号", required = true, example = "15601691300")
|
||||||
|
@NotEmpty(message = "登陆账号不能为空")
|
||||||
|
@Length(min = 5, max = 16, message = "账号长度为 5-16 位")
|
||||||
|
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "密码", required = true, example = "buzhidao")
|
||||||
|
@NotEmpty(message = "密码不能为空")
|
||||||
|
@Length(min = 6, max = 16, message = "密码长度为 6-16 位")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
}
|
@ -22,7 +22,7 @@ public class AdminUpdateDTO implements Serializable {
|
|||||||
|
|
||||||
@ApiModelProperty(value = "登陆账号", required = true, example = "15601691300")
|
@ApiModelProperty(value = "登陆账号", required = true, example = "15601691300")
|
||||||
@NotEmpty(message = "登陆账号不能为空")
|
@NotEmpty(message = "登陆账号不能为空")
|
||||||
@Length(min = 6, max = 16, message = "账号长度为 6-16 位")
|
@Length(min = 5, max = 16, message = "账号长度为 5-16 位")
|
||||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package cn.iocoder.mall.admin.api.dto.datadict;
|
package cn.iocoder.mall.admin.api.dto.datadict;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@ -7,36 +9,28 @@ import javax.validation.constraints.NotEmpty;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
@ApiModel("数据字典添加 DTO")
|
||||||
* 数据字典添加 DTO
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class DataDictAddDTO implements Serializable {
|
public class DataDictAddDTO implements Serializable {
|
||||||
|
|
||||||
/**
|
@ApiModelProperty(value = "大类枚举值", required = true, example = "gender")
|
||||||
* 大类枚举值
|
|
||||||
*/
|
|
||||||
@NotEmpty(message = "大类枚举值不能为空")
|
@NotEmpty(message = "大类枚举值不能为空")
|
||||||
private String enumValue;
|
private String enumValue;
|
||||||
/**
|
|
||||||
* 小类数值
|
@ApiModelProperty(value = "小类数值", required = true, example = "1")
|
||||||
*/
|
|
||||||
@NotEmpty(message = "小类数值不能为空")
|
@NotEmpty(message = "小类数值不能为空")
|
||||||
private String value;
|
private String value;
|
||||||
/**
|
|
||||||
* 展示名
|
@ApiModelProperty(value = "展示名", required = true, example = "男")
|
||||||
*/
|
|
||||||
@NotEmpty(message = "展示名不能为空")
|
@NotEmpty(message = "展示名不能为空")
|
||||||
private String displayName;
|
private String displayName;
|
||||||
/**
|
|
||||||
* 排序值
|
@ApiModelProperty(required = true, value = "排序值", example = "123")
|
||||||
*/
|
|
||||||
@NotNull(message = "排序值不能为空")
|
@NotNull(message = "排序值不能为空")
|
||||||
private Integer sort;
|
private Integer sort;
|
||||||
/**
|
|
||||||
* 备注
|
@ApiModelProperty(value = "备注", example = "你猜我猜不猜")
|
||||||
*/
|
|
||||||
private String memo;
|
private String memo;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.mall.admin.api.dto.datadict;
|
package cn.iocoder.mall.admin.api.dto.datadict;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@ -14,29 +15,27 @@ import java.io.Serializable;
|
|||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class DataDictUpdateDTO implements Serializable {
|
public class DataDictUpdateDTO implements Serializable {
|
||||||
|
|
||||||
/**
|
@ApiModelProperty(value = "数据字典编号", required = true, example = "1")
|
||||||
* 编号
|
@NotNull(message = "数据字典编号不能为空")
|
||||||
*/
|
|
||||||
@NotNull(message = "编号不能为空")
|
|
||||||
private Integer id;
|
private Integer id;
|
||||||
/**
|
|
||||||
* 小类数值
|
@ApiModelProperty(value = "大类枚举值", required = true, example = "gender")
|
||||||
*/
|
@NotEmpty(message = "大类枚举值不能为空")
|
||||||
|
private String enumValue;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "小类数值", required = true, example = "1")
|
||||||
@NotEmpty(message = "小类数值不能为空")
|
@NotEmpty(message = "小类数值不能为空")
|
||||||
private String value;
|
private String value;
|
||||||
/**
|
|
||||||
* 展示名
|
@ApiModelProperty(value = "展示名", required = true, example = "男")
|
||||||
*/
|
|
||||||
@NotEmpty(message = "展示名不能为空")
|
@NotEmpty(message = "展示名不能为空")
|
||||||
private String displayName;
|
private String displayName;
|
||||||
/**
|
|
||||||
* 排序值
|
@ApiModelProperty(required = true, value = "排序值", example = "123")
|
||||||
*/
|
|
||||||
@NotNull(message = "排序值不能为空")
|
@NotNull(message = "排序值不能为空")
|
||||||
private Integer sort;
|
private Integer sort;
|
||||||
/**
|
|
||||||
* 备注
|
@ApiModelProperty(value = "备注", example = "你猜我猜不猜")
|
||||||
*/
|
|
||||||
private String memo;
|
private String memo;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.dto.oauth2;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.ResourceTypeEnum;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@ApiModel("OAuth2 创建 Token DTO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class OAuth2CreateTokenDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "用户编号", required = true, example = "1")
|
||||||
|
@NotNull(message = "用户编号不能为空")
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "用户类型", required = true, example = "1", notes = "参见 ResourceTypeEnum 枚举")
|
||||||
|
@NotNull(message = "用户类型不能为空")
|
||||||
|
@InEnum(value = ResourceTypeEnum.class, message = "用户类型必须是 {value}")
|
||||||
|
private Integer userType;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package cn.iocoder.mall.admin.api.dto.oauth2;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.ResourceTypeEnum;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@ApiModel("OAuth2 身份验证 DTO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class OAuth2GetTokenDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "accessToken", required = true, example = "001e8f49b20e47f7b3a2de774497cd50")
|
||||||
|
@NotEmpty(message = "accessToken 不能为空")
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "用户类型", required = true, example = "1", notes = "参见 ResourceTypeEnum 枚举")
|
||||||
|
@NotNull(message = "用户类型不能为空")
|
||||||
|
@InEnum(value = ResourceTypeEnum.class, message = "用户类型必须是 {value}")
|
||||||
|
private Integer userType;
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package cn.iocoder.mall.admin.api.dto.resource;
|
package cn.iocoder.mall.admin.api.dto.resource;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.ResourceTypeEnum;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -17,6 +19,7 @@ public class ResourceAddDTO implements Serializable {
|
|||||||
|
|
||||||
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
|
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
|
||||||
@NotNull(message = "类型不能为空")
|
@NotNull(message = "类型不能为空")
|
||||||
|
@InEnum(value = ResourceTypeEnum.class, message = "资源类型必须是 {value}")
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
@ApiModelProperty(value = "排序", required = true, example = "1")
|
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package cn.iocoder.mall.admin.api.dto.resource;
|
package cn.iocoder.mall.admin.api.dto.resource;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
|
import cn.iocoder.mall.admin.api.constant.ResourceTypeEnum;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -21,6 +23,7 @@ public class ResourceUpdateDTO implements Serializable {
|
|||||||
|
|
||||||
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
|
@ApiModelProperty(value = "资源类型。1 代表【菜单】;2 代表【按钮】", required = true, example = "1")
|
||||||
@NotNull(message = "类型不能为空")
|
@NotNull(message = "类型不能为空")
|
||||||
|
@InEnum(value = ResourceTypeEnum.class, message = "资源类型必须是 {value}")
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
@ApiModelProperty(value = "排序", required = true, example = "1")
|
@ApiModelProperty(value = "排序", required = true, example = "1")
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.iocoder.mall.admin.convert;
|
package cn.iocoder.mall.admin.convert;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.vo.PageResult;
|
import cn.iocoder.common.framework.vo.PageResult;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.admin.AdminAuthenticationBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.admin.AdminBO;
|
import cn.iocoder.mall.admin.api.bo.admin.AdminBO;
|
||||||
import cn.iocoder.mall.admin.api.dto.admin.AdminAddDTO;
|
import cn.iocoder.mall.admin.api.dto.admin.AdminAddDTO;
|
||||||
import cn.iocoder.mall.admin.api.dto.admin.AdminUpdateDTO;
|
import cn.iocoder.mall.admin.api.dto.admin.AdminUpdateDTO;
|
||||||
@ -21,6 +22,9 @@ public interface AdminConvert {
|
|||||||
@Mappings({})
|
@Mappings({})
|
||||||
AdminBO convert(AdminDO adminDO);
|
AdminBO convert(AdminDO adminDO);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
AdminAuthenticationBO convert2(AdminDO admin);
|
||||||
|
|
||||||
@Mappings({})
|
@Mappings({})
|
||||||
AdminDO convert(AdminAddDTO adminAddDTO);
|
AdminDO convert(AdminAddDTO adminAddDTO);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package cn.iocoder.mall.admin.convert;
|
|||||||
|
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationOldBO;
|
||||||
import cn.iocoder.mall.admin.dataobject.AdminRoleDO;
|
import cn.iocoder.mall.admin.dataobject.AdminRoleDO;
|
||||||
import cn.iocoder.mall.admin.dataobject.OAuth2AccessTokenDO;
|
import cn.iocoder.mall.admin.dataobject.OAuth2AccessTokenDO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
@ -27,11 +28,14 @@ public interface OAuth2Convert {
|
|||||||
.setExpiresIn(Math.max((int) ((oauth2AccessTokenDO.getExpiresTime().getTime() - System.currentTimeMillis()) / 1000), 0));
|
.setExpiresIn(Math.max((int) ((oauth2AccessTokenDO.getExpiresTime().getTime() - System.currentTimeMillis()) / 1000), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
OAuth2AuthenticationOldBO convertToAuthenticationOld(OAuth2AccessTokenDO oauth2AccessTokenDO);
|
||||||
|
|
||||||
@Mappings({})
|
@Mappings({})
|
||||||
OAuth2AuthenticationBO convertToAuthentication(OAuth2AccessTokenDO oauth2AccessTokenDO);
|
OAuth2AuthenticationBO convertToAuthentication(OAuth2AccessTokenDO oauth2AccessTokenDO);
|
||||||
|
|
||||||
default OAuth2AuthenticationBO convertToAuthentication(OAuth2AccessTokenDO oauth2AccessTokenDO, List<AdminRoleDO> adminRoleDOs) {
|
default OAuth2AuthenticationOldBO convertToAuthenticationOld(OAuth2AccessTokenDO oauth2AccessTokenDO, List<AdminRoleDO> adminRoleDOs) {
|
||||||
return convertToAuthentication(oauth2AccessTokenDO)
|
return convertToAuthenticationOld(oauth2AccessTokenDO)
|
||||||
.setRoleIds(adminRoleDOs.stream().map(AdminRoleDO::getRoleId).collect(Collectors.toSet()));
|
.setRoleIds(adminRoleDOs.stream().map(AdminRoleDO::getRoleId).collect(Collectors.toSet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,16 +12,27 @@ import java.util.List;
|
|||||||
@Repository
|
@Repository
|
||||||
public interface AdminRoleMapper extends BaseMapper<AdminRoleDO> {
|
public interface AdminRoleMapper extends BaseMapper<AdminRoleDO> {
|
||||||
|
|
||||||
List<AdminRoleDO> selectByAdminId(@Param("adminId") Integer adminId);
|
default List<AdminRoleDO> selectByAdminId( Integer adminId) {
|
||||||
|
return selectList(new QueryWrapper<AdminRoleDO>().eq("admin_id", adminId));
|
||||||
|
}
|
||||||
|
|
||||||
default List<AdminRoleDO> selectListByAdminIds(Collection<Integer> adminIds) {
|
default List<AdminRoleDO> selectListByAdminIds(Collection<Integer> adminIds) {
|
||||||
return selectList(new QueryWrapper<AdminRoleDO>().in("admin_id", adminIds));
|
return selectList(new QueryWrapper<AdminRoleDO>().in("admin_id", adminIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
int updateToDeletedByAdminId(@Param("adminId") Integer adminId);
|
default int deleteByAdminId(Integer adminId) {
|
||||||
|
return delete(new QueryWrapper<AdminRoleDO>().eq("admin_id", adminId));
|
||||||
|
}
|
||||||
|
|
||||||
int updateToDeletedByRoleId(@Param("roleId") Integer roleId);
|
default int deleteByRoleId(Integer roleId) {
|
||||||
|
return delete(new QueryWrapper<AdminRoleDO>().eq("role_id", roleId));
|
||||||
|
}
|
||||||
|
|
||||||
void insertList(@Param("adminRoleDOs") List<AdminRoleDO> adminRoleDOs);
|
/**
|
||||||
|
* 批量插入。因为 MyBaits Plus 的批量插入是基于 Service 实现,所以只好写 XML
|
||||||
|
*
|
||||||
|
* @param adminRoleDOs 数组
|
||||||
|
*/
|
||||||
|
int insertList(@Param("adminRoleDOs") List<AdminRoleDO> adminRoleDOs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package cn.iocoder.mall.admin.dao;
|
package cn.iocoder.mall.admin.dao;
|
||||||
|
|
||||||
import cn.iocoder.mall.admin.dataobject.DataDictDO;
|
import cn.iocoder.mall.admin.dataobject.DataDictDO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@ -8,9 +10,7 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface DataDictMapper {
|
public interface DataDictMapper extends BaseMapper<DataDictDO> {
|
||||||
|
|
||||||
DataDictDO selectById(@Param("id") Integer id);
|
|
||||||
|
|
||||||
DataDictDO selectByEnumValueAndValue(
|
DataDictDO selectByEnumValueAndValue(
|
||||||
@Param("enumValue") String enumValue,
|
@Param("enumValue") String enumValue,
|
||||||
@ -26,10 +26,9 @@ public interface DataDictMapper {
|
|||||||
@Param("enumValue") String enumValue
|
@Param("enumValue") String enumValue
|
||||||
);
|
);
|
||||||
|
|
||||||
List<DataDictDO> selectList();
|
default List<DataDictDO> selectList() {
|
||||||
|
return selectList(new QueryWrapper<>());
|
||||||
|
}
|
||||||
|
|
||||||
void insert(DataDictDO dataDict);
|
|
||||||
|
|
||||||
int update(DataDictDO dataDict);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package cn.iocoder.mall.admin.dao;
|
package cn.iocoder.mall.admin.dao;
|
||||||
|
|
||||||
import cn.iocoder.mall.admin.dataobject.OAuth2AccessTokenDO;
|
import cn.iocoder.mall.admin.dataobject.OAuth2AccessTokenDO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface OAuth2AccessTokenMapper {
|
public interface OAuth2AccessTokenMapper extends BaseMapper<OAuth2AccessTokenDO> {
|
||||||
|
|
||||||
void insert(OAuth2AccessTokenDO entity);
|
default int updateToInvalidByAdminId(Integer adminId) {
|
||||||
|
QueryWrapper<OAuth2AccessTokenDO> query = new QueryWrapper<OAuth2AccessTokenDO>()
|
||||||
OAuth2AccessTokenDO selectByTokenId(@Param("id") String id);
|
.eq("admin_id", adminId).eq("valid", true);
|
||||||
|
return update(new OAuth2AccessTokenDO().setValid(false), query);
|
||||||
int updateToInvalidByAdminId(@Param("adminId") Integer adminId);
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,14 +1,17 @@
|
|||||||
package cn.iocoder.mall.admin.dao;
|
package cn.iocoder.mall.admin.dao;
|
||||||
|
|
||||||
import cn.iocoder.mall.admin.dataobject.OAuth2RefreshTokenDO;
|
import cn.iocoder.mall.admin.dataobject.OAuth2RefreshTokenDO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface OAuth2RefreshTokenMapper {
|
public interface OAuth2RefreshTokenMapper extends BaseMapper<OAuth2RefreshTokenDO> {
|
||||||
|
|
||||||
void insert(OAuth2RefreshTokenDO entity);
|
default int updateToInvalidByAdminId(Integer adminId) {
|
||||||
|
QueryWrapper<OAuth2RefreshTokenDO> query = new QueryWrapper<OAuth2RefreshTokenDO>()
|
||||||
int updateToInvalidByAdminId(@Param("adminId") Integer adminId);
|
.eq("admin_id", adminId).eq("valid", true);
|
||||||
|
return update(new OAuth2RefreshTokenDO().setValid(false), query);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package cn.iocoder.mall.admin.dao;
|
package cn.iocoder.mall.admin.dao;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.mybatis.QueryWrapperX;
|
||||||
import cn.iocoder.mall.admin.dataobject.ResourceDO;
|
import cn.iocoder.mall.admin.dataobject.ResourceDO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
@ -11,16 +13,24 @@ import java.util.Set;
|
|||||||
@Repository
|
@Repository
|
||||||
public interface ResourceMapper extends BaseMapper<ResourceDO> {
|
public interface ResourceMapper extends BaseMapper<ResourceDO> {
|
||||||
|
|
||||||
ResourceDO selectByTypeAndHandler(@Param("type") Integer type,
|
// TODO 芋艿,后续改造。
|
||||||
@Param("handler") String handler);
|
|
||||||
|
|
||||||
List<ResourceDO> selectListByTypeAndRoleIds(@Param("type") Integer type,
|
List<ResourceDO> selectListByTypeAndRoleIds(@Param("type") Integer type,
|
||||||
@Param("roleIds") Set<Integer> roleIds);
|
@Param("roleIds") Set<Integer> roleIds);
|
||||||
|
|
||||||
List<ResourceDO> selectListByType(@Param("type") Integer type);
|
default List<ResourceDO> selectListByPermission(String permission) {
|
||||||
|
return selectList(new QueryWrapperX<ResourceDO>().like("permissions", permission));
|
||||||
|
}
|
||||||
|
|
||||||
List<ResourceDO> selectListByIds(@Param("ids") Set<Integer> ids);
|
default List<ResourceDO> selectListByType(Integer type) {
|
||||||
|
return selectList(new QueryWrapperX<ResourceDO>().eqIfPresent("type", type));
|
||||||
|
}
|
||||||
|
|
||||||
int selectCountByPid(@Param("pid") Integer pid);
|
default List<ResourceDO> selectListByIds(Set<Integer> ids) {
|
||||||
|
return selectList(new QueryWrapper<ResourceDO>().in("id", ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
default int selectCountByPid(Integer pid) {
|
||||||
|
return selectCount(new QueryWrapper<ResourceDO>().eq("pid", pid));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface RoleMapper extends BaseMapper<RoleDO> {
|
public interface RoleMapper extends BaseMapper<RoleDO> {
|
||||||
|
|
||||||
default List<RoleDO> selectListByIds(Collection<Integer> ids) {
|
|
||||||
return selectList(new QueryWrapper<RoleDO>().in("id", ids));
|
|
||||||
}
|
|
||||||
|
|
||||||
default List<RoleDO> selectList() {
|
default List<RoleDO> selectList() {
|
||||||
return selectList(new QueryWrapper<>());
|
return selectList(new QueryWrapper<>());
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,38 @@
|
|||||||
package cn.iocoder.mall.admin.dao;
|
package cn.iocoder.mall.admin.dao;
|
||||||
|
|
||||||
import cn.iocoder.mall.admin.dataobject.RoleResourceDO;
|
import cn.iocoder.mall.admin.dataobject.RoleResourceDO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface RoleResourceMapper {
|
public interface RoleResourceMapper extends BaseMapper<RoleResourceDO> {
|
||||||
|
|
||||||
int insertList(@Param("roleResources") List<RoleResourceDO> resourceDOs);
|
/**
|
||||||
|
* 批量插入。因为 MyBaits Plus 的批量插入是基于 Service 实现,所以只好写 XML
|
||||||
|
*
|
||||||
|
* @param roleResources 数组
|
||||||
|
*/
|
||||||
|
int insertList(@Param("roleResources") List<RoleResourceDO> roleResources);
|
||||||
|
|
||||||
List<RoleResourceDO> selectByResourceHandler(@Param("resourceHandler") String resourceHandler);
|
default List<RoleResourceDO> selectListByResourceId(Integer resourceId) {
|
||||||
|
return selectList(new QueryWrapper<RoleResourceDO>().eq("resource_id", resourceId));
|
||||||
|
}
|
||||||
|
|
||||||
List<RoleResourceDO> selectByResourceId(@Param("resourceId") Integer resourceId);
|
default List<RoleResourceDO> selectListByResourceId(Collection<Integer> resourceIds) {
|
||||||
|
return selectList(new QueryWrapper<RoleResourceDO>().in("resource_id", resourceIds));
|
||||||
|
}
|
||||||
|
|
||||||
int updateToDeletedByResourceId(@Param("resourceId") Integer resourceId);
|
default int deleteByResourceId(Integer resourceId) {
|
||||||
|
return delete(new QueryWrapper<RoleResourceDO>().eq("resource_id", resourceId));
|
||||||
|
}
|
||||||
|
|
||||||
int updateToDeletedByRoleId(@Param("roleId") Integer roleId);
|
default int deleteByRoleId(Integer roleId) {
|
||||||
|
return delete(new QueryWrapper<RoleResourceDO>().eq("role_id", roleId));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package cn.iocoder.mall.admin.dataobject;
|
package cn.iocoder.mall.admin.dataobject;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ import lombok.experimental.Accessors;
|
|||||||
* value:1 男
|
* value:1 男
|
||||||
* value:2 女
|
* value:2 女
|
||||||
*/
|
*/
|
||||||
|
@TableName("data_dict")
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class DataDictDO extends DeletableDO {
|
public class DataDictDO extends DeletableDO {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package cn.iocoder.mall.admin.dataobject;
|
package cn.iocoder.mall.admin.dataobject;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@ -8,22 +12,28 @@ import java.util.Date;
|
|||||||
/**
|
/**
|
||||||
* OAUTH2 AccessToken
|
* OAUTH2 AccessToken
|
||||||
*/
|
*/
|
||||||
|
@TableName("oauth2_access_token")
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class OAuth2AccessTokenDO {
|
public class OAuth2AccessTokenDO extends BaseDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 访问令牌
|
* 访问令牌
|
||||||
*/
|
*/
|
||||||
|
@TableId(type = IdType.INPUT)
|
||||||
private String id;
|
private String id;
|
||||||
/**
|
/**
|
||||||
* 刷新令牌
|
* 刷新令牌
|
||||||
*/
|
*/
|
||||||
private String refreshToken;
|
private String refreshToken;
|
||||||
/**
|
/**
|
||||||
* 管理员比那好
|
* 用户编号
|
||||||
*/
|
*/
|
||||||
private Integer adminId;
|
private Integer userId;
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private Integer userType;
|
||||||
/**
|
/**
|
||||||
* 过期时间
|
* 过期时间
|
||||||
*/
|
*/
|
||||||
@ -32,63 +42,5 @@ public class OAuth2AccessTokenDO {
|
|||||||
* 是否有效
|
* 是否有效
|
||||||
*/
|
*/
|
||||||
private Boolean valid;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package cn.iocoder.mall.admin.dataobject;
|
package cn.iocoder.mall.admin.dataobject;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@ -10,18 +14,24 @@ import java.util.Date;
|
|||||||
*
|
*
|
||||||
* idx_uid
|
* idx_uid
|
||||||
*/
|
*/
|
||||||
|
@TableName("oauth2_refresh_token")
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class OAuth2RefreshTokenDO {
|
public class OAuth2RefreshTokenDO extends BaseDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新令牌
|
* 刷新令牌
|
||||||
*/
|
*/
|
||||||
|
@TableId(type = IdType.INPUT)
|
||||||
private String id;
|
private String id;
|
||||||
/**
|
/**
|
||||||
* 用户编号
|
* 用户编号
|
||||||
*/
|
*/
|
||||||
private Integer adminId;
|
private Integer userId;
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private Integer userType;
|
||||||
/**
|
/**
|
||||||
* 是否有效
|
* 是否有效
|
||||||
*/
|
*/
|
||||||
@ -30,9 +40,5 @@ public class OAuth2RefreshTokenDO {
|
|||||||
* 过期时间
|
* 过期时间
|
||||||
*/
|
*/
|
||||||
private Date expiresTime;
|
private Date expiresTime;
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
private Date createTime;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package cn.iocoder.mall.admin.dataobject;
|
package cn.iocoder.mall.admin.dataobject;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link RoleDO} 和 {@link ResourceDO} 的关联表
|
* {@link RoleDO} 和 {@link ResourceDO} 的关联表
|
||||||
*/
|
*/
|
||||||
|
@TableName("role_resource")
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class RoleResourceDO extends DeletableDO {
|
public class RoleResourceDO extends DeletableDO {
|
||||||
|
@ -2,16 +2,20 @@ package cn.iocoder.mall.admin.service;
|
|||||||
|
|
||||||
import cn.iocoder.common.framework.constant.CommonStatusEnum;
|
import cn.iocoder.common.framework.constant.CommonStatusEnum;
|
||||||
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
||||||
|
import cn.iocoder.common.framework.constant.UserTypeEnum;
|
||||||
import cn.iocoder.common.framework.util.CollectionUtil;
|
import cn.iocoder.common.framework.util.CollectionUtil;
|
||||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
|
||||||
import cn.iocoder.common.framework.vo.PageResult;
|
import cn.iocoder.common.framework.vo.PageResult;
|
||||||
import cn.iocoder.mall.admin.api.AdminService;
|
import cn.iocoder.mall.admin.api.AdminService;
|
||||||
import cn.iocoder.mall.admin.api.bo.role.RoleBO;
|
import cn.iocoder.mall.admin.api.bo.admin.AdminAuthenticationBO;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.admin.AdminAuthorizationBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.admin.AdminBO;
|
import cn.iocoder.mall.admin.api.bo.admin.AdminBO;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
||||||
|
import cn.iocoder.mall.admin.api.bo.role.RoleBO;
|
||||||
import cn.iocoder.mall.admin.api.constant.AdminConstants;
|
import cn.iocoder.mall.admin.api.constant.AdminConstants;
|
||||||
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
||||||
import cn.iocoder.mall.admin.api.dto.admin.*;
|
import cn.iocoder.mall.admin.api.dto.admin.*;
|
||||||
|
import cn.iocoder.mall.admin.api.dto.oauth2.OAuth2CreateTokenDTO;
|
||||||
import cn.iocoder.mall.admin.convert.AdminConvert;
|
import cn.iocoder.mall.admin.convert.AdminConvert;
|
||||||
import cn.iocoder.mall.admin.dao.AdminMapper;
|
import cn.iocoder.mall.admin.dao.AdminMapper;
|
||||||
import cn.iocoder.mall.admin.dao.AdminRoleMapper;
|
import cn.iocoder.mall.admin.dao.AdminRoleMapper;
|
||||||
@ -39,32 +43,30 @@ public class AdminServiceImpl implements AdminService {
|
|||||||
private AdminRoleMapper adminRoleMapper;
|
private AdminRoleMapper adminRoleMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private OAuth2ServiceImpl oAuth2Service;
|
private OAuth2ServiceImpl oauth2Service;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RoleServiceImpl roleService;
|
private RoleServiceImpl roleService;
|
||||||
|
|
||||||
public CommonResult<AdminDO> validAdmin(String username, String password) {
|
@Override
|
||||||
AdminDO admin = adminMapper.selectByUsername(username);
|
public AdminAuthenticationBO authentication(AdminAuthenticationDTO adminAuthenticationDTO) {
|
||||||
|
AdminDO admin = adminMapper.selectByUsername(adminAuthenticationDTO.getUsername());
|
||||||
// 账号不存在
|
// 账号不存在
|
||||||
if (admin == null) {
|
if (admin == null) {
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
|
||||||
}
|
}
|
||||||
// 密码不正确
|
// 密码不正确
|
||||||
if (encodePassword(password).equals(admin.getPassword())) {
|
if (encodePassword(adminAuthenticationDTO.getPassword()).equals(admin.getPassword())) {
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_PASSWORD_ERROR.getCode());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.ADMIN_PASSWORD_ERROR.getCode());
|
||||||
}
|
}
|
||||||
// 账号被禁用
|
// 账号被禁用
|
||||||
if (CommonStatusEnum.DISABLE.getValue().equals(admin.getStatus())) {
|
if (CommonStatusEnum.DISABLE.getValue().equals(admin.getStatus())) {
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_IS_DISABLE.getCode());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.ADMIN_IS_DISABLE.getCode());
|
||||||
}
|
}
|
||||||
// 校验成功,返回管理员。并且,去掉一些非关键字段,考虑安全性。
|
// 创建 accessToken
|
||||||
admin.setPassword(null);
|
OAuth2AccessTokenBO accessTokenBO = oauth2Service.createToken(new OAuth2CreateTokenDTO().setUserId(admin.getId())
|
||||||
admin.setStatus(null);
|
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||||
return CommonResult.success(admin);
|
// 转换返回
|
||||||
}
|
return AdminConvert.INSTANCE.convert2(admin).setToken(accessTokenBO);
|
||||||
|
|
||||||
public List<AdminRoleDO> getAdminRoles(Integer adminId) {
|
|
||||||
return adminRoleMapper.selectByAdminId(adminId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -130,7 +132,7 @@ public class AdminServiceImpl implements AdminService {
|
|||||||
adminMapper.updateById(updateAdmin);
|
adminMapper.updateById(updateAdmin);
|
||||||
// 如果是关闭管理员,则标记 token 失效。否则,管理员还可以继续蹦跶
|
// 如果是关闭管理员,则标记 token 失效。否则,管理员还可以继续蹦跶
|
||||||
if (CommonStatusEnum.DISABLE.getValue().equals(adminUpdateStatusDTO.getStatus())) {
|
if (CommonStatusEnum.DISABLE.getValue().equals(adminUpdateStatusDTO.getStatus())) {
|
||||||
oAuth2Service.removeToken(adminUpdateStatusDTO.getId());
|
oauth2Service.removeToken(adminUpdateStatusDTO.getId());
|
||||||
}
|
}
|
||||||
// TODO 插入操作日志
|
// TODO 插入操作日志
|
||||||
// 返回成功
|
// 返回成功
|
||||||
@ -152,7 +154,7 @@ public class AdminServiceImpl implements AdminService {
|
|||||||
// 标记删除 AdminDO
|
// 标记删除 AdminDO
|
||||||
adminMapper.deleteById(updateAdminId); // 标记删除
|
adminMapper.deleteById(updateAdminId); // 标记删除
|
||||||
// 标记删除 AdminRole
|
// 标记删除 AdminRole
|
||||||
adminRoleMapper.updateToDeletedByAdminId(updateAdminId);
|
adminRoleMapper.deleteByAdminId(updateAdminId);
|
||||||
// TODO 插入操作日志
|
// TODO 插入操作日志
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return true;
|
return true;
|
||||||
@ -202,7 +204,7 @@ public class AdminServiceImpl implements AdminService {
|
|||||||
}
|
}
|
||||||
// TODO 芋艿,这里先简单实现。即方式是,删除老的分配的角色关系,然后添加新的分配的角色关系
|
// TODO 芋艿,这里先简单实现。即方式是,删除老的分配的角色关系,然后添加新的分配的角色关系
|
||||||
// 标记管理员角色源关系都为删除
|
// 标记管理员角色源关系都为删除
|
||||||
adminRoleMapper.updateToDeletedByAdminId(adminAssignRoleDTO.getId());
|
adminRoleMapper.deleteByAdminId(adminAssignRoleDTO.getId());
|
||||||
// 创建 RoleResourceDO 数组,并插入到数据库
|
// 创建 RoleResourceDO 数组,并插入到数据库
|
||||||
if (!CollectionUtil.isEmpty(adminAssignRoleDTO.getRoleIds())) {
|
if (!CollectionUtil.isEmpty(adminAssignRoleDTO.getRoleIds())) {
|
||||||
List<AdminRoleDO> adminRoleDOs = adminAssignRoleDTO.getRoleIds().stream().map(roleId -> {
|
List<AdminRoleDO> adminRoleDOs = adminAssignRoleDTO.getRoleIds().stream().map(roleId -> {
|
||||||
@ -218,6 +220,24 @@ public class AdminServiceImpl implements AdminService {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AdminAuthorizationBO checkPermissions(Integer adminId, List<String> permissions) {
|
||||||
|
// 查询管理员拥有的角色关联数据
|
||||||
|
List<AdminRoleDO> adminRoleList = adminRoleMapper.selectByAdminId(adminId);
|
||||||
|
Set<Integer> adminRoleIds = CollectionUtil.convertSet(adminRoleList, AdminRoleDO::getRoleId);
|
||||||
|
// 授权校验
|
||||||
|
if (!CollectionUtil.isEmpty(permissions)) {
|
||||||
|
Map<String, List<Integer>> permissionRoleMap = roleService.getPermissionRoleMap(permissions);
|
||||||
|
for (Map.Entry<String, List<Integer>> entry : permissionRoleMap.entrySet()) {
|
||||||
|
if (!CollectionUtil.containsAny(entry.getValue(), adminRoleIds)) { // 所以有任一不满足,就验证失败,抛出异常
|
||||||
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.ADMIN_INVALID_PERMISSION.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 返回成功
|
||||||
|
return new AdminAuthorizationBO().setId(adminId).setRoleIds(adminRoleIds);
|
||||||
|
}
|
||||||
|
|
||||||
private String encodePassword(String password) {
|
private String encodePassword(String password) {
|
||||||
return DigestUtils.md5DigestAsHex(password.getBytes());
|
return DigestUtils.md5DigestAsHex(password.getBytes());
|
||||||
}
|
}
|
||||||
|
@ -31,16 +31,16 @@ public class DataDictServiceImpl implements DataDictService {
|
|||||||
private DataDictMapper dataDictMapper;
|
private DataDictMapper dataDictMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<List<DataDictBO>> selectDataDictList() {
|
public List<DataDictBO> selectDataDictList() {
|
||||||
List<DataDictDO> dataDicts = dataDictMapper.selectList();
|
List<DataDictDO> dataDicts = dataDictMapper.selectList();
|
||||||
return CommonResult.success(DataDictConvert.INSTANCE.convert(dataDicts));
|
return DataDictConvert.INSTANCE.convert(dataDicts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<DataDictBO> addDataDict(Integer adminId, DataDictAddDTO dataDictAddDTO) {
|
public DataDictBO addDataDict(Integer adminId, DataDictAddDTO dataDictAddDTO) {
|
||||||
// 校验数据字典重复
|
// 校验数据字典重复
|
||||||
if (dataDictMapper.selectByEnumValueAndValue(dataDictAddDTO.getEnumValue(), dataDictAddDTO.getValue()) != null) {
|
if (dataDictMapper.selectByEnumValueAndValue(dataDictAddDTO.getEnumValue(), dataDictAddDTO.getValue()) != null) {
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.DATA_DICT_EXISTS.getCode());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.DATA_DICT_EXISTS.getCode());
|
||||||
}
|
}
|
||||||
// 保存到数据库
|
// 保存到数据库
|
||||||
DataDictDO dataDict = DataDictConvert.INSTANCE.convert(dataDictAddDTO);
|
DataDictDO dataDict = DataDictConvert.INSTANCE.convert(dataDictAddDTO);
|
||||||
@ -49,45 +49,43 @@ public class DataDictServiceImpl implements DataDictService {
|
|||||||
dataDictMapper.insert(dataDict);
|
dataDictMapper.insert(dataDict);
|
||||||
// TODO 插入操作日志
|
// TODO 插入操作日志
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return CommonResult.success(DataDictConvert.INSTANCE.convert(dataDict));
|
return DataDictConvert.INSTANCE.convert(dataDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<Boolean> updateDataDict(Integer adminId, DataDictUpdateDTO dataDictUpdateDTO) {
|
public Boolean updateDataDict(Integer adminId, DataDictUpdateDTO dataDictUpdateDTO) {
|
||||||
// 校验数据字典不存在
|
// 校验数据字典不存在
|
||||||
DataDictDO existsDataDict = dataDictMapper.selectById(dataDictUpdateDTO.getId());
|
DataDictDO existsDataDict = dataDictMapper.selectById(dataDictUpdateDTO.getId());
|
||||||
if (existsDataDict == null) {
|
if (existsDataDict == null) {
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.DATA_DICT_NOT_EXISTS.getCode());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.DATA_DICT_NOT_EXISTS.getCode());
|
||||||
}
|
}
|
||||||
// 校验数据字典重复
|
// 校验数据字典重复
|
||||||
DataDictDO duplicateDataDict = dataDictMapper.selectByEnumValueAndValue(existsDataDict.getEnumValue(), dataDictUpdateDTO.getValue());
|
DataDictDO duplicateDataDict = dataDictMapper.selectByEnumValueAndValue(existsDataDict.getEnumValue(), dataDictUpdateDTO.getValue());
|
||||||
if (duplicateDataDict != null && !duplicateDataDict.getId().equals(dataDictUpdateDTO.getId())) {
|
if (duplicateDataDict != null && !duplicateDataDict.getId().equals(dataDictUpdateDTO.getId())) {
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.DATA_DICT_EXISTS.getCode());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.DATA_DICT_EXISTS.getCode());
|
||||||
}
|
}
|
||||||
// 更新到数据库
|
// 更新到数据库
|
||||||
DataDictDO updateDataDict = DataDictConvert.INSTANCE.convert(dataDictUpdateDTO);
|
DataDictDO updateDataDict = DataDictConvert.INSTANCE.convert(dataDictUpdateDTO);
|
||||||
dataDictMapper.update(updateDataDict);
|
dataDictMapper.updateById(updateDataDict);
|
||||||
// TODO 插入操作日志
|
// TODO 插入操作日志
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return CommonResult.success(true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 一般情况下,不要删除数据字典。
|
// 一般情况下,不要删除数据字典。
|
||||||
// 因为,业务数据正在使用该数据字典,删除后,可能有不可预知的问题。
|
// 因为,业务数据正在使用该数据字典,删除后,可能有不可预知的问题。
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<Boolean> deleteDataDict(Integer adminId, Integer dataDictId) {
|
public Boolean deleteDataDict(Integer adminId, Integer dataDictId) {
|
||||||
// 校验数据字典不存在
|
// 校验数据字典不存在
|
||||||
DataDictDO existsDataDict = dataDictMapper.selectById(dataDictId);
|
DataDictDO existsDataDict = dataDictMapper.selectById(dataDictId);
|
||||||
if (existsDataDict == null) {
|
if (existsDataDict == null) {
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.DATA_DICT_NOT_EXISTS.getCode());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.DATA_DICT_NOT_EXISTS.getCode());
|
||||||
}
|
}
|
||||||
// 更新到数据库
|
// 标记删除
|
||||||
DataDictDO updateDataDict = new DataDictDO().setId(dataDictId);
|
dataDictMapper.deleteById(dataDictId);
|
||||||
updateDataDict.setDeleted(DeletedStatusEnum.DELETED_YES.getValue());
|
|
||||||
dataDictMapper.update(updateDataDict);
|
|
||||||
// TODO 插入操作日志
|
// TODO 插入操作日志
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return CommonResult.success(true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -106,7 +104,7 @@ public class DataDictServiceImpl implements DataDictService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<List<DataDictBO>> getDataDictList(String dictKey, Collection<?> dictValueList) {
|
public CommonResult<List<DataDictBO>> getDataDictList(String dictKey, Collection<?> dictValueList) {
|
||||||
Set<String> convertDictValueList = dictValueList.stream().map(o -> String.valueOf(o)).collect(Collectors.toSet());
|
Set<String> convertDictValueList = dictValueList.stream().map(String::valueOf).collect(Collectors.toSet());
|
||||||
List<DataDictDO> dataDictDOList = dataDictMapper.selectByEnumValueAndValues(dictKey, convertDictValueList);
|
List<DataDictDO> dataDictDOList = dataDictMapper.selectByEnumValueAndValues(dictKey, convertDictValueList);
|
||||||
List<DataDictBO> dataDictBOList = DataDictConvert.INSTANCE.convert(dataDictDOList);
|
List<DataDictBO> dataDictBOList = DataDictConvert.INSTANCE.convert(dataDictDOList);
|
||||||
return CommonResult.success(dataDictBOList);
|
return CommonResult.success(dataDictBOList);
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
package cn.iocoder.mall.admin.service;
|
package cn.iocoder.mall.admin.service;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
|
||||||
import cn.iocoder.mall.admin.api.OAuth2Service;
|
import cn.iocoder.mall.admin.api.OAuth2Service;
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AccessTokenBO;
|
||||||
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
import cn.iocoder.mall.admin.api.bo.oauth2.OAuth2AuthenticationBO;
|
||||||
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
||||||
import cn.iocoder.mall.admin.api.constant.ResourceConstants;
|
import cn.iocoder.mall.admin.api.dto.oauth2.OAuth2CreateTokenDTO;
|
||||||
|
import cn.iocoder.mall.admin.api.dto.oauth2.OAuth2GetTokenDTO;
|
||||||
import cn.iocoder.mall.admin.convert.OAuth2Convert;
|
import cn.iocoder.mall.admin.convert.OAuth2Convert;
|
||||||
import cn.iocoder.mall.admin.dao.OAuth2AccessTokenMapper;
|
import cn.iocoder.mall.admin.dao.OAuth2AccessTokenMapper;
|
||||||
import cn.iocoder.mall.admin.dao.OAuth2RefreshTokenMapper;
|
import cn.iocoder.mall.admin.dao.OAuth2RefreshTokenMapper;
|
||||||
import cn.iocoder.mall.admin.dataobject.*;
|
import cn.iocoder.mall.admin.dataobject.OAuth2AccessTokenDO;
|
||||||
|
import cn.iocoder.mall.admin.dataobject.OAuth2RefreshTokenDO;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -49,36 +48,15 @@ public class OAuth2ServiceImpl implements OAuth2Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public CommonResult<OAuth2AccessTokenBO> getAccessToken(String username, String password) {
|
public OAuth2AccessTokenBO createToken(OAuth2CreateTokenDTO oauth2CreateTokenDTO) {
|
||||||
CommonResult<AdminDO> adminResult = adminService.validAdmin(username, password);
|
Integer userId = oauth2CreateTokenDTO.getUserId();
|
||||||
// 校验失败,返回错误结果
|
Integer userType = oauth2CreateTokenDTO.getUserType();
|
||||||
if (adminResult.isError()) {
|
|
||||||
return CommonResult.error(adminResult);
|
|
||||||
}
|
|
||||||
AdminDO admin = adminResult.getData();
|
|
||||||
// 创建刷新令牌
|
// 创建刷新令牌
|
||||||
OAuth2RefreshTokenDO oauth2RefreshTokenDO = createOAuth2RefreshToken(admin.getId());
|
OAuth2RefreshTokenDO oauth2RefreshTokenDO = createOAuth2RefreshToken(userId, userType);
|
||||||
// 创建访问令牌
|
// 创建访问令牌
|
||||||
OAuth2AccessTokenDO oauth2AccessTokenDO = createOAuth2AccessToken(admin.getId(), oauth2RefreshTokenDO.getId());
|
OAuth2AccessTokenDO oauth2AccessTokenDO = createOAuth2AccessToken(userId, userType, oauth2RefreshTokenDO.getId());
|
||||||
// 转换返回
|
// 转换返回
|
||||||
return CommonResult.success(OAuth2Convert.INSTANCE.convertToAccessTokenWithExpiresIn(oauth2AccessTokenDO));
|
return OAuth2Convert.INSTANCE.convertToAccessTokenWithExpiresIn(oauth2AccessTokenDO);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommonResult<OAuth2AuthenticationBO> checkToken(String accessToken) {
|
|
||||||
OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectByTokenId(accessToken);
|
|
||||||
if (accessTokenDO == null) { // 不存在
|
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.OAUTH_INVALID_TOKEN_NOT_FOUND.getCode());
|
|
||||||
}
|
|
||||||
if (accessTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期
|
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.OAUTH_INVALID_TOKEN_EXPIRED.getCode());
|
|
||||||
}
|
|
||||||
if (!accessTokenDO.getValid()) { // 无效
|
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.OAUTH_INVALID_TOKEN_INVALID.getCode());
|
|
||||||
}
|
|
||||||
// 获得管理员拥有的角色
|
|
||||||
List<AdminRoleDO> adminRoleDOs = adminService.getAdminRoles(accessTokenDO.getAdminId());
|
|
||||||
return CommonResult.success(OAuth2Convert.INSTANCE.convertToAuthentication(accessTokenDO, adminRoleDOs));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,40 +73,37 @@ public class OAuth2ServiceImpl implements OAuth2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<Boolean> checkPermission(Integer adminId, Set<Integer> roleIds, String url) {
|
public OAuth2AuthenticationBO getAuthentication(OAuth2GetTokenDTO oauth2GetTokenDTO) {
|
||||||
// 如果未配置该资源,说明无需权限控制。
|
OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectById(oauth2GetTokenDTO.getAccessToken());
|
||||||
ResourceDO resource = resourceService.getResourceByTypeAndHandler(ResourceConstants.TYPE_BUTTON, url);
|
if (accessTokenDO == null) { // 不存在
|
||||||
if (resource == null) {
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.OAUTH2_INVALID_TOKEN_NOT_FOUND.getCode());
|
||||||
return CommonResult.success(true);
|
|
||||||
}
|
}
|
||||||
// 资源存在,结果无角色,说明没有权限。
|
if (accessTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期
|
||||||
if (roleIds == null || roleIds.isEmpty()) {
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.OAUTH2_INVALID_TOKEN_EXPIRED.getCode());
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.OAUTH_INVALID_PERMISSION.getCode());
|
|
||||||
}
|
}
|
||||||
// 校验是否有资源对应的角色,即 RBAC 。
|
if (!accessTokenDO.getValid()) { // 无效
|
||||||
List<RoleResourceDO> roleResourceDOs = roleService.getRoleByResourceId(resource.getId());
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.OAUTH2_INVALID_TOKEN_INVALID.getCode());
|
||||||
for (RoleResourceDO roleResourceDO : roleResourceDOs) {
|
|
||||||
if (roleIds.contains(roleResourceDO.getRoleId())) {
|
|
||||||
return CommonResult.success(true);
|
|
||||||
}
|
}
|
||||||
|
if (!oauth2GetTokenDTO.getUserType().equals(accessTokenDO.getUserType())) {
|
||||||
|
throw ServiceExceptionUtil.exception(AdminErrorCodeEnum.OAUTH2_INVALID_TOKEN_INVALID.getCode());
|
||||||
}
|
}
|
||||||
// 没有权限,返回错误
|
// 转换返回
|
||||||
return ServiceExceptionUtil.error(AdminErrorCodeEnum.OAUTH_INVALID_PERMISSION.getCode());
|
return OAuth2Convert.INSTANCE.convertToAuthentication(accessTokenDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OAuth2AccessTokenDO createOAuth2AccessToken(Integer adminId, String refreshToken) {
|
private OAuth2AccessTokenDO createOAuth2AccessToken(Integer userId, Integer userType, String refreshToken) {
|
||||||
OAuth2AccessTokenDO accessToken = new OAuth2AccessTokenDO().setId(generateAccessToken())
|
OAuth2AccessTokenDO accessToken = new OAuth2AccessTokenDO().setId(generateAccessToken())
|
||||||
.setRefreshToken(refreshToken)
|
.setRefreshToken(refreshToken)
|
||||||
.setAdminId(adminId)
|
.setUserId(userId).setUserType(userType)
|
||||||
.setExpiresTime(new Date(System.currentTimeMillis() + accessTokenExpireTimeMillis))
|
.setExpiresTime(new Date(System.currentTimeMillis() + accessTokenExpireTimeMillis))
|
||||||
.setValid(true);
|
.setValid(true);
|
||||||
oauth2AccessTokenMapper.insert(accessToken);
|
oauth2AccessTokenMapper.insert(accessToken);
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OAuth2RefreshTokenDO createOAuth2RefreshToken(Integer adminId) {
|
private OAuth2RefreshTokenDO createOAuth2RefreshToken(Integer userId, Integer userType) {
|
||||||
OAuth2RefreshTokenDO refreshToken = new OAuth2RefreshTokenDO().setId(generateRefreshToken())
|
OAuth2RefreshTokenDO refreshToken = new OAuth2RefreshTokenDO().setId(generateRefreshToken())
|
||||||
.setAdminId(adminId)
|
.setUserId(userId).setUserType(userType)
|
||||||
.setExpiresTime(new Date(System.currentTimeMillis() + refreshTokenExpireTimeMillis))
|
.setExpiresTime(new Date(System.currentTimeMillis() + refreshTokenExpireTimeMillis))
|
||||||
.setValid(true);
|
.setValid(true);
|
||||||
oauth2RefreshTokenMapper.insert(refreshToken);
|
oauth2RefreshTokenMapper.insert(refreshToken);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package cn.iocoder.mall.admin.service;
|
package cn.iocoder.mall.admin.service;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
import cn.iocoder.common.framework.constant.DeletedStatusEnum;
|
||||||
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
|
|
||||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
|
import cn.iocoder.common.framework.util.StringUtil;
|
||||||
import cn.iocoder.mall.admin.api.ResourceService;
|
import cn.iocoder.mall.admin.api.ResourceService;
|
||||||
import cn.iocoder.mall.admin.api.bo.resource.ResourceBO;
|
import cn.iocoder.mall.admin.api.bo.resource.ResourceBO;
|
||||||
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
import cn.iocoder.mall.admin.api.constant.AdminErrorCodeEnum;
|
||||||
@ -31,8 +31,14 @@ public class ResourceServiceImpl implements ResourceService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RoleResourceMapper roleResourceMapper;
|
private RoleResourceMapper roleResourceMapper;
|
||||||
|
|
||||||
public ResourceDO getResourceByTypeAndHandler(Integer type, String handler) {
|
public List<ResourceDO> getResourceListByPermission(String permission) {
|
||||||
return resourceMapper.selectByTypeAndHandler(type, handler);
|
List<ResourceDO> resources = resourceMapper.selectListByPermission(permission);
|
||||||
|
if (resources.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
// 因为 ResourceDO 存储的 permissions 是字符串,使用逗号分隔,需要进一步判断
|
||||||
|
resources.removeIf(resourceDO -> !StringUtil.split(resourceDO.getPermissions(), ",").contains(permission));
|
||||||
|
return resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,12 +55,7 @@ public class ResourceServiceImpl implements ResourceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("Duplicates")
|
|
||||||
public ResourceBO addResource(Integer adminId, ResourceAddDTO resourceAddDTO) {
|
public ResourceBO addResource(Integer adminId, ResourceAddDTO resourceAddDTO) {
|
||||||
// 补充未在 Validation 中校验的参数校验
|
|
||||||
if (!isValidResourceType(resourceAddDTO.getType())) {
|
|
||||||
throw ServiceExceptionUtil.exception(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "资源类型必须是菜单或 Url"); // TODO 有点搓
|
|
||||||
}
|
|
||||||
// 校验父资源存在
|
// 校验父资源存在
|
||||||
checkParentResource(resourceAddDTO.getPid(), null);
|
checkParentResource(resourceAddDTO.getPid(), null);
|
||||||
// 存储到数据库
|
// 存储到数据库
|
||||||
@ -69,7 +70,6 @@ public class ResourceServiceImpl implements ResourceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("Duplicates")
|
|
||||||
public Boolean updateResource(Integer adminId, ResourceUpdateDTO resourceUpdateDTO) {
|
public Boolean updateResource(Integer adminId, ResourceUpdateDTO resourceUpdateDTO) {
|
||||||
// 校验更新的资源是否存在
|
// 校验更新的资源是否存在
|
||||||
if (resourceMapper.selectById(resourceUpdateDTO.getId()) == null) {
|
if (resourceMapper.selectById(resourceUpdateDTO.getId()) == null) {
|
||||||
@ -100,7 +100,7 @@ public class ResourceServiceImpl implements ResourceService {
|
|||||||
// 更新到数据库
|
// 更新到数据库
|
||||||
resourceMapper.deleteById(resourceId);
|
resourceMapper.deleteById(resourceId);
|
||||||
// 删除资源关联表
|
// 删除资源关联表
|
||||||
roleResourceMapper.updateToDeletedByResourceId(resourceId);
|
roleResourceMapper.deleteByResourceId(resourceId);
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -112,18 +112,6 @@ public class ResourceServiceImpl implements ResourceService {
|
|||||||
return resourceMapper.selectListByIds(resourceIds);
|
return resourceMapper.selectListByIds(resourceIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidResourceType(Integer type) {
|
|
||||||
return ResourceConstants.TYPE_MENU.equals(type)
|
|
||||||
|| ResourceConstants.TYPE_BUTTON.equals(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkParentExists(Integer pid) {
|
|
||||||
if (!ResourceConstants.PID_ROOT.equals(pid)) {
|
|
||||||
return resourceMapper.selectById(pid) == null;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkParentResource(Integer pid, Integer childId) {
|
private void checkParentResource(Integer pid, Integer childId) {
|
||||||
if (pid == null || ResourceConstants.PID_ROOT.equals(pid)) {
|
if (pid == null || ResourceConstants.PID_ROOT.equals(pid)) {
|
||||||
return;
|
return;
|
||||||
|
@ -19,6 +19,7 @@ import cn.iocoder.mall.admin.dataobject.ResourceDO;
|
|||||||
import cn.iocoder.mall.admin.dataobject.RoleDO;
|
import cn.iocoder.mall.admin.dataobject.RoleDO;
|
||||||
import cn.iocoder.mall.admin.dataobject.RoleResourceDO;
|
import cn.iocoder.mall.admin.dataobject.RoleResourceDO;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -40,12 +41,8 @@ public class RoleServiceImpl implements RoleService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ResourceServiceImpl resourceService;
|
private ResourceServiceImpl resourceService;
|
||||||
|
|
||||||
public List<RoleResourceDO> getRoleByResourceHandler(String resourceHandler) {
|
|
||||||
return roleResourceMapper.selectByResourceHandler(resourceHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RoleResourceDO> getRoleByResourceId(Integer resourceId) {
|
public List<RoleResourceDO> getRoleByResourceId(Integer resourceId) {
|
||||||
return roleResourceMapper.selectByResourceId(resourceId);
|
return roleResourceMapper.selectListByResourceId(resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,7 +59,7 @@ public class RoleServiceImpl implements RoleService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RoleBO> getRoleList(Collection<Integer> ids) {
|
public List<RoleBO> getRoleList(Collection<Integer> ids) {
|
||||||
List<RoleDO> roles = roleMapper.selectListByIds(ids);
|
List<RoleDO> roles = roleMapper.selectBatchIds(ids);
|
||||||
return RoleConvert.INSTANCE.convert(roles);
|
return RoleConvert.INSTANCE.convert(roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +101,9 @@ public class RoleServiceImpl implements RoleService {
|
|||||||
// 更新到数据库,标记删除
|
// 更新到数据库,标记删除
|
||||||
roleMapper.deleteById(roleId);
|
roleMapper.deleteById(roleId);
|
||||||
// 标记删除 RoleResource
|
// 标记删除 RoleResource
|
||||||
roleResourceMapper.updateToDeletedByRoleId(roleId);
|
roleResourceMapper.deleteByRoleId(roleId);
|
||||||
// 标记删除 AdminRole
|
// 标记删除 AdminRole
|
||||||
adminRoleMapper.updateToDeletedByRoleId(roleId);
|
adminRoleMapper.deleteByRoleId(roleId);
|
||||||
// TODO 插入操作日志
|
// TODO 插入操作日志
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return true;
|
return true;
|
||||||
@ -130,7 +127,7 @@ public class RoleServiceImpl implements RoleService {
|
|||||||
}
|
}
|
||||||
// TODO 芋艿,这里先简单实现。即方式是,删除老的分配的资源关系,然后添加新的分配的资源关系
|
// TODO 芋艿,这里先简单实现。即方式是,删除老的分配的资源关系,然后添加新的分配的资源关系
|
||||||
// 标记角色原资源关系都为删除
|
// 标记角色原资源关系都为删除
|
||||||
roleResourceMapper.updateToDeletedByRoleId(roleId);
|
roleResourceMapper.deleteByRoleId(roleId);
|
||||||
// 创建 RoleResourceDO 数组,并插入到数据库
|
// 创建 RoleResourceDO 数组,并插入到数据库
|
||||||
if (!CollectionUtil.isEmpty(resourceIds)) {
|
if (!CollectionUtil.isEmpty(resourceIds)) {
|
||||||
List<RoleResourceDO> roleResources = resourceIds.stream().map(resourceId -> {
|
List<RoleResourceDO> roleResources = resourceIds.stream().map(resourceId -> {
|
||||||
@ -150,7 +147,37 @@ public class RoleServiceImpl implements RoleService {
|
|||||||
if (CollectionUtil.isEmpty(roleIds)) {
|
if (CollectionUtil.isEmpty(roleIds)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return roleMapper.selectListByIds(roleIds);
|
return roleMapper.selectBatchIds(roleIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得权限与角色的映射关系。
|
||||||
|
*
|
||||||
|
* TODO 芋艿,等以后有 redis ,优化成从缓存读取。每个 permission ,哪些角色可以访问
|
||||||
|
*
|
||||||
|
* @param permissions 权限标识数组
|
||||||
|
* @return 映射关系。KEY:权限标识;VALUE:角色编号数组
|
||||||
|
*/
|
||||||
|
public Map<String, List<Integer>> getPermissionRoleMap(List<String> permissions) {
|
||||||
|
if (CollectionUtil.isEmpty(permissions)) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
Map<String, List<Integer>> result = Maps.newHashMapWithExpectedSize(permissions.size());
|
||||||
|
for (String permission : permissions) {
|
||||||
|
List<ResourceDO> resources = resourceService.getResourceListByPermission(permission);
|
||||||
|
if (resources.isEmpty()) { // 无需授权
|
||||||
|
result.put(permission, Collections.emptyList());
|
||||||
|
} else {
|
||||||
|
List<RoleResourceDO> roleResources = roleResourceMapper.selectListByResourceId(
|
||||||
|
CollectionUtil.convertSet(resources, ResourceDO::getId));
|
||||||
|
if (roleResources.isEmpty()) {
|
||||||
|
result.put(permission, Collections.emptyList());
|
||||||
|
} else {
|
||||||
|
result.put(permission, CollectionUtil.convertList(roleResources, RoleResourceDO::getRoleId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,37 +2,6 @@
|
|||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="cn.iocoder.mall.admin.dao.AdminRoleMapper">
|
<mapper namespace="cn.iocoder.mall.admin.dao.AdminRoleMapper">
|
||||||
|
|
||||||
<!--<insert id="insert" parameterType="UserDO" useGeneratedKeys="true" keyProperty="id">-->
|
|
||||||
<!--INSERT INTO users (-->
|
|
||||||
<!--id, mobile, create_time-->
|
|
||||||
<!--) VALUES (-->
|
|
||||||
<!--#{id}, #{mobile}, #{createTime}-->
|
|
||||||
<!--)-->
|
|
||||||
<!--</insert>-->
|
|
||||||
|
|
||||||
<select id="selectByAdminId" parameterType="Integer" resultType="AdminRoleDO">
|
|
||||||
SELECT
|
|
||||||
ar.id, ar.admin_id, ar.role_id
|
|
||||||
FROM admin a, admin_role ar
|
|
||||||
WHERE a.id = #{adminId}
|
|
||||||
AND a.id = ar.admin_id
|
|
||||||
AND ar.deleted = 0
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="updateToDeletedByAdminId" parameterType="Integer">
|
|
||||||
UPDATE admin_role
|
|
||||||
SET deleted = 1
|
|
||||||
WHERE admin_id = #{adminId}
|
|
||||||
AND deleted = 0
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="updateToDeletedByRoleId" parameterType="Integer">
|
|
||||||
UPDATE admin_role
|
|
||||||
SET deleted = 1
|
|
||||||
WHERE role_id = #{roleId}
|
|
||||||
AND deleted = 0
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<insert id="insertList">
|
<insert id="insertList">
|
||||||
INSERT INTO admin_role (
|
INSERT INTO admin_role (
|
||||||
admin_id, role_id, create_time, deleted
|
admin_id, role_id, create_time, deleted
|
||||||
|
@ -29,21 +29,6 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<select id="selectById" resultType="DataDictDO">
|
|
||||||
SELECT
|
|
||||||
<include refid="FIELDS"/>
|
|
||||||
FROM data_dict
|
|
||||||
WHERE id = #{id}
|
|
||||||
AND deleted = 0
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectList" resultType="DataDictDO">
|
|
||||||
SELECT
|
|
||||||
<include refid="FIELDS"/>
|
|
||||||
FROM data_dict
|
|
||||||
WHERE deleted = 0
|
|
||||||
</select>
|
|
||||||
<select id="selectByEnumValue" resultType="cn.iocoder.mall.admin.dataobject.DataDictDO">
|
<select id="selectByEnumValue" resultType="cn.iocoder.mall.admin.dataobject.DataDictDO">
|
||||||
SELECT
|
SELECT
|
||||||
<include refid="FIELDS"/>
|
<include refid="FIELDS"/>
|
||||||
@ -52,39 +37,4 @@
|
|||||||
AND enum_value = #{enumValue}
|
AND enum_value = #{enumValue}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insert" parameterType="DataDictDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
|
||||||
INSERT INTO data_dict (
|
|
||||||
id, enum_value, value, display_name, sort,
|
|
||||||
memo, create_time, deleted
|
|
||||||
) VALUES (
|
|
||||||
#{id}, #{enumValue}, #{value}, #{displayName}, #{sort},
|
|
||||||
#{memo}, #{createTime}, #{deleted}
|
|
||||||
)
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<update id="update" parameterType="DataDictDO">
|
|
||||||
UPDATE data_dict
|
|
||||||
<set>
|
|
||||||
<if test="enumValue != null">
|
|
||||||
enum_value = #{enumValue},
|
|
||||||
</if>
|
|
||||||
<if test="value != null">
|
|
||||||
value = #{value},
|
|
||||||
</if>
|
|
||||||
<if test="displayName != null">
|
|
||||||
display_name = #{displayName},
|
|
||||||
</if>
|
|
||||||
<if test="sort != null">
|
|
||||||
sort = #{sort},
|
|
||||||
</if>
|
|
||||||
<if test="memo != null">
|
|
||||||
memo = #{memo},
|
|
||||||
</if>
|
|
||||||
<if test="deleted != null">
|
|
||||||
deleted = #{deleted}
|
|
||||||
</if>
|
|
||||||
</set>
|
|
||||||
WHERE id = #{id}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="cn.iocoder.mall.admin.dao.OAuth2AccessTokenMapper">
|
|
||||||
|
|
||||||
<insert id="insert" parameterType="OAuth2AccessTokenDO">
|
|
||||||
INSERT INTO oauth2_access_token (
|
|
||||||
id, refresh_token, admin_id, valid, expires_time,
|
|
||||||
create_time
|
|
||||||
) VALUES (
|
|
||||||
#{id}, #{refreshToken}, #{adminId}, #{valid}, #{expiresTime},
|
|
||||||
#{createTime}
|
|
||||||
)
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<select id="selectByTokenId" parameterType="String" resultType="OAuth2AccessTokenDO">
|
|
||||||
SELECT
|
|
||||||
id, admin_id, valid, expires_time
|
|
||||||
FROM oauth2_access_token
|
|
||||||
WHERE id = #{id}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="updateToInvalidByAdminId" parameterType="Integer">
|
|
||||||
UPDATE oauth2_access_token
|
|
||||||
SET valid = 0
|
|
||||||
WHERE admin_id = #{adminId}
|
|
||||||
AND valid = 1
|
|
||||||
</update>
|
|
||||||
|
|
||||||
</mapper>
|
|
@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="cn.iocoder.mall.admin.dao.OAuth2RefreshTokenMapper">
|
|
||||||
|
|
||||||
<insert id="insert" parameterType="OAuth2RefreshTokenDO">
|
|
||||||
INSERT INTO oauth2_refresh_token (
|
|
||||||
id, admin_id, valid, expires_time, create_time
|
|
||||||
) VALUES (
|
|
||||||
#{id}, #{adminId}, #{valid}, #{expiresTime}, #{createTime}
|
|
||||||
)
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<update id="updateToInvalidByAdminId" parameterType="Integer">
|
|
||||||
UPDATE oauth2_refresh_token
|
|
||||||
SET valid = 0
|
|
||||||
WHERE admin_id = #{adminId}
|
|
||||||
AND valid = 1
|
|
||||||
</update>
|
|
||||||
|
|
||||||
</mapper>
|
|
@ -7,31 +7,9 @@
|
|||||||
create_time, pid, handler
|
create_time, pid, handler
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectByTypeAndHandler" resultType="ResourceDO">
|
|
||||||
SELECT
|
|
||||||
<include refid="FIELDS"/>
|
|
||||||
FROM resource
|
|
||||||
WHERE type = #{type}
|
|
||||||
AND handler = #{handler}
|
|
||||||
AND deleted = 0
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectListByType" parameterType="Integer" resultType="ResourceDO">
|
|
||||||
SELECT
|
|
||||||
<include refid="FIELDS"/>
|
|
||||||
FROM resource
|
|
||||||
<where>
|
|
||||||
<if test="type != null">
|
|
||||||
type = #{type}
|
|
||||||
</if>
|
|
||||||
AND deleted = 0
|
|
||||||
</where>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectListByTypeAndRoleIds" resultType="ResourceDO">
|
<select id="selectListByTypeAndRoleIds" resultType="ResourceDO">
|
||||||
SELECT
|
SELECT
|
||||||
r.id, r.name, r.type, r.sort, r.display_name,
|
r.id, r.type, r.sort, r.display_name,
|
||||||
r.create_time, r.pid, r.handler
|
r.create_time, r.pid, r.handler
|
||||||
FROM resource r, role_resource rr
|
FROM resource r, role_resource rr
|
||||||
WHERE r.deleted = 0
|
WHERE r.deleted = 0
|
||||||
@ -46,23 +24,4 @@
|
|||||||
AND r.id = rr.resource_id
|
AND r.id = rr.resource_id
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectListByIds" resultType="ResourceDO">
|
|
||||||
SELECT
|
|
||||||
<include refid="FIELDS"/>
|
|
||||||
FROM resource
|
|
||||||
WHERE id IN
|
|
||||||
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
|
|
||||||
#{id}
|
|
||||||
</foreach>
|
|
||||||
AND deleted = 0
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectCountByPid" resultType="int">
|
|
||||||
SELECT
|
|
||||||
COUNT(1)
|
|
||||||
FROM resource
|
|
||||||
WHERE pid = #{pid}
|
|
||||||
AND deleted = 0
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
@ -2,45 +2,6 @@
|
|||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="cn.iocoder.mall.admin.dao.RoleResourceMapper">
|
<mapper namespace="cn.iocoder.mall.admin.dao.RoleResourceMapper">
|
||||||
|
|
||||||
<!--<insert id="insert" parameterType="UserDO" useGeneratedKeys="true" keyProperty="id">-->
|
|
||||||
<!--INSERT INTO users (-->
|
|
||||||
<!--id, mobile, create_time-->
|
|
||||||
<!--) VALUES (-->
|
|
||||||
<!--#{id}, #{mobile}, #{createTime}-->
|
|
||||||
<!--)-->
|
|
||||||
<!--</insert>-->
|
|
||||||
|
|
||||||
<select id="selectByResourceHandler" parameterType="String" resultType="RoleResourceDO">
|
|
||||||
SELECT
|
|
||||||
rr.id, rr.role_id, rr.resource_id
|
|
||||||
FROM resource r, role_resource rr
|
|
||||||
WHERE r.handler = #{resourceHandler}
|
|
||||||
AND r.id = rr.resource_id
|
|
||||||
AND rr.deleted = 0;
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectByResourceId" parameterType="Integer" resultType="RoleResourceDO">
|
|
||||||
SELECT
|
|
||||||
id, role_id, resource_id
|
|
||||||
FROM role_resource
|
|
||||||
WHERE resource_id = #{resourceId}
|
|
||||||
AND deleted = 0
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="updateToDeletedByResourceId" parameterType="Integer">
|
|
||||||
UPDATE role_resource
|
|
||||||
SET deleted = 1
|
|
||||||
WHERE resource_id = #{resourceId}
|
|
||||||
AND deleted = 0
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="updateToDeletedByRoleId" parameterType="Integer">
|
|
||||||
UPDATE role_resource
|
|
||||||
SET deleted = 1
|
|
||||||
WHERE role_id = #{roleId}
|
|
||||||
AND deleted = 0
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<insert id="insertList">
|
<insert id="insertList">
|
||||||
INSERT INTO role_resource (
|
INSERT INTO role_resource (
|
||||||
resource_id, role_id, create_time, deleted
|
resource_id, role_id, create_time, deleted
|
||||||
|
Loading…
Reference in New Issue
Block a user