Skip to content

Commit 77d7279

Browse files
authored
3차 배포 (#95)
2 parents 3435fd6 + 6200f76 commit 77d7279

18 files changed

Lines changed: 400 additions & 14 deletions

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ dependencies {
6565

6666
// oauth2
6767
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
68+
69+
// mail
70+
implementation 'org.springframework.boot:spring-boot-starter-mail'
71+
implementation 'org.springframework:spring-context-support'
6872
}
6973

7074
tasks.named('test') {

src/main/java/umc/codeplay/apiPayLoad/code/status/ErrorStatus.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ public enum ErrorStatus implements BaseErrorCode {
3333

3434
MUSIC_NOT_FOUND(HttpStatus.BAD_REQUEST, "MUSIC400", "음원을 찾을 수 없습니다."),
3535

36-
LIKE_NOT_FOUND(HttpStatus.BAD_REQUEST, "LIKE400", "해당 좋아요를 찾을 수 없습니다.");
36+
LIKE_NOT_FOUND(HttpStatus.BAD_REQUEST, "LIKE400", "해당 좋아요를 찾을 수 없습니다."),
37+
38+
EMAIL_SEND_ERROR(HttpStatus.BAD_REQUEST, "EMAIL400", "메일 발송에 실패하였습니다."),
39+
EMAIL_CODE_ERROR(HttpStatus.BAD_REQUEST, "EMAIL401", "유효한 코드가 아닙니다.");
3740

3841
private final HttpStatus httpStatus;
3942
private final String code;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package umc.codeplay.config.security;
2+
3+
import java.util.Collection;
4+
5+
import org.springframework.security.core.GrantedAuthority;
6+
import org.springframework.security.core.userdetails.UserDetails;
7+
8+
import lombok.Getter;
9+
import lombok.RequiredArgsConstructor;
10+
11+
@Getter
12+
@RequiredArgsConstructor
13+
public class CustomUserDetails implements UserDetails {
14+
private final String email;
15+
private final String password;
16+
private final Collection<? extends GrantedAuthority> authorities;
17+
18+
@Override
19+
public String getUsername() {
20+
return email; // username대신 email 사용
21+
}
22+
23+
@Override
24+
public String getPassword() {
25+
return password;
26+
}
27+
28+
@Override
29+
public Collection<? extends GrantedAuthority> getAuthorities() {
30+
return authorities;
31+
}
32+
33+
@Override
34+
public boolean isAccountNonExpired() {
35+
return true;
36+
}
37+
38+
@Override
39+
public boolean isAccountNonLocked() {
40+
return true;
41+
}
42+
43+
@Override
44+
public boolean isCredentialsNonExpired() {
45+
return true;
46+
}
47+
48+
@Override
49+
public boolean isEnabled() {
50+
return true;
51+
}
52+
}

src/main/java/umc/codeplay/config/security/CustomUserDetailsService.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package umc.codeplay.config.security;
22

3+
import java.util.Collections;
4+
5+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
36
import org.springframework.security.core.userdetails.UserDetails;
47
import org.springframework.security.core.userdetails.UserDetailsService;
58
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -19,15 +22,21 @@ public class CustomUserDetailsService implements UserDetailsService {
1922
private final MemberRepository memberRepository;
2023

2124
@Override
22-
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
25+
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
2326
Member member =
2427
memberRepository
25-
.findByEmail(username)
28+
.findByEmail(email)
2629
.orElseThrow(() -> new GeneralHandler(ErrorStatus.MEMBER_NOT_FOUND));
2730

28-
return org.springframework.security.core.userdetails.User.withUsername(member.getEmail())
29-
.password(member.getPassword())
30-
.roles(member.getRole().name())
31-
.build();
31+
// return
32+
// org.springframework.security.core.userdetails.User.withUsername(member.getEmail())
33+
// .password(member.getPassword())
34+
// .roles(member.getRole().name())
35+
// .build();
36+
37+
return new CustomUserDetails(
38+
member.getEmail(),
39+
member.getPassword(),
40+
Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
3241
}
3342
}

src/main/java/umc/codeplay/controller/AuthController.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Collection;
44
import java.util.stream.Collectors;
5+
import jakarta.mail.MessagingException;
56
import jakarta.validation.constraints.NotBlank;
67
import jakarta.validation.constraints.NotNull;
78

@@ -24,6 +25,7 @@
2425
import umc.codeplay.dto.MemberRequestDTO;
2526
import umc.codeplay.dto.MemberResponseDTO;
2627
import umc.codeplay.jwt.JwtUtil;
28+
import umc.codeplay.service.EmailService;
2729
import umc.codeplay.service.MemberService;
2830

2931
@RestController
@@ -35,6 +37,7 @@ public class AuthController {
3537
private final AuthenticationManager authenticationManager;
3638
private final JwtUtil jwtUtil;
3739
private final MemberService memberService;
40+
private final EmailService emailService;
3841

3942
@PostMapping("/login")
4043
public ApiResponse<MemberResponseDTO.LoginResultDTO> login(
@@ -104,4 +107,25 @@ public ApiResponse<MemberResponseDTO.LoginResultDTO> refresh(
104107
throw new GeneralHandler(ErrorStatus.INVALID_REFRESH_TOKEN);
105108
}
106109
}
110+
111+
// 비밀번호 찾기 및 변경. 이메일 인증
112+
@PostMapping("/password/reset/request")
113+
public ApiResponse<String> resetPasswordRequest(
114+
@RequestBody MemberRequestDTO.ResetPasswordDTO request) throws MessagingException {
115+
emailService.sendCode(request.getEmail());
116+
return ApiResponse.onSuccess("메일로 인증번호가 전송되었습니다.");
117+
}
118+
119+
// 비밀번호 찾기 및 변경. 인증 코드 확인
120+
@PostMapping("/password/reset/verify")
121+
public ApiResponse<String> resetPasswordVerify(
122+
@RequestBody MemberRequestDTO.CheckVerificationCodeDTO request) {
123+
boolean isValid = emailService.verifyCode(request.getEmail(), request.getCode());
124+
if (isValid) {
125+
return ApiResponse.onSuccess("인증에 성공하였습니다.");
126+
// 이후에 비밀번호 변경 페이지 연결해 주어야 함.
127+
} else {
128+
throw new GeneralHandler(ErrorStatus.EMAIL_CODE_ERROR);
129+
}
130+
}
107131
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package umc.codeplay.controller;
2+
3+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
4+
import org.springframework.web.bind.annotation.*;
5+
6+
import lombok.RequiredArgsConstructor;
7+
8+
import umc.codeplay.apiPayLoad.ApiResponse;
9+
import umc.codeplay.config.security.CustomUserDetails;
10+
import umc.codeplay.converter.MemberConverter;
11+
import umc.codeplay.domain.Member;
12+
import umc.codeplay.dto.MemberRequestDTO;
13+
import umc.codeplay.dto.MemberResponseDTO;
14+
import umc.codeplay.service.MemberService;
15+
16+
@RestController
17+
@RequestMapping("/member")
18+
@RequiredArgsConstructor
19+
public class MemberController {
20+
21+
private final MemberService memberService;
22+
private final MemberConverter memberConverter;
23+
24+
@PutMapping("/update")
25+
public ApiResponse<MemberResponseDTO.UpdateResultDTO> updateMember(
26+
@AuthenticationPrincipal
27+
CustomUserDetails
28+
userDetails, // 현재 로그인된 사용자 정보, email로 조회하기 위해 customUserDetails 사용
29+
@RequestBody MemberRequestDTO.UpdateMemberDTO requestDto) {
30+
31+
Member updatedMember = memberService.updateMember(userDetails.getUsername(), requestDto);
32+
MemberResponseDTO.UpdateResultDTO responseDto =
33+
memberConverter.toUpdateResultDTO(updatedMember);
34+
35+
return ApiResponse.onSuccess(responseDto);
36+
}
37+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package umc.codeplay.controller;
2+
3+
import org.springframework.web.bind.annotation.DeleteMapping;
4+
import org.springframework.web.bind.annotation.PathVariable;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
import org.springframework.web.bind.annotation.RestController;
7+
8+
import lombok.RequiredArgsConstructor;
9+
10+
import umc.codeplay.apiPayLoad.ApiResponse;
11+
import umc.codeplay.service.MusicService;
12+
13+
@RestController
14+
@RequiredArgsConstructor
15+
@RequestMapping("/music")
16+
public class MusicController {
17+
18+
private final MusicService musicService;
19+
20+
@DeleteMapping("/{musicId}")
21+
public ApiResponse<Long> delete(@PathVariable Long musicId) {
22+
23+
musicService.deleteMusic(musicId);
24+
return ApiResponse.onSuccess(musicId);
25+
}
26+
}

src/main/java/umc/codeplay/converter/MemberConverter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package umc.codeplay.converter;
22

3+
import org.springframework.stereotype.Component;
4+
35
import umc.codeplay.domain.Member;
46
import umc.codeplay.domain.enums.Role;
57
import umc.codeplay.domain.enums.SocialStatus;
68
import umc.codeplay.dto.MemberRequestDTO;
79
import umc.codeplay.dto.MemberResponseDTO;
810

11+
@Component
912
public class MemberConverter {
1013

1114
public static Member toMember(MemberRequestDTO.JoinDto request) {
@@ -32,4 +35,11 @@ public static MemberResponseDTO.LoginResultDTO toLoginResultDTO(
3235
.refreshToken(refreshToken)
3336
.build();
3437
}
38+
39+
public static MemberResponseDTO.UpdateResultDTO toUpdateResultDTO(Member member) {
40+
return MemberResponseDTO.UpdateResultDTO.builder()
41+
.email(member.getEmail())
42+
.profileUrl(member.getProfileUrl())
43+
.build();
44+
}
3545
}
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
package umc.codeplay.domain.enums;
22

33
public enum Role {
4-
ADMIN,
5-
USER
4+
USER("ROLE_USER"),
5+
ADMIN("ROLE_ADMIN");
6+
7+
private final String role;
8+
9+
Role(String role) {
10+
this.role = role;
11+
}
12+
13+
public String getRole() {
14+
return role;
15+
}
616
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package umc.codeplay.dto;
2+
3+
import java.time.LocalDateTime;
4+
5+
import lombok.AllArgsConstructor;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
9+
public class EmailCodeDTO {
10+
11+
@Getter
12+
@NoArgsConstructor
13+
@AllArgsConstructor
14+
public static class VerificationCode {
15+
String code;
16+
LocalDateTime expires;
17+
}
18+
}

0 commit comments

Comments
 (0)