From 829407b7d3cf682d1ecfe3c5255a450a123ca0be Mon Sep 17 00:00:00 2001 From: sjinssun Date: Tue, 16 Dec 2025 22:24:14 +0900 Subject: [PATCH 1/2] mission#10 --- build.gradle | 12 ++- .../repository/CategoryRepository.java | 7 ++ .../user/controller/UserController.java | 22 ++++- .../domain/user/converter/UserConverter.java | 35 +++++++ .../umc9th/domain/user/dto/UserReqDTO.java | 38 ++++++++ .../umc9th/domain/user/dto/UserResDTO.java | 13 +++ .../com/umc9th/domain/user/entity/User.java | 21 +++-- .../user/repository/UserRepository.java | 12 +++ .../user/service/UserCommandService.java | 35 +++++++ .../domain/user/service/UserQueryService.java | 37 ++++++++ .../user/userdetail/CustomUserDetails.java | 30 ++++++ .../userdetail/CustomUserDetailsService.java | 30 ++++++ .../global/annotation/ExistCategories.java | 18 ++++ .../apiPayload/code/GeneralErrorCode.java | 6 +- .../umc9th/global/config/SecurityConfig.java | 62 +++++++++++++ .../java/com/umc9th/global/enums/Role.java | 5 + .../com/umc9th/global/jwt/JwtAuthFilter.java | 72 ++++++++++++++ .../java/com/umc9th/global/jwt/JwtUtil.java | 93 +++++++++++++++++++ .../validator/CategoriesExistValidator.java | 44 +++++++++ src/resources/application.yml | 24 +++++ 20 files changed, 606 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java create mode 100644 src/main/java/com/umc9th/domain/user/converter/UserConverter.java create mode 100644 src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java create mode 100644 src/main/java/com/umc9th/domain/user/dto/UserResDTO.java create mode 100644 src/main/java/com/umc9th/domain/user/repository/UserRepository.java create mode 100644 src/main/java/com/umc9th/domain/user/service/UserCommandService.java create mode 100644 src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java create mode 100644 src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java create mode 100644 src/main/java/com/umc9th/global/annotation/ExistCategories.java create mode 100644 src/main/java/com/umc9th/global/config/SecurityConfig.java create mode 100644 src/main/java/com/umc9th/global/enums/Role.java create mode 100644 src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java create mode 100644 src/main/java/com/umc9th/global/jwt/JwtUtil.java create mode 100644 src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java create mode 100644 src/resources/application.yml diff --git a/build.gradle b/build.gradle index 5506359..aa7e658 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id 'io.spring.dependency-management' version '1.1.7' } -group = 'com' +group = 'com.example' version = '0.0.1-SNAPSHOT' description = 'Demo project for Spring Boot' @@ -42,6 +42,16 @@ dependencies { // Swagger implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.13' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.13' + + // Security + implementation 'org.springframework.boot:spring-boot-starter-security' + testImplementation 'org.springframework.security:spring-security-test' + + // Jwt + implementation 'io.jsonwebtoken:jjwt-api:0.12.3' + implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' + implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' + implementation 'org.springframework.boot:spring-boot-configuration-processor' } tasks.named('test') { diff --git a/src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java b/src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java new file mode 100644 index 0000000..98189e1 --- /dev/null +++ b/src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java @@ -0,0 +1,7 @@ +package com.example.umc9th.domain.category.repository; + +import com.example.umc9th.domain.category.entity.Category; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CategoryRepository extends JpaRepository { +} diff --git a/src/main/java/com/umc9th/domain/user/controller/UserController.java b/src/main/java/com/umc9th/domain/user/controller/UserController.java index 7f9d840..501cb7e 100644 --- a/src/main/java/com/umc9th/domain/user/controller/UserController.java +++ b/src/main/java/com/umc9th/domain/user/controller/UserController.java @@ -3,12 +3,16 @@ import com.example.umc9th.domain.mission.dto.res.GetUserMissionResponse; import com.example.umc9th.domain.review.dto.UserReviewDto; +import com.example.umc9th.domain.user.dto.UserReqDTO; +import com.example.umc9th.domain.user.dto.UserResDTO; +import com.example.umc9th.domain.user.service.UserCommandService; import com.example.umc9th.domain.user.service.UserQueryService; import com.example.umc9th.global.apiPayload.ApiResponse; import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode; import com.example.umc9th.global.annotation.PageCheck; import com.example.umc9th.global.apiPayload.response.PageResponse; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -28,9 +32,10 @@ @RequiredArgsConstructor @RequestMapping("/users")// 유저 관련 API 경로 @Tag(name="유저") -public class UserController { // 클래스 이름 변경 +public class UserController { // 💡 클래스 이름 변경 private final UserQueryService userQueryService; + private final UserCommandService userCommandService; // [API 1] 내가 작성한 리뷰 목록 조회 (GET /users/{userId}/review-list) @Operation(summary = "내가 작성한 리뷰 목록 조회", description = "사용자가 작성한 리뷰 목록을 페이지네이션으로 조회합니다. page는 1부터 시작합니다.") @@ -93,5 +98,20 @@ public ApiResponse> getUserMissionList( PageResponse.from(pageResponse) ); } + // 회원가입 + @PostMapping("/signup") + @Operation(summary = "회원가입api") + public ApiResponse join(@RequestBody @Valid UserReqDTO.JoinDTO request) { + userCommandService.joinUser(request); + return ApiResponse.onSuccess(GeneralSuccessCode.CREATED, "회원가입 성공!"); + } + // 로그인 + @PostMapping("/login") + @Operation(summary = "로그인api") + public ApiResponse login( + @RequestBody @Valid UserReqDTO.LoginDTO dto + ){ + return ApiResponse.onSuccess(GeneralSuccessCode.OK, userQueryService.login(dto)); + } } diff --git a/src/main/java/com/umc9th/domain/user/converter/UserConverter.java b/src/main/java/com/umc9th/domain/user/converter/UserConverter.java new file mode 100644 index 0000000..c3862f2 --- /dev/null +++ b/src/main/java/com/umc9th/domain/user/converter/UserConverter.java @@ -0,0 +1,35 @@ +package com.example.umc9th.domain.user.converter; + +import com.example.umc9th.domain.user.dto.UserReqDTO; +import com.example.umc9th.domain.user.dto.UserResDTO; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.global.enums.Role; +import com.example.umc9th.domain.user.enums.SocialType; +public class UserConverter { + + //DTO, Salted Passwd, Role -> Entity + public static User toUser( + UserReqDTO.JoinDTO dto, + String password, + Role role + ){ + return User.builder() + .name(dto.name()) + .email(dto.email()) // 추가된 코드 + .password(password) // 추가된 코드 + .role(role) // 추가된 코드 + .birthday(dto.birthday()) + .address(dto.address()) + .gender(dto.gender()) + .socialType(SocialType.naver) + .userPoint(0L) + .build(); + } + //login + public static UserResDTO.LoginDTO toLoginDTO(User user, String accessToken) { + return UserResDTO.LoginDTO.builder() + .userId(user.getId()) + .accessToken(accessToken) + .build(); + } +} diff --git a/src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java b/src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java new file mode 100644 index 0000000..a1410c1 --- /dev/null +++ b/src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java @@ -0,0 +1,38 @@ +package com.example.umc9th.domain.user.dto; + +import com.example.umc9th.domain.user.enums.Address; +import com.example.umc9th.domain.user.enums.Gender; +import com.example.umc9th.global.annotation.ExistCategories; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +import java.time.LocalDate; +import java.util.List; + +public class UserReqDTO { + public record JoinDTO( + @NotBlank + String name, + @Email + String email, // 추가된 속성 + @NotBlank + String password, // 추가된 속성 + @NotNull + Gender gender, + @NotNull + LocalDate birthday, + @NotNull + Address address, + @ExistCategories + List preferCategory + ){} + + //로그인dto + public record LoginDTO( + @NotBlank + String email, + @NotBlank + String password + ){} +} diff --git a/src/main/java/com/umc9th/domain/user/dto/UserResDTO.java b/src/main/java/com/umc9th/domain/user/dto/UserResDTO.java new file mode 100644 index 0000000..e953a18 --- /dev/null +++ b/src/main/java/com/umc9th/domain/user/dto/UserResDTO.java @@ -0,0 +1,13 @@ +package com.example.umc9th.domain.user.dto; + +import lombok.Builder; + +public class UserResDTO { + + // 로그인 + @Builder + public record LoginDTO( + Long userId, + String accessToken + ){} +} diff --git a/src/main/java/com/umc9th/domain/user/entity/User.java b/src/main/java/com/umc9th/domain/user/entity/User.java index 5a85544..3f17d58 100644 --- a/src/main/java/com/umc9th/domain/user/entity/User.java +++ b/src/main/java/com/umc9th/domain/user/entity/User.java @@ -1,9 +1,10 @@ -package com.umc9th.domain.user.entity; +package com.example.umc9th.domain.user.entity; -import com.umc9th.domain.user.enums.Address; -import com.umc9th.domain.user.enums.Gender; -import com.umc9th.domain.user.enums.SocialType; -import com.umc9th.global.entity.BaseEntity; +import com.example.umc9th.global.enums.Role; +import com.example.umc9th.domain.user.enums.Address; +import com.example.umc9th.domain.user.enums.Gender; +import com.example.umc9th.domain.user.enums.SocialType; +import com.example.umc9th.global.entity.BaseEntity; import jakarta.persistence.*; import lombok.*; @@ -45,6 +46,14 @@ public class User extends BaseEntity { @Column(name ="userpoint", nullable = false) private Long userPoint; + @Column(nullable = false, unique = true) + private String email; + @Column(nullable = false) + private String password; -} \ No newline at end of file + @Enumerated(EnumType.STRING) + private Role role; + + +} diff --git a/src/main/java/com/umc9th/domain/user/repository/UserRepository.java b/src/main/java/com/umc9th/domain/user/repository/UserRepository.java new file mode 100644 index 0000000..99efad1 --- /dev/null +++ b/src/main/java/com/umc9th/domain/user/repository/UserRepository.java @@ -0,0 +1,12 @@ +package com.example.umc9th.domain.user.repository; + +import com.example.umc9th.domain.user.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + + //이메일로 유저찾기 + Optional findByEmail(String email); +} diff --git a/src/main/java/com/umc9th/domain/user/service/UserCommandService.java b/src/main/java/com/umc9th/domain/user/service/UserCommandService.java new file mode 100644 index 0000000..edcc098 --- /dev/null +++ b/src/main/java/com/umc9th/domain/user/service/UserCommandService.java @@ -0,0 +1,35 @@ +package com.example.umc9th.domain.user.service; + + +import com.example.umc9th.domain.user.converter.UserConverter; +import com.example.umc9th.domain.user.dto.UserReqDTO; +import com.example.umc9th.domain.user.dto.UserResDTO; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.domain.user.repository.UserRepository; +import com.example.umc9th.global.enums.Role; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class UserCommandService { + + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + + public User joinUser (UserReqDTO.JoinDTO request){ + + // 1. 비밀번호 암호화 (Service에서 처리) + String encodedPassword = passwordEncoder.encode(request.password()); + + // 2. DTO와 암호화된 비밀번호를 넘겨서 Entity 생성 + User newUser = UserConverter.toUser(request, encodedPassword, Role.ROLE_USER); + + // 3. 저장 + return userRepository.save(newUser); + } +} diff --git a/src/main/java/com/umc9th/domain/user/service/UserQueryService.java b/src/main/java/com/umc9th/domain/user/service/UserQueryService.java index 5f65757..6e417b3 100644 --- a/src/main/java/com/umc9th/domain/user/service/UserQueryService.java +++ b/src/main/java/com/umc9th/domain/user/service/UserQueryService.java @@ -5,12 +5,21 @@ import com.example.umc9th.domain.mission.dto.res.GetUserMissionResponse; import com.example.umc9th.domain.mission.repository.UserMissionRepository; import com.example.umc9th.domain.review.dto.UserReviewDto; +import com.example.umc9th.domain.user.converter.UserConverter; +import com.example.umc9th.domain.user.dto.UserReqDTO; +import com.example.umc9th.domain.user.dto.UserResDTO; +import com.example.umc9th.domain.user.entity.User; import com.example.umc9th.domain.user.repository.MyPageRepository; +import com.example.umc9th.domain.user.repository.UserRepository; +import com.example.umc9th.domain.user.userdetail.CustomUserDetails; import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; import com.example.umc9th.global.apiPayload.exception.GeneralException; +import com.example.umc9th.global.jwt.JwtUtil; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,6 +30,10 @@ public class UserQueryService { private final MyPageRepository myPageRepository; private final UserMissionRepository userMissionRepository; + private final UserRepository userRepository; + private final JwtUtil jwtUtil; + private final PasswordEncoder encoder; + public Page getUserReviewList(Long userId, Pageable pageable) { @@ -44,4 +57,28 @@ public Page getUserMissionList( .map(UserMissionConverter::toUserMissionResponse); } + + + public UserResDTO.LoginDTO login( + UserReqDTO.@Valid LoginDTO dto + ) { + + // Member 조회 + User user = userRepository.findByEmail(dto.email()) + .orElseThrow(() -> new GeneralException(GeneralErrorCode.NOT_FOUND)); + + // 비밀번호 검증 + if (!encoder.matches(dto.password(), user.getPassword())){ + throw new GeneralException(GeneralErrorCode.NOT_MATCH); + } + + // JWT 토큰 발급용 UserDetails + CustomUserDetails userDetails = new CustomUserDetails(user); + + // 엑세스 토큰 발급 + String accessToken = jwtUtil.createAccessToken(userDetails); + + // DTO 조립 + return UserConverter.toLoginDTO(user, accessToken); + } } \ No newline at end of file diff --git a/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java new file mode 100644 index 0000000..2b4649c --- /dev/null +++ b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.user.userdetail; + +import com.example.umc9th.domain.user.entity.User; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.List; + +@RequiredArgsConstructor +public class CustomUserDetails implements UserDetails { + + private final User user; + + @Override + public Collection getAuthorities() { + return List.of(() -> user.getRole().toString()); + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public String getUsername() { + return user.getEmail(); + } +} diff --git a/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java new file mode 100644 index 0000000..2d4ed95 --- /dev/null +++ b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.user.userdetail; + +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.domain.user.repository.UserRepository; +import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.example.umc9th.global.apiPayload.exception.GeneralException; +import jdk.jshell.spi.ExecutionControl; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + + private final UserRepository userRepository; + + @Override + public UserDetails loadUserByUsername( + String username + ) throws UsernameNotFoundException { + // 검증할 Member 조회 + User user = userRepository.findByEmail(username) + .orElseThrow(() -> new GeneralException(GeneralErrorCode.NOT_FOUND)); + // CustomUserDetails 반환 + return new CustomUserDetails(user); + } +} diff --git a/src/main/java/com/umc9th/global/annotation/ExistCategories.java b/src/main/java/com/umc9th/global/annotation/ExistCategories.java new file mode 100644 index 0000000..46d2e32 --- /dev/null +++ b/src/main/java/com/umc9th/global/annotation/ExistCategories.java @@ -0,0 +1,18 @@ +package com.example.umc9th.global.annotation; + +import com.example.umc9th.global.validator.CategoriesExistValidator; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = CategoriesExistValidator.class) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExistCategories { + + String message() default "해당하는 카테고리가 존재하지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java b/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java index fc4e5cc..71312a1 100644 --- a/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java +++ b/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java @@ -1,4 +1,4 @@ -package com.umc9th.global.apiPayload.code; +package com.example.umc9th.global.apiPayload.code; import lombok.AllArgsConstructor; import lombok.Getter; @@ -30,7 +30,9 @@ public enum GeneralErrorCode implements BaseErrorCode{ MISSION_ALREADY_CHALLENGING(HttpStatus.BAD_REQUEST, "MISSION400_1", "이미 도전 중인 미션입니다."), - + NOT_MATCH(HttpStatus.BAD_REQUEST, + "COMMON405", + "잘못된 비밀번호입니다.") ; diff --git a/src/main/java/com/umc9th/global/config/SecurityConfig.java b/src/main/java/com/umc9th/global/config/SecurityConfig.java new file mode 100644 index 0000000..afdd1a8 --- /dev/null +++ b/src/main/java/com/umc9th/global/config/SecurityConfig.java @@ -0,0 +1,62 @@ +package com.example.umc9th.global.config; + +import com.example.umc9th.domain.user.userdetail.CustomUserDetailsService; +import com.example.umc9th.global.jwt.JwtAuthFilter; +import com.example.umc9th.global.jwt.JwtUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@EnableWebSecurity //spring security 활성화 +@Configuration +@RequiredArgsConstructor +public class SecurityConfig { + + private final JwtUtil jwtUtil; + private final CustomUserDetailsService customUserDetailService; + private final String[] allowUris = { + "/users/login", + "/swagger-ui/**", + "/swagger-resources/**", + "/v3/api-docs/**", + }; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(requests -> requests + .requestMatchers(allowUris).permitAll() + .requestMatchers("/admin/**").hasRole("ADMIN") + .anyRequest().authenticated() + ) + // 폼로그인 비활성화 + .formLogin(AbstractHttpConfigurer::disable) + // JwtAuthFilter를 UsernamePasswordAuthenticationFilter 앞에 추가 + .addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class) + .csrf(AbstractHttpConfigurer::disable) + .logout(logout -> logout + .logoutUrl("/logout") + .logoutSuccessUrl("/login?logout") + .permitAll() + ); + + return http.build(); + } + + @Bean + public JwtAuthFilter jwtAuthFilter() { + return new JwtAuthFilter(jwtUtil, customUserDetailService); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file diff --git a/src/main/java/com/umc9th/global/enums/Role.java b/src/main/java/com/umc9th/global/enums/Role.java new file mode 100644 index 0000000..0a4211a --- /dev/null +++ b/src/main/java/com/umc9th/global/enums/Role.java @@ -0,0 +1,5 @@ +package com.example.umc9th.global.enums; + +public enum Role { + ROLE_ADMIN, ROLE_USER +} diff --git a/src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java b/src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java new file mode 100644 index 0000000..e56bfd6 --- /dev/null +++ b/src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java @@ -0,0 +1,72 @@ +package com.example.umc9th.global.jwt; + +import com.example.umc9th.domain.user.userdetail.CustomUserDetailsService; +import com.example.umc9th.global.apiPayload.ApiResponse; +import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +@RequiredArgsConstructor +public class JwtAuthFilter extends OncePerRequestFilter { + + private final JwtUtil jwtUtil; + private final CustomUserDetailsService customUserDetailsService; + + @Override + protected void doFilterInternal( + @NonNull HttpServletRequest request, + @NonNull HttpServletResponse response, + @NonNull FilterChain filterChain + ) throws ServletException, IOException { + + try { + // 토큰 가져오기 + String token = request.getHeader("Authorization"); + // token이 없거나 Bearer가 아니면 넘기기 + if (token == null || !token.startsWith("Bearer ")) { + filterChain.doFilter(request, response); + return; + } + // Bearer이면 추출 + token = token.replace("Bearer ", ""); + // AccessToken 검증하기: 올바른 토큰이면 + if (jwtUtil.isValid(token)) { + // 토큰에서 이메일 추출 + String email = jwtUtil.getEmail(token); + // 인증 객체 생성: 이메일로 찾아온 뒤, 인증 객체 생성 + UserDetails user = customUserDetailsService.loadUserByUsername(email); + Authentication auth = new UsernamePasswordAuthenticationToken( + user, + null, + user.getAuthorities() + ); + // 인증 완료 후 SecurityContextHolder에 넣기 + SecurityContextHolder.getContext().setAuthentication(auth); + } + filterChain.doFilter(request, response); + } catch (Exception e) { + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + + ApiResponse errorResponse = ApiResponse.onFailure( + GeneralErrorCode.UNAUTHORIZED, + null + ); + + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(response.getOutputStream(), errorResponse); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/umc9th/global/jwt/JwtUtil.java b/src/main/java/com/umc9th/global/jwt/JwtUtil.java new file mode 100644 index 0000000..e1b7874 --- /dev/null +++ b/src/main/java/com/umc9th/global/jwt/JwtUtil.java @@ -0,0 +1,93 @@ +package com.example.umc9th.global.jwt; + +import com.example.umc9th.domain.user.userdetail.CustomUserDetails; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Component; +import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.stream.Collectors; + +@Component +public class JwtUtil { + + private final SecretKey secretKey; + private final Duration accessExpiration; + + public JwtUtil( + @Value("${jwt.token.secretKey}") String secret, + @Value("${jwt.token.expiration.access}") Long accessExpiration + ) { + this.secretKey = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)); + this.accessExpiration = Duration.ofMillis(accessExpiration); + } + + // AccessToken 생성 + public String createAccessToken(CustomUserDetails user) { + return createToken(user, accessExpiration); + } + + /** 토큰에서 이메일 가져오기 + * + * @param token 유저 정보를 추출할 토큰 + * @return 유저 이메일을 토큰에서 추출합니다 + */ + public String getEmail(String token) { + try { + return getClaims(token).getPayload().getSubject(); // Parsing해서 Subject 가져오기 + } catch (JwtException e) { + return null; + } + } + + /** 토큰 유효성 확인 + * + * @param token 유효한지 확인할 토큰 + * @return True, False 반환합니다 + */ + public boolean isValid(String token) { + try { + getClaims(token); + return true; + } catch (JwtException e) { + return false; + } + } + + // 토큰 생성 + private String createToken(CustomUserDetails user, Duration expiration) { + Instant now = Instant.now(); + + // 인가 정보 + String authorities = user.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .collect(Collectors.joining(",")); + + return Jwts.builder() + .subject(user.getUsername()) // User 이메일을 Subject로 + .claim("role", authorities) + .claim("email", user.getUsername()) + .issuedAt(Date.from(now)) // 언제 발급한지 + .expiration(Date.from(now.plus(expiration))) // 언제까지 유효한지 + .signWith(secretKey) // sign할 Key + .compact(); + } + + // 토큰 정보 가져오기 + private Jws getClaims(String token) throws JwtException { + return Jwts.parser() + .verifyWith(secretKey) + .clockSkewSeconds(60) + .build() + .parseSignedClaims(token); + } +} \ No newline at end of file diff --git a/src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java b/src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java new file mode 100644 index 0000000..40874dc --- /dev/null +++ b/src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java @@ -0,0 +1,44 @@ +package com.example.umc9th.global.validator; + +import com.example.umc9th.domain.category.repository.CategoryRepository; +import com.example.umc9th.global.annotation.ExistCategories; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +public class CategoriesExistValidator implements ConstraintValidator> { + + private final CategoryRepository categoryRepository; + + @Override + public void initialize(ExistCategories constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(List values, ConstraintValidatorContext context) { + // 1. null 여부 확인 + if (values == null || values.isEmpty()) { + return true; + } + + // 2. DB에서 해당 ID들이 존재하는지 확인 + // 요청한 카테고리 ID 개수와 실제 DB에서 찾은 카테고리 개수가 일치하는지 검증 + boolean isValid = values.stream() + .allMatch(value -> categoryRepository.existsById(value)); + + if (!isValid) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate("일부 카테고리가 존재하지 않습니다.") + .addConstraintViolation(); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/src/resources/application.yml b/src/resources/application.yml new file mode 100644 index 0000000..d4a0f2c --- /dev/null +++ b/src/resources/application.yml @@ -0,0 +1,24 @@ +spring: + application: + name: umc9th + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ${DB_URL} + username: ${DB_USER} + password: ${DB_PW} + + jpa: + database: mysql + database-platform: org.hibernate.dialect.MySQLDialect + show-sql: true + hibernate: + ddl-auto: update + properties: + hibernate.format_sql: true + +jwt: + token: + secretKey: ZGh3YWlkc2F2ZXdhZXZ3b2EgMTM5ZXUgMDMxdWMyIHEyMiBAIDAgKTJFVio= + expiration: + access: 14400000 \ No newline at end of file From 22307c97ad33ce7d2e22d49b1f3ed9a3e017b2cd Mon Sep 17 00:00:00 2001 From: sjinssun Date: Tue, 16 Dec 2025 22:27:24 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=EB=B2=84=EA=B7=B8=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../repository/CategoryRepository.java | 4 +-- .../converter/UserMissionConverter.java | 6 ++-- .../mission/repository/MissionRepository.java | 8 ++--- .../repository/UserMissionRepository.java | 4 +-- .../service/MissionCommandService.java | 26 +++++++-------- .../mission/service/MissionQueryService.java | 14 ++++---- .../domain/review/dto/res/ReviewResDTO.java | 2 +- .../controller/StoreReviewController.java | 14 ++++---- .../controller/StroreMissionController.java | 16 +++++----- .../user/controller/UserController.java | 26 +++++++-------- .../domain/user/converter/UserConverter.java | 12 +++---- .../umc9th/domain/user/dto/UserReqDTO.java | 8 ++--- .../umc9th/domain/user/dto/UserResDTO.java | 2 +- .../com/umc9th/domain/user/entity/User.java | 12 +++---- .../user/repository/MyPageRepository.java | 12 +++---- .../user/repository/UserRepository.java | 4 +-- .../user/service/UserCommandService.java | 14 ++++---- .../domain/user/service/UserQueryService.java | 32 +++++++++---------- .../user/userdetail/CustomUserDetails.java | 4 +-- .../userdetail/CustomUserDetailsService.java | 10 +++--- .../global/annotation/ExistCategories.java | 4 +-- .../umc9th/global/annotation/PageCheck.java | 4 +-- .../apiPayload/code/GeneralErrorCode.java | 2 +- .../handler/GeneralExceptionAdvice.java | 10 +++--- .../umc9th/global/config/SecurityConfig.java | 8 ++--- .../java/com/umc9th/global/enums/Role.java | 2 +- .../com/umc9th/global/jwt/JwtAuthFilter.java | 8 ++--- .../java/com/umc9th/global/jwt/JwtUtil.java | 4 +-- .../umc9th/global/response/PageResponse.java | 2 +- .../validator/CategoriesExistValidator.java | 6 ++-- .../global/validator/PageCheckValidator.java | 4 +-- 32 files changed, 143 insertions(+), 143 deletions(-) diff --git a/build.gradle b/build.gradle index aa7e658..a854997 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id 'io.spring.dependency-management' version '1.1.7' } -group = 'com.example' +group = 'com' version = '0.0.1-SNAPSHOT' description = 'Demo project for Spring Boot' diff --git a/src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java b/src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java index 98189e1..7bc1dfa 100644 --- a/src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java +++ b/src/main/java/com/umc9th/domain/category/repository/CategoryRepository.java @@ -1,6 +1,6 @@ -package com.example.umc9th.domain.category.repository; +package com.umc9th.domain.category.repository; -import com.example.umc9th.domain.category.entity.Category; +import com.umc9th.domain.category.entity.Category; import org.springframework.data.jpa.repository.JpaRepository; public interface CategoryRepository extends JpaRepository { diff --git a/src/main/java/com/umc9th/domain/mission/converter/UserMissionConverter.java b/src/main/java/com/umc9th/domain/mission/converter/UserMissionConverter.java index 5b98a76..63dc594 100644 --- a/src/main/java/com/umc9th/domain/mission/converter/UserMissionConverter.java +++ b/src/main/java/com/umc9th/domain/mission/converter/UserMissionConverter.java @@ -1,7 +1,7 @@ -package com.example.umc9th.domain.mission.converter; +package com.umc9th.domain.mission.converter; -import com.example.umc9th.domain.mission.dto.res.GetUserMissionResponse; -import com.example.umc9th.domain.user.entity.UserMission; +import com.umc9th.domain.mission.dto.res.GetUserMissionResponse; +import com.umc9th.domain.user.entity.UserMission; public class UserMissionConverter { diff --git a/src/main/java/com/umc9th/domain/mission/repository/MissionRepository.java b/src/main/java/com/umc9th/domain/mission/repository/MissionRepository.java index 97bf087..4f29140 100644 --- a/src/main/java/com/umc9th/domain/mission/repository/MissionRepository.java +++ b/src/main/java/com/umc9th/domain/mission/repository/MissionRepository.java @@ -1,7 +1,7 @@ -package com.example.umc9th.domain.mission.repository; +package com.umc9th.domain.mission.repository; -import com.example.umc9th.domain.mission.dto.UserMissionDto; -import com.example.umc9th.domain.mission.entity.Mission; +import com.umc9th.domain.mission.dto.UserMissionDto; +import com.umc9th.domain.mission.entity.Mission; import org.springframework.data.domain.Page; // 💡 페이징 처리를 위해 Page 클래스 사용 import org.springframework.data.domain.Pageable; // 💡 페이징 정보를 받기 위해 Pageable 사용 import org.springframework.data.jpa.repository.JpaRepository; @@ -13,7 +13,7 @@ public interface MissionRepository extends JpaRepository { //내가 진행중/완료한 미션 모아보기 쿼리 (페이징 포함) - @Query("SELECT new com.example.umc9th.domain.mission.dto.UserMissionDto(" + + @Query("SELECT new com.umc9th.domain.mission.dto.UserMissionDto(" + "um.id, " + "m.id, " + "s.storeName, " + diff --git a/src/main/java/com/umc9th/domain/mission/repository/UserMissionRepository.java b/src/main/java/com/umc9th/domain/mission/repository/UserMissionRepository.java index 6979beb..1bb89fb 100644 --- a/src/main/java/com/umc9th/domain/mission/repository/UserMissionRepository.java +++ b/src/main/java/com/umc9th/domain/mission/repository/UserMissionRepository.java @@ -1,6 +1,6 @@ -package com.example.umc9th.domain.mission.repository; +package com.umc9th.domain.mission.repository; -import com.example.umc9th.domain.user.entity.UserMission; +import com.umc9th.domain.user.entity.UserMission; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/umc9th/domain/mission/service/MissionCommandService.java b/src/main/java/com/umc9th/domain/mission/service/MissionCommandService.java index 368c64c..d42357b 100644 --- a/src/main/java/com/umc9th/domain/mission/service/MissionCommandService.java +++ b/src/main/java/com/umc9th/domain/mission/service/MissionCommandService.java @@ -1,16 +1,16 @@ -package com.example.umc9th.domain.mission.service; - -import com.example.umc9th.domain.mission.converter.MissionConverter; -import com.example.umc9th.domain.mission.dto.req.MissionRequestDto; -import com.example.umc9th.domain.mission.dto.res.MissionResponseDto; -import com.example.umc9th.domain.mission.entity.Mission; -import com.example.umc9th.domain.mission.repository.MissionRepository; -import com.example.umc9th.domain.mission.repository.UserMissionRepository; -import com.example.umc9th.domain.user.entity.User; -import com.example.umc9th.domain.user.entity.UserMission; -import com.example.umc9th.domain.user.repository.MyPageRepository; // 혹은 UserRepository -import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; -import com.example.umc9th.global.apiPayload.exception.GeneralException; +package com.umc9th.domain.mission.service; + +import com.umc9th.domain.mission.converter.MissionConverter; +import com.umc9th.domain.mission.dto.req.MissionRequestDto; +import com.umc9th.domain.mission.dto.res.MissionResponseDto; +import com.umc9th.domain.mission.entity.Mission; +import com.umc9th.domain.mission.repository.MissionRepository; +import com.umc9th.domain.mission.repository.UserMissionRepository; +import com.umc9th.domain.user.entity.User; +import com.umc9th.domain.user.entity.UserMission; +import com.umc9th.domain.user.repository.MyPageRepository; // 혹은 UserRepository +import com.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.umc9th.global.apiPayload.exception.GeneralException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/umc9th/domain/mission/service/MissionQueryService.java b/src/main/java/com/umc9th/domain/mission/service/MissionQueryService.java index f59c93c..2ae482e 100644 --- a/src/main/java/com/umc9th/domain/mission/service/MissionQueryService.java +++ b/src/main/java/com/umc9th/domain/mission/service/MissionQueryService.java @@ -1,11 +1,11 @@ -package com.example.umc9th.domain.mission.service; +package com.umc9th.domain.mission.service; -import com.example.umc9th.domain.mission.converter.MissionConverter; -import com.example.umc9th.domain.mission.dto.res.StoreMissionDto; -import com.example.umc9th.domain.mission.entity.Mission; -import com.example.umc9th.domain.mission.repository.MissionRepository; -import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; -import com.example.umc9th.global.apiPayload.exception.GeneralException; +import com.umc9th.domain.mission.converter.MissionConverter; +import com.umc9th.domain.mission.dto.res.StoreMissionDto; +import com.umc9th.domain.mission.entity.Mission; +import com.umc9th.domain.mission.repository.MissionRepository; +import com.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.umc9th.global.apiPayload.exception.GeneralException; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/src/main/java/com/umc9th/domain/review/dto/res/ReviewResDTO.java b/src/main/java/com/umc9th/domain/review/dto/res/ReviewResDTO.java index e1323f4..b474f2f 100644 --- a/src/main/java/com/umc9th/domain/review/dto/res/ReviewResDTO.java +++ b/src/main/java/com/umc9th/domain/review/dto/res/ReviewResDTO.java @@ -1,4 +1,4 @@ -package com.example.umc9th.domain.review.dto.res; +package com.umc9th.domain.review.dto.res; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/umc9th/domain/store/controller/StoreReviewController.java b/src/main/java/com/umc9th/domain/store/controller/StoreReviewController.java index a1de3bd..131e54a 100644 --- a/src/main/java/com/umc9th/domain/store/controller/StoreReviewController.java +++ b/src/main/java/com/umc9th/domain/store/controller/StoreReviewController.java @@ -1,11 +1,11 @@ -package com.example.umc9th.domain.store.controller; +package com.umc9th.domain.store.controller; -import com.example.umc9th.domain.review.dto.req.ReviewCreateRequest; -import com.example.umc9th.domain.review.dto.res.ReviewResDTO; -import com.example.umc9th.domain.review.service.ReviewService; -import com.example.umc9th.global.annotation.ExistStore; -import com.example.umc9th.global.apiPayload.ApiResponse; -import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode; +import com.umc9th.domain.review.dto.req.ReviewCreateRequest; +import com.umc9th.domain.review.dto.res.ReviewResDTO; +import com.umc9th.domain.review.service.ReviewService; +import com.umc9th.global.annotation.ExistStore; +import com.umc9th.global.apiPayload.ApiResponse; +import com.umc9th.global.apiPayload.code.GeneralSuccessCode; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; diff --git a/src/main/java/com/umc9th/domain/store/controller/StroreMissionController.java b/src/main/java/com/umc9th/domain/store/controller/StroreMissionController.java index d6115ae..f7b04d0 100644 --- a/src/main/java/com/umc9th/domain/store/controller/StroreMissionController.java +++ b/src/main/java/com/umc9th/domain/store/controller/StroreMissionController.java @@ -1,12 +1,12 @@ -package com.example.umc9th.domain.store.controller; +package com.umc9th.domain.store.controller; -import com.example.umc9th.domain.mission.dto.res.StoreMissionDto; -import com.example.umc9th.domain.mission.service.MissionQueryService; -import com.example.umc9th.global.annotation.ExistStore; -import com.example.umc9th.global.annotation.PageCheck; -import com.example.umc9th.global.apiPayload.ApiResponse; -import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode; -import com.example.umc9th.global.apiPayload.response.PageResponse; +import com.umc9th.domain.mission.dto.res.StoreMissionDto; +import com.umc9th.domain.mission.service.MissionQueryService; +import com.umc9th.global.annotation.ExistStore; +import com.umc9th.global.annotation.PageCheck; +import com.umc9th.global.apiPayload.ApiResponse; +import com.umc9th.global.apiPayload.code.GeneralSuccessCode; +import com.umc9th.global.apiPayload.response.PageResponse; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; diff --git a/src/main/java/com/umc9th/domain/user/controller/UserController.java b/src/main/java/com/umc9th/domain/user/controller/UserController.java index 501cb7e..f12a48e 100644 --- a/src/main/java/com/umc9th/domain/user/controller/UserController.java +++ b/src/main/java/com/umc9th/domain/user/controller/UserController.java @@ -1,16 +1,16 @@ -package com.example.umc9th.domain.user.controller; - - -import com.example.umc9th.domain.mission.dto.res.GetUserMissionResponse; -import com.example.umc9th.domain.review.dto.UserReviewDto; -import com.example.umc9th.domain.user.dto.UserReqDTO; -import com.example.umc9th.domain.user.dto.UserResDTO; -import com.example.umc9th.domain.user.service.UserCommandService; -import com.example.umc9th.domain.user.service.UserQueryService; -import com.example.umc9th.global.apiPayload.ApiResponse; -import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode; -import com.example.umc9th.global.annotation.PageCheck; -import com.example.umc9th.global.apiPayload.response.PageResponse; +package com.umc9th.domain.user.controller; + + +import com.umc9th.domain.mission.dto.res.GetUserMissionResponse; +import com.umc9th.domain.review.dto.UserReviewDto; +import com.umc9th.domain.user.dto.UserReqDTO; +import com.umc9th.domain.user.dto.UserResDTO; +import com.umc9th.domain.user.service.UserCommandService; +import com.umc9th.domain.user.service.UserQueryService; +import com.umc9th.global.apiPayload.ApiResponse; +import com.umc9th.global.apiPayload.code.GeneralSuccessCode; +import com.umc9th.global.annotation.PageCheck; +import com.umc9th.global.apiPayload.response.PageResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/umc9th/domain/user/converter/UserConverter.java b/src/main/java/com/umc9th/domain/user/converter/UserConverter.java index c3862f2..8d0a12d 100644 --- a/src/main/java/com/umc9th/domain/user/converter/UserConverter.java +++ b/src/main/java/com/umc9th/domain/user/converter/UserConverter.java @@ -1,10 +1,10 @@ -package com.example.umc9th.domain.user.converter; +package com.umc9th.domain.user.converter; -import com.example.umc9th.domain.user.dto.UserReqDTO; -import com.example.umc9th.domain.user.dto.UserResDTO; -import com.example.umc9th.domain.user.entity.User; -import com.example.umc9th.global.enums.Role; -import com.example.umc9th.domain.user.enums.SocialType; +import com.umc9th.domain.user.dto.UserReqDTO; +import com.umc9th.domain.user.dto.UserResDTO; +import com.umc9th.domain.user.entity.User; +import com.umc9th.global.enums.Role; +import com.umc9th.domain.user.enums.SocialType; public class UserConverter { //DTO, Salted Passwd, Role -> Entity diff --git a/src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java b/src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java index a1410c1..39c1f0c 100644 --- a/src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java +++ b/src/main/java/com/umc9th/domain/user/dto/UserReqDTO.java @@ -1,8 +1,8 @@ -package com.example.umc9th.domain.user.dto; +package com.umc9th.domain.user.dto; -import com.example.umc9th.domain.user.enums.Address; -import com.example.umc9th.domain.user.enums.Gender; -import com.example.umc9th.global.annotation.ExistCategories; +import com.umc9th.domain.user.enums.Address; +import com.umc9th.domain.user.enums.Gender; +import com.umc9th.global.annotation.ExistCategories; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/src/main/java/com/umc9th/domain/user/dto/UserResDTO.java b/src/main/java/com/umc9th/domain/user/dto/UserResDTO.java index e953a18..249557a 100644 --- a/src/main/java/com/umc9th/domain/user/dto/UserResDTO.java +++ b/src/main/java/com/umc9th/domain/user/dto/UserResDTO.java @@ -1,4 +1,4 @@ -package com.example.umc9th.domain.user.dto; +package com.umc9th.domain.user.dto; import lombok.Builder; diff --git a/src/main/java/com/umc9th/domain/user/entity/User.java b/src/main/java/com/umc9th/domain/user/entity/User.java index 3f17d58..f76eb94 100644 --- a/src/main/java/com/umc9th/domain/user/entity/User.java +++ b/src/main/java/com/umc9th/domain/user/entity/User.java @@ -1,10 +1,10 @@ -package com.example.umc9th.domain.user.entity; +package com.umc9th.domain.user.entity; -import com.example.umc9th.global.enums.Role; -import com.example.umc9th.domain.user.enums.Address; -import com.example.umc9th.domain.user.enums.Gender; -import com.example.umc9th.domain.user.enums.SocialType; -import com.example.umc9th.global.entity.BaseEntity; +import com.umc9th.global.enums.Role; +import com.umc9th.domain.user.enums.Address; +import com.umc9th.domain.user.enums.Gender; +import com.umc9th.domain.user.enums.SocialType; +import com.umc9th.global.entity.BaseEntity; import jakarta.persistence.*; import lombok.*; diff --git a/src/main/java/com/umc9th/domain/user/repository/MyPageRepository.java b/src/main/java/com/umc9th/domain/user/repository/MyPageRepository.java index 4d53865..2989245 100644 --- a/src/main/java/com/umc9th/domain/user/repository/MyPageRepository.java +++ b/src/main/java/com/umc9th/domain/user/repository/MyPageRepository.java @@ -1,8 +1,8 @@ -package com.example.umc9th.domain.user.repository; +package com.umc9th.domain.user.repository; -import com.example.umc9th.domain.review.dto.UserReviewDto; // 💡 사용자 리뷰 목록 DTO -import com.example.umc9th.domain.user.dto.MyPageUserDto; // 💡 마이 페이지 상단 DTO -import com.example.umc9th.domain.user.entity.User; // User 엔티티 import +import com.umc9th.domain.review.dto.UserReviewDto; // 💡 사용자 리뷰 목록 DTO +import com.umc9th.domain.user.dto.MyPageUserDto; // 💡 마이 페이지 상단 DTO +import com.umc9th.domain.user.entity.User; // User 엔티티 import import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -19,7 +19,7 @@ public interface MyPageRepository extends JpaRepository { // [1. 마이 페이지 상단 정보 조회 쿼리] // 마이 페이지 화면 (닉네임, 포인트, 리뷰 개수 등)에 필요한 데이터를 조회 - @Query("SELECT new com.example.umc9th.domain.user.dto.MyPageUserDto(" + + @Query("SELECT new com.umc9th.domain.user.dto.MyPageUserDto(" + "u.name, " + "u.address, " + "u.userPoint, " + @@ -33,7 +33,7 @@ public interface MyPageRepository extends JpaRepository { //2. 사용자가 작성한 리뷰 목록 조회 쿼리 // '작성한 리뷰' 버튼 클릭 시 호출되어, page로 반환 - @Query("SELECT new com.example.umc9th.domain.review.dto.UserReviewDto(" + + @Query("SELECT new com.umc9th.domain.review.dto.UserReviewDto(" + "r.id, " + "s.storeName, " + // Store 정보를 가져옴 "r.star, " + diff --git a/src/main/java/com/umc9th/domain/user/repository/UserRepository.java b/src/main/java/com/umc9th/domain/user/repository/UserRepository.java index 99efad1..c74af7a 100644 --- a/src/main/java/com/umc9th/domain/user/repository/UserRepository.java +++ b/src/main/java/com/umc9th/domain/user/repository/UserRepository.java @@ -1,6 +1,6 @@ -package com.example.umc9th.domain.user.repository; +package com.umc9th.domain.user.repository; -import com.example.umc9th.domain.user.entity.User; +import com.umc9th.domain.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; diff --git a/src/main/java/com/umc9th/domain/user/service/UserCommandService.java b/src/main/java/com/umc9th/domain/user/service/UserCommandService.java index edcc098..00d3a51 100644 --- a/src/main/java/com/umc9th/domain/user/service/UserCommandService.java +++ b/src/main/java/com/umc9th/domain/user/service/UserCommandService.java @@ -1,12 +1,12 @@ -package com.example.umc9th.domain.user.service; +package com.umc9th.domain.user.service; -import com.example.umc9th.domain.user.converter.UserConverter; -import com.example.umc9th.domain.user.dto.UserReqDTO; -import com.example.umc9th.domain.user.dto.UserResDTO; -import com.example.umc9th.domain.user.entity.User; -import com.example.umc9th.domain.user.repository.UserRepository; -import com.example.umc9th.global.enums.Role; +import com.umc9th.domain.user.converter.UserConverter; +import com.umc9th.domain.user.dto.UserReqDTO; +import com.umc9th.domain.user.dto.UserResDTO; +import com.umc9th.domain.user.entity.User; +import com.umc9th.domain.user.repository.UserRepository; +import com.umc9th.global.enums.Role; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.security.crypto.password.PasswordEncoder; diff --git a/src/main/java/com/umc9th/domain/user/service/UserQueryService.java b/src/main/java/com/umc9th/domain/user/service/UserQueryService.java index 6e417b3..569da2e 100644 --- a/src/main/java/com/umc9th/domain/user/service/UserQueryService.java +++ b/src/main/java/com/umc9th/domain/user/service/UserQueryService.java @@ -1,20 +1,20 @@ // com/example/umc9th/domain/user/service/UserQueryService.java (새 파일) -package com.example.umc9th.domain.user.service; - -import com.example.umc9th.domain.mission.converter.UserMissionConverter; -import com.example.umc9th.domain.mission.dto.res.GetUserMissionResponse; -import com.example.umc9th.domain.mission.repository.UserMissionRepository; -import com.example.umc9th.domain.review.dto.UserReviewDto; -import com.example.umc9th.domain.user.converter.UserConverter; -import com.example.umc9th.domain.user.dto.UserReqDTO; -import com.example.umc9th.domain.user.dto.UserResDTO; -import com.example.umc9th.domain.user.entity.User; -import com.example.umc9th.domain.user.repository.MyPageRepository; -import com.example.umc9th.domain.user.repository.UserRepository; -import com.example.umc9th.domain.user.userdetail.CustomUserDetails; -import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; -import com.example.umc9th.global.apiPayload.exception.GeneralException; -import com.example.umc9th.global.jwt.JwtUtil; +package com.umc9th.domain.user.service; + +import com.umc9th.domain.mission.converter.UserMissionConverter; +import com.umc9th.domain.mission.dto.res.GetUserMissionResponse; +import com.umc9th.domain.mission.repository.UserMissionRepository; +import com.umc9th.domain.review.dto.UserReviewDto; +import com.umc9th.domain.user.converter.UserConverter; +import com.umc9th.domain.user.dto.UserReqDTO; +import com.umc9th.domain.user.dto.UserResDTO; +import com.umc9th.domain.user.entity.User; +import com.umc9th.domain.user.repository.MyPageRepository; +import com.umc9th.domain.user.repository.UserRepository; +import com.umc9th.domain.user.userdetail.CustomUserDetails; +import com.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.umc9th.global.apiPayload.exception.GeneralException; +import com.umc9th.global.jwt.JwtUtil; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; diff --git a/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java index 2b4649c..8ba4ff4 100644 --- a/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java +++ b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetails.java @@ -1,6 +1,6 @@ -package com.example.umc9th.domain.user.userdetail; +package com.umc9th.domain.user.userdetail; -import com.example.umc9th.domain.user.entity.User; +import com.umc9th.domain.user.entity.User; import lombok.RequiredArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; diff --git a/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java index 2d4ed95..bfab5d6 100644 --- a/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java +++ b/src/main/java/com/umc9th/domain/user/userdetail/CustomUserDetailsService.java @@ -1,9 +1,9 @@ -package com.example.umc9th.domain.user.userdetail; +package com.umc9th.domain.user.userdetail; -import com.example.umc9th.domain.user.entity.User; -import com.example.umc9th.domain.user.repository.UserRepository; -import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; -import com.example.umc9th.global.apiPayload.exception.GeneralException; +import com.umc9th.domain.user.entity.User; +import com.umc9th.domain.user.repository.UserRepository; +import com.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.umc9th.global.apiPayload.exception.GeneralException; import jdk.jshell.spi.ExecutionControl; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; diff --git a/src/main/java/com/umc9th/global/annotation/ExistCategories.java b/src/main/java/com/umc9th/global/annotation/ExistCategories.java index 46d2e32..1d99bc7 100644 --- a/src/main/java/com/umc9th/global/annotation/ExistCategories.java +++ b/src/main/java/com/umc9th/global/annotation/ExistCategories.java @@ -1,6 +1,6 @@ -package com.example.umc9th.global.annotation; +package com.umc9th.global.annotation; -import com.example.umc9th.global.validator.CategoriesExistValidator; +import com.umc9th.global.validator.CategoriesExistValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; diff --git a/src/main/java/com/umc9th/global/annotation/PageCheck.java b/src/main/java/com/umc9th/global/annotation/PageCheck.java index 17cda6b..b3b6160 100644 --- a/src/main/java/com/umc9th/global/annotation/PageCheck.java +++ b/src/main/java/com/umc9th/global/annotation/PageCheck.java @@ -1,6 +1,6 @@ -package com.example.umc9th.global.annotation; +package com.umc9th.global.annotation; -import com.example.umc9th.global.validator.PageCheckValidator; +import com.umc9th.global.validator.PageCheckValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; diff --git a/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java b/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java index 71312a1..a16af77 100644 --- a/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java +++ b/src/main/java/com/umc9th/global/apiPayload/code/GeneralErrorCode.java @@ -1,4 +1,4 @@ -package com.example.umc9th.global.apiPayload.code; +package com.umc9th.global.apiPayload.code; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/com/umc9th/global/apiPayload/handler/GeneralExceptionAdvice.java b/src/main/java/com/umc9th/global/apiPayload/handler/GeneralExceptionAdvice.java index 6c8b009..067660f 100644 --- a/src/main/java/com/umc9th/global/apiPayload/handler/GeneralExceptionAdvice.java +++ b/src/main/java/com/umc9th/global/apiPayload/handler/GeneralExceptionAdvice.java @@ -1,9 +1,9 @@ -package com.example.umc9th.global.apiPayload.handler; +package com.umc9th.global.apiPayload.handler; -import com.example.umc9th.global.apiPayload.ApiResponse; -import com.example.umc9th.global.apiPayload.code.BaseErrorCode; -import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; -import com.example.umc9th.global.apiPayload.exception.GeneralException; +import com.umc9th.global.apiPayload.ApiResponse; +import com.umc9th.global.apiPayload.code.BaseErrorCode; +import com.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.umc9th.global.apiPayload.exception.GeneralException; import jakarta.validation.ConstraintViolationException; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/com/umc9th/global/config/SecurityConfig.java b/src/main/java/com/umc9th/global/config/SecurityConfig.java index afdd1a8..ca560b0 100644 --- a/src/main/java/com/umc9th/global/config/SecurityConfig.java +++ b/src/main/java/com/umc9th/global/config/SecurityConfig.java @@ -1,8 +1,8 @@ -package com.example.umc9th.global.config; +package com.umc9th.global.config; -import com.example.umc9th.domain.user.userdetail.CustomUserDetailsService; -import com.example.umc9th.global.jwt.JwtAuthFilter; -import com.example.umc9th.global.jwt.JwtUtil; +import com.umc9th.domain.user.userdetail.CustomUserDetailsService; +import com.umc9th.global.jwt.JwtAuthFilter; +import com.umc9th.global.jwt.JwtUtil; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/umc9th/global/enums/Role.java b/src/main/java/com/umc9th/global/enums/Role.java index 0a4211a..732289d 100644 --- a/src/main/java/com/umc9th/global/enums/Role.java +++ b/src/main/java/com/umc9th/global/enums/Role.java @@ -1,4 +1,4 @@ -package com.example.umc9th.global.enums; +package com.umc9th.global.enums; public enum Role { ROLE_ADMIN, ROLE_USER diff --git a/src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java b/src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java index e56bfd6..d194acc 100644 --- a/src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java +++ b/src/main/java/com/umc9th/global/jwt/JwtAuthFilter.java @@ -1,8 +1,8 @@ -package com.example.umc9th.global.jwt; +package com.umc9th.global.jwt; -import com.example.umc9th.domain.user.userdetail.CustomUserDetailsService; -import com.example.umc9th.global.apiPayload.ApiResponse; -import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.umc9th.domain.user.userdetail.CustomUserDetailsService; +import com.umc9th.global.apiPayload.ApiResponse; +import com.umc9th.global.apiPayload.code.GeneralErrorCode; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; diff --git a/src/main/java/com/umc9th/global/jwt/JwtUtil.java b/src/main/java/com/umc9th/global/jwt/JwtUtil.java index e1b7874..0526ff4 100644 --- a/src/main/java/com/umc9th/global/jwt/JwtUtil.java +++ b/src/main/java/com/umc9th/global/jwt/JwtUtil.java @@ -1,6 +1,6 @@ -package com.example.umc9th.global.jwt; +package com.umc9th.global.jwt; -import com.example.umc9th.domain.user.userdetail.CustomUserDetails; +import com.umc9th.domain.user.userdetail.CustomUserDetails; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.JwtException; diff --git a/src/main/java/com/umc9th/global/response/PageResponse.java b/src/main/java/com/umc9th/global/response/PageResponse.java index 9424d0a..f62ba9a 100644 --- a/src/main/java/com/umc9th/global/response/PageResponse.java +++ b/src/main/java/com/umc9th/global/response/PageResponse.java @@ -1,4 +1,4 @@ -package com.example.umc9th.global.apiPayload.response; +package com.umc9th.global.apiPayload.response; import lombok.Builder; diff --git a/src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java b/src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java index 40874dc..ecc3b2e 100644 --- a/src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java +++ b/src/main/java/com/umc9th/global/validator/CategoriesExistValidator.java @@ -1,7 +1,7 @@ -package com.example.umc9th.global.validator; +package com.umc9th.global.validator; -import com.example.umc9th.domain.category.repository.CategoryRepository; -import com.example.umc9th.global.annotation.ExistCategories; +import com.umc9th.domain.category.repository.CategoryRepository; +import com.umc9th.global.annotation.ExistCategories; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/umc9th/global/validator/PageCheckValidator.java b/src/main/java/com/umc9th/global/validator/PageCheckValidator.java index 1ad34cb..c49f654 100644 --- a/src/main/java/com/umc9th/global/validator/PageCheckValidator.java +++ b/src/main/java/com/umc9th/global/validator/PageCheckValidator.java @@ -1,7 +1,7 @@ -package com.example.umc9th.global.validator; +package com.umc9th.global.validator; -import com.example.umc9th.global.annotation.PageCheck; +import com.umc9th.global.annotation.PageCheck; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import org.springframework.stereotype.Component;