diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml
index ac8e328..397c268 100644
--- a/refrigerator/.idea/modules/refrigerator.main.iml
+++ b/refrigerator/.idea/modules/refrigerator.main.iml
@@ -1,6 +1,9 @@
+
+
+
@@ -17,5 +20,4 @@
-
-
+
\ No newline at end of file
diff --git a/refrigerator/build.gradle b/refrigerator/build.gradle
index bc46bee..156aa6d 100644
--- a/refrigerator/build.gradle
+++ b/refrigerator/build.gradle
@@ -41,6 +41,8 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt-impl:0.12.3'
implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
+
+ implementation 'org.springframework.boot:spring-boot-starter-mail'
}
tasks.named('test') {
useJUnitPlatform()
diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java
index cbd031e..3dd637c 100644
--- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java
+++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java
@@ -1,9 +1,12 @@
package moja.refrigerator.controller.user;
import jakarta.servlet.http.HttpServletRequest;
+import moja.refrigerator.dto.user.request.PasswordResetRequest;
+import moja.refrigerator.dto.user.request.PasswordUpdateRequest;
import moja.refrigerator.dto.user.request.UserCreateRequest;
import moja.refrigerator.dto.user.request.UserUpdateRequest;
import moja.refrigerator.service.user.UserService;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@@ -25,7 +28,7 @@ public String getMainPage() {
@PostMapping("/auth/join")
public ResponseEntity> join(@RequestBody UserCreateRequest request) {
userService.createUser(request);
- return ResponseEntity.ok().body("회원 가입이 완료되었습니다.");
+ return ResponseEntity.status(HttpStatus.CREATED).body("회원 가입이 완료되었습니다.");
}
// 회원 정보 수정
@@ -34,4 +37,18 @@ public ResponseEntity> update(@RequestBody UserUpdateRequest request) {
userService.updateUser(request);
return ResponseEntity.ok().body("회원 정보가 수정되었습니다.");
}
+
+ // 비밀번호 재발급
+ @PostMapping("/password/reset")
+ public ResponseEntity> resetPassword(@RequestBody PasswordResetRequest request) {
+ userService.resetPassword(request);
+ return ResponseEntity.ok().body("임시 비밀번호가 이메일로 발송되었습니다.");
+ }
+
+ // 비밀번호 재설정
+ @PutMapping("/password/update")
+ public ResponseEntity> updatePassword(@RequestBody PasswordUpdateRequest request) {
+ userService.updatePassword(request);
+ return ResponseEntity.ok().body("비밀번호가 변경되었습니다.");
+ }
}
diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordResetRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordResetRequest.java
new file mode 100644
index 0000000..89b2c75
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordResetRequest.java
@@ -0,0 +1,8 @@
+package moja.refrigerator.dto.user.request;
+
+import lombok.Data;
+
+@Data
+public class PasswordResetRequest {
+ private String userEmail;
+}
diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordUpdateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordUpdateRequest.java
new file mode 100644
index 0000000..3b6762a
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordUpdateRequest.java
@@ -0,0 +1,9 @@
+package moja.refrigerator.dto.user.request;
+
+import lombok.Data;
+
+@Data
+public class PasswordUpdateRequest {
+ private String currentPw;
+ private String newPw;
+}
diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java
index b3b44c0..1742c4b 100644
--- a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java
+++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java
@@ -13,4 +13,5 @@ public interface UserRepository extends JpaRepository {
boolean existsByUserNickname(String userNickname);
Optional findByUserPk(long userPk);
Optional findByUserId(String userId);
+ Optional findByUserEmail(String userEmail);
}
diff --git a/refrigerator/src/main/java/moja/refrigerator/service/email/EmailService.java b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailService.java
new file mode 100644
index 0000000..c189c53
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailService.java
@@ -0,0 +1,5 @@
+package moja.refrigerator.service.email;
+
+public interface EmailService {
+ void sendTempPassword(String name, String email, String tempPassword);
+}
diff --git a/refrigerator/src/main/java/moja/refrigerator/service/email/EmailServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailServiceImpl.java
new file mode 100644
index 0000000..ec915b3
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailServiceImpl.java
@@ -0,0 +1,38 @@
+package moja.refrigerator.service.email;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class EmailServiceImpl implements EmailService {
+ private final JavaMailSender mailSender;
+
+ public EmailServiceImpl(JavaMailSender mailSender) {
+ this.mailSender = mailSender;
+ }
+
+ @Value("${spring.mail.username}")
+ private String senderEmail;
+
+ @Override
+ @Transactional
+ public void sendTempPassword(String name, String email, String tempPassword) {
+ SimpleMailMessage message = new SimpleMailMessage();
+
+ message.setTo(email);
+ message.setFrom(senderEmail);
+ message.setSubject("[ReciPick] 임시 비밀번호 발급");
+ message.setText(String.format("""
+ 안녕하세요. %s님! 임시 비밀번호가 발급되었습니다.
+
+ 임시 비밀번호: %s
+
+ 보안을 위해 로그인 후 반드시 비밀번호를 변경해 주세요.
+ """, name, tempPassword));
+
+ mailSender.send(message);
+ }
+}
diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java
index 9109d98..cfb1abd 100644
--- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java
+++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java
@@ -1,9 +1,13 @@
package moja.refrigerator.service.user;
+import moja.refrigerator.dto.user.request.PasswordResetRequest;
+import moja.refrigerator.dto.user.request.PasswordUpdateRequest;
import moja.refrigerator.dto.user.request.UserCreateRequest;
import moja.refrigerator.dto.user.request.UserUpdateRequest;
public interface UserService {
void createUser(UserCreateRequest request);
void updateUser(UserUpdateRequest request);
+ void resetPassword(PasswordResetRequest request);
+ void updatePassword(PasswordUpdateRequest request);
}
diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java
index 5309804..7329781 100644
--- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java
+++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java
@@ -1,11 +1,14 @@
package moja.refrigerator.service.user;
+import lombok.RequiredArgsConstructor;
import moja.refrigerator.aggregate.user.User;
+import moja.refrigerator.dto.user.request.PasswordResetRequest;
+import moja.refrigerator.dto.user.request.PasswordUpdateRequest;
import moja.refrigerator.dto.user.request.UserCreateRequest;
import moja.refrigerator.dto.user.request.UserUpdateRequest;
import moja.refrigerator.exception.user.DuplicateUserException;
-import moja.refrigerator.repository.user.TokenBlacklistRepository;
import moja.refrigerator.repository.user.UserRepository;
+import moja.refrigerator.service.email.EmailService;
import org.modelmapper.ModelMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -16,18 +19,15 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
@Service
+@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder passwordEncoder;
private final ModelMapper modelMapper;
-
- public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder, ModelMapper modelMapper) {
- this.userRepository = userRepository;
- this.passwordEncoder = passwordEncoder;
- this.modelMapper = modelMapper;
- }
+ private final EmailService emailService;
@Override
@Transactional
@@ -74,6 +74,46 @@ public void updateUser(UserUpdateRequest request) {
}
}
+ @Override
+ @Transactional
+ public void resetPassword(PasswordResetRequest request) {
+ // 이메일로 사용자 찾기
+ User user = userRepository.findByUserEmail(request.getUserEmail())
+ .orElseThrow(() -> new UsernameNotFoundException("해당 이메일로 가입된 계정이 없습니다."));
+
+ // 임시 비밀번호 생성
+ String tempPassword = UUID.randomUUID().toString().substring(0, 12);
+
+ try {
+ // 이메일 발송
+ emailService.sendTempPassword(user.getUserNickname(), user.getUserEmail(), tempPassword);
+ // 임시 비밀번호로 업데이트
+ user.setUserPw(passwordEncoder.encode(tempPassword));
+ } catch (Exception e) {
+ System.out.println("Detailed error: " + e.getMessage());
+ throw new RuntimeException("이메일 발송에 실패했습니다.");
+ }
+
+ }
+
+ @Override
+ @Transactional
+ public void updatePassword(PasswordUpdateRequest request) {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ String userId = authentication.getName();
+
+ User user = userRepository.findByUserId(userId)
+ .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다."));
+
+ // 기존 비밀번호 검증
+ if (!passwordEncoder.matches(request.getCurrentPw(), user.getUserPw())) {
+ throw new IllegalArgumentException("기존 비밀번호가 일치하지 않습니다.");
+ }
+
+ // 새 비밀번호 암호화 후 저장
+ user.setUserPw(passwordEncoder.encode(request.getNewPw()));
+ }
+
private void checkDuplicateUser(UserCreateRequest request) {
List errors = new ArrayList<>();
if (userRepository.existsByUserId(request.getUserId())) {