feat: 开发中...

This commit is contained in:
2023-03-17 03:55:20 +08:00
parent 8233fd5141
commit 9949fba3ed
25 changed files with 325 additions and 67 deletions

View File

@@ -1,15 +1,16 @@
package cn.hamster3.application.blog.config; package cn.hamster3.application.blog.config;
import cn.hamster3.application.blog.config.security.BlogUser;
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.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
@Configuration @Configuration
public class WebConfig { public class WebConfig {
@@ -19,14 +20,14 @@ public class WebConfig {
} }
@Bean @Bean
public AuditorAware<String> getUserIDAuditorAware() { public AuditorAware<UUID> getUserIDAuditorAware() {
return () -> { return () -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) { if (authentication == null || !authentication.isAuthenticated()) {
return Optional.empty(); return Optional.empty();
} }
User user = (User) authentication.getPrincipal(); BlogUser user = (BlogUser) authentication.getPrincipal();
return Optional.of(user.getUsername()); return Optional.of(user.getUuid());
}; };
} }

View File

@@ -0,0 +1,18 @@
package cn.hamster3.application.blog.config.security;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
import java.util.UUID;
@Getter
public class BlogUser extends User {
private final UUID uuid;
public BlogUser(String username, String password, Collection<? extends GrantedAuthority> authorities, UUID uuid) {
super(username, password, authorities);
this.uuid = uuid;
}
}

View File

@@ -1,6 +1,7 @@
package cn.hamster3.application.blog.config.security; package cn.hamster3.application.blog.config.security;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
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.context.annotation.Profile; import org.springframework.context.annotation.Profile;
@@ -32,7 +33,7 @@ public class DevSecurityConfiguration {
log.info("add cors configuration..."); log.info("add cors configuration...");
return new WebMvcConfigurer() { return new WebMvcConfigurer() {
@Override @Override
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(@NotNull CorsRegistry registry) {
registry.addMapping("/**") registry.addMapping("/**")
.allowedOriginPatterns("*") .allowedOriginPatterns("*")
.allowedMethods("*") .allowedMethods("*")

View File

@@ -1,10 +1,8 @@
package cn.hamster3.application.blog.config.security; package cn.hamster3.application.blog.config.security;
import cn.hamster3.application.blog.constant.UserPermissions;
import cn.hamster3.application.blog.dao.UserRepository; import cn.hamster3.application.blog.dao.UserRepository;
import cn.hamster3.application.blog.entity.UserEntity;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -17,14 +15,15 @@ public class UserDetailServiceImpl implements UserDetailsService {
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userRepo.findByEmailOrNicknameAllIgnoreCase(username, username, UserEntity.class) return userRepo.findByEmailIgnoreCaseWithPermission(username)
.map(user -> new User( .map(user -> new BlogUser(
user.getId().toString(), user.getEmail(),
user.getPassword(), user.getPassword(),
user.getPermissions() user.getPermissions()
.stream() .stream()
.map(permission -> new SimpleGrantedAuthority(permission.name())) .map(UserPermissions::getAuthority)
.toList() .toList(),
user.getId()
)).orElseThrow(() -> new UsernameNotFoundException("user not found.")); )).orElseThrow(() -> new UsernameNotFoundException("user not found."));
} }
} }

View File

@@ -1,5 +0,0 @@
package cn.hamster3.application.blog.constant;
public enum UserPermission {
}

View File

@@ -0,0 +1,17 @@
package cn.hamster3.application.blog.constant;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
public enum UserPermissions {
MODIFY_USER_INFO,
MODIFY_USER_PERMISSION;
private final SimpleGrantedAuthority authority;
UserPermissions() {
this.authority = new SimpleGrantedAuthority(name());
}
public SimpleGrantedAuthority getAuthority() {
return authority;
}
}

View File

@@ -1,16 +0,0 @@
package cn.hamster3.application.blog.constant;
public enum UserRole {
/**
* 游客
*/
GUEST,
/**
* 作者
*/
AUTHOR,
/**
* 管理员
*/
ADMINISTRATOR
}

View File

@@ -0,0 +1,13 @@
package cn.hamster3.application.blog.controller;
import cn.hamster3.application.blog.vo.ResponseVO;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class ExceptionController {
@ExceptionHandler(Exception.class)
public ResponseVO<String> onException(Exception e) {
return ResponseVO.failed(e);
}
}

View File

@@ -2,10 +2,8 @@ package cn.hamster3.application.blog.controller;
import cn.hamster3.application.blog.service.IUserService; import cn.hamster3.application.blog.service.IUserService;
import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.ResponseVO;
import cn.hamster3.application.blog.vo.user.UserInfoResponseVO; import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO;
import cn.hamster3.application.blog.vo.user.UserRegisterRequireVO; import cn.hamster3.application.blog.vo.user.*;
import cn.hamster3.application.blog.vo.user.UserRegisterResponseVO;
import cn.hamster3.application.blog.vo.user.UserUpdateRequireVO;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@@ -13,6 +11,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
/** /**
* 用户相关接口 * 用户相关接口
@@ -23,14 +22,19 @@ public class UserController {
@Resource @Resource
private IUserService userService; private IUserService userService;
@PostMapping("/login")
public ResponseVO<Void> loginUser(@RequestBody @Valid UserLoginRequireVO requireVO) {
return userService.loginUser(requireVO);
}
@PostMapping("/") @PostMapping("/")
public ResponseVO<UserRegisterResponseVO> createUser(@RequestBody @Valid UserRegisterRequireVO requireVO) { public ResponseVO<UserRegisterResponseVO> createUser(@RequestBody @Valid UserCreateRequireVO requireVO) {
return userService.registerUser(requireVO); return userService.createUser(requireVO);
} }
@PutMapping("/") @PutMapping("/")
public ResponseVO<Void> updateUser(@RequestBody @Valid UserUpdateRequireVO requireVO) { public ResponseVO<Void> updateUser(@RequestBody @Valid UserUpdateRequireVO requireVO) {
return ResponseVO.success(); return userService.updateUser(requireVO);
} }
@GetMapping("/") @GetMapping("/")
@@ -39,12 +43,12 @@ public class UserController {
} }
@GetMapping("/{userID}/") @GetMapping("/{userID}/")
public ResponseVO<UserInfoResponseVO> getUserInfo(@PathVariable String userID) { public ResponseVO<UserInfoResponseVO> getUserInfo(@PathVariable UUID userID) {
return ResponseVO.success(null); return userService.getUserInfo(userID);
} }
@GetMapping("/{userID}/attaches") @GetMapping("/{userID}/attaches")
public ResponseVO<Void> getUserAttaches(@PathVariable String userID) { public ResponseVO<List<AttachInfoResponseVO>> getUserAttaches(@PathVariable UUID userID) {
return ResponseVO.success(null); return userService.getUserAttaches(userID);
} }
} }

View File

@@ -0,0 +1,8 @@
package cn.hamster3.application.blog.dao;
import cn.hamster3.application.blog.entity.AttachEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface AttachRepository extends JpaRepository<AttachEntity, Long>, JpaSpecificationExecutor<AttachEntity> {
}

View File

@@ -10,10 +10,14 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public interface UserRepository extends JpaRepository<UserEntity, UUID>, JpaSpecificationExecutor<BlogEntity> { public interface UserRepository extends JpaRepository<UserEntity, UUID>, JpaSpecificationExecutor<BlogEntity> {
@EntityGraph(attributePaths = {"permissions"})
Optional<UserEntity> findByEmailIgnoreCaseWithPermission(String email);
boolean existsByNicknameIgnoreCase(String nickname); boolean existsByNicknameIgnoreCase(String nickname);
boolean existsByEmailIgnoreCase(String email); boolean existsByEmailIgnoreCase(String email);
@EntityGraph(attributePaths = {"permissions"}) @EntityGraph(attributePaths = {"attachEntities"})
<T> Optional<T> findByEmailOrNicknameAllIgnoreCase(String email, String nickname, Class<T> type); UserEntity findByIdWithAttach(UUID uuid);
} }

View File

@@ -1,7 +1,6 @@
package cn.hamster3.application.blog.entity; package cn.hamster3.application.blog.entity;
import cn.hamster3.application.blog.constant.UserPermission; import cn.hamster3.application.blog.constant.UserPermissions;
import cn.hamster3.application.blog.constant.UserRole;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -36,19 +35,21 @@ public class UserEntity {
@Column(name = "password", nullable = false, length = 32) @Column(name = "password", nullable = false, length = 32)
private String password; private String password;
@Setter
@ToString.Exclude
@ElementCollection @ElementCollection
@Column(name = "permission") @Column(name = "permission")
@CollectionTable(name = "user_entity_permissions", joinColumns = @JoinColumn(name = "user_id")) @CollectionTable(name = "user_entity_permissions", joinColumns = @JoinColumn(name = "user_id"))
private Set<UserPermission> permissions = new HashSet<>(); private Set<UserPermissions> permissions = new HashSet<>();
@Enumerated
@Column(name = "role", nullable = false)
private UserRole role;
@Setter
@ToString.Exclude
@OneToMany(mappedBy = "uploader", orphanRemoval = true) @OneToMany(mappedBy = "uploader", orphanRemoval = true)
@OrderBy("create_time DESC") @OrderBy("create_time DESC")
private List<AttachEntity> attachEntities = new ArrayList<>(); private List<AttachEntity> attachEntities = new ArrayList<>();
@Setter
@ToString.Exclude
@OneToMany(mappedBy = "uploader", orphanRemoval = true) @OneToMany(mappedBy = "uploader", orphanRemoval = true)
@OrderBy("create_time DESC") @OrderBy("create_time DESC")
private List<BlogEntity> blogEntities = new ArrayList<>(); private List<BlogEntity> blogEntities = new ArrayList<>();

View File

@@ -0,0 +1,13 @@
package cn.hamster3.application.blog.entity.mapper;
import cn.hamster3.application.blog.entity.AttachEntity;
import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy;
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
public interface AttachMapper {
AttachInfoResponseVO entityToInfoVO(AttachEntity entity);
}

View File

@@ -1,16 +1,19 @@
package cn.hamster3.application.blog.entity.mapper; package cn.hamster3.application.blog.entity.mapper;
import cn.hamster3.application.blog.entity.UserEntity; import cn.hamster3.application.blog.entity.UserEntity;
import cn.hamster3.application.blog.vo.user.UserCreateRequireVO;
import cn.hamster3.application.blog.vo.user.UserInfoResponseVO; import cn.hamster3.application.blog.vo.user.UserInfoResponseVO;
import cn.hamster3.application.blog.vo.user.UserRegisterRequireVO;
import cn.hamster3.application.blog.vo.user.UserRegisterResponseVO; import cn.hamster3.application.blog.vo.user.UserRegisterResponseVO;
import cn.hamster3.application.blog.vo.user.UserUpdateRequireVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants; import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy; 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(UserRegisterRequireVO requireVO); UserEntity voToEntity(UserCreateRequireVO requireVO);
UserEntity voToEntity(UserUpdateRequireVO requireVO);
UserInfoResponseVO entityToInfoVO(UserEntity requireVO); UserInfoResponseVO entityToInfoVO(UserEntity requireVO);

View File

@@ -2,7 +2,8 @@ package cn.hamster3.application.blog.service;
import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.ResponseVO;
import cn.hamster3.application.blog.vo.blog.BlogCreateRequireVO; import cn.hamster3.application.blog.vo.blog.BlogCreateRequireVO;
import org.jetbrains.annotations.NotNull;
public interface IBlogService { public interface IBlogService {
ResponseVO<Long> createBlog(BlogCreateRequireVO requireVO); @NotNull ResponseVO<Long> createBlog(@NotNull BlogCreateRequireVO requireVO);
} }

View File

@@ -1,10 +1,22 @@
package cn.hamster3.application.blog.service; package cn.hamster3.application.blog.service;
import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.ResponseVO;
import cn.hamster3.application.blog.vo.user.UserRegisterRequireVO; import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO;
import cn.hamster3.application.blog.vo.user.UserRegisterResponseVO; import cn.hamster3.application.blog.vo.user.*;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
import java.util.UUID;
public interface IUserService { public interface IUserService {
@NotNull ResponseVO<UserRegisterResponseVO> registerUser(@NotNull UserRegisterRequireVO requireVO); @NotNull ResponseVO<Void> loginUser(@NotNull UserLoginRequireVO requireVO);
@NotNull ResponseVO<UserRegisterResponseVO> createUser(@NotNull UserCreateRequireVO requireVO);
@NotNull ResponseVO<Void> updateUser(@NotNull UserUpdateRequireVO requireVO);
@NotNull ResponseVO<UserInfoResponseVO> getUserInfo(UUID id);
@NotNull ResponseVO<List<AttachInfoResponseVO>> getUserAttaches(@PathVariable UUID userID);
} }

View File

@@ -7,6 +7,7 @@ import cn.hamster3.application.blog.service.IBlogService;
import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.ResponseVO;
import cn.hamster3.application.blog.vo.blog.BlogCreateRequireVO; import cn.hamster3.application.blog.vo.blog.BlogCreateRequireVO;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@@ -17,7 +18,7 @@ public class BlogService implements IBlogService {
private BlogRepository blogRepo; private BlogRepository blogRepo;
@Override @Override
public ResponseVO<Long> createBlog(BlogCreateRequireVO requireVO) { public @NotNull ResponseVO<Long> createBlog(@NotNull BlogCreateRequireVO requireVO) {
BlogEntity entity = blogMapper.voToEntity(requireVO); BlogEntity entity = blogMapper.voToEntity(requireVO);
BlogEntity save = blogRepo.save(entity); BlogEntity save = blogRepo.save(entity);
return ResponseVO.success(save.getId()); return ResponseVO.success(save.getId());

View File

@@ -1,28 +1,78 @@
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.constant.UserPermissions;
import cn.hamster3.application.blog.dao.UserRepository; import cn.hamster3.application.blog.dao.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.UserMapper; import cn.hamster3.application.blog.entity.mapper.UserMapper;
import cn.hamster3.application.blog.service.IUserService; import cn.hamster3.application.blog.service.IUserService;
import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.ResponseVO;
import cn.hamster3.application.blog.vo.user.UserRegisterRequireVO; import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO;
import cn.hamster3.application.blog.vo.user.UserRegisterResponseVO; import cn.hamster3.application.blog.vo.user.*;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
import java.util.UUID;
@Service @Service
public class UserService implements IUserService { public class UserService implements IUserService {
@Resource @Resource
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
@Resource @Resource
private UserMapper userMapper; private UserMapper userMapper;
@Resource
private AttachMapper attachMapper;
@Resource @Resource
private UserRepository userRepo; private UserRepository userRepo;
@Resource
private AuthenticationManager authenticationManager;
@Override @Override
public @NotNull ResponseVO<UserRegisterResponseVO> registerUser(@NotNull UserRegisterRequireVO requireVO) { public @NotNull ResponseVO<Void> loginUser(@NotNull UserLoginRequireVO requireVO) {
UserEntity userEntity = userRepo.findByEmailIgnoreCaseWithPermission(requireVO.getEmail()).orElse(null);
if (userEntity == null) {
return ResponseVO.failed("未找到该邮箱!");
}
if (!passwordEncoder.matches(requireVO.getPassword(), userEntity.getPassword())) {
return ResponseVO.failed("密码错误!");
}
List<SimpleGrantedAuthority> userPermissions = userEntity.getPermissions().stream()
.map(UserPermissions::getAuthority)
.toList();
BlogUser blogUser = new BlogUser(
userEntity.getEmail(),
userEntity.getPassword(),
userPermissions,
userEntity.getId()
);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
blogUser,
requireVO.getPassword(),
blogUser.getAuthorities()
);
authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(token);
return ResponseVO.success();
}
@Override
public @NotNull ResponseVO<UserRegisterResponseVO> createUser(@NotNull UserCreateRequireVO requireVO) {
UserEntity entity = userMapper.voToEntity(requireVO); UserEntity entity = userMapper.voToEntity(requireVO);
entity.setEmail(entity.getEmail().toLowerCase()); entity.setEmail(entity.getEmail().toLowerCase());
@@ -39,4 +89,69 @@ public class UserService implements IUserService {
return ResponseVO.success("注册成功!", userMapper.entityToRegisterVO(save)); return ResponseVO.success("注册成功!", userMapper.entityToRegisterVO(save));
} }
@Override
public @NotNull ResponseVO<Void> updateUser(@NotNull UserUpdateRequireVO requireVO) {
UserEntity userEntity = userRepo.findById(requireVO.getId()).orElse(null);
if (userEntity == null) {
return ResponseVO.failed("未找到该用户!");
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return ResponseVO.failed("你没有这个权限!");
}
BlogUser blogUser = (BlogUser) authentication.getPrincipal();
if (!blogUser.getUuid().equals(userEntity.getId())
&& blogUser.getAuthorities().contains(UserPermissions.MODIFY_USER_INFO.getAuthority())) {
return ResponseVO.failed("你没有这个权限!");
}
if (requireVO.getEmail() != null) {
if (userRepo.existsByEmailIgnoreCase(requireVO.getEmail())) {
return ResponseVO.failed("已存在相同邮箱的账户!");
}
userEntity.setEmail(requireVO.getEmail().toLowerCase());
}
if (requireVO.getNickname() != null) {
if (userRepo.existsByNicknameIgnoreCase(requireVO.getNickname())) {
return ResponseVO.failed("已存在相同的用户昵称!");
}
userEntity.setNickname(requireVO.getNickname());
}
if (requireVO.getPassword() != null) {
userEntity.setPassword(passwordEncoder.encode(requireVO.getPassword()));
}
if (requireVO.getPermissions() != null) {
if (!blogUser.getAuthorities().contains(UserPermissions.MODIFY_USER_PERMISSION.getAuthority())) {
return ResponseVO.failed("你没有这个权限!");
}
// 用户必须具有 MODIFY_USER_PERMISSION 权限,且操作对象不为用户自己时才能更改权限
if (blogUser.getUuid().equals(userEntity.getId())) {
return ResponseVO.failed("你不能更改自己的权限!");
}
userEntity.setPermissions(requireVO.getPermissions());
}
return ResponseVO.success();
}
@Override
public @NotNull ResponseVO<UserInfoResponseVO> getUserInfo(UUID id) {
return userRepo.findById(id)
.map(o -> ResponseVO.success(userMapper.entityToInfoVO(o)))
.orElse(ResponseVO.failed("未找到该用户!"));
}
@Override
public @NotNull ResponseVO<List<AttachInfoResponseVO>> getUserAttaches(@PathVariable UUID userID) {
UserEntity userEntity = userRepo.findByIdWithAttach(userID);
if (userEntity == null) {
return ResponseVO.failed("未找到该用户!");
}
List<AttachInfoResponseVO> list = userEntity.getAttachEntities()
.stream().map(o -> attachMapper.entityToInfoVO(o))
.toList();
return ResponseVO.success(list);
}
} }

View File

@@ -5,6 +5,9 @@ import lombok.Data;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.PrintWriter;
import java.io.StringWriter;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
public class ResponseVO<T> { public class ResponseVO<T> {
@@ -31,4 +34,11 @@ public class ResponseVO<T> {
return new ResponseVO<>(403, msg, null); return new ResponseVO<>(403, msg, null);
} }
public static ResponseVO<String> failed(Exception e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
// StringWriter 不需要 close()
return new ResponseVO<>(403, e.getMessage(), writer.toString());
}
} }

View File

@@ -0,0 +1,14 @@
package cn.hamster3.application.blog.vo.attach;
import lombok.Data;
import java.util.Date;
import java.util.UUID;
@Data
public class AttachInfoResponseVO {
private Long id;
private UUID uploader;
private Date createTime;
private Date updateTime;
}

View File

@@ -7,7 +7,7 @@ import lombok.Data;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
public class UserRegisterRequireVO { public class UserCreateRequireVO {
@Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "邮箱配置不合法!") @Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "邮箱配置不合法!")
private String email; private String email;
@Size(min = 3, max = 16, message = "用户昵称必须包含 3~16 个字符!") @Size(min = 3, max = 16, message = "用户昵称必须包含 3~16 个字符!")

View File

@@ -1,4 +1,14 @@
package cn.hamster3.application.blog.vo.user; package cn.hamster3.application.blog.vo.user;
import cn.hamster3.application.blog.constant.UserPermissions;
import java.util.Set;
import java.util.UUID;
public class UserInfoResponseVO { public class UserInfoResponseVO {
private UUID id;
private String email;
private String nickname;
private String password;
private Set<UserPermissions> permissions;
} }

View File

@@ -0,0 +1,15 @@
package cn.hamster3.application.blog.vo.user;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class UserLoginRequireVO {
@Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "邮箱不合法!")
private String email;
@Size(min = 8, max = 16, message = "密码必须包含 8~16 个字符!")
private String password;
}

View File

@@ -1,6 +1,6 @@
package cn.hamster3.application.blog.vo.user; package cn.hamster3.application.blog.vo.user;
import cn.hamster3.application.blog.constant.UserPermission; import cn.hamster3.application.blog.constant.UserPermissions;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@@ -14,7 +14,7 @@ public class UserRegisterResponseVO {
private UUID id; private UUID id;
private String email; private String email;
private String nickname; private String nickname;
private List<UserPermission> permissions; private List<UserPermissions> permissions;
private Date createTime; private Date createTime;
private Date updateTime; private Date updateTime;
} }

View File

@@ -1,4 +1,23 @@
package cn.hamster3.application.blog.vo.user; package cn.hamster3.application.blog.vo.user;
import cn.hamster3.application.blog.constant.UserPermissions;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.Set;
import java.util.UUID;
@Data
public class UserUpdateRequireVO { public class UserUpdateRequireVO {
@NotNull(message = "用户id不能为空")
private UUID id;
@Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "邮箱配置不合法!")
private String email;
@Size(min = 3, max = 16, message = "用户昵称必须包含 3~16 个字符!")
private String nickname;
@Size(min = 8, max = 16, message = "密码必须包含 8~16 个字符!")
private String password;
private Set<UserPermissions> permissions;
} }