Skip to content
Open
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 @@ -39,9 +39,9 @@ public CalenderDateServiceResponse readCalenderDates(Member member, Long memberI
DatingDatesServiceResponse datingDates = datingReadService.readDatingDates(
member, coupleId, year, month);
ScheduleDatesServiceResponse myScheduleDates = scheduleReadService.readScheduleDates(
member, memberId, year, month);
memberId, year, month);
ScheduleDatesServiceResponse partnerScheduleDates = scheduleReadService.readScheduleDates(
member, partnerId, year, month);
partnerId, year, month);
AnniversaryDatesServiceResponse anniversaryDates = anniversaryReadService.readAnniversaryDates(
coupleId, year, month);
return CalenderDateServiceResponse.of(datingDates, myScheduleDates, partnerScheduleDates,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ public class ScheduleController {
private final ScheduleReadService scheduleReadService;

@PostMapping("/{member_id}/schedules")
public ApiResponse<Void> createSchedule(@PathVariable("member_id") Long memberId,
@Valid @RequestBody ScheduleRequest request) {
public ApiResponse<Void> createSchedule(@Valid @RequestBody ScheduleRequest request) {

Member loginMember = MemberThreadLocal.get();

scheduleService.createSchedule(loginMember, memberId, request.toScheduleServiceRequest());
scheduleService.createSchedule(loginMember, request.toScheduleServiceRequest());
return ApiResponse.ofSuccess();
}

Expand All @@ -47,11 +46,8 @@ public ApiResponse<ScheduleDatesResponse> readScheduleDates(
@RequestParam(value = "year", required = false) Integer year,
@RequestParam(value = "month", required = false) Integer month
) {

Member loginMember = MemberThreadLocal.get();

ScheduleDatesServiceResponse scheduleDatesServiceResponse = scheduleReadService
.readScheduleDates(loginMember, memberId, year, month);
.readScheduleDates(memberId, year, month);

return ApiResponse.ofSuccess(ScheduleDatesResponse.from(scheduleDatesServiceResponse));
}
Expand All @@ -63,33 +59,29 @@ public ApiResponse<ScheduleResponse> readSchedules(
@RequestParam(value = "month") Integer month,
@RequestParam(value = "day") Integer day
) {
final Member member = MemberThreadLocal.get();
ScheduleServiceResponse response = scheduleReadService.readSchedules(memberId, member, year,
ScheduleServiceResponse response = scheduleReadService.readSchedules(memberId, year,
month, day);
return ApiResponse.ofSuccess(ScheduleResponse.from(response));
}

@PutMapping("/{member_id}/schedules/{schedule_id}")
public ApiResponse<Void> updateSchedule(
@PathVariable("member_id") Long memberId,
@PathVariable("schedule_id") Long scheduleId,
@Valid @RequestBody ScheduleUpdateRequest request,
@RequestParam(value = "updateRepeat", defaultValue = "false") Boolean updateRepeat
) {
Member member = MemberThreadLocal.get();
scheduleService.updateSchedule(
memberId, scheduleId, request.toScheduleUpdateServiceRequest(), member, updateRepeat);
scheduleId, request.toScheduleUpdateServiceRequest(), member, updateRepeat);
return ApiResponse.ofSuccess();
}

@DeleteMapping("/{member_id}/schedules/{schedule_id}")
public ApiResponse<Void> deleteSchedule(
@PathVariable("member_id") Long memberId,
@PathVariable("schedule_id") Long scheduleId,
@RequestParam(value = "deleteRepeat", defaultValue = "false") Boolean deleteRepeat
) {
Member member = MemberThreadLocal.get();
scheduleService.deleteSchedule(memberId, scheduleId, member, deleteRepeat);
scheduleService.deleteSchedule(memberId, deleteRepeat);
return ApiResponse.ofSuccess();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.dateplan.dateplan.domain.schedule.interceptor;

import com.dateplan.dateplan.domain.couple.service.CoupleReadService;
import com.dateplan.dateplan.domain.member.entity.Member;
import com.dateplan.dateplan.domain.schedule.entity.Schedule;
import com.dateplan.dateplan.domain.schedule.service.ScheduleReadService;
import com.dateplan.dateplan.global.auth.MemberThreadLocal;
import com.dateplan.dateplan.global.constant.Operation;
import com.dateplan.dateplan.global.constant.Resource;
import com.dateplan.dateplan.global.exception.auth.NoPermissionException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;

@Component
@RequiredArgsConstructor
public class ScheduleAuthInterceptor implements HandlerInterceptor {

private final ScheduleReadService scheduleReadService;
private final CoupleReadService coupleReadService;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
Map<String, String> map = (Map<String, String>) request.getAttribute(
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
String method = request.getMethod();

Member member = MemberThreadLocal.get();
String memberId = map.get("member_id");
String scheduleId = map.get("schedule_id");

if (memberId != null) {
if (method.equals("GET")) {
Long partnerId = coupleReadService.getPartnerId(member);
if (isNotSameMember(Long.valueOf(memberId), member.getId())
&& isNotSameMember(Long.valueOf(memberId), partnerId)) {
throwNoPermissionException(method);
}
} else {
if (isNotSameMember(Long.valueOf(memberId), member.getId())) {
throwNoPermissionException(method);
}
}
if (scheduleId != null) {
Schedule schedule = scheduleReadService.findScheduleByIdOrElseThrow(
Long.valueOf(scheduleId));
if (isNotScheduleOwner(Long.valueOf(memberId), schedule)) {
throwNoPermissionException(method);
}
}
}

return true;
}

private boolean isNotSameMember(Long requestId, Long memberId) {
return !Objects.equals(requestId, memberId);
}

private boolean isNotScheduleOwner(Long memberId, Schedule schedule) {
return !Objects.equals(memberId, schedule.getSchedulePattern().getMember().getId());
}

private void throwNoPermissionException(String method) {
Operation operation = switch (method) {
case "GET" -> Operation.READ;
case "POST" -> Operation.CREATE;
case "PUT" -> Operation.UPDATE;
default -> Operation.DELETE;
};
throw new NoPermissionException(Resource.SCHEDULE, operation);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
package com.dateplan.dateplan.domain.schedule.service;

import com.dateplan.dateplan.domain.couple.service.CoupleReadService;
import com.dateplan.dateplan.domain.member.entity.Member;
import com.dateplan.dateplan.domain.schedule.entity.Schedule;
import com.dateplan.dateplan.domain.schedule.repository.ScheduleQueryRepository;
import com.dateplan.dateplan.domain.schedule.repository.ScheduleRepository;
import com.dateplan.dateplan.domain.schedule.service.dto.response.ScheduleDatesServiceResponse;
import com.dateplan.dateplan.domain.schedule.service.dto.response.ScheduleServiceResponse;
import com.dateplan.dateplan.global.constant.Operation;
import com.dateplan.dateplan.global.constant.Resource;
import com.dateplan.dateplan.global.exception.auth.NoPermissionException;
import com.dateplan.dateplan.global.exception.schedule.ScheduleNotFoundException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
Expand All @@ -27,7 +21,6 @@
public class ScheduleReadService {

private final ScheduleQueryRepository scheduleQueryRepository;
private final CoupleReadService coupleReadService;
private final ScheduleRepository scheduleRepository;

public Optional<LocalDateTime> findMinStartDateTimeBySchedulePatternId(Long schedulePatternId) {
Expand All @@ -49,28 +42,20 @@ public Schedule findScheduleByIdOrElseThrow(Long id) {

public ScheduleServiceResponse readSchedules(
Long requestId,
Member member,
Integer year,
Integer month,
Integer day
) {
Long partnerId = coupleReadService.getPartnerId(member);
validatePermission(requestId, member.getId(), partnerId);
List<Schedule> schedules = scheduleQueryRepository.findByDateBetween(requestId,
year, month, day);
return ScheduleServiceResponse.from(schedules);
}

public ScheduleDatesServiceResponse readScheduleDates(
Member loginMember,
Long requestId,
Integer year,
Integer month
) {

Long partnerId = coupleReadService.getPartnerId(loginMember);
validatePermission(requestId, loginMember.getId(), partnerId);

List<Schedule> schedules = scheduleQueryRepository
.findByYearAndMonthOrderByDate(requestId, year, month);

Expand Down Expand Up @@ -110,15 +95,4 @@ private boolean checkDateRange(Integer year, Integer month, LocalDate date) {
}
return date.getYear() == year && date.getMonthValue() == month;
}

private void validatePermission(Long requestId, Long memberId, Long partnerId) {
if (isNotSameMember(requestId, memberId) && isNotSameMember(requestId, partnerId)) {
throw new NoPermissionException(Resource.MEMBER, Operation.READ);
}
}

private boolean isNotSameMember(Long requestId, Long memberId) {

return !(Objects.equals(requestId, memberId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,12 @@
import com.dateplan.dateplan.domain.schedule.repository.ScheduleRepository;
import com.dateplan.dateplan.domain.schedule.service.dto.request.ScheduleServiceRequest;
import com.dateplan.dateplan.domain.schedule.service.dto.request.ScheduleUpdateServiceRequest;
import com.dateplan.dateplan.global.constant.Operation;
import com.dateplan.dateplan.global.constant.RepeatRule;
import com.dateplan.dateplan.global.constant.Resource;
import com.dateplan.dateplan.global.exception.auth.NoPermissionException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -35,12 +31,7 @@ public class ScheduleService {
private final ScheduleReadService scheduleReadService;
private final ScheduleRepository scheduleRepository;

public void createSchedule(Member loginMember, Long memberId, ScheduleServiceRequest request) {

if (!isSameMember(memberId, loginMember.getId())) {
throw new NoPermissionException(Resource.MEMBER, Operation.CREATE);
}

public void createSchedule(Member loginMember, ScheduleServiceRequest request) {
SchedulePattern schedulePattern = request.toSchedulePatternEntity(loginMember);
schedulePatternRepository.save(schedulePattern);

Expand All @@ -50,22 +41,13 @@ public void createSchedule(Member loginMember, Long memberId, ScheduleServiceReq
}

public void updateSchedule(
Long memberId,
Long scheduleId,
ScheduleUpdateServiceRequest request,
Member loginMember,
Boolean updateRepeat
) {
if (!isSameMember(memberId, loginMember.getId())) {
throw new NoPermissionException(Resource.MEMBER, Operation.UPDATE);
}
Schedule schedule = scheduleReadService.findScheduleByIdOrElseThrow(scheduleId);

if (isNotScheduleOwner(loginMember.getId(),
schedule.getSchedulePattern().getMember().getId())) {
throw new NoPermissionException(Resource.SCHEDULE, Operation.UPDATE);
}

if (updateRepeat) {
updateRepeatSchedules(request, schedule);
return;
Expand Down Expand Up @@ -116,18 +98,9 @@ private void updateSingleSchedule(
originalSchedulePattern.updateDateTime(minStart.get(), maxStart.get());
}

public void deleteSchedule(Long memberId, Long scheduleId, Member loginMember,
Boolean deleteRepeat) {
if (!isSameMember(memberId, loginMember.getId())) {
throw new NoPermissionException(Resource.MEMBER, Operation.DELETE);
}
public void deleteSchedule(Long scheduleId, Boolean deleteRepeat) {
Schedule schedule = scheduleReadService.findScheduleByIdOrElseThrow(scheduleId);

if (isNotScheduleOwner(loginMember.getId(),
schedule.getSchedulePattern().getMember().getId())) {
throw new NoPermissionException(Resource.SCHEDULE, Operation.DELETE);
}

if (deleteRepeat) {
deleteRepeatSchedule(schedule);
return;
Expand Down Expand Up @@ -188,15 +161,6 @@ private boolean isBeforeOfRepeatEndDate(LocalDate repeatEndTime, LocalDateTime n
return !now.toLocalDate().isAfter(repeatEndTime);
}

private boolean isSameMember(Long memberId, Long loginMemberId) {

return Objects.equals(memberId, loginMemberId);
}

private boolean isNotScheduleOwner(Long memberId, Long scheduleOwnerId) {
return !Objects.equals(memberId, scheduleOwnerId);
}

private boolean checkSingleScheduleAndUpdate(
ScheduleUpdateServiceRequest request,
Schedule schedule
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dateplan.dateplan.global.config.web;

import com.dateplan.dateplan.domain.anniversary.interceptor.AnniversaryAuthInterceptor;
import com.dateplan.dateplan.domain.schedule.interceptor.ScheduleAuthInterceptor;
import com.dateplan.dateplan.global.interceptor.AuthInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
Expand All @@ -13,6 +14,7 @@ public class WebConfig implements WebMvcConfigurer {

private final AuthInterceptor authInterceptor;
private final AnniversaryAuthInterceptor anniversaryAuthInterceptor;
private final ScheduleAuthInterceptor scheduleAuthInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
Expand All @@ -24,5 +26,9 @@ public void addInterceptors(InterceptorRegistry registry) {
registry
.addInterceptor(anniversaryAuthInterceptor)
.addPathPatterns("/api/couples/**/anniversary/**");

registry
.addInterceptor(scheduleAuthInterceptor)
.addPathPatterns("/api/members/**/schedules/**");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.dateplan.dateplan.domain.member.service.MemberReadService;
import com.dateplan.dateplan.domain.member.service.MemberService;
import com.dateplan.dateplan.domain.schedule.controller.ScheduleController;
import com.dateplan.dateplan.domain.schedule.interceptor.ScheduleAuthInterceptor;
import com.dateplan.dateplan.domain.schedule.service.ScheduleReadService;
import com.dateplan.dateplan.domain.schedule.service.ScheduleService;
import com.dateplan.dateplan.domain.sms.service.SmsSendClient;
Expand Down Expand Up @@ -89,4 +90,7 @@ public abstract class ControllerTestSupport {

@MockBean
protected CalenderReadService calenderReadService;

@MockBean
protected ScheduleAuthInterceptor scheduleAuthInterceptor;
}
Loading