diff --git a/.idea/vcs.xml b/.idea/vcs.xml index fda1536..94a25f7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,7 +2,5 @@ - - \ No newline at end of file diff --git a/ideac-admin/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java b/ideac-admin/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java index 421863a..b8d7ace 100644 --- a/ideac-admin/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java +++ b/ideac-admin/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java @@ -3,12 +3,10 @@ import depth.main.ideac.domain.admin.application.AdminService; import depth.main.ideac.domain.auth.application.AuthService; -import depth.main.ideac.domain.auth.dto.AuthRes; -import depth.main.ideac.domain.auth.dto.FindIdReq; -import depth.main.ideac.domain.auth.dto.SignInReq; -import depth.main.ideac.domain.auth.dto.SignUpReq; -import depth.main.ideac.domain.user.application.UserService; -import depth.main.ideac.domain.user.domain.User; +import depth.main.ideac.domain.auth.dto.response.AuthRes; +import depth.main.ideac.domain.auth.dto.request.FindIdReq; +import depth.main.ideac.domain.auth.dto.request.SignInReq; +import depth.main.ideac.domain.auth.dto.request.PasswordReq; import depth.main.ideac.global.payload.ErrorResponse; import depth.main.ideac.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -22,7 +20,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @Tag(name = "Auth API", description = "Authorization 관련 API입니다.") @@ -66,4 +63,15 @@ public ResponseEntity findId(@Parameter(description = "Schemas의 FindIdReque return authService.findId(findIdReq); } + @Operation(summary = "비밀번호 바꾸기", description = "비밀번호를 바꾼다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "비밀번호 바꾸기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "비밀번호 바꾸기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PostMapping(value = "/change-password/{code}") + public ResponseEntity changePassword(@Parameter(description = "Schemas의 PassWordReq를 참고해주세요.") + @Valid @RequestBody PasswordReq passwordReq, + @PathVariable String code) { + return authService.changePassword(passwordReq,code); + } } diff --git a/ideac-admin/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java b/ideac-admin/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java index 62d2db9..940fd83 100644 --- a/ideac-admin/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java +++ b/ideac-admin/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java @@ -1,7 +1,6 @@ package depth.main.ideac.domain.user.presentation; import depth.main.ideac.domain.user.application.UserService; -import depth.main.ideac.domain.user.dto.PasswordReq; import depth.main.ideac.global.config.security.token.CurrentUser; import depth.main.ideac.global.config.security.token.UserPrincipal; import depth.main.ideac.global.payload.ErrorResponse; @@ -12,7 +11,6 @@ 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 jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -23,17 +21,6 @@ public class UserController { private final UserService userService; - @Operation(summary = "메일 보내기", description = "비밀번호를 찾기위해 메일을 보낸다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "비밀번호 바꾸기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), - @ApiResponse(responseCode = "400", description = "비밀번호 바꾸기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) - }) - @PostMapping(value = "/change-password/{code}") - public ResponseEntity changePassword(@Parameter(description = "Schemas의 PassWordReq를 참고해주세요.") - @Valid @RequestBody PasswordReq passwordReq, - @PathVariable String code) { - return userService.changePassword(passwordReq,code); - } @Operation(summary = "로그아웃", description = "로그아웃 API입니다.") @ApiResponses(value = { diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/AuthService.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/AuthService.java index 6b0894d..cb3a418 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/AuthService.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/AuthService.java @@ -3,16 +3,26 @@ import depth.main.ideac.domain.auth.domain.Token; import depth.main.ideac.domain.auth.domain.repository.TokenRepository; import depth.main.ideac.domain.auth.dto.*; +import depth.main.ideac.domain.auth.dto.request.FindIdReq; +import depth.main.ideac.domain.auth.dto.request.RefreshTokenReq; +import depth.main.ideac.domain.auth.dto.request.SignInReq; +import depth.main.ideac.domain.auth.dto.request.SignUpReq; +import depth.main.ideac.domain.auth.dto.response.AuthRes; +import depth.main.ideac.domain.mail.domain.Verify; +import depth.main.ideac.domain.mail.domain.repository.MailRepository; import depth.main.ideac.domain.user.domain.Role; import depth.main.ideac.domain.user.domain.Status; import depth.main.ideac.domain.user.domain.User; import depth.main.ideac.domain.user.domain.repository.UserRepository; +import depth.main.ideac.domain.auth.dto.request.PasswordReq; import depth.main.ideac.global.DefaultAssert; import depth.main.ideac.global.error.DefaultException; import depth.main.ideac.global.payload.ApiResponse; import depth.main.ideac.global.payload.ErrorCode; import depth.main.ideac.global.payload.Message; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -20,12 +30,15 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.Optional; @RequiredArgsConstructor @Service +@Slf4j public class AuthService { private final AuthenticationManager authenticationManager; @@ -34,13 +47,12 @@ public class AuthService { private final UserRepository userRepository; private final TokenRepository tokenRepository; + private final MailRepository mailRepository; // 회원가입 하기 public ResponseEntity signUp(SignUpReq signUpRequest){ -// //검증 -// DefaultAssert.isTrue(!userRepository.existsByEmail(signUpRequest.getIdEmail()), "해당 이메일이 존재합니다."); -// DefaultAssert.isTrue(!userRepository.existsByNickname(signUpRequest.getNickname()), "이미 존재하는 닉네임입니다."); + DefaultAssert.isTrue(signUpRequest.getPassword().equals(signUpRequest.getCheckPassword()), "비밀번호가 서로 다릅니다."); User user = User.builder() .email(signUpRequest.getIdEmail()) @@ -70,7 +82,6 @@ public ResponseEntity signUp(SignUpReq signUpRequest){ //로그인 하기 public ResponseEntity signIn(SignInReq signInReq){ - Optional user = userRepository.findByEmail(signInReq.getEmail()); DefaultAssert.isTrue(user.isPresent(), "이메일이 틀렸습니다."); @@ -79,7 +90,6 @@ public ResponseEntity signIn(SignInReq signInReq){ throw new DefaultException(ErrorCode.INVALID_CHECK, "정지되었거나 탈퇴된 유저입니다."); } - boolean checkPassword = passwordEncoder.matches(signInReq.getPassword(), findUser.getPassword()); DefaultAssert.isTrue(checkPassword, "비밀번호가 틀렸습니다"); @@ -89,7 +99,6 @@ public ResponseEntity signIn(SignInReq signInReq){ signInReq.getPassword() ) ); - SecurityContextHolder.getContext().setAuthentication(authentication); TokenMapping tokenMapping = customTokenProviderService.createToken(authentication); @@ -103,20 +112,20 @@ public ResponseEntity signIn(SignInReq signInReq){ AuthRes authResponse = AuthRes.builder() .accessToken(tokenMapping.getAccessToken()) .refreshToken(token.getRefreshToken()).build(); - return ResponseEntity.ok(authResponse); } // 핸드폰번호로 아이디(이메일) 찾기 public ResponseEntity findId(FindIdReq findIdReq) { + System.out.println("findIdReq.getPhoneNumber() = " + findIdReq.getPhoneNumber()); Optional findUser = userRepository.findByPhoneNumber(findIdReq.getPhoneNumber()); DefaultAssert.isTrue(findUser.isPresent(), "해당이메일을 갖고 있는 유저가 없습니다."); - + User user = findUser.get(); + System.out.println("user.getEmail() = " + user.getEmail()); ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(user.getEmail()) - .message("가입하신 아이디를 찾아왔어요!") .build(); return ResponseEntity.ok(apiResponse); } @@ -164,21 +173,51 @@ private boolean valid(String refreshToken){ return true; } + // 닉네임 중복검증 public ResponseEntity doubleCheckNickname(String nickname) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(userRepository.findByNickname(nickname).isEmpty()) - .message("닉네임 검증 완료") .build(); return ResponseEntity.ok(apiResponse); } + // 이메일 중복검증 public ResponseEntity doubleCheckEmail(String email) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(userRepository.findByEmail(email).isEmpty()) - .message("이메일 검증 완료") .build(); return ResponseEntity.ok(apiResponse); } + + @Transactional + public ResponseEntity changePassword(@Valid PasswordReq passwordReq, String code){ + + //검증 + DefaultAssert.isTrue(passwordReq.getPassword().equals(passwordReq.getRePassword()), "비밀번호가 서로 다릅니다."); + //만료시간 검증 + Verify verify = mailRepository.findByCode(code); + + if (verify == null){ + throw new DefaultException(ErrorCode.INVALID_CHECK, "이미변경되었습니다."); + } + + DefaultAssert.isTrue(verify.checkExpiration(LocalDateTime.now()), "만료되었습니다."); + + Optional findUser = userRepository.findByEmail(verify.getEmail()); + + User user = findUser.get(); + user.updatePassWord(passwordEncoder.encode(passwordReq.getPassword())); + + // 인증완료 후 삭제 + mailRepository.delete(verify); + + ApiResponse apiResponse = ApiResponse.builder() + .check(true) + .information(null) + .build(); + + return ResponseEntity.ok(apiResponse); + } } diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/CustomDefaultOAuth2UserService.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/CustomDefaultOAuth2UserService.java index 9afcc59..295ea85 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/CustomDefaultOAuth2UserService.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/application/CustomDefaultOAuth2UserService.java @@ -43,19 +43,12 @@ private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2 Optional userOptional = userRepository.findByEmail(oAuth2UserInfo.getEmail()); User user; - if(userOptional.isPresent()) { - user = userOptional.get(); - DefaultAssert.isAuthentication(user.getProvider().equals(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()))); -// user = updateExistingUser(user, oAuth2UserInfo); - } else { - user = registerNewUser(oAuth2UserRequest, oAuth2UserInfo); - log.info("통과1"); - - } + user = registerNewUser(oAuth2UserRequest, oAuth2UserInfo); return UserPrincipal.create(user, oAuth2User.getAttributes()); } + // oauth2 회원 등록 private User registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) { User user = User.builder() .provider(Provider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId())) @@ -67,12 +60,4 @@ private User registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo .build(); return userRepository.save(user); } - -// private User updateExistingUser(User user, OAuth2UserInfo oAuth2UserInfo) { -//// 추후 사용시 바뀔예정인 함수 -//// user.updateName(oAuth2UserInfo.getName()); -//// user.updateImageUrl(oAuth2UserInfo.getImageUrl()); -// -// return userRepository.save(user); -// } } diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/FindIdReq.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/FindIdReq.java similarity index 91% rename from ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/FindIdReq.java rename to ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/FindIdReq.java index 8e4e91f..5d599b2 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/FindIdReq.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/FindIdReq.java @@ -1,4 +1,4 @@ -package depth.main.ideac.domain.auth.dto; +package depth.main.ideac.domain.auth.dto.request; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/user/dto/PasswordReq.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/PasswordReq.java similarity index 90% rename from ideac-core/src/main/java/depth/main/ideac/domain/user/dto/PasswordReq.java rename to ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/PasswordReq.java index f80e285..acd7366 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/user/dto/PasswordReq.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/PasswordReq.java @@ -1,4 +1,4 @@ -package depth.main.ideac.domain.user.dto; +package depth.main.ideac.domain.auth.dto.request; import jakarta.validation.constraints.Pattern; import lombok.Getter; diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/RefreshTokenReq.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/RefreshTokenReq.java similarity index 88% rename from ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/RefreshTokenReq.java rename to ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/RefreshTokenReq.java index 306b965..9f14b26 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/RefreshTokenReq.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/RefreshTokenReq.java @@ -1,12 +1,12 @@ -package depth.main.ideac.domain.auth.dto; +package depth.main.ideac.domain.auth.dto.request; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Builder; -import lombok.Data; +import lombok.Getter; -@Data +@Getter public class RefreshTokenReq { @Schema( type = "string", example = "eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2NTI3OTgxOTh9.6CoxHB_siOuz6PxsxHYQCgUT1_QbdyKTUwStQDutEd1-cIIARbQ0cyrnAmpIgi3IBoLRaqK7N1vXO42nYy4g5g", description="refresh token 입니다." ) diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/SignInReq.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/SignInReq.java similarity index 86% rename from ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/SignInReq.java rename to ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/SignInReq.java index a9da48f..4098563 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/SignInReq.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/SignInReq.java @@ -1,15 +1,13 @@ -package depth.main.ideac.domain.auth.dto; +package depth.main.ideac.domain.auth.dto.request; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; -import lombok.Data; import lombok.Getter; -@Data +@Getter public class SignInReq { @Schema( type = "string", example = "idea00@naver.com", description="계정 이메일 입니다.") diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/SignUpReq.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/SignUpReq.java similarity index 84% rename from ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/SignUpReq.java rename to ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/SignUpReq.java index ae6201f..fd3338e 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/SignUpReq.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/request/SignUpReq.java @@ -1,11 +1,10 @@ -package depth.main.ideac.domain.auth.dto; +package depth.main.ideac.domain.auth.dto.request; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Email; +import jakarta.persistence.Column; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; -import lombok.Data; import lombok.Getter; @Getter @@ -15,6 +14,7 @@ public class SignUpReq { private String idEmail; @Schema( type = "string", example = "홍길동", description="이름") + @Size(min = 2, message = "2자 이상 입력해주세요") @NotBlank private String name; @@ -35,6 +35,7 @@ public class SignUpReq { @Schema( type = "string", example = "01012341234", description="휴대폰번호") @NotBlank + @Pattern(regexp = "^01([0|1|6|7|8|9])?([0-9]{3,4})?([0-9]{4})$", message = "번호를 정확하게 입력해주세요") private String phoneNumber; @Schema( type = "string", example = "depth", description="소속 동아리") diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/AuthRes.java b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/response/AuthRes.java similarity index 91% rename from ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/AuthRes.java rename to ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/response/AuthRes.java index bf005d0..22a1403 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/AuthRes.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/auth/dto/response/AuthRes.java @@ -1,10 +1,10 @@ -package depth.main.ideac.domain.auth.dto; +package depth.main.ideac.domain.auth.dto.response; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; -import lombok.Data; +import lombok.Getter; -@Data +@Getter public class AuthRes { @Schema( type = "string", example = "eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2NTI3OTgxOTh9.6CoxHB_siOuz6PxsxHYQCgUT1_QbdyKTUwStQDutEd1-cIIARbQ0cyrnAmpIgi3IBoLRaqK7N1vXO42nYy4g5g" , description="access token 을 출력합니다.") diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/idea_post/IdeaPost.java b/ideac-core/src/main/java/depth/main/ideac/domain/idea_post/IdeaPost.java index 1d69f10..36559ec 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/idea_post/IdeaPost.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/idea_post/IdeaPost.java @@ -44,12 +44,4 @@ public class IdeaPost extends BaseEntity { private User user; private Long hits; - -// public void updateIdea(UpdateIdeaReq updateIdeaReq) { -// this.title = updateIdeaReq.getTitle(); -// this.simpleDescription = updateIdeaReq.getSimpleDescription(); -// this.detailedDescription = updateIdeaReq.getDetailedDescription(); -// this.url1 = updateIdeaReq.getUrl1(); -// this.url2 = updateIdeaReq.getUrl2(); -// } } diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/mail/application/MailService.java b/ideac-core/src/main/java/depth/main/ideac/domain/mail/application/MailService.java index d97eef8..a456716 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/mail/application/MailService.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/mail/application/MailService.java @@ -4,17 +4,14 @@ import depth.main.ideac.domain.mail.domain.repository.MailRepository; import depth.main.ideac.domain.mail.dto.FindPasswordReq; import depth.main.ideac.domain.user.domain.User; -import depth.main.ideac.domain.user.dto.PasswordReq; import depth.main.ideac.domain.user.domain.repository.UserRepository; import depth.main.ideac.global.DefaultAssert; import depth.main.ideac.global.payload.ApiResponse; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.http.ResponseEntity; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,7 +24,6 @@ public class MailService { private final JavaMailSender javaMailSender; private final UserRepository userRepository; private final MailRepository mailRepository; - private final PasswordEncoder passwordEncoder; @Transactional public ResponseEntity sendEmail(FindPasswordReq findPasswordReq) { // 이메일이 존재하는지 확인 @@ -45,10 +41,13 @@ public ResponseEntity sendEmail(FindPasswordReq findPasswordReq) { simpleMailMessage.setTo(receiveList); // 2. 메일 제목 설정 - simpleMailMessage.setSubject("test_title"); + simpleMailMessage.setSubject("IDEA CAMPUS 비밀번호 재설정"); // 3. 메일 내용 설정 - simpleMailMessage.setText("http://localhost:8080/mail/send-email/" + code); + simpleMailMessage.setText("안녕하세요. IDEA CAMPUS입니다.\n" + + "서비스 이용을 위한 하단 계정의 비밀번호 재설정 이메일 요청 메일입니다.\n" + + "‘비밀번호 재설정’ 버튼을 클릭하여 재설정이 완료하실 수 있습니다." + + "http://localhost:8080/mail/send-email/" + code); // 4. 메일 전송 javaMailSender.send(simpleMailMessage); @@ -60,7 +59,6 @@ public ResponseEntity sendEmail(FindPasswordReq findPasswordReq) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(verify.getCode()) - .message("메일을 보냈어요!") .build(); return ResponseEntity.ok(apiResponse); diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/user/application/UserService.java b/ideac-core/src/main/java/depth/main/ideac/domain/user/application/UserService.java index 7275c23..da380da 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/user/application/UserService.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/user/application/UserService.java @@ -2,27 +2,19 @@ import depth.main.ideac.domain.auth.domain.Token; import depth.main.ideac.domain.auth.domain.repository.TokenRepository; -import depth.main.ideac.domain.auth.dto.SignUpReq; -import depth.main.ideac.domain.mail.domain.Verify; +import depth.main.ideac.domain.auth.dto.request.SignUpReq; import depth.main.ideac.domain.mail.domain.repository.MailRepository; -import depth.main.ideac.domain.user.domain.Role; import depth.main.ideac.domain.user.domain.Status; import depth.main.ideac.domain.user.domain.User; import depth.main.ideac.domain.user.domain.repository.UserRepository; -import depth.main.ideac.domain.user.dto.PasswordReq; import depth.main.ideac.global.DefaultAssert; import depth.main.ideac.global.config.security.token.UserPrincipal; -import depth.main.ideac.global.error.DefaultException; import depth.main.ideac.global.payload.ApiResponse; -import depth.main.ideac.global.payload.ErrorCode; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; import java.util.Optional; @Service @@ -31,38 +23,7 @@ public class UserService { private final MailRepository mailRepository; private final UserRepository userRepository; - private final PasswordEncoder passwordEncoder; private final TokenRepository tokenRepository; - @Transactional - public ResponseEntity changePassword(@Valid PasswordReq passwordReq, String code){ - - //검증 - DefaultAssert.isTrue(passwordReq.getPassword().equals(passwordReq.getRePassword()), "비밀번호가 서로 다릅니다."); - //만료시간 검증 - Verify verify = mailRepository.findByCode(code); - - if (verify == null){ - throw new DefaultException(ErrorCode.INVALID_CHECK, "이미변경되었습니다?"); - } - - DefaultAssert.isTrue(verify.checkExpiration(LocalDateTime.now()), "만료되었습니다."); - - Optional findUser = userRepository.findByEmail(verify.getEmail()); - - User user = findUser.get(); - user.updatePassWord(passwordEncoder.encode(passwordReq.getPassword())); - - // 인증완료 후 삭제 - mailRepository.delete(verify); - - ApiResponse apiResponse = ApiResponse.builder() - .check(true) - .information(null) - .message("비밀번호를 바꾸었어요") - .build(); - - return ResponseEntity.ok(apiResponse); - } @Transactional public ResponseEntity deleteUser(UserPrincipal userPrincipal) { @@ -86,7 +47,7 @@ public ResponseEntity deleteUser(UserPrincipal userPrincipal) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(null) - .message("회원탈퇴 완료!") + .message("회원탈퇴 완료하였습니다.") .build(); return ResponseEntity.ok(apiResponse); diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/Provider.java b/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/Provider.java index e244ef4..821432b 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/Provider.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/Provider.java @@ -1,10 +1,5 @@ package depth.main.ideac.domain.user.domain; public enum Provider { - local, - facebook, - google, - github, - kakao, - naver + google } diff --git a/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/User.java b/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/User.java index 27aed4a..8159203 100644 --- a/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/User.java +++ b/ideac-core/src/main/java/depth/main/ideac/domain/user/domain/User.java @@ -1,6 +1,6 @@ package depth.main.ideac.domain.user.domain; -import depth.main.ideac.domain.auth.dto.SignUpReq; +import depth.main.ideac.domain.auth.dto.request.SignUpReq; import depth.main.ideac.domain.club_post.ClubPost; import depth.main.ideac.domain.common.BaseEntity; import depth.main.ideac.domain.idea_post.IdeaPost; @@ -27,7 +27,6 @@ public class User extends BaseEntity { private Long id; @Email(message = "이메일 형식이어야 합니다.") - // @Pattern @NotBlank(message = "이메일이 입력되지 않았습니다.") private String email; diff --git a/ideac-core/src/main/java/depth/main/ideac/global/config/MailConfig.java b/ideac-core/src/main/java/depth/main/ideac/global/config/MailConfig.java index 7245ded..7f1d23a 100644 --- a/ideac-core/src/main/java/depth/main/ideac/global/config/MailConfig.java +++ b/ideac-core/src/main/java/depth/main/ideac/global/config/MailConfig.java @@ -1,15 +1,15 @@ -package depth.main.ideac.global.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.JavaMailSenderImpl; - -@Configuration -public class MailConfig { - - @Bean - public JavaMailSender javaMailSender() { - return new JavaMailSenderImpl(); - } -} \ No newline at end of file +//package depth.main.ideac.global.config; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.mail.javamail.JavaMailSender; +//import org.springframework.mail.javamail.JavaMailSenderImpl; +// +//@Configuration +//public class MailConfig { +// +// @Bean +// public JavaMailSender javaMailSender() { +// return new JavaMailSenderImpl(); +// } +//} \ No newline at end of file diff --git a/ideac-core/src/main/java/depth/main/ideac/global/config/security/OAuth2Config.java b/ideac-core/src/main/java/depth/main/ideac/global/config/security/OAuth2Config.java index c93c594..689fabb 100644 --- a/ideac-core/src/main/java/depth/main/ideac/global/config/security/OAuth2Config.java +++ b/ideac-core/src/main/java/depth/main/ideac/global/config/security/OAuth2Config.java @@ -1,6 +1,8 @@ package depth.main.ideac.global.config.security; import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -13,7 +15,8 @@ public class OAuth2Config { private final Auth auth = new Auth(); private final OAuth2 oauth2 = new OAuth2(); - @Data + @Getter + @Setter public static class Auth { private String tokenSecret; private long accessTokenExpirationMsec; diff --git a/ideac-core/src/main/java/depth/main/ideac/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java b/ideac-core/src/main/java/depth/main/ideac/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java index 6e60e91..3176e4b 100644 --- a/ideac-core/src/main/java/depth/main/ideac/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java +++ b/ideac-core/src/main/java/depth/main/ideac/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java @@ -55,7 +55,7 @@ protected String determineTargetUrl(HttpServletRequest request, HttpServletRespo DefaultAssert.isAuthentication( !(redirectUri.isPresent() && !isAuthorizedRedirectUri(redirectUri.get())) ); // String targetUrl = redirectUri.orElse(getDefaultTargetUrl()); // - String targetUrl = redirectUri.orElse("/auth/sign-up"); //회원가입창으로 리다이렉트 + String targetUrl = redirectUri.orElse("/api/user/google"); //회원가입창으로 리다이렉트 log.info(targetUrl); System.out.println("targetUrl = " + targetUrl); TokenMapping tokenMapping = customTokenProviderService.createToken(authentication); diff --git a/ideac-core/src/main/java/depth/main/ideac/global/error/DefaultNullPointerException.java b/ideac-core/src/main/java/depth/main/ideac/global/error/DefaultNullPointerException.java index 6db8937..4576e9a 100644 --- a/ideac-core/src/main/java/depth/main/ideac/global/error/DefaultNullPointerException.java +++ b/ideac-core/src/main/java/depth/main/ideac/global/error/DefaultNullPointerException.java @@ -7,9 +7,15 @@ public class DefaultNullPointerException extends NullPointerException{ private ErrorCode errorCode; + private String message; public DefaultNullPointerException(ErrorCode errorCode) { super(errorCode.getMessage()); this.errorCode = errorCode; } + public DefaultNullPointerException(ErrorCode errorCode, String message) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + this.message = message; + } } diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java b/ideac-user/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java index 3134265..17f9867 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/auth/presentation/AuthController.java @@ -2,10 +2,11 @@ import depth.main.ideac.domain.auth.application.AuthService; -import depth.main.ideac.domain.auth.dto.AuthRes; -import depth.main.ideac.domain.auth.dto.FindIdReq; -import depth.main.ideac.domain.auth.dto.SignInReq; -import depth.main.ideac.domain.auth.dto.SignUpReq; +import depth.main.ideac.domain.auth.dto.response.AuthRes; +import depth.main.ideac.domain.auth.dto.request.FindIdReq; +import depth.main.ideac.domain.auth.dto.request.SignInReq; +import depth.main.ideac.domain.auth.dto.request.SignUpReq; +import depth.main.ideac.domain.auth.dto.request.PasswordReq; import depth.main.ideac.global.payload.ErrorResponse; import depth.main.ideac.global.payload.Message; import io.swagger.v3.oas.annotations.Operation; @@ -83,10 +84,17 @@ public ResponseEntity doubleCheckEmail(@PathVariable(value = "email") String return authService.doubleCheckEmail(email); } -// @GetMapping(value = "test") -// public ResponseEntity test(){ -// -// return ResponseEntity.ok("test"); -// } + @Operation(summary = "비밀번호 바꾸기", description = "비밀번호를 바꾼다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "비밀번호 바꾸기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), + @ApiResponse(responseCode = "400", description = "비밀번호 바꾸기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) + }) + @PostMapping(value = "/change-password/{code}") + public ResponseEntity changePassword(@Parameter(description = "Schemas의 PassWordReq를 참고해주세요.") + @Valid @RequestBody PasswordReq passwordReq, + @PathVariable String code) { + return authService.changePassword(passwordReq,code); + } + } diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/auth/presentation/test.java b/ideac-user/src/main/java/depth/main/ideac/domain/auth/presentation/test.java deleted file mode 100644 index 7bd2146..0000000 --- a/ideac-user/src/main/java/depth/main/ideac/domain/auth/presentation/test.java +++ /dev/null @@ -1,27 +0,0 @@ -package depth.main.ideac.domain.auth.presentation; -import io.swagger.v3.oas.annotations.Hidden; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -@RestController -@RequestMapping("/") -public class test { - @GetMapping("/returnStr") - public String returnStr(@RequestParam String str) { - return str + "\n" + str; - } - - @GetMapping("/example") - public String example() { - return "예시 API"; - } - - @GetMapping("/ignore") - public String ignore() { - return "무시되는 API"; - } -} diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/club_post/application/ClubPostService.java b/ideac-user/src/main/java/depth/main/ideac/domain/club_post/application/ClubPostService.java index 5bff447..7e0ec18 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/club_post/application/ClubPostService.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/club_post/application/ClubPostService.java @@ -13,7 +13,7 @@ import depth.main.ideac.global.error.DefaultException; import depth.main.ideac.global.payload.ErrorCode; import depth.main.ideac.domain.user.domain.repository.UserRepository; -import depth.main.ideac.global.service.FileService; +import depth.main.ideac.global.service.S3Service; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -34,7 +34,7 @@ public class ClubPostService { private final UserRepository userRepository; private final ClubPostRepository clubPostRepository; private final ClubPostImageRepository clubPostImageRepository; - private final FileService fileService; + private final S3Service s3Service; // 전체 조회 public Page getAllClubPosts(Pageable pageable) { @@ -151,16 +151,16 @@ public void uploadFile(ClubPost clubPost, List images) throws IOE boolean isFirstImage = true; for (MultipartFile image : images) { - String s3ImageKey = fileService.uploadFile(image, getClass().getSimpleName()); + String s3key = s3Service.uploadFile(image, getClass().getSimpleName()); // 첫 번째 이미지인 경우에만 thumbnail로 설정 boolean isThumbnail = isFirstImage; isFirstImage = false; clubPostImages.add(ClubPostImage.builder() - .imagePath(fileService.getUrl(s3ImageKey)) + .imagePath(s3Service.getUrl(s3key)) .isThumbnail(isThumbnail) - .s3key(s3ImageKey) + .s3key(s3key) .clubPost(clubPost) .build()); } @@ -171,7 +171,7 @@ public void uploadFile(ClubPost clubPost, List images) throws IOE public void deleteFile(Long clubId){ List images = clubPostImageRepository.findByClubPostId(clubId); for(ClubPostImage image : images) { - fileService.deleteFile(image.getS3key()); //s3 삭제 + s3Service.deleteFile(image.getS3key()); //s3 삭제 clubPostImageRepository.deleteById(image.getId()); //엔티티 삭제 } } diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/home/application/HomeService.java b/ideac-user/src/main/java/depth/main/ideac/domain/home/application/HomeService.java index d7c9fe0..9487219 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/home/application/HomeService.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/home/application/HomeService.java @@ -28,6 +28,7 @@ public class HomeService { private final IdeaPostRepository ideaPostRepository; private final ProjectPostRepository projectPostRepository; + // 아이디어 public List getIdeas() { List ideaPosts = ideaPostRepository.findTop3ByOrderByCreatedAtDesc(); diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/application/IdeaPostService.java b/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/application/IdeaPostService.java index 169c642..3eda3ed 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/application/IdeaPostService.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/application/IdeaPostService.java @@ -1,7 +1,8 @@ package depth.main.ideac.domain.idea_post.application; import depth.main.ideac.domain.idea_post.IdeaPost; -import depth.main.ideac.domain.idea_post.dto.request.*; +import depth.main.ideac.domain.idea_post.dto.request.RegisterIdeaReq; +import depth.main.ideac.domain.idea_post.dto.request.UpdateIdeaReq; import depth.main.ideac.domain.idea_post.dto.response.GetAllIdeasRes; import depth.main.ideac.domain.idea_post.dto.response.GetDetailIdeaRes; import depth.main.ideac.domain.idea_post.repository.IdeaPostRepository; @@ -36,6 +37,7 @@ public class IdeaPostService { private final UserRepository userRepository; private final RedisTemplate redisTemplate; + //아이디어 등록 @Transactional public Long registerIdea(UserPrincipal userPrincipal, RegisterIdeaReq registerIdeaReq){ User user = userRepository.findById(userPrincipal.getId()).get(); @@ -56,14 +58,12 @@ public Long registerIdea(UserPrincipal userPrincipal, RegisterIdeaReq registerId return ideapost.getId(); } + //상세아디이어 조회 @Transactional public ResponseEntity getDetailIdea(Long id) { IdeaPost ideaPost = ideaPostRepository.findById(id).get(); String[] split = ideaPost.getKeyword().split(","); -// for (String s : split) { -// System.out.println("s = " + s); -// } List list = Arrays.asList(split); GetDetailIdeaRes getDetailIdeaRes = GetDetailIdeaRes.builder() .id(ideaPost.getId()) @@ -82,19 +82,15 @@ public ResponseEntity getDetailIdea(Long id) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(getDetailIdeaRes) - .message("상세내용을 가져왔어요!") .build(); return ResponseEntity.ok(apiResponse); } + //아이디어 수정 @Transactional public ResponseEntity updateIdea(Long id, UpdateIdeaReq updateIdeaReq) { IdeaPost ideaPost = ideaPostRepository.findById(id).get(); - String[] split = updateIdeaReq.getKeyWord().split(","); -// for (String s : split) { -// System.out.println("s = " + s); -// } - List list = Arrays.asList(split); + ideaPost.setTitle(updateIdeaReq.getTitle()); ideaPost.setKeyword(updateIdeaReq.getKeyWord()); ideaPost.setSimpleDescription(updateIdeaReq.getSimpleDescription()); @@ -105,11 +101,11 @@ public ResponseEntity updateIdea(Long id, UpdateIdeaReq updateIdeaReq) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(null) - .message("업데이트 했어요!") .build(); return ResponseEntity.ok(apiResponse); } + //아이디어 삭제 @Transactional public ResponseEntity deleteIdea(Long id) { IdeaPost ideaPost = ideaPostRepository.findById(id).get(); @@ -117,11 +113,11 @@ public ResponseEntity deleteIdea(Long id) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(null) - .message("삭제 했어요!") .build(); return ResponseEntity.ok(apiResponse); } + //모든 아이디어들 조회 public ResponseEntity getAllIdea(int page, int size, String sortBy) { Pageable pageable; if (sortBy.equals("hits")) { @@ -145,11 +141,11 @@ public ResponseEntity getAllIdea(int page, int size, String sortBy) { ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(getAllIdeasRes) - .message("조회목록들이에요") .build(); return ResponseEntity.ok(apiResponse); } + //권한 검증 public boolean isAdminOrWriter(Long ideaId, Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new DefaultException(ErrorCode.USER_NOT_FOUND)); diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/dto/request/RegisterIdeaReq.java b/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/dto/request/RegisterIdeaReq.java index 738ee46..b46ce27 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/dto/request/RegisterIdeaReq.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/idea_post/dto/request/RegisterIdeaReq.java @@ -12,6 +12,7 @@ public class RegisterIdeaReq { @NotBlank(message = "내용이 입력되지 않았습니다.") @Size(max = 50, message = "간단 설명은 최대 50자까지 입력 가능합니다.") private String simpleDescription; + @NotBlank private String keyword; @NotBlank(message = "내용이 입력되지 않았습니다.") private String detailedDescription; diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/PostRes.java b/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/PostRes.java index 28b9626..f3153fa 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/PostRes.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/PostRes.java @@ -1,5 +1,6 @@ package depth.main.ideac.domain.my_page.dto.response; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.time.LocalDateTime; @@ -8,6 +9,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@Schema(description = "내 게시물 조회 Response") public class PostRes { private String title; private String type; diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/UserRes.java b/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/UserRes.java index a7e87f2..d05bfad 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/UserRes.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/my_page/dto/response/UserRes.java @@ -1,5 +1,6 @@ package depth.main.ideac.domain.my_page.dto.response; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @@ -8,6 +9,7 @@ public class UserRes { @Builder @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor + @Schema(description = "Header에 표기될 회원 정보 Response") public static class HeaderInfoRes { private String nickname; private String color; @@ -16,6 +18,7 @@ public static class HeaderInfoRes { @Builder @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor + @Schema(description = "마이페이지에 표기될 회원 정보 Request, 필요에 따라 필터링하여 사용") public static class MyPageInfoRes { private String color; private String name; diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/my_page/presentation/MyPageController.java b/ideac-user/src/main/java/depth/main/ideac/domain/my_page/presentation/MyPageController.java index 2b3bec4..7bc6f64 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/my_page/presentation/MyPageController.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/my_page/presentation/MyPageController.java @@ -6,11 +6,13 @@ import depth.main.ideac.global.config.security.token.UserPrincipal; import depth.main.ideac.global.payload.ApiResponse; import io.swagger.v3.oas.annotations.Operation; +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.*; +@Tag(name = "MyPage API", description = "마이페이지 관련 API입니다.") @RestController @RequestMapping("/api/my-page") @RequiredArgsConstructor diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/application/ProjectPostService.java b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/application/ProjectPostService.java index 3236966..11852cc 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/application/ProjectPostService.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/application/ProjectPostService.java @@ -13,9 +13,8 @@ import depth.main.ideac.domain.user.domain.repository.UserRepository; import depth.main.ideac.global.error.DefaultException; import depth.main.ideac.global.payload.ErrorCode; -import depth.main.ideac.global.service.FileService; +import depth.main.ideac.global.service.S3Service; import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.*; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; @@ -35,7 +34,7 @@ @RequiredArgsConstructor public class ProjectPostService { - private final FileService fileService; + private final S3Service s3Service; private final ProjectPostRepository projectPostRepository; private final ProjectPostImageRepository projectPostImageRepository; private final UserRepository userRepository; @@ -212,16 +211,16 @@ public void uploadFile(ProjectPost projectPost, List images) thro boolean isFirstImage = true; for (MultipartFile image : images) { - String s3ImageKey = fileService.uploadFile(image, getClass().getSimpleName()); + String s3key = s3Service.uploadFile(image, getClass().getSimpleName()); // 첫 번째 이미지인 경우에만 thumbnail로 설정 boolean isThumbnail = isFirstImage; isFirstImage = false; projectPostImages.add(ProjectPostImage.builder() - .imagePath(fileService.getUrl(s3ImageKey)) + .imagePath(s3Service.getUrl(s3key)) .isThumbnail(isThumbnail) - .s3key(s3ImageKey) + .s3key(s3key) .projectPost(projectPost) .build()); } @@ -232,7 +231,7 @@ public void uploadFile(ProjectPost projectPost, List images) thro public void deleteFile(Long projectId){ List images = projectPostImageRepository.findByProjectPostId(projectId); for(ProjectPostImage image : images) { - fileService.deleteFile(image.getS3key()); //s3 삭제 + s3Service.deleteFile(image.getS3key()); //s3 삭제 projectPostImageRepository.deleteById(image.getId()); //엔티티 삭제 } } diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectDetailRes.java b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectDetailRes.java index b3e61e7..1a817a9 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectDetailRes.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectDetailRes.java @@ -1,6 +1,7 @@ package depth.main.ideac.domain.project_post.dto.response; import depth.main.ideac.domain.user.domain.User; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.FetchType; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; @@ -14,6 +15,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@Schema(description = "프로젝트 상세 조회 Response") public class ProjectDetailRes { @NotBlank(message = "제목이 입력되지 않았습니다.") private String title; diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectRes.java b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectRes.java index bb6e00d..666590a 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectRes.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/dto/response/ProjectRes.java @@ -1,5 +1,6 @@ package depth.main.ideac.domain.project_post.dto.response; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.time.LocalDateTime; @@ -8,6 +9,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@Schema(description = "프로젝트 목록 조회 Response") public class ProjectRes { private Long id; private boolean booleanWeb; diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/presentation/ProjectPostController.java b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/presentation/ProjectPostController.java index db782bd..796f6a5 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/project_post/presentation/ProjectPostController.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/project_post/presentation/ProjectPostController.java @@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -29,6 +30,7 @@ @RestController @RequestMapping("/api/project") @RequiredArgsConstructor +@Tag(name = "ProjectPost API", description = "프로젝트 갤러리 관련 API입니다.") public class ProjectPostController { private final ProjectPostService projectPostService; diff --git a/ideac-user/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java b/ideac-user/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java index 3064e65..5e6df17 100644 --- a/ideac-user/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java +++ b/ideac-user/src/main/java/depth/main/ideac/domain/user/presentation/UserController.java @@ -1,9 +1,7 @@ package depth.main.ideac.domain.user.presentation; -import depth.main.ideac.domain.auth.dto.SignUpReq; -import depth.main.ideac.domain.mail.application.MailService; +import depth.main.ideac.domain.auth.dto.request.SignUpReq; import depth.main.ideac.domain.user.application.UserService; -import depth.main.ideac.domain.user.dto.PasswordReq; import depth.main.ideac.global.config.security.token.CurrentUser; import depth.main.ideac.global.config.security.token.UserPrincipal; import depth.main.ideac.global.payload.ErrorResponse; @@ -24,17 +22,7 @@ @RequestMapping("/api/user") public class UserController { private final UserService userService; - @Operation(summary = "비밀번호 바꾸기", description = "비밀번호를 바꾼다.") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "비밀번호 바꾸기 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), - @ApiResponse(responseCode = "400", description = "비밀번호 바꾸기 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}) - }) - @PostMapping(value = "/change-password/{code}") - public ResponseEntity changePassword(@Parameter(description = "Schemas의 PassWordReq를 참고해주세요.") - @Valid @RequestBody PasswordReq passwordReq, - @PathVariable String code) { - return userService.changePassword(passwordReq,code); - } + @Operation(summary = "회원탈퇴", description = "회원탈퇴를 한다.") @ApiResponses(value = { diff --git a/ideac-user/src/main/java/depth/main/ideac/global/service/FileService.java b/ideac-user/src/main/java/depth/main/ideac/global/service/S3Service.java similarity index 66% rename from ideac-user/src/main/java/depth/main/ideac/global/service/FileService.java rename to ideac-user/src/main/java/depth/main/ideac/global/service/S3Service.java index 054c738..a776d76 100644 --- a/ideac-user/src/main/java/depth/main/ideac/global/service/FileService.java +++ b/ideac-user/src/main/java/depth/main/ideac/global/service/S3Service.java @@ -5,6 +5,9 @@ import com.amazonaws.services.s3.model.DeleteObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; +import depth.main.ideac.global.DefaultAssert; +import depth.main.ideac.global.error.DefaultNullPointerException; +import depth.main.ideac.global.payload.ErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -18,7 +21,7 @@ @Service @Transactional(readOnly = true) @RequiredArgsConstructor -public class FileService { +public class S3Service { @Value("${cloud.aws.s3.bucket}") private String BUCKET; @@ -26,6 +29,9 @@ public class FileService { @Transactional public String uploadFile(MultipartFile file, String className) throws IOException { + if(file == null){ + throw new DefaultNullPointerException(ErrorCode.INVALID_PARAMETER, "파일을 첨부해주세요.."); + } String fileName = convertToRandomName(file.getOriginalFilename()); ObjectMetadata objectMetadata = new ObjectMetadata(); @@ -36,12 +42,15 @@ public String uploadFile(MultipartFile file, String className) throws IOExceptio String filePath = BUCKET + "/image/" + className; amazonS3.putObject(new PutObjectRequest(filePath, fileName, inputStream, objectMetadata) .withCannedAcl(CannedAccessControlList.PublicRead)); - String s3ImageKey = "image/" + className + "/" + fileName; - return s3ImageKey; + String s3key = "image/" + className + "/" + fileName; + return s3key; } - - public void deleteFile(String s3ImageKey) { - amazonS3.deleteObject(new DeleteObjectRequest(BUCKET, s3ImageKey)); + @Transactional + public void deleteFile(String s3key) { + if(s3key == null){ + throw new DefaultNullPointerException(ErrorCode.INVALID_PARAMETER, "삭제하려는 파일을 찾을 수 없습니다."); + } + amazonS3.deleteObject(new DeleteObjectRequest(BUCKET, s3key)); } public String convertToRandomName(String originalFileName) { @@ -49,7 +58,10 @@ public String convertToRandomName(String originalFileName) { return UUID.randomUUID().toString().concat(fileExtension); } - public String getUrl(String s3ImageKey) { - return amazonS3.getUrl(BUCKET, s3ImageKey).toString(); + public String getUrl(String s3key) { + if(s3key == null){ + throw new DefaultNullPointerException(ErrorCode.INVALID_PARAMETER, "파일을 찾을 수 없습니다."); + } + return amazonS3.getUrl(BUCKET, s3key).toString(); } }