Skip to content

Commit

Permalink
fix: 동아리 관리자가 지원서 상세 정보 조회하는 기능 권한 관련 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
jongmee committed Aug 26, 2024
1 parent 11274ef commit 4a87dc9
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import com.server.crews.applicant.repository.NarrativeAnswerRepository;
import com.server.crews.applicant.repository.SelectiveAnswerRepository;
import com.server.crews.auth.domain.Applicant;
import com.server.crews.auth.dto.LoginUser;
import com.server.crews.auth.repository.ApplicantRepository;
import com.server.crews.global.exception.CrewsException;
import com.server.crews.global.exception.ErrorCode;
Expand Down Expand Up @@ -143,18 +142,18 @@ public List<ApplicationsResponse> findAllApplicationsByRecruitment(Long publishe
.toList();
}

public ApplicationDetailsResponse findApplicationDetails(Long applicationId, LoginUser loginUser) {
Application application = applicationRepository.findById(applicationId)
public ApplicationDetailsResponse findApplicationDetails(Long applicationId, Long publisherId) {
Application application = applicationRepository.findByIdWithRecruitmentAndPublisher(applicationId)
.orElseThrow(() -> new CrewsException(ErrorCode.APPLICATION_NOT_FOUND));
checkPermission(application, loginUser);
checkPermission(application, publisherId);
List<NarrativeAnswer> narrativeAnswers = narrativeAnswerRepository.findAllByApplication(application);
Map<Long, List<SelectiveAnswer>> selectiveAnswers = collectSelectiveAnswersByQuestion(
selectiveAnswerRepository.findAllByApplication(application));
return ApplicationDetailsResponse.of(application, narrativeAnswers, selectiveAnswers);
}

private void checkPermission(Application application, LoginUser loginUser) {
if (!application.canBeAccessedBy(loginUser.userId(), loginUser.role())) {
private void checkPermission(Application application, Long publisherId) {
if (!application.canBeAccessedBy(publisherId)) {
throw new CrewsException(ErrorCode.UNAUTHORIZED_USER);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,7 @@ public boolean isNotDetermined() {
return outcome.equals(Outcome.PENDING);
}

public boolean canBeAccessedBy(Long userId, Role role) {
if (role == Role.ADMIN) {
return true;
}
return applicant.getId().equals(userId);
public boolean canBeAccessedBy(Long publisherId) {
return this.recruitment.isPublishedBy(publisherId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,14 @@ public ResponseEntity<ApplicationDetailsResponse> saveApplication(
.body(applicationService.saveApplication(loginUser.userId(), request));
}

// Todo: 지원서 수정 api 추가

/**
* 특정 지원자의 지원서를 조회한다.
* 동아리 관리자가 특정 지원자의 지원서를 조회한다.
*/
@GetMapping("/{application-id}")
public ResponseEntity<ApplicationDetailsResponse> getApplicationDetails(
@ApplicantAuthentication LoginUser loginUser,
@AdminAuthentication LoginUser loginUser,
@PathVariable(value = "application-id") Long applicationId) {
return ResponseEntity.ok(applicationService.findApplicationDetails(applicationId, loginUser));
return ResponseEntity.ok(applicationService.findApplicationDetails(applicationId, loginUser.userId()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,12 @@ select count(application) from Application application
where a.applicant.id = :applicantId
""")
Optional<Application> findByApplicantId(@Param("applicantId") Long applicantId);

@Query("""
select a from Application a
join fetch a.recruitment r
join fetch r.publisher
where a.id = :id
""")
Optional<Application> findByIdWithRecruitmentAndPublisher(@Param("id") Long id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,8 @@ public boolean hasPassedDeadline(LocalDateTime now) {
public void sortQuestions() {
this.sections.forEach(Section::sortQuestions);
}

public boolean isPublishedBy(Long publisherId) {
return this.publisher.getId().equals(publisherId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public static RestDocumentationFilter SAVE_APPLICATION_400_DOCUMENT() {
}

public static RestDocumentationFilter GET_APPLICATION_200_DOCUMENT() {
return document(APPLICATION_API + "지원서 상세 조회",
new ResourceSnippetParametersBuilder().description("지원서 상세 정보를 조회한다.")
return document(APPLICATION_API + "동아리 관리자 지원서 상세 조회",
new ResourceSnippetParametersBuilder().description("동아리 관리자가 지원서 상세 정보를 조회한다.")
.pathParameters(parameterWithName("application-id").description("지원서 id")));
}

Expand Down
4 changes: 2 additions & 2 deletions src/test/java/com/server/crews/api/ApplicationApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void saveApplicationWithDuplicatedNarrativeAnswer() {
}

@Test
@DisplayName("지원서의 상세 정보를 조회한다.")
@DisplayName("동아리 관리자가 지원서 상세 정보를 조회한다.")
void getApplicationDetails() {
// given
AdminLoginResponse adminTokenResponse = signUpAdmin(TEST_CLUB_NAME, TEST_PASSWORD);
Expand All @@ -154,7 +154,7 @@ void getApplicationDetails() {
.filter(ApplicationApiDocuments.GET_APPLICATION_200_DOCUMENT())
.contentType(MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.AUTHORIZATION,
AuthorizationExtractor.BEARER_TYPE + applicantLoginResponse.accessToken())
AuthorizationExtractor.BEARER_TYPE + adminTokenResponse.accessToken())
.pathParam("application-id", testApplication.id())
.when().get("/applications/{application-id}")
.then().log().all()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import static com.server.crews.fixture.SectionFixture.BACKEND_SECTION_NAME;
import static com.server.crews.fixture.SectionFixture.FRONTEND_SECTION_NAME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;

Expand All @@ -29,12 +28,9 @@
import com.server.crews.applicant.repository.SelectiveAnswerRepository;
import com.server.crews.auth.domain.Administrator;
import com.server.crews.auth.domain.Applicant;
import com.server.crews.auth.domain.Role;
import com.server.crews.auth.dto.LoginUser;
import com.server.crews.environ.service.ServiceTest;
import com.server.crews.environ.service.TestRecruitment;
import com.server.crews.global.exception.CrewsException;
import com.server.crews.global.exception.ErrorCode;
import com.server.crews.recruitment.domain.Choice;
import com.server.crews.recruitment.domain.NarrativeQuestion;
import com.server.crews.recruitment.domain.Recruitment;
Expand Down Expand Up @@ -146,10 +142,9 @@ void findApplicationDetails() {
.saveSelectiveAnswers(selectiveQuestion, choices.get(1))
.application();

LoginUser loginUser = new LoginUser(publisher.getId(), Role.ADMIN);

// when
ApplicationDetailsResponse response = applicationService.findApplicationDetails(application.getId(), loginUser);
ApplicationDetailsResponse response = applicationService.findApplicationDetails(application.getId(),
publisher.getId());

// then
assertAll(() -> {
Expand All @@ -160,44 +155,6 @@ void findApplicationDetails() {
});
}

@ParameterizedTest
@MethodSource("provideRole")
@DisplayName("지원서의 작성자 혹은 동아리 관리자만이 지원서 상세 정보를 조회할 수 있다.")
void checkApplicationPermission(Role givenRole) {
// given
Administrator publisher = LIKE_LION_ADMIN().administrator();
Recruitment testRecruitment = LIKE_LION_RECRUITMENT(publisher).recruitment();
Applicant applicant = JONGMEE_APPLICANT().applicant();
Application application = JONGMEE_APPLICATION(applicant, testRecruitment).application();

LoginUser loginUser = new LoginUser(1L, givenRole);

// when & then
assertThatCode(() -> applicationService.findApplicationDetails(application.getId(), loginUser))
.doesNotThrowAnyException();
}

private static Stream<Role> provideRole() {
return Stream.of(Role.APPLICANT, Role.ADMIN);
}

@Test
@DisplayName("지원서 작성자가 아닌 지원자는 지원서 상세 정보를 조회할 수 없다.")
void checkInvalidApplicationPermission() {
// given
Administrator publisher = LIKE_LION_ADMIN().administrator();
Recruitment testRecruitment = LIKE_LION_RECRUITMENT(publisher).recruitment();
Applicant jongmeeApplicant = JONGMEE_APPLICANT().applicant();
Application application = JONGMEE_APPLICATION(jongmeeApplicant, testRecruitment).application();
Applicant kyunghoApplicant = KYUNGHO_APPLICANT().applicant();

LoginUser loginUser = new LoginUser(kyunghoApplicant.getId(), Role.APPLICANT);

// when & then
assertThatThrownBy(() -> applicationService.findApplicationDetails(application.getId(), loginUser))
.hasMessage(ErrorCode.UNAUTHORIZED_USER.getMessage());
}

@Test
@DisplayName("지원자들을 평가한다.")
void decideOutcome() {
Expand Down

0 comments on commit 4a87dc9

Please sign in to comment.