dev #4

Merged
bunny merged 4 commits from dev into master 2024-05-24 14:38:29 +08:00
83 changed files with 192 additions and 951 deletions

View File

@ -20,7 +20,7 @@
<dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>model</artifactId>
<artifactId>dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

View File

@ -1,51 +0,0 @@
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

@ -1,5 +1,8 @@
package cn.bunny.common.utils;
/**
* 计算 kb mb gb
*/
public class FileUtil {
public static String getSize(Long fileSize) {
double fileSizeInKB = fileSize / 1024.00;

View File

@ -19,7 +19,7 @@
<dependencies>
<dependency>
<groupId>cn.bunny</groupId>
<artifactId>model</artifactId>
<artifactId>dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- httpclient -->

View File

@ -0,0 +1,38 @@
package cn.bunny.common.service.config;
import cn.bunny.common.service.interceptor.UserTokenInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@Slf4j
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private UserTokenInterceptor userTokenInterceptor;
/**
* 跨域配置
*
* @param registry 跨域注册表
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
// 是否发送Cookies
.allowCredentials(true)
// 放行哪些原始域
.allowedOriginPatterns("*").allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("*").exposedHeaders("*");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] excludeList = {"/api/checkCode", "/api/sendEmailCode", "/api/register", "/api/login", "/api/article/loadArticle/**"};
log.info("WebMvcConfiguration===>开始注册自定义拦截器...");
// TODO 如果想使用普通JWT可以使用这个不使用 SpringSecurity6
// registry.addInterceptor(userTokenInterceptor).addPathPatterns("/api/**").excludePathPatterns(excludeList);
}
}

View File

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

View File

@ -1,9 +1,9 @@
package cn.bunny.common.service.exception;
import cn.bunny.result.Result;
import cn.bunny.result.ResultCodeEnum;
import cn.bunny.result.constant.ExceptionConstant;
import cn.bunny.pojo.result.Result;
import cn.bunny.pojo.result.ResultCodeEnum;
import cn.bunny.pojo.result.constant.ExceptionConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

View File

@ -0,0 +1,54 @@
package cn.bunny.common.service.interceptor;
import cn.bunny.common.service.context.BaseContext;
import cn.bunny.common.service.utils.JwtHelper;
import cn.bunny.common.service.utils.ResponseUtil;
import cn.bunny.pojo.result.Result;
import cn.bunny.pojo.result.ResultCodeEnum;
import cn.bunny.pojo.result.constant.RedisUserConstant;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
@Slf4j
public class UserTokenInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("UserTokenInterceptor===>设置拦截器");
String token = request.getHeader("token");
Long userId = JwtHelper.getUserId(token);
String username = JwtHelper.getUsername(token);
Object redisUserinfo = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(username));
// 不是动态方法直接返回
if (!(handler instanceof HandlerMethod)) return true;
// 解析不到userId
if (userId == null) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_AUTH));
return false;
}
if (redisUserinfo == null) {
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_AUTH));
return false;
}
BaseContext.setUserId(userId);
BaseContext.setUsername(username);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
BaseContext.removeUser();
}
}

View File

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

View File

@ -7,7 +7,7 @@
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>model</artifactId>
<artifactId>dao</artifactId>
<packaging>jar</packaging>
<name>model</name>

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package cn.bunny.enums;
package cn.bunny.pojo.enums;
/**
* 数据库操作类型

View File

@ -1,4 +1,4 @@
package cn.bunny.result;
package cn.bunny.pojo.result;
import lombok.AllArgsConstructor;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package cn.bunny.result;
package cn.bunny.pojo.result;
import lombok.Getter;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package cn.bunny.tree;
package cn.bunny.pojo.tree;
import java.util.List;

View File

@ -1,4 +1,4 @@
package cn.bunny.tree;
package cn.bunny.pojo.tree;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,6 +1,6 @@
package cn.bunny.vo.system.login;
import cn.bunny.result.constant.LocalDateTimeConstant;
import cn.bunny.pojo.result.constant.LocalDateTimeConstant;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

View File

@ -1,6 +1,6 @@
package cn.bunny.vo.system.user;
import cn.bunny.result.constant.LocalDateTimeConstant;
import cn.bunny.pojo.result.constant.LocalDateTimeConstant;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

View File

@ -1,22 +0,0 @@
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

@ -1,15 +0,0 @@
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

@ -1,19 +0,0 @@
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

@ -1,16 +0,0 @@
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

@ -1,15 +0,0 @@
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

@ -1,17 +0,0 @@
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

@ -1,16 +0,0 @@
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

@ -1,22 +0,0 @@
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

@ -1,15 +0,0 @@
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

@ -1,14 +0,0 @@
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

@ -1,83 +0,0 @@
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

@ -1,67 +0,0 @@
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

@ -1,40 +0,0 @@
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

@ -1,43 +0,0 @@
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

@ -1,49 +0,0 @@
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,50 +0,0 @@
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

@ -1,58 +0,0 @@
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,32 +0,0 @@
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

@ -1,70 +0,0 @@
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

@ -1,29 +0,0 @@
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

@ -1,53 +0,0 @@
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

@ -1,33 +0,0 @@
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

@ -1,19 +0,0 @@
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

@ -1,43 +0,0 @@
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

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

View File

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

View File

@ -1,7 +1,7 @@
package cn.bunny.module.minio.utils;
import cn.bunny.result.constant.FileMessageConstant;
import cn.bunny.common.service.exception.BunnyException;
import cn.bunny.pojo.result.constant.FileMessageConstant;
import io.minio.*;
import io.minio.messages.*;
import lombok.extern.slf4j.Slf4j;

View File

@ -17,6 +17,7 @@
<module>module-mail</module>
<module>module-rabbitMQ</module>
<module>module-websocket</module>
<module>spring-security</module>
<module>module-task</module>
</modules>

View File

@ -4,9 +4,9 @@ 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.ResponseUtil;
import cn.bunny.result.Result;
import cn.bunny.result.ResultCodeEnum;
import cn.bunny.result.constant.RedisUserConstant;
import cn.bunny.pojo.result.Result;
import cn.bunny.pojo.result.ResultCodeEnum;
import cn.bunny.pojo.result.constant.RedisUserConstant;
import cn.bunny.vo.system.login.LoginVo;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.FilterChain;

View File

@ -3,9 +3,9 @@ package cn.bunny.security.filter;
import cn.bunny.common.service.utils.ResponseUtil;
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.pojo.result.Result;
import cn.bunny.pojo.result.ResultCodeEnum;
import cn.bunny.pojo.result.constant.RedisUserConstant;
import cn.bunny.security.handelr.SecurityAuthenticationFailureHandler;
import cn.bunny.security.handelr.SecurityAuthenticationSuccessHandler;
import cn.bunny.security.service.CustomUserDetailsService;

View File

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

View File

@ -1,8 +1,8 @@
package cn.bunny.security.handelr;
import cn.bunny.common.service.utils.ResponseUtil;
import cn.bunny.result.Result;
import cn.bunny.result.ResultCodeEnum;
import cn.bunny.pojo.result.Result;
import cn.bunny.pojo.result.ResultCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

View File

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

View File

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

View File

@ -17,7 +17,7 @@
<modules>
<module>common</module>
<module>model</module>
<module>dao</module>
<module>service</module>
<module>module</module>
</modules>

View File

@ -1,6 +1,6 @@
package cn.bunny.service.aop.annotation;
import cn.bunny.enums.OperationType;
import cn.bunny.pojo.enums.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View File

@ -2,7 +2,7 @@ package cn.bunny.service.controller;
import cn.bunny.dto.user.LoginDto;
import cn.bunny.result.Result;
import cn.bunny.pojo.result.Result;
import cn.bunny.service.service.UserService;
import cn.bunny.vo.system.login.LoginVo;
import io.swagger.v3.oas.annotations.Operation;

View File

@ -1,13 +1,20 @@
package cn.bunny.service.security;
import cn.bunny.common.service.utils.JwtHelper;
import cn.bunny.entity.system.admin.AdminPower;
import cn.bunny.security.service.CustomAuthorizationManagerService;
import cn.bunny.service.mapper.AdminPowerMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Service;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.function.Supplier;
@ -15,22 +22,51 @@ import java.util.function.Supplier;
* 自定义权限判断
* 判断用户有哪些权限
*/
@Service
@Component
@Slf4j
public class CustomAuthorizationManagerServiceImpl implements CustomAuthorizationManagerService {
@Autowired
private AdminPowerMapper adminPowerMapper;
@Override
public void verify(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {
CustomAuthorizationManagerService.super.verify(authentication, requestAuthorizationContext);
}
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
String token = object.getRequest().getHeader("token");
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
// 用户的token和用户id请求Url
HttpServletRequest request = context.getRequest();
String token = request.getHeader("token");
Long userId = JwtHelper.getUserId(token);// 用户id
String requestURI = request.getRequestURI();// 请求地址
String method = request.getMethod();// 请求方式
List<String> roleCodeList = authentication.get().getAuthorities().stream().map(GrantedAuthority::getAuthority).toList();// 角色代码列表
if (token == null) {
throw new AccessDeniedException("");
}
return new AuthorizationDecision(true);
return new AuthorizationDecision(hasRoleList(requestURI, method, userId));
}
/**
* 查询用户所属的角色信息
*
* @param requestURI 请求url地址
* @param method 请求方式
* @param userId 用户id
*/
private Boolean hasRoleList(String requestURI, String method, Long userId) {
// 查询用户权限
List<AdminPower> powerList = adminPowerMapper.queryByUserIdWithPower(userId);
// 如果查询到当前地址符合这个地址
for (AdminPower adminPower : powerList) {
String description = adminPower.getDescription();
if (description.equals(requestURI) || requestURI.matches(description)) {
return true;
}
}
return false;
}
}

View File

@ -10,14 +10,14 @@ import cn.bunny.service.service.UserService;
import cn.bunny.vo.system.login.LoginVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.List;
@Configuration
@Component
public class CustomUserDetailsService implements cn.bunny.security.service.CustomUserDetailsService {
@Autowired
private UserMapper userMapper;
@ -51,4 +51,4 @@ public class CustomUserDetailsService implements cn.bunny.security.service.Custo
public LoginVo login(LoginDto loginDto) {
return userService.login(loginDto);
}
}
}

View File

@ -5,14 +5,14 @@ import cn.bunny.common.service.utils.JwtHelper;
import cn.bunny.dto.user.LoginDto;
import cn.bunny.entity.system.admin.AdminPower;
import cn.bunny.entity.system.admin.auth.AuthUserRole;
import cn.bunny.entity.system.email.EmailSend;
import cn.bunny.entity.system.email.EmailSendInit;
import cn.bunny.entity.system.email.EmailUsers;
import cn.bunny.entity.system.user.User;
import cn.bunny.module.mail.utils.MailSenderUtil;
import cn.bunny.result.constant.ExceptionConstant;
import cn.bunny.result.constant.MailMessageConstant;
import cn.bunny.result.constant.RedisUserConstant;
import cn.bunny.pojo.email.EmailSend;
import cn.bunny.pojo.email.EmailSendInit;
import cn.bunny.pojo.result.constant.ExceptionConstant;
import cn.bunny.pojo.result.constant.MailMessageConstant;
import cn.bunny.pojo.result.constant.RedisUserConstant;
import cn.bunny.service.mapper.AdminPowerMapper;
import cn.bunny.service.mapper.AdminRoleMapper;
import cn.bunny.service.mapper.EmailUsersMapper;