From 205f274cc6347a4472549568a43e8e29dd76a27b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Mon, 17 Jun 2024 10:00:00 +0900 Subject: [PATCH 01/26] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=97=86=EC=9D=B4=20=EA=B8=B0=EC=97=85(=ED=9A=8C=EC=9B=90)=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A1=B0=ED=9A=8C=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/companyUser/controller/CpUserController.java | 6 +++--- .../sinchulgwinong/global/config/WebSecurityConfig.java | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java b/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java index 1d88b93..a62bda5 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java @@ -27,7 +27,7 @@ public class CpUserController { private final CpUserService cpUserService; - @GetMapping("/profile") + @GetMapping("/{cpUserId}/profile") @Operation(summary = "기업(회원) 프로필 조회", description = "로그인한 사용자의 프로필 정보를 조회합니다. 전체를 수정할 필요 없이, 원하는 부분만 수정 가능합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "기업(회원) 프로필 조회 성공", @@ -44,9 +44,9 @@ public class CpUserController { examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> getCompanyUserProfile( - @AuthenticationPrincipal UserDetailsImpl userDetails) { + @PathVariable("cpUserId") Long cpUserId) { - CpUserProfileResponseDTO responseDTO = cpUserService.getCpUserProfile(userDetails.getCpUserId()); + CpUserProfileResponseDTO responseDTO = cpUserService.getCpUserProfile(cpUserId); return ResponseEntity.status(SUCCESS_CP_USER_PROFILE_READ.getHttpStatus()) .body( diff --git a/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java b/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java index aac915f..6557d56 100644 --- a/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java +++ b/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java @@ -34,6 +34,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers("/", "/home", "/aws", "/swagger-ui.html", "/v3/api-docs/**", "/swagger-ui/**").permitAll() .requestMatchers("/auth/signup", "/auth/login", "/auth/cp-signup", "/auth/cp-login").permitAll() .requestMatchers("/email/**").permitAll() + .requestMatchers("/cpUsers/{cpUserId}/profile").permitAll() .requestMatchers("/business/status", "/business/verify").permitAll() .requestMatchers(HttpMethod.GET, "/jobBoards", "/jobBoards/{jobBoardId}").permitAll() .anyRequest().authenticated()) From 3918e54162390edf74fb58f1d0470c12e09af055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Mon, 17 Jun 2024 10:08:26 +0900 Subject: [PATCH 02/26] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../companyUser/service/CpUserService.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/companyUser/service/CpUserService.java b/src/main/java/team9502/sinchulgwinong/domain/companyUser/service/CpUserService.java index c21ab28..18d2390 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/companyUser/service/CpUserService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/companyUser/service/CpUserService.java @@ -45,28 +45,32 @@ public CpUserProfileResponseDTO getCpUserProfile(Long cpUserId) { } @Transactional - public CpUserProfileResponseDTO updateCpUserProfile(Long cpUserId, CpUserProfileUpdateRequestDTO updateRequestDTO) { + public CpUserProfileResponseDTO updateCpUserProfile(Long cpUserId, CpUserProfileUpdateRequestDTO requestDTO) { + + if (requestDTO == null) { + throw new ApiException(ErrorCode.INVALID_INPUT); + } CompanyUser companyUser = companyUserRepository.findById(cpUserId) .orElseThrow(() -> new ApiException(ErrorCode.COMPANY_USER_NOT_FOUND)); - if (updateRequestDTO.getEmployeeCount() != null) { - companyUser.setEmployeeCount(updateRequestDTO.getEmployeeCount()); + if (requestDTO.getEmployeeCount() != null) { + companyUser.setEmployeeCount(requestDTO.getEmployeeCount()); } - if (updateRequestDTO.getHiringStatus() != null) { - companyUser.setHiringStatus(updateRequestDTO.getHiringStatus()); + if (requestDTO.getHiringStatus() != null) { + companyUser.setHiringStatus(requestDTO.getHiringStatus()); } - if (updateRequestDTO.getDescription() != null) { - companyUser.setDescription(updateRequestDTO.getDescription()); + if (requestDTO.getDescription() != null) { + companyUser.setDescription(requestDTO.getDescription()); } - if (updateRequestDTO.getCpEmail() != null) { - if (!emailVerificationService.isEmailVerified(updateRequestDTO.getCpEmail())) { + if (requestDTO.getCpEmail() != null) { + if (!emailVerificationService.isEmailVerified(requestDTO.getCpEmail())) { throw new ApiException(ErrorCode.EMAIL_NOT_VERIFIED); } - companyUser.setCpEmail(updateRequestDTO.getCpEmail()); + companyUser.setCpEmail(requestDTO.getCpEmail()); } - if (updateRequestDTO.getCpPhoneNumber() != null) { - companyUser.setCpPhoneNumber(updateRequestDTO.getCpPhoneNumber()); + if (requestDTO.getCpPhoneNumber() != null) { + companyUser.setCpPhoneNumber(requestDTO.getCpPhoneNumber()); } return new CpUserProfileResponseDTO( From e6f9dfb23fe6da73014874750994a42620b8161e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Mon, 17 Jun 2024 10:10:11 +0900 Subject: [PATCH 03/26] =?UTF-8?q?fix:=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CpUserController.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java b/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java index a62bda5..352b9e6 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java @@ -28,20 +28,20 @@ public class CpUserController { private final CpUserService cpUserService; @GetMapping("/{cpUserId}/profile") - @Operation(summary = "기업(회원) 프로필 조회", description = "로그인한 사용자의 프로필 정보를 조회합니다. 전체를 수정할 필요 없이, 원하는 부분만 수정 가능합니다.") + @Operation(summary = "기업(회원) 프로필 조회", description = "기업(회원)의 정보를 조회합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "기업(회원) 프로필 조회 성공", content = @Content(mediaType = "application/json", examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"프로필 조회 성공\", \"data\": {\"cpUserId\": 1, \"cpName\": \"팀9502\", \"cpEmail\": \"example@email.com\", \"cpPhoneNumber\": \"01012345678\", \"cpUsername\": \"김은채\", \"hiringStatus\": true, \"employeeCount\": 50, \"foundationDate\": \"2021-01-01\", \"description\": \"기업 소개 예시입니다.\", \"cpNum\": \"1234567890\", \"averageRating\": 4.5, \"reviewCount\": 20} }"))), - @ApiResponse(responseCode = "400", description = "잘못된 사용자 유형", + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"잘못된 요청 데이터입니다.\" }"))), @ApiResponse(responseCode = "404", description = "기업(회원)을 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"기업(회원)을 찾을 수 없습니다.\", \"data\": null }"))), - @ApiResponse(responseCode = "500", description = "서버 에러", + examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"기업(회원)을 찾을 수 없습니다.\" }"))), + @ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 오류가 발생했습니다.\" }"))) }) public ResponseEntity> getCompanyUserProfile( @PathVariable("cpUserId") Long cpUserId) { @@ -58,20 +58,17 @@ public ResponseEntity> getCompanyUse } @PatchMapping("/profile") - @Operation(summary = "기업(회원) 프로필 수정", description = "로그인한 기업 사용자의 프로필 정보를 수정합니다.") + @Operation(summary = "기업(회원) 프로필 수정", description = "로그인한 기업(회원)이 본인의 프로필 정보를 수정합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "프로필 수정 성공", content = @Content(mediaType = "application/json", examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"프로필 수정 성공\", \"data\": {\"cpUserId\": 1, \"cpName\": \"팀9502\", \"cpEmail\": \"fix@email.com\", \"cpPhoneNumber\": \"01012345678\", \"cpUsername\": \"김은채\", \"hiringStatus\": true, \"employeeCount\": 100, \"description\": \"수정된 기업 소개입니다.\", \"cpNum\": \"1234567890\"} }"))), - @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"요청 데이터가 유효하지 않습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "400", description = "이메일 인증 필요", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"이메일 인증이 필요합니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"이메일 인증이 필요합니다.\" }"))), @ApiResponse(responseCode = "404", description = "기업(회원)을 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"기업(회원)을 찾을 수 없습니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"기업(회원)을 찾을 수 없습니다.\" }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) From a4743528eeb022d53cc86483182eee2d1deb2846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Mon, 17 Jun 2024 10:43:17 +0900 Subject: [PATCH 04/26] =?UTF-8?q?feat:=20=EC=A0=95=EA=B7=9C=EC=8B=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/dto/request/CpUserSignupRequestDTO.java | 8 ++++++-- .../domain/auth/dto/request/UserSignupRequestDTO.java | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CpUserSignupRequestDTO.java b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CpUserSignupRequestDTO.java index 89530e0..43bc419 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CpUserSignupRequestDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CpUserSignupRequestDTO.java @@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.Getter; import lombok.NoArgsConstructor; @@ -40,6 +41,7 @@ public class CpUserSignupRequestDTO { private String cpUsername; @NotBlank(message = "회사 이메일을 입력해주세요.") + @Pattern(regexp = "^[a-zA-Z0-9]+@[a-zA-Z0-9]+(\\.[a-zA-Z]{2,})+$", message = "유효한 이메일 주소를 입력해주세요.") @Schema(description = "회사 이메일", example = "example@email.com") private String cpEmail; @@ -47,8 +49,10 @@ public class CpUserSignupRequestDTO { @Schema(description = "회사 전화번호", example = "01012345678") private String cpPhoneNumber; - @NotBlank(message = "회사 비밀번호를 입력해주세요.") - @Schema(description = "회사 비밀번호", example = "password") + @NotBlank(message = "비밀번호를 입력해주세요.") + @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$" + , message = "비밀번호는 최소 8자리이며, 알파벳, 숫자, 특수문자를 포함해야 합니다.") + @Schema(description = "비밀번호", example = "password") private String cpPassword; @NotBlank(message = "비밀번호 확인을 입력해주세요.") diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java index cea2ab4..1703ebc 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java @@ -2,6 +2,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; @@ -20,6 +21,8 @@ public class UserSignupRequestDTO { private String nickname; @NotBlank(message = "비밀번호를 입력해주세요.") + @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$" + , message = "비밀번호는 최소 8자리이며, 알파벳, 숫자, 특수문자를 포함해야 합니다.") @Schema(description = "비밀번호", example = "password") private String password; @@ -28,6 +31,7 @@ public class UserSignupRequestDTO { private String confirmPassword; @NotBlank(message = "이메일을 입력해주세요.") + @Pattern(regexp = "^[a-zA-Z0-9]+@[a-zA-Z0-9]+(\\.[a-zA-Z]{2,})+$", message = "유효한 이메일 주소를 입력해주세요.") @Schema(description = "이메일 주소", example = "example@example.com") private String email; From 825c86034835bc55cb2eda9d4c877a1f1c758bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Tue, 18 Jun 2024 14:06:57 +0900 Subject: [PATCH 05/26] =?UTF-8?q?feat:=20=EA=B5=AC=EA=B8=80=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 + .../dto/request/UserSignupRequestDTO.java | 14 +-- .../dto/response/UserLoginResponseDTO.java | 4 +- .../domain/auth/service/AuthService.java | 9 +- .../controller/SocialLoginController.java | 61 ++++++++++ .../domain/oauth/enums/SocialType.java | 6 + .../security/CustomOauth2UserDetails.java | 65 ++++++++++ .../security/CustomOauth2UserService.java | 43 +++++++ .../oauth/security/GoogleUserDetails.java | 32 +++++ .../domain/oauth/security/OAuth2UserInfo.java | 12 ++ .../oauth/service/SocialLoginService.java | 115 ++++++++++++++++++ .../domain/user/entity/User.java | 11 +- .../domain/user/enums/LoginType.java | 5 - .../domain/user/service/UserService.java | 5 - .../global/config/WebSecurityConfig.java | 2 +- .../global/exception/ErrorCode.java | 1 + .../global/response/SuccessCode.java | 3 + .../global/security/UserDetailsImpl.java | 7 +- .../security/UserDetailsServiceImpl.java | 5 +- src/main/resources/application-local.yml | 12 ++ src/main/resources/application-prod.yml | 12 ++ 21 files changed, 392 insertions(+), 36 deletions(-) create mode 100644 src/main/java/team9502/sinchulgwinong/domain/oauth/controller/SocialLoginController.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/oauth/enums/SocialType.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserDetails.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserService.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/oauth/security/GoogleUserDetails.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/oauth/security/OAuth2UserInfo.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/oauth/service/SocialLoginService.java delete mode 100644 src/main/java/team9502/sinchulgwinong/domain/user/enums/LoginType.java diff --git a/build.gradle b/build.gradle index 2e0c63f..786aa04 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,10 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web-services' + // OAuth2 + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation 'org.springframework.security:spring-security-oauth2-core' + // Springdoc OpenAPI implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0' diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java index 1703ebc..7afcb06 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserSignupRequestDTO.java @@ -6,7 +6,7 @@ import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; -import team9502.sinchulgwinong.domain.user.enums.LoginType; +import team9502.sinchulgwinong.domain.oauth.enums.SocialType; @Getter @NoArgsConstructor @@ -21,13 +21,13 @@ public class UserSignupRequestDTO { private String nickname; @NotBlank(message = "비밀번호를 입력해주세요.") - @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$" - , message = "비밀번호는 최소 8자리이며, 알파벳, 숫자, 특수문자를 포함해야 합니다.") + @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%?&])[A-Za-z\\d@$!%*?&]{8,}$", + message = "비밀번호는 최소 8자리이며, 알파벳, 숫자, 특수문자를 포함해야 합니다.") @Schema(description = "비밀번호", example = "password") private String password; @NotBlank(message = "비밀번호 확인을 입력해주세요.") - @Schema(description = "비밀번호 확인", example = "password") + @Schema(description = "비밀번호 확인", example = "Password1!") private String confirmPassword; @NotBlank(message = "이메일을 입력해주세요.") @@ -38,9 +38,9 @@ public class UserSignupRequestDTO { @Schema(description = "전화번호", example = "01012345678") private String phoneNumber; - @Schema(description = "로그인 유형", example = "EMAIL") - private LoginType loginType; - @Schema(description = "약관 동의 여부", example = "true") private boolean agreeToTerms; + + @Schema(description = "로그인 타입", example = "GOOGLE") + private SocialType loginType; } diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/response/UserLoginResponseDTO.java b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/response/UserLoginResponseDTO.java index 5ddcc2c..992b17c 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/response/UserLoginResponseDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/response/UserLoginResponseDTO.java @@ -3,7 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import team9502.sinchulgwinong.domain.user.enums.LoginType; +import team9502.sinchulgwinong.domain.oauth.enums.SocialType; @Getter @NoArgsConstructor @@ -20,5 +20,5 @@ public class UserLoginResponseDTO { private String phoneNumber; - private LoginType loginType; + private SocialType loginType; } diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java b/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java index 09ca4ed..26140cd 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java @@ -19,6 +19,7 @@ import team9502.sinchulgwinong.domain.companyUser.repository.CompanyUserRepository; import team9502.sinchulgwinong.domain.companyUser.service.EncryptionService; import team9502.sinchulgwinong.domain.email.service.EmailVerificationService; +import team9502.sinchulgwinong.domain.oauth.enums.SocialType; import team9502.sinchulgwinong.domain.point.enums.SpType; import team9502.sinchulgwinong.domain.point.service.PointService; import team9502.sinchulgwinong.domain.user.entity.User; @@ -59,7 +60,7 @@ public void signup(UserSignupRequestDTO signupRequest) { .nickname(signupRequest.getNickname()) .email(signupRequest.getEmail()) .password(passwordEncoder.encode(signupRequest.getPassword())) - .loginType(signupRequest.getLoginType()) + .loginType(SocialType.NORMAL) .build(); userRepository.save(user); @@ -129,7 +130,7 @@ public UserLoginResponseDTO login(UserLoginRequestDTO loginRequest) { user.getNickname(), user.getEmail(), user.getPhoneNumber(), - user.getLoginType() + user.getLoginType() // 로그인 타입 추가 ); } @@ -175,6 +176,10 @@ private void validateUserSignupRequest(String email, String password, String con throw new ApiException(ErrorCode.EMAIL_DUPLICATION); } + if (password == null || password.isEmpty()) { + throw new ApiException(ErrorCode.PASSWORD_CANNOT_BE_NULL); + } + if (!password.equals(confirmPassword)) { throw new ApiException(ErrorCode.PASSWORD_MISMATCH); } diff --git a/src/main/java/team9502/sinchulgwinong/domain/oauth/controller/SocialLoginController.java b/src/main/java/team9502/sinchulgwinong/domain/oauth/controller/SocialLoginController.java new file mode 100644 index 0000000..5ebbfa6 --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/oauth/controller/SocialLoginController.java @@ -0,0 +1,61 @@ +package team9502.sinchulgwinong.domain.oauth.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import team9502.sinchulgwinong.domain.auth.dto.request.UserSignupRequestDTO; +import team9502.sinchulgwinong.domain.oauth.enums.SocialType; +import team9502.sinchulgwinong.domain.oauth.service.SocialLoginService; +import team9502.sinchulgwinong.global.response.GlobalApiResponse; + +import static team9502.sinchulgwinong.global.response.SuccessCode.SUCCESS_SOCIAL_LOGIN; + +@RestController +@RequestMapping("/social-login") +@RequiredArgsConstructor +@Tag(name = "SocialLogin", description = "소셜 로그인 관련 API [김은채]") +public class SocialLoginController { + + private final SocialLoginService socialLoginService; + + @PostMapping("/additional-info") + @Operation(summary = "소셜 로그인 추가 정보", description = "소셜 로그인 후 추가 정보를 입력받습니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "추가 정보 등록 성공", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"추가 정보 등록 성공\", \"data\": {\"userId\": 3, \"socialType\": \"GOOGLE\", \"email\": \"user@example.com\"}}"))), + @ApiResponse(responseCode = "400", description = "입력 데이터 오류", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"입력 데이터 오류\", \"data\": null }"))), + @ApiResponse(responseCode = "500", description = "서버 에러", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + }) + public ResponseEntity> submitAdditionalInfo( + @RequestBody @Valid UserSignupRequestDTO requestDTO) { + + socialLoginService.createOrUpdateSocialLogin(requestDTO, SocialType.GOOGLE); + + return ResponseEntity.status(SUCCESS_SOCIAL_LOGIN.getHttpStatus()) + .body(GlobalApiResponse.of(SUCCESS_SOCIAL_LOGIN.getMessage(), null)); + } + + @GetMapping("/callback") + @Operation(summary = "소셜 로그인 콜백", description = "구글 OAuth2 콜백을 처리합니다.") + public ResponseEntity handleGoogleCallback( + @RequestParam("code") String code) { + try { + String response = socialLoginService.handleGoogleCallback(code); + return ResponseEntity.ok("소셜 로그인 콜백 처리 완료: " + response); + } catch (Exception e) { + return ResponseEntity.status(500).body("소셜 로그인 콜백 처리 실패: " + e.getMessage()); + } + } +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/oauth/enums/SocialType.java b/src/main/java/team9502/sinchulgwinong/domain/oauth/enums/SocialType.java new file mode 100644 index 0000000..03eba93 --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/oauth/enums/SocialType.java @@ -0,0 +1,6 @@ +package team9502.sinchulgwinong.domain.oauth.enums; + +public enum SocialType { + + NORMAL, GOOGLE, KAKAO +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserDetails.java b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserDetails.java new file mode 100644 index 0000000..bafff92 --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserDetails.java @@ -0,0 +1,65 @@ +package team9502.sinchulgwinong.domain.oauth.security; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.user.OAuth2User; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +public class CustomOauth2UserDetails implements UserDetails, OAuth2User { + private final OAuth2UserInfo userInfo; + private final Map attributes; + + public CustomOauth2UserDetails(OAuth2UserInfo userInfo, Map attributes) { + this.userInfo = userInfo; + this.attributes = attributes; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public String getName() { + return userInfo.getName(); + } + + @Override + public Collection getAuthorities() { + return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + } + + @Override + public String getPassword() { + return null; // 소셜 로그인에는 비밀번호가 없습니다. + } + + @Override + public String getUsername() { + return userInfo.getEmail(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserService.java b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserService.java new file mode 100644 index 0000000..fa02a10 --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/CustomOauth2UserService.java @@ -0,0 +1,43 @@ +package team9502.sinchulgwinong.domain.oauth.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; +import team9502.sinchulgwinong.domain.user.entity.User; +import team9502.sinchulgwinong.domain.user.repository.UserRepository; + +import java.util.Map; + +@Service +public class CustomOauth2UserService extends DefaultOAuth2UserService { + private final UserRepository userRepository; + + @Autowired + public CustomOauth2UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2AuthenticationException { + OAuth2User oAuth2User = super.loadUser(request); + String provider = request.getClientRegistration().getRegistrationId(); + Map attributes = oAuth2User.getAttributes(); + OAuth2UserInfo userInfo = new GoogleUserDetails(attributes); + + User user = userRepository.findByEmail(userInfo.getEmail()) + .orElseGet(() -> registerNewUser(userInfo)); + + return new CustomOauth2UserDetails(userInfo, attributes); + } + + private User registerNewUser(OAuth2UserInfo userInfo) { + User user = new User(); + user.setEmail(userInfo.getEmail()); + user.setUsername(userInfo.getName()); + + return userRepository.save(user); + } +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/oauth/security/GoogleUserDetails.java b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/GoogleUserDetails.java new file mode 100644 index 0000000..755b329 --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/GoogleUserDetails.java @@ -0,0 +1,32 @@ +package team9502.sinchulgwinong.domain.oauth.security; + +import java.util.Map; + +public class GoogleUserDetails implements OAuth2UserInfo { + + private final Map attributes; + + public GoogleUserDetails(Map attributes) { + this.attributes = attributes; + } + + @Override + public String getProvider() { + return "google"; + } + + @Override + public String getProviderId() { + return (String) attributes.get("sub"); + } + + @Override + public String getEmail() { + return (String) attributes.get("email"); + } + + @Override + public String getName() { + return (String) attributes.get("name"); + } +} \ No newline at end of file diff --git a/src/main/java/team9502/sinchulgwinong/domain/oauth/security/OAuth2UserInfo.java b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/OAuth2UserInfo.java new file mode 100644 index 0000000..770767d --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/oauth/security/OAuth2UserInfo.java @@ -0,0 +1,12 @@ +package team9502.sinchulgwinong.domain.oauth.security; + +public interface OAuth2UserInfo { + + String getProvider(); + + String getProviderId(); + + String getEmail(); + + String getName(); +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/oauth/service/SocialLoginService.java b/src/main/java/team9502/sinchulgwinong/domain/oauth/service/SocialLoginService.java new file mode 100644 index 0000000..94bb17c --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/oauth/service/SocialLoginService.java @@ -0,0 +1,115 @@ +package team9502.sinchulgwinong.domain.oauth.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.http.converter.FormHttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import team9502.sinchulgwinong.domain.auth.dto.request.UserSignupRequestDTO; +import team9502.sinchulgwinong.domain.oauth.enums.SocialType; +import team9502.sinchulgwinong.domain.point.enums.SpType; +import team9502.sinchulgwinong.domain.point.service.PointService; +import team9502.sinchulgwinong.domain.user.entity.User; +import team9502.sinchulgwinong.domain.user.repository.UserRepository; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +@Service +@RequiredArgsConstructor +public class SocialLoginService { + + private final UserRepository userRepository; + private final RestTemplate restTemplate; + private final PointService pointService; + + @Value("${spring.security.oauth2.client.registration.google.client-id}") + private String clientId; + + @Value("${spring.security.oauth2.client.registration.google.client-secret}") + private String clientSecret; + + @Value("${spring.security.oauth2.client.registration.google.redirect-uri}") + private String redirectUri; + + @Transactional + public User createOrUpdateSocialLogin(UserSignupRequestDTO requestDTO, SocialType socialType) { + return userRepository.findByEmail(requestDTO.getEmail()) + .orElseGet(() -> createUser(requestDTO, socialType)); + } + + @Transactional + public String handleGoogleCallback(String code) throws Exception { + + restTemplate.setMessageConverters(Arrays.asList(new FormHttpMessageConverter(), new StringHttpMessageConverter(StandardCharsets.UTF_8))); + + String accessTokenUrl = "https://oauth2.googleapis.com/token"; + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("code", code); + params.add("client_id", clientId); + params.add("client_secret", clientSecret); + params.add("redirect_uri", redirectUri); + params.add("grant_type", "authorization_code"); + + HttpEntity> request = new HttpEntity<>(params, headers); + ResponseEntity response = restTemplate.postForEntity(accessTokenUrl, request, String.class); + + if (response.getStatusCode() == HttpStatus.OK) { + String responseBody = response.getBody(); + ObjectMapper mapper = new ObjectMapper(); + JsonNode jsonNode = mapper.readTree(responseBody); + String accessToken = jsonNode.get("access_token").asText(); + + String userInfoUrl = "https://www.googleapis.com/oauth2/v2/userinfo"; + HttpHeaders userInfoHeaders = new HttpHeaders(); + userInfoHeaders.setBearerAuth(accessToken); + + HttpEntity userInfoRequest = new HttpEntity<>(userInfoHeaders); + ResponseEntity userInfoResponse = restTemplate.exchange(userInfoUrl, HttpMethod.GET, userInfoRequest, String.class); + + if (userInfoResponse.getStatusCode() == HttpStatus.OK) { + // Google 사용자 정보 파싱 + JsonNode userInfo = mapper.readTree(userInfoResponse.getBody()); + String email = userInfo.get("email").asText(); + String username = userInfo.get("name").asText(); + String nickname = userInfo.get("given_name").asText(); + + // 임시로 소셜 로그인 사용자 정보 세션에 저장 + // 클라이언트 측에서 추가 정보 입력 폼으로 리디렉션 후 이 정보를 사용 + return "redirect:/social-login/additional-info?email=" + email + "&username=" + username + "&nickname=" + nickname; + } else { + throw new RuntimeException("사용자 정보 요청 실패"); + } + } else { + // 오류 메시지 로깅 + System.out.println("Response Status: " + response.getStatusCode()); + System.out.println("Response Body: " + response.getBody()); + + throw new RuntimeException("액세스 토큰 요청 실패"); + } + } + + private User createUser(UserSignupRequestDTO requestDTO, SocialType socialType) { + User newUser = User.builder() + .email(requestDTO.getEmail()) + .nickname(requestDTO.getNickname()) + .password(requestDTO.getPassword()) + .username(requestDTO.getUsername()) + .phoneNumber(requestDTO.getPhoneNumber()) + .loginType(socialType) + .build(); + User savedUser = userRepository.save(newUser); + pointService.earnPoints(savedUser, SpType.SIGNUP); // 포인트 적립 + return savedUser; + } +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/entity/User.java b/src/main/java/team9502/sinchulgwinong/domain/user/entity/User.java index 400b3d9..7679dde 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/user/entity/User.java +++ b/src/main/java/team9502/sinchulgwinong/domain/user/entity/User.java @@ -3,9 +3,9 @@ import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.DynamicUpdate; +import team9502.sinchulgwinong.domain.oauth.enums.SocialType; import team9502.sinchulgwinong.domain.point.CommonPoint; import team9502.sinchulgwinong.domain.point.entity.Point; -import team9502.sinchulgwinong.domain.user.enums.LoginType; import team9502.sinchulgwinong.global.entity.BaseTimeEntity; @Entity @@ -42,11 +42,12 @@ public class User extends BaseTimeEntity implements CommonPoint { @Column(nullable = false, length = 250) private String email; - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private LoginType loginType; - @Setter @Column(length = 11) private String phoneNumber; + + @Setter + @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 20) + private SocialType loginType; } diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/enums/LoginType.java b/src/main/java/team9502/sinchulgwinong/domain/user/enums/LoginType.java deleted file mode 100644 index ec38c98..0000000 --- a/src/main/java/team9502/sinchulgwinong/domain/user/enums/LoginType.java +++ /dev/null @@ -1,5 +0,0 @@ -package team9502.sinchulgwinong.domain.user.enums; - -public enum LoginType { - EMAIL, GOOGLE, KAKAO -} diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java b/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java index 1546d8e..4fe0df8 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java @@ -9,7 +9,6 @@ import team9502.sinchulgwinong.domain.user.dto.request.UserProfileUpdateRequestDTO; import team9502.sinchulgwinong.domain.user.dto.response.UserProfileResponseDTO; import team9502.sinchulgwinong.domain.user.entity.User; -import team9502.sinchulgwinong.domain.user.enums.LoginType; import team9502.sinchulgwinong.domain.user.repository.UserRepository; import team9502.sinchulgwinong.global.exception.ApiException; import team9502.sinchulgwinong.global.exception.ErrorCode; @@ -72,10 +71,6 @@ public UserProfileResponseDTO updateUserProfile(Long userId, UserProfileUpdateRe @Transactional public void updateUserPassword(Long userId, UserPasswordUpdateRequestDTO requestDTO, UserDetailsImpl userDetails) { - if (!userDetails.getLoginType().equals(LoginType.EMAIL)) { - throw new ApiException(ErrorCode.INVALID_LOGIN_TYPE); - } - User user = userRepository.findById(userId) .orElseThrow(() -> new ApiException(ErrorCode.USER_NOT_FOUND)); diff --git a/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java b/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java index 6557d56..c033143 100644 --- a/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java +++ b/src/main/java/team9502/sinchulgwinong/global/config/WebSecurityConfig.java @@ -33,7 +33,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/home", "/aws", "/swagger-ui.html", "/v3/api-docs/**", "/swagger-ui/**").permitAll() .requestMatchers("/auth/signup", "/auth/login", "/auth/cp-signup", "/auth/cp-login").permitAll() - .requestMatchers("/email/**").permitAll() + .requestMatchers("/email/**", "/social-login/**").permitAll() .requestMatchers("/cpUsers/{cpUserId}/profile").permitAll() .requestMatchers("/business/status", "/business/verify").permitAll() .requestMatchers(HttpMethod.GET, "/jobBoards", "/jobBoards/{jobBoardId}").permitAll() diff --git a/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java b/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java index e2e49ba..de63397 100644 --- a/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java +++ b/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java @@ -24,6 +24,7 @@ public enum ErrorCode { TERMS_NOT_ACCEPTED(HttpStatus.BAD_REQUEST, "약관에 동의해야 합니다."), INVALID_LOGIN_TYPE(HttpStatus.BAD_REQUEST, "잘못된 로그인 유형입니다."), PASSWORD_CONFIRM_MISMATCH(HttpStatus.BAD_REQUEST, "비밀번호와 비밀번호 확인이 일치하지 않습니다."), + PASSWORD_CANNOT_BE_NULL(HttpStatus.BAD_REQUEST, "비밀번호를 입력해주세요."), // Email EMAIL_AUTH_FAILED(HttpStatus.UNAUTHORIZED, "이메일 인증에 실패했습니다."), diff --git a/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java b/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java index 67b68dc..a3bf80b 100644 --- a/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java +++ b/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java @@ -19,6 +19,9 @@ public enum SuccessCode { SUCCESS_USER_PROFILE_UPDATED(HttpStatus.OK, "구직자 프로필 수정 성공"), SUCCESS_USER_PASSWORD_UPDATED(HttpStatus.OK, "구직자 비밀번호 수정 성공"), + // SocialLogin + SUCCESS_SOCIAL_LOGIN(HttpStatus.OK, "소셜 로그인 성공"), + // Email SUCCESS_EMAIL_VERIFICATION_SENT(HttpStatus.OK, "이메일 인증 코드 발송 성공"), SUCCESS_EMAIL_VERIFICATION(HttpStatus.OK, "이메일 인증 성공"), diff --git a/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsImpl.java b/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsImpl.java index f305d21..489b910 100644 --- a/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsImpl.java +++ b/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsImpl.java @@ -5,7 +5,6 @@ import org.springframework.security.core.userdetails.UserDetails; import team9502.sinchulgwinong.domain.companyUser.entity.CompanyUser; import team9502.sinchulgwinong.domain.user.entity.User; -import team9502.sinchulgwinong.domain.user.enums.LoginType; import team9502.sinchulgwinong.global.exception.ApiException; import java.util.Collection; @@ -24,16 +23,12 @@ public class UserDetailsImpl implements UserDetails { @Getter private final Object user; - @Getter - private final LoginType loginType; - - public UserDetailsImpl(String email, String password, Collection authorities, String userType, Object user, LoginType loginType) { + public UserDetailsImpl(String email, String password, Collection authorities, String userType, Object user) { this.email = email; this.password = password; this.authorities = authorities; this.userType = userType; this.user = user; - this.loginType = loginType; } public Long getUserId() { diff --git a/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsServiceImpl.java b/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsServiceImpl.java index cdb7e15..fe48e8e 100644 --- a/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsServiceImpl.java +++ b/src/main/java/team9502/sinchulgwinong/global/security/UserDetailsServiceImpl.java @@ -8,7 +8,6 @@ import team9502.sinchulgwinong.domain.companyUser.entity.CompanyUser; import team9502.sinchulgwinong.domain.companyUser.repository.CompanyUserRepository; import team9502.sinchulgwinong.domain.user.entity.User; -import team9502.sinchulgwinong.domain.user.enums.LoginType; import team9502.sinchulgwinong.domain.user.repository.UserRepository; import java.util.Collections; @@ -30,13 +29,13 @@ public UserDetails loadUserByUsername(String email) throws UsernameNotFoundExcep if (user != null) { return new UserDetailsImpl(user.getEmail(), user.getPassword(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")), - "USER", user, user.getLoginType()); + "USER", user); } CompanyUser companyUser = companyUserRepository.findByCpEmail(email).orElseThrow(() -> new UsernameNotFoundException(email + "으로 등록된 사용자를 찾을 수 없습니다.")); return new UserDetailsImpl(companyUser.getCpEmail(), companyUser.getCpPassword(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_COMPANY")), - "COMPANY", companyUser, LoginType.EMAIL); + "COMPANY", companyUser); } } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index eca4106..3e56e30 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -34,6 +34,18 @@ spring: starttls: enable: true + security: + oauth2: + client: + registration: + google: + client-id: ${GOOGLE_CLIENT_ID} + client-secret: ${GOOGLE_CLIENT_SECRET} + scope: + - email + - profile + redirect-uri: ${GOOGLE_REDIRECT_URI} + jwt: secret: ${jwt.secretKey} expirationMs: 21600000 # 6 hours diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 71e5b77..07d6d50 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -33,6 +33,18 @@ spring: starttls: enable: true + security: + oauth2: + client: + registration: + google: + client-id: ${GOOGLE_CLIENT_ID} + client-secret: ${GOOGLE_CLIENT_SECRET} + scope: + - email + - profile + redirect-uri: ${GOOGLE_REDIRECT_URI} + jwt: secret: ${JWT_SECRETKEY} expirationMs: 3600000 # 1 hour From fa809a380fc73824651d365662cb71c9840622ec Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Tue, 18 Jun 2024 22:53:48 +0900 Subject: [PATCH 06/26] =?UTF-8?q?fix:=20=EA=B5=AC=EC=9D=B8=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scrap/controller/ScrapController.java | 46 ++++++++++++++++++ .../dto/response/JobScrapResponseDTO.java | 30 ++++++++++++ .../domain/scrap/entity/JobScrap.java | 26 ++++++++++ .../domain/scrap/entity/Scrap.java | 2 +- .../scrap/repository/JobScrapRepository.java | 13 +++++ .../domain/scrap/service/ScrapService.java | 48 ++++++++++++++++++- 6 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/scrap/entity/JobScrap.java create mode 100644 src/main/java/team9502/sinchulgwinong/domain/scrap/repository/JobScrapRepository.java diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java index 6f9cfff..d077963 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java @@ -4,6 +4,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; +import team9502.sinchulgwinong.domain.scrap.dto.response.JobScrapResponseDTO; import team9502.sinchulgwinong.domain.scrap.dto.response.ScrapResponseDTO; import team9502.sinchulgwinong.domain.scrap.service.ScrapService; import team9502.sinchulgwinong.domain.user.entity.User; @@ -67,5 +68,50 @@ public ResponseEntity>> getAllScraps( ); } + @PostMapping("/jobBoards/{/jobBoardId}") + public ResponseEntity> scrapCreateJobBoard( + @PathVariable Long jobBoardId, + @AuthenticationPrincipal UserDetailsImpl userDetails){ + + User user = (User) userDetails.getUser(); + + boolean isCreated = scrapService.scrapCreateJobBoard(jobBoardId, user); + + if (isCreated) { + return ResponseEntity.status(SUCCESS_CREATE_SCRAP.getHttpStatus()) + .body( + GlobalApiResponse.of( + SUCCESS_CREATE_SCRAP.getMessage(), + null + ) + ); + } + else { + return ResponseEntity.status(SUCCESS_CREATE_SCRAP.getHttpStatus()) + .body( + GlobalApiResponse.of( + SUCCESS_DELETE_SCRAP.getMessage(), + null + ) + ); + } +} + + @GetMapping + public ResponseEntity>> getAllJobScraps( + @AuthenticationPrincipal UserDetailsImpl userDetails){ + + User user = (User) userDetails.getUser(); + + List jobScrapResponseDTOS = scrapService.getAllJobBoards(user); + + return ResponseEntity.status(SUCCESS_READ_ALL_SCRAP.getHttpStatus()) + .body( + GlobalApiResponse.of( + SUCCESS_READ_ALL_SCRAP.getMessage(), + jobScrapResponseDTOS + ) + ); + } } diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java new file mode 100644 index 0000000..80f675f --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java @@ -0,0 +1,30 @@ +package team9502.sinchulgwinong.domain.scrap.dto.response; + +import lombok.Getter; +import team9502.sinchulgwinong.domain.jobBoard.entity.JobBoard; +import team9502.sinchulgwinong.domain.scrap.entity.JobScrap; + +import java.time.LocalDateTime; + +@Getter +public class JobScrapResponseDTO { + + private Long userId; + + private Long scrapId; + + private Long jobBoardId; + + private String boardTitle; + + private String userName; + + private LocalDateTime createdAt; + + public JobScrapResponseDTO(JobScrap jobScrap, JobBoard jobBoard) { + this.scrapId = jobScrap.getJobScrapId(); + this.jobBoardId = jobScrap.getJobBoard().getJobBoardId(); + this.userId = jobScrap.getUser().getUserId(); + + } +} \ No newline at end of file diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/entity/JobScrap.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/entity/JobScrap.java new file mode 100644 index 0000000..c95d2e8 --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/entity/JobScrap.java @@ -0,0 +1,26 @@ +package team9502.sinchulgwinong.domain.scrap.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import team9502.sinchulgwinong.domain.jobBoard.entity.JobBoard; +import team9502.sinchulgwinong.domain.user.entity.User; + +@Getter +@Entity +public class JobScrap { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long jobScrapId; + + @Setter + @OneToOne + @JoinColumn(name = "job_board_id") + private JobBoard jobBoard; + + @Setter + @ManyToOne + @JoinColumn(name = "userId") + private User user; +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/entity/Scrap.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/entity/Scrap.java index 2f749bd..437153d 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/entity/Scrap.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/entity/Scrap.java @@ -15,7 +15,7 @@ public class Scrap { private Long scrapId; @Setter - @ManyToOne + @OneToOne @JoinColumn(name = "boardId") private Board board; diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/repository/JobScrapRepository.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/repository/JobScrapRepository.java new file mode 100644 index 0000000..0227111 --- /dev/null +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/repository/JobScrapRepository.java @@ -0,0 +1,13 @@ +package team9502.sinchulgwinong.domain.scrap.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import team9502.sinchulgwinong.domain.scrap.entity.JobScrap; + +import java.util.List; + +public interface JobScrapRepository extends JpaRepository { + + boolean existsByJobBoard_JobBoardIdAndUser_UserId(Long jobBoardId, Long userId); + JobScrap findByJobBoard_JobBoardIdAndUser_UserId(Long jobBoardId, Long userId); + List findByUser_UserId(Long userId); +} diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/service/ScrapService.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/service/ScrapService.java index ecc4af7..72f3d31 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/service/ScrapService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/service/ScrapService.java @@ -5,8 +5,13 @@ import org.springframework.transaction.annotation.Transactional; import team9502.sinchulgwinong.domain.board.entity.Board; import team9502.sinchulgwinong.domain.board.repository.BoardRepository; +import team9502.sinchulgwinong.domain.jobBoard.entity.JobBoard; +import team9502.sinchulgwinong.domain.jobBoard.repository.JobBoardRepository; +import team9502.sinchulgwinong.domain.scrap.dto.response.JobScrapResponseDTO; import team9502.sinchulgwinong.domain.scrap.dto.response.ScrapResponseDTO; +import team9502.sinchulgwinong.domain.scrap.entity.JobScrap; import team9502.sinchulgwinong.domain.scrap.entity.Scrap; +import team9502.sinchulgwinong.domain.scrap.repository.JobScrapRepository; import team9502.sinchulgwinong.domain.scrap.repository.ScrapsRepository; import team9502.sinchulgwinong.domain.user.entity.User; import team9502.sinchulgwinong.global.exception.ApiException; @@ -21,6 +26,8 @@ public class ScrapService { private final ScrapsRepository scrapsRepository; private final BoardRepository boardRepository; + private final JobBoardRepository jobBoardRepository; + private final JobScrapRepository jobScrapRepository; @Transactional public boolean scrapCreateBoard(Long boardId, User user){ @@ -58,4 +65,43 @@ public List getAllScraps(User user){ .collect(Collectors.toList()); } -} + @Transactional + public boolean scrapCreateJobBoard(Long jobBoardId, User user){ + + JobBoard jobBoard = jobBoardRepository.findById(jobBoardId) + .orElseThrow(()-> new ApiException(ErrorCode.BOARD_NOT_FOUND)); + + if(jobScrapRepository.existsByJobBoard_JobBoardIdAndUser_UserId(jobBoardId, user.getUserId())){ + + JobScrap jobScrap = jobScrapRepository.findByJobBoard_JobBoardIdAndUser_UserId(jobBoardId, user.getUserId()); + + jobScrapRepository.delete(jobScrap); + + return false; + + } + else{ + + JobScrap jobScrap = new JobScrap(); + + jobScrap.setJobBoard(jobBoard); + jobScrap.setUser(user); + + jobScrapRepository.save(jobScrap); + + return true; + } + } + + @Transactional(readOnly = true) + public List getAllJobBoards(User user){ + + return jobScrapRepository.findByUser_UserId(user.getUserId()).stream() + .map(jobScrap ->{ + JobBoard jobBoard = jobScrap.getJobBoard(); + return new JobScrapResponseDTO(jobScrap,jobBoard); + }) + .collect(Collectors.toList()); + } + + } From dae9f13ea5417b42b09e54f8127f81d9f4aa8d02 Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Tue, 18 Jun 2024 22:58:59 +0900 Subject: [PATCH 07/26] =?UTF-8?q?fix:=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20?= =?UTF-8?q?=EC=95=A4=EB=93=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/scrap/controller/ScrapController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java index d077963..b2dd42d 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java @@ -50,7 +50,7 @@ public ResponseEntity> scrapCreateBoard( } } - @GetMapping + @GetMapping("/boards") public ResponseEntity>> getAllScraps( @AuthenticationPrincipal UserDetailsImpl userDetails){ @@ -97,7 +97,7 @@ public ResponseEntity> scrapCreateJobBoard( } } - @GetMapping + @GetMapping("/jobBoards") public ResponseEntity>> getAllJobScraps( @AuthenticationPrincipal UserDetailsImpl userDetails){ From 830b2e07c3c5f3ea63928b173a3918e074b99447 Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Tue, 18 Jun 2024 23:15:00 +0900 Subject: [PATCH 08/26] =?UTF-8?q?fix:=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20?= =?UTF-8?q?=EC=95=A4=EB=93=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sinchulgwinong/domain/scrap/controller/ScrapController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java index b2dd42d..ee51090 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java @@ -68,7 +68,7 @@ public ResponseEntity>> getAllScraps( ); } - @PostMapping("/jobBoards/{/jobBoardId}") + @PostMapping("/jobBoards/{jobBoardId}") public ResponseEntity> scrapCreateJobBoard( @PathVariable Long jobBoardId, @AuthenticationPrincipal UserDetailsImpl userDetails){ From e929baeda7cafa3c1922c58029018ecf5d001c35 Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 00:08:28 +0900 Subject: [PATCH 09/26] =?UTF-8?q?fix:=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20?= =?UTF-8?q?=EC=95=A4=EB=93=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/scrap/controller/ScrapController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java index ee51090..f77aeaa 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java @@ -68,7 +68,7 @@ public ResponseEntity>> getAllScraps( ); } - @PostMapping("/jobBoards/{jobBoardId}") + @PostMapping("/job-boards/{jobBoardId}") public ResponseEntity> scrapCreateJobBoard( @PathVariable Long jobBoardId, @AuthenticationPrincipal UserDetailsImpl userDetails){ @@ -97,7 +97,7 @@ public ResponseEntity> scrapCreateJobBoard( } } - @GetMapping("/jobBoards") + @GetMapping("/job-boards") public ResponseEntity>> getAllJobScraps( @AuthenticationPrincipal UserDetailsImpl userDetails){ From 25d480e4f900846339695ba3ec09cc4358ccef42 Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 01:34:35 +0900 Subject: [PATCH 10/26] =?UTF-8?q?fix:=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20?= =?UTF-8?q?=EC=95=A4=EB=93=9C=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/scrap/controller/ScrapController.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java index f77aeaa..81368df 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/controller/ScrapController.java @@ -2,6 +2,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import team9502.sinchulgwinong.domain.scrap.dto.response.JobScrapResponseDTO; @@ -17,6 +18,7 @@ @RestController @RequestMapping("/scraps") +@PreAuthorize("hasAuthority('ROLE_USER')") @RequiredArgsConstructor public class ScrapController { @@ -24,7 +26,7 @@ public class ScrapController { @PostMapping("/boards/{boardId}") public ResponseEntity> scrapCreateBoard( - @PathVariable Long boardId, + @PathVariable(("boardId")) Long boardId, @AuthenticationPrincipal UserDetailsImpl userDetails){ User user = (User) userDetails.getUser(); @@ -70,7 +72,7 @@ public ResponseEntity>> getAllScraps( @PostMapping("/job-boards/{jobBoardId}") public ResponseEntity> scrapCreateJobBoard( - @PathVariable Long jobBoardId, + @PathVariable("jobBoardId") Long jobBoardId, @AuthenticationPrincipal UserDetailsImpl userDetails){ User user = (User) userDetails.getUser(); From fb44e07dc8623d5c3e6d957f92af086ed3dbd664 Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 01:40:02 +0900 Subject: [PATCH 11/26] =?UTF-8?q?fix:=20=EA=B5=AC=EC=9D=B8=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/scrap/dto/response/JobScrapResponseDTO.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java b/src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java index 80f675f..0433819 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/scrap/dto/response/JobScrapResponseDTO.java @@ -4,8 +4,6 @@ import team9502.sinchulgwinong.domain.jobBoard.entity.JobBoard; import team9502.sinchulgwinong.domain.scrap.entity.JobScrap; -import java.time.LocalDateTime; - @Getter public class JobScrapResponseDTO { @@ -15,16 +13,10 @@ public class JobScrapResponseDTO { private Long jobBoardId; - private String boardTitle; - - private String userName; - - private LocalDateTime createdAt; - public JobScrapResponseDTO(JobScrap jobScrap, JobBoard jobBoard) { this.scrapId = jobScrap.getJobScrapId(); this.jobBoardId = jobScrap.getJobBoard().getJobBoardId(); this.userId = jobScrap.getUser().getUserId(); - + //TODO: 스크랩 조회시 나올 응답값은 피그마 수정후 추가 } } \ No newline at end of file From fac2da484a056698c94777dc2e421785b6bd3d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 12:45:27 +0900 Subject: [PATCH 12/26] =?UTF-8?q?fix:=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 74 +++++++++++-------- .../request/CompanyUserLoginRequestDTO.java | 3 + .../auth/dto/request/UserLoginRequestDTO.java | 3 + .../domain/auth/service/AuthService.java | 6 +- .../global/exception/ErrorCode.java | 2 +- 5 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/controller/AuthController.java b/src/main/java/team9502/sinchulgwinong/domain/auth/controller/AuthController.java index 87b7f92..f53df8b 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/controller/AuthController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/controller/AuthController.java @@ -33,23 +33,29 @@ public class AuthController { private final AuthService authService; @PostMapping("/signup") - @Operation(summary = "구직자 회원 가입", description = "새로운 사용자를 등록합니다. 구직자 회원가입입니다.") + @Operation(summary = "구직자 회원 가입", description = "새로운 구직자 사용자를 시스템에 등록합니다. 이메일 인증이 선행되어야 합니다. 회원가입시 300포인트가 적립됩니다.") @ApiResponses({ @ApiResponse(responseCode = "201", description = "구직자 회원 가입 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"201\", \"message\": \"구직자 회원 가입 성공\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "유효성 검사 실패", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"유효성 검사 실패\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "이메일 인증 필요", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"이메일 인증 필요\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"구직자 회원 가입 성공\", \"data\": null }"))), + @ApiResponse(responseCode = "400", description = "요청 처리 중 오류 발생", + content = @Content(mediaType = "application/json", + examples = { + @ExampleObject(name = "EMAIL_VERIFICATION_NEEDED", summary = "이메일 인증 필요", + value = "{\"message\": \"이메일 인증이 필요합니다.\", \"data\": null }"), + @ExampleObject(name = "TERMS_AGREEMENT_NEEDED", summary = "약관 동의 필요", + value = "{\"message\": \"약관에 동의해야 합니다.\", \"data\": null }"), + @ExampleObject(name = "PASSWORD_REQUIRED", summary = "비밀번호 입력 필요", + value = "{\"message\": \"비밀번호를 입력해주세요.\", \"data\": null }"), + @ExampleObject(name = "PASSWORD_MISMATCH", summary = "비밀번호 불일치", + value = "{\"message\": \"비밀번호와 비밀번호 확인이 일치하지 않습니다.\", \"data\": null }") + })), @ApiResponse(responseCode = "409", description = "중복된 이메일", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"409\", \"message\": \"중복된 이메일\", \"data\": null }"))), - @ApiResponse(responseCode = "500", description = "서버 에러", + examples = @ExampleObject(value = "{\"message\": \"중복된 이메일입니다.\", \"data\": null }"))), + @ApiResponse(responseCode = "500", description = "내부 서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{\"message\": \"내부 서버 에러\", \"data\": null }"))) }) public ResponseEntity> signup( @RequestBody @Valid UserSignupRequestDTO requestDTO) { @@ -66,23 +72,29 @@ public ResponseEntity> signup( } @PostMapping("/cp-signup") - @Operation(summary = "기업 회원 가입", description = "새로운 기업 사용자를 등록합니다. 기업(회원) 회원가입입니다.") + @Operation(summary = "기업 회원 가입", description = "새로운 기업 사용자를 시스템에 등록합니다. 이메일 인증이 선행되어야 합니다. 회원가입시 300포인트가 적립됩니다.") @ApiResponses({ @ApiResponse(responseCode = "201", description = "기업 회원 가입 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"201\", \"message\": \"기업 회원 가입 성공\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "유효성 검사 실패", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"유효성 검사 실패\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "이메일 인증 필요", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"이메일 인증 필요\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"기업 회원 가입 성공\", \"data\": null }"))), + @ApiResponse(responseCode = "400", description = "요청 처리 중 오류 발생", + content = @Content(mediaType = "application/json", + examples = { + @ExampleObject(name = "EMAIL_VERIFICATION_NEEDED", summary = "이메일 인증 필요", + value = "{\"message\": \"이메일 인증이 필요합니다.\", \"data\": null }"), + @ExampleObject(name = "TERMS_AGREEMENT_NEEDED", summary = "약관 동의 필요", + value = "{\"message\": \"약관에 동의해야 합니다.\", \"data\": null }"), + @ExampleObject(name = "PASSWORD_REQUIRED", summary = "비밀번호 입력 필요", + value = "{\"message\": \"비밀번호를 입력해주세요.\", \"data\": null }"), + @ExampleObject(name = "PASSWORD_MISMATCH", summary = "비밀번호 불일치", + value = "{\"message\": \"비밀번호와 비밀번호 확인이 일치하지 않습니다.\", \"data\": null }") + })), @ApiResponse(responseCode = "409", description = "중복된 이메일", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"409\", \"message\": \"중복된 이메일\", \"data\": null }"))), - @ApiResponse(responseCode = "500", description = "서버 에러", + examples = @ExampleObject(value = "{\"message\": \"중복된 이메일입니다.\", \"data\": null }"))), + @ApiResponse(responseCode = "500", description = "내부 서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{\"message\": \"내부 서버 에러\", \"data\": null }"))) }) public ResponseEntity> signupCompany( @RequestBody @Valid CpUserSignupRequestDTO requestDTO) { @@ -98,17 +110,17 @@ public ResponseEntity> signupCompany( } @PostMapping("/login") - @Operation(summary = "구직자 로그인", description = "사용자가 이메일로 로그인합니다.") + @Operation(summary = "구직자(사용자) 로그인", description = "사용자가 이메일로 로그인합니다. 일반 로그인입니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "로그인 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"로그인 성공\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "로그인 실패", + examples = @ExampleObject(value = "{ \"message\": \"로그인 성공\", \"data\": {\"userId\": 1, \"username\": \"김은채\", \"nickname\": \"대구총잡이\", \"email\": \"faleles442@gawte.com\", \"phoneNumber\": null, \"loginType\": \"NORMAL\"} }"))), + @ApiResponse(responseCode = "404", description = "미존재 사용자", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"로그인 실패\", \"data\": null }"))), + examples = @ExampleObject(value = "{\"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> login( @RequestBody @Valid UserLoginRequestDTO requestDTO) { @@ -129,13 +141,13 @@ public ResponseEntity> login( @ApiResponses({ @ApiResponse(responseCode = "200", description = "로그인 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"로그인 성공\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "로그인 실패", + examples = @ExampleObject(value = "{ \"message\": \"로그인 성공\", \"data\": {\"cpUserId\": 1, \"cpUsername\": \"김고양이\", \"cpName\": \"고양이탕후루\", \"cpEmail\": \"rihic26977@exeneli.com\", \"cpPhoneNumber\": \"01012345678\", \"hiringStatus\": true, \"employeeCount\": 10} }"))), + @ApiResponse(responseCode = "404", description = "미존재 사용자", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"로그인 실패\", \"data\": null }"))), + examples = @ExampleObject(value = "{\"message\": \"기업(회원)을 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> cpLogin( @RequestBody @Valid CompanyUserLoginRequestDTO requestDTO) { diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CompanyUserLoginRequestDTO.java b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CompanyUserLoginRequestDTO.java index 994b204..30002d0 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CompanyUserLoginRequestDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/CompanyUserLoginRequestDTO.java @@ -1,5 +1,6 @@ package team9502.sinchulgwinong.domain.auth.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.AccessLevel; import lombok.Builder; @@ -10,9 +11,11 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CompanyUserLoginRequestDTO { + @Schema(description = "이메일", example = "example@email.com") @NotBlank(message = "필수 입력입니다.") private String cpEmail; + @Schema(description = "비밀번호", example = "Password1!") @NotBlank(message = "필수 입력입니다.") private String cpPassword; diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserLoginRequestDTO.java b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserLoginRequestDTO.java index 2d50845..bdbcc11 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserLoginRequestDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/dto/request/UserLoginRequestDTO.java @@ -1,5 +1,6 @@ package team9502.sinchulgwinong.domain.auth.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.AccessLevel; import lombok.Builder; @@ -10,9 +11,11 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class UserLoginRequestDTO { + @Schema(description = "이메일", example = "example@email.com") @NotBlank(message = "필수 입력입니다.") private String email; + @Schema(description = "비밀번호", example = "Password1!") @NotBlank(message = "필수 입력입니다.") private String password; diff --git a/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java b/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java index 26140cd..d51e24b 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/auth/service/AuthService.java @@ -147,7 +147,7 @@ public CompanyUserLoginResponseDTO cpLogin(CompanyUserLoginRequestDTO loginReque Optional companyUserOptional = companyUserRepository.findByCpEmail(loginRequest.getCpEmail()); if (companyUserOptional.isEmpty()) { - throw new ApiException(ErrorCode.USER_NOT_FOUND); + throw new ApiException(ErrorCode.COMPANY_USER_NOT_FOUND); } CompanyUser companyUser = companyUserOptional.get(); @@ -181,7 +181,7 @@ private void validateUserSignupRequest(String email, String password, String con } if (!password.equals(confirmPassword)) { - throw new ApiException(ErrorCode.PASSWORD_MISMATCH); + throw new ApiException(ErrorCode.PASSWORD_CONFIRM_MISMATCH); } } @@ -195,7 +195,7 @@ private void validateCpSignupRequest(String cpEmail, String cpPassword, String c } if (!cpPassword.equals(cpConfirmPassword)) { - throw new ApiException(ErrorCode.PASSWORD_MISMATCH); + throw new ApiException(ErrorCode.PASSWORD_CONFIRM_MISMATCH); } } } diff --git a/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java b/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java index de63397..20d5cb8 100644 --- a/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java +++ b/src/main/java/team9502/sinchulgwinong/global/exception/ErrorCode.java @@ -19,7 +19,7 @@ public enum ErrorCode { LOGIN_FAILURE(HttpStatus.UNAUTHORIZED, "로그인 실패"), USER_NOT_FOUND(HttpStatus.NOT_FOUND, "사용자를 찾을 수 없습니다."), COMPANY_USER_NOT_FOUND(HttpStatus.NOT_FOUND, "기업(회원)을 찾을 수 없습니다."), - EMAIL_DUPLICATION(HttpStatus.BAD_REQUEST, "중복된 이메일입니다."), + EMAIL_DUPLICATION(HttpStatus.CONFLICT, "중복된 이메일입니다."), PASSWORD_MISMATCH(HttpStatus.BAD_REQUEST, "입력한 비밀번호가 기존 비밀번호와 일치하지 않습니다."), TERMS_NOT_ACCEPTED(HttpStatus.BAD_REQUEST, "약관에 동의해야 합니다."), INVALID_LOGIN_TYPE(HttpStatus.BAD_REQUEST, "잘못된 로그인 유형입니다."), From 75653dec9b64217bed7beaf63e007c2266b0f253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 13:12:12 +0900 Subject: [PATCH 13/26] =?UTF-8?q?fix:=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CpUserController.java | 57 ++++++++++--------- .../CpUserPasswordUpdateRequestDTO.java | 6 +- .../global/response/SuccessCode.java | 1 + 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java b/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java index 352b9e6..cf1e5c7 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/companyUser/controller/CpUserController.java @@ -28,20 +28,17 @@ public class CpUserController { private final CpUserService cpUserService; @GetMapping("/{cpUserId}/profile") - @Operation(summary = "기업(회원) 프로필 조회", description = "기업(회원)의 정보를 조회합니다.") + @Operation(summary = "기업(회원) 프로필 조회", description = "기업(회원)의 정보를 조회합니다. 로그인을 하지 않아도 확인할 수 있습니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "기업(회원) 프로필 조회 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"프로필 조회 성공\", \"data\": {\"cpUserId\": 1, \"cpName\": \"팀9502\", \"cpEmail\": \"example@email.com\", \"cpPhoneNumber\": \"01012345678\", \"cpUsername\": \"김은채\", \"hiringStatus\": true, \"employeeCount\": 50, \"foundationDate\": \"2021-01-01\", \"description\": \"기업 소개 예시입니다.\", \"cpNum\": \"1234567890\", \"averageRating\": 4.5, \"reviewCount\": 20} }"))), - @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"잘못된 요청 데이터입니다.\" }"))), + examples = @ExampleObject(value = "{ \"message\": \"기업(회원) 프로필 조회 성공\", \"data\": {\"cpUserId\": 1, \"cpName\": \"고양이탕후루\", \"cpEmail\": \"rihic26977@exeneli.com\", \"cpPhoneNumber\": \"01012345678\", \"cpUsername\": \"김고양이\", \"hiringStatus\": true, \"employeeCount\": 10, \"foundationDate\": \"1999-10-06\", \"description\": \"고양이는 세상을 움직이는 혁신입니다.\", \"cpNum\": \"1234567890\", \"averageRating\": null, \"reviewCount\": null} }"))), @ApiResponse(responseCode = "404", description = "기업(회원)을 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"기업(회원)을 찾을 수 없습니다.\" }"))), + examples = @ExampleObject(value = "{\"message\": \"기업(회원)을 찾을 수 없습니다.\" }"))), @ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 오류가 발생했습니다.\" }"))) + examples = @ExampleObject(value = "{\"message\": \"서버 오류가 발생했습니다.\" }"))) }) public ResponseEntity> getCompanyUserProfile( @PathVariable("cpUserId") Long cpUserId) { @@ -58,20 +55,27 @@ public ResponseEntity> getCompanyUse } @PatchMapping("/profile") - @Operation(summary = "기업(회원) 프로필 수정", description = "로그인한 기업(회원)이 본인의 프로필 정보를 수정합니다.") + @Operation(summary = "기업(회원) 프로필 수정", description = "로그인한 기업(회원)이 본인의 프로필 정보를 수정합니다. 원하는 정보만 수정 가능합니다. 이메일 수정 시 인증이 필요합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "프로필 수정 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"프로필 수정 성공\", \"data\": {\"cpUserId\": 1, \"cpName\": \"팀9502\", \"cpEmail\": \"fix@email.com\", \"cpPhoneNumber\": \"01012345678\", \"cpUsername\": \"김은채\", \"hiringStatus\": true, \"employeeCount\": 100, \"description\": \"수정된 기업 소개입니다.\", \"cpNum\": \"1234567890\"} }"))), - @ApiResponse(responseCode = "400", description = "이메일 인증 필요", + examples = @ExampleObject(value = "{ \"message\": \"기업(회원) 프로필 수정 성공\", \"data\": {\"cpUserId\": 1, \"cpName\": \"고양이탕후루\", \"cpEmail\": \"rihic26977@exeneli.com\", \"cpPhoneNumber\": \"01099998888\", \"cpUsername\": \"김고양이\", \"hiringStatus\": true, \"employeeCount\": 10, \"foundationDate\": \"1999-10-06\", \"description\": \"고양이는 세상을 움직이는 혁신입니다.\", \"cpNum\": \"1234567890\", \"averageRating\": null, \"reviewCount\": null} }"))), + @ApiResponse(responseCode = "400", description = "요청 처리 중 오류 발생", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"이메일 인증이 필요합니다.\" }"))), + examples = { + @ExampleObject(name = "EMAIL_VERIFICATION_NEEDED", summary = "이메일 인증 필요", + value = "{\"message\": \"이메일 인증이 필요합니다.\", \"data\": null }"), + @ExampleObject(name = "INVALID_INPUT", summary = "요청값 누락", + value = "{\"message\": \"잘못된 입력입니다.\", \"data\": null }"), + @ExampleObject(name = "잘못된 사용자 유형", + value = "{\"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }") + })), @ApiResponse(responseCode = "404", description = "기업(회원)을 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"기업(회원)을 찾을 수 없습니다.\" }"))), + examples = @ExampleObject(value = "{\"message\": \"기업(회원)을 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{\"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> updateCompanyUserProfile( @AuthenticationPrincipal UserDetailsImpl userDetails, @@ -89,26 +93,27 @@ public ResponseEntity> updateCompany } @PatchMapping("/password") - @Operation(summary = "비밀번호 변경", description = "로그인한 기업(회원)의 비밀번호를 안전하게 변경합니다.") + @Operation(summary = "비밀번호 변경", description = "로그인한 기업(회원)의 비밀번호를 변경합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "비밀번호 변경 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"비밀번호 변경 성공\" }"))), - @ApiResponse(responseCode = "400", description = "비밀번호 불일치 또는 유효하지 않은 요청", + examples = @ExampleObject(value = "{\"message\": \"기업(회원) 비밀번호 수정 성공\", \"data\": null }"))), + @ApiResponse(responseCode = "400", description = "요청 처리 중 오류 발생", content = @Content(mediaType = "application/json", examples = { - @ExampleObject(name = "비밀번호 불일치", value = "{ \"code\": \"400\", \"message\": \"입력한 비밀번호가 기존 비밀번호와 일치하지 않습니다.\" }"), - @ExampleObject(name = "비밀번호 확인 불일치", value = "{ \"code\": \"400\", \"message\": \"비밀번호와 비밀번호 확인이 일치하지 않습니다.\" }") + @ExampleObject(name = "비밀번호 불일치", + value = "{\"message\": \"입력한 비밀번호가 기존 비밀번호와 일치하지 않습니다.\", \"data\": null }"), + @ExampleObject(name = "비밀번호 확인 불일치", + value = "{\"message\": \"비밀번호와 비밀번호 확인이 일치하지 않습니다.\", \"data\": null }"), + @ExampleObject(name = "잘못된 사용자 유형", + value = "{\"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }") })), - @ApiResponse(responseCode = "400", description = "잘못된 사용자 유형", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), - @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없음", + @ApiResponse(responseCode = "404", description = "기업(회원)을 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"사용자를 찾을 수 없습니다.\" }"))), + examples = @ExampleObject(value = "{\"message\": \"기업(회원)을 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 오류가 발생했습니다.\" }"))) + examples = @ExampleObject(value = "{\"message\": \"서버 오류가 발생했습니다.\", \"data\": null }"))) }) public ResponseEntity> updateUserProfile( @AuthenticationPrincipal UserDetailsImpl userDetails, @@ -116,10 +121,10 @@ public ResponseEntity> updateUserProfile( cpUserService.updateCpUserPassword(userDetails.getCpUserId(), requestDTO); - return ResponseEntity.status(SUCCESS_USER_PASSWORD_UPDATED.getHttpStatus()) + return ResponseEntity.status(SUCCESS_CP_USER_PASSWORD_UPDATED.getHttpStatus()) .body( GlobalApiResponse.of( - SUCCESS_USER_PASSWORD_UPDATED.getMessage(), + SUCCESS_CP_USER_PASSWORD_UPDATED.getMessage(), null)); } } diff --git a/src/main/java/team9502/sinchulgwinong/domain/companyUser/dto/request/CpUserPasswordUpdateRequestDTO.java b/src/main/java/team9502/sinchulgwinong/domain/companyUser/dto/request/CpUserPasswordUpdateRequestDTO.java index 0eb45c5..91d7bae 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/companyUser/dto/request/CpUserPasswordUpdateRequestDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/companyUser/dto/request/CpUserPasswordUpdateRequestDTO.java @@ -10,12 +10,12 @@ @AllArgsConstructor public class CpUserPasswordUpdateRequestDTO { - @Schema(description = "현재 비밀번호", example = "password") + @Schema(description = "현재 비밀번호", example = "Password1!") private String currentPassword; - @Schema(description = "변경할 비밀번호", example = "newPassword") + @Schema(description = "변경할 비밀번호", example = "newPassword1!") private String newPassword; - @Schema(description = "변경할 비밀번호 확인", example = "newPassword") + @Schema(description = "변경할 비밀번호 확인", example = "newPassword1!") private String newPasswordConfirm; } diff --git a/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java b/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java index a3bf80b..faa9394 100644 --- a/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java +++ b/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java @@ -29,6 +29,7 @@ public enum SuccessCode { // CompanyUser SUCCESS_CP_USER_PROFILE_READ(HttpStatus.OK, "기업(회원) 프로필 조회 성공"), SUCCESS_CP_USER_PROFILE_UPDATED(HttpStatus.OK, "기업(회원) 프로필 수정 성공"), + SUCCESS_CP_USER_PASSWORD_UPDATED(HttpStatus.OK, "기업(회원) 비밀번호 수정 성공"), //Board SUCCESS_CREATE_BOARD(HttpStatus.CREATED, "게시글 생성 성공"), From 66706cbbc3303e96c90888af13f70cf5a56a4530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 14:18:26 +0900 Subject: [PATCH 14/26] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=9D=91=EB=8B=B5=EA=B0=92=EC=97=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/controller/UserController.java | 8 ++++---- .../domain/user/dto/response/UserProfileResponseDTO.java | 6 +++++- .../sinchulgwinong/domain/user/service/UserService.java | 6 ++++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java b/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java index 540d31c..0cbfb6e 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java @@ -32,16 +32,16 @@ public class UserController { @ApiResponses({ @ApiResponse(responseCode = "200", description = "구인자 프로필 조회 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"구인자 프로필 조회 성공\", \"data\": {\"userId\": 1, \"username\": \"김은채\", \"nickname\": \"정신체리라\", \"email\": \"email@example.com\", \"phoneNumber\": \"010-1234-5678\"} }"))), + examples = @ExampleObject(value = "{ \"message\": \"구직자 프로필 조회 성공\", \"data\": {\"userId\": 1, \"username\": \"김은채\", \"nickname\": \"정신체리라\", \"email\": \"email@example.com\", \"phoneNumber\": \"010-1234-5678\"} }"))), @ApiResponse(responseCode = "400", description = "잘못된 사용자 유형", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> getUserProfile( @AuthenticationPrincipal UserDetailsImpl userDetails) { diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/dto/response/UserProfileResponseDTO.java b/src/main/java/team9502/sinchulgwinong/domain/user/dto/response/UserProfileResponseDTO.java index 1bc1419..8a89605 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/user/dto/response/UserProfileResponseDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/user/dto/response/UserProfileResponseDTO.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import team9502.sinchulgwinong.domain.oauth.enums.SocialType; @Getter @NoArgsConstructor @@ -22,6 +23,9 @@ public class UserProfileResponseDTO { @Schema(description = "사용자 이메일", example = "example@email.com") private String email; - @Schema(description = "사용자 전화번호", example = "010-1234-5678") + @Schema(description = "사용자 전화번호", example = "01012345678") private String phoneNumber; + + @Schema(description = "로그인 타입", example = "KAKAO") + private SocialType loginType; } diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java b/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java index 4fe0df8..4ac9834 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java @@ -33,7 +33,8 @@ public UserProfileResponseDTO getUserProfile(Long userId) { user.getUsername(), user.getNickname(), user.getEmail(), - user.getPhoneNumber()); + user.getPhoneNumber(), + user.getLoginType()); } @Transactional @@ -65,7 +66,8 @@ public UserProfileResponseDTO updateUserProfile(Long userId, UserProfileUpdateRe user.getUsername(), user.getNickname(), user.getEmail(), - user.getPhoneNumber()); + user.getPhoneNumber(), + user.getLoginType()); } @Transactional From 36c59fd3f9ec363406783537f889032644e09a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 14:32:50 +0900 Subject: [PATCH 15/26] =?UTF-8?q?fix:=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 54 ++++++++++--------- .../domain/user/service/UserService.java | 4 ++ 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java b/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java index 0cbfb6e..dae7139 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/user/controller/UserController.java @@ -28,14 +28,14 @@ public class UserController { private final UserService userService; @GetMapping("/profile") - @Operation(summary = "구인자 프로필 조회", description = "로그인한 사용자의 프로필 정보를 조회합니다.") + @Operation(summary = "구직자 프로필 조회", description = "로그인한 사용자의 프로필 정보를 조회합니다.") @ApiResponses({ - @ApiResponse(responseCode = "200", description = "구인자 프로필 조회 성공", + @ApiResponse(responseCode = "200", description = "구직자 프로필 조회 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"message\": \"구직자 프로필 조회 성공\", \"data\": {\"userId\": 1, \"username\": \"김은채\", \"nickname\": \"정신체리라\", \"email\": \"email@example.com\", \"phoneNumber\": \"010-1234-5678\"} }"))), + examples = @ExampleObject(value = "{ \"message\": \"구직자 프로필 조회 성공\", \"data\": {\"userId\": 1, \"username\": \"김은채\", \"nickname\": \"대구총잡이\", \"email\": \"faleles442@gawte.com\", \"phoneNumber\": null, \"loginType\": \"NORMAL\"} }"))), @ApiResponse(responseCode = "400", description = "잘못된 사용자 유형", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{\"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없음", content = @Content(mediaType = "application/json", examples = @ExampleObject(value = "{ \"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), @@ -58,26 +58,27 @@ public ResponseEntity> getUserProfile( } @PatchMapping("/profile") - @Operation(summary = "사용자 프로필 수정", description = "로그인한 사용자의 프로필 정보를 수정합니다. 전체를 수정할 필요 없이, 원하는 부분만 수정 가능합니다.") + @Operation(summary = "사용자 프로필 수정", description = "로그인한 사용자의 프로필 정보를 수정합니다. 전체를 수정할 필요 없이 원하는 정보만 수정 가능합니다. 이메일 수정 시 인증이 필요합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "프로필 수정 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"프로필 수정 성공\", \"data\": {\"userId\": 1, \"username\": \"김수정\", \"nickname\": \"수정이의 별명\", \"email\": \"fix@email.com\", \"phoneNumber\": \"010-5678-1234\"} }"))), - @ApiResponse(responseCode = "400", description = "유효하지 않은 요청 데이터", + examples = @ExampleObject(value = "{\"message\": \"구직자 프로필 수정 성공\", \"data\": {\"userId\": 1, \"username\": \"수정\", \"nickname\": \"대구총잡이\", \"email\": \"faleles442@gawte.com\", \"phoneNumber\": null, \"loginType\": \"NORMAL\"} }"))), + @ApiResponse(responseCode = "400", description = "요청 처리 중 오류 발생", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"요청 데이터가 유효하지 않습니다.\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "이메일 인증 필요", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"이메일 인증이 필요합니다.\", \"data\": null }"))), - @ApiResponse(responseCode = "400", description = "잘못된 사용자 유형", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), + examples = { + @ExampleObject(name = "EMAIL_VERIFICATION_NEEDED", summary = "이메일 인증 필요", + value = "{\"message\": \"이메일 인증이 필요합니다.\", \"data\": null }"), + @ExampleObject(name = "INVALID_INPUT", summary = "요청값 누락", + value = "{\"message\": \"잘못된 입력입니다.\", \"data\": null }"), + @ExampleObject(name = "잘못된 사용자 유형", + value = "{\"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }") + })), @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{\"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{\"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> updateUserProfile( @AuthenticationPrincipal UserDetailsImpl userDetails, @@ -93,26 +94,27 @@ public ResponseEntity> updateUserProfi } @PatchMapping("/password") - @Operation(summary = "비밀번호 변경", description = "로그인한 사용자의 비밀번호를 안전하게 변경합니다.") + @Operation(summary = "비밀번호 변경", description = "로그인한 사용자의 비밀번호를 변경합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "비밀번호 변경 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"비밀번호 변경 성공\" }"))), - @ApiResponse(responseCode = "400", description = "비밀번호 불일치 또는 유효하지 않은 요청", + examples = @ExampleObject(value = "{\"message\": \"구직자 비밀번호 수정 성공\", \"data\": null }"))), + @ApiResponse(responseCode = "400", description = "요청 처리 중 오류 발생", content = @Content(mediaType = "application/json", examples = { - @ExampleObject(name = "비밀번호 불일치", value = "{ \"code\": \"400\", \"message\": \"입력한 비밀번호가 기존 비밀번호와 일치하지 않습니다.\" }"), - @ExampleObject(name = "비밀번호 확인 불일치", value = "{ \"code\": \"400\", \"message\": \"비밀번호와 비밀번호 확인이 일치하지 않습니다.\" }") + @ExampleObject(name = "비밀번호 불일치", + value = "{\"message\": \"입력한 비밀번호가 기존 비밀번호와 일치하지 않습니다.\", \"data\": null }"), + @ExampleObject(name = "비밀번호 확인 불일치", + value = "{\"message\": \"비밀번호와 비밀번호 확인이 일치하지 않습니다.\", \"data\": null }"), + @ExampleObject(name = "잘못된 사용자 유형", + value = "{\"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }") })), - @ApiResponse(responseCode = "401", description = "권한 없음", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"401\", \"message\": \"로그인 타입이 EMAIL이 아닙니다.\" }"))), @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"사용자를 찾을 수 없습니다.\" }"))), + examples = @ExampleObject(value = "{\"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 오류가 발생했습니다.\" }"))) + examples = @ExampleObject(value = "{\"message\": \"서버 오류가 발생했습니다.\", \"data\": null }"))) }) public ResponseEntity> updateUserProfile( @AuthenticationPrincipal UserDetailsImpl userDetails, diff --git a/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java b/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java index 4ac9834..4c908b2 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/user/service/UserService.java @@ -43,6 +43,10 @@ public UserProfileResponseDTO updateUserProfile(Long userId, UserProfileUpdateRe User user = userRepository.findById(userId) .orElseThrow(() -> new ApiException(ErrorCode.USER_NOT_FOUND)); + if (requestDTO == null) { + throw new ApiException(ErrorCode.INVALID_INPUT); + } + if (requestDTO.getUsername() != null) { user.setUsername(requestDTO.getUsername()); } From c7c449c5d13eac0567c3ee60368bca1b17863416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 14:52:55 +0900 Subject: [PATCH 16/26] =?UTF-8?q?fix:=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../point/controller/PointController.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/point/controller/PointController.java b/src/main/java/team9502/sinchulgwinong/domain/point/controller/PointController.java index 59f7936..06a2f17 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/point/controller/PointController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/point/controller/PointController.java @@ -38,13 +38,13 @@ public class PointController { @ApiResponses({ @ApiResponse(responseCode = "200", description = "포인트 총액 조회 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"포인트 조회 성공\", \"data\": {\"totalSaved\": 500, \"totalUsed\": 300} }"))), - @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없음", + examples = @ExampleObject(value = "{ \"message\": \"포인트 총액 조회 성공\", \"data\": {\"totalSaved\": 400, \"totalUsed\": 0} }"))), + @ApiResponse(responseCode = "404", description = "포인트 미존재", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"포인트를 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> getPointSummary( @AuthenticationPrincipal UserDetailsImpl userDetails) { @@ -65,13 +65,10 @@ public ResponseEntity> getPointSummar @ApiResponses({ @ApiResponse(responseCode = "200", description = "포인트 적립 내역 조회 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"적립 포인트 조회 성공\", \"data\": [{\"type\": \"REVIEW\", \"savedPoint\": 300, \"createdAt\": \"2024-06-11\"}, {\"type\": \"SIGNUP\", \"savedPoint\": 300, \"createdAt\": \"2024-06-11\", \"hasNextPage\": false}] }"))), - @ApiResponse(responseCode = "404", description = "포인트를 찾을 수 없습니다.", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"포인트를 찾을 수 없습니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"적립 포인트 조회 성공\", \"data\": { \"data\": [{\"type\": \"BOARD\", \"savedPoint\": 100, \"createdAt\": \"2024-06-19\"}, {\"type\": \"SIGNUP\", \"savedPoint\": 300, \"createdAt\": \"2024-06-18\"}], \"hasNextPage\": false} }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) @Parameter( name = "cursorId", @@ -108,7 +105,7 @@ public ResponseEntity Date: Wed, 19 Jun 2024 15:35:21 +0900 Subject: [PATCH 17/26] =?UTF-8?q?fix:=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/controller/ReviewController.java | 83 ++++++++++++++----- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java b/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java index 8e29f50..fdca2f7 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java @@ -1,8 +1,10 @@ package team9502.sinchulgwinong.domain.review.controller; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; @@ -30,17 +32,25 @@ public class ReviewController { private final ReviewService reviewService; @PostMapping("/reviews") - @Operation(summary = "리뷰 작성", description = "사용자가 리뷰를 작성합니다.") + @Operation(summary = "리뷰 작성", description = "사용자가 리뷰를 작성합니다. 이미 리뷰를 작성한 기업에 대해선 리뷰를 추가로 작성할 수 없습니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "리뷰 작성 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"리뷰 작성 성공\", \"data\": {\"reviewId\": 1, \"reviewTitle\": \"친절한 사장님!\", \"reviewContent\": \"사장님이 맛있고 사과가 친절해요.\", \"rating\": 5}}"))), + examples = @ExampleObject(value = "{ \"message\": \"리뷰 작성 성공\", \"data\": {\"reviewId\": 1, \"cpUserId\": 1, \"reviewTitle\": \"친절한 사장님!\", \"reviewContent\": \"돍망갉셇욦\", \"rating\": 3}}"))), @ApiResponse(responseCode = "400", description = "리뷰 작성 실패", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"400\", \"message\": \"리뷰 작성 실패\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"이미 리뷰를 작성하셨습니다.\", \"data\": null }"))), + @ApiResponse(responseCode = "404", description = "사용자 또는 기업(회원)을 찾을 수 없음", + content = @Content(mediaType = "application/json", + examples = { + @ExampleObject(name = "USER_NOT_FOUND", summary = "미존재 사용자", + value = "{\"message\": \"사용자를 찾을 수 없습니다.\", \"data\": null }"), + @ExampleObject(name = "COMPANY_USER_NOT_FOUND", summary = "미존재 기업(회원)", + value = "{\"message\": \"기업(회원)을 찾을 수 없습니다.\", \"data\": null }") + })), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> createReview( @AuthenticationPrincipal UserDetailsImpl userDetails, @@ -63,13 +73,13 @@ public ResponseEntity> createReview @ApiResponses({ @ApiResponse(responseCode = "200", description = "기업 리뷰 전체 조회 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"조회 성공\", \"data\": {\"reviews\": [{\"reviewId\": 1, \"reviewTitle\": \"친절한 사장님!\", \"reviewContent\": \"사장님이 맛있고 사과가 친절해요.\", \"rating\": 5}, {\"reviewId\": 2, \"reviewTitle\": \"좋은 품질\", \"reviewContent\": \"상품의 품질이 아주 좋습니다.\", \"rating\": 4}], \"totalReviewCount\": 2 }}"))), - @ApiResponse(responseCode = "404", description = "기업 사용자를 찾을 수 없음", + examples = @ExampleObject(value = "{ \"message\": \"기업 리뷰 전체 조회 성공\", \"data\": {\"reviews\": [{\"reviewId\": 1, \"reviewTitle\": \"친절한 사장님!\", \"reviewContent\": \"돍망갉셇욦\", \"rating\": 3}], \"totalReviewCount\": 1 }}"))), + @ApiResponse(responseCode = "400", description = "잘못된 사용자 유형", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"기업 사용자를 찾을 수 없습니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"잘못된 사용자 유형입니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> getAllReviewsForCompanyUser( @AuthenticationPrincipal UserDetailsImpl userDetails) { @@ -88,17 +98,39 @@ public ResponseEntity> getAllReviewsFor } @GetMapping("/cpUsers/{cpUserId}/reviews") - @Operation(summary = "기업 회원 리뷰 목록 조회", description = "사용자가 기업 회원의 리뷰 목록을 조회합니다.") + @Operation( + summary = "기업 회원 리뷰 목록 조회", + description = "사용자가 기업 회원의 리뷰 목록을 조회합니다. 각 리뷰의 가시성 상태도(공개/비공개) 함께 반환합니다.", + parameters = { + @Parameter( + name = "cpUserId", + description = "기업 회원의 고유 ID, 해당 기업에 대한 리뷰를 조회합니다.", + required = true, + schema = @Schema(type = "long") + ) + } + ) @ApiResponses({ - @ApiResponse(responseCode = "200", description = "기업 리뷰 전체 조회 성공", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"리뷰 목록 조회 성공\", \"data\": {\"reviews\": [{\"reviewId\": 1, \"reviewTitle\": \"친절한 사장님!\", \"reviewContent\": \"사장님이 맛있고 사과가 친절해요.\", \"rating\": 5}, {\"reviewId\": 2, \"reviewTitle\": \"좋은 품질\", \"reviewContent\": \"상품의 품질이 아주 좋습니다.\", \"rating\": 4}], \"totalReviewCount\": 2 }}"))), - @ApiResponse(responseCode = "404", description = "리뷰를 찾을 수 없음", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"리뷰를 찾을 수 없습니다.\", \"data\": null }"))), - @ApiResponse(responseCode = "500", description = "서버 에러", - content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + @ApiResponse( + responseCode = "200", + description = "기업 리뷰 전체 조회 성공", + content = @Content( + mediaType = "application/json", + examples = @ExampleObject( + value = "{ \"message\": \"리뷰 목록 조회 성공\", \"data\": {\"reviews\": [{\"reviewId\": 1, \"reviewTitle\": \"친절한 사장님!\", \"reviewContent\": \"사장님이 맛있고 사과가 친절해요.\", \"rating\": 5, \"visibility\": \"PRIVATE\"}, {\"reviewId\": 2, \"reviewTitle\": \"좋은 품질\", \"reviewContent\": \"상품의 품질이 아주 좋습니다.\", \"rating\": 4, \"visibility\": \"PUBLIC\"}], \"totalReviewCount\": 2 }}" + ) + ) + ), + @ApiResponse( + responseCode = "500", + description = "서버 에러", + content = @Content( + mediaType = "application/json", + examples = @ExampleObject( + value = "{ \"message\": \"서버 에러\", \"data\": null }" + ) + ) + ) }) public ResponseEntity> getReviewsWithVisibility( @AuthenticationPrincipal UserDetailsImpl userDetails, @@ -119,17 +151,24 @@ public ResponseEntity> getReviewsWi } @PostMapping("/reviews/{reviewId}/view") - @Operation(summary = "리뷰 열람", description = "사용자가 포인트를 사용하여 리뷰를 열람합니다.") + @Operation(summary = "리뷰 열람", description = "사용자가 100포인트를 사용하여 리뷰를 열람합니다. 포인트가 충분하지 않거나 리뷰가 이미 공개된 경우 오류가 발생할 수 있습니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "포인트 사용하여 리뷰 조회 성공", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"200\", \"message\": \"리뷰 열람 성공\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"포인트 사용하여 리뷰 조회 성공\", \"data\": {\"reviewId\": 1, \"reviewTitle\": \"친절한 사장님!\", \"reviewContent\": \"돍망갉셇욦\", \"rating\": 3} }"))), + @ApiResponse(responseCode = "400", description = "포인트 부족 또는 리뷰 이미 공개", + content = @Content(mediaType = "application/json", + examples = { + @ExampleObject(name = "POINT_NOT_FOUND", value = "{ \"message\": \"포인트를 찾을 수 없습니다.\", \"data\": null }"), + @ExampleObject(name = "INSUFFICIENT_POINTS", value = "{ \"message\": \"포인트가 부족합니다.\", \"data\": null }"), + @ExampleObject(name = "REVIEW_ALREADY_PUBLIC", value = "{ \"message\": \"이미 공개된 리뷰입니다.\", \"data\": null }") + })), @ApiResponse(responseCode = "404", description = "리뷰를 찾을 수 없음", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"404\", \"message\": \"리뷰를 찾을 수 없습니다.\", \"data\": null }"))), + examples = @ExampleObject(value = "{ \"message\": \"리뷰를 찾을 수 없습니다.\", \"data\": null }"))), @ApiResponse(responseCode = "500", description = "서버 에러", content = @Content(mediaType = "application/json", - examples = @ExampleObject(value = "{ \"code\": \"500\", \"message\": \"서버 에러\", \"data\": null }"))) + examples = @ExampleObject(value = "{ \"message\": \"서버 에러\", \"data\": null }"))) }) public ResponseEntity> viewReview( @AuthenticationPrincipal UserDetailsImpl userDetails, From 69a0a469d38785435151439506f87df5084c902e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 15:38:18 +0900 Subject: [PATCH 18/26] =?UTF-8?q?fix:=20swagger=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/review/controller/ReviewController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java b/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java index fdca2f7..c737154 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/review/controller/ReviewController.java @@ -26,7 +26,7 @@ @RestController @RequiredArgsConstructor -@Tag(name = "Review", description = "리뷰 관련 API") +@Tag(name = "Review", description = "리뷰 관련 API [김은채]") public class ReviewController { private final ReviewService reviewService; From d339216ce0b090c3e8f732f6ffee5c9e838f34ac Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 15:56:04 +0900 Subject: [PATCH 19/26] =?UTF-8?q?fix:=20=EB=8C=93=EA=B8=80=20=EA=B8=B8?= =?UTF-8?q?=EC=9D=B4=20300=EC=9E=90=EB=A1=9C=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team9502/sinchulgwinong/domain/comment/entity/Comment.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/comment/entity/Comment.java b/src/main/java/team9502/sinchulgwinong/domain/comment/entity/Comment.java index 89894f1..87986d2 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/comment/entity/Comment.java +++ b/src/main/java/team9502/sinchulgwinong/domain/comment/entity/Comment.java @@ -7,8 +7,6 @@ import team9502.sinchulgwinong.domain.user.entity.User; import team9502.sinchulgwinong.global.entity.BaseTimeEntity; -import java.time.LocalDateTime; - @Entity @Getter public class Comment extends BaseTimeEntity { @@ -28,5 +26,6 @@ public class Comment extends BaseTimeEntity { private Board board; @Setter + @Column(length = 300) private String commentContent; } From 1a6b0e6419eca5f4d92cc0d329cd4d6ca80a80fa Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 15:56:43 +0900 Subject: [PATCH 20/26] =?UTF-8?q?fix:=20pathvariable=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EC=A7=80=EC=A0=95,=20=EB=82=B4=EA=B0=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=ED=95=9C=20=EB=8C=93=EA=B8=80=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/comment/controller/CommentController.java b/src/main/java/team9502/sinchulgwinong/domain/comment/controller/CommentController.java index 35a5f07..928d2c8 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/comment/controller/CommentController.java +++ b/src/main/java/team9502/sinchulgwinong/domain/comment/controller/CommentController.java @@ -1,5 +1,6 @@ package team9502.sinchulgwinong.domain.comment.controller; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -26,8 +27,8 @@ public class CommentController { @PostMapping("/boards/{boardId}") public ResponseEntity> commentCreate( - @PathVariable Long boardId, - @RequestBody CommentRequestDTO commentRequestDTO, + @PathVariable("boardId") Long boardId, + @RequestBody @Valid CommentRequestDTO commentRequestDTO, @AuthenticationPrincipal UserDetailsImpl userDetails) { User user = (User) userDetails.getUser(); @@ -45,7 +46,7 @@ public ResponseEntity> commentCreate( @GetMapping("/boards/{boardId}") public ResponseEntity>> getAllComment( - @PathVariable Long boardId) { + @PathVariable("boardId") Long boardId) { List commentResponseDTOS = commentService.getAllComment(boardId); @@ -60,10 +61,10 @@ public ResponseEntity>> getAllComment @PatchMapping("{commentId}/boards/{boardId}") public ResponseEntity> commentUpdate( - @PathVariable Long boardId, - @PathVariable Long commentId, + @PathVariable("boardId") Long boardId, + @PathVariable("commentId") Long commentId, @AuthenticationPrincipal UserDetailsImpl userDetails, - @RequestBody CommentRequestDTO commentRequestDTO) { + @RequestBody @Valid CommentRequestDTO commentRequestDTO) { User user = (User) userDetails.getUser(); @@ -80,8 +81,8 @@ public ResponseEntity> commentUpdate( @DeleteMapping("/{commentId}/boards/{boardId}") public ResponseEntity> deleteComment( - @PathVariable Long boardId, - @PathVariable Long commentId, + @PathVariable("boardId") Long boardId, + @PathVariable("commentId") Long commentId, @AuthenticationPrincipal UserDetailsImpl userDetails) { User user = (User) userDetails.getUser(); @@ -97,5 +98,22 @@ public ResponseEntity> deleteComment( ); } + @GetMapping("/my-comments") + public ResponseEntity>> getAllMyComment( + @AuthenticationPrincipal UserDetailsImpl userDetails) { + + User user = (User) userDetails.getUser(); + + List commentResponseDTOS = commentService.getAllMyComment(user); + + return ResponseEntity.status(SUCCESS_READ_ALL_MY_COMMENT.getHttpStatus()) + .body( + GlobalApiResponse.of( + SUCCESS_READ_ALL_MY_COMMENT.getMessage(), + commentResponseDTOS + ) + ); + } + } From 47ab20e5613e6f1eab662595c46c19cc3915a03b Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 15:57:22 +0900 Subject: [PATCH 21/26] =?UTF-8?q?fix:=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=9D=91=EB=8B=B5=EC=8B=9C=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=B4=9D=20=EA=B0=AF=EC=88=98=EB=8F=84=20=ED=8F=AC=ED=95=A8?= =?UTF-8?q?=ED=95=B4=EC=84=9C=20=EC=9D=91=EB=8B=B5=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/dto/response/CommentResponseDTO.java | 12 ++++++++++++ .../domain/comment/repository/CommentRepository.java | 7 ++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/comment/dto/response/CommentResponseDTO.java b/src/main/java/team9502/sinchulgwinong/domain/comment/dto/response/CommentResponseDTO.java index b686d88..a515947 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/comment/dto/response/CommentResponseDTO.java +++ b/src/main/java/team9502/sinchulgwinong/domain/comment/dto/response/CommentResponseDTO.java @@ -16,6 +16,8 @@ public class CommentResponseDTO { private String commentContent; + private Long totalComments; + private LocalDateTime createdAt; private LocalDateTime modifiedAt; @@ -28,4 +30,14 @@ public CommentResponseDTO(Comment comment) { this.createdAt = comment.getCreatedAt(); this.modifiedAt = comment.getModifiedAt(); } + + public CommentResponseDTO(Comment comment, Long totalComments) { + this.commentId = comment.getCommentId(); + this.userId = comment.getUser().getUserId(); + this.boardId = comment.getBoard().getBoardId(); + this.commentContent = comment.getCommentContent(); + this.createdAt = comment.getCreatedAt(); + this.modifiedAt = comment.getModifiedAt(); + this.totalComments = totalComments; + } } diff --git a/src/main/java/team9502/sinchulgwinong/domain/comment/repository/CommentRepository.java b/src/main/java/team9502/sinchulgwinong/domain/comment/repository/CommentRepository.java index e0f55f5..e8237aa 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/comment/repository/CommentRepository.java +++ b/src/main/java/team9502/sinchulgwinong/domain/comment/repository/CommentRepository.java @@ -1,7 +1,7 @@ package team9502.sinchulgwinong.domain.comment.repository; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; +import org.springframework.data.jpa.repository.Query; import team9502.sinchulgwinong.domain.comment.entity.Comment; import java.util.List; @@ -9,4 +9,9 @@ public interface CommentRepository extends JpaRepository { List findByBoard_BoardId(Long boardId); + + List findByUser_UserId(Long userId); + + @Query("SELECT COUNT(c) FROM Comment c WHERE c.board.boardId = :boardId") + Long countCommentsByBoardId(Long boardId); } From 3cb97b18a45caed56a79df1aab2775e1980ade2e Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 15:58:01 +0900 Subject: [PATCH 22/26] =?UTF-8?q?fix:=20=EB=82=B4=EA=B0=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=ED=95=9C=20=EB=8C=93=EA=B8=80=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20api=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/service/CommentService.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java b/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java index 0c9f98f..5795049 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java @@ -9,11 +9,12 @@ import team9502.sinchulgwinong.domain.comment.dto.response.CommentResponseDTO; import team9502.sinchulgwinong.domain.comment.entity.Comment; import team9502.sinchulgwinong.domain.comment.repository.CommentRepository; +import team9502.sinchulgwinong.domain.point.enums.SpType; +import team9502.sinchulgwinong.domain.point.service.PointService; import team9502.sinchulgwinong.domain.user.entity.User; import team9502.sinchulgwinong.global.exception.ApiException; import team9502.sinchulgwinong.global.exception.ErrorCode; -import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @@ -23,10 +24,13 @@ public class CommentService { private final CommentRepository commentRepository; private final BoardRepository boardRepository; + private final PointService pointService; @Transactional public CommentResponseDTO createComment(Long boardId, User user, CommentRequestDTO commentRequestDTO) { + validation(commentRequestDTO); + Board board = boardRepository.findById(boardId) .orElseThrow(() -> new ApiException(ErrorCode.BOARD_NOT_FOUND)); @@ -38,16 +42,18 @@ public CommentResponseDTO createComment(Long boardId, User user, CommentRequestD commentRepository.save(comment); + pointService.earnPoints(user, SpType.BOARD); //TODO: comment 타입이 없어서 임시로 board 넣어놓음 + return new CommentResponseDTO(comment); } @Transactional(readOnly = true) public List getAllComment(Long boardId) { - commentRepository.findByBoard_BoardId(boardId); + Long totalComments = commentRepository.countCommentsByBoardId(boardId); return commentRepository.findByBoard_BoardId(boardId).stream() - .map(CommentResponseDTO::new) + .map(comment -> new CommentResponseDTO(comment, totalComments)) .collect(Collectors.toList()); } @@ -55,6 +61,8 @@ public List getAllComment(Long boardId) { @Transactional public CommentResponseDTO updateComment(Long boardId, Long commentId, User user, CommentRequestDTO commentRequestDTO) { + validation(commentRequestDTO); + Comment comment = commentRepository.findById(commentId) .orElseThrow(() -> new ApiException(ErrorCode.COMMENT_NOT_FOUND)); @@ -90,4 +98,22 @@ public void deleteComment(Long boardId, Long commentId, User user) { commentRepository.delete(comment); } + @Transactional(readOnly = true) + public List getAllMyComment(User user) { + + return commentRepository.findByUser_UserId(user.getUserId()).stream() + .map(CommentResponseDTO::new) + .collect(Collectors.toList()); + } + + private void validation(CommentRequestDTO commentRequestDTO) { + + if (commentRequestDTO.getCommentContent().isEmpty()) { + throw new ApiException(ErrorCode.CONTENT_REQUIRED); + } + if (commentRequestDTO.getCommentContent().length() > 300) { + throw new ApiException(ErrorCode.CONTENT_TOO_LONG); + } + } + } From 4afd06a80cc9b004a96cbcf731cb62388bec5c30 Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 15:58:15 +0900 Subject: [PATCH 23/26] =?UTF-8?q?fix:=20=EB=82=B4=EA=B0=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=ED=95=9C=20=EB=8C=93=EA=B8=80=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20api=20=EC=84=B1=EA=B3=B5=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team9502/sinchulgwinong/global/response/SuccessCode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java b/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java index a3bf80b..9f39c59 100644 --- a/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java +++ b/src/main/java/team9502/sinchulgwinong/global/response/SuccessCode.java @@ -60,6 +60,7 @@ public enum SuccessCode { SUCCESS_READ_ALL_COMMENT(HttpStatus.OK, "댓글 전체 조회 성공"), SUCCESS_UPDATE_COMMENT(HttpStatus.OK, "댓글 업데이트 성공"), SUCCESS_DELETE_COMMENT(HttpStatus.OK, "댓글 삭제 성공"), + SUCCESS_READ_ALL_MY_COMMENT(HttpStatus.OK, "내가 작성한 댓글 전체 조회 성공"), //Scrap SUCCESS_CREATE_SCRAP(HttpStatus.CREATED, "스크랩 생성 성공"), From a08c70708db9275644a5efdc3177fff33d989d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 16:06:58 +0900 Subject: [PATCH 24/26] =?UTF-8?q?fix:=20workflow=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/sinChul.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/sinChul.yml b/.github/workflows/sinChul.yml index b16c961..8a74e1b 100644 --- a/.github/workflows/sinChul.yml +++ b/.github/workflows/sinChul.yml @@ -53,6 +53,9 @@ jobs: export SECRET_ACCESS_KEY="${{ secrets.SECRET_ACCESS_KEY }}" export GOOGLE_ACCOUNT="${{ secrets.GOOGLE_ACCOUNT }}" export GOOGLE_PASSWORD="${{ secrets.GOOGLE_PASSWORD }}" + export GOOGLE_CLIENT_ID="${{ secrets.GOOGLE_CLIENT_ID }}" + export GOOGLE_CLIENT_SECRET="${{ secrets.GOOGLE_CLIENT_SECRET }}" + export GOOGLE_REDIRECT_URI="${{ secrets.GOOGLE_REDIRECT_URI }}" # JAR 파일을 /home/ec2-user 디렉토리에서 실행 nohup java -jar /home/ec2-user/*.jar > nohup.out 2>&1 & @@ -69,3 +72,6 @@ jobs: SECRET_ACCESS_KEY: ${{ secrets.SECRET_ACCESS_KEY }} GOOGLE_ACCOUNT: ${{ secrets.GOOGLE_ACCOUNT }} GOOGLE_PASSWORD: ${{ secrets.GOOGLE_PASSWORD }} + GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }} + GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }} + GOOGLE_REDIRECT_URI: ${{ secrets.GOOGLE_REDIRECT_URI }} From f194a7d5d1dfcc0f2c14ebb71b16ffa08499cd81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 19 Jun 2024 16:11:47 +0900 Subject: [PATCH 25/26] =?UTF-8?q?feat:=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=81=EB=A6=BD=20=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team9502/sinchulgwinong/domain/point/enums/SpType.java | 3 ++- .../sinchulgwinong/domain/point/service/PointService.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/point/enums/SpType.java b/src/main/java/team9502/sinchulgwinong/domain/point/enums/SpType.java index 110f70c..d1a214a 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/point/enums/SpType.java +++ b/src/main/java/team9502/sinchulgwinong/domain/point/enums/SpType.java @@ -10,7 +10,8 @@ public enum SpType { CHAT: 채팅 FIRST_BOARD: 첫 게시글 작성 JOBS: 채용글 작성 + COMMENT: 댓글 작성 */ - REVIEW, SIGNUP, BOARD, EVENT, CHAT, FIRST_BOARD, JOBS + REVIEW, SIGNUP, BOARD, EVENT, CHAT, FIRST_BOARD, JOBS, COMMENT } diff --git a/src/main/java/team9502/sinchulgwinong/domain/point/service/PointService.java b/src/main/java/team9502/sinchulgwinong/domain/point/service/PointService.java index f2df7cd..40b048d 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/point/service/PointService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/point/service/PointService.java @@ -61,7 +61,7 @@ private int getPointsByType(SpType spType) { return switch (spType) { case REVIEW, SIGNUP, JOBS -> 300; case BOARD, CHAT, EVENT -> 100; - case FIRST_BOARD -> 50; + case FIRST_BOARD, COMMENT -> 50; }; } From 82d3feb552426f8c5136ae76e933e81390e9806e Mon Sep 17 00:00:00 2001 From: de123456sdf Date: Wed, 19 Jun 2024 16:20:39 +0900 Subject: [PATCH 26/26] =?UTF-8?q?fix:=20=EC=A0=81=EB=A6=BD=ED=83=80?= =?UTF-8?q?=EC=9E=85=20comment=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sinchulgwinong/domain/comment/service/CommentService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java b/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java index 5795049..a81eb75 100644 --- a/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java +++ b/src/main/java/team9502/sinchulgwinong/domain/comment/service/CommentService.java @@ -42,7 +42,7 @@ public CommentResponseDTO createComment(Long boardId, User user, CommentRequestD commentRepository.save(comment); - pointService.earnPoints(user, SpType.BOARD); //TODO: comment 타입이 없어서 임시로 board 넣어놓음 + pointService.earnPoints(user, SpType.COMMENT); return new CommentResponseDTO(comment); }