feat: 开发中...

This commit is contained in:
2023-03-27 00:17:27 +08:00
parent 9949fba3ed
commit d06e6d9f16
22 changed files with 201 additions and 66 deletions

View File

@@ -71,4 +71,4 @@ processResources {
clean { clean {
delete(files('bin')) delete(files('bin'))
} }

View File

@@ -26,8 +26,17 @@ public class WebConfig {
if (authentication == null || !authentication.isAuthenticated()) { if (authentication == null || !authentication.isAuthenticated()) {
return Optional.empty(); return Optional.empty();
} }
BlogUser user = (BlogUser) authentication.getPrincipal(); System.out.println("getUserIDAuditorAware");
return Optional.of(user.getUuid()); System.out.println(authentication.getName());
System.out.println(authentication.getPrincipal());
System.out.println(authentication.getCredentials());
System.out.println(authentication.getDetails());
System.out.println(authentication.getAuthorities());
Object userDetails = authentication.getDetails();
if (userDetails instanceof BlogUser user) {
return Optional.of(user.getUuid());
}
return Optional.empty();
}; };
} }

View File

@@ -0,0 +1,31 @@
package cn.hamster3.application.blog.config.security;
import jakarta.annotation.Resource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
@Component
public class BlogAuthenticationManager implements 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;
}
}

View File

@@ -1,6 +1,5 @@
package cn.hamster3.application.blog.config.security; package cn.hamster3.application.blog.config.security;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull; 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;
@@ -10,13 +9,11 @@ import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Slf4j
@Configuration @Configuration
@Profile("dev") @Profile("dev")
public class DevSecurityConfiguration { public class DevSecurityConfiguration {
@Bean @Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain getSecurityFilterChain(HttpSecurity http) throws Exception {
log.info("development environment security settings enabled.");
return http.authorizeHttpRequests(request -> request return http.authorizeHttpRequests(request -> request
.anyRequest().permitAll()) .anyRequest().permitAll())
.cors().and() .cors().and()
@@ -29,8 +26,7 @@ public class DevSecurityConfiguration {
} }
@Bean @Bean
public WebMvcConfigurer corsConfigurer() { public WebMvcConfigurer getWebMvcConfigurer() {
log.info("add cors configuration...");
return new WebMvcConfigurer() { return new WebMvcConfigurer() {
@Override @Override
public void addCorsMappings(@NotNull CorsRegistry registry) { public void addCorsMappings(@NotNull CorsRegistry registry) {
@@ -43,4 +39,5 @@ public class DevSecurityConfiguration {
} }
}; };
} }
} }

View File

@@ -1,6 +1,5 @@
package cn.hamster3.application.blog.config.security; package cn.hamster3.application.blog.config.security;
import lombok.extern.slf4j.Slf4j;
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;
@@ -8,13 +7,11 @@ import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
@Slf4j
@Configuration @Configuration
@Profile("prod") @Profile("prod")
public class SecurityConfiguration { public class SecurityConfiguration {
@Bean @Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain getSecurityFilterChain(HttpSecurity http) throws Exception {
log.info("production environment security settings enabled.");
return http.authorizeHttpRequests(request -> request return http.authorizeHttpRequests(request -> request
.requestMatchers(HttpMethod.GET, "/", "/index", "/index.html").permitAll() .requestMatchers(HttpMethod.GET, "/", "/index", "/index.html").permitAll()
.requestMatchers(HttpMethod.GET, "/favicon.ico", "/assets/**").permitAll() .requestMatchers(HttpMethod.GET, "/favicon.ico", "/assets/**").permitAll()
@@ -30,4 +27,5 @@ public class SecurityConfiguration {
.and() .and()
.build(); .build();
} }
} }

View File

@@ -3,11 +3,13 @@ package cn.hamster3.application.blog.config.security;
import cn.hamster3.application.blog.constant.UserPermissions; import cn.hamster3.application.blog.constant.UserPermissions;
import cn.hamster3.application.blog.dao.UserRepository; import cn.hamster3.application.blog.dao.UserRepository;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
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;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Slf4j
@Component @Component
public class UserDetailServiceImpl implements UserDetailsService { public class UserDetailServiceImpl implements UserDetailsService {
@Resource @Resource
@@ -15,7 +17,8 @@ public class UserDetailServiceImpl implements UserDetailsService {
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userRepo.findByEmailIgnoreCaseWithPermission(username) log.info("find user by email: {}", username);
return userRepo.findByEmailIgnoreCase(username)
.map(user -> new BlogUser( .map(user -> new BlogUser(
user.getEmail(), user.getEmail(),
user.getPassword(), user.getPassword(),

View File

@@ -8,6 +8,7 @@ import cn.hamster3.application.blog.vo.blog.BlogUpdateRequireVO;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@@ -26,13 +27,13 @@ public class BlogController {
} }
@GetMapping("/{blogID}/") @GetMapping("/{blogID}/")
public ResponseVO<BlogInfoResponseVO> getBlogInfo() { public ResponseVO<BlogInfoResponseVO> getBlogInfo(@PathVariable Long blogID) {
return null; return blogService.getBlogInfo(blogID);
} }
@GetMapping("/") @GetMapping("/")
public ResponseVO<List<BlogInfoResponseVO>> getBlogInfoList() { public ResponseVO<List<BlogInfoResponseVO>> getBlogInfoList(int page, int size) {
return null; return blogService.getBlogInfoList(PageRequest.of(page, size));
} }
@PutMapping("/{blogID}/") @PutMapping("/{blogID}/")

View File

@@ -1,13 +1,30 @@
package cn.hamster3.application.blog.controller; package cn.hamster3.application.blog.controller;
import cn.hamster3.application.blog.vo.ResponseVO; import cn.hamster3.application.blog.vo.ResponseVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.io.PrintWriter;
import java.io.StringWriter;
@Slf4j
@RestControllerAdvice @RestControllerAdvice
public class ExceptionController { public class ExceptionController {
@Resource
private Environment environment;
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
public ResponseVO<String> onException(Exception e) { public ResponseVO<String> onException(Exception e) {
return ResponseVO.failed(e); log.error("", e);
if ("dev".equals(environment.getProperty("spring.profiles.active"))) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
// StringWriter 不需要 close()
return new ResponseVO<>(403, e.getMessage(), writer.toString());
}
return ResponseVO.failed(e.getMessage());
} }
} }

View File

@@ -1,15 +1,16 @@
package cn.hamster3.application.blog.controller; 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.PageableResponseVO;
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;
import cn.hamster3.application.blog.vo.user.*; import cn.hamster3.application.blog.vo.user.*;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@@ -27,6 +28,11 @@ public class UserController {
return userService.loginUser(requireVO); return userService.loginUser(requireVO);
} }
@GetMapping("/current")
public ResponseVO<UserInfoResponseVO> currentUser() {
return userService.currentUser();
}
@PostMapping("/") @PostMapping("/")
public ResponseVO<UserRegisterResponseVO> createUser(@RequestBody @Valid UserCreateRequireVO requireVO) { public ResponseVO<UserRegisterResponseVO> createUser(@RequestBody @Valid UserCreateRequireVO requireVO) {
return userService.createUser(requireVO); return userService.createUser(requireVO);
@@ -38,8 +44,8 @@ public class UserController {
} }
@GetMapping("/") @GetMapping("/")
public ResponseVO<List<UserInfoResponseVO>> getAllUserInfo() { public ResponseVO<PageableResponseVO<UserInfoResponseVO>> getAllUserInfo(int page, int size) {
return ResponseVO.success(new ArrayList<>()); return userService.getAllUserInfo(PageRequest.of(page, size));
} }
@GetMapping("/{userID}/") @GetMapping("/{userID}/")

View File

@@ -2,6 +2,7 @@ package cn.hamster3.application.blog.dao;
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 org.jetbrains.annotations.NotNull;
import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -12,12 +13,13 @@ 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"}) @EntityGraph(attributePaths = {"permissions"})
Optional<UserEntity> findByEmailIgnoreCaseWithPermission(String email); Optional<UserEntity> findByEmailIgnoreCase(String email);
boolean existsByNicknameIgnoreCase(String nickname); boolean existsByNicknameIgnoreCase(String nickname);
boolean existsByEmailIgnoreCase(String email); boolean existsByEmailIgnoreCase(String email);
@EntityGraph(attributePaths = {"attachEntities"}) @EntityGraph(attributePaths = {"attachEntities"})
UserEntity findByIdWithAttach(UUID uuid); @NotNull
Optional<UserEntity> findById(@NotNull UUID uuid);
} }

View File

@@ -7,6 +7,7 @@ import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes; import org.hibernate.type.SqlTypes;
import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@@ -18,6 +19,7 @@ import java.util.List;
@Getter @Getter
@Entity @Entity
@Table(name = "blog_entity") @Table(name = "blog_entity")
@EntityListeners(AuditingEntityListener.class)
public class BlogEntity { public class BlogEntity {
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
@@ -44,10 +46,12 @@ public class BlogEntity {
private UserEntity uploader; private UserEntity uploader;
@CreatedDate @CreatedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "create_time", nullable = false) @Column(name = "create_time", nullable = false)
private Date createTime; private Date createTime;
@LastModifiedDate @LastModifiedDate
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "update_time", nullable = false) @Column(name = "update_time", nullable = false)
private Date updateTime; private Date updateTime;

View File

@@ -32,7 +32,7 @@ public class UserEntity {
private String nickname; private String nickname;
@Setter @Setter
@Column(name = "password", nullable = false, length = 32) @Column(name = "password", nullable = false, length = 60)
private String password; private String password;
@Setter @Setter

View File

@@ -1,13 +1,19 @@
package cn.hamster3.application.blog.entity.mapper; package cn.hamster3.application.blog.entity.mapper;
import cn.hamster3.application.blog.entity.AttachEntity; import cn.hamster3.application.blog.entity.AttachEntity;
import cn.hamster3.application.blog.entity.UserEntity;
import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO; import cn.hamster3.application.blog.vo.attach.AttachInfoResponseVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants; import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy; import org.mapstruct.ReportingPolicy;
import java.util.UUID;
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
public interface AttachMapper { public interface AttachMapper {
AttachInfoResponseVO entityToInfoVO(AttachEntity entity); AttachInfoResponseVO entityToInfoVO(AttachEntity entity);
default UUID map(UserEntity value) {
return value.getId();
}
} }

View File

@@ -2,8 +2,16 @@ 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 cn.hamster3.application.blog.vo.blog.BlogInfoResponseVO;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.data.domain.PageRequest;
import java.util.List;
public interface IBlogService { public interface IBlogService {
@NotNull ResponseVO<Long> createBlog(@NotNull BlogCreateRequireVO requireVO); @NotNull ResponseVO<Long> createBlog(@NotNull BlogCreateRequireVO requireVO);
@NotNull ResponseVO<BlogInfoResponseVO> getBlogInfo(@NotNull Long blogID);
@NotNull ResponseVO<List<BlogInfoResponseVO>> getBlogInfoList(@NotNull PageRequest page);
} }

View File

@@ -1,9 +1,11 @@
package cn.hamster3.application.blog.service; package cn.hamster3.application.blog.service;
import cn.hamster3.application.blog.vo.PageableResponseVO;
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;
import cn.hamster3.application.blog.vo.user.*; import cn.hamster3.application.blog.vo.user.*;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import java.util.List; import java.util.List;
@@ -12,10 +14,14 @@ import java.util.UUID;
public interface IUserService { public interface IUserService {
@NotNull ResponseVO<Void> loginUser(@NotNull UserLoginRequireVO requireVO); @NotNull ResponseVO<Void> loginUser(@NotNull UserLoginRequireVO requireVO);
@NotNull ResponseVO<UserInfoResponseVO> currentUser();
@NotNull ResponseVO<UserRegisterResponseVO> createUser(@NotNull UserCreateRequireVO requireVO); @NotNull ResponseVO<UserRegisterResponseVO> createUser(@NotNull UserCreateRequireVO requireVO);
@NotNull ResponseVO<Void> updateUser(@NotNull UserUpdateRequireVO requireVO); @NotNull ResponseVO<Void> updateUser(@NotNull UserUpdateRequireVO requireVO);
@NotNull ResponseVO<PageableResponseVO<UserInfoResponseVO>> getAllUserInfo(@NotNull Pageable pageable);
@NotNull ResponseVO<UserInfoResponseVO> getUserInfo(UUID id); @NotNull ResponseVO<UserInfoResponseVO> getUserInfo(UUID id);
@NotNull ResponseVO<List<AttachInfoResponseVO>> getUserAttaches(@PathVariable UUID userID); @NotNull ResponseVO<List<AttachInfoResponseVO>> getUserAttaches(@PathVariable UUID userID);

View File

@@ -6,10 +6,14 @@ import cn.hamster3.application.blog.entity.mapper.BlogMapper;
import cn.hamster3.application.blog.service.IBlogService; 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 cn.hamster3.application.blog.vo.blog.BlogInfoResponseVO;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
@Service @Service
public class BlogService implements IBlogService { public class BlogService implements IBlogService {
@Resource @Resource
@@ -23,4 +27,20 @@ public class BlogService implements IBlogService {
BlogEntity save = blogRepo.save(entity); BlogEntity save = blogRepo.save(entity);
return ResponseVO.success(save.getId()); return ResponseVO.success(save.getId());
} }
@Override
public @NotNull ResponseVO<BlogInfoResponseVO> getBlogInfo(@NotNull Long blogID) {
return blogRepo.findById(blogID)
.map(o -> ResponseVO.success(blogMapper.entityToInfoVO(o)))
.orElseThrow(() -> new IllegalArgumentException("未找到该文章!"));
}
@Override
public @NotNull ResponseVO<List<BlogInfoResponseVO>> getBlogInfoList(@NotNull PageRequest page) {
return ResponseVO.success(
blogRepo.findAll(page).stream()
.map(o -> blogMapper.entityToInfoVO(o))
.toList()
);
}
} }

View File

@@ -7,15 +7,17 @@ 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.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.PageableResponseVO;
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;
import cn.hamster3.application.blog.vo.user.*; import cn.hamster3.application.blog.vo.user.*;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.data.domain.Pageable;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; 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;
@@ -24,6 +26,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@Slf4j
@Service @Service
public class UserService implements IUserService { public class UserService implements IUserService {
@Resource @Resource
@@ -43,34 +46,28 @@ public class UserService implements IUserService {
@Override @Override
public @NotNull ResponseVO<Void> loginUser(@NotNull UserLoginRequireVO requireVO) { public @NotNull ResponseVO<Void> loginUser(@NotNull UserLoginRequireVO requireVO) {
UserEntity userEntity = userRepo.findByEmailIgnoreCaseWithPermission(requireVO.getEmail()).orElse(null); Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
if (userEntity == null) { requireVO.getEmail(),
return ResponseVO.failed("未找到该邮箱!"); requireVO.getPassword()
} ));
if (!passwordEncoder.matches(requireVO.getPassword(), userEntity.getPassword())) { SecurityContextHolder.getContext().setAuthentication(authenticate);
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(); return ResponseVO.success();
} }
@Override
public @NotNull ResponseVO<UserInfoResponseVO> currentUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Object userDetails = authentication.getDetails();
if (userDetails instanceof BlogUser user) {
return ResponseVO.success(
userRepo.findById(user.getUuid())
.map(o -> userMapper.entityToInfoVO(o))
.orElse(null)
);
}
return ResponseVO.failed("not login.");
}
@Override @Override
public @NotNull ResponseVO<UserRegisterResponseVO> createUser(@NotNull UserCreateRequireVO requireVO) { public @NotNull ResponseVO<UserRegisterResponseVO> createUser(@NotNull UserCreateRequireVO requireVO) {
UserEntity entity = userMapper.voToEntity(requireVO); UserEntity entity = userMapper.voToEntity(requireVO);
@@ -85,6 +82,7 @@ public class UserService implements IUserService {
} }
entity.setPassword(passwordEncoder.encode(entity.getPassword())); entity.setPassword(passwordEncoder.encode(entity.getPassword()));
log.info("prepare to save userinfo: {}", entity);
UserEntity save = userRepo.save(entity); UserEntity save = userRepo.save(entity);
return ResponseVO.success("注册成功!", userMapper.entityToRegisterVO(save)); return ResponseVO.success("注册成功!", userMapper.entityToRegisterVO(save));
@@ -136,6 +134,13 @@ public class UserService implements IUserService {
return ResponseVO.success(); return ResponseVO.success();
} }
@Override
public @NotNull ResponseVO<PageableResponseVO<UserInfoResponseVO>> getAllUserInfo(@NotNull Pageable pageable) {
return PageableResponseVO.success(
userRepo.findAll(pageable).map(o -> userMapper.entityToInfoVO(o))
);
}
@Override @Override
public @NotNull ResponseVO<UserInfoResponseVO> getUserInfo(UUID id) { public @NotNull ResponseVO<UserInfoResponseVO> getUserInfo(UUID id) {
return userRepo.findById(id) return userRepo.findById(id)
@@ -145,7 +150,7 @@ public class UserService implements IUserService {
@Override @Override
public @NotNull ResponseVO<List<AttachInfoResponseVO>> getUserAttaches(@PathVariable UUID userID) { public @NotNull ResponseVO<List<AttachInfoResponseVO>> getUserAttaches(@PathVariable UUID userID) {
UserEntity userEntity = userRepo.findByIdWithAttach(userID); UserEntity userEntity = userRepo.findById(userID).orElse(null);
if (userEntity == null) { if (userEntity == null) {
return ResponseVO.failed("未找到该用户!"); return ResponseVO.failed("未找到该用户!");
} }

View File

@@ -0,0 +1,31 @@
package cn.hamster3.application.blog.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.domain.Page;
import java.util.List;
@Data
@AllArgsConstructor
public class PageableResponseVO<T> {
private int page;
private int size;
private long totalElements;
private int totalPage;
private List<T> data;
public static <T> ResponseVO<PageableResponseVO<T>> success(Page<T> page) {
return ResponseVO.success(of(page));
}
public static <T> PageableResponseVO<T> of(Page<T> page) {
return new PageableResponseVO<>(
page.getNumber(),
page.getSize(),
page.getTotalElements(),
page.getTotalPages(),
page.getContent()
);
}
}

View File

@@ -5,9 +5,6 @@ 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> {
@@ -34,11 +31,4 @@ 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

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

View File

@@ -2,11 +2,9 @@ package cn.hamster3.application.blog.vo.user;
import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@Data @Data
@AllArgsConstructor
public class UserLoginRequireVO { public class UserLoginRequireVO {
@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;

View File

@@ -7,7 +7,7 @@ spring:
ddl-auto: update ddl-auto: update
# open-in-view: true # open-in-view: true
show-ddl: true show-ddl: true
# show-sql: true show-sql: true
autoconfigure: autoconfigure:
exclude: exclude:
# - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration # - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration