Skip to content

Commit a7162ee

Browse files
authored
Merge pull request #63 from Dalguring/feature/change-password
Feature/change password
2 parents 8908160 + a910fcd commit a7162ee

File tree

7 files changed

+291
-114
lines changed

7 files changed

+291
-114
lines changed

src/main/java/com/rentify/rentify_api/rental/service/RentalService.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,15 @@
1515
import com.rentify.rentify_api.user.entity.User;
1616
import com.rentify.rentify_api.user.exception.UserNotFoundException;
1717
import com.rentify.rentify_api.user.repository.UserRepository;
18+
import java.time.LocalDate;
19+
import java.time.temporal.ChronoUnit;
20+
import java.util.List;
1821
import lombok.RequiredArgsConstructor;
1922
import org.springframework.data.domain.Page;
2023
import org.springframework.data.domain.Pageable;
2124
import org.springframework.stereotype.Service;
2225
import org.springframework.transaction.annotation.Transactional;
2326

24-
import java.time.LocalDate;
25-
import java.time.temporal.ChronoUnit;
26-
import java.util.List;
27-
2827
@Service
2928
@RequiredArgsConstructor
3029
@Transactional(readOnly = true)
@@ -198,21 +197,18 @@ public RentalResponse cancelRental(Long userId, Long rentalId) {
198197
// 내가 빌리는 대여 목록
199198
@Transactional(readOnly = true)
200199
public Page<RentalResponse> getMyBorrowedRentals(Long userId, Pageable pageable) {
201-
Page<RentalResponse> rentals = rentalRepository.findByUserId(userId, pageable);
202-
return rentals;
200+
return rentalRepository.findByUserId(userId, pageable);
203201
}
204202

205203
// 내가 빌려준 대여 목록
206204
@Transactional(readOnly = true)
207205
public Page<RentalResponse> getMyLendedRentals(Long userId, Pageable pageable) {
208-
Page<RentalResponse> rentals = rentalRepository.findByPostOwnerId(userId, pageable);
209-
return rentals;
206+
return rentalRepository.findByPostOwnerId(userId, pageable);
210207
}
211208

212209
// 나의 모든 대여 목록
213210
@Transactional(readOnly = true)
214211
public Page<RentalResponse> getMyAllRentals(Long userId, Pageable pageable) {
215-
Page<RentalResponse> rentals = rentalRepository.findByUserIdOrPostOwnerId(userId, pageable);
216-
return rentals;
212+
return rentalRepository.findByUserIdOrPostOwnerId(userId, pageable);
217213
}
218214
}

src/main/java/com/rentify/rentify_api/user/controller/UserApiDocs.java

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.rentify.rentify_api.rental.dto.RentalResponse;
55
import com.rentify.rentify_api.user.dto.CreateUserRequest;
66
import com.rentify.rentify_api.user.dto.LoginRequest;
7+
import com.rentify.rentify_api.user.dto.PasswordUpdateRequest;
78
import io.swagger.v3.oas.annotations.Operation;
89
import io.swagger.v3.oas.annotations.Parameter;
910
import io.swagger.v3.oas.annotations.Parameters;
@@ -22,11 +23,11 @@
2223
import org.springdoc.core.annotations.ParameterObject;
2324
import org.springframework.data.domain.Page;
2425
import org.springframework.data.domain.Pageable;
25-
import org.springframework.data.domain.Sort;
2626
import org.springframework.http.HttpHeaders;
2727
import org.springframework.http.ResponseEntity;
2828
import org.springframework.security.core.annotation.AuthenticationPrincipal;
2929
import org.springframework.web.bind.annotation.GetMapping;
30+
import org.springframework.web.bind.annotation.PatchMapping;
3031
import org.springframework.web.bind.annotation.PostMapping;
3132
import org.springframework.web.bind.annotation.RequestHeader;
3233
import org.springframework.web.bind.annotation.RequestParam;
@@ -409,10 +410,64 @@ ResponseEntity<com.rentify.rentify_api.common.response.ApiResponse<Page<RentalRe
409410
@Parameter(
410411
name = "role",
411412
description = "조회 역할 필터 (예: LENDER(빌려준 내역), BORROWER(빌린 내역))",
412-
example = "BORROWER",
413-
required = false
413+
example = "BORROWER"
414414
)
415415
@RequestParam(required = false) String role,
416416
@ParameterObject Pageable pageable
417417
);
418+
419+
@Operation(summary = "패스워드 변경", description = "사용자의 패스워드를 변경합니다.")
420+
@ApiResponses(value = {
421+
@ApiResponse(
422+
responseCode = "200",
423+
description = "패스워드 변경 성공",
424+
content = @Content(
425+
mediaType = "application/json",
426+
examples = @ExampleObject(
427+
value = "{\"success\": true, \"code\": \"200\", \"message\": \"패스워드 변경 성공\", \"data\": null}"
428+
)
429+
)
430+
),
431+
@ApiResponse(
432+
responseCode = "400",
433+
description = "동일한 패스워드로 변경 요청",
434+
content = @Content(
435+
mediaType = "application/json",
436+
examples = @ExampleObject(
437+
value = "{\"success\": false, \"code\": \"401\", \"message\": \"기존과 동일한 비밀번호로 변경할 수 없습니다.\", \"data\": null}"
438+
)
439+
)
440+
),
441+
@ApiResponse(
442+
responseCode = "401",
443+
description = "패스워드 인증 실패",
444+
content = @Content(
445+
mediaType = "application/json",
446+
examples = @ExampleObject(
447+
value = "{\"success\": false, \"code\": \"401\", \"message\": \"패스워드가 일치하지 않습니다.\", \"data\": null}"
448+
)
449+
)
450+
)
451+
})
452+
@PatchMapping("/me/password")
453+
ResponseEntity<com.rentify.rentify_api.common.response.ApiResponse<Void>> changePassword(
454+
@AuthenticationPrincipal Long userId,
455+
@RequestBody(
456+
description = "패스워드 변경 요청 데이터",
457+
required = true,
458+
content = @Content(
459+
mediaType = "application/json",
460+
schema = @Schema(implementation = PasswordUpdateRequest.class),
461+
examples = @ExampleObject(
462+
value = """
463+
{
464+
"currentPassword": "old_pass",
465+
"newPassword": "new_pass"
466+
}
467+
"""
468+
)
469+
)
470+
)
471+
@Valid @org.springframework.web.bind.annotation.RequestBody PasswordUpdateRequest request
472+
);
418473
}

src/main/java/com/rentify/rentify_api/user/controller/UserController.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.rentify.rentify_api.rental.dto.RentalResponse;
66
import com.rentify.rentify_api.user.dto.CreateUserRequest;
77
import com.rentify.rentify_api.user.dto.LoginRequest;
8+
import com.rentify.rentify_api.user.dto.PasswordUpdateRequest;
89
import com.rentify.rentify_api.user.dto.UserResponse;
910
import com.rentify.rentify_api.user.entity.LoginResponse;
1011
import com.rentify.rentify_api.user.service.UserService;
@@ -25,6 +26,7 @@
2526
import org.springframework.http.ResponseEntity;
2627
import org.springframework.security.core.annotation.AuthenticationPrincipal;
2728
import org.springframework.web.bind.annotation.GetMapping;
29+
import org.springframework.web.bind.annotation.PatchMapping;
2830
import org.springframework.web.bind.annotation.PathVariable;
2931
import org.springframework.web.bind.annotation.PostMapping;
3032
import org.springframework.web.bind.annotation.RequestBody;
@@ -136,4 +138,13 @@ public ResponseEntity<ApiResponse<Page<RentalResponse>>> getMyRentals(
136138
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, rentals));
137139
}
138140

141+
@Override
142+
@PatchMapping("/me/password")
143+
public ResponseEntity<ApiResponse<Void>> changePassword(
144+
@AuthenticationPrincipal Long userId,
145+
@Valid @RequestBody PasswordUpdateRequest request
146+
) {
147+
userService.changePassword(userId, request);
148+
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, "패스워드 변경 성공"));
149+
}
139150
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.rentify.rentify_api.user.dto;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
5+
public record PasswordUpdateRequest(
6+
@NotBlank String currentPassword,
7+
@NotBlank String newPassword
8+
) {}

src/main/java/com/rentify/rentify_api/user/entity/User.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ public class User {
3737
@Column(name = "email", nullable = false, length = 100, unique = true)
3838
private String email;
3939

40-
@Column(name = "password", nullable = false, length = 255)
40+
@Column(name = "password", nullable = false)
4141
private String password;
4242

43-
@Column(name = "address", length = 255)
43+
@Column(name = "address")
4444
private String address;
4545

4646
@Column(name = "bank", length = 20)
@@ -89,4 +89,8 @@ public void usePoint(int amount) {
8989
}
9090
this.point -= amount;
9191
}
92+
93+
public void updatePassword(String hashedPassword) {
94+
this.password = hashedPassword;
95+
}
9296
}

src/main/java/com/rentify/rentify_api/user/service/UserService.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.rentify.rentify_api.common.exception.AccountDeactivatedException;
44
import com.rentify.rentify_api.common.exception.IdempotencyException;
55
import com.rentify.rentify_api.common.exception.InvalidPasswordException;
6+
import com.rentify.rentify_api.common.exception.InvalidValueException;
67
import com.rentify.rentify_api.common.exception.NotFoundException;
78
import com.rentify.rentify_api.common.idempotency.IdempotencyKey;
89
import com.rentify.rentify_api.common.idempotency.IdempotencyKeyRepository;
@@ -15,6 +16,7 @@
1516
import com.rentify.rentify_api.rental.service.RentalService;
1617
import com.rentify.rentify_api.user.dto.CreateUserRequest;
1718
import com.rentify.rentify_api.user.dto.LoginRequest;
19+
import com.rentify.rentify_api.user.dto.PasswordUpdateRequest;
1820
import com.rentify.rentify_api.user.dto.UserResponse;
1921
import com.rentify.rentify_api.user.entity.LoginResponse;
2022
import com.rentify.rentify_api.user.entity.RefreshToken;
@@ -216,4 +218,20 @@ public Page<RentalResponse> getMyRentals(Long userId, String role, Pageable page
216218
default -> throw new IllegalArgumentException("Invalid role parameter. Use 'borrower' or 'lender'");
217219
};
218220
}
221+
222+
@Transactional
223+
public void changePassword(Long userId, PasswordUpdateRequest request) {
224+
User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new);
225+
226+
if (!passwordEncoder.matches(request.currentPassword(), user.getPassword())) {
227+
throw new InvalidPasswordException("패스워드가 일치하지 않습니다.");
228+
}
229+
230+
if (passwordEncoder.matches(request.newPassword(), user.getPassword())) {
231+
throw new InvalidValueException("기존과 동일한 비밀번호로 변경할 수 없습니다.");
232+
}
233+
234+
String hashedPassword = passwordEncoder.encode(request.newPassword());
235+
user.updatePassword(hashedPassword);
236+
}
219237
}

0 commit comments

Comments
 (0)