菜单管理 && 用户管理 && 登录

This commit is contained in:
lijiaqi 2023-02-06 09:35:48 +08:00
parent b9b4ab1021
commit 34f11b11e1
22 changed files with 1069 additions and 21 deletions

View File

@ -21,6 +21,8 @@ public interface UrlConstant {
String DICT_DATA = API + "/dict_data"; String DICT_DATA = API + "/dict_data";
String USER = API + "/user";
String MENU = API + "/menu"; String MENU = API + "/menu";

View File

@ -0,0 +1,51 @@
package com.ydool.platform.saToken.config;
import cn.dev33.satoken.stp.StpInterface;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.ydool.system.entity.Menu;
import com.ydool.system.entity.Role;
import com.ydool.system.service.impl.UserServiceImpl;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 自定义权限验证接口扩展
*/
@Component // 保证此类被SpringBoot扫描完成Sa-Token的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一个账号所拥有的权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
UserServiceImpl userService = SpringUtil.getBean(UserServiceImpl.class);
List<String> list = new ArrayList<String>();
List<Menu> menuList = userService.menusByUser((String) loginId);
if (CollUtil.isNotEmpty(menuList)) {
List<String> perms = menuList.stream().map(Menu::getPerms).collect(Collectors.toList());
list.addAll(perms);
}
return list;
}
/**
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
UserServiceImpl userService = SpringUtil.getBean(UserServiceImpl.class);
List<String> list = new ArrayList<String>();
List<Role> roleList = userService.roleListByUser((String) loginId);
if (CollUtil.isNotEmpty(roleList)) {
List<String> roleCodes = roleList.stream().map(Role::getCode).collect(Collectors.toList());
list.addAll(roleCodes);
}
return list;
}
}

View File

@ -1,12 +1,12 @@
package com.ydool.system.controller; package com.ydool.system.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport; import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.ydool.common.constant.UrlConstant; import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult; import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.request.AuthRequest; import com.ydool.system.request.AuthRequest;
import com.ydool.system.request.EditPasswordRequest;
import com.ydool.system.request.NewPasswordRequest;
import com.ydool.system.service.IAuthService; import com.ydool.system.service.IAuthService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -23,6 +23,12 @@ public class AuthController {
@Autowired @Autowired
private IAuthService authService; private IAuthService authService;
/**
* 登录
*
* @param authRequest
* @return
*/
@PostMapping("login") @PostMapping("login")
@ApiOperation("登录") @ApiOperation("登录")
@ApiOperationSupport(order = 1) @ApiOperationSupport(order = 1)
@ -30,4 +36,44 @@ public class AuthController {
return authService.login(authRequest.getUserName(), authRequest.getPassword()); return authService.login(authRequest.getUserName(), authRequest.getPassword());
} }
/**
* 退出登录
*
* @return
*/
@GetMapping("logout")
@ApiOperation("退出登录")
@ApiOperationSupport(order = 2)
public AjaxResult logout() {
return authService.logout();
}
/**
* 修改密码
*
* @param editPasswordRequest
* @return
*/
@PutMapping("editPassword")
@ApiOperation("修改密码")
@ApiOperationSupport(order = 3)
public AjaxResult editPassword(@RequestBody @Validated EditPasswordRequest editPasswordRequest) {
return authService.editPassword(editPasswordRequest.getOldPassword(), editPasswordRequest.getNewPassword());
}
/**
* 修改重置以后的密码
*
* @param newPasswordRequest
* @return
*/
@PutMapping("newPassword")
@ApiOperation("修改重置以后的密码")
@ApiOperationSupport(order = 4)
public AjaxResult newPassword(@RequestBody @Validated NewPasswordRequest newPasswordRequest) {
return authService.newPassword(newPasswordRequest.getNewPassword());
}
} }

View File

@ -63,7 +63,7 @@ public class ConfigController extends BaseController {
/** /**
* 参数详情 * 参数详情
* *
* @param id 参数Id * @param id
* @return * @return
*/ */
@GetMapping(value = "detail") @GetMapping(value = "detail")
@ -109,7 +109,7 @@ public class ConfigController extends BaseController {
/** /**
* 单个删除参数 * 单个删除参数
* *
* @param id 参数Id * @param id
* @return * @return
*/ */
@DeleteMapping(value = "remove") @DeleteMapping(value = "remove")
@ -123,7 +123,7 @@ public class ConfigController extends BaseController {
/** /**
* 批量删除参数 * 批量删除参数
* *
* @param ids 参数Id集合 * @param ids
* @return * @return
*/ */
@PostMapping(value = "removeBatch") @PostMapping(value = "removeBatch")

View File

@ -7,7 +7,6 @@ import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.ydool.common.base.BaseController; import com.ydool.common.base.BaseController;
import com.ydool.common.constant.UrlConstant; import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult; import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.entity.Config;
import com.ydool.system.entity.Role; import com.ydool.system.entity.Role;
import com.ydool.system.request.IdsRequest; import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.RoleMenuRequest; import com.ydool.system.request.RoleMenuRequest;
@ -68,7 +67,7 @@ public class RoleController extends BaseController {
/** /**
* 角色详情 * 角色详情
* *
* @param id 参数Id * @param id
* @return * @return
*/ */
@GetMapping(value = "detail") @GetMapping(value = "detail")
@ -114,7 +113,7 @@ public class RoleController extends BaseController {
/** /**
* 单个删除角色 * 单个删除角色
* *
* @param id 角色Id * @param id
* @return * @return
*/ */
@DeleteMapping(value = "remove") @DeleteMapping(value = "remove")
@ -128,13 +127,13 @@ public class RoleController extends BaseController {
/** /**
* 批量删除角色 * 批量删除角色
* *
* @param ids 角色Id集合 * @param ids
* @return * @return
*/ */
@PostMapping(value = "removeBatch") @PostMapping(value = "removeBatch")
@ApiOperation(value = "批量删除角色") @ApiOperation(value = "批量删除角色")
@ApiOperationSupport(order = 6) @ApiOperationSupport(order = 6)
public AjaxResult removeConfigs(@RequestBody @Validated IdsRequest ids) { public AjaxResult removeRoles(@RequestBody @Validated IdsRequest ids) {
return roleService.removeRoles(ids); return roleService.removeRoles(ids);
} }
@ -158,6 +157,7 @@ public class RoleController extends BaseController {
/** /**
* 权限分配 * 权限分配
*
* @param roleMenuRequest * @param roleMenuRequest
* @return * @return
*/ */
@ -168,4 +168,20 @@ public class RoleController extends BaseController {
return roleService.editRoleMenu(roleMenuRequest); return roleService.editRoleMenu(roleMenuRequest);
} }
/**
* 角色列表下拉框
*
* @return
*/
@GetMapping(value = "roles")
@ApiOperation(value = "角色列表下拉框")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = Role.class)
}), order = 9
)
public AjaxResult roles() {
return roleService.roles();
}
} }

View File

@ -0,0 +1,190 @@
package com.ydool.system.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.ydool.common.base.BaseController;
import com.ydool.common.constant.UrlConstant;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.dto.UserDto;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.UserRequest;
import com.ydool.system.request.UserRolesRequest;
import com.ydool.system.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(UrlConstant.USER)
@Api(tags = "用户", value = "用户")
@ApiSupport(order = 9)
public class UserController extends BaseController {
@Autowired
private IUserService userService;
/**
* 用户列表
*
* @param value
* @param column
* @param orderBy
* @param status
* @param role
* @param dept
* @return
*/
@GetMapping(value = "list")
@ApiOperation(value = "用户列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "current", value = "当前页", dataType = "Integer"),
@ApiImplicitParam(name = "size", value = "每页条数", dataType = "Integer"),
@ApiImplicitParam(name = "value", value = "搜索框中的内容(只支持字符串类型)"),
@ApiImplicitParam(name = "column", value = "排序字段 字段名"),
@ApiImplicitParam(name = "orderBy", value = "排序顺序 降序desc升序asc"),
@ApiImplicitParam(name = "status", value = "启用状态", dataType = "Boolean"),
@ApiImplicitParam(name = "role", value = "角色"),
@ApiImplicitParam(name = "dept", value = "部门"),
})
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = UserDto.class)
}),
order = 1
)
public AjaxResult userList(String value,
String column,
String orderBy,
Boolean status,
String role,
String dept
) {
return userService.userList(getPage(), value, column, orderBy, status, role, dept);
}
/**
* 用户详情
*
* @param id
* @return
*/
@GetMapping(value = "detail")
@ApiOperation(value = "用户详情")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = UserDto.class)
}), order = 2
)
@ApiImplicitParam(name = "id", value = "用户Id")
public AjaxResult userDetail(String id) {
return userService.userDetail(id);
}
/**
* 保存用户
*
* @param userRequest
* @return
*/
@PostMapping(value = "save")
@ApiOperation(value = "保存角色")
@ApiOperationSupport(order = 3)
public AjaxResult saveUser(@RequestBody @Validated UserRequest userRequest) {
return userService.saveUser(userRequest);
}
/**
* 编辑用户
*
* @param id
* @param userRequest
* @return
*/
@PutMapping(value = "edit")
@ApiOperation(value = "编辑用户")
@ApiImplicitParam(name = "id", value = "用户Id")
@ApiOperationSupport(order = 4)
public AjaxResult editUser(String id, @RequestBody @Validated UserRequest userRequest) {
return userService.editUser(id, userRequest);
}
/**
* 单个用户
*
* @param id
* @return
*/
@DeleteMapping(value = "remove")
@ApiOperation(value = "删除用户")
@ApiImplicitParam(name = "id", value = "用户Id")
@ApiOperationSupport(order = 5)
public AjaxResult removeUser(String id) {
return userService.removeUser(id);
}
/**
* 批量删除用户
*
* @param ids 用户Id集合
* @return
*/
@PostMapping(value = "removeBatch")
@ApiOperation(value = "批量删除用户")
@ApiOperationSupport(order = 6)
public AjaxResult removeUsers(@RequestBody @Validated IdsRequest ids) {
return userService.removeUsers(ids);
}
/**
* 重置密码
*
* @param id
* @return
*/
@PutMapping(value = "resetPassword")
@ApiOperation(value = "重置密码")
@ApiImplicitParam(name = "id", value = "用户Id")
@ApiOperationSupport(order = 7)
public AjaxResult resetPassword(String id) {
return userService.resetPassword(id);
}
/**
* 获取用户所拥有的角色
*
* @param id
* @return
*/
@GetMapping(value = "rolesByUser")
@ApiOperation(value = "获取用户所拥有的角色")
@ApiImplicitParam(name = "id", value = "用户Id")
@ApiOperationSupport(
responses = @DynamicResponseParameters(properties = {
@DynamicParameter(name = "data", dataTypeClass = List.class)
}), order = 8
)
public AjaxResult rolesByUser(String id) {
return userService.rolesByUser(id);
}
/**
* 分配角色
*
* @param userRolesRequest
* @return
*/
@PutMapping(value = "editUserRoles")
@ApiOperation(value = "分配角色")
@ApiOperationSupport(order = 9)
public AjaxResult editUserRoles(UserRolesRequest userRolesRequest) {
return userService.editUserRoles(userRolesRequest);
}
}

View File

@ -0,0 +1,15 @@
package com.ydool.system.dto;
import com.ydool.system.entity.User;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class UserDto extends User {
@ApiModelProperty(value = "部门名称")
private String deptName;
@ApiModelProperty(value = "角色名称")
private String rolesName;
}

View File

@ -36,6 +36,12 @@ public class User extends BaseEntity{
@ApiModelProperty(value = "用户昵称") @ApiModelProperty(value = "用户昵称")
private String userName; private String userName;
@ApiModelProperty(value = "部门")
private String dept;
@ApiModelProperty(value = "角色")
private String roles;
@ApiModelProperty(value = "手机号码") @ApiModelProperty(value = "手机号码")
private String phone; private String phone;

View File

@ -0,0 +1,17 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class EditPasswordRequest {
@ApiModelProperty(value = "旧密码")
@NotBlank(message = "旧密码不能为空")
String oldPassword;
@ApiModelProperty(value = "新密码")
@NotBlank(message = "新密码不能为空")
String newPassword;
}

View File

@ -0,0 +1,13 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class NewPasswordRequest {
@ApiModelProperty(value = "新密码")
@NotBlank(message = "新密码不能为空")
String newPassword;
}

View File

@ -0,0 +1,39 @@
package com.ydool.system.request;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NonNull;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class UserRequest {
@ApiModelProperty(value = "登录账号")
@NotBlank(message = "登录账号不能为空")
private String loginName;
@ApiModelProperty(value = "用户昵称")
@NotBlank(message = "用户昵称不能为空")
private String userName;
@ApiModelProperty(value = "部门")
@NotBlank(message = "部门不能为空")
private String dept;
@ApiModelProperty(value = "角色")
@NotBlank(message = "角色不能为空")
private String roles;
@ApiModelProperty(value = "手机号码")
@NotBlank(message = "手机号码不能为空")
private String phone;
@ApiModelProperty(value = "帐号状态0正常 1停用")
@NotNull(message = "帐号状态不能为空")
private Boolean status;
@ApiModelProperty(value = "备注")
private String remarks;
}

View File

@ -0,0 +1,15 @@
package com.ydool.system.request;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class UserRolesRequest {
@ApiModelProperty(value = "用户Id")
@NotBlank(message = "用户Id不能为空")
private String userId;
@ApiModelProperty(value = "角色Id集合字符串")
private String roleIds;
}

View File

@ -10,4 +10,25 @@ public interface IAuthService {
* @return * @return
*/ */
AjaxResult login(String userName, String password); AjaxResult login(String userName, String password);
/**
* 登出
* @return
*/
AjaxResult logout();
/**
* 修改密码
* @param oldPassword
* @param newPassword
* @return
*/
AjaxResult editPassword(String oldPassword,String newPassword);
/**
* 修改重置以后的密码
* @param newPassword
* @return
*/
AjaxResult newPassword(String newPassword);
} }

View File

@ -73,5 +73,7 @@ public interface IDictDataService {
*/ */
AjaxResult dictDataByDictType(String dataType); AjaxResult dictDataByDictType(String dataType);
} }

View File

@ -82,6 +82,13 @@ public interface IRoleService {
AjaxResult editRoleMenu(RoleMenuRequest roleMenuRequest); AjaxResult editRoleMenu(RoleMenuRequest roleMenuRequest);
/**
* 角色列表
* @return
*/
AjaxResult roles();
} }

View File

@ -1,5 +1,15 @@
package com.ydool.system.service; package com.ydool.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.entity.Menu;
import com.ydool.system.entity.Role;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.UserRequest;
import com.ydool.system.request.UserRolesRequest;
import java.util.List;
/** /**
* <p> * <p>
* 系统账号表 服务类 * 系统账号表 服务类
@ -9,6 +19,105 @@ package com.ydool.system.service;
* @since 2023-01-05 * @since 2023-01-05
*/ */
public interface IUserService { public interface IUserService {
/**
* 添加用户
*
* @param userRequest
* @return
*/
AjaxResult saveUser(UserRequest userRequest);
/**
* 编辑用户
*
* @param id
* @param userRequest
* @return
*/
AjaxResult editUser(String id, UserRequest userRequest);
/**
* 删除用户
*
* @param id
* @return
*/
AjaxResult removeUser(String id);
/**
* 批量删除用户
*
* @param ids
* @return
*/
AjaxResult removeUsers(IdsRequest ids);
/**
* 用户详情
*
* @param id
* @return
*/
AjaxResult userDetail(String id);
/**
* 用户列表
*
* @param page
* @param value
* @param column
* @param orderBy
* @param status
* @param role
* @param dept
* @return
*/
AjaxResult userList(Page page, String value, String column, String orderBy, Boolean status, String role,
String dept);
/**
* 重置密码
* @param id
* @return
*/
AjaxResult resetPassword(String id);
/**
* 获取用户所拥有的角色
* @param id
* @return
*/
AjaxResult rolesByUser(String id);
/**
* 分配角色
* @param userRolesRequest
* @return
*/
AjaxResult editUserRoles(UserRolesRequest userRolesRequest);
/**
* 获取拥有的角色
* @param id
* @return
*/
List<Role> roleListByUser(String id);
/**
* 获取菜单树
* @param id
* @return
*/
List<Menu> menuTreesByUser(String id);
/**
* 获取菜单
* @param id
* @return
*/
List<Menu> menusByUser(String id);
} }

View File

@ -2,31 +2,44 @@ package com.ydool.system.service.impl;
import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict; import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ydool.common.base.BaseService; import com.ydool.common.base.BaseService;
import com.ydool.common.constant.UrlConstant; import com.ydool.common.cache.ConfigCache;
import com.ydool.common.data.dto.AjaxResult; import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.utils.HttpServletUtil; import com.ydool.common.utils.HttpServletUtil;
import com.ydool.common.utils.PasswordUtil; import com.ydool.common.utils.PasswordUtil;
import com.ydool.common.utils.RsaUtil; import com.ydool.system.entity.Menu;
import com.ydool.system.entity.Role;
import com.ydool.system.entity.User; import com.ydool.system.entity.User;
import com.ydool.system.mapper.UserMapper; import com.ydool.system.mapper.UserMapper;
import com.ydool.system.service.IAuthService; import com.ydool.system.service.IAuthService;
import com.ydool.system.service.IUserService;
import lombok.SneakyThrows; import lombok.SneakyThrows;
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 java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service @Service
public class AuthServiceImpl extends BaseService<UserMapper, User> implements IAuthService { public class AuthServiceImpl extends BaseService<UserMapper, User> implements IAuthService {
@Value("${sa-token.token-prefix}") @Value("${sa-token.token-prefix}")
private String tokenPrefix; private String tokenPrefix;
@Autowired
private IUserService userService;
/** /**
* 登录接口 * 登录接口
* *
@ -53,6 +66,13 @@ public class AuthServiceImpl extends BaseService<UserMapper, User> implements IA
//判断账号是否停用 //判断账号是否停用
if (loginUser.getStatus()) return AjaxResult.fail("当前账号已被停用,请联系管理员"); if (loginUser.getStatus()) return AjaxResult.fail("当前账号已被停用,请联系管理员");
//判断账号角色
if (StrUtil.isBlank(loginUser.getRoles())) return AjaxResult.fail("该用户没有对应的角色,无法登陆系统");
List<Role> roleList = userService.roleListByUser(loginUser.getId());
if (CollUtil.isEmpty(roleList)) return AjaxResult.fail("该用户没有对应的角色或角色已被删除或禁用,无法登陆系统");
loginUser.setLoginDate(LocalDateTime.now()); loginUser.setLoginDate(LocalDateTime.now());
loginUser.setLoginIp(HttpServletUtil.getRemoteAddress()); loginUser.setLoginIp(HttpServletUtil.getRemoteAddress());
@ -66,13 +86,84 @@ public class AuthServiceImpl extends BaseService<UserMapper, User> implements IA
SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
Dict result = Dict.create(); Dict result = Dict.create();
result.set("tokenName", tokenInfo.getTokenName()); result.set("tokenName", tokenInfo.getTokenName());
result.set("tokenPrefix",tokenPrefix); result.set("tokenPrefix", tokenPrefix);
result.set("tokenValue", tokenInfo.getTokenValue()); result.set("tokenValue", tokenInfo.getTokenValue());
result.set("name", loginUser.getUserName()); result.set("name", loginUser.getUserName());
//获取菜单和权限标识
List<Menu> menus = userService.menuTreesByUser(loginUser.getId());
result.set("menus", menus);
List<String> perms = new ArrayList<String>();
List<Menu> menuList = userService.menusByUser(StpUtil.getLoginIdAsString());
if (CollUtil.isNotEmpty(menuList)) {
perms = menuList.stream().map(Menu::getPerms).collect(Collectors.toList());
}
result.set("perms", perms);
//是否需要强制修改密码
result.set("need_init_password", password.equals(ConfigCache.getStr(ConfigCache.USER_INIT_PASSWORD,
"888888")) ? true : false);
return AjaxResult.ok().data(result); return AjaxResult.ok().data(result);
}else { } else {
StpUtil.logout(); StpUtil.logout();
} }
return AjaxResult.fail("登陆失败"); return AjaxResult.fail("失败");
} }
/**
* 登出
*
* @return
*/
@Override
public AjaxResult logout() {
StpUtil.logout();
return AjaxResult.ok().msg("退出成功");
}
/**
* 修改密码
*
* @param oldPassword
* @param newPassword
* @return
*/
@Override
public AjaxResult editPassword(String oldPassword, String newPassword) {
if (!PasswordUtil.valid(newPassword)) return AjaxResult.fail("密码需由长度不小于6位的英文、数字及特殊符号组成");
String loginId = StpUtil.getLoginIdAsString();
User user = getById(loginId);
if (!user.getPassword().equals(PasswordUtil.password(user.getSalt(), oldPassword))) return AjaxResult.fail(
"旧密码错误");
if (oldPassword.equals(newPassword)) return AjaxResult.fail("新旧密码不能相同");
String salt = RandomUtil.randomString(6);
String password = PasswordUtil.password(salt, newPassword);
user.setSalt(salt).setPassword(password);
user.setLastUpdatePwd(LocalDateTime.now());
boolean flag = updateById(user);
return flag ? AjaxResult.ok().msg("修改密码成功") : AjaxResult.fail("修改密码失败");
}
/**
* 修改重置以后的密码
*
* @param newPassword
* @return
*/
@Override
public AjaxResult newPassword(String newPassword) {
if (!PasswordUtil.valid(newPassword)) return AjaxResult.fail("密码需由长度不小于6位的英文、数字及特殊符号组成");
String loginId = StpUtil.getLoginIdAsString();
String salt = RandomUtil.randomString(6);
String password = PasswordUtil.password(salt, newPassword);
User user = getById(loginId);
user.setLastUpdatePwd(LocalDateTime.now());
user.setSalt(salt).setPassword(password);
boolean flag = updateById(user);
return flag ? AjaxResult.ok().msg("修改密码成功") : AjaxResult.fail("修改密码失败");
}
} }

View File

@ -203,6 +203,7 @@ public class DeptServiceImpl extends BaseTreeService<DeptMapper, Dept> implement
.last("limit 1") .last("limit 1")
); );
if (ObjectUtil.isNotNull(dept)) return "部门编码不能重复"; if (ObjectUtil.isNotNull(dept)) return "部门编码不能重复";
if (StrUtil.isNotBlank(id) && id.equals(deptRequest.getPid())) return "上级部门不能选择自己";
return null; return null;
} }
} }

View File

@ -236,7 +236,11 @@ public class MenuServiceImpl extends BaseTreeService<MenuMapper, Menu> implement
); );
if (ObjectUtil.isNotNull(menu)) return "权限字符不能重复"; if (ObjectUtil.isNotNull(menu)) return "权限字符不能重复";
if (StrUtil.isNotBlank(id) && id.equals(menuRequest.getPid())) return "上级菜单不能选择自己";
return null; return null;
} }
} }

View File

@ -10,13 +10,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.base.BaseService; import com.ydool.common.base.BaseService;
import com.ydool.common.data.dto.AjaxResult; import com.ydool.common.data.dto.AjaxResult;
import com.ydool.system.entity.Role; import com.ydool.system.entity.Role;
import com.ydool.system.mapper.MenuMapper;
import com.ydool.system.mapper.RoleMapper; import com.ydool.system.mapper.RoleMapper;
import com.ydool.system.request.IdsRequest; import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.RoleMenuRequest; import com.ydool.system.request.RoleMenuRequest;
import com.ydool.system.request.RoleRequest; import com.ydool.system.request.RoleRequest;
import com.ydool.system.service.IRoleService; import com.ydool.system.service.IRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Arrays; import java.util.Arrays;
@ -33,9 +31,6 @@ import java.util.List;
@Service @Service
public class RoleServiceImpl extends BaseService<RoleMapper, Role> implements IRoleService { public class RoleServiceImpl extends BaseService<RoleMapper, Role> implements IRoleService {
@Autowired
private MenuMapper menuMapper;
/** /**
* 保存角色 * 保存角色
* *
@ -183,6 +178,19 @@ public class RoleServiceImpl extends BaseService<RoleMapper, Role> implements IR
return flag ? AjaxResult.ok().msg("权限分配成功") : AjaxResult.fail("权限分配失败"); return flag ? AjaxResult.ok().msg("权限分配成功") : AjaxResult.fail("权限分配失败");
} }
/**
* 角色列表
*
* @return
*/
@Override
public AjaxResult roles() {
QueryWrapper<Role> qw = new QueryWrapper<Role>();
qw.lambda().eq(Role::getStatus, true).orderByAsc(Role::getSortNo);
List<Role> roleList = list(qw);
return AjaxResult.ok().data(roleList);
}
/** /**
* 校验角色 * 校验角色
* *

View File

@ -1,11 +1,37 @@
package com.ydool.system.service.impl; package com.ydool.system.service.impl;
import com.ydool.system.entity.User; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ydool.common.base.BaseService; import com.ydool.common.base.BaseService;
import com.ydool.common.cache.ConfigCache;
import com.ydool.common.data.dto.AjaxResult;
import com.ydool.common.utils.CodecUtils;
import com.ydool.common.utils.PasswordUtil;
import com.ydool.common.utils.TreeMapUtil;
import com.ydool.system.entity.Menu;
import com.ydool.system.entity.Role;
import com.ydool.system.entity.User;
import com.ydool.system.mapper.UserMapper; import com.ydool.system.mapper.UserMapper;
import com.ydool.system.request.IdsRequest;
import com.ydool.system.request.UserRequest;
import com.ydool.system.request.UserRolesRequest;
import com.ydool.system.service.IUserService; import com.ydool.system.service.IUserService;
import com.ydool.system.wrapper.UserWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* <p> * <p>
* 系统账号表 服务类 * 系统账号表 服务类
@ -17,5 +43,330 @@ import org.springframework.stereotype.Service;
@Service @Service
public class UserServiceImpl extends BaseService<UserMapper, User> implements IUserService { public class UserServiceImpl extends BaseService<UserMapper, User> implements IUserService {
@Autowired
private RoleServiceImpl roleService;
@Autowired
private MenuServiceImpl menuService;
/**
* 添加用户
*
* @param userRequest
* @return
*/
@Override
public AjaxResult saveUser(UserRequest userRequest) {
String message = checkUser("", userRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
User user = BeanUtil.copyProperties(userRequest, User.class);
user.setPhone(CodecUtils.encrypt(user.getPhone()));
String initPassword = ConfigCache.getStr(ConfigCache.USER_INIT_PASSWORD, "888888");
user.setSalt(RandomUtil.randomString(6));
user.setPassword(PasswordUtil.password(user.getSalt(), initPassword));
user.setLastUpdatePwd(LocalDateTime.now());
boolean flag = save(user);
return flag ? AjaxResult.ok().msg("保存成功") : AjaxResult.fail("保存失败");
}
/**
* 编辑用户
*
* @param id
* @param userRequest
* @return
*/
@Override
public AjaxResult editUser(String id, UserRequest userRequest) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
String message = checkUser(id, userRequest);
if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message);
User user = getById(id);
if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在");
BeanUtil.copyProperties(userRequest, user);
user.setPhone(CodecUtils.encrypt(user.getPhone()));
boolean flag = updateById(user);
return flag ? AjaxResult.ok().msg("编辑成功") : AjaxResult.fail("编辑失败");
}
/**
* 删除用户
*
* @param id
* @return
*/
@Override
public AjaxResult removeUser(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
User user = getById(id);
if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在");
return removeById(id) ? AjaxResult.ok().msg("删除成功") : AjaxResult.fail("删除失败");
}
/**
* 批量删除用户
*
* @param ids
* @return
*/
@Override
public AjaxResult removeUsers(IdsRequest ids) {
String[] idList = ids.getIds();
if (ArrayUtil.isEmpty(idList)) return AjaxResult.fail("用户Id集合不能为空");
List<User> userList = listByIds(Arrays.asList(idList));
if (CollUtil.isEmpty(userList)) return AjaxResult.fail("该用户集合全部不存在");
return removeByIds(Arrays.asList(idList)) ? AjaxResult.ok().msg("批量删除成功") : AjaxResult.fail("批量删除失败");
}
/**
* 用户详情
*
* @param id
* @return
*/
@Override
public AjaxResult userDetail(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
User user = getById(id);
if (ObjectUtil.isNull(user)) return AjaxResult.fail("该角色不存在");
return AjaxResult.ok().data(UserWrapper.INSTANCE.toDto(user));
}
/**
* 用户列表
*
* @param page
* @param value
* @param column
* @param orderBy
* @param status
* @param role
* @param dept
* @return
*/
@Override
public AjaxResult userList(Page page, String value, String column, String orderBy, Boolean status, String role,
String dept) {
QueryWrapper<User> qw = new QueryWrapper<User>();
if (StrUtil.isNotBlank(value)) {
qw.like("AES_DECRYPT(from_base64 (phone),'" + CodecUtils.KEY + "')", value).lambda()
.or().like(User::getLoginName, value)
.or().like(User::getRemarks, value)
.or().like(User::getUserName, value);
}
qw.lambda().eq(ObjectUtil.isNotNull(status), User::getStatus, status)
.eq(StrUtil.isNotBlank(dept), User::getDept, dept)
.like(StrUtil.isNotBlank(role), User::getRoles, role);
if ("desc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByDesc(StrUtil.toUnderlineCase(column));
}
if ("asc".equals(orderBy) && StrUtil.isNotBlank(column)) {
qw.orderByAsc(StrUtil.toUnderlineCase(column));
}
Page<User> pageList = page(page, qw);
return AjaxResult.ok().data(UserWrapper.INSTANCE.toDto(pageList));
}
/**
* 重置密码
*
* @param id
* @return
*/
@Override
public AjaxResult resetPassword(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
User user = getById(id);
if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在");
String initPassword = ConfigCache.getStr(ConfigCache.USER_INIT_PASSWORD, "888888");
user.setSalt(RandomUtil.randomString(6));
user.setPassword(PasswordUtil.password(user.getSalt(), initPassword));
user.setLastUpdatePwd(LocalDateTime.now());
boolean flag = updateById(user);
return flag ? AjaxResult.ok().msg("重置密码成功,新密码为" + initPassword) : AjaxResult.fail("重置密码失败");
}
/**
* 获取用户所拥有的角色
*
* @param id
* @return
*/
@Override
public AjaxResult rolesByUser(String id) {
if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空");
User user = getById(id);
if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在");
if (StrUtil.isNotBlank(user.getRoles())) {
List<String> roles = Arrays.asList(user.getRoles().split(","));
return AjaxResult.ok().data(roles);
}
return AjaxResult.ok();
}
/**
* 分配角色
*
* @param userRolesRequest
* @return
*/
@Override
public AjaxResult editUserRoles(UserRolesRequest userRolesRequest) {
User user = getById(userRolesRequest.getUserId());
if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在");
user.setRoles(userRolesRequest.getRoleIds());
boolean flag = updateById(user);
return flag ? AjaxResult.ok().msg("分配角色成功") : AjaxResult.fail("分配角色失败");
}
/**
* 获取拥有的角色
*
* @param id
* @return
*/
@Override
public List<Role> roleListByUser(String id) {
User user = getById(id);
List<Role> roles = new ArrayList<Role>();
if (StrUtil.isNotBlank(user.getRoles())) {
roles = roleService.list(new QueryWrapper<Role>().lambda()
.in(Role::getId, Arrays.asList(user.getRoles().split(
",")))
.eq(Role::getStatus, true)
.orderByAsc(Role::getSortNo)
);
}
return roles;
}
/**
* 获取菜单树
*
* @return
*/
@Override
public List<Menu> menuTreesByUser(String id) {
List<Role> roles = roleListByUser(id);
if(CollUtil.isNotEmpty(roles)) {
String menus = roles.stream().map(Role::getMenus).collect(Collectors.joining(","));
List<Map<String, Object>> menuMap = menuService.listMaps(new QueryWrapper<Menu>().lambda()
.in(Menu::getId, Arrays.asList(menus.split(
",")))
.eq(Menu::getStatus, true)
.eq(Menu::getVisible, false)
.orderByAsc(Menu::getSortNo)
);
//树结构下搜索,如果子级符合条件,就把父级也放进去,确保其能显示
Iterator<Map<String, Object>> iterator = menuMap.iterator();
List<Map<String, Object>> parentList = new ArrayList<>();
QueryWrapper<Menu> wrapper = new QueryWrapper<Menu>();
wrapper.lambda().eq(Menu::getStatus, true)
.eq(Menu::getVisible, false).orderByAsc(Menu::getSortNo);
//获取所有菜单
List<Map<String, Object>> allMenuMap = menuService.listMaps(wrapper);
Map<String, Object> allMap = new HashMap<String, Object>();
allMenuMap.forEach(item -> {
HashMap map = (HashMap) item;
allMap.put(map.get("id").toString(), map);
});
while (iterator.hasNext()) {
Map map = (HashMap) iterator.next();
String pid = map.get("pid").toString();
if (!"0".equals(pid)) {
for (; ; ) {
Map pMap = (HashMap) allMap.get(pid);
if (pMap != null && !menuMap.contains(pMap) && !parentList.contains(pMap)) {
parentList.add(pMap);
pid = pMap.get("pid").toString();
} else {
break;
}
}
}
}
menuMap.addAll(parentList);
TreeMapUtil treeMapUtil = new TreeMapUtil();
treeMapUtil.tree(menuMap);
//转换为集合对象
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(menuMap);
List<Menu> menuList = jsonArray.toList(Menu.class);
return menuList;
}
return null;
}
/**
* 获取菜单
*
* @return
*/
@Override
public List<Menu> menusByUser(String id) {
List<Role> roles = roleListByUser(id);
if(CollUtil.isNotEmpty(roles)){
String menus = roles.stream().map(Role::getMenus).collect(Collectors.joining(","));
List<Menu> menuList = menuService.list(new QueryWrapper<Menu>().lambda()
.in(Menu::getId, Arrays.asList(menus.split(
",")))
.eq(Menu::getStatus, true)
.eq(Menu::getVisible, false)
.orderByAsc(Menu::getSortNo)
);
return menuList;
}
return null;
}
/**
* 校验用户
*
* @param id
* @param userRequest
* @return
*/
private String checkUser(String id, UserRequest userRequest) {
if (!Validator.isMobile(userRequest.getPhone())) return "手机号码格式不正确";
User user = getOne(new QueryWrapper<User>()
.eq("AES_DECRYPT(from_base64 (phone),'" + CodecUtils.KEY + "')", userRequest.getPhone())
.lambda()
.ne(StrUtil.isNotBlank(id), User::getId, id)
.last("limit 1")
);
if (ObjectUtil.isNotNull(user)) return "手机号码不能重复";
user = getOne(new QueryWrapper<User>().lambda()
.eq(User::getLoginName, userRequest.getLoginName())
.ne(StrUtil.isNotBlank(id), User::getId, id)
.last("limit 1")
);
if (ObjectUtil.isNotNull(user)) return "登录账号不能重复";
return null;
}
} }

View File

@ -0,0 +1,44 @@
package com.ydool.system.wrapper;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ydool.common.base.BaseWrapper;
import com.ydool.common.utils.CodecUtils;
import com.ydool.system.dto.UserDto;
import com.ydool.system.entity.Dept;
import com.ydool.system.entity.Role;
import com.ydool.system.entity.User;
import com.ydool.system.service.impl.DeptServiceImpl;
import com.ydool.system.service.impl.RoleServiceImpl;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Mapper
public interface UserWrapper extends BaseWrapper<User, UserDto> {
UserWrapper INSTANCE = Mappers.getMapper(UserWrapper.class);
@AfterMapping
default void setOtherField(User obj, @MappingTarget UserDto dto) {
DeptServiceImpl deptService = SpringUtil.getBean(DeptServiceImpl.class);
RoleServiceImpl roleService = SpringUtil.getBean(RoleServiceImpl.class);
dto.setPhone(CodecUtils.decrypt(obj.getPhone()));
Dept dept = deptService.getById(obj.getDept());
if (ObjectUtil.isNotNull(dept)) dto.setDeptName(dept.getName());
List<Role> roles = roleService.list(new QueryWrapper<Role>().lambda()
.in(Role::getId, Arrays.asList(obj.getRoles().split(
",")))
.eq(Role::getStatus, true)
.orderByAsc(Role::getSortNo)
);
if (CollUtil.isNotEmpty(roles))
dto.setRolesName(roles.stream().map(Role::getName).collect(Collectors.joining(",")));
}
}