Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ public ResponseEntity<Void> deleteDevice(
@AuthDevice final DeviceIdentifier identifier,
@RequestBody final DeviceDeleteRequest request
) {
final DeviceDeleteInput input = DeviceDeleteInput.from(request.email(), identifier,
request.targetDeviceIdentifier());
final DeviceDeleteInput input = DeviceDeleteInput.from(identifier, request.targetDeviceIdentifier());
memberService.deleteDevice(input);
return ResponseEntity.noContent().build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
Expand All @@ -46,12 +45,8 @@ public ResponseEntity<MemberSaveResponse> saveMember(@RequestBody final MemberSa
}

@GetMapping
public ResponseEntity<MemberFindResponse> findAllMemberDevices(
@RequestParam(name = "email") final String email,
@AuthDevice final DeviceIdentifier identifier
) {

final MemberFindInput input = MemberFindInput.from(email, identifier);
public ResponseEntity<MemberFindResponse> findAllMemberDevices(@AuthDevice final DeviceIdentifier identifier) {
final MemberFindInput input = MemberFindInput.from(identifier);
final MemberFindOutput output = memberService.findAllMemberDevices(input);
final MemberFindResponse response = MemberFindResponse.from(output);
return ResponseEntity.ok(response);
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/com/recyclestudy/member/service/MemberService.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ public MemberSaveOutput saveDevice(final MemberSaveInput input) {

@Transactional(readOnly = true)
public MemberFindOutput findAllMemberDevices(final MemberFindInput input) {
final List<Device> devices = deviceRepository.findAllByMemberEmail(input.email());
return MemberFindOutput.of(input.email(), devices);
final Member member = memberRepository.findByIdentifier(input.deviceIdentifier())
.orElseThrow(() -> new UnauthorizedException("인증되지 않은 디바이스입니다"));

final List<Device> devices = deviceRepository.findAllByMemberEmail(member.getEmail());
return MemberFindOutput.of(member.getEmail(), devices);
}

@Transactional(readOnly = true)
Expand All @@ -69,11 +72,11 @@ public void authenticateDevice(final Email email, final DeviceIdentifier deviceI
checkExistedMember(email);

final Device device = deviceRepository.findByIdentifier(deviceIdentifier)
.orElseThrow(() -> new NotFoundException("존재하지 않는 디바이스 아이디입니다: %s"
.orElseThrow(() -> new NotFoundException("존재하지 않는 디바이스 식별자입니다: %s"
.formatted(deviceIdentifier.getValue())));

if (device.isActive()) {
throw new BadRequestException("이미 인증되었습니다");
throw new BadRequestException("이미 인증된 디바이스입니다");
}

device.verifyOwner(email);
Expand All @@ -83,7 +86,18 @@ public void authenticateDevice(final Email email, final DeviceIdentifier deviceI

@Transactional
public void deleteDevice(final DeviceDeleteInput input) {
deviceRepository.deleteByIdentifier(input.targetDeviceIdentifier());
final Member requestMember = memberRepository.findByIdentifier(input.deviceIdentifier())
.orElseThrow(() -> new UnauthorizedException("유효하지 않은 디바이스입니다"));

final Device targetDevice = deviceRepository.findByIdentifier(input.targetDeviceIdentifier())
.orElseThrow(() -> new NotFoundException("존재하지 않는 디바이스입니다: %s"
.formatted(input.targetDeviceIdentifier().getValue())));

if (!targetDevice.getMember().hasEmail(requestMember.getEmail())) {
throw new NotFoundException("존재하지 않는 디바이스입니다: %s".formatted(input.targetDeviceIdentifier().getValue()));
}

deviceRepository.delete(targetDevice);
log.info("[DEVICE_DELETED] 디바이스 삭제 성공: {}", input.targetDeviceIdentifier());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package com.recyclestudy.member.service.input;

import com.recyclestudy.member.domain.DeviceIdentifier;
import com.recyclestudy.member.domain.Email;

public record DeviceDeleteInput(Email email, DeviceIdentifier deviceIdentifier,
DeviceIdentifier targetDeviceIdentifier) {
public record DeviceDeleteInput(DeviceIdentifier deviceIdentifier, DeviceIdentifier targetDeviceIdentifier) {

public static DeviceDeleteInput from(
final String emailValue,
final DeviceIdentifier identifier,
final String targetIdentifier
) {
final Email email = Email.from(emailValue);
final DeviceIdentifier targetDeviceIdentifier = DeviceIdentifier.from(targetIdentifier);
return new DeviceDeleteInput(email, identifier, targetDeviceIdentifier);
return new DeviceDeleteInput(identifier, targetDeviceIdentifier);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.recyclestudy.member.service.input;

import com.recyclestudy.member.domain.DeviceIdentifier;
import com.recyclestudy.member.domain.Email;

public record MemberFindInput(Email email, DeviceIdentifier deviceIdentifier) {
public record MemberFindInput(DeviceIdentifier deviceIdentifier) {

public static MemberFindInput from(final String emailValue, final DeviceIdentifier identifier) {
final Email email = Email.from(emailValue);
return new MemberFindInput(email, identifier);
public static MemberFindInput from(final DeviceIdentifier identifier) {
return new MemberFindInput(identifier);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/recyclestudy/review/service/ReviewService.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.recyclestudy.review.service;

import com.recyclestudy.common.BaseEntity;
import com.recyclestudy.cycle.domain.CycleOption;
import com.recyclestudy.cycle.domain.selection.CustomCycleSelection;
import com.recyclestudy.cycle.domain.selection.CycleSelection;
import com.recyclestudy.cycle.repository.CycleOptionRepository;
import com.recyclestudy.cycle.service.resolver.CycleSelectionResolverRegistry;
import com.recyclestudy.exception.NotFoundException;
import com.recyclestudy.exception.UnauthorizedException;
import com.recyclestudy.member.domain.Member;
import com.recyclestudy.member.repository.MemberRepository;
Expand Down Expand Up @@ -33,6 +37,7 @@ public class ReviewService {
private final ReviewRepository reviewRepository;
private final ReviewCycleRepository reviewCycleRepository;
private final MemberRepository memberRepository;
private final CycleOptionRepository cycleOptionRepository;
private final CycleSelectionResolverRegistry cycleSelectionResolverRegistry;
private final NotificationHistoryRepository notificationHistoryRepository;
private final Clock clock;
Expand All @@ -46,6 +51,7 @@ public ReviewSaveOutput saveReview(final ReviewSaveInput input) {
final Review savedReview = reviewRepository.save(review);
log.info("[REVIEW_SAVED] 복습 주제 저장 성공: reviewId={}", savedReview.getId());

validateCycleSelectionOwnership(input.cycle(), member);
final List<LocalDateTime> scheduledAts = calculateScheduledAts(input.cycle(), member);

final List<ReviewCycle> reviewCycles = scheduledAts.stream()
Expand Down Expand Up @@ -98,4 +104,17 @@ private void savePendingNotificationHistory(final List<ReviewCycle> savedReviewC
log.info("[NOTIFY_HIST_SAVED] 전송 현황 등록 성공: status={}, notificationHistoryId={}",
NotificationStatus.PENDING, savedNotificationHistories.stream().map(BaseEntity::getId).toList());
}

private void validateCycleSelectionOwnership(final CycleSelection cycleSelection, final Member member) {
if (!(cycleSelection instanceof CustomCycleSelection(Long id))) {
return;
}

final CycleOption cycleOption = cycleOptionRepository.findById(id)
.orElseThrow(() -> new NotFoundException("존재하지 않는 복습 주기입니다"));

if (!cycleOption.isOwner(member)) {
throw new NotFoundException("존재하지 않는 복습 주기입니다");
}
}
}
Loading
Loading