feat(修改): 模块、包、项目结构修改

This commit is contained in:
bunny 2024-05-22 15:34:22 +08:00
parent 17ddb8750e
commit 324b9f2c29
154 changed files with 3262 additions and 860 deletions

View File

@ -22,16 +22,20 @@
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>jaxb-api</artifactId>
<version>2.1</version> <version>2.1</version>
</dependency> </dependency>
<!-- velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
</dependency>
<!--mysql--> <!--mysql-->
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
@ -54,11 +58,6 @@
<artifactId>mybatis-plus-generator</artifactId> <artifactId>mybatis-plus-generator</artifactId>
<version>3.5.6</version> <version>3.5.6</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!-- 数据库代码生成器 - 旧版 --> <!-- 数据库代码生成器 - 旧版 -->
<!-- <dependency> --> <!-- <dependency> -->
<!-- <groupId>com.baomidou</groupId> --> <!-- <groupId>com.baomidou</groupId> -->

View File

@ -1,6 +1,5 @@
package cn.bunny.common.generator; package cn.bunny.common.generator;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator; import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile; import com.baomidou.mybatisplus.generator.config.OutputFile;
@ -15,12 +14,12 @@ public class NewCodeGet {
// 作者名称 // 作者名称
public static final String author = "Bunny"; public static final String author = "Bunny";
// 公共路径 // 公共路径
public static final String outputDir = "F:\\web项目\\PC\\BunnyNote\\bunny-server\\service\\service-admin"; public static final String outputDir = "F:\\web项目\\PC\\BunnyNote\\BunnyBBS-server\\service\\service-web";
// 实体类名称 // 实体类名称
public static final String entity = "Bunny"; public static final String entity = "Bunny";
public static void main(String[] args) { public static void main(String[] args) {
Generation("email_users"); Generation("article");
} }
/** /**
@ -42,7 +41,7 @@ public class NewCodeGet {
.packageConfig(builder -> { .packageConfig(builder -> {
builder.entity(entity)// 实体类包名 builder.entity(entity)// 实体类包名
// TODO 父包名如果为空将下面子包名必须写全部 否则就只需写子包名 // TODO 父包名如果为空将下面子包名必须写全部 否则就只需写子包名
.parent("cn.bunny.service.admin") .parent("cn.bunny.service.web")
.controller("controller")// 控制层包名 .controller("controller")// 控制层包名
.mapper("mapper")// mapper层包名 .mapper("mapper")// mapper层包名
.service("service")// service层包名 .service("service")// service层包名

View File

@ -1,41 +0,0 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* 信息提示常量类
*/
@Data
public class CommonMessageConstant {
public static final String PASSWORD_ERROR = "密码错误";
public static final String OLD_PASSWORD_ERROR = "旧密码不匹配";
public static final String OLD_PASSWORD_SAME_NEW_PASSWORD = "旧密码与新密码相同";
public static final String ACCOUNT_NOT_FOUND = "账号不存在";
public static final String ACCOUNT_LOCKED = "账号被锁定";
public static final String UNKNOWN_ERROR = "未知错误";
public static final String USER_NOT_LOGIN = "用户未登录";
public static final String USER_TOKEN_OUT_OF_DATE = "用户登录过期";
public static final String LOGIN_FAILED = "登录失败";
public static final String UPLOAD_FAILED = "文件上传失败";
public static final String PASSWORD_EDIT_FAILED = "密码修改失败";
public static final String ALREADY_EXISTS = "已存在";
public static final String REQUEST_NOT_EMPTY = "请求不为空";
public static final String UPDATE_ID_IS_NOT_EMPTY = "删除id不能为空";
public static final String DELETE_ID_IS_NOT_EMPTY = "修改id不能为空";
public static final String MENU_IS_NOT_EXIST = "菜单不存在";
public static final String SAVE_DTO_IS_NULL = "添加参数不能为空";
public static final String UPDATE_DTO_IS_NULL = "修改参数不能为空";
public static final String FIND_ID_IS_NOT_EMPTY = "查询ID不能为空";
public static final String MESSAGE_CODE_NOT_PASS = "短信验证码未过期";
public static final String MESSAGE_CODE_UNAUTHORIZED = "短信验证码未授权,请联系管理员";
public static final String VERIFICATION_CODE_ERROR = "验证码错误";
public static final String USER_DOES_NOT_EXIST = "用户不存在";
public static final String USER_DOES_IS_EXIST = "用户已存在";
public static final String VERIFICATION_CODE_IS_EMPTY = "请先发送验证码";
public static final String LOGIN_DTO_IS_EMPTY = "登录参数不能为空";
public static final String TOKEN_IS_EMPTY = "token为空";
public static final String DATA_IS_EMPTY = "数据为空";
public static final String USERNAME_NOT_EMPTY = "用户名不能为空";
public static final String PASSWORD_NOT_EMPTY = "密码不能为空";
public static final String SERVER_ERROR = "密码不能为空";
}

View File

@ -1,16 +0,0 @@
package cn.bunny.common.result.constant;
import lombok.Data;
@Data
public class ExceptionConstant {
public static final String USER_NOT_FOUND = "用户不存在";
public static final String USERNAME_IS_EMPTY = "用户名不能为空";
public static final String PASSWORD_ERROR = "密码错误";
public static final String PASSWORD_IS_EMPTY = "密码不能为空";
public static final String CAPTCHA_IS_EMPTY = "提交验证码不能为空";
public static final String KEY_IS_EMPTY = "验证码key不能为空";
public static final String VERIFICATION_CODE_DOES_NOT_MATCH = "验证码不匹配";
public static final String VERIFICATION_CODE_IS_EMPTY = "验证码失效或不存在";
}

View File

@ -1,18 +0,0 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* 密码常量
*/
@Data
public class PasswordConstant {
// 默认密码
public static final String DEFAULT_PASSWORD = "123456";
// JWT密码
public static final String DEFAULT_JWT_PASSWORD = "123456";
// 默认头像
public static final String AVTAR = "https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg";
// 设置token过期时间
public static final long TOKEN_EXPIRATION = 365L * 24 * 60 * 60 * 1000;
}

View File

@ -1,11 +0,0 @@
package cn.bunny.common.result.constant;
import lombok.Data;
/**
* Redis用户前缀设置
*/
@Data
public class RedisUserConstant {
public static final String REDIS_CART_KEY = "user::";
}

View File

@ -1,44 +0,0 @@
package cn.bunny.common.result.enums;
import lombok.Getter;
/**
* 统一返回结果状态信息类
*/
@Getter
public enum ResultCodeEnum {
SUCCESS(200, "操作成功"),
SUCCESS_LOGOUT(200, "退出成功"),
FAIL(201, "失败"),
USERNAME_NOT_EMPTY(201, "用户名不能为空"),
PASSWORD_NOT_EMPTY(201, "密码不能为空"),
SERVICE_ERROR(2012, "服务异常"),
DATA_ERROR(204, "数据异常"),
LOGIN_ERROR(204, "账号或密码错误"),
ILLEGAL_REQUEST(205, "非法请求"),
REPEAT_SUBMIT(206, "重复提交"),
LOGIN_AUTH(208, "未登陆"),
PERMISSION(209, "没有权限"),
URL_ENCODE_ERROR(216, "URL编码失败"),
ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"),
FETCH_ACCESSTOKEN_FAILD(218, "获取accessToken失败"),
FETCH_USERINFO_ERROR(219, "获取用户信息失败"),
FAIL_REQUEST_NOT_AUTH(403, "用户未认证"),
FAIL_NO_ACCESS_DENIED(403, "无权访问"),
LOGGED_IN_FROM_ANOTHER_DEVICE(403, "没有权限访问"),
THE_SAME_USER_HAS_LOGGED_IN(403, "相同用户已登录"),
SESSION_EXPIRATION(403, "会话过期");
private final Integer code;
private final String message;
ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -7,10 +7,10 @@
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>common-result</artifactId> <artifactId>common-utils</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>common-result</name> <name>common-utils</name>
<url>https://maven.apache.org</url> <url>https://maven.apache.org</url>
<properties> <properties>
@ -19,8 +19,9 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>cn.bunny</groupId>
<artifactId>lombok</artifactId> <artifactId>model</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,51 @@
package cn.bunny.common.utils;
import cn.bunny.vo.system.comment.CommentVo;
import java.util.ArrayList;
import java.util.List;
public class CommentUtil {
/**
* 构建树型结构
*
* @param commentList 评论列表
* @return 结构列表
*/
public static List<CommentVo> buildTree(List<CommentVo> commentList) {
// 构建树形结构
List<CommentVo> tree = new ArrayList<>();
// 遍历评论列表
for (CommentVo comment : commentList) {
// 找到顶级评论没有父评论
if (comment.getPCommentId() == 0) {
// 递归构建子评论
comment.setChildren(getChildren(comment.getId(), commentList));
tree.add(comment);
}
}
return tree;
}
/**
* 递归获取子评论
*
* @param commentId 当前评论ID
* @param commentList 评论列表
* @return 子评论列表
*/
private static List<CommentVo> getChildren(Long commentId, List<CommentVo> commentList) {
List<CommentVo> children = new ArrayList<>();
// 遍历评论列表
for (CommentVo comment : commentList) {
// 找到当前评论的子评论
if (Long.valueOf(comment.getPCommentId()).equals(commentId)) {
// 递归构建子评论的子评论
comment.setChildren(getChildren(comment.getId(), commentList));
children.add(comment);
}
}
return children;
}
}

View File

@ -0,0 +1,25 @@
package cn.bunny.common.utils;
public class FileUtil {
public static String getSize(Long fileSize) {
double fileSizeInKB = fileSize / 1024.00;
double fileSizeInMB = fileSizeInKB / 1024;
double fileSizeInGB = fileSizeInMB / 1024;
String size;
if (fileSizeInGB >= 1) {
fileSizeInGB = Double.parseDouble(String.format("%.2f", fileSizeInGB));
size = fileSizeInGB + "GB";
} else if (fileSizeInMB >= 1) {
fileSizeInMB = Double.parseDouble(String.format("%.2f", fileSizeInMB));
size = fileSizeInMB + "MB";
} else if (fileSizeInKB >= 1) {
fileSizeInKB = Double.parseDouble(String.format("%.2f", fileSizeInKB));
size = fileSizeInKB + "KB";
} else {
size = fileSize + "B";
}
return size;
}
}

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>cn.bunny</groupId> <groupId>cn.bunny</groupId>
<artifactId>bunny-template-mirror-server</artifactId> <artifactId>bunny-mirror-server</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
@ -14,14 +14,13 @@
<modules> <modules>
<module>service-utils</module> <module>service-utils</module>
<module>common-generator</module> <module>common-generator</module>
<module>common-result</module> <module>common-utils</module>
</modules> </modules>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId> <artifactId>jackson-datatype-jsr310</artifactId>
<version>2.17.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>

View File

@ -19,13 +19,14 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>cn.bunny</groupId> <groupId>cn.bunny</groupId>
<artifactId>common-generator</artifactId> <artifactId>model</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</dependency> </dependency>
<!-- httpclient -->
<dependency> <dependency>
<groupId>cn.bunny</groupId> <groupId>org.apache.httpcomponents</groupId>
<artifactId>common-result</artifactId> <artifactId>httpclient</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>4.5.14</version>
</dependency> </dependency>
<!-- knife4j --> <!-- knife4j -->
<dependency> <dependency>
@ -47,5 +48,10 @@
<artifactId>redisson</artifactId> <artifactId>redisson</artifactId>
<version>3.26.1</version> <version>3.26.1</version>
</dependency> </dependency>
<!-- pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.github.pagehelper.PageInterceptor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -23,7 +24,9 @@ public class MybatisPlusConfig {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件 // 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(100L);// ? 设置最大分页为100
interceptor.addInnerInterceptor(paginationInnerInterceptor);
// 乐观锁 // 乐观锁
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 防止全表删除 // 防止全表删除
@ -31,4 +34,9 @@ public class MybatisPlusConfig {
return interceptor; return interceptor;
} }
@Bean// pagehelper分页插件需要配的拦截器
public PageInterceptor pageInterceptor() {
return new PageInterceptor();
}
} }

View File

@ -63,14 +63,12 @@ public class RedisConfiguration {
log.info("RedisConfiguration===>解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题"); log.info("RedisConfiguration===>解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题");
// 配置序列化 // 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer()))
.entryTtl(Duration.ofDays(365)); .entryTtl(Duration.ofDays(30));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory) return RedisCacheManager.builder(factory).cacheDefaults(config).build();
.cacheDefaults(config).build();
return cacheManager;
} }
/** /**

View File

@ -3,8 +3,8 @@ package cn.bunny.common.service.context;
public class BaseContext { public class BaseContext {
private static final ThreadLocal<Long> userId = new ThreadLocal<>(); private static final ThreadLocal<Long> userId = new ThreadLocal<>();
private static final ThreadLocal<String> username = new ThreadLocal<String>(); private static final ThreadLocal<String> username = new ThreadLocal<String>();
private static final ThreadLocal<Long> wareId = new ThreadLocal<>();
private static final ThreadLocal<Long> adminId = new ThreadLocal<>(); private static final ThreadLocal<Long> adminId = new ThreadLocal<>();
private static final ThreadLocal<String> adminName = new ThreadLocal<>();
// 用户id相关 // 用户id相关
public static Long getUserId() { public static Long getUserId() {
@ -15,10 +15,6 @@ public class BaseContext {
userId.set(_userId); userId.set(_userId);
} }
public static void removeUserId() {
userId.remove();
}
public static String getUsername() { public static String getUsername() {
return username.get(); return username.get();
} }
@ -27,6 +23,11 @@ public class BaseContext {
username.set(_username); username.set(_username);
} }
public static void removeUser() {
username.remove();
userId.remove();
}
// adminId 相关 // adminId 相关
public static Long getAdminId() { public static Long getAdminId() {
return adminId.get(); return adminId.get();
@ -36,7 +37,16 @@ public class BaseContext {
adminId.set(_adminId); adminId.set(_adminId);
} }
public static void removeAdminId() { public static String getAdminName() {
return adminName.get();
}
public static void setAdminName(String _adminName) {
adminName.set(_adminName);
}
public static void removeAdmin() {
adminName.remove();
adminId.remove(); adminId.remove();
} }
} }

View File

@ -1,6 +1,6 @@
package cn.bunny.common.service.exception; package cn.bunny.common.service.exception;
import cn.bunny.common.result.enums.ResultCodeEnum; import cn.bunny.result.ResultCodeEnum;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString; import lombok.ToString;

View File

@ -1,8 +1,9 @@
package cn.bunny.common.service.exception; package cn.bunny.common.service.exception;
import cn.bunny.common.result.constant.CommonMessageConstant;
import cn.bunny.common.result.enums.ResultCodeEnum; import cn.bunny.result.Result;
import cn.bunny.common.result.utils.Result; import cn.bunny.result.ResultCodeEnum;
import cn.bunny.result.constant.ExceptionConstant;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -58,7 +59,7 @@ public class GlobalExceptionHandler {
public Result<String> error(AccessDeniedException exception) throws AccessDeniedException { public Result<String> error(AccessDeniedException exception) throws AccessDeniedException {
log.error("GlobalExceptionHandler===>spring security异常{}", exception.getMessage()); log.error("GlobalExceptionHandler===>spring security异常{}", exception.getMessage());
return Result.error(ResultCodeEnum.PERMISSION); return Result.error(ResultCodeEnum.SERVICE_ERROR);
} }
// 处理SQL异常 // 处理SQL异常
@ -72,10 +73,10 @@ public class GlobalExceptionHandler {
// 截取用户名 // 截取用户名
String username = message.split(" ")[2]; String username = message.split(" ")[2];
// 错误信息 // 错误信息
String errorMessage = username + CommonMessageConstant.ALREADY_EXISTS; String errorMessage = username + ExceptionConstant.ALREADY_USER_Exception;
return Result.error(errorMessage); return Result.error(errorMessage);
} else { } else {
return Result.error(CommonMessageConstant.UNKNOWN_ERROR); return Result.error(ExceptionConstant.UNKNOWN_Exception);
} }
} }
} }

View File

@ -25,10 +25,11 @@ public class JwtHelper {
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody(); Claims claims = claimsJws.getBody();
return (Long) claims.get("userId");
return Long.valueOf(String.valueOf(claims.get("userId")));
} }
public static String getUserName(String token) { public static String getUsername(String token) {
if (!StringUtils.hasText(token)) return ""; if (!StringUtils.hasText(token)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
@ -44,6 +45,6 @@ public class JwtHelper {
String token = JwtHelper.createToken(7L, "admin", 7); String token = JwtHelper.createToken(7L, "admin", 7);
// token = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_6tWKi5NUrJScirNy6vUDQ12DVLSUUqtKFCyMjQ3MTc0NrYwNddRKi1OLfJMUbKyNDIwNLQwMDAzg4j5JeamAjUbGhtaWhoYGJqaOBQW6iXn5yrVAgCrO9jLWAAAAA.DS1wYprXGoIMrjtUWfDSN9AG5gWoRZ17oAgcvC0kwag"; // token = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_6tWKi5NUrJScirNy6vUDQ12DVLSUUqtKFCyMjQ3MTc0NrYwNddRKi1OLfJMUbKyNDIwNLQwMDAzg4j5JeamAjUbGhtaWhoYGJqaOBQW6iXn5yrVAgCrO9jLWAAAAA.DS1wYprXGoIMrjtUWfDSN9AG5gWoRZ17oAgcvC0kwag";
System.out.println(JwtHelper.getUserId(token)); System.out.println(JwtHelper.getUserId(token));
System.out.println(JwtHelper.getUserName(token)); System.out.println(JwtHelper.getUsername(token));
} }
} }

View File

@ -1,6 +1,6 @@
package cn.bunny.common.service.utils; package cn.bunny.common.service.utils;
import cn.bunny.common.result.utils.Result; import cn.bunny.result.Result;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>cn.bunny</groupId> <groupId>cn.bunny</groupId>
<artifactId>bunny-template-mirror-server</artifactId> <artifactId>bunny-mirror-server</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
@ -42,6 +42,12 @@
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency> </dependency>
<!-- 实体类注解 -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.14</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,22 @@
package cn.bunny.dto.article;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Objects;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoadArticleListDto {
private Integer pBoardId;
private Integer boardId;
private Integer orderType = 1;
public void getOrderType(Integer orderType) {
this.orderType = Objects.requireNonNullElse(orderType, 1);
}
}

View File

@ -0,0 +1,15 @@
package cn.bunny.dto.article;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoadUserArticleDto {
private Long userId;
private Integer type;
}

View File

@ -0,0 +1,19 @@
package cn.bunny.dto.common;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class CommentPostDto {
private String articleId;
private Integer pCommentId;
private String content;
private MultipartFile image;
private Long replyUserId;
}

View File

@ -0,0 +1,16 @@
package cn.bunny.dto.common;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class CommentQueryDto {
private String articleId;
// time 时间查询goods 点赞数量
private String orderType;
}

View File

@ -0,0 +1,15 @@
package cn.bunny.dto.common;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class QueryTopTypeDto {
private Long commentId;
private Integer topType;
}

View File

@ -0,0 +1,21 @@
package cn.bunny.dto.email;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class EmailTemplateDto {
// 模板名称
private String templateName;
// 主题
private String subject;
// 邮件内容
private String body;
// 邮件类型
private String type;
}

View File

@ -0,0 +1,30 @@
package cn.bunny.dto.email;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 添加邮箱用户
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class EmailUsersDto {
// 修改时需要传
private Long id;
// 邮箱
private String email;
// 密码
private String password;
// SMTP服务器
private String host;
// 端口号
private Integer port;
// 邮箱协议
private Integer smtpAgreement;
// 是否为默认邮件
private Boolean isDefault;
}

View File

@ -1,4 +1,4 @@
package cn.bunny.dto; package cn.bunny.dto.user;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@ -10,7 +10,10 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
@Builder @Builder
public class LoginDto { public class LoginDto {
// 用户名
private String username; private String username;
// 密码 // 密码
private String password; private String password;
// 邮箱验证码
private String emailCode;
} }

View File

@ -0,0 +1,17 @@
package cn.bunny.dto.user;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class RegisterDto {
private String email;
private String nickName;
private String password;
private String code;
}

View File

@ -0,0 +1,16 @@
package cn.bunny.dto.user;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ResetPwdDto {
private String email;
private String password;
private String emailCode;
}

View File

@ -0,0 +1,22 @@
package cn.bunny.dto.user;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
/**
* 修改用户信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserInfoDto {
private String nickName;
private String password;
private MultipartFile avatar;
private Integer sex;
private String personDescription;
}

View File

@ -0,0 +1,15 @@
package cn.bunny.dto.user;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserIntegralRecordDto {
private String startDate;
private String endDate;
}

View File

@ -0,0 +1,14 @@
package cn.bunny.dto.user;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserMessageDto {
private String type;
}

View File

@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
@ -15,19 +15,26 @@ import java.util.Map;
@Data @Data
public class BaseEntity implements Serializable { public class BaseEntity implements Serializable {
@TableId(type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID)
@Schema(description = "唯一标识") @ApiModelProperty("唯一标识")
private Long id; private Long id;
@TableField("create_time") @TableField("create_time")
@ApiModelProperty("创建时间")
private Date createTime; private Date createTime;
@TableField("update_time") @TableField("update_time")
@ApiModelProperty("更新时间")
private Date updateTime; private Date updateTime;
@TableField("update_user")
@ApiModelProperty("操作用户ID")
private Long updateUser;
@TableLogic @TableLogic
@TableField("is_deleted") @TableField("is_deleted")
private Integer isDeleted; @ApiModelProperty("是否被删除")
private Boolean isDeleted;
@TableField(exist = false) @TableField(exist = false)
private Map<String, Object> param = new HashMap<>(); private Map<String, Object> param = new HashMap<>();

View File

@ -1,68 +0,0 @@
package cn.bunny.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 用户信息
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Getter
@Setter
@Accessors(chain = true)
@Schema(description = "用户信息")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "用户ID")
@TableId(value = "user_id", type = IdType.AUTO)
private String userId;
@Schema(description = "昵称")
private String nickName;
@Schema(description = "邮箱")
private String email;
@Schema(description = "密码")
private String password;
@Schema(description = "0:女 1:男")
private Integer sex;
@Schema(description = "个人描述")
private String personDescription;
@Schema(description = "加入时间")
private LocalDateTime joinTime;
@Schema(description = "最后登录时间")
private LocalDateTime lastLoginTime;
@Schema(description = "最后登录IP")
private String lastLoginIp;
@Schema(description = "最后登录ip地址")
private String lastLoginIpAddress;
@Schema(description = "积分")
private Integer totalIntegral;
@Schema(description = "当前积分")
private Integer currentIntegral;
@Schema(description = "0:禁用 1:正常")
private Byte status;
}

View File

@ -1,46 +0,0 @@
package cn.bunny.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 用户积分记录表
* </p>
*
* @author Bunny
* @since 2024-05-13
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("user_integral_record")
@Schema(description = "用户积分记录表")
public class UserIntegralRecord implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "记录ID")
@TableId(value = "record_id", type = IdType.AUTO)
private Integer recordId;
@Schema(description = "用户ID")
private String userId;
@Schema(description = "操作类型")
private Byte operType;
@Schema(description = "积分")
private Integer integral;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,58 @@
package cn.bunny.entity.system.admin;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
*
* </p>
*
* @author Bunny
* @since 2024-05-18
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("admin_power")
@ApiModel(value = "AdminPower对象", description = "")
public class AdminPower implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("权限ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("权限名称")
private String powerName;
@ApiModelProperty("权限编码")
private String powerCode;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("更新用户")
private String updateUser;
@ApiModelProperty("是否删除0-未删除1-已删除")
private Byte isDelete;
}

View File

@ -1,9 +1,10 @@
package cn.bunny.entity.system; package cn.bunny.entity.system.admin;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -17,31 +18,38 @@ import java.time.LocalDateTime;
* </p> * </p>
* *
* @author Bunny * @author Bunny
* @since 2024-05-13 * @since 2024-05-18
*/ */
@Getter @Getter
@Setter @Setter
@Accessors(chain = true) @Accessors(chain = true)
@TableName("user_role") @TableName("admin_role")
@Schema(description = "UserRole对象") @ApiModel(value = "AdminRole对象", description = "")
public class UserRole implements Serializable { public class AdminRole implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private String id; private String id;
private String userId; @ApiModelProperty("角色名称")
private String roleName; private String roleName;
@ApiModelProperty("描述")
private String description; private String description;
@ApiModelProperty("角色代码")
private String roleCode; private String roleCode;
@Schema(description = "创建时间") @ApiModelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "更新时间") @ApiModelProperty("更新时间")
private LocalDateTime updateTime; private LocalDateTime updateTime;
@ApiModelProperty("操作用户")
private String updateUser;
@ApiModelProperty("是否删除")
private Byte isDeleted;
} }

View File

@ -0,0 +1,56 @@
package cn.bunny.entity.system.admin;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
*
* </p>
*
* @author Bunny
* @since 2024-05-18
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("admin_role_power")
@ApiModel(value = "AdminRolePower对象", description = "")
public class AdminRolePower implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("ID")
@TableId(value = "id", type = IdType.AUTO)
private String id;
@ApiModelProperty("角色id")
private String roleId;
@ApiModelProperty("权限id")
private String powerId;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("更新用户")
private String updateUser;
@ApiModelProperty("是否删除0-未删除1-已删除")
private Byte isDelete;
}

View File

@ -0,0 +1,56 @@
package cn.bunny.entity.system.admin;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
*
* </p>
*
* @author Bunny
* @since 2024-05-18
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("admin_user_role")
@ApiModel(value = "AdminUserRole对象", description = "")
public class AdminUserRole implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("ID")
@TableId(value = "id", type = IdType.AUTO)
private String id;
@ApiModelProperty("用户id")
private String userId;
@ApiModelProperty("角色id")
private String roleId;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("更新用户")
private String updateUser;
@ApiModelProperty("是否删除0-未删除1-已删除")
private Byte isDelete;
}

View File

@ -0,0 +1,21 @@
package cn.bunny.entity.system.admin.auth;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AuthUserRole {
// 用户id
private Long userId;
// 角色id
private Long roleId;
// 角色代码
private String roleCode;
// 描述
private String roleDescription;
}

View File

@ -0,0 +1,83 @@
package cn.bunny.entity.system.article;
import cn.bunny.entity.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 文章信息
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@Getter
@Setter
@Accessors(chain = true)
@ApiModel(value = "Article对象", description = "文章信息")
public class Article extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("板块ID")
private Integer boardId;
@ApiModelProperty("板块名称")
private String boardName;
@ApiModelProperty("父级板块ID")
private Integer pBoardId;
@ApiModelProperty("父板块名称")
private String pBoardName;
@ApiModelProperty("用户ID")
private Long userId;
@ApiModelProperty("昵称")
private String nickName;
@ApiModelProperty("最后登录ip地址")
private String userIpAddress;
@ApiModelProperty("标题")
private String title;
@ApiModelProperty("封面")
private String cover;
@ApiModelProperty("内容")
private String content;
@ApiModelProperty("0:富文本编辑器 1:markdown编辑器")
private Byte editorType;
@ApiModelProperty("摘要")
private String summary;
@ApiModelProperty("阅读数量")
private Integer readCount;
@ApiModelProperty("点赞数")
private Integer goodCount;
@ApiModelProperty("评论数")
private Integer commentCount;
@ApiModelProperty("0未置顶 1:已置顶")
private Byte topType;
@ApiModelProperty("0:没有附件 1:有附件")
private Byte attachmentType;
@ApiModelProperty("-1已删除 0:待审核 1:已审核 ")
private Byte status;
}

View File

@ -0,0 +1,67 @@
package cn.bunny.entity.system.article;
import cn.bunny.entity.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 评论
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("forum_comment")
@ApiModel(value = "ForumComment对象", description = "评论")
public class ForumComment extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("父级评论ID")
private Long pCommentId;
@ApiModelProperty("文章ID")
private String articleId;
@ApiModelProperty("回复内容")
private String content;
@ApiModelProperty("图片")
private String imgPath;
@ApiModelProperty("用户ID")
private Long userId;
@ApiModelProperty("昵称")
private String nickName;
@ApiModelProperty("用户ip地址")
private String userIpAddress;
@ApiModelProperty("回复人ID")
private Long replyUserId;
@ApiModelProperty("回复人昵称")
private String replyNickName;
@ApiModelProperty("0:未置顶 1:置顶")
private Integer topType;
@ApiModelProperty("good数量")
private Integer goodCount;
@ApiModelProperty("0:待审核 1:已审核")
private Integer status;
}

View File

@ -0,0 +1,40 @@
package cn.bunny.entity.system.article;
import cn.bunny.entity.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 用户积分记录表
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("integral_record")
@ApiModel(value = "IntegralRecord对象", description = "用户积分记录表")
public class IntegralRecord extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("用户ID")
private Long userId;
@ApiModelProperty("操作类型")
private Byte operType;
@ApiModelProperty("积分")
private Integer integral;
}

View File

@ -0,0 +1,43 @@
package cn.bunny.entity.system.article;
import cn.bunny.entity.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 点赞记录
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("like_record")
@ApiModel(value = "LikeRecord对象", description = "点赞记录")
public class LikeRecord extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("操作类型0:文章点赞 1:评论点赞")
private Byte opType;
@ApiModelProperty("主体ID")
private String objectId;
@ApiModelProperty("用户ID")
private Long userId;
@ApiModelProperty("主体作者ID")
private Long authorUserId;
}

View File

@ -0,0 +1,49 @@
package cn.bunny.entity.system.board;
import cn.bunny.entity.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 文章板块信息
* </p>
*
* @author Bunny
* @since 2024-05-19
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("forum_board")
@ApiModel(value = "ForumBoard对象", description = "文章板块信息")
public class ForumBoard extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("父级板块ID")
private Long parentId;
@ApiModelProperty("板块名")
private String boardName;
@ApiModelProperty("封面")
private String cover;
@ApiModelProperty("描述")
private String boardDesc;
@ApiModelProperty("排序")
private Integer sort;
@ApiModelProperty("0:只允许管理员发帖 1:任何人可以发帖")
private Boolean postType;
}

View File

@ -1,4 +1,4 @@
package cn.bunny.entity.email; package cn.bunny.entity.system.email;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;

View File

@ -1,4 +1,4 @@
package cn.bunny.entity.email; package cn.bunny.entity.system.email;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;

View File

@ -0,0 +1,42 @@
package cn.bunny.entity.system.email;
import cn.bunny.entity.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author Bunny
* @since 2024-05-19
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("email_template")
@ApiModel(value = "EmailTemplate对象", description = "邮件模板")
public class EmailTemplate extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("模板名称")
private String templateName;
@ApiModelProperty("主题")
private String subject;
@ApiModelProperty("邮件内容")
private String body;
@ApiModelProperty("邮件类型")
private String type;
}

View File

@ -0,0 +1,49 @@
package cn.bunny.entity.system.email;
import cn.bunny.entity.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 邮箱发送表
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("email_users")
@ApiModel(value = "EmailUsers对象", description = "邮箱发送表")
public class EmailUsers extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("邮箱")
private String email;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("Host地址")
private String host;
@ApiModelProperty("端口号")
private Integer port;
@ApiModelProperty("邮箱协议")
private String smtpAgreement;
@ApiModelProperty("是否为默认邮件")
private Integer isDefault;
}

View File

@ -0,0 +1,50 @@
package cn.bunny.entity.system.file;
import cn.bunny.entity.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 用于存储文件信息的数据表
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@Getter
@Setter
@Accessors(chain = true)
@ApiModel(value = "Files对象", description = "用于存储文件信息的数据表")
public class Files extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("文章ID")
private Long articleId;
@ApiModelProperty("文件的名称")
private String filename;
@ApiModelProperty("文件在服务器上的存储路径")
private String filepath;
@ApiModelProperty("文件的大小,以字节为单位")
private Long fileSize;
@ApiModelProperty("文件的MIME类型")
private String fileType;
@ApiModelProperty("创建用户")
private Long createUser;
@ApiModelProperty("下载次数")
private Integer downloadCount;
}

View File

@ -0,0 +1,61 @@
package cn.bunny.entity.system.user;
import cn.bunny.entity.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 用户信息
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@ApiModel(value = "User对象", description = "用户信息")
public class User extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("昵称")
private String nickName;
@ApiModelProperty("邮箱")
private String email;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("头像")
private String avatar;
@ApiModelProperty("0:女 1:男")
private Byte sex;
@ApiModelProperty("个人描述")
private String personDescription;
@ApiModelProperty("加入时间")
private LocalDateTime joinTime;
@ApiModelProperty("最后登录时间")
private LocalDateTime lastLoginTime;
@ApiModelProperty("最后登录IP")
private String lastLoginIp;
@ApiModelProperty("最后登录ip地址")
private String lastLoginIpAddress;
@ApiModelProperty("积分")
private Integer totalIntegral;
@ApiModelProperty("当前积分")
private Integer currentIntegral;
@ApiModelProperty("0:禁用 1:正常")
private Byte status;
}

View File

@ -0,0 +1,58 @@
package cn.bunny.entity.system.user;
import cn.bunny.entity.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* <p>
* 用户消息
* </p>
*
* @author Bunny
* @since 2024-05-17
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("user_message")
@ApiModel(value = "UserMessage对象", description = "用户消息")
public class UserMessage extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ApiModelProperty("接收人用户ID")
private Long receivedUserId;
@ApiModelProperty("文章ID")
private String articleId;
@ApiModelProperty("文章标题")
private String articleTitle;
@ApiModelProperty("评论ID")
private Integer commentId;
@ApiModelProperty("发送人用户ID")
private Long sendUserId;
@ApiModelProperty("发送人昵称")
private String sendNickName;
@ApiModelProperty("sys:系统消息 reply:评论 likePost:文章点赞 likeComment:评论点赞 attachment:附件下载")
private String messageType;
@ApiModelProperty("消息内容")
private String messageContent;
@ApiModelProperty("1:未读 2:已读")
private Byte status;
}

View File

@ -1,6 +1,5 @@
package cn.bunny.common.result.utils; package cn.bunny.result;
import cn.bunny.common.result.enums.ResultCodeEnum;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -64,7 +63,7 @@ public class Result<T> {
* @return Result<T> * @return Result<T>
*/ */
public static <T> Result<T> success() { public static <T> Result<T> success() {
return Result.success(null, ResultCodeEnum.SUCCESS); return success(null, ResultCodeEnum.SUCCESS);
} }
/** /**

View File

@ -0,0 +1,54 @@
package cn.bunny.result;
import lombok.Getter;
/**
* 统一返回结果状态信息类
*/
@Getter
public enum ResultCodeEnum {
// 成功操作 200
SUCCESS(200, "操作成功"),
SUCCESS_LOGOUT(200, "退出成功"),
EMAIL_CODE_REFRESH(200, "邮箱验证码已刷新"),
// 验证错误 201
USERNAME_NOT_EMPTY(201, "用户名不能为空"),
PASSWORD_NOT_EMPTY(201, "密码不能为空"),
EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"),
SEND_EMAIL_CODE_NOT_EMPTY(201, "请先发送邮箱验证码"),
EMAIL_CODE_NOT_MATCHING(201, "邮箱验证码不匹配"),
LOGIN_ERROR(201, "账号或密码错误"),
LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY(201, "登录信息不能为空"),
// 数据相关 206
ILLEGAL_REQUEST(206, "非法请求"),
REPEAT_SUBMIT(206, "重复提交"),
DATA_ERROR(206, "数据异常"),
// 身份过期 208
LOGIN_AUTH(208, "请先登陆"),
AUTHENTICATION_EXPIRED(208, "身份验证过期"),
SESSION_EXPIRATION(208, "会话过期"),
// 封禁 209
FAIL_NO_ACCESS_DENIED_USER_LOCKED(209, "该账户被封禁"),
THE_SAME_USER_HAS_LOGGED_IN(209, "相同用户已登录"),
// 提示错误
URL_ENCODE_ERROR(216, "URL编码失败"),
ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"),
FETCH_USERINFO_ERROR(219, "获取用户信息失败"),
// 无权访问 403
FAIL_REQUEST_NOT_AUTH(403, "用户未认证"),
FAIL_NO_ACCESS_DENIED(403, "无权访问"),
FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"),
LOGGED_IN_FROM_ANOTHER_DEVICE(403, "没有权限访问"),
// 系统错误 500
SERVICE_ERROR(500, "服务异常"),
FAIL(500, "失败"),
;
private final Integer code;
private final String message;
ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,52 @@
package cn.bunny.result.constant;
import lombok.Data;
@Data
public class ExceptionConstant {
public static final String UNKNOWN_Exception = "未知错误";
public static final String TOKEN_IS_EMPTY = "token为空";
public static final String DATA_IS_EMPTY = "数据为空";
public static final String REQUEST_DATA_NOT_EMPTY_Exception = "请求参数为空";
public static final String UPDATE_DTO_IS_NULL_Exception = "修改参数为空";
public static final String ADD_DATA_IS_EMPTY_Exception = "添加数据为空";
public static final String DELETE_ID_IS_NOT_EMPTY_Exception = "删除id不能为空";
// 文章操作相关
public static final String DO_LIKE_COMMENT_NOT_EXIST = "点赞内容不存在";
public static final String REPLY_USER_EMPTY_EXCEPTION = "回复的用户不存在";
public static final String REPLY_USER_ID_EMPTY_EXCEPTION = "回复的用户不能为空";
public static final String MENU_IS_NOT_EXIST_Exception = "菜单不存在";
public static final String POST_COMMENT_EMPTY_Exception = "评论内容不能为空";
public static final String ARTICLE_ID_NOT_EMPTY_Exception = "文章id不能为空";
public static final String UPDATE_ID_IS_NOT_EMPTY_Exception = "修改id不能为空";
public static final String CANNOT_TOP_OTHER_USER = "不能操作此内容";
public static final String ARTICLE_NOT_FOUND_EXCEPTION = "文章未找到";
// 登录相关
public static final String USER_TOKEN_OUT_OF_DATE_Exception = "用户登录过期";
public static final String LOGIN_DTO_IS_EMPTY_Exception = "登录参数不能为空";
public static final String LOGIN_FAILED_Exception = "登录失败";
// 账号相关
public static final String ACCOUNT_NOT_FOUND_Exception = "账号不存在";
public static final String ACCOUNT_LOCKED_Exception = "账号被锁定";
// 用户相关
public static final String USER_NOT_LOGIN_Exception = "用户未登录";
public static final String USERNAME_IS_EMPTY_Exception = "用户名不能为空";
public static final String ALREADY_USER_Exception = "用户已存在";
public static final String USER_NOT_FOUND_Exception = "用户不存在";
// 密码相关
public static final String PASSWORD_Exception = "密码错误";
public static final String PASSWORD_NOT_EMPTY_Exception = "密码不能为空";
public static final String OLD_PASSWORD_Exception = "旧密码不匹配";
public static final String PASSWORD_EDIT_Exception = "密码修改失败";
public static final String OLD_PASSWORD_SAME_NEW_PASSWORD_Exception = "旧密码与新密码相同";
// 验证码错误
public static final String PLEASE_SEND_EMAIL_CODE_Exception = "请先发送验证码";
public static final String MESSAGE_CODE_NOT_PASS_Exception = "短信验证码未过期";
public static final String MESSAGE_CODE_UNAUTHORIZED_Exception = "短信验证码未授权,请联系管理员";
public static final String VERIFICATION_CODE_ERROR_Exception = "验证码错误";
public static final String CAPTCHA_IS_EMPTY_Exception = "验证码不能为空";
public static final String KEY_IS_EMPTY_Exception = "验证码key不能为空";
public static final String VERIFICATION_CODE_DOES_NOT_MATCH_Exception = "验证码不匹配";
public static final String VERIFICATION_CODE_IS_EMPTY_Exception = "验证码失效或不存在";
}

View File

@ -1,11 +1,15 @@
package cn.bunny.common.result.constant; package cn.bunny.result.constant;
import lombok.Data; import lombok.Data;
@Data @Data
public class MinioMessageConstant { public class FileMessageConstant {
public static final String DOWNLOAD_BUCKET_EXCEPTION = "下载文件失败";
public static final String FILE_UPLOAD_EXCEPTION = "文件上传失败";
public static final String BUCKET_EXISTS_EXCEPTION = "查询文化部对象失败"; public static final String BUCKET_EXISTS_EXCEPTION = "查询文化部对象失败";
public static final String DELETE_BUCKET_EXCEPTION = "删除文件对象失败"; public static final String DELETE_BUCKET_EXCEPTION = "删除文件对象失败";
public static final String FILE_IS_EMPTY = "文件信息为空";
public static final String FILE_IS_NOT_EXITS = "文件信息为空";
public static final String GET_BUCKET_EXCEPTION = "获取文件信息失败"; public static final String GET_BUCKET_EXCEPTION = "获取文件信息失败";
public static final String QUERY_BUCKET_EXCEPTION = "查询文件信息失败"; public static final String QUERY_BUCKET_EXCEPTION = "查询文件信息失败";
public static final String CREATE_BUCKET_EXCEPTION = "创建文件对象失败"; public static final String CREATE_BUCKET_EXCEPTION = "创建文件对象失败";
@ -14,6 +18,4 @@ public class MinioMessageConstant {
public static final String COPY_BUCKET_EXCEPTION = "复制文件内容失败"; public static final String COPY_BUCKET_EXCEPTION = "复制文件内容失败";
public static final String DISABLE_BUCKET_EXCEPTION = "禁用文件失败"; public static final String DISABLE_BUCKET_EXCEPTION = "禁用文件失败";
public static final String ENABLE_BUCKET_EXCEPTION = "启用文件失败"; public static final String ENABLE_BUCKET_EXCEPTION = "启用文件失败";
public static final String DOWNLOAD_BUCKET_EXCEPTION = "下载文件失败";
public static final String UPLOAD_BUCKET_EXCEPTION = "上传文件失败";
} }

View File

@ -1,4 +1,4 @@
package cn.bunny.common.result.constant; package cn.bunny.result.constant;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package cn.bunny.common.result.constant; package cn.bunny.result.constant;
import lombok.Data; import lombok.Data;
@ -11,4 +11,5 @@ public class MailMessageConstant {
public static final String ADDRESS_NOT_NULL = "收件人不能为空"; public static final String ADDRESS_NOT_NULL = "收件人不能为空";
public static final String TITLE_NOT_NULL = "标题不能为空"; public static final String TITLE_NOT_NULL = "标题不能为空";
public static final String SEND_MESSAGE_NOT_NULL = "发送消息不能为空"; public static final String SEND_MESSAGE_NOT_NULL = "发送消息不能为空";
public static final String EMAIL_CONFIG_NOT_FOUND = "邮箱配置为空";
} }

View File

@ -0,0 +1,67 @@
package cn.bunny.result.constant;
import lombok.Data;
/**
* Redis用户前缀设置
*/
@Data
public class RedisUserConstant {
// 管理员用户
public static final String ADMIN_LOGIN_INFO_PREFIX = "ADMIN::LOGIN_INFO::";
public static final String ADMIN_EMAIL_CODE_PREFIX = "ADMIN::EMAIL_CODE::";
// 普通用户
public static final String USER_LOGIN_INFO_PREFIX = "USER::LOGIN_INFO::";
public static final String USER_EMAIL_CODE_PREFIX = "USER::EMAIL_CODE::";
public static final String USER_DO_LIKE_PREFIX = "USER::doLike::";
/**
* * 管理员用户登录信息
*
* @param adminUser 管理员用户
* @return 登录信息key
*/
public static String getAdminLoginInfoPrefix(String adminUser) {
return ADMIN_LOGIN_INFO_PREFIX + adminUser;
}
/**
* * 管理员用户邮箱验证码
*
* @param adminUser 管理员用户
* @return 管理员用户邮箱验证码key
*/
public static String getAdminUserEmailCodePrefix(String adminUser) {
return ADMIN_EMAIL_CODE_PREFIX + adminUser;
}
/**
* * 用户登录信息
*
* @param user 用户名
* @return 登录信息key
*/
public static String getUserLoginInfoPrefix(String user) {
return USER_LOGIN_INFO_PREFIX + user;
}
/**
* * 用户邮箱验证码
*
* @param user 用户名
* @return 用户邮箱验证码key
*/
public static String getUserEmailCodePrefix(String user) {
return USER_EMAIL_CODE_PREFIX + user;
}
/**
* * 用户点赞操作
*
* @param user 用户名
* @return 用户点赞key
*/
public static String getUserDoLikePrefix(String user) {
return USER_DO_LIKE_PREFIX + user;
}
}

View File

@ -1,4 +1,4 @@
package cn.bunny.common.result.constant; package cn.bunny.result.constant;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package cn.bunny.common.result.constant; package cn.bunny.result.constant;
import lombok.Data; import lombok.Data;
@ -7,6 +7,7 @@ import java.util.List;
@Data @Data
public class SecurityConstant { public class SecurityConstant {
public static String[] annotations = {"/", "/test/**", "/diagram-viewer/**", "/editor-app/**", "/*.html", "/admin/system/index/login", "/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v3/**", "/swagger-ui.html/**", "/doc.html"}; public static String[] annotations = {"/", "/test/**", "/diagram-viewer/**", "/editor-app/**", "/*.html",
"/*/*/noAuth/**", "/*/noAuth/**", "/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v3/**", "/swagger-ui.html/**", "/doc.html"};
public static List<String> annotationsList = Arrays.asList(annotations); public static List<String> annotationsList = Arrays.asList(annotations);
} }

View File

@ -1,4 +1,4 @@
package cn.bunny.common.result.constant; package cn.bunny.result.constant;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package cn.bunny.common.result.constant; package cn.bunny.result.constant;
import lombok.Data; import lombok.Data;

View File

@ -0,0 +1,11 @@
package cn.bunny.tree;
import java.util.List;
public interface AbstractTreeNode {
Long getId();
Long getParentId();
void setChildren(List<? extends AbstractTreeNode> children);
}

View File

@ -0,0 +1,29 @@
package cn.bunny.tree;
import java.util.ArrayList;
import java.util.List;
public class TreeBuilder<T extends AbstractTreeNode> {
public List<T> buildTree(List<T> nodeList) {
List<T> tree = new ArrayList<>();
for (T node : nodeList) {
if (node.getParentId() == 0) {
node.setChildren(getChildren(node.getId(), nodeList));
tree.add(node);
}
}
return tree;
}
private List<T> getChildren(Long nodeId, List<T> nodeList) {
List<T> children = new ArrayList<>();
for (T node : nodeList) {
if (node.getParentId().equals(nodeId)) {
node.setChildren(getChildren(node.getId(), nodeList));
children.add(node);
}
}
return children;
}
}

View File

@ -0,0 +1,19 @@
package cn.bunny.vo.email;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class EmailTemplateVo {
// 模板名称
private String templateName;
// 主题
private String subject;
// 邮件内容
private String body;
}

View File

@ -0,0 +1,32 @@
package cn.bunny.vo.file;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 返回文件信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class FileInfoVo {
private Long id;
// 文章Id
private Long articleId;
// 文件的名称
private String filename;
// 文件在服务器上的存储路径
private String filepath;
// 文件的大小以字节为单位
private Long fileSize;
// 文件大小
private String size;
// 文件的MIME类型
private String fileType;
// 上传人昵称
private String uploadNickname;
private Integer downloadCount;
}

View File

@ -0,0 +1,27 @@
package cn.bunny.vo.page;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 封装分页查询结果
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class PageResult<T> implements Serializable {
// 当前页
private Integer pageNo;
// 每页记录数
private Integer pageSize;
// 总记录数
private long total;
// 当前页数据集合
private List<T> list;
}

View File

@ -1,34 +0,0 @@
package cn.bunny.vo.system;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 用户登录返回内容
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginVo {
private String userId;
private String nickName;
private String email;
private Integer sex;
private String personDescription;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime joinTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime lastLoginTime;
private String lastLoginIp;
private String lastLoginIpAddress;
private Integer totalIntegral;
private Integer currentIntegral;
private Byte status;
private String token;
}

View File

@ -0,0 +1,70 @@
package cn.bunny.vo.system.article;
import cn.bunny.vo.file.FileInfoVo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ForumArticleVo {
// 文章ID
private Long id;
// 板块ID
private Integer boardId;
// 父级板块ID
private Integer pBoardId;
// 板块名称
private String boardName;
// 父板块名称
private String pBoardName;
// 用户ID
private String userId;
// 昵称
private String nickName;
// 最后登录ip地址
private String userIpAddress;
// 标题
private String title;
// 封面
private String cover;
// 内容
private String content;
// 0:富文本编辑器 1:markdown编辑器
private Byte editorType;
// 摘要
private String summary;
// 发布时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private String createTime;
// 最后更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private String updateTime;
// 阅读数量
private Integer readCount;
// 点赞数
private Integer goodCount;
// 评论数
private Integer commentCount;
// 0未置顶 1:已置顶
private Byte topType;
// 0:没有附件 1:有附件
private Byte attachmentType;
// -1已删除 0:待审核 1:已审核
private Byte status;
private List<FileInfoVo> fileInfo;
}

View File

@ -0,0 +1,29 @@
package cn.bunny.vo.system.board;
import cn.bunny.tree.AbstractTreeNode;
import lombok.Data;
import java.util.List;
@Data
public class ForumBoardVo implements AbstractTreeNode {
private Long id;
// 父级板块ID
private Long parentId;
// 板块名
private String boardName;
// 封面
private String cover;
// 描述
private String boardDesc;
// 排序
private Integer sort;
// 0:只允许管理员发帖 1:任何人可以发帖
private Boolean postType;
private List<ForumBoardVo> children;
@Override
public void setChildren(List<? extends AbstractTreeNode> children) {
this.children = (List<ForumBoardVo>) children;
}
}

View File

@ -0,0 +1,53 @@
package cn.bunny.vo.system.comment;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class CommentVo {
// 评论ID
private Long id;
// 父级评论ID
private Integer pCommentId;
// 文章ID
private String articleId;
// 回复内容
private String content;
// 图片
private String imgPath;
// 用户ID
private Long userId;
// 昵称
private String nickName;
// 用户ip地址
private String userIpAddress;
// 回复人ID
private Long replyUserId;
// 回复人昵称
private String replyNickName;
// 0:未置顶 1:置顶
private Byte topType;
// 发布时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime postTime;
// good数量
private Integer goodCount;
// 0:待审核 1:已审核
private Byte status;
private List<CommentVo> children;
}

View File

@ -0,0 +1,48 @@
package cn.bunny.vo.system.login;
import cn.bunny.result.constant.LocalDateTimeConstant;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
/**
* 用户登录返回内容
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginVo {
private Long id;
private String nickName;
private String email;
private String password;
private String avatar;
private Byte sex;
private String personDescription;
@JsonFormat(pattern = LocalDateTimeConstant.DEFAULT_DATE_TIME_SECOND_FORMAT)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime joinTime;
@JsonFormat(pattern = LocalDateTimeConstant.DEFAULT_DATE_TIME_SECOND_FORMAT)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime lastLoginTime;
private String lastLoginIp;
private String lastLoginIpAddress;
private Integer totalIntegral;
private Integer currentIntegral;
private Byte status;
private String token;
private List<String> roleList;
private List<String> powerList;
}

View File

@ -1,4 +1,4 @@
package cn.bunny.vo.system; package cn.bunny.vo.system.login;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -0,0 +1,43 @@
package cn.bunny.vo.system.user;
import cn.bunny.result.constant.LocalDateTimeConstant;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 获取用户信息返回参数
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserInfoVo {
private Long userId;
private String nickName;
private String email;
private String avatar;
private Byte sex;
private String personDescription;
@JsonFormat(pattern = LocalDateTimeConstant.DEFAULT_DATE_TIME_SECOND_FORMAT)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime joinTime;
@JsonFormat(pattern = LocalDateTimeConstant.DEFAULT_DATE_TIME_SECOND_FORMAT)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime lastLoginTime;
private String lastLoginIp;
private String lastLoginIpAddress;
private Integer totalIntegral;
private Integer currentIntegral;
private Byte status;
}

View File

@ -0,0 +1,33 @@
package cn.bunny.vo.system.user;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserIntegralRecordVo {
// 记录ID
private Integer recordId;
// 用户ID
private String userId;
// 操作类型
private Byte operType;
// 积分
private Integer integral;
// 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,19 @@
package cn.bunny.vo.system.user;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserMessageCountVo {
private Integer total;
private Integer sys;
private Integer reply;
private Integer likePost;
private Integer likeComment;
}

View File

@ -0,0 +1,43 @@
package cn.bunny.vo.system.user;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserMessageVo {
// 自增ID
private Integer messageId;
// 接收人用户ID
private String receivedUserId;
// 文章ID
private String articleId;
// 文章标题
private String articleTitle;
// 评论ID
private Integer commentId;
// 发送人用户ID
private String sendUserId;
// 发送人昵称
private String sendNickName;
// sys:系统消息 reply:评论 likePost:文章点赞 likeComment:评论点赞 attachment:附件下载
private String messageType;
// 消息内容
private String messageContent;
// 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createTime;
}

View File

@ -18,11 +18,6 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId> <artifactId>spring-boot-starter-mail</artifactId>

View File

@ -1,8 +1,8 @@
package cn.bunny.module.mail.utils; package cn.bunny.module.mail.utils;
import cn.bunny.common.result.constant.MailMessageConstant;
import cn.bunny.common.service.utils.EmptyUtil; import cn.bunny.common.service.utils.EmptyUtil;
import cn.bunny.entity.email.EmailSend; import cn.bunny.entity.system.email.EmailSend;
import cn.bunny.result.constant.MailMessageConstant;
public class MailSendCheckUtil { public class MailSendCheckUtil {
/** /**

View File

@ -1,7 +1,7 @@
package cn.bunny.module.mail.utils; package cn.bunny.module.mail.utils;
import cn.bunny.entity.email.EmailSend; import cn.bunny.entity.system.email.EmailSend;
import cn.bunny.entity.email.EmailSendInit; import cn.bunny.entity.system.email.EmailSendInit;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage; import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.SimpleMailMessage;

View File

@ -18,11 +18,6 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- minio --> <!-- minio -->
<dependency> <dependency>
<groupId>io.minio</groupId> <groupId>io.minio</groupId>

View File

@ -1,6 +1,6 @@
package cn.bunny.module.minio.utils; package cn.bunny.module.minio.utils;
import cn.bunny.common.result.constant.MinioMessageConstant; import cn.bunny.result.constant.FileMessageConstant;
import cn.bunny.common.service.exception.BunnyException; import cn.bunny.common.service.exception.BunnyException;
import io.minio.*; import io.minio.*;
import io.minio.messages.*; import io.minio.messages.*;
@ -37,7 +37,7 @@ public class MinioUtil {
log.error("判断桶是否存在 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("判断桶是否存在 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
} }
throw new BunnyException(MinioMessageConstant.BUCKET_EXISTS_EXCEPTION); throw new BunnyException(FileMessageConstant.BUCKET_EXISTS_EXCEPTION);
} }
/** /**
@ -53,7 +53,7 @@ public class MinioUtil {
log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
} }
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
/** /**
@ -68,7 +68,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除桶的生命周期配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶的生命周期配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -84,7 +84,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -100,7 +100,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -116,7 +116,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除桶的桶复制配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶的桶复制配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -132,7 +132,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除桶的桶复制配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶的桶复制配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -148,7 +148,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除桶中的对象锁配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶中的对象锁配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -167,7 +167,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取存储桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取存储桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return conf; return conf;
@ -187,7 +187,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取存储桶的生命周期配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取存储桶的生命周期配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return lifecycle; return lifecycle;
@ -208,7 +208,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取存储桶的通知配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取存储桶的通知配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return configuration; return configuration;
@ -229,7 +229,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取桶的桶策略配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取桶的桶策略配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return config; return config;
@ -250,7 +250,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取桶复制参数 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取桶复制参数 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return configuration; return configuration;
@ -271,7 +271,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取存储桶的标签 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取存储桶的标签 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return tags; return tags;
} }
@ -291,7 +291,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取存储桶的版本控制配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取存储桶的版本控制配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return configuration; return configuration;
@ -311,7 +311,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取存储桶中的对象锁配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取存储桶中的对象锁配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
return configuration; return configuration;
@ -331,7 +331,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("列出所有桶的桶信息 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("列出所有桶的桶信息 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.QUERY_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.QUERY_BUCKET_EXCEPTION);
} }
return buckets; return buckets;
@ -349,7 +349,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("创建桶 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("创建桶 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.CREATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.CREATE_BUCKET_EXCEPTION);
} }
} }
@ -365,7 +365,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("创建桶 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("创建桶 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.CREATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.CREATE_BUCKET_EXCEPTION);
} }
} }
@ -381,7 +381,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("创建桶 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("创建桶 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.CREATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.CREATE_BUCKET_EXCEPTION);
} }
} }
@ -397,7 +397,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除桶 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除桶 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -414,7 +414,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("设置桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("设置桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -431,7 +431,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("查看桶策略 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("查看桶策略 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -449,7 +449,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("设置桶复制参数 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("设置桶复制参数 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -466,7 +466,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("设置/修改桶标签 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("设置/修改桶标签 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -484,7 +484,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("设置桶的版本配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("设置桶的版本配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -501,7 +501,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("对象对象锁定配置 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("对象对象锁定配置 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -519,7 +519,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.COMPOSE_OBJECT_EXCEPTION); throw new BunnyException(FileMessageConstant.COMPOSE_OBJECT_EXCEPTION);
} }
} }
@ -542,7 +542,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.COMPOSE_OBJECT_EXCEPTION); throw new BunnyException(FileMessageConstant.COMPOSE_OBJECT_EXCEPTION);
} }
} }
@ -567,7 +567,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.COMPOSE_OBJECT_EXCEPTION); throw new BunnyException(FileMessageConstant.COMPOSE_OBJECT_EXCEPTION);
} }
} }
@ -590,7 +590,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.COPY_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.COPY_BUCKET_EXCEPTION);
} }
} }
@ -615,7 +615,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.COPY_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.COPY_BUCKET_EXCEPTION);
} }
} }
@ -641,7 +641,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.COPY_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.COPY_BUCKET_EXCEPTION);
} }
} }
@ -658,7 +658,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除对象的标记 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除对象的标记 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -675,7 +675,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("禁用对象 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("禁用对象 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DISABLE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DISABLE_BUCKET_EXCEPTION);
} }
} }
@ -692,7 +692,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("禁用对象 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("禁用对象 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.ENABLE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.ENABLE_BUCKET_EXCEPTION);
} }
} }
@ -710,7 +710,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
} }
@ -728,7 +728,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("下载文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("下载文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DOWNLOAD_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DOWNLOAD_BUCKET_EXCEPTION);
} }
} }
@ -747,7 +747,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("下载文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("下载文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DOWNLOAD_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DOWNLOAD_BUCKET_EXCEPTION);
} }
} }
@ -767,7 +767,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取对象保留 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取对象保留 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DOWNLOAD_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DOWNLOAD_BUCKET_EXCEPTION);
} }
} }
@ -786,7 +786,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取对象标签 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取对象标签 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.GET_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
} }
} }
@ -805,7 +805,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPLOAD_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
} }
} }
@ -825,7 +825,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPLOAD_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
} }
} }
@ -848,7 +848,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPLOAD_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
} }
} }
@ -865,7 +865,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -883,7 +883,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -901,7 +901,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
@ -918,7 +918,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("上传多文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("上传多文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPLOAD_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
} }
} }
@ -937,7 +937,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -955,7 +955,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.UPDATE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
} }
} }
@ -976,7 +976,7 @@ public class MinioUtil {
} catch (Exception exception) { } catch (Exception exception) {
log.error("获取对象状态 ------ 失败消息:{}", exception.getLocalizedMessage()); log.error("获取对象状态 ------ 失败消息:{}", exception.getLocalizedMessage());
exception.getStackTrace(); exception.getStackTrace();
throw new BunnyException(MinioMessageConstant.DELETE_BUCKET_EXCEPTION); throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
} }
} }
} }

View File

@ -29,6 +29,7 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId> <groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId> <artifactId>jackson-dataformat-xml</artifactId>
<version>2.16.0-rc1</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,23 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bunny</groupId>
<artifactId>module</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>module-task</artifactId>
<packaging>jar</packaging>
<name>module-task</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
</project>

View File

@ -0,0 +1,14 @@
package cn.bunny.module.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class TemplateTask {
@Scheduled(cron = "0/1 5 * * * ?")
public void templateTask() {
log.info("定时任务执行...");
}
}

View File

@ -0,0 +1,13 @@
package cn.bunny.module.websocket.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfiguration {
@Bean
public ServerEndpointExporter endpointExporter() {
return new ServerEndpointExporter();
}
}

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>cn.bunny</groupId> <groupId>cn.bunny</groupId>
<artifactId>bunny-template-mirror-server</artifactId> <artifactId>bunny-mirror-server</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
@ -16,6 +16,8 @@
<module>module-minio</module> <module>module-minio</module>
<module>module-mail</module> <module>module-mail</module>
<module>module-rabbitMQ</module> <module>module-rabbitMQ</module>
<module>module-websocket</module>
<module>module-task</module>
</modules> </modules>
<properties> <properties>
@ -25,7 +27,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>cn.bunny</groupId> <groupId>cn.bunny</groupId>
<artifactId>model</artifactId> <artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -18,11 +18,6 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>service-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- spring-security --> <!-- spring-security -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -1,6 +1,5 @@
package cn.bunny.security.config; package cn.bunny.security.config;
import cn.bunny.common.result.constant.SecurityConstant;
import cn.bunny.security.custom.CustomPasswordEncoder; import cn.bunny.security.custom.CustomPasswordEncoder;
import cn.bunny.security.filter.TokenAuthenticationFilter; import cn.bunny.security.filter.TokenAuthenticationFilter;
import cn.bunny.security.filter.TokenLoginFilterService; import cn.bunny.security.filter.TokenLoginFilterService;
@ -16,6 +15,7 @@ import org.springframework.security.config.annotation.authentication.configurati
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.core.session.SessionRegistryImpl;
@ -27,13 +27,15 @@ import org.springframework.security.web.util.matcher.RegexRequestMatcher;
@EnableWebSecurity @EnableWebSecurity
@EnableMethodSecurity @EnableMethodSecurity
public class WebSecurityConfig { public class WebSecurityConfig {
@Autowired @Autowired
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
// 自定义用户接口
@Autowired @Autowired
private CustomUserDetailsService customUserDetailsService; private CustomUserDetailsService customUserDetailsService;
// 自定义密码加密器
@Autowired @Autowired
private CustomPasswordEncoder customPasswordEncoder; private CustomPasswordEncoder customPasswordEncoder;
// 自定义验证码
@Autowired @Autowired
private CustomAuthorizationManagerService customAuthorizationManager; private CustomAuthorizationManagerService customAuthorizationManager;
@Autowired @Autowired
@ -57,8 +59,6 @@ public class WebSecurityConfig {
// 前后端分离不需要---记住我e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey") // 前后端分离不需要---记住我e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey")
.rememberMe(AbstractHttpConfigurer::disable) .rememberMe(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> { .authorizeHttpRequests(authorize -> {
// 如果访问路径有下面的不需要访问权限
authorize.requestMatchers(SecurityConstant.annotations).permitAll();
// 有样式文件不需要访问权限 // 有样式文件不需要访问权限
authorize.requestMatchers(RegexRequestMatcher.regexMatcher("^\\S*[css|js]$")).permitAll(); authorize.requestMatchers(RegexRequestMatcher.regexMatcher("^\\S*[css|js]$")).permitAll();
// 上面都不是需要鉴权访问 // 上面都不是需要鉴权访问
@ -70,9 +70,10 @@ public class WebSecurityConfig {
// 没有权限访问 // 没有权限访问
exception.accessDeniedHandler(new SecurityAccessDeniedHandler()); exception.accessDeniedHandler(new SecurityAccessDeniedHandler());
}) })
// 自定义过滤器 // 登录验证过滤器
.addFilterBefore(new TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class)
.addFilterAt(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class) // 其它权限鉴权过滤器
.addFilterAt(new TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class)
// 自定义密码加密器和用户登录 // 自定义密码加密器和用户登录
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService); .passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
@ -83,4 +84,12 @@ public class WebSecurityConfig {
public SessionRegistry sessionRegistry() { public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl(); return new SessionRegistryImpl();
} }
// 排出鉴定路径
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
String[] annotations = {"/", "/test/**", "/diagram-viewer/**", "/editor-app/**", "/*.html",
"/*/*/noAuth/**", "/*/noAuth/**", "/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v3/**", "/swagger-ui.html/**", "/doc.html"};
return web -> web.ignoring().requestMatchers(annotations);
}
} }

View File

@ -13,9 +13,9 @@ import java.util.Collection;
@Getter @Getter
@Setter @Setter
public class CustomUser extends User { public class CustomUser extends User {
private cn.bunny.entity.system.User user; private cn.bunny.entity.system.user.User user;
public CustomUser(cn.bunny.entity.system.User user, Collection<? extends GrantedAuthority> authorities) { public CustomUser(cn.bunny.entity.system.user.User user, Collection<? extends GrantedAuthority> authorities) {
super(user.getEmail(), user.getPassword(), authorities); super(user.getEmail(), user.getPassword(), authorities);
this.user = user; this.user = user;
} }

View File

@ -1,7 +1,13 @@
package cn.bunny.security.filter; package cn.bunny.security.filter;
import cn.bunny.common.service.context.BaseContext; import cn.bunny.common.service.context.BaseContext;
import cn.bunny.common.service.exception.BunnyException;
import cn.bunny.common.service.utils.JwtHelper; import cn.bunny.common.service.utils.JwtHelper;
import cn.bunny.common.service.utils.ResponseUtil;
import cn.bunny.result.Result;
import cn.bunny.result.ResultCodeEnum;
import cn.bunny.result.constant.RedisUserConstant;
import cn.bunny.vo.system.login.LoginVo;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
@ -17,7 +23,6 @@ import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
public class TokenAuthenticationFilter extends OncePerRequestFilter { public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final RedisTemplate<String, Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;
@ -27,7 +32,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
} }
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException, BunnyException {
String token = request.getHeader("token"); String token = request.getHeader("token");
// login请求就没token直接放行因为后边有其他的过滤器 // login请求就没token直接放行因为后边有其他的过滤器
@ -36,39 +41,51 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
return; return;
} }
// 如果想让这个用户下线清空Redis这个用户值返回未登录判断Redis是否有这个用户
// 如果想让这个用户锁定清空Redis值并在数据库中设置status值为1
String userName = JwtHelper.getUsername(token);
Object usernameObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(userName));
if (usernameObject == null) {
Result<Object> error = Result.error(ResultCodeEnum.LOGIN_AUTH);
ResponseUtil.out(response, error);
return;
}
// 获取Redis中登录信息
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(usernameObject), LoginVo.class);
// 如果是登录接口直接放行 // 如果是登录接口直接放行
UsernamePasswordAuthenticationToken authentication = getAuthentication(request); UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
if (authentication != null) {
// 设置用户详细信息
authentication.setDetails(loginVo.getPersonDescription());
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response); chain.doFilter(request, response);
} }
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) { private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// 请求头是否有token // 请求头是否有token
String token = request.getHeader("token"); String token = request.getHeader("token");
if (StringUtils.hasText(token)) { String username = RedisUserConstant.getAdminLoginInfoPrefix(JwtHelper.getUsername(token));
String username = JwtHelper.getUserName(token); List<SimpleGrantedAuthority> authList = new ArrayList<>();
if (StringUtils.hasText(username)) { if (!StringUtils.hasText(username)) return null;
// 当前用户信息放到ThreadLocal里面 // 当前用户信息放到ThreadLocal里面
BaseContext.setUserId(JwtHelper.getUserId(token)); BaseContext.setAdminId(JwtHelper.getUserId(token));
BaseContext.setUsername(username); BaseContext.setAdminName(username);
// 通过username从redis获取权限数据 // 通过username从redis获取权限数据
String authString = (String) redisTemplate.opsForValue().get(username); Object UserObject = redisTemplate.opsForValue().get(username);
// 把redis获取字符串权限数据转换要求集合类型 List<SimpleGrantedAuthority> // 把redis获取字符串权限数据转换要求集合类型 List<SimpleGrantedAuthority>
if (StringUtils.hasText(authString)) { if (UserObject != null) {
List<Map> maplist = JSON.parseArray(authString, Map.class); LoginVo loginVo = JSON.parseObject(JSON.toJSONString(UserObject), LoginVo.class);
System.out.println(maplist); List<String> roleList = loginVo.getRoleList();
List<SimpleGrantedAuthority> authList = new ArrayList<>(); roleList.forEach(role -> authList.add(new SimpleGrantedAuthority(role)));
for (Map map : maplist) {
String authority = (String) map.get("authority");
authList.add(new SimpleGrantedAuthority(authority));
}
return new UsernamePasswordAuthenticationToken(username, null, authList); return new UsernamePasswordAuthenticationToken(username, null, authList);
} else { } else {
return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>()); return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
} }
} }
}
return null;
}
} }

View File

@ -1,19 +1,21 @@
package cn.bunny.security.filter; package cn.bunny.security.filter;
import cn.bunny.common.result.enums.ResultCodeEnum;
import cn.bunny.common.result.utils.Result;
import cn.bunny.common.service.utils.ResponseUtil; import cn.bunny.common.service.utils.ResponseUtil;
import cn.bunny.dto.LoginDto; import cn.bunny.dto.user.LoginDto;
import cn.bunny.result.Result;
import cn.bunny.result.ResultCodeEnum;
import cn.bunny.result.constant.RedisUserConstant;
import cn.bunny.security.handelr.SecurityAuthenticationFailureHandler; import cn.bunny.security.handelr.SecurityAuthenticationFailureHandler;
import cn.bunny.security.handelr.SecurityAuthenticationSuccessHandler; import cn.bunny.security.handelr.SecurityAuthenticationSuccessHandler;
import cn.bunny.security.service.CustomUserDetailsService; import cn.bunny.security.service.CustomUserDetailsService;
import cn.bunny.vo.system.LoginVo; import cn.bunny.vo.system.login.LoginVo;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -23,53 +25,106 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** /**
* * UsernamePasswordAuthenticationFilter
* * 也可以在这里添加验证码短信等的验证
* 由于SpringSecurity的登录只能是表单形式 并且用户名密码需要时usernamepassword,可以通过继承 UsernamePasswordAuthenticationFilter 获取登录请求的参数 * 由于SpringSecurity的登录只能是表单形式 并且用户名密码需要时usernamepassword,可以通过继承 UsernamePasswordAuthenticationFilter 获取登录请求的参数
* 再去设置到 UsernamePasswordAuthenticationToken 来改变请求传参方式参数名等 或者也可以在登录的时候加入其他参数等等 * 再去设置到 UsernamePasswordAuthenticationToken 来改变请求传参方式参数名等 或者也可以在登录的时候加入其他参数等等
* 也可以在这里添加验证码短信等的验证
*/ */
public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilter { public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilter {
private final RedisTemplate<String, Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;
private final CustomUserDetailsService customUserDetailsService; private final CustomUserDetailsService customUserDetailsService;
private LoginDto loginDto; private LoginDto loginDto;
// 构造方法 // 依赖注入
public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, RedisTemplate<String, Object> redisTemplate, CustomUserDetailsService customUserDetailsService) throws Exception { public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, RedisTemplate<String, Object> redisTemplate, CustomUserDetailsService customUserDetailsService) throws Exception {
this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler()); this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler());
this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler()); this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler());
this.setPostOnly(false); this.setPostOnly(false);
// 指定登录接口及提交方式可以指定任意路径 // ? 指定登录接口及提交方式可以指定任意路径
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/*/login", "POST")); this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/*/login", HttpMethod.POST.name()));
this.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager()); this.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager());
// 依赖注入
this.redisTemplate = redisTemplate; this.redisTemplate = redisTemplate;
this.customUserDetailsService = customUserDetailsService; this.customUserDetailsService = customUserDetailsService;
} }
// 登录认证 /**
// 获取输入的用户名和密码调用方法认证 * * 登录认证获取输入的用户名和密码调用方法认证
* 接受前端login登录参数
* 在这里可以设置短信验证登录
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try { try {
// 获取用户信息 // 获取用户信息
loginDto = new ObjectMapper().readValue(request.getInputStream(), LoginDto.class); loginDto = new ObjectMapper().readValue(request.getInputStream(), LoginDto.class);
// 封装对象
// 登录验证码判断
String username = loginDto.getUsername();
String emailCode = loginDto.getEmailCode().toLowerCase();
String redisEmailCode = (String) redisTemplate.opsForValue().get(RedisUserConstant.getAdminUserEmailCodePrefix(username));
// 如果不存在验证码
if (!StringUtils.hasText(emailCode)) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_EMPTY));
return null;
}
if (!StringUtils.hasText(redisEmailCode)) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.SEND_EMAIL_CODE_NOT_EMPTY));
return null;
}
// 验证码不匹配
if (!Objects.equals(redisEmailCode.toLowerCase(), emailCode)) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING));
return null;
}
// 封装对象将用户名密码传入
Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword()); Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword());
// 调用方法
return this.getAuthenticationManager().authenticate(authenticationToken); return this.getAuthenticationManager().authenticate(authenticationToken);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e.getLocalizedMessage());
} }
} }
// 认证成功调用方法 /**
* * 认证成功调用方法
* 返回登录成功后的信息
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) { protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) {
// 返回登录信息 // 封装返回对象
LoginVo login = customUserDetailsService.login(loginDto); LoginVo loginVo = customUserDetailsService.login(loginDto);
ResponseUtil.out(response, Result.success(login));
// 判断用户是否被锁定
if (loginVo.getStatus() == 1) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED));
return;
} }
// 认证失败调用方法 // 将值存入Redis中
redisTemplate.opsForValue().set(RedisUserConstant.getAdminLoginInfoPrefix(loginVo.getEmail()), loginVo, 15, TimeUnit.DAYS);
// 将Redis中验证码删除
redisTemplate.delete(RedisUserConstant.getAdminUserEmailCodePrefix(loginVo.getEmail()));
// 返回登录信息
ResponseUtil.out(response, Result.success(loginVo));
}
/**
* * 认证失败调用方法失败判断
* 1. 是否包含用户名
* 2. 是否包含密码
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
// 账号和密码不能为空
if (loginDto == null) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY));
}
// 用户名为空 // 用户名为空
if (!StringUtils.hasText(loginDto.getUsername())) { if (!StringUtils.hasText(loginDto.getUsername())) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.USERNAME_NOT_EMPTY)); ResponseUtil.out(response, Result.error(ResultCodeEnum.USERNAME_NOT_EMPTY));
@ -78,7 +133,7 @@ public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilte
if (!StringUtils.hasText(loginDto.getPassword())) { if (!StringUtils.hasText(loginDto.getPassword())) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.PASSWORD_NOT_EMPTY)); ResponseUtil.out(response, Result.error(ResultCodeEnum.PASSWORD_NOT_EMPTY));
} }
// 抛出异常 // 抛出异常账号或密码错误
ResponseUtil.out(response, Result.error(null, ResultCodeEnum.LOGIN_ERROR)); ResponseUtil.out(response, Result.error(null, ResultCodeEnum.LOGIN_ERROR));
} }
} }

View File

@ -1,7 +1,7 @@
package cn.bunny.security.handelr; package cn.bunny.security.handelr;
import cn.bunny.common.result.enums.ResultCodeEnum; import cn.bunny.result.Result;
import cn.bunny.common.result.utils.Result; import cn.bunny.result.ResultCodeEnum;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;

View File

@ -1,8 +1,8 @@
package cn.bunny.security.handelr; package cn.bunny.security.handelr;
import cn.bunny.common.result.utils.Result; import cn.bunny.common.service.utils.ResponseUtil;
import cn.bunny.common.result.enums.ResultCodeEnum; import cn.bunny.result.Result;
import com.alibaba.fastjson2.JSON; import cn.bunny.result.ResultCodeEnum;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -24,16 +24,14 @@ public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoin
Result<Object> result; Result<Object> result;
if (token == null) { if (token == null) {
result = Result.error(new Object(), ResultCodeEnum.LOGIN_AUTH); result = Result.error(ResultCodeEnum.LOGIN_AUTH);
log.info("请求未登录接口:{}用户id{}", message, null); log.info("请求未登录接口:{}用户id{}", message, null);
} else { } else {
result = Result.error(new Object(), ResultCodeEnum.LOGGED_IN_FROM_ANOTHER_DEVICE); result = Result.error(ResultCodeEnum.LOGGED_IN_FROM_ANOTHER_DEVICE);
log.info("请求未授权接口:{}用户id{}", message, token); log.info("请求未授权接口:{}用户id{}", message, token);
} }
// 返回响应 // 返回响应
response.setContentType("application/json;charset=UTF-8"); ResponseUtil.out(response, result);
response.getWriter().println(JSON.toJSON(result));
} }
} }

View File

@ -1,6 +1,6 @@
package cn.bunny.security.handelr; package cn.bunny.security.handelr;
import cn.bunny.common.result.utils.Result; import cn.bunny.result.Result;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;

View File

@ -1,6 +1,6 @@
package cn.bunny.security.handelr; package cn.bunny.security.handelr;
import cn.bunny.common.result.utils.Result; import cn.bunny.result.Result;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;

View File

@ -1,7 +1,7 @@
package cn.bunny.security.service; package cn.bunny.security.service;
import cn.bunny.dto.LoginDto; import cn.bunny.dto.user.LoginDto;
import cn.bunny.vo.system.LoginVo; import cn.bunny.vo.system.login.LoginVo;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;

15
pom.xml
View File

@ -11,7 +11,7 @@
</parent> </parent>
<groupId>cn.bunny</groupId> <groupId>cn.bunny</groupId>
<artifactId>bunny-template-mirror-server</artifactId> <artifactId>bunny-mirror-server</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>bunny-mirror-server</name> <name>bunny-mirror-server</name>
@ -47,6 +47,8 @@
<discovery.version>2023.0.0.0-RC1</discovery.version> <discovery.version>2023.0.0.0-RC1</discovery.version>
<loadbalancer.version>4.1.2</loadbalancer.version> <loadbalancer.version>4.1.2</loadbalancer.version>
<pagehelper.version>6.1.0</pagehelper.version> <pagehelper.version>6.1.0</pagehelper.version>
<velocity.version>2.3</velocity.version>
<velocity-tools.version>3.1</velocity-tools.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
@ -56,6 +58,17 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>${junit.version}</version> <version>${junit.version}</version>
</dependency> </dependency>
<!-- velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
<version>${velocity-tools.version}</version>
</dependency>
<!-- mybatis-plus --> <!-- mybatis-plus -->
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>

Some files were not shown because too many files have changed in this diff Show More