This commit is contained in:
2023-05-19 17:38:09 +08:00
parent e41797c750
commit 3dc6fb7828
77 changed files with 1000 additions and 256 deletions

View File

@ -14,6 +14,7 @@
<modules>
<module>qiaoba-module-system</module>
<module>qiaoba-module-job</module>
<module>qiaoba-module-file</module>
</modules>
</project>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qiaoba-modules</artifactId>
<groupId>com.qiaoba</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qiaoba-module-file</artifactId>
<dependencies>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-api-file</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,33 @@
package com.qiaoba.module.file.config;
import cn.hutool.core.util.URLUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 配置静态文件资源服务器
*
* @author ailanyin
* @version 1.0
* @since 2022/2/28 0028 上午 9:12
*/
@Configuration
@Getter
@Setter
public class FileConfig implements WebMvcConfigurer {
@Value("${qiaoba.file-upload-path}")
private String uploadPath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(BaseConstant.RESOURCE_PREFIX + "/**")
.addResourceLocations(URLUtil.FILE_URL_PREFIX + uploadPath);
}
}

View File

@ -0,0 +1,41 @@
package com.qiaoba.module.file.controller;
import com.qiaoba.api.file.entity.File;
import com.qiaoba.common.base.result.AjaxResult;
import com.qiaoba.module.file.service.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件管理 Web层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 9:14
*/
@RestController
@RequestMapping("/file")
@RequiredArgsConstructor
@Tag(name = "文件管理")
public class FileController {
private final FileService fileService;
@PostMapping("/upload")
@Operation(summary = "上传文件")
public AjaxResult upload(MultipartFile file) {
AjaxResult ajax = AjaxResult.success();
ajax.put("url", fileService.upload(file));
ajax.put("fileName", file.getOriginalFilename());
return ajax;
}
@DeleteMapping
@Operation(summary = "删除文件")
public AjaxResult remove(@RequestBody File file) {
return fileService.delete(file.getUrl()) ? AjaxResult.success("文件删除成功") : AjaxResult.error("文件删除失败");
}
}

View File

@ -0,0 +1,13 @@
package com.qiaoba.module.file.service;
import com.qiaoba.api.file.service.FileApiService;
/**
* 文件管理 服务层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 9:15
*/
public interface FileService extends FileApiService {
}

View File

@ -0,0 +1,39 @@
package com.qiaoba.module.file.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.module.file.config.FileConfig;
import com.qiaoba.module.file.service.FileService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件管理 服务层实现
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 9:15
*/
@Service
@RequiredArgsConstructor
public class FileServiceImpl implements FileService {
private FileConfig fileConfig;
@Override
public String upload(MultipartFile file) {
return com.qiaoba.module.file.utils.FileUtil.upload(file, fileConfig.getUploadPath());
}
@Override
public boolean delete(String path) {
String localPath = fileConfig.getUploadPath() + StrUtil.removePrefix(path, BaseConstant.RESOURCE_PREFIX);
if (FileUtil.isDirectory(localPath)) {
throw new ServiceException("删除路径异常, 请勿非法操作");
}
return FileUtil.del(localPath);
}
}

View File

@ -0,0 +1,130 @@
package com.qiaoba.module.file.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.exceptions.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Date;
/**
* 文件工具类
*
* @author ailanyin
* @version 1.0
* @since 2021/10/25 0025 上午 9:15
*/
public class FileUtil {
private static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 音频
"mp3", "wav", "wma", "mp2", "flac", "midi", "ra", "ape", "aac", "cda", "mov",
// 视频
"mp4", "avi", "rmvb", "blob",
// pdf
"pdf"};
/**
* @param file 上传的文件
* @return 文件全路径名称
*/
public static String upload(MultipartFile file, String path) {
// 获取文件后缀名
String extension = getExtension(file);
// 判断是否允许上传
isAllowedExtension(extension);
// 重命名文件
String fileName = extractFilename(extension);
// 日期 + 格式 分类
String dir = DateUtil.format(new Date(), "yyyy/MM/dd") + "/" + extension + "/";
path = path + dir;
// 新建文件
File newFile = getAbsoluteFile(fileName, path);
try {
file.transferTo(newFile);
return getPathFileName(fileName, path, dir);
} catch (IOException e) {
e.printStackTrace();
throw new ServiceException("文件上传失败, 请联系管理员处理");
}
}
/**
* 判断文件类型是否是允许上传的类型
*
* @param extension 文件类型
*/
private static void isAllowedExtension(String extension) {
boolean flag = true;
for (String str : DEFAULT_ALLOWED_EXTENSION) {
if (str.equalsIgnoreCase(extension)) {
flag = false;
}
}
if (flag) {
throw new ServiceException("不允许上传该文件类型");
}
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
private static String getExtension(MultipartFile file) {
String fileName = file.getOriginalFilename();
if (StrUtil.isBlank(fileName)) {
throw new ServiceException("上传文件-获取文件后缀名失败");
}
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
/**
* 编码文件名(UUID去除-)
*/
private static String extractFilename(String extension) {
return UUID.fastUUID().toString(true) + "." + extension;
}
/**
* 创建文件
*
* @param fileName 文件名
* @return file
*/
private static File getAbsoluteFile(String fileName, String path) {
File desc = new File(path + File.separator + fileName);
if (!desc.exists()) {
if (!desc.getParentFile().exists()) {
boolean result = desc.getParentFile().mkdirs();
if (!result) {
throw new ServiceException("上传文件-创建父目录失败");
}
}
}
return desc;
}
private static String getPathFileName(String fileName, String path, String dir) {
int dirLastIndex = path.length() + 1;
String currentDir = StringUtils.substring(path, dirLastIndex);
return currentDir + BaseConstant.RESOURCE_PREFIX + "/" + dir + fileName;
}
}

View File

@ -0,0 +1,11 @@
{
"groups": [
],
"properties": [
{
"name": "qiaoba.file-upload-path",
"type": "java.lang.String"
}
],
"hints": []
}

View File

@ -0,0 +1 @@
null not found

View File

@ -16,5 +16,9 @@
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-api-system</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-api-file</artifactId>
</dependency>
</dependencies>
</project>
</project>

View File

@ -29,10 +29,11 @@ public class SysLoginController {
private final SysMenuService sysMenuService;
private final SysLoginService sysLoginService;
@GetMapping("/captchaImage")
public AjaxResult getCaptchaImage() {
return sysLoginService.getCaptchaImage();
AjaxResult result = AjaxResult.success();
result.putAll(sysLoginService.getCaptchaImage());
return result;
}
@PostMapping("/login")
@ -44,21 +45,20 @@ public class SysLoginController {
}
@GetMapping("/getInfo")
public String getInfo() {
List<String> roleIds = SecurityUtil.getLoginUser().getRoleIds();
public AjaxResult getInfo() {
List<String> roles = SecurityUtil.getLoginUser().getRoleKeys();
Set<String> permissions = SecurityUtil.getLoginUser().getPermissions();
AjaxResult ajax = AjaxResult.success();
ajax.put("permissions", permissions);
ajax.put("roles", roleIds);
ajax.put("user",sysLoginService.selectUserFromCache(SecurityUtil.getLoginUserId()));
return "{\"msg\":\"操作成功\",\"code\":200,\"permissions\":[\"*:*:*\"],\"roles\":[\"admin\"],\"user\":{\"createBy\":\"admin\",\"createTime\":\"2023-04-23 16:11:38\",\"updateBy\":null,\"updateTime\":null,\"remark\":\"管理员\",\"userId\":1,\"deptId\":103,\"userName\":\"admin\",\"nickName\":\"若依\",\"email\":\"ry@163.com\",\"phonenumber\":\"15888888888\",\"sex\":\"1\",\"avatar\":\"\",\"password\":\"$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2\",\"status\":\"0\",\"delFlag\":\"0\",\"loginIp\":\"27.154.23.192\",\"loginDate\":\"2023-05-05T09:45:24.000+08:00\",\"dept\":{\"createBy\":null,\"createTime\":null,\"updateBy\":null,\"updateTime\":null,\"remark\":null,\"deptId\":103,\"parentId\":101,\"ancestors\":\"0,100,101\",\"deptName\":\"研发部门\",\"orderNum\":1,\"leader\":\"若依\",\"phone\":null,\"email\":null,\"status\":\"0\",\"delFlag\":null,\"parentName\":null,\"children\":[]},\"roles\":[{\"createBy\":null,\"createTime\":null,\"updateBy\":null,\"updateTime\":null,\"remark\":null,\"roleId\":1,\"roleName\":\"超级管理员\",\"roleKey\":\"admin\",\"roleSort\":1,\"dataScope\":\"1\",\"menuCheckStrictly\":false,\"deptCheckStrictly\":false,\"status\":\"0\",\"delFlag\":null,\"flag\":false,\"menuIds\":null,\"deptIds\":null,\"permissions\":null,\"admin\":true}],\"roleIds\":null,\"postIds\":null,\"roleId\":null,\"admin\":true}}";
ajax.put("roles", roles);
ajax.put("user", SecurityUtil.getLoginUser());
return ajax;
}
@GetMapping("/getRouters")
public Object getRouters() {
List<SysMenuVo> sysMenuVos = sysMenuService.selectByUserId("1650123803828019202");
public AjaxResult getRouters() {
List<SysMenuVo> sysMenuVos = sysMenuService.selectByUserId(SecurityUtil.getLoginUserId());
return AjaxResult.success(sysMenuService.menusToRouters(sysMenuVos));
//return "{\"msg\":\"操作成功\",\"code\":200,\"data\":[{\"name\":\"System\",\"path\":\"/system\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统管理\",\"icon\":\"system\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"User\",\"path\":\"user\",\"hidden\":false,\"component\":\"system/user/index\",\"meta\":{\"title\":\"用户管理\",\"icon\":\"user\",\"noCache\":false,\"link\":null}},{\"name\":\"Role\",\"path\":\"role\",\"hidden\":false,\"component\":\"system/role/index\",\"meta\":{\"title\":\"角色管理\",\"icon\":\"peoples\",\"noCache\":false,\"link\":null}},{\"name\":\"Menu\",\"path\":\"menu\",\"hidden\":false,\"component\":\"system/menu/index\",\"meta\":{\"title\":\"菜单管理\",\"icon\":\"tree-table\",\"noCache\":false,\"link\":null}},{\"name\":\"Dept\",\"path\":\"dept\",\"hidden\":false,\"component\":\"system/dept/index\",\"meta\":{\"title\":\"部门管理\",\"icon\":\"tree\",\"noCache\":false,\"link\":null}},{\"name\":\"Post\",\"path\":\"post\",\"hidden\":false,\"component\":\"system/post/index\",\"meta\":{\"title\":\"岗位管理\",\"icon\":\"post\",\"noCache\":false,\"link\":null}},{\"name\":\"Dict\",\"path\":\"dict\",\"hidden\":false,\"component\":\"system/dict/index\",\"meta\":{\"title\":\"字典管理\",\"icon\":\"dict\",\"noCache\":false,\"link\":null}},{\"name\":\"Config\",\"path\":\"config\",\"hidden\":false,\"component\":\"system/config/index\",\"meta\":{\"title\":\"参数设置\",\"icon\":\"edit\",\"noCache\":false,\"link\":null}},{\"name\":\"Notice\",\"path\":\"notice\",\"hidden\":false,\"component\":\"system/notice/index\",\"meta\":{\"title\":\"通知公告\",\"icon\":\"message\",\"noCache\":false,\"link\":null}},{\"name\":\"Log\",\"path\":\"log\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"ParentView\",\"alwaysShow\":true,\"meta\":{\"title\":\"日志管理\",\"icon\":\"log\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Operlog\",\"path\":\"operlog\",\"hidden\":false,\"component\":\"monitor/operlog/index\",\"meta\":{\"title\":\"操作日志\",\"icon\":\"form\",\"noCache\":false,\"link\":null}},{\"name\":\"Logininfor\",\"path\":\"logininfor\",\"hidden\":false,\"component\":\"monitor/logininfor/index\",\"meta\":{\"title\":\"登录日志\",\"icon\":\"logininfor\",\"noCache\":false,\"link\":null}}]}]},{\"name\":\"Monitor\",\"path\":\"/monitor\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统监控\",\"icon\":\"monitor\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Online\",\"path\":\"online\",\"hidden\":false,\"component\":\"monitor/online/index\",\"meta\":{\"title\":\"在线用户\",\"icon\":\"online\",\"noCache\":false,\"link\":null}},{\"name\":\"Job\",\"path\":\"job\",\"hidden\":false,\"component\":\"monitor/job/index\",\"meta\":{\"title\":\"定时任务\",\"icon\":\"job\",\"noCache\":false,\"link\":null}},{\"name\":\"Druid\",\"path\":\"druid\",\"hidden\":false,\"component\":\"monitor/druid/index\",\"meta\":{\"title\":\"数据监控\",\"icon\":\"druid\",\"noCache\":false,\"link\":null}},{\"name\":\"Server\",\"path\":\"server\",\"hidden\":false,\"component\":\"monitor/server/index\",\"meta\":{\"title\":\"服务监控\",\"icon\":\"server\",\"noCache\":false,\"link\":null}},{\"name\":\"Cache\",\"path\":\"cache\",\"hidden\":false,\"component\":\"monitor/cache/index\",\"meta\":{\"title\":\"缓存监控\",\"icon\":\"redis\",\"noCache\":false,\"link\":null}},{\"name\":\"CacheList\",\"path\":\"cacheList\",\"hidden\":false,\"component\":\"monitor/cache/list\",\"meta\":{\"title\":\"缓存列表\",\"icon\":\"redis-list\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Tool\",\"path\":\"/tool\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统工具\",\"icon\":\"tool\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Build\",\"path\":\"build\",\"hidden\":false,\"component\":\"tool/build/index\",\"meta\":{\"title\":\"表单构建\",\"icon\":\"build\",\"noCache\":false,\"link\":null}},{\"name\":\"Gen\",\"path\":\"gen\",\"hidden\":false,\"component\":\"tool/gen/index\",\"meta\":{\"title\":\"代码生成\",\"icon\":\"code\",\"noCache\":false,\"link\":null}},{\"name\":\"Swagger\",\"path\":\"swagger\",\"hidden\":false,\"component\":\"tool/swagger/index\",\"meta\":{\"title\":\"系统接口\",\"icon\":\"swagger\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Http://ruoyi.vip\",\"path\":\"http://ruoyi.vip\",\"hidden\":false,\"component\":\"Layout\",\"meta\":{\"title\":\"若依官网\",\"icon\":\"guide\",\"noCache\":false,\"link\":\"http://ruoyi.vip\"}}]}";
}
}

View File

@ -0,0 +1,62 @@
package com.qiaoba.module.system.controller;
import com.qiaoba.api.system.entity.dto.ResetUserBasicInfoDto;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.result.AjaxResult;
import com.qiaoba.module.system.service.SysProfileService;
import com.qiaoba.module.system.service.SysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* 个人信息 Web层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 11:25
*/
@RestController
@RequestMapping("/system/user/profile")
@RequiredArgsConstructor
@Tag(name = "用户管理-个人中心")
public class SysProfileController {
private final SysProfileService sysProfileService;
private final SysUserService sysUserService;
@GetMapping
@Operation(summary = "基本信息")
public AjaxResult profile() {
String username = SecurityUtil.getLoginUserId();
AjaxResult ajax = AjaxResult.success(sysUserService.selectById(username, false));
// todo
ajax.put("roleGroup", "超级管理员,普通角色");
ajax.put("postGroup", "董事长");
return ajax;
}
@PutMapping("/update-avatar")
@Operation(summary = "更改头像")
public AjaxResult updateAvatar(@RequestParam("file") MultipartFile file) {
AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", sysProfileService.updateAvatar(file));
return ajax;
}
@PutMapping("/update-password")
@Operation(summary = "更改密码")
public AjaxResult updatePassword(String oldPassword, String newPassword) {
sysProfileService.updatePassword(oldPassword, newPassword);
return AjaxResult.success("密码更改成功");
}
@PutMapping
@Operation(summary = "更改信息")
public AjaxResult updateBasicInfo(@RequestBody ResetUserBasicInfoDto dto) {
sysProfileService.updateBasicInfo(dto);
return AjaxResult.success("基本信息更改成功");
}
}

View File

@ -1,9 +1,10 @@
package com.qiaoba.module.system.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.SysRole;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.ResetPwdDto;
import com.qiaoba.api.system.entity.dto.ResetPasswordDto;
import com.qiaoba.api.system.entity.dto.ResetUserStatusDto;
import com.qiaoba.api.system.entity.dto.SysUserDto;
import com.qiaoba.api.system.entity.param.SysPostParam;
@ -70,15 +71,18 @@ public class SysUserController {
@PreAuthorize("hasAuthority('system:user:resetPwd')")
@PutMapping("/resetPwd")
@Operation(summary = "重置密码")
public AjaxResult resetPwd(@RequestBody ResetPwdDto dto) {
return AjaxResult.toAjax(sysUserService.resetPwd(dto));
public AjaxResult resetPwd(@RequestBody ResetPasswordDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
sysUser.setPassword(SecurityUtil.encryptPassword(dto.getPassword()));
return AjaxResult.toAjax(sysUserService.updateById(sysUser));
}
@PreAuthorize("hasAuthority('system:user:edit')")
@PutMapping("/changeStatus")
@Operation(summary = "更改状态")
public AjaxResult changeStatus(@RequestBody ResetUserStatusDto dto) {
return AjaxResult.toAjax(sysUserService.updateUserStatus(dto));
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
return AjaxResult.toAjax(sysUserService.updateById(sysUser));
}
@PreAuthorize("hasAuthority('system:user:remove')")
@ -154,15 +158,4 @@ public class SysUserController {
return AjaxResult.success();
}
/**
* 个人中心-个人信息
*/
@GetMapping("/profile")
public AjaxResult profile() {
String username = SecurityUtil.getLoginUserId();
AjaxResult ajax = AjaxResult.success(sysUserService.selectById(username, false));
ajax.put("roleGroup", "超级管理员,普通角色");
ajax.put("postGroup", "董事长");
return ajax;
}
}

View File

@ -24,6 +24,15 @@ public interface SysUserRoleMapper extends BaseMapper<SysUserRole> {
*/
List<String> selectRoleIdsByUserId(@Param("userId") String userId, @Param("status") String status);
/**
* 通过userId查询所绑定的角色Key列表
*
* @param userId userId
* @param status 状态
* @return roleIds
*/
List<String> selectRoleKeysByUserId(@Param("userId") String userId, @Param("status") String status);
/**
* 批量取消角色所绑定的用户
*

View File

@ -4,6 +4,8 @@ import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.LoginDto;
import com.qiaoba.common.base.result.AjaxResult;
import java.util.Map;
/**
* 登录 服务层
*
@ -18,7 +20,7 @@ public interface SysLoginService {
*
* @return uuid + base64
*/
AjaxResult getCaptchaImage();
Map<String, Object> getCaptchaImage();
/**
* 登录
@ -28,11 +30,4 @@ public interface SysLoginService {
*/
String login(LoginDto dto);
/**
* 从缓存中读取user
*
* @param userId userId
* @return SysUser
*/
SysUser selectUserFromCache(String userId);
}

View File

@ -1,7 +1,6 @@
package com.qiaoba.module.system.service;
import cn.hutool.core.lang.tree.Tree;
import com.qiaoba.api.system.entity.SysMenu;
import com.qiaoba.api.system.entity.vo.RouterVo;
import com.qiaoba.api.system.entity.vo.SysMenuVo;
import com.qiaoba.api.system.service.SysMenuApiService;
@ -37,6 +36,7 @@ public interface SysMenuService extends SysMenuApiService {
/**
* 通过 userId 查询目录和菜单
*
* @param userId userId
* @return list
*/

View File

@ -1,11 +1,8 @@
package com.qiaoba.module.system.service;
import com.qiaoba.api.system.entity.SysPost;
import com.qiaoba.api.system.entity.SysRole;
import com.qiaoba.api.system.entity.param.SysPostParam;
import com.qiaoba.api.system.entity.param.SysRoleParam;
import com.qiaoba.api.system.service.SysPostApiService;
import com.qiaoba.api.system.service.SysRoleApiService;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;
@ -21,7 +18,7 @@ public interface SysPostService extends SysPostApiService {
/**
* 分页查询岗位列表
*
* @param param param
* @param param param
* @param pageQuery pageQuery
* @return list
*/

View File

@ -0,0 +1,37 @@
package com.qiaoba.module.system.service;
import com.qiaoba.api.system.entity.dto.ResetUserBasicInfoDto;
import org.springframework.web.multipart.MultipartFile;
/**
* 个人信息 服务层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 11:28
*/
public interface SysProfileService {
/**
* 更新个人头像
*
* @param file file
* @return 头像链接
*/
String updateAvatar(MultipartFile file);
/**
* 更改密码
*
* @param oldPassword 旧密码
* @param newPassword 新密码
*/
void updatePassword(String oldPassword, String newPassword);
/**
* 更改基本信息
*
* @param dto dto
*/
void updateBasicInfo(ResetUserBasicInfoDto dto);
}

View File

@ -18,7 +18,7 @@ public interface SysRoleService extends SysRoleApiService {
/**
* 分页查询角色列表
*
* @param param param
* @param param param
* @param pageQuery pageQuery
* @return list
*/

View File

@ -51,6 +51,15 @@ public interface SysUserRoleService {
*/
List<String> selectRoleIdsByUserId(String userId, String status);
/**
* 通过userId查询所绑定的角色Key列表
*
* @param userId userId
* @param status 状态
* @return roleIds
*/
List<String> selectRoleKeysByUserId(String userId, String status);
/**
* 批量选择用户授权
*

View File

@ -1,7 +1,6 @@
package com.qiaoba.module.system.service;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.ResetPwdDto;
import com.qiaoba.api.system.entity.param.SysUserParam;
import com.qiaoba.api.system.entity.vo.SysUserVo;
import com.qiaoba.api.system.service.SysUserApiService;
@ -32,7 +31,7 @@ public interface SysUserService extends SysUserApiService {
/**
* 条件分页查询列表
*
* @param param 查询参数
* @param param 查询参数
* @param pageQuery 分页参数
* @return list
*/
@ -42,7 +41,7 @@ public interface SysUserService extends SysUserApiService {
* 分页查询用户列表
*
* @param pageQuery 分页信息
* @param param 查询条件
* @param param 查询条件
* @return list
*/
TableDataInfo<SysUserVo> selectVoPageList(SysUserParam param, PageQuery pageQuery);
@ -51,7 +50,7 @@ public interface SysUserService extends SysUserApiService {
* 分页查询角色已绑定的用户列表
*
* @param pageQuery 分页信息
* @param param 查询条件
* @param param 查询条件
* @return list
*/
TableDataInfo<SysUserVo> selectAllocatedList(SysUserParam param, PageQuery pageQuery);
@ -60,7 +59,7 @@ public interface SysUserService extends SysUserApiService {
* 分页查询角色未绑定的用户列表
*
* @param pageQuery 分页信息
* @param param 查询条件
* @param param 查询条件
* @return list
*/
TableDataInfo selectUnAllocatedList(SysUserParam param, PageQuery pageQuery);

View File

@ -3,25 +3,26 @@ package com.qiaoba.module.system.service.impl;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.LoginDto;
import com.qiaoba.api.system.service.SysUserDetailsApiService;
import com.qiaoba.auth.constants.SecurityConstant;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.auth.utils.TokenUtil;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.base.result.AjaxResult;
import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.system.service.SysLoginService;
import com.qiaoba.module.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 登录 服务层实现
@ -36,24 +37,26 @@ public class SysLoginServiceImpl implements SysLoginService {
private final RedisService redisService;
private final HttpServletRequest request;
private final UserDetailsService userDetailsService;
private final SysUserDetailsApiService userDetailsService;
private final SysUserService sysUserService;
@Override
public AjaxResult getCaptchaImage() {
AjaxResult ajax = AjaxResult.success();
ajax.put("register", getRegisterConfig());
public Map<String, Object> getCaptchaImage() {
Map<String, Object> map = new HashMap<String, Object>(4);
map.put("register", getRegisterConfig());
if (!getCaptchaConfig()) {
ajax.put("captchaEnabled", false);
return ajax;
map.put("captchaEnabled", false);
return map;
}
String uuid = UUID.randomUUID().toString(true);
LineCaptcha captcha = CaptchaUtil.createLineCaptcha(150, 50, 4, 20);
ajax.put("uuid", uuid);
ajax.put("img", captcha.getImageBase64());
map.put("uuid", uuid);
map.put("img", captcha.getImageBase64());
redisService.set(SecurityConstant.CAPTCHA_KEY + uuid, captcha.getCode(), 120);
return ajax;
return map;
}
@Override
@ -67,27 +70,15 @@ public class SysLoginServiceImpl implements SysLoginService {
// 检验密码
validatePassword(dto.getUsername(), sysUser.getPassword(), dto.getPassword());
// 缓存user
addUserToCache(sysUser);
// 创建UserDetails
UserDetails userDetails = userDetailsService.loadUserByUsername(dto.getUsername());
userDetailsService.toCache(sysUser.getUsername());
// 生成Token
return TokenUtil.generateToken(userDetails.getUsername());
}
@Override
public SysUser selectUserFromCache(String userId) {
return redisService.getObject(userId, SysUser.class);
}
private void addUserToCache(SysUser sysUser) {
sysUser.setPassword(null);
redisService.set(sysUser.getUserId(), sysUser);
return TokenUtil.generateToken(sysUser.getUsername());
}
private void validatePassword(String username, String password, String inputPassword) {
boolean result = SecurityUtil.matchesPassword(inputPassword, password);
if (!result) {
beforePasswordError(username);
ThreadUtil.execAsync(() -> beforePasswordError(username));
throw new ServiceException(SecurityConstant.PASSWORD_ERROR);
}
}
@ -105,7 +96,7 @@ public class SysLoginServiceImpl implements SysLoginService {
}
private boolean getCaptchaConfig() {
return false;
return true;
/* try {
return SecurityConstant.CAPTCHA_ON.equals(redisService.get(SecurityConstant.CAPTCHA_ON_OFF_KEY));
} catch (Exception e) {
@ -114,7 +105,7 @@ public class SysLoginServiceImpl implements SysLoginService {
}
private boolean getRegisterConfig() {
return false;
return true;
/* try {
return SecurityConstant.REGISTER_ON.equals(redisService.get(SecurityConstant.REGISTER_ON_OFF_KEY));
} catch (Exception e) {

View File

@ -5,10 +5,10 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiaoba.api.system.entity.SysPost;
import com.qiaoba.api.system.entity.param.SysPostParam;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.module.system.mapper.SysPostMapper;
import com.qiaoba.module.system.service.SysPostService;
import com.qiaoba.module.system.service.SysUserPostService;

View File

@ -0,0 +1,62 @@
package com.qiaoba.module.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.qiaoba.api.file.service.FileApiService;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.ResetUserBasicInfoDto;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.module.system.service.SysProfileService;
import com.qiaoba.module.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 个人信息 服务层实现
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 11:29
*/
@Service
@RequiredArgsConstructor
public class SysProfileServiceImpl implements SysProfileService {
private final FileApiService fileService;
private final SysUserService sysUserService;
@Override
public String updateAvatar(MultipartFile file) {
String url = fileService.upload(file);
SysUser sysUser = new SysUser();
sysUser.setUserId(SecurityUtil.getLoginUserId());
sysUser.setAvatar(url);
if (sysUserService.updateById(sysUser) == 0) {
fileService.delete(url);
throw new ServiceException("修改头像失败");
}
return url;
}
@Override
public void updatePassword(String oldPassword, String newPassword) {
String userId = SecurityUtil.getLoginUserId();
String password = sysUserService.selectById(userId, true).getPassword();
if (!SecurityUtil.matchesPassword(oldPassword, password)) {
throw new ServiceException("旧密码错误, 请重新输入");
}
SysUser sysUser = new SysUser();
sysUser.setUserId(SecurityUtil.getLoginUserId());
sysUser.setPassword(SecurityUtil.encryptPassword(newPassword));
sysUserService.updateById(sysUser);
}
@Override
public void updateBasicInfo(ResetUserBasicInfoDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
sysUser.setUserId(SecurityUtil.getLoginUserId());
sysUserService.checkAddOrUpdate(sysUser);
sysUserService.updateById(sysUser);
}
}

View File

@ -10,10 +10,10 @@ import com.qiaoba.api.system.entity.SysRoleMenu;
import com.qiaoba.api.system.entity.dto.DataScopeDto;
import com.qiaoba.api.system.entity.dto.SysRoleDto;
import com.qiaoba.api.system.entity.param.SysRoleParam;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.module.system.mapper.SysRoleMapper;
import com.qiaoba.module.system.service.SysRoleDeptService;
import com.qiaoba.module.system.service.SysRoleMenuService;

View File

@ -3,10 +3,9 @@ package com.qiaoba.module.system.service.impl;
import com.qiaoba.api.system.entity.SysTenant;
import com.qiaoba.module.system.mapper.SysTenantMapper;
import com.qiaoba.module.system.service.SysTenantService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 租户管理 业务层实现
*
@ -15,18 +14,18 @@ import javax.annotation.Resource;
* @since 2023-04-24 19:46:00
*/
@Service
@RequiredArgsConstructor
public class SysTenantServiceImpl implements SysTenantService {
@Resource
private SysTenantMapper baseMapper;
private final SysTenantMapper sysTenantMapper;
@Override
public int insert(SysTenant sysTenant) {
return baseMapper.insert(sysTenant);
return sysTenantMapper.insert(sysTenant);
}
@Override
public int update(SysTenant sysTenant) {
return baseMapper.updateById(sysTenant);
return sysTenantMapper.updateById(sysTenant);
}
}

View File

@ -1,9 +1,14 @@
package com.qiaoba.module.system.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.service.SysUserDetailsApiService;
import com.qiaoba.auth.constants.SecurityConstant;
import com.qiaoba.auth.entity.LoginUser;
import com.qiaoba.auth.entity.SecurityUser;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.system.service.SysMenuService;
import com.qiaoba.module.system.service.SysUserRoleService;
import com.qiaoba.module.system.service.SysUserService;
@ -25,23 +30,36 @@ import java.util.Set;
*/
@Service
@RequiredArgsConstructor
public class SysUserDetailsServiceImpl implements UserDetailsService {
public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDetailsApiService {
private final SysUserService sysUserService;
private final SysMenuService sysMenuService;
private final SysUserRoleService sysUserRoleService;
private final RedisService redisService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser user = sysUserService.selectByUsername(username);
return createUserDetails(user);
if (redisService.hasKey(SecurityConstant.USER_DETAILS_REDIS_KEY + username)) {
SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class);
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoleKeys(), user.getPermissions());
}
return toCache(username);
}
private UserDetails createUserDetails(SysUser user) {
Set<String> perms = sysMenuService.selectPermsByUserId(user.getUserId());
List<String> roleIds = sysUserRoleService.selectRoleIdsByUserId(user.getUserId(), BaseEnum.NORMAL.getCode());
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roleIds, perms);
List<String> roleKeys = sysUserRoleService.selectRoleKeysByUserId(user.getUserId(), BaseEnum.NORMAL.getCode());
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roleKeys, perms);
}
@Override
public UserDetails toCache(String username) {
SysUser user = sysUserService.selectByUsername(username);
UserDetails details = createUserDetails(user);
SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class);
redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser);
return details;
}
}

View File

@ -2,16 +2,14 @@ package com.qiaoba.module.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.SysUserDto;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.base.utils.ObjectUtil;
import com.qiaoba.module.system.service.SysUserImportService;
import com.qiaoba.module.system.service.SysUserService;
import com.qiaoba.module.system.templates.SysUserImport;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -27,7 +25,7 @@ import java.util.stream.Collectors;
* @since 2023/5/18 14:50
*/
@Service
@AllArgsConstructor
@RequiredArgsConstructor
public class SysUserImportServiceImpl implements SysUserImportService {
private final SysUserService sysUserService;

View File

@ -49,6 +49,11 @@ public class SysUserRoleServiceImpl implements SysUserRoleService {
return sysUserRoleMapper.selectRoleIdsByUserId(userId, status);
}
@Override
public List<String> selectRoleKeysByUserId(String userId, String status) {
return sysUserRoleMapper.selectRoleKeysByUserId(userId, status);
}
@Override
public void insertAuthUsers(String roleId, List<String> userIds) {
List<SysUserRole> list = new ArrayList<>();

View File

@ -9,13 +9,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.SysUserPost;
import com.qiaoba.api.system.entity.SysUserRole;
import com.qiaoba.api.system.entity.dto.ResetPwdDto;
import com.qiaoba.api.system.entity.dto.ResetUserStatusDto;
import com.qiaoba.api.system.entity.dto.SysUserDto;
import com.qiaoba.api.system.entity.param.SysUserParam;
import com.qiaoba.api.system.entity.vo.SysUserVo;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;
@ -83,18 +80,6 @@ public class SysUserServiceImpl implements SysUserService {
return sysUserMapper.selectOne(wrapper);
}
@Override
public int resetPwd(ResetPwdDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
sysUser.setPassword(SecurityUtil.encryptPassword(dto.getPassword()));
return sysUserMapper.updateById(sysUser);
}
@Override
public int updateUserStatus(ResetUserStatusDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
return sysUserMapper.updateById(sysUser);
}
@Override
@Transactional(rollbackFor = Exception.class)
@ -150,6 +135,11 @@ public class SysUserServiceImpl implements SysUserService {
sysUserRoleService.insertBatch(list);
}
@Override
public int updateById(SysUser sysUser) {
return sysUserMapper.updateById(sysUser);
}
@Override
public List<SysUserExport> selectExportData(SysUserParam param) {
List<SysUserExport> list = sysUserMapper.selectExportData(param);
@ -188,15 +178,16 @@ public class SysUserServiceImpl implements SysUserService {
return sysUser;
}
private void checkAddOrUpdate(SysUser sysUser) {
if (checkUsernameNotUnique(sysUser)) {
throw new ServiceException(StrUtil.format("新增或修改用户'{}'失败,登录账号已存在", sysUser.getUsername()));
@Override
public void checkAddOrUpdate(SysUser sysUser) {
if (StrUtil.isNotBlank(sysUser.getUsername()) && checkUsernameNotUnique(sysUser)) {
throw new ServiceException("登录账号已存在");
}
if (StrUtil.isNotBlank(sysUser.getPhone()) && checkPhoneNotUnique(sysUser)) {
throw new ServiceException(StrUtil.format("新增或修改用户'{}'失败,手机号已存在", sysUser.getUsername()));
throw new ServiceException("手机号已存在");
}
if (StrUtil.isNotBlank(sysUser.getEmail()) && checkEmailNotUnique(sysUser)) {
throw new ServiceException(StrUtil.format("新增或修改用户'{}'失败,邮箱号已存在", sysUser.getUsername()));
throw new ServiceException("邮箱号已存在");
}
}

View File

@ -3,9 +3,6 @@ package com.qiaoba.module.system.templates;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 用户导入模板
*
@ -35,7 +32,7 @@ public class SysUserImport {
private String post;
/**
* addressList = true -> 下拉框
* addressList = true -> 下拉框
*/
@Excel(name = "性别", replace = {"男_0", "女_1", "未知_2"}, addressList = true)
private String gender;

View File

@ -73,7 +73,8 @@
</select>
<select id="selectExportData" resultMap="ExportData">
select t1.user_id, t1.username, t1.nickname, t1.email, t1.phone, t1.gender, t1.status,t1.create_time, t2.dept_name,t4.role_name,t6.post_name
select t1.user_id, t1.username, t1.nickname, t1.email, t1.phone, t1.gender, t1.status,t1.create_time,
t2.dept_name,t4.role_name,t6.post_name
from sys_user t1
left join sys_dept t2 on t1.dept_id = t2.dept_id
left join sys_user_role t3 on t1.user_id = t3.user_id
@ -124,14 +125,16 @@
</select>
<select id="selectUnAllocatedList" resultMap="SysUserVoResult">
select distinct t1.user_id, t2.dept_name, t1.username, t1.nickname, t1.email, t1.phone, t1.status, t1.create_time
select distinct t1.user_id, t2.dept_name, t1.username, t1.nickname, t1.email, t1.phone, t1.status,
t1.create_time
from sys_user t1
left join sys_dept t2 on t1.dept_id = t2.dept_id
left join sys_user_role t3 on t1.user_id = t3.user_id
left join sys_role t4 on t4.role_id = t3.role_id
where (t4.role_id != #{param.roleId} or t4.role_id IS NULL)
and t1.user_id not in (select t1.user_id from sys_user t1 inner join sys_user_role t3 on t1.user_id = t3.user_id and
t3.role_id = #{param.roleId})
where (t4.role_id != #{param.roleId} or t4.role_id IS NULL)
and t1.user_id not in (select t1.user_id from sys_user t1 inner join sys_user_role t3 on t1.user_id = t3.user_id
and
t3.role_id = #{param.roleId})
<if test="param.username != null and param.username != ''">
AND t1.username like concat('%', #{param.username}, '%')
</if>
@ -155,7 +158,7 @@
limit 1
</select>
<select id="checkEmailUnique" resultType="int">
<select id="checkEmailUnique" resultType="int">
select count(*) from sys_user where email = #{email}
<if test="userId != null and userId != ''">and user_id != #{userId}</if>
limit 1

View File

@ -13,6 +13,15 @@
</if>
</select>
<select id="selectRoleKeysByUserId" resultType="string">
select t2.role_key from sys_user_role t1
left join sys_role t2 on t2.role_id = t1.role_id
where t1.user_id = #{userId}
<if test="status != null and status != ''">
and t2.status = #{status}
</if>
</select>
<delete id="deleteByRoleIdAndUserIds">
delete from sys_user_role where role_id = #{roleId} and user_id in
<foreach collection="list" item="userId" open="(" separator="," close=")">