feat: 开发中...
This commit is contained in:
@@ -2,8 +2,11 @@ package cn.hamster3.application.blog.config;
|
|||||||
|
|
||||||
import cn.hamster3.application.blog.vo.ResponseVO;
|
import cn.hamster3.application.blog.vo.ResponseVO;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.ConstraintViolation;
|
||||||
|
import jakarta.validation.ConstraintViolationException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||||
|
import org.springframework.core.NestedRuntimeException;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
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)
|
@ExceptionHandler(Exception.class)
|
||||||
public ResponseVO<String> onException(Exception e) {
|
public ResponseVO<String> onException(Exception e) {
|
||||||
if ("dev".equals(environment.getProperty("spring.profiles.active"))) {
|
if ("dev".equals(environment.getProperty("spring.profiles.active"))) {
|
||||||
|
@@ -1,9 +1,13 @@
|
|||||||
package cn.hamster3.application.blog.config;
|
package cn.hamster3.application.blog.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.ProviderManager;
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
@@ -31,26 +35,12 @@ public class WebConfig {
|
|||||||
return new ProviderManager(provider);
|
return new ProviderManager(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Bean
|
@Bean
|
||||||
// public AuthenticationManager getAuthenticationManager() {
|
@ConditionalOnMissingBean(ObjectMapper.class)
|
||||||
// return new AuthenticationManager() {
|
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
|
||||||
// @Resource
|
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
|
||||||
// private UserDetailsService userDetailsService;
|
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||||
//
|
return objectMapper;
|
||||||
// @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;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package cn.hamster3.application.blog.config.security;
|
package cn.hamster3.application.blog.config.security;
|
||||||
|
|
||||||
|
import cn.hamster3.application.blog.constant.UserRole;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
@@ -10,9 +11,11 @@ import java.util.UUID;
|
|||||||
@Getter
|
@Getter
|
||||||
public class BlogUser extends User {
|
public class BlogUser extends User {
|
||||||
private final UUID id;
|
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);
|
super(username, password, authorities);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.role = role;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,8 @@ public class BlogUserDetailService implements UserDetailsService {
|
|||||||
user.getEmail(),
|
user.getEmail(),
|
||||||
user.getPassword(),
|
user.getPassword(),
|
||||||
Collections.singleton(user.getRole().getAuthority()),
|
Collections.singleton(user.getRole().getAuthority()),
|
||||||
user.getId()
|
user.getId(),
|
||||||
|
user.getRole()
|
||||||
)).orElseThrow(() -> new UsernameNotFoundException("user not found."));
|
)).orElseThrow(() -> new UsernameNotFoundException("user not found."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,12 @@
|
|||||||
package cn.hamster3.application.blog.config.security;
|
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.UserEntity;
|
||||||
|
import cn.hamster3.application.blog.entity.repo.UserRepository;
|
||||||
|
import cn.hamster3.application.blog.util.BlogUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.data.domain.AuditorAware;
|
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 org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -20,36 +18,9 @@ public class UserAuditorAware implements AuditorAware<UserEntity> {
|
|||||||
@Resource
|
@Resource
|
||||||
private UserRepository userRepo;
|
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
|
@Override
|
||||||
public @NotNull Optional<UserEntity> getCurrentAuditor() {
|
public @NotNull Optional<UserEntity> getCurrentAuditor() {
|
||||||
UUID uuid = UserAuditorAware.currentUserUUID().orElse(null);
|
UUID uuid = BlogUtils.getCurrentUserUUID().orElse(null);
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,9 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|||||||
|
|
||||||
public enum UserRole {
|
public enum UserRole {
|
||||||
/**
|
/**
|
||||||
* 读者
|
* 访客
|
||||||
*/
|
*/
|
||||||
USER,
|
GUEST,
|
||||||
/**
|
/**
|
||||||
* 作者
|
* 作者
|
||||||
*/
|
*/
|
||||||
|
@@ -40,7 +40,7 @@ public class BlogController {
|
|||||||
@Parameter(description = "页码", example = "0") int page,
|
@Parameter(description = "页码", example = "0") int page,
|
||||||
@Parameter(description = "大小", example = "10") int size
|
@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}/")
|
@PutMapping("/{blogID}/")
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -60,7 +60,7 @@ public class UserController {
|
|||||||
@Parameter(description = "页码", example = "0") int page,
|
@Parameter(description = "页码", example = "0") int page,
|
||||||
@Parameter(description = "大小", example = "10") int size
|
@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}/")
|
@GetMapping("/{userID}/")
|
||||||
@@ -76,7 +76,7 @@ public class UserController {
|
|||||||
@Parameter(description = "页码", example = "0") int page,
|
@Parameter(description = "页码", example = "0") int page,
|
||||||
@Parameter(description = "大小", example = "10") int size
|
@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/")
|
@GetMapping("/{userID}/attach/")
|
||||||
@@ -86,6 +86,6 @@ public class UserController {
|
|||||||
@Parameter(description = "页码", example = "0") int page,
|
@Parameter(description = "页码", example = "0") int page,
|
||||||
@Parameter(description = "大小", example = "10") int size
|
@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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,18 +2,18 @@ package cn.hamster3.application.blog.entity;
|
|||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
|
||||||
import org.springframework.data.annotation.CreatedBy;
|
import org.springframework.data.annotation.CreatedBy;
|
||||||
import org.springframework.data.annotation.CreatedDate;
|
import org.springframework.data.annotation.CreatedDate;
|
||||||
import org.springframework.data.annotation.LastModifiedBy;
|
import org.springframework.data.annotation.LastModifiedBy;
|
||||||
import org.springframework.data.annotation.LastModifiedDate;
|
import org.springframework.data.annotation.LastModifiedDate;
|
||||||
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "blog_attach_entity")
|
@Table(name = "blog_attach_entity")
|
||||||
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
public class BlogAttachEntity {
|
public class BlogAttachEntity {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
@@ -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;
|
||||||
|
}
|
@@ -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;
|
|
||||||
}
|
|
@@ -13,9 +13,9 @@ import java.util.UUID;
|
|||||||
|
|
||||||
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
|
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
|
||||||
public interface BlogMapper {
|
public interface BlogMapper {
|
||||||
BlogEntity voToEntity(BlogUpdateRequireVO requireVO);
|
BlogEntity voToEntity(BlogUpdateRequireVO vo);
|
||||||
|
|
||||||
BlogInfoResponseVO entityToInfoVO(BlogEntity requireVO);
|
BlogInfoResponseVO entityToInfoVO(BlogEntity entity);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@@ -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);
|
||||||
|
}
|
@@ -9,7 +9,7 @@ import org.mapstruct.ReportingPolicy;
|
|||||||
|
|
||||||
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
|
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
|
||||||
public interface UserMapper {
|
public interface UserMapper {
|
||||||
UserEntity voToEntity(UserCreateRequireVO requireVO);
|
UserEntity voToEntity(UserCreateRequireVO vo);
|
||||||
|
|
||||||
UserInfoResponseVO entityToInfoVO(UserEntity entity);
|
UserInfoResponseVO entityToInfoVO(UserEntity entity);
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
}
|
@@ -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);
|
||||||
|
}
|
@@ -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.BlogUser;
|
||||||
import cn.hamster3.application.blog.config.security.UserAuditorAware;
|
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.BlogEntity;
|
||||||
import cn.hamster3.application.blog.entity.UserEntity;
|
import cn.hamster3.application.blog.entity.UserEntity;
|
||||||
import cn.hamster3.application.blog.entity.mapper.BlogMapper;
|
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.service.IBlogService;
|
||||||
|
import cn.hamster3.application.blog.util.BlogUtils;
|
||||||
import cn.hamster3.application.blog.vo.ResponseVO;
|
import cn.hamster3.application.blog.vo.ResponseVO;
|
||||||
import cn.hamster3.application.blog.vo.blog.BlogInfoResponseVO;
|
import cn.hamster3.application.blog.vo.blog.BlogInfoResponseVO;
|
||||||
import cn.hamster3.application.blog.vo.blog.BlogUpdateRequireVO;
|
import cn.hamster3.application.blog.vo.blog.BlogUpdateRequireVO;
|
||||||
@@ -62,7 +63,7 @@ public class BlogService implements IBlogService {
|
|||||||
if (!blogRepo.existsById(blogID)) {
|
if (!blogRepo.existsById(blogID)) {
|
||||||
return ResponseVO.failed("该博文不存在!");
|
return ResponseVO.failed("该博文不存在!");
|
||||||
}
|
}
|
||||||
BlogUser user = UserAuditorAware.currentUser().orElse(null);
|
BlogUser user = BlogUtils.getCurrentUser().orElse(null);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return ResponseVO.unauthorized();
|
return ResponseVO.unauthorized();
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,16 +1,16 @@
|
|||||||
package cn.hamster3.application.blog.service.impl;
|
package cn.hamster3.application.blog.service.impl;
|
||||||
|
|
||||||
import cn.hamster3.application.blog.config.security.BlogUser;
|
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.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.UserEntity;
|
||||||
import cn.hamster3.application.blog.entity.mapper.AttachMapper;
|
import cn.hamster3.application.blog.entity.mapper.AttachMapper;
|
||||||
import cn.hamster3.application.blog.entity.mapper.BlogMapper;
|
import cn.hamster3.application.blog.entity.mapper.BlogMapper;
|
||||||
import cn.hamster3.application.blog.entity.mapper.UserMapper;
|
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.service.IUserService;
|
||||||
|
import cn.hamster3.application.blog.util.BlogUtils;
|
||||||
import cn.hamster3.application.blog.vo.PageableVO;
|
import cn.hamster3.application.blog.vo.PageableVO;
|
||||||
import cn.hamster3.application.blog.vo.ResponseVO;
|
import cn.hamster3.application.blog.vo.ResponseVO;
|
||||||
import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO;
|
import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO;
|
||||||
@@ -55,7 +55,7 @@ public class UserService implements IUserService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ResponseVO<UserInfoResponseVO> getCurrentUserInfo() {
|
public @NotNull ResponseVO<UserInfoResponseVO> getCurrentUserInfo() {
|
||||||
UUID uuid = UserAuditorAware.currentUserUUID().orElse(null);
|
UUID uuid = BlogUtils.getCurrentUserUUID().orElse(null);
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
return ResponseVO.unauthorized();
|
return ResponseVO.unauthorized();
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ public class UserService implements IUserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
entity.setPassword(passwordEncoder.encode(entity.getPassword()));
|
entity.setPassword(passwordEncoder.encode(entity.getPassword()));
|
||||||
entity.setRole(UserRole.USER);
|
entity.setRole(UserRole.AUTHOR);
|
||||||
log.info("prepare to save userinfo: {}", entity);
|
log.info("prepare to save userinfo: {}", entity);
|
||||||
UserEntity save = userRepo.save(entity);
|
UserEntity save = userRepo.save(entity);
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ public class UserService implements IUserService {
|
|||||||
if (userEntity == null) {
|
if (userEntity == null) {
|
||||||
return ResponseVO.failed("未找到该用户!");
|
return ResponseVO.failed("未找到该用户!");
|
||||||
}
|
}
|
||||||
BlogUser blogUser = UserAuditorAware.currentUser().orElse(null);
|
BlogUser blogUser = BlogUtils.getCurrentUser().orElse(null);
|
||||||
if (blogUser == null) {
|
if (blogUser == null) {
|
||||||
return ResponseVO.unauthorized();
|
return ResponseVO.unauthorized();
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,61 @@
|
|||||||
package cn.hamster3.application.blog.util;
|
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 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
|
@Slf4j
|
||||||
public class BlogUtils {
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package cn.hamster3.application.blog.vo;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -15,11 +16,13 @@ public class PageableVO<T> {
|
|||||||
private int totalPage;
|
private int totalPage;
|
||||||
private List<T> data;
|
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));
|
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<>(
|
return new PageableVO<>(
|
||||||
page.getNumber(),
|
page.getNumber(),
|
||||||
page.getSize(),
|
page.getSize(),
|
||||||
|
@@ -10,29 +10,39 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
public class ResponseVO<T> {
|
public class ResponseVO<T> {
|
||||||
@NotNull
|
@NotNull
|
||||||
private Integer code;
|
private Integer code;
|
||||||
@NotNull
|
@Nullable
|
||||||
private String msg;
|
private String msg;
|
||||||
@Nullable
|
@Nullable
|
||||||
private T data;
|
private T data;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public static ResponseVO<Void> success() {
|
public static ResponseVO<Void> success() {
|
||||||
return new ResponseVO<>(200, "", null);
|
return new ResponseVO<>(200, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ResponseVO<T> success(T data) {
|
@NotNull
|
||||||
return new ResponseVO<>(200, "", data);
|
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);
|
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() {
|
public static <T> ResponseVO<T> unauthorized() {
|
||||||
return new ResponseVO<>(401, "Unauthorized", null);
|
return new ResponseVO<>(401, "Unauthorized", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ResponseVO<T> failed(@NotNull String msg) {
|
@NotNull
|
||||||
return new ResponseVO<>(403, msg, null);
|
public static <T> ResponseVO<T> notFound() {
|
||||||
|
return new ResponseVO<>(404, "Not Found", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import lombok.Data;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class BlogInfoResponseVO {
|
public class BlogInfoResponseVO {
|
||||||
|
@@ -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;
|
||||||
|
}
|
@@ -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;
|
||||||
|
}
|
Reference in New Issue
Block a user