Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

로그인 반환값 수정, 인증 관련 api docs 추가 #33

Merged
merged 4 commits into from
Aug 18, 2024
Merged
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
32 changes: 27 additions & 5 deletions src/main/java/com/server/crews/auth/application/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
import com.server.crews.auth.dto.LoginUser;
import com.server.crews.auth.dto.request.AdminLoginRequest;
import com.server.crews.auth.dto.request.ApplicantLoginRequest;
import com.server.crews.auth.dto.response.AccessTokenResponse;
import com.server.crews.auth.dto.response.LoginResponse;
import com.server.crews.auth.repository.AdministratorRepository;
import com.server.crews.auth.repository.ApplicantRepository;
import com.server.crews.global.exception.CrewsException;
import com.server.crews.global.exception.ErrorCode;
import com.server.crews.recruitment.domain.Progress;
import com.server.crews.recruitment.domain.Recruitment;
import com.server.crews.recruitment.repository.RecruitmentRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -26,23 +27,36 @@ public class AuthService {
private final JwtTokenProvider jwtTokenProvider;

@Transactional
public AccessTokenResponse loginForAdmin(AdminLoginRequest request) {
public LoginResponse loginForAdmin(AdminLoginRequest request) {
String clubName = request.clubName();
String password = request.password();

Administrator administrator = administratorRepository.findByClubName(clubName)
.orElseGet(() -> createAdmin(clubName, password));
String accessToken = jwtTokenProvider.createAccessToken(Role.ADMIN, clubName);
return new AccessTokenResponse(administrator.getId(), accessToken);
Progress progress = determineProgress(administrator);
return new LoginResponse(administrator.getId(), accessToken, progress);
}

private Administrator createAdmin(String clubName, String password) {
Administrator administrator = new Administrator(clubName, password);
return administratorRepository.save(administrator);
}

private Progress determineProgress(Administrator administrator) {
return recruitmentRepository.findByPublisher(administrator.getId())
.map(recruitment -> {
if (recruitment.hasPassedClosingDate()) {
recruitment.close();
return Progress.COMPLETION;
}
return recruitment.getProgress();
})
.orElse(Progress.READY);
}

@Transactional
public AccessTokenResponse loginForApplicant(ApplicantLoginRequest request) {
public LoginResponse loginForApplicant(ApplicantLoginRequest request) {
String email = request.email();
String password = request.password();
Recruitment recruitment = recruitmentRepository.findByCode(request.recruitmentCode())
Expand All @@ -51,7 +65,15 @@ public AccessTokenResponse loginForApplicant(ApplicantLoginRequest request) {
Applicant applicant = applicantRepository.findByEmailAndRecruitment(email, recruitment)
.orElseGet(() -> createApplicant(email, password, recruitment));
String accessToken = jwtTokenProvider.createAccessToken(Role.APPLICANT, email);
return new AccessTokenResponse(applicant.getId(), accessToken);
Progress progress = determineProgress(recruitment);
return new LoginResponse(applicant.getId(), accessToken, progress);
}

private Progress determineProgress(Recruitment recruitment) {
if (recruitment.hasPassedClosingDate()) {
return Progress.COMPLETION;
}
return Progress.IN_PROGRESS;
}

private Applicant createApplicant(String email, String password, Recruitment recruitment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.server.crews.auth.domain.RefreshToken;
import com.server.crews.auth.domain.Role;
import com.server.crews.auth.dto.RefreshTokenWithValidity;
import com.server.crews.auth.dto.response.AccessTokenResponse;
import com.server.crews.auth.dto.response.LoginResponse;
import com.server.crews.auth.repository.RefreshTokenRepository;
import com.server.crews.global.exception.CrewsException;
import com.server.crews.global.exception.ErrorCode;
Expand Down Expand Up @@ -34,7 +34,7 @@ public RefreshTokenWithValidity createRefreshToken(Role role, Long id) {
return new RefreshTokenWithValidity(refreshTokenValidityInSecond, refreshToken);
}

public AccessTokenResponse renew(String refreshToken) {
public LoginResponse renew(String refreshToken) {
jwtTokenProvider.validateRefreshToken(refreshToken);
refreshTokenRepository.findByToken(refreshToken)
.orElseThrow(() -> new CrewsException(ErrorCode.INVALID_REFRESH_TOKEN));
Expand All @@ -43,6 +43,6 @@ public AccessTokenResponse renew(String refreshToken) {
long id = Long.parseLong(payload);
Role role = jwtTokenProvider.getRole(refreshToken);
String accessToken = jwtTokenProvider.createAccessToken(role, payload);
return new AccessTokenResponse(id, accessToken);
return new LoginResponse(id, accessToken, null);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.server.crews.auth.dto.response;

import com.server.crews.recruitment.domain.Progress;

public record LoginResponse(Long userId, String accessToken, Progress progress) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.server.crews.auth.dto.RefreshTokenWithValidity;
import com.server.crews.auth.dto.request.AdminLoginRequest;
import com.server.crews.auth.dto.request.ApplicantLoginRequest;
import com.server.crews.auth.dto.response.AccessTokenResponse;
import com.server.crews.auth.dto.response.LoginResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
Expand All @@ -29,35 +29,35 @@ public class AuthController {
* [동아리 관리자] 로그인 해 토큰을 발급 받는다. 모집 공고가 존재하지 않는다면 모집 공고를 새로 생성한다.
*/
@PostMapping("/admin/login")
public ResponseEntity<AccessTokenResponse> loginForAdmin(@RequestBody AdminLoginRequest request) {
AccessTokenResponse accessTokenResponse = authService.loginForAdmin(request);
public ResponseEntity<LoginResponse> loginForAdmin(@RequestBody AdminLoginRequest request) {
LoginResponse loginResponse = authService.loginForAdmin(request);
RefreshTokenWithValidity refreshTokenWithValidity = refreshTokenService.createRefreshToken(Role.ADMIN,
accessTokenResponse.userId());
loginResponse.userId());
ResponseCookie cookie = refreshTokenWithValidity.toCookie();
return ResponseEntity.status(HttpStatus.OK)
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(accessTokenResponse);
.body(loginResponse);
}

/**
* [지원자] 로그인 해 토큰을 발급 받는다.
*/
@PostMapping("/applicant/login")
public ResponseEntity<AccessTokenResponse> loginForApplicant(@RequestBody ApplicantLoginRequest request) {
AccessTokenResponse accessTokenResponse = authService.loginForApplicant(request);
public ResponseEntity<LoginResponse> loginForApplicant(@RequestBody ApplicantLoginRequest request) {
LoginResponse loginResponse = authService.loginForApplicant(request);
RefreshTokenWithValidity refreshTokenWithValidity = refreshTokenService.createRefreshToken(Role.APPLICANT,
accessTokenResponse.userId());
loginResponse.userId());
ResponseCookie cookie = refreshTokenWithValidity.toCookie();
return ResponseEntity.status(HttpStatus.OK)
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(accessTokenResponse);
.body(loginResponse);
}

/**
* access token을 재발급 받는다.
*/
@PostMapping("/refresh")
public ResponseEntity<AccessTokenResponse> renew(@CookieValue("refreshToken") String refreshToken) {
public ResponseEntity<LoginResponse> renew(@CookieValue("refreshToken") String refreshToken) {
return ResponseEntity.ok(refreshTokenService.renew(refreshToken));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ public void announce() {
this.progress = Progress.ANNOUNCED;
}

public void close() {
this.progress = Progress.COMPLETION;
}

public void updateClosingDate(LocalDateTime closingDate) {
validateClosingDate(closingDate);
this.closingDate = closingDate;
Expand All @@ -108,4 +112,8 @@ public boolean isAnnounced() {
public boolean isStarted() {
return this.progress != Progress.READY;
}

public boolean hasPassedClosingDate() {
return LocalDateTime.now().isAfter(closingDate);
}
}
12 changes: 6 additions & 6 deletions src/test/java/com/server/crews/api/ApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import com.server.crews.applicant.dto.response.ApplicationDetailsResponse;
import com.server.crews.auth.dto.request.AdminLoginRequest;
import com.server.crews.auth.dto.request.ApplicantLoginRequest;
import com.server.crews.auth.dto.response.AccessTokenResponse;
import com.server.crews.auth.dto.response.LoginResponse;
import com.server.crews.auth.presentation.AuthorizationExtractor;
import com.server.crews.environ.DatabaseCleaner;
import com.server.crews.external.application.EmailService;
Expand Down Expand Up @@ -70,15 +70,15 @@ protected ApplicationSaveRequest applicationSaveRequest() {
answerSaveRequests);
}

protected AccessTokenResponse signUpAdmin(String email, String password) {
protected LoginResponse signUpAdmin(String clubName, String password) {
ExtractableResponse<Response> response = RestAssured.given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(new AdminLoginRequest(email, password))
.body(new AdminLoginRequest(clubName, password))
.when().post("/auth/admin/login")
.then()
.statusCode(HttpStatus.OK.value())
.extract();
return response.as(AccessTokenResponse.class);
return response.as(LoginResponse.class);
}

protected RecruitmentDetailsResponse createRecruitment(String accessToken) {
Expand All @@ -97,15 +97,15 @@ protected RecruitmentDetailsResponse createRecruitment(String accessToken, Recru
return response.as(RecruitmentDetailsResponse.class);
}

protected AccessTokenResponse signUpApplicant(String recruitmentCode, String email, String password) {
protected LoginResponse signUpApplicant(String recruitmentCode, String email, String password) {
ExtractableResponse<Response> response = RestAssured.given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(new ApplicantLoginRequest(recruitmentCode, email, password))
.when().post("/auth/applicant/login")
.then()
.statusCode(HttpStatus.OK.value())
.extract();
return response.as(AccessTokenResponse.class);
return response.as(LoginResponse.class);
}

protected ApplicationDetailsResponse createTestApplication(String accessToken,
Expand Down
38 changes: 16 additions & 22 deletions src/test/java/com/server/crews/api/ApplicationApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static com.server.crews.fixture.ApplicationFixture.DEFAULT_NAME;
import static com.server.crews.fixture.ApplicationFixture.DEFAULT_NARRATIVE_ANSWER;
import static com.server.crews.fixture.ApplicationFixture.DEFAULT_STUDENT_NUMBER;
import static com.server.crews.fixture.UserFixture.TEST_CLUB_NAME;
import static com.server.crews.fixture.UserFixture.TEST_EMAIL;
import static com.server.crews.fixture.UserFixture.TEST_PASSWORD;
import static org.assertj.core.api.SoftAssertions.assertSoftly;
Expand All @@ -18,7 +19,7 @@
import com.server.crews.applicant.dto.response.ApplicationsResponse;
import com.server.crews.applicant.dto.response.NarrativeAnswerResponse;
import com.server.crews.applicant.dto.response.SelectiveAnswerResponse;
import com.server.crews.auth.dto.response.AccessTokenResponse;
import com.server.crews.auth.dto.response.LoginResponse;
import com.server.crews.auth.presentation.AuthorizationExtractor;
import com.server.crews.recruitment.dto.request.QuestionType;
import com.server.crews.recruitment.dto.response.RecruitmentDetailsResponse;
Expand All @@ -30,7 +31,6 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

public class ApplicationApiTest extends ApiTest {
Expand All @@ -39,9 +39,9 @@ public class ApplicationApiTest extends ApiTest {
@DisplayName("지원자가 로그인하여 지원서를 저장한다.")
void saveApplication() {
// given
AccessTokenResponse adminTokenResponse = signUpAdmin(TEST_EMAIL, TEST_PASSWORD);
LoginResponse adminTokenResponse = signUpAdmin(TEST_CLUB_NAME, TEST_PASSWORD);
RecruitmentDetailsResponse recruitmentDetailsResponse = createRecruitment(adminTokenResponse.accessToken());
AccessTokenResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
LoginResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
TEST_PASSWORD);
List<AnswerSaveRequest> firstAnswerSaveRequests = List.of(
new AnswerSaveRequest(null, QuestionType.NARRATIVE.name(), 2L, DEFAULT_NARRATIVE_ANSWER, null),
Expand All @@ -67,7 +67,6 @@ void saveApplication() {
.body(applicationUpdateRequest)
.when().post("/applications")
.then().log().all()
.statusCode(HttpStatus.OK.value())
.extract();

// then
Expand All @@ -86,9 +85,9 @@ void saveApplication() {
@DisplayName("존재하지 않는 질문에 대해 답변을 저장한다.")
void saveApplicationWithNotExistingQuestion() {
// given
AccessTokenResponse adminTokenResponse = signUpAdmin(TEST_EMAIL, TEST_PASSWORD);
LoginResponse adminTokenResponse = signUpAdmin(TEST_CLUB_NAME, TEST_PASSWORD);
RecruitmentDetailsResponse recruitmentDetailsResponse = createRecruitment(adminTokenResponse.accessToken());
AccessTokenResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
LoginResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
TEST_PASSWORD);
List<AnswerSaveRequest> answerSaveRequests = List.of(
new AnswerSaveRequest(null, QuestionType.NARRATIVE.name(), 10L, DEFAULT_NARRATIVE_ANSWER, null));
Expand All @@ -104,7 +103,6 @@ void saveApplicationWithNotExistingQuestion() {
.body(applicationSaveRequest)
.when().post("/applications")
.then().log().all()
.statusCode(HttpStatus.NOT_FOUND.value())
.extract();

// then
Expand All @@ -115,9 +113,9 @@ void saveApplicationWithNotExistingQuestion() {
@DisplayName("한 서술형 문항에 두 개 이상의 답변을 저장한다.")
void saveApplicationWithDuplicatedNarrativeAnswer() {
// given
AccessTokenResponse adminTokenResponse = signUpAdmin(TEST_EMAIL, TEST_PASSWORD);
LoginResponse adminTokenResponse = signUpAdmin(TEST_CLUB_NAME, TEST_PASSWORD);
RecruitmentDetailsResponse recruitmentDetailsResponse = createRecruitment(adminTokenResponse.accessToken());
AccessTokenResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
LoginResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
TEST_PASSWORD);
List<AnswerSaveRequest> answerSaveRequests = List.of(
new AnswerSaveRequest(null, QuestionType.NARRATIVE.name(), 1L, "동일한 내용", null),
Expand All @@ -134,7 +132,6 @@ void saveApplicationWithDuplicatedNarrativeAnswer() {
.body(applicationSaveRequest)
.when().post("/applications")
.then().log().all()
.statusCode(HttpStatus.BAD_REQUEST.value())
.extract();

// then
Expand All @@ -145,9 +142,9 @@ void saveApplicationWithDuplicatedNarrativeAnswer() {
@DisplayName("지원서의 상세 정보를 조회한다.")
void getApplicationDetails() {
// given
AccessTokenResponse adminTokenResponse = signUpAdmin(TEST_EMAIL, TEST_PASSWORD);
LoginResponse adminTokenResponse = signUpAdmin(TEST_CLUB_NAME, TEST_PASSWORD);
RecruitmentDetailsResponse recruitmentDetailsResponse = createRecruitment(adminTokenResponse.accessToken());
AccessTokenResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
LoginResponse applicantTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(), TEST_EMAIL,
TEST_PASSWORD);

ApplicationSaveRequest applicationSaveRequest = applicationSaveRequest();
Expand All @@ -163,7 +160,6 @@ void getApplicationDetails() {
.pathParam("application-id", testApplication.id())
.when().get("/applications/{application-id}")
.then().log().all()
.statusCode(HttpStatus.OK.value())
.extract();

// then
Expand All @@ -181,11 +177,11 @@ void getApplicationDetails() {
@DisplayName("지원서들을 평가한다.")
void evaluate() {
// given
AccessTokenResponse adminTokenResponse = signUpAdmin(TEST_EMAIL, TEST_PASSWORD);
LoginResponse adminTokenResponse = signUpAdmin(TEST_CLUB_NAME, TEST_PASSWORD);
RecruitmentDetailsResponse recruitmentDetailsResponse = createRecruitment(adminTokenResponse.accessToken());
AccessTokenResponse applicantATokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
LoginResponse applicantATokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
"A" + TEST_EMAIL, TEST_PASSWORD);
AccessTokenResponse applicantBTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
LoginResponse applicantBTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
"B" + TEST_EMAIL, TEST_PASSWORD);

ApplicationSaveRequest applicationSaveRequest = applicationSaveRequest();
Expand All @@ -204,7 +200,6 @@ void evaluate() {
AuthorizationExtractor.BEARER_TYPE + adminTokenResponse.accessToken())
.when().post("/applications/evaluation")
.then().log().all()
.statusCode(HttpStatus.OK.value())
.extract();

// then
Expand All @@ -215,11 +210,11 @@ void evaluate() {
@DisplayName("한 공고의 모든 지원서 목록을 조회한다.")
void getAllApplicationsByRecruitment() {
// given
AccessTokenResponse adminTokenResponse = signUpAdmin(TEST_EMAIL, TEST_PASSWORD);
LoginResponse adminTokenResponse = signUpAdmin(TEST_CLUB_NAME, TEST_PASSWORD);
RecruitmentDetailsResponse recruitmentDetailsResponse = createRecruitment(adminTokenResponse.accessToken());
AccessTokenResponse applicantATokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
LoginResponse applicantATokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
"A" + TEST_EMAIL, TEST_PASSWORD);
AccessTokenResponse applicantBTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
LoginResponse applicantBTokenResponse = signUpApplicant(recruitmentDetailsResponse.code(),
"B" + TEST_EMAIL, TEST_PASSWORD);

ApplicationSaveRequest applicationSaveRequest = applicationSaveRequest();
Expand All @@ -234,7 +229,6 @@ void getAllApplicationsByRecruitment() {
AuthorizationExtractor.BEARER_TYPE + adminTokenResponse.accessToken())
.when().get("/applications")
.then().log().all()
.statusCode(HttpStatus.OK.value())
.extract();

// then
Expand Down
Loading
Loading