Skip to content

Commit

Permalink
Feat/authentication - 자원 인가 검증 (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
SHEOMM authored Sep 8, 2024
1 parent 9f46a36 commit f101d13
Show file tree
Hide file tree
Showing 27 changed files with 253 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import com.waruru.areyouhere.attendance.dto.request.AuthCodeDeactivationRequestDto;
import com.waruru.areyouhere.attendance.dto.request.AuthCodeRequestDto;
import com.waruru.areyouhere.active.service.ActiveSessionService;
import com.waruru.areyouhere.common.annotation.Login;
import com.waruru.areyouhere.common.annotation.LoginRequired;
import com.waruru.areyouhere.manager.domain.entity.Manager;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -23,14 +26,19 @@ public class ActiveSessionController {


@PostMapping
public ResponseEntity<String> activate(@RequestBody AuthCodeRequestDto authCodeRequestDto) {
@LoginRequired
public ResponseEntity<String> activate(
@Login Manager manager,
@RequestBody AuthCodeRequestDto authCodeRequestDto) {
Long sessionId = authCodeRequestDto.getSessionId();
Long courseId = authCodeRequestDto.getCourseId();
return ResponseEntity.ok(activeSessionService.activate(sessionId, courseId));
return ResponseEntity.ok(activeSessionService.activate(manager.getId(), sessionId, courseId));
}

@PostMapping("/deactivate")
@LoginRequired
public ResponseEntity<HttpStatus> deactivate(
@Login Manager manager,
@RequestBody AuthCodeDeactivationRequestDto authCodeDeactivationRequestDto) {
Long sessionId = authCodeDeactivationRequestDto.getSessionId();
Long courseId = authCodeDeactivationRequestDto.getCourseId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ public interface ActiveSessionService {

public void deactivate(String authCode, Long sessionId, Long courseId);

public String activate(Long sessionId, Long courseId);
public String activate(Long managerId, Long sessionId, Long courseId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ public class ActiveSessionServiceImpl implements ActiveSessionService {

@Override
@Transactional
public String activate(Long sessionId, Long courseId) {
Course course = courseService.get(courseId);
Session session = sessionQueryService.get(sessionId);
public String activate(Long managerId, Long sessionId, Long courseId) {
Course course = courseService.get(managerId, courseId);
Session session = sessionQueryService.get(managerId, sessionId);
LocalDateTime currentTime = LocalDateTime.now(ZoneId.of("Asia/Seoul"));
sessionCommandService.setAuthCodeDate(session, currentTime);
return activeAttendanceService.activate(course, session, currentTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import com.waruru.areyouhere.attendance.service.AttendanceService;
import com.waruru.areyouhere.attendance.service.dto.CurrentSessionAttendCount;
import com.waruru.areyouhere.attendance.service.dto.CurrentSessionAttendeeAttendance;
import com.waruru.areyouhere.common.annotation.Login;
import com.waruru.areyouhere.common.annotation.LoginRequired;
import com.waruru.areyouhere.manager.domain.entity.Manager;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;
Expand Down Expand Up @@ -67,11 +69,11 @@ public ResponseEntity<AttendResponseDto> attend(HttpServletRequest request,

@LoginRequired
@PutMapping
ResponseEntity<HttpStatus> update(@RequestBody UpdateAttendanceRequestDto updateAttendanceRequestDto) {
Long sessionId = updateAttendanceRequestDto.getSessionId();
ResponseEntity<HttpStatus> update(
@Login Manager manager,
@RequestBody UpdateAttendanceRequestDto updateAttendanceRequestDto) {
List<UpdateAttendance> updateAttendance = updateAttendanceRequestDto.getUpdateAttendances();

attendanceService.updateAllStatuses(sessionId, updateAttendance);
attendanceService.updateAllStatuses(manager.getId(), updateAttendance);
return ResponseEntity.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.waruru.areyouhere.attendance.domain.entity.Attendance;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -22,4 +23,16 @@ public interface AttendanceRepository extends JpaRepository<Attendance, Long>{
@Modifying(clearAutomatically = true)
@Query("delete from attendance a where a.session.id in :ids")
public void deleteAllBySessionIds(@Param("ids") List<Long> ids);


// TODO: 이런 쿼리를 사용하는게 맞는지에 대한 의문. -> 일단 사용하지 맙시다.
@Query(nativeQuery = true, value = "SELECT case when EXISTS"
+ "(SELECT 1 FROM course WHERE course.id = "
+ "(SELECT course_id FROM session WHERE id = "
+ "(SELECT session_id FROM attendance WHERE id = :attendanceId)) and manager_id = :managerId)"
+ "then 'true' else 'false' end")
public boolean isAttendanceOwnByManagerId(@Param("managerId") Long managerId, @Param("attendanceId") Long attendanceId);

@Query(nativeQuery = true, value = "SELECT session_id FROM attendance WHERE id = :attendanceId")
public Optional<Long> getSessionIdByAttendanceId(@Param("attendanceId") Long attendanceId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public interface AttendanceService {

public AttendResponseDto attend(String attendeeName, String authCode, Long attendeeId);

public void updateAllStatuses(Long sessionId, List<UpdateAttendance> updateAttendances);
public void updateAllStatuses(Long managerId, List<UpdateAttendance> updateAttendances);

public CurrentSessionAttendCount getCurrentSessionAttendCount(Long sessionId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import com.waruru.areyouhere.attendance.service.rdb.AttendanceRDBService;
import com.waruru.areyouhere.active.service.ActiveAttendanceService;
import com.waruru.areyouhere.attendee.service.dto.AttendeeInfo;
import com.waruru.areyouhere.session.domain.repository.SessionRepository;
import com.waruru.areyouhere.session.service.dto.AuthCodeInfo;
import com.waruru.areyouhere.session.service.query.SessionQueryService;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
Expand All @@ -23,6 +25,7 @@
public class AttendanceServiceImpl implements AttendanceService {
private final AttendanceRDBService attendanceRDBService;
private final ActiveAttendanceService activeAttendanceService;
private final SessionQueryService sessionQueryService;

@Override
@Transactional
Expand Down Expand Up @@ -53,8 +56,9 @@ public AttendResponseDto attend(String attendeeName, String authCode, Long atten

@Override
@Transactional
public void updateAllStatuses(Long sessionId, List<UpdateAttendance> updateAttendances) {
attendanceRDBService.setAttendanceStatuses(sessionId, updateAttendances);
public void updateAllStatuses(Long managerId, List<UpdateAttendance> updateAttendances) {
updateAttendances.forEach(updateAttendance -> throwIfAttendanceNotOwnByManager(managerId, updateAttendance.getAttendanceId()));
attendanceRDBService.setAttendanceStatuses(updateAttendances);
}

@Override
Expand All @@ -72,6 +76,11 @@ public CurrentSessionAttendeeAttendance getCurrentSessionAttendeesAndAbsentees(S
return activeAttendanceService.getCurrentSessionAttendees(authCode);
}

private void throwIfAttendanceNotOwnByManager(Long managerId, Long attendanceId){
long sessionId = attendanceRDBService.getSessionId(attendanceId);
sessionQueryService.throwIfSessionAuthorizationFail(managerId, sessionId);
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
public interface AttendanceRDBService {
public void setAttendancesAfterDeactivate(long courseId, long sessionId, CurrentSessionAttendanceInfo currentSessionAttendanceInfo);

public void setAttendanceStatuses(Long sessionId, List<UpdateAttendance> updateAttendances);
public void setAttendanceStatuses(List<UpdateAttendance> updateAttendances);

public long getSessionId(Long attendanceId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.waruru.areyouhere.attendance.service.dto.CurrentSessionAttendeeAttendance;
import com.waruru.areyouhere.attendee.domain.entity.Attendee;
import com.waruru.areyouhere.attendee.domain.repository.AttendeeRepository;
import com.waruru.areyouhere.manager.exception.UnAuthenticatedException;
import com.waruru.areyouhere.session.domain.entity.Session;
import com.waruru.areyouhere.session.domain.repository.SessionRepository;
import com.waruru.areyouhere.session.exception.SessionIdNotFoundException;
Expand All @@ -34,11 +35,9 @@ public class AttendanceRDBServiceImpl implements AttendanceRDBService {
private final AttendanceRepository attendanceRepository;
private final AttendanceBatchRepository attendanceBatchRepository;


@Override
public void setAttendancesAfterDeactivate(long courseId, long sessionId,
CurrentSessionAttendanceInfo currentSessionAttendanceInfo) {

LocalDateTime absentTime = LocalDateTime.now();
List<AttendeeRedisData> attendees = new LinkedList<>();
List<AttendeeRedisData> absentees = new LinkedList<>();
Expand All @@ -58,7 +57,8 @@ public void setAttendancesAfterDeactivate(long courseId, long sessionId,
}


public void setAttendanceStatuses(Long sessionId, List<UpdateAttendance> updateAttendances) {
public void setAttendanceStatuses(List<UpdateAttendance> updateAttendances) {

List<Attendance> attendancesToUpdate = updateAttendances.stream()
.map(updateAttendance -> {
Attendance attendance = attendanceRepository.findById(updateAttendance.getAttendanceId())
Expand All @@ -72,5 +72,10 @@ public void setAttendanceStatuses(Long sessionId, List<UpdateAttendance> updateA
attendanceRepository.saveAll(attendancesToUpdate);
}

@Override
public long getSessionId(Long attendanceId){
return attendanceRepository.getSessionIdByAttendanceId(attendanceId).orElseThrow();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import com.waruru.areyouhere.attendee.service.dto.ClassAttendees;
import com.waruru.areyouhere.attendee.service.dto.DuplicateAttendees;
import com.waruru.areyouhere.attendee.service.query.AttendeeQueryService;
import com.waruru.areyouhere.common.annotation.Login;
import com.waruru.areyouhere.common.annotation.LoginRequired;
import com.waruru.areyouhere.manager.domain.entity.Manager;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -36,8 +38,10 @@ public class AttendeeController {

@LoginRequired
@GetMapping
public ResponseEntity<ClassAttendeesResponseDto> getClassAttendees(@RequestParam("courseId") Long courseId) {
List<ClassAttendees> classAttendees = attendeeQueryService.getClassAttendeesIfExistsOrEmpty(courseId);
public ResponseEntity<ClassAttendeesResponseDto> getClassAttendees(
@Login Manager manager,
@RequestParam("courseId") Long courseId) {
List<ClassAttendees> classAttendees = attendeeQueryService.getClassAttendeesIfExistsOrEmpty(manager.getId(), courseId);

return ResponseEntity.ok(ClassAttendeesResponseDto.builder()
.classAttendees(classAttendees)
Expand All @@ -46,16 +50,22 @@ public ResponseEntity<ClassAttendeesResponseDto> getClassAttendees(@RequestParam

@LoginRequired
@PostMapping
public ResponseEntity<HttpStatus> create(@RequestBody NewAttendeesRequestDto newAttendeesRequestDto) {
attendeeCommandService.createAll(newAttendeesRequestDto.getCourseId(),
public ResponseEntity<HttpStatus> create(
@Login Manager manager,
@RequestBody NewAttendeesRequestDto newAttendeesRequestDto) {
attendeeCommandService.createAll(
manager.getId(),
newAttendeesRequestDto.getCourseId(),
newAttendeesRequestDto.getNewAttendees());
return ResponseEntity.ok().build();
}

@LoginRequired
@PostMapping("/delete")
public ResponseEntity<HttpStatus> delete(@RequestBody DeleteAttendeesRequestDto deleteAttendeesRequestDto) {
attendeeCommandService.deleteAll(deleteAttendeesRequestDto.getAttendeeIds());
public ResponseEntity<HttpStatus> delete(
@Login Manager manager,
@RequestBody DeleteAttendeesRequestDto deleteAttendeesRequestDto) {
attendeeCommandService.deleteAll(manager.getId(), deleteAttendeesRequestDto.getAttendeeIds());
return ResponseEntity.ok().build();
}

Expand All @@ -75,8 +85,12 @@ public ResponseEntity<AttendeeDetailDto> getAttendeeDetail(@RequestParam("attend

@LoginRequired
@PutMapping
public ResponseEntity<HttpStatus> update(@RequestBody UpdateAttendeesRequestDto UpdateAttendeesRequestDto) {
attendeeCommandService.updateAll(UpdateAttendeesRequestDto.getCourseId(),
public ResponseEntity<HttpStatus> update(
@Login Manager manager,
@RequestBody UpdateAttendeesRequestDto UpdateAttendeesRequestDto) {
attendeeCommandService.updateAll(
manager.getId(),
UpdateAttendeesRequestDto.getCourseId(),
UpdateAttendeesRequestDto.getUpdatedAttendees());
return ResponseEntity.ok().build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import java.util.List;

public interface AttendeeCommandService {
public void createAll(Long courseId, List<AttendeeInfo> newAttendees);
public void deleteAll(List<Long> deleteAttendees);
public void createAll(Long managerId, Long courseId, List<AttendeeInfo> newAttendees);
public void deleteAll(Long managerId, List<Long> deleteAttendees);

public void updateAll(Long courseId, List<AttendeeInfo> updatedAttendees);
public void updateAll(Long managerId, Long courseId, List<AttendeeInfo> updatedAttendees);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.waruru.areyouhere.course.domain.entity.Course;
import com.waruru.areyouhere.course.domain.repository.CourseRepository;
import com.waruru.areyouhere.course.exception.CourseNotFoundException;
import com.waruru.areyouhere.manager.exception.UnAuthenticatedException;
import com.waruru.areyouhere.session.exception.ActivatedSessionExistsException;
import java.util.HashMap;
import java.util.HashSet;
Expand All @@ -37,7 +38,8 @@ public class AttendeeCommandServiceImpl implements AttendeeCommandService{
private final ActiveAttendanceService activeAttendanceService;

@Override
public void createAll(Long courseId, List<AttendeeInfo> newAttendees){
public void createAll(Long managerId, Long courseId, List<AttendeeInfo> newAttendees){
throwIfCourseAuthorizationFail(managerId, courseId);
Course course = courseRepository.findById(courseId)
.orElseThrow(CourseNotFoundException::new);

Expand Down Expand Up @@ -69,8 +71,8 @@ public void createAll(Long courseId, List<AttendeeInfo> newAttendees){
}

@Override
public void updateAll(Long courseId, List<AttendeeInfo> updatedAttendees){

public void updateAll(Long managerId, Long courseId, List<AttendeeInfo> updatedAttendees){
throwIfCourseAuthorizationFail(managerId, courseId);
throwIfAttendeesNameAndNoteNotUnique(updatedAttendees, courseId);
updatedAttendees.stream()
.map(attendee ->
Expand All @@ -85,10 +87,11 @@ public void updateAll(Long courseId, List<AttendeeInfo> updatedAttendees){
syncToRedis(courseId);
}

public void deleteAll(List<Long> deleteAttendees){
public void deleteAll(Long managerId, List<Long> deleteAttendees){
Long courseId = attendeeRepository.findById(deleteAttendees.get(0))
.orElseThrow(() -> new AttendeeNotFoundException("Attendee not found"))
.getCourse().getId();
throwIfCourseAuthorizationFail(managerId, courseId);
if(activeAttendanceService.isSessionActivatedByCourseId(courseId)){
throw new ActivatedSessionExistsException();
}
Expand Down Expand Up @@ -174,4 +177,12 @@ private boolean addUniqueNameAndNote(Attendee attendee, Map<String, Set<String>>
.get(attendee.getName())
.add(Optional.ofNullable(attendee.getNote()).orElse(""));
}

private void throwIfCourseAuthorizationFail(Long managerId, Long courseId){
if(!courseRepository.isCourseMadeByManagerId(managerId, courseId)){
throw new UnAuthenticatedException();
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public interface AttendeeQueryService {

public List<SessionAttendees> getSessionAbsenteesIfExistsOrEmpty(Long sessionId);

public List<ClassAttendees> getClassAttendeesIfExistsOrEmpty(Long courseId);
public List<ClassAttendees> getClassAttendeesIfExistsOrEmpty(Long managerId, Long courseId);

public int getAllByCourseId(Long courseId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.waruru.areyouhere.attendee.service.dto.ClassAttendees;
import com.waruru.areyouhere.attendee.service.dto.DuplicateAttendees;
import com.waruru.areyouhere.attendee.service.dto.SessionAttendees;
import com.waruru.areyouhere.course.domain.repository.CourseRepository;
import com.waruru.areyouhere.manager.exception.UnAuthenticatedException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
Expand All @@ -25,6 +27,8 @@
public class AttendeeQueryServiceImpl implements AttendeeQueryService{

private final AttendeeRepository attendeeRepository;
private final CourseRepository courseRepository;

@Override
public AttendeeDetailDto getAttendanceCount(Long attendeeId) {
Attendee attendee = attendeeRepository.findById(attendeeId)
Expand Down Expand Up @@ -114,12 +118,14 @@ public List<SessionAttendees> getSessionAbsenteesIfExistsOrEmpty(Long sessionId)
}

@Override
public List<ClassAttendees> getClassAttendeesIfExistsOrEmpty(Long courseId) {
public List<ClassAttendees> getClassAttendeesIfExistsOrEmpty(Long managerId, Long courseId) {
List<ClassAttendeeInfo> classAttendancesInfos = attendeeRepository.getClassAttendancesInfo(courseId);

if(classAttendancesInfos == null || classAttendancesInfos.isEmpty())
throw new ClassAttendeesEmptyException();

throwIfCourseAuthorizationFail(managerId, courseId);

return classAttendancesInfos.stream().map( classAttendancesInfo -> ClassAttendees.builder()
.id(classAttendancesInfo.getAttendeeId())
.name(classAttendancesInfo.getName())
Expand All @@ -134,4 +140,10 @@ public List<ClassAttendees> getClassAttendeesIfExistsOrEmpty(Long courseId) {
public int getAllByCourseId(Long courseId) {
return attendeeRepository.findAttendeesByCourse_Id(courseId).size();
}

private void throwIfCourseAuthorizationFail(Long managerId, Long courseId){
if(!courseRepository.isCourseMadeByManagerId(managerId, courseId)){
throw new UnAuthenticatedException();
}
}
}
Loading

0 comments on commit f101d13

Please sign in to comment.