Skip to content

Commit 10fd6c3

Browse files
authored
Merge pull request #119 from noeyeyh/feat/password
#106 Feat: 비밀번호 찾기
2 parents fc72cec + 4575948 commit 10fd6c3

File tree

14 files changed

+152
-45
lines changed

14 files changed

+152
-45
lines changed

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ dependencies {
6161

6262
// redis
6363
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
64+
65+
// 이메일 전송
66+
implementation 'org.springframework.boot:spring-boot-starter-mail'
6467
}
6568

6669
tasks.named('test') {

src/main/java/com/memesphere/domain/user/controller/UserController.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
package com.memesphere.domain.user.controller;
22

3-
import com.memesphere.domain.user.dto.request.ReissueRequest;
4-
import com.memesphere.domain.user.dto.request.NicknameRequest;
5-
import com.memesphere.domain.user.dto.request.SignInRequest;
6-
import com.memesphere.domain.user.dto.request.SignUpRequest;
7-
import com.memesphere.domain.user.dto.response.GoogleUserInfoResponse;
8-
import com.memesphere.domain.user.dto.response.TokenResponse;
9-
import com.memesphere.domain.user.dto.response.KakaoUserInfoResponse;
10-
import com.memesphere.domain.user.service.AuthServiceImpl;
11-
import com.memesphere.domain.user.service.GoogleServiceImpl;
12-
import com.memesphere.domain.user.service.KakaoServiceImpl;
3+
import com.memesphere.domain.user.dto.request.*;
4+
import com.memesphere.domain.user.dto.response.*;
5+
import com.memesphere.domain.user.service.*;
136
import com.memesphere.global.apipayload.ApiResponse;
14-
import com.memesphere.domain.user.dto.response.LoginResponse;
157
import com.memesphere.global.apipayload.code.status.ErrorStatus;
168
import com.memesphere.global.apipayload.exception.GeneralException;
179
import com.memesphere.global.jwt.CustomUserDetails;
@@ -35,6 +27,7 @@ public class UserController {
3527
private final KakaoServiceImpl kakaoServiceImpl;
3628
private final GoogleServiceImpl googleServiceImpl;
3729
private final AuthServiceImpl authServiceImpl;
30+
private final MailServiceImpl mailServiceImpl;
3831
private final JwtAuthenticationFilter jwtAuthenticationFilter;
3932

4033
@PostMapping("/login/oauth2/kakao")
@@ -115,4 +108,30 @@ public ApiResponse<?> isNicknameValidate(@RequestBody NicknameRequest nicknameRe
115108
return ApiResponse.onSuccess("사용 가능한 닉네임입니다.");
116109
}
117110
}
111+
112+
@PostMapping("/password/send")
113+
@Operation(summary = "비밀번호 찾기 API")
114+
public ApiResponse<?> sendPassword(@RequestParam("email") String email) {
115+
// 임시 비밀번호 생성 및 저장
116+
String tmpPassword = authServiceImpl.getTmpPassword();
117+
authServiceImpl.updatePassword(tmpPassword, email);
118+
119+
// 메일 생성 및 전송
120+
EmailResponse mailResponse = mailServiceImpl.createMail(tmpPassword, email);
121+
mailServiceImpl.sendMail(mailResponse);
122+
123+
return ApiResponse.onSuccess("이메일 전송이 완료되었습니다.");
124+
}
125+
126+
@PostMapping("/password/change")
127+
@Operation(summary = "비밀번호 변경 API")
128+
public ApiResponse<?> sendPassword(@RequestParam("newPassword") String newPassword, @AuthenticationPrincipal CustomUserDetails customUserDetails) {
129+
if (customUserDetails == null) {
130+
throw new GeneralException(ErrorStatus.USER_NOT_FOUND);
131+
}
132+
133+
authServiceImpl.updatePassword(newPassword, customUserDetails.getUser().getEmail());
134+
135+
return ApiResponse.onSuccess("비밀번호 변경이 완료되었습니다.");
136+
}
118137
}

src/main/java/com/memesphere/domain/user/converter/UserConverter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.memesphere.domain.user.converter;
22

33
import com.memesphere.domain.user.dto.request.SignUpRequest;
4+
import com.memesphere.domain.user.dto.response.EmailResponse;
45
import com.memesphere.domain.user.dto.response.GoogleUserInfoResponse;
56
import com.memesphere.domain.user.entity.SocialType;
67
import com.memesphere.domain.user.entity.User;
@@ -49,5 +50,14 @@ public static User toAuthUser(SignUpRequest signUpRequest, PasswordEncoder passw
4950
.build();
5051
}
5152

53+
// 비밀번호 찾기 이메일
54+
public static EmailResponse toEmailResponse(String tmpPassword, String memberEmail, String title, String message, String fromAddress) {
55+
return EmailResponse.builder()
56+
.toAddress(memberEmail)
57+
.title(title)
58+
.message(message + tmpPassword)
59+
.fromAddress(fromAddress)
60+
.build();
61+
}
5262
}
5363

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.memesphere.domain.user.dto.response;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
8+
@Getter
9+
@Builder
10+
@AllArgsConstructor
11+
@NoArgsConstructor
12+
public class EmailResponse {
13+
private String toAddress; // 받는 이메일 주소
14+
private String title; // 이메일 제목
15+
private String message; // 이메일 내용
16+
private String fromAddress; // 보내는 이메일 주소
17+
}

src/main/java/com/memesphere/domain/user/entity/User.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,8 @@ public class User extends BaseEntity {
6767
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
6868
@Builder.Default
6969
private List<ChatLike> chatLikeList = new ArrayList<>();
70+
71+
public void updatePassword(String password){
72+
this.password = password;
73+
}
7074
}

src/main/java/com/memesphere/domain/user/service/AuthService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ public interface AuthService {
1212
LoginResponse reissueAccessToken(String refreshToken, User existingUser);
1313
void checkPassword(User user, String password);
1414
boolean checkNicknameDuplicate(String nickname);
15+
String getTmpPassword();
16+
void updatePassword(String tmpPassword, String memberEmail);
1517
}

src/main/java/com/memesphere/domain/user/service/AuthServiceImpl.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import lombok.RequiredArgsConstructor;
1414
import org.springframework.security.crypto.password.PasswordEncoder;
1515
import org.springframework.stereotype.Service;
16+
import org.springframework.transaction.annotation.Transactional;
1617
import org.springframework.util.StringUtils;
1718

1819

@@ -22,7 +23,6 @@ public class AuthServiceImpl implements AuthService{
2223

2324
private final PasswordEncoder passwordEncoder;
2425
private final UserRepository userRepository;
25-
private final UserServiceImpl userServiceImpl;
2626
private final TokenProvider tokenProvider;
2727
private final RedisService redisService;
2828

@@ -38,7 +38,7 @@ public void handleUserRegistration(SignUpRequest signUpRequest) {
3838
}
3939

4040
User newUser = UserConverter.toAuthUser(signUpRequest, passwordEncoder);
41-
userServiceImpl.save(newUser);
41+
userRepository.save(newUser);
4242
}
4343

4444
public LoginResponse handleUserLogin(SignInRequest signInRequest) {
@@ -111,4 +111,29 @@ public void checkPassword(User user, String password) {
111111
public boolean checkNicknameDuplicate(String nickname) {
112112
return userRepository.findByNickname(nickname).isPresent();
113113
}
114+
115+
public String getTmpPassword() {
116+
char[] charSet = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
117+
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
118+
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
119+
120+
String pwd = "";
121+
122+
// 문자 배열 길이의 값을 랜덤으로 10개를 뽑아 조합
123+
int idx = 0;
124+
for(int i = 0; i < 10; i++){
125+
idx = (int) (charSet.length * Math.random());
126+
pwd += charSet[idx];
127+
}
128+
129+
return pwd;
130+
}
131+
132+
@Transactional
133+
public void updatePassword(String tmpPassword, String memberEmail) {
134+
String encryptPassword = passwordEncoder.encode(tmpPassword);
135+
User existingUser = userRepository.findByEmail(memberEmail).orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND));
136+
137+
existingUser.updatePassword(encryptPassword);
138+
}
114139
}

src/main/java/com/memesphere/domain/user/service/GoogleServiceImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
public class GoogleServiceImpl implements GoogleService{
2525

2626
private final TokenProvider tokenProvider;
27-
private final UserServiceImpl userServiceImpl;
2827
private final UserRepository userRepository;
2928

3029
@Value("${security.oauth2.client.registration.google.client-id}")

src/main/java/com/memesphere/domain/user/service/KakaoServiceImpl.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
public class KakaoServiceImpl implements KakaoService {
2323

2424
private final TokenProvider tokenProvider;
25-
private final UserServiceImpl userServiceImpl;
2625
private final UserRepository userRepository;
2726
private final RedisService redisService;
2827

@@ -70,7 +69,7 @@ public KakaoUserInfoResponse getUserInfo(String accessToken) {
7069
}
7170

7271
public LoginResponse handleUserLogin(KakaoUserInfoResponse kakaoUserInfoResponse) {
73-
User existingUser = userServiceImpl.findByLoginId(kakaoUserInfoResponse.getId());
72+
User existingUser = userRepository.findByLoginId(kakaoUserInfoResponse.getId()).orElse(null);
7473
String accessToken;
7574

7675
if (existingUser != null) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.memesphere.domain.user.service;
2+
3+
import com.memesphere.domain.user.dto.response.EmailResponse;
4+
5+
public interface MailService {
6+
EmailResponse createMail(String tmpPassword, String memberEmail);
7+
void sendMail(EmailResponse email);
8+
}

0 commit comments

Comments
 (0)