feat: 开发中...

This commit is contained in:
2023-03-29 16:58:59 +08:00
parent b56d70ffe5
commit 4199c3a56b
27 changed files with 405 additions and 137 deletions

View File

@@ -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<String> 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<String> onException(Exception e) {
if ("dev".equals(environment.getProperty("spring.profiles.active"))) {

View File

@@ -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;
}
}

View File

@@ -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<? extends GrantedAuthority> authorities, UUID id) {
public BlogUser(String username, String password, Collection<? extends GrantedAuthority> authorities, UUID id, UserRole role) {
super(username, password, authorities);
this.id = id;
this.role = role;
}
}

View File

@@ -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."));
}
}

View File

@@ -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<UserEntity> {
@Resource
private UserRepository userRepo;
@NotNull
public static Optional<BlogUser> 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<UUID> currentUserUUID() {
return currentUser().map(BlogUser::getId);
}
@Override
public @NotNull Optional<UserEntity> getCurrentAuditor() {
UUID uuid = UserAuditorAware.currentUserUUID().orElse(null);
UUID uuid = BlogUtils.getCurrentUserUUID().orElse(null);
if (uuid == null) {
return Optional.empty();
}

View File

@@ -4,9 +4,9 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
public enum UserRole {
/**
* 读者
* 访客
*/
USER,
GUEST,
/**
* 作者
*/

View File

@@ -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}/")

View File

@@ -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<SettingInfoResponseVO> getSettingInfo(@Parameter(description = "设置ID") @PathVariable String id) {
return settingService.getSettingInfo(id);
}
@GetMapping("/{id}/content/")
@Operation(summary = "获取网站设置")
public ResponseVO<String> getSettingContent(@Parameter(description = "设置ID") @PathVariable String id) {
return settingService.getSettingContent(id);
}
@GetMapping("/")
@Operation(summary = "获取网站设置")
public ResponseVO<PageableVO<SettingInfoResponseVO>> 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<Void> updateSetting(
@Parameter(description = "设置ID") @PathVariable String id,
@RequestBody @Valid SettingUpdateRequireVO requireVO
) {
return settingService.updateSetting(id, requireVO);
}
@DeleteMapping("/{id}/")
@Operation(summary = "删除网站设置")
public ResponseVO<Void> deleteSetting(@Parameter(description = "设置ID") @PathVariable String id) {
return settingService.deleteSetting(id);
}
}

View File

@@ -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<String> getSiteSettings(@Parameter(description = "设置ID") @PathVariable String path) {
return ResponseVO.success(path);
}
}

View File

@@ -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)));
}
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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")

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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<SettingEntity, String>, JpaSpecificationExecutor<SettingEntity> {
@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);
}

View File

@@ -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<SettingInfoResponseVO> getSettingInfo(@NotNull String id);
@NotNull ResponseVO<String> getSettingContent(@NotNull String id);
@NotNull ResponseVO<PageableVO<SettingInfoResponseVO>> getSettingInfoList(@NotNull Pageable pageable);
@NotNull ResponseVO<Void> updateSetting(@NotNull String id, @NotNull SettingUpdateRequireVO requireVO);
@NotNull ResponseVO<Void> deleteSetting(@NotNull String id);
}

View File

@@ -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();
}

View File

@@ -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<SettingInfoResponseVO> 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<String> getSettingContent(@NotNull String id) {
SettingEntity entity = settingRepo.findByIdIgnoreCase(id);
if (entity == null) {
return ResponseVO.notFound();
}
return ResponseVO.success(entity.getContent());
}
@Override
public @NotNull ResponseVO<PageableVO<SettingInfoResponseVO>> getSettingInfoList(@NotNull Pageable pageable) {
return PageableVO.success(
settingRepo.findAll(pageable)
.map(o -> settingMapper.entityToInfoVO(o))
);
}
@Override
public @NotNull ResponseVO<Void> updateSetting(@NotNull String id, @NotNull SettingUpdateRequireVO requireVO) {
ResponseVO<Void> 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<Void> deleteSetting(@NotNull String id) {
ResponseVO<Void> check = BlogUtils.checkAdminPermission();
if (check != null) {
return check;
}
if (!settingRepo.existsByIdIgnoreCase(id)) {
return ResponseVO.notFound();
}
settingRepo.deleteByIdIgnoreCase(id);
return ResponseVO.success();
}
}

View File

@@ -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<UserInfoResponseVO> 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();
}

View File

@@ -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<BlogUser> 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<UUID> getCurrentUserUUID() {
return getCurrentUser().map(BlogUser::getId);
}
@NotNull
public static UserRole getCurrentUserRole() {
return getCurrentUser().map(BlogUser::getRole).orElse(UserRole.GUEST);
}
@Nullable
public static <T> ResponseVO<T> checkAdminPermission() {
BlogUser user = BlogUtils.getCurrentUser().orElse(null);
if (user == null) {
return ResponseVO.unauthorized();
}
if (user.getRole() != UserRole.ADMIN) {
return ResponseVO.failed("你没有这个权限!");
}
return null;
}
}

View File

@@ -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<T> {
private int totalPage;
private List<T> data;
public static <T> ResponseVO<PageableVO<T>> success(Page<T> page) {
@NotNull
public static <T> ResponseVO<PageableVO<T>> success(@NotNull Page<T> page) {
return ResponseVO.success(of(page));
}
public static <T> PageableVO<T> of(Page<T> page) {
@NotNull
public static <T> PageableVO<T> of(@NotNull Page<T> page) {
return new PageableVO<>(
page.getNumber(),
page.getSize(),

View File

@@ -10,29 +10,39 @@ import org.jetbrains.annotations.Nullable;
public class ResponseVO<T> {
@NotNull
private Integer code;
@NotNull
@Nullable
private String msg;
@Nullable
private T data;
@NotNull
public static ResponseVO<Void> success() {
return new ResponseVO<>(200, "", null);
return new ResponseVO<>(200, null, null);
}
public static <T> ResponseVO<T> success(T data) {
return new ResponseVO<>(200, "", data);
@NotNull
public static <T> ResponseVO<T> success(@Nullable T data) {
return new ResponseVO<>(200, null, data);
}
public static <T> ResponseVO<T> success(String msg, T data) {
@NotNull
public static <T> ResponseVO<T> success(@Nullable String msg, @Nullable T data) {
return new ResponseVO<>(200, msg, data);
}
@NotNull
public static <T> ResponseVO<T> failed(@Nullable String msg) {
return new ResponseVO<>(403, msg, null);
}
@NotNull
public static <T> ResponseVO<T> unauthorized() {
return new ResponseVO<>(401, "Unauthorized", null);
}
public static <T> ResponseVO<T> failed(@NotNull String msg) {
return new ResponseVO<>(403, msg, null);
@NotNull
public static <T> ResponseVO<T> notFound() {
return new ResponseVO<>(404, "Not Found", null);
}
}

View File

@@ -8,6 +8,7 @@ import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Set;
@Data
@AllArgsConstructor
public class BlogInfoResponseVO {

View File

@@ -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;
}

View File

@@ -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;
}