From 4199c3a56bf6bc02bdffb90247af45e7e20c1106 Mon Sep 17 00:00:00 2001 From: MiniDay <372403923@qq.com> Date: Wed, 29 Mar 2023 16:58:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BC=80=E5=8F=91=E4=B8=AD...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blog/config/BlogExceptionHandler.java | 19 +++++ .../application/blog/config/WebConfig.java | 34 +++----- .../blog/config/security/BlogUser.java | 5 +- .../security/BlogUserDetailService.java | 3 +- .../config/security/UserAuditorAware.java | 35 +------- .../application/blog/constant/UserRole.java | 4 +- .../blog/controller/BlogController.java | 2 +- .../blog/controller/SettingController.java | 59 ++++++++++++++ .../controller/SiteSettingController.java | 23 ------ .../blog/controller/UserController.java | 6 +- .../blog/entity/BlogAttachEntity.java | 4 +- .../blog/entity/SettingEntity.java | 43 ++++++++++ .../application/blog/entity/SiteSetting.java | 29 ------- .../blog/entity/mapper/BlogMapper.java | 4 +- .../blog/entity/mapper/SettingMapper.java | 12 +++ .../blog/entity/mapper/UserMapper.java | 2 +- .../blog/entity/repo/SettingRepository.java | 24 ++++++ .../blog/service/ISettingService.java | 20 +++++ .../blog/service/impl/BlogService.java | 5 +- .../blog/service/impl/SettingService.java | 81 +++++++++++++++++++ .../blog/service/impl/UserService.java | 14 ++-- .../application/blog/util/BlogUtils.java | 53 ++++++++++++ .../application/blog/vo/PageableVO.java | 7 +- .../application/blog/vo/ResponseVO.java | 24 ++++-- .../blog/vo/blog/BlogInfoResponseVO.java | 1 + .../vo/setting/SettingInfoResponseVO.java | 15 ++++ .../vo/setting/SettingUpdateRequireVO.java | 14 ++++ 27 files changed, 405 insertions(+), 137 deletions(-) create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/controller/SettingController.java delete mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/controller/SiteSettingController.java create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/entity/SettingEntity.java delete mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/entity/SiteSetting.java create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/SettingMapper.java create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/entity/repo/SettingRepository.java create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/service/ISettingService.java create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/SettingService.java create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingInfoResponseVO.java create mode 100644 blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingUpdateRequireVO.java diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/config/BlogExceptionHandler.java b/blog-backend/src/main/java/cn/hamster3/application/blog/config/BlogExceptionHandler.java index aaf8108..5bbb3de 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/config/BlogExceptionHandler.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/config/BlogExceptionHandler.java @@ -2,8 +2,11 @@ package cn.hamster3.application.blog.config; import cn.hamster3.application.blog.vo.ResponseVO; import jakarta.annotation.Resource; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.core.NestedRuntimeException; import org.springframework.core.env.Environment; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -34,6 +37,22 @@ public class BlogExceptionHandler { ); } + @ExceptionHandler(NestedRuntimeException.class) + public ResponseVO onNestedRuntimeException(NestedRuntimeException e) { + if (e.getRootCause() != null) { + if (e.getRootCause() instanceof ConstraintViolationException ve) { + return ResponseVO.failed(ve.getConstraintViolations() + .stream() + .findFirst() + .map(ConstraintViolation::getMessage) + .orElse("未知错误!") + ); + } + return ResponseVO.failed(e.getRootCause().getMessage()); + } + return ResponseVO.failed(e.getMessage()); + } + @ExceptionHandler(Exception.class) public ResponseVO onException(Exception e) { if ("dev".equals(environment.getProperty("spring.profiles.active"))) { diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/config/WebConfig.java b/blog-backend/src/main/java/cn/hamster3/application/blog/config/WebConfig.java index e9e0977..388c743 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/config/WebConfig.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/config/WebConfig.java @@ -1,9 +1,13 @@ package cn.hamster3.application.blog.config; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.Resource; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cache.concurrent.ConcurrentMapCache; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; @@ -31,26 +35,12 @@ public class WebConfig { return new ProviderManager(provider); } -// @Bean -// public AuthenticationManager getAuthenticationManager() { -// return new AuthenticationManager() { -// @Resource -// private UserDetailsService userDetailsService; -// -// @Override -// public Authentication authenticate(Authentication authentication) throws AuthenticationException { -// if (!(authentication instanceof UsernamePasswordAuthenticationToken)) { -// throw new IllegalArgumentException("BlogAuthenticationManager only support UsernamePasswordAuthenticationToken!"); -// } -// UserDetails user = userDetailsService.loadUserByUsername((String) authentication.getPrincipal()); -// UsernamePasswordAuthenticationToken authenticated = UsernamePasswordAuthenticationToken.authenticated( -// authentication.getPrincipal(), -// authentication.getCredentials(), -// user.getAuthorities() -// ); -// authenticated.setDetails(user); -// return authenticated; -// } -// }; -// } + @Bean + @ConditionalOnMissingBean(ObjectMapper.class) + public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { + ObjectMapper objectMapper = builder.createXmlMapper(false).build(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + return objectMapper; + } + } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUser.java b/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUser.java index 22b1943..a2c2b9d 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUser.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUser.java @@ -1,5 +1,6 @@ package cn.hamster3.application.blog.config.security; +import cn.hamster3.application.blog.constant.UserRole; import lombok.Getter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; @@ -10,9 +11,11 @@ import java.util.UUID; @Getter public class BlogUser extends User { private final UUID id; + private final UserRole role; - public BlogUser(String username, String password, Collection authorities, UUID id) { + public BlogUser(String username, String password, Collection authorities, UUID id, UserRole role) { super(username, password, authorities); this.id = id; + this.role = role; } } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUserDetailService.java b/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUserDetailService.java index b9178e1..fbc4eff 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUserDetailService.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/BlogUserDetailService.java @@ -24,7 +24,8 @@ public class BlogUserDetailService implements UserDetailsService { user.getEmail(), user.getPassword(), Collections.singleton(user.getRole().getAuthority()), - user.getId() + user.getId(), + user.getRole() )).orElseThrow(() -> new UsernameNotFoundException("user not found.")); } } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/UserAuditorAware.java b/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/UserAuditorAware.java index 0e19815..065852d 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/UserAuditorAware.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/config/security/UserAuditorAware.java @@ -1,14 +1,12 @@ package cn.hamster3.application.blog.config.security; -import cn.hamster3.application.blog.entity.repo.UserRepository; import cn.hamster3.application.blog.entity.UserEntity; +import cn.hamster3.application.blog.entity.repo.UserRepository; +import cn.hamster3.application.blog.util.BlogUtils; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.data.domain.AuditorAware; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import java.util.Optional; @@ -20,36 +18,9 @@ public class UserAuditorAware implements AuditorAware { @Resource private UserRepository userRepo; - @NotNull - public static Optional currentUser() { - SecurityContext context = SecurityContextHolder.getContext(); - Authentication authentication = context.getAuthentication(); - if (authentication == null) { - return Optional.empty(); - } - log.info("=============================="); - log.info("current user authentication: {}", authentication); - log.info("current user authentication getPrincipal: {}", authentication.getPrincipal()); - log.info("current user authentication getCredentials: {}", authentication.getCredentials()); - log.info("current user authentication getDetails: {}", authentication.getDetails()); - log.info("current user authentication getAuthorities: {}", authentication.getAuthorities()); - if (!authentication.isAuthenticated()) { - return Optional.empty(); - } - if (!(authentication.getPrincipal() instanceof BlogUser user)) { - return Optional.empty(); - } - return Optional.of(user); - } - - @NotNull - public static Optional currentUserUUID() { - return currentUser().map(BlogUser::getId); - } - @Override public @NotNull Optional getCurrentAuditor() { - UUID uuid = UserAuditorAware.currentUserUUID().orElse(null); + UUID uuid = BlogUtils.getCurrentUserUUID().orElse(null); if (uuid == null) { return Optional.empty(); } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/constant/UserRole.java b/blog-backend/src/main/java/cn/hamster3/application/blog/constant/UserRole.java index e38df61..e9e8db0 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/constant/UserRole.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/constant/UserRole.java @@ -4,9 +4,9 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; public enum UserRole { /** - * 读者 + * 访客 */ - USER, + GUEST, /** * 作者 */ diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/controller/BlogController.java b/blog-backend/src/main/java/cn/hamster3/application/blog/controller/BlogController.java index 35e7914..b61f217 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/controller/BlogController.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/controller/BlogController.java @@ -40,7 +40,7 @@ public class BlogController { @Parameter(description = "页码", example = "0") int page, @Parameter(description = "大小", example = "10") int size ) { - return blogService.getBlogInfoList(PageRequest.of(page, size)); + return blogService.getBlogInfoList(PageRequest.of(page, Math.max(size, 100))); } @PutMapping("/{blogID}/") diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/controller/SettingController.java b/blog-backend/src/main/java/cn/hamster3/application/blog/controller/SettingController.java new file mode 100644 index 0000000..9ac87d8 --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/controller/SettingController.java @@ -0,0 +1,59 @@ +package cn.hamster3.application.blog.controller; + +import cn.hamster3.application.blog.service.ISettingService; +import cn.hamster3.application.blog.vo.PageableVO; +import cn.hamster3.application.blog.vo.ResponseVO; +import cn.hamster3.application.blog.vo.setting.SettingInfoResponseVO; +import cn.hamster3.application.blog.vo.setting.SettingUpdateRequireVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "网站设置接口", description = "网站设置相关接口") +@RestController +@RequestMapping(value = "/api/v1/settings", produces = MediaType.APPLICATION_JSON_VALUE) +public class SettingController { + @Resource + private ISettingService settingService; + + @GetMapping("/{id}/") + @Operation(summary = "获取网站设置") + public ResponseVO getSettingInfo(@Parameter(description = "设置ID") @PathVariable String id) { + return settingService.getSettingInfo(id); + } + + @GetMapping("/{id}/content/") + @Operation(summary = "获取网站设置") + public ResponseVO getSettingContent(@Parameter(description = "设置ID") @PathVariable String id) { + return settingService.getSettingContent(id); + } + + @GetMapping("/") + @Operation(summary = "获取网站设置") + public ResponseVO> getSetting( + @Parameter(description = "页码", example = "0") int page, + @Parameter(description = "大小", example = "10") int size + ) { + return settingService.getSettingInfoList(PageRequest.of(page, Math.max(size, 100))); + } + + @PutMapping("/{id}/") + @Operation(summary = "更改网站设置") + public ResponseVO updateSetting( + @Parameter(description = "设置ID") @PathVariable String id, + @RequestBody @Valid SettingUpdateRequireVO requireVO + ) { + return settingService.updateSetting(id, requireVO); + } + + @DeleteMapping("/{id}/") + @Operation(summary = "删除网站设置") + public ResponseVO deleteSetting(@Parameter(description = "设置ID") @PathVariable String id) { + return settingService.deleteSetting(id); + } +} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/controller/SiteSettingController.java b/blog-backend/src/main/java/cn/hamster3/application/blog/controller/SiteSettingController.java deleted file mode 100644 index b9e4de0..0000000 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/controller/SiteSettingController.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.hamster3.application.blog.controller; - -import cn.hamster3.application.blog.vo.ResponseVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@Tag(name = "网站设置接口", description = "网站设置相关接口") -@RestController -@RequestMapping(value = "/api/v1/settings", produces = MediaType.APPLICATION_JSON_VALUE) -public class SiteSettingController { - @GetMapping("/{path}/") - @Operation(summary = "获取网站设置") - public ResponseVO getSiteSettings(@Parameter(description = "设置ID") @PathVariable String path) { - return ResponseVO.success(path); - } - -} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/controller/UserController.java b/blog-backend/src/main/java/cn/hamster3/application/blog/controller/UserController.java index e0f0c2a..09f1db3 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/controller/UserController.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/controller/UserController.java @@ -60,7 +60,7 @@ public class UserController { @Parameter(description = "页码", example = "0") int page, @Parameter(description = "大小", example = "10") int size ) { - return userService.getAllUserInfo(PageRequest.of(page, size)); + return userService.getAllUserInfo(PageRequest.of(page, Math.max(size, 100))); } @GetMapping("/{userID}/") @@ -76,7 +76,7 @@ public class UserController { @Parameter(description = "页码", example = "0") int page, @Parameter(description = "大小", example = "10") int size ) { - return userService.getUserBlogList(userID, PageRequest.of(page, size)); + return userService.getUserBlogList(userID, PageRequest.of(page, Math.max(size, 100))); } @GetMapping("/{userID}/attach/") @@ -86,6 +86,6 @@ public class UserController { @Parameter(description = "页码", example = "0") int page, @Parameter(description = "大小", example = "10") int size ) { - return userService.getUserAttachList(userID, PageRequest.of(page, size)); + return userService.getUserAttachList(userID, PageRequest.of(page, Math.max(size, 100))); } } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/BlogAttachEntity.java b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/BlogAttachEntity.java index d1d4929..8cf5604 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/BlogAttachEntity.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/BlogAttachEntity.java @@ -2,18 +2,18 @@ package cn.hamster3.application.blog.entity; import jakarta.persistence.*; import lombok.Getter; -import lombok.Setter; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.util.Date; @Getter -@Setter @Entity @Table(name = "blog_attach_entity") +@EntityListeners(AuditingEntityListener.class) public class BlogAttachEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/SettingEntity.java b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/SettingEntity.java new file mode 100644 index 0000000..4137d87 --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/SettingEntity.java @@ -0,0 +1,43 @@ +package cn.hamster3.application.blog.entity; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.util.Date; + +@Getter +@Entity +@Table(name = "setting_entity") +@EntityListeners(AuditingEntityListener.class) +public class SettingEntity { + @Setter + @Id + @Column(name = "id", nullable = false, updatable = false, length = 64) + @NotBlank(message = "网站设置 ID 不能为空!") + @Length(message = "网站设置 ID 长度不能超过 64 字符!", max = 64) + @Pattern(message = "网站设置 ID 只能包含字母、数字和下划线!", regexp = "[a-zA-Z0-9-_]+") + private String id; + + @Setter + @Lob + @Column(name = "content", nullable = false) + @NotBlank(message = "网站设置内容不能为空!") + private String content; + + @CreatedDate + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "create_time", nullable = false) + private Date createTime; + + @LastModifiedDate + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "update_time", nullable = false) + private Date updateTime; +} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/SiteSetting.java b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/SiteSetting.java deleted file mode 100644 index a8cdd41..0000000 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/SiteSetting.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.hamster3.application.blog.entity; - -import jakarta.persistence.*; -import lombok.Getter; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; - -import java.util.Date; - -@Getter -@Entity -public class SiteSetting { - @Id - @Column(name = "id", nullable = false, updatable = false, length = 64) - private String id; - - @Column(name = "content", nullable = false, length = 1024) - private String content; - - @CreatedDate - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "create_time", nullable = false) - private Date createTime; - - @LastModifiedDate - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "update_time", nullable = false) - private Date updateTime; -} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/BlogMapper.java b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/BlogMapper.java index 260d4a3..aed9886 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/BlogMapper.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/BlogMapper.java @@ -13,9 +13,9 @@ import java.util.UUID; @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) public interface BlogMapper { - BlogEntity voToEntity(BlogUpdateRequireVO requireVO); + BlogEntity voToEntity(BlogUpdateRequireVO vo); - BlogInfoResponseVO entityToInfoVO(BlogEntity requireVO); + BlogInfoResponseVO entityToInfoVO(BlogEntity entity); @NotNull @SuppressWarnings("unused") diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/SettingMapper.java b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/SettingMapper.java new file mode 100644 index 0000000..0b1663a --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/SettingMapper.java @@ -0,0 +1,12 @@ +package cn.hamster3.application.blog.entity.mapper; + +import cn.hamster3.application.blog.entity.SettingEntity; +import cn.hamster3.application.blog.vo.setting.SettingInfoResponseVO; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ReportingPolicy; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) +public interface SettingMapper { + SettingInfoResponseVO entityToInfoVO(SettingEntity entity); +} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/UserMapper.java b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/UserMapper.java index 2702c0d..eb2c5ef 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/UserMapper.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/mapper/UserMapper.java @@ -9,7 +9,7 @@ import org.mapstruct.ReportingPolicy; @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) public interface UserMapper { - UserEntity voToEntity(UserCreateRequireVO requireVO); + UserEntity voToEntity(UserCreateRequireVO vo); UserInfoResponseVO entityToInfoVO(UserEntity entity); } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/entity/repo/SettingRepository.java b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/repo/SettingRepository.java new file mode 100644 index 0000000..79e9151 --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/entity/repo/SettingRepository.java @@ -0,0 +1,24 @@ +package cn.hamster3.application.blog.entity.repo; + +import cn.hamster3.application.blog.entity.SettingEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; + +public interface SettingRepository extends JpaRepository, JpaSpecificationExecutor { + @Transactional + @Modifying + @Query("delete from SettingEntity s where upper(s.id) = upper(?1)") + void deleteByIdIgnoreCase(String id); + + SettingEntity findByIdIgnoreCase(String id); + + boolean existsByIdIgnoreCase(String id); + + @Transactional + @Modifying + @Query("update SettingEntity s set s.content = ?1 where upper(s.id) = upper(?2)") + void updateContentByIdIgnoreCase(String content, String id); +} \ No newline at end of file diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/service/ISettingService.java b/blog-backend/src/main/java/cn/hamster3/application/blog/service/ISettingService.java new file mode 100644 index 0000000..fe44b11 --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/service/ISettingService.java @@ -0,0 +1,20 @@ +package cn.hamster3.application.blog.service; + +import cn.hamster3.application.blog.vo.PageableVO; +import cn.hamster3.application.blog.vo.ResponseVO; +import cn.hamster3.application.blog.vo.setting.SettingInfoResponseVO; +import cn.hamster3.application.blog.vo.setting.SettingUpdateRequireVO; +import org.jetbrains.annotations.NotNull; +import org.springframework.data.domain.Pageable; + +public interface ISettingService { + @NotNull ResponseVO getSettingInfo(@NotNull String id); + + @NotNull ResponseVO getSettingContent(@NotNull String id); + + @NotNull ResponseVO> getSettingInfoList(@NotNull Pageable pageable); + + @NotNull ResponseVO updateSetting(@NotNull String id, @NotNull SettingUpdateRequireVO requireVO); + + @NotNull ResponseVO deleteSetting(@NotNull String id); +} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/BlogService.java b/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/BlogService.java index 43842f0..f4914a8 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/BlogService.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/BlogService.java @@ -2,11 +2,12 @@ package cn.hamster3.application.blog.service.impl; import cn.hamster3.application.blog.config.security.BlogUser; import cn.hamster3.application.blog.config.security.UserAuditorAware; -import cn.hamster3.application.blog.entity.repo.BlogRepository; import cn.hamster3.application.blog.entity.BlogEntity; import cn.hamster3.application.blog.entity.UserEntity; import cn.hamster3.application.blog.entity.mapper.BlogMapper; +import cn.hamster3.application.blog.entity.repo.BlogRepository; import cn.hamster3.application.blog.service.IBlogService; +import cn.hamster3.application.blog.util.BlogUtils; import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.blog.BlogInfoResponseVO; import cn.hamster3.application.blog.vo.blog.BlogUpdateRequireVO; @@ -62,7 +63,7 @@ public class BlogService implements IBlogService { if (!blogRepo.existsById(blogID)) { return ResponseVO.failed("该博文不存在!"); } - BlogUser user = UserAuditorAware.currentUser().orElse(null); + BlogUser user = BlogUtils.getCurrentUser().orElse(null); if (user == null) { return ResponseVO.unauthorized(); } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/SettingService.java b/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/SettingService.java new file mode 100644 index 0000000..222e603 --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/SettingService.java @@ -0,0 +1,81 @@ +package cn.hamster3.application.blog.service.impl; + +import cn.hamster3.application.blog.entity.SettingEntity; +import cn.hamster3.application.blog.entity.mapper.SettingMapper; +import cn.hamster3.application.blog.entity.repo.SettingRepository; +import cn.hamster3.application.blog.service.ISettingService; +import cn.hamster3.application.blog.util.BlogUtils; +import cn.hamster3.application.blog.vo.PageableVO; +import cn.hamster3.application.blog.vo.ResponseVO; +import cn.hamster3.application.blog.vo.setting.SettingInfoResponseVO; +import cn.hamster3.application.blog.vo.setting.SettingUpdateRequireVO; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class SettingService implements ISettingService { + @Resource + private SettingMapper settingMapper; + @Resource + private SettingRepository settingRepo; + + @Override + public @NotNull ResponseVO getSettingInfo(@NotNull String id) { + SettingEntity entity = settingRepo.findByIdIgnoreCase(id); + if (entity == null) { + return ResponseVO.notFound(); + } + return ResponseVO.success(settingMapper.entityToInfoVO(entity)); + } + + @Override + public @NotNull ResponseVO getSettingContent(@NotNull String id) { + SettingEntity entity = settingRepo.findByIdIgnoreCase(id); + if (entity == null) { + return ResponseVO.notFound(); + } + return ResponseVO.success(entity.getContent()); + } + + @Override + public @NotNull ResponseVO> getSettingInfoList(@NotNull Pageable pageable) { + return PageableVO.success( + settingRepo.findAll(pageable) + .map(o -> settingMapper.entityToInfoVO(o)) + ); + } + + @Override + public @NotNull ResponseVO updateSetting(@NotNull String id, @NotNull SettingUpdateRequireVO requireVO) { + ResponseVO check = BlogUtils.checkAdminPermission(); + if (check != null) { + return check; + } + if (!settingRepo.existsByIdIgnoreCase(id)) { + SettingEntity entity = new SettingEntity(); + entity.setId(id); + entity.setContent(requireVO.getContent()); + settingRepo.save(entity); + } else { + settingRepo.updateContentByIdIgnoreCase(requireVO.getContent(), id); + } + return ResponseVO.success(); + } + + @Override + public @NotNull ResponseVO deleteSetting(@NotNull String id) { + ResponseVO check = BlogUtils.checkAdminPermission(); + if (check != null) { + return check; + } + if (!settingRepo.existsByIdIgnoreCase(id)) { + return ResponseVO.notFound(); + } + settingRepo.deleteByIdIgnoreCase(id); + return ResponseVO.success(); + } +} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/UserService.java b/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/UserService.java index 9d4d788..658a6ba 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/UserService.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/service/impl/UserService.java @@ -1,16 +1,16 @@ package cn.hamster3.application.blog.service.impl; import cn.hamster3.application.blog.config.security.BlogUser; -import cn.hamster3.application.blog.config.security.UserAuditorAware; import cn.hamster3.application.blog.constant.UserRole; -import cn.hamster3.application.blog.entity.repo.AttachRepository; -import cn.hamster3.application.blog.entity.repo.BlogRepository; -import cn.hamster3.application.blog.entity.repo.UserRepository; import cn.hamster3.application.blog.entity.UserEntity; import cn.hamster3.application.blog.entity.mapper.AttachMapper; import cn.hamster3.application.blog.entity.mapper.BlogMapper; import cn.hamster3.application.blog.entity.mapper.UserMapper; +import cn.hamster3.application.blog.entity.repo.AttachRepository; +import cn.hamster3.application.blog.entity.repo.BlogRepository; +import cn.hamster3.application.blog.entity.repo.UserRepository; import cn.hamster3.application.blog.service.IUserService; +import cn.hamster3.application.blog.util.BlogUtils; import cn.hamster3.application.blog.vo.PageableVO; import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO; @@ -55,7 +55,7 @@ public class UserService implements IUserService { @Override public @NotNull ResponseVO getCurrentUserInfo() { - UUID uuid = UserAuditorAware.currentUserUUID().orElse(null); + UUID uuid = BlogUtils.getCurrentUserUUID().orElse(null); if (uuid == null) { return ResponseVO.unauthorized(); } @@ -80,7 +80,7 @@ public class UserService implements IUserService { } entity.setPassword(passwordEncoder.encode(entity.getPassword())); - entity.setRole(UserRole.USER); + entity.setRole(UserRole.AUTHOR); log.info("prepare to save userinfo: {}", entity); UserEntity save = userRepo.save(entity); @@ -93,7 +93,7 @@ public class UserService implements IUserService { if (userEntity == null) { return ResponseVO.failed("未找到该用户!"); } - BlogUser blogUser = UserAuditorAware.currentUser().orElse(null); + BlogUser blogUser = BlogUtils.getCurrentUser().orElse(null); if (blogUser == null) { return ResponseVO.unauthorized(); } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/util/BlogUtils.java b/blog-backend/src/main/java/cn/hamster3/application/blog/util/BlogUtils.java index 3141b00..8a3eddd 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/util/BlogUtils.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/util/BlogUtils.java @@ -1,8 +1,61 @@ package cn.hamster3.application.blog.util; +import cn.hamster3.application.blog.config.security.BlogUser; +import cn.hamster3.application.blog.constant.UserRole; +import cn.hamster3.application.blog.vo.ResponseVO; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.util.Optional; +import java.util.UUID; @Slf4j public class BlogUtils { + @NotNull + public static Authentication getCurrentAuthentication() { + return SecurityContextHolder.getContext().getAuthentication(); + } + @NotNull + public static Optional getCurrentUser() { + Authentication authentication = getCurrentAuthentication(); + log.info("=============================="); + log.info("current user authentication: {}", authentication); + log.info("current user authentication getPrincipal: {}", authentication.getPrincipal()); + log.info("current user authentication getCredentials: {}", authentication.getCredentials()); + log.info("current user authentication getDetails: {}", authentication.getDetails()); + log.info("current user authentication getAuthorities: {}", authentication.getAuthorities()); + if (!authentication.isAuthenticated()) { + return Optional.empty(); + } + if (!(authentication.getPrincipal() instanceof BlogUser user)) { + return Optional.empty(); + } + return Optional.of(user); + } + + @NotNull + public static Optional getCurrentUserUUID() { + return getCurrentUser().map(BlogUser::getId); + } + + @NotNull + public static UserRole getCurrentUserRole() { + return getCurrentUser().map(BlogUser::getRole).orElse(UserRole.GUEST); + } + + @Nullable + public static ResponseVO checkAdminPermission() { + BlogUser user = BlogUtils.getCurrentUser().orElse(null); + if (user == null) { + return ResponseVO.unauthorized(); + } + if (user.getRole() != UserRole.ADMIN) { + return ResponseVO.failed("你没有这个权限!"); + } + return null; + } } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/PageableVO.java b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/PageableVO.java index 7fe67eb..69f4be3 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/PageableVO.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/PageableVO.java @@ -2,6 +2,7 @@ package cn.hamster3.application.blog.vo; import lombok.AllArgsConstructor; import lombok.Data; +import org.jetbrains.annotations.NotNull; import org.springframework.data.domain.Page; import java.util.List; @@ -15,11 +16,13 @@ public class PageableVO { private int totalPage; private List data; - public static ResponseVO> success(Page page) { + @NotNull + public static ResponseVO> success(@NotNull Page page) { return ResponseVO.success(of(page)); } - public static PageableVO of(Page page) { + @NotNull + public static PageableVO of(@NotNull Page page) { return new PageableVO<>( page.getNumber(), page.getSize(), diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/ResponseVO.java b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/ResponseVO.java index da63140..475fe79 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/ResponseVO.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/ResponseVO.java @@ -10,29 +10,39 @@ import org.jetbrains.annotations.Nullable; public class ResponseVO { @NotNull private Integer code; - @NotNull + @Nullable private String msg; @Nullable private T data; + @NotNull public static ResponseVO success() { - return new ResponseVO<>(200, "", null); + return new ResponseVO<>(200, null, null); } - public static ResponseVO success(T data) { - return new ResponseVO<>(200, "", data); + @NotNull + public static ResponseVO success(@Nullable T data) { + return new ResponseVO<>(200, null, data); } - public static ResponseVO success(String msg, T data) { + @NotNull + public static ResponseVO success(@Nullable String msg, @Nullable T data) { return new ResponseVO<>(200, msg, data); } + @NotNull + public static ResponseVO failed(@Nullable String msg) { + return new ResponseVO<>(403, msg, null); + } + + @NotNull public static ResponseVO unauthorized() { return new ResponseVO<>(401, "Unauthorized", null); } - public static ResponseVO failed(@NotNull String msg) { - return new ResponseVO<>(403, msg, null); + @NotNull + public static ResponseVO notFound() { + return new ResponseVO<>(404, "Not Found", null); } } diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/blog/BlogInfoResponseVO.java b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/blog/BlogInfoResponseVO.java index e6df031..cffeef9 100644 --- a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/blog/BlogInfoResponseVO.java +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/blog/BlogInfoResponseVO.java @@ -8,6 +8,7 @@ import lombok.Data; import java.util.Date; import java.util.List; import java.util.Set; + @Data @AllArgsConstructor public class BlogInfoResponseVO { diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingInfoResponseVO.java b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingInfoResponseVO.java new file mode 100644 index 0000000..f7d0ff4 --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingInfoResponseVO.java @@ -0,0 +1,15 @@ +package cn.hamster3.application.blog.vo.setting; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.Date; + +@Data +@AllArgsConstructor +public class SettingInfoResponseVO { + private String id; + private String content; + private Date createTime; + private Date updateTime; +} diff --git a/blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingUpdateRequireVO.java b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingUpdateRequireVO.java new file mode 100644 index 0000000..f7cc021 --- /dev/null +++ b/blog-backend/src/main/java/cn/hamster3/application/blog/vo/setting/SettingUpdateRequireVO.java @@ -0,0 +1,14 @@ +package cn.hamster3.application.blog.vo.setting; + +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SettingUpdateRequireVO { + @NotBlank(message = "网站设置内容不能为空!") + private String content; +}