Skip to content

Commit

Permalink
Merge pull request #115 from Open-Eye-Im-Developer/develop
Browse files Browse the repository at this point in the history
[MERGE] develop 을 main 에 반영
  • Loading branch information
happyjamy committed Feb 20, 2024
2 parents 92ddb05 + 0539ba3 commit 60fefe9
Show file tree
Hide file tree
Showing 41 changed files with 557 additions and 91 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.oeid.mogakgo.common.base;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;

Expand All @@ -18,19 +19,19 @@ public class CursorPaginationResult<T> {
private Integer size;

private CursorPaginationResult(List<T> data, Integer size) {
this.data = data;
this.size = size;
if (data.size() > size) {
this.hasNext = true;
this.data.remove(data.size() - 1);
this.data = new ArrayList<>(data.subList(0, size));
} else {
this.hasNext = false;
this.data = new ArrayList<>(data);
}
this.numberOfElements = data.size();
}

private CursorPaginationResult(List<T> data, Integer size, boolean hasNext) {
this.data = data;
this.data = new ArrayList<>(data);
this.numberOfElements = data.size();
this.hasNext = hasNext;
this.size = size;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.oeid.mogakgo.common.swagger.template;

import io.oeid.mogakgo.core.properties.swagger.error.SwaggerMatchingErrorExamples;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerProjectErrorExamples;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerUserErrorExamples;
import io.oeid.mogakgo.domain.matching.presentation.dto.MatchingId;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;

@Tag(name = "Matching", description = "매칭 관련 API")
@SuppressWarnings("unused")
public interface MatchingSwagger {

@Operation(summary = "매칭 취소", description = "회원이 현재 진행 중인 매칭을 취소할때 사용하는 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "매칭 취소 완료"),
@ApiResponse(responseCode = "400", description = "매칭을 취소할 수 없는 상태임",
content = @Content(
mediaType = "application/json",
examples = {
@ExampleObject(name = "E090101", value = SwaggerMatchingErrorExamples.MATCHING_CANCEL_NOT_ALLOWED),
@ExampleObject(name = "E030110", value = SwaggerProjectErrorExamples.INVALID_PROJECT_STATUS_TO_FINISH)
})),
@ApiResponse(responseCode = "403", description = "요청을 보낸 사람이 매칭 취소할 권한이 안됨 (매칭 참여자가 아님)",
content = @Content(
mediaType = "application/json",
examples = @ExampleObject(name = "E090201", value = SwaggerMatchingErrorExamples.MATCHING_FORBIDDEN_OPERATION))),
@ApiResponse(responseCode = "404", description = "요청한 데이터가 존재하지 않음",
content = @Content(
mediaType = "application/json",
examples = {
@ExampleObject(name = "E090201", value = SwaggerMatchingErrorExamples.MATCHING_NOT_FOUND),
@ExampleObject(name = "E020301", value = SwaggerUserErrorExamples.USER_NOT_FOUND)
})),
})
ResponseEntity<MatchingId> cancel(
@Parameter(hidden = true) Long userId,
@Parameter(description = "매칭 ID", required = true) Long matchingId
);

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

import io.oeid.mogakgo.common.base.CursorPaginationInfoReq;
import io.oeid.mogakgo.common.base.CursorPaginationResult;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerUserErrorExamples;
import io.oeid.mogakgo.domain.notification.presentation.dto.req.FCMTokenApiRequest;
import io.oeid.mogakgo.domain.notification.presentation.dto.res.NotificationPublicApiRes;
import io.oeid.mogakgo.exception.dto.ErrorResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand All @@ -29,4 +32,18 @@ public interface NotificationSwagger {
)
ResponseEntity<Void> manageFCMToken(@Parameter(hidden = true) Long userId,
FCMTokenApiRequest request);

@Operation(summary = "알림 조회", description = "회원의 알림을 조회할 때 사용하는 API")
@ApiResponse(responseCode = "200", description = "알림 조회 성공",
content = @Content(schema = @Schema(implementation = NotificationPublicApiRes.class)))
@ApiResponse(responseCode = "404", description = "요청한 유저가 존재하지 않음", content = @Content(
mediaType = APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(name = "E020301", value = SwaggerUserErrorExamples.USER_NOT_FOUND)
})
)
ResponseEntity<CursorPaginationResult<NotificationPublicApiRes>> getByUserId(
@Parameter(hidden = true) Long id,
CursorPaginationInfoReq pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

import io.oeid.mogakgo.domain.auth.presentation.dto.res.AuthAccessTokenResponse;
import io.oeid.mogakgo.domain.auth.presentation.dto.res.AuthLoginUrlResponse;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -11,19 +10,22 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.core.user.OAuth2User;

@Tag(name = "OAuth2", description = "OAuth2 관련 API")
@SuppressWarnings("unused")
public interface OAuth2Swagger {

@Operation(summary = "로그인 URL 반환", description = "로그인 URL을 반환하는 API")
@ApiResponse(responseCode = "200", description = "로그인 URL 반환 성공",
content = @Content(
mediaType = APPLICATION_JSON_VALUE,
schema = @Schema(implementation = AuthLoginUrlResponse.class)))
ResponseEntity<AuthLoginUrlResponse> login();

@Hidden
ResponseEntity<AuthAccessTokenResponse> loginSuccess(
OAuth2User oAuth2User, HttpServletResponse response);
void loginSuccess(
OAuth2User oAuth2User, HttpServletResponse response) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerProjectJoinReqErrorExamples;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerProjectJoinRequestErrorExamples;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerUserErrorExamples;
import io.oeid.mogakgo.domain.matching.presentation.dto.res.MatchingId;
import io.oeid.mogakgo.domain.matching.presentation.dto.MatchingId;
import io.oeid.mogakgo.domain.project_join_req.application.dto.req.ProjectJoinCreateReq;
import io.oeid.mogakgo.domain.project_join_req.presentation.dto.res.ProjectJoinRequestAPIRes;
import io.oeid.mogakgo.domain.project_join_req.presentation.dto.res.ProjectJoinRequestDetailAPIRes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io.oeid.mogakgo.common.swagger.template;

import io.oeid.mogakgo.common.annotation.UserId;
import io.oeid.mogakgo.common.base.CursorPaginationInfoReq;
import io.oeid.mogakgo.common.base.CursorPaginationResult;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerGeoErrorExamples;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerProjectErrorExamples;
import io.oeid.mogakgo.core.properties.swagger.error.SwaggerUserErrorExamples;
import io.oeid.mogakgo.domain.geo.domain.enums.Region;
import io.oeid.mogakgo.domain.project.presentation.dto.res.ProjectDensityRankRes;
import io.oeid.mogakgo.domain.project.presentation.dto.res.ProjectDetailAPIRes;
import io.oeid.mogakgo.domain.project.presentation.dto.req.ProjectCreateReq;
import io.oeid.mogakgo.domain.project.presentation.dto.res.ProjectIdRes;
Expand All @@ -20,7 +22,9 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;

@Tag(name = "Project Card", description = "프로젝트 카드 관련 API")
@SuppressWarnings("unused")
Expand Down Expand Up @@ -171,4 +175,11 @@ ResponseEntity<CursorPaginationResult<projectJoinRequestRes>> getJoinRequest(
@Parameter(description = "프로젝트 ID", required = true) Long id,
@Parameter(hidden = true) CursorPaginationInfoReq pageable
);

@Operation(summary = "지역별 프로젝트 밀도 순위 조회", description = "지역별 프로젝트 밀도 순위를 조회할 때 사용하는 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "지역별 프로젝트 밀도 순위 조회 성공",
content = @Content(schema = @Schema(implementation = ProjectDensityRankRes.class))),
})
ResponseEntity<ProjectDensityRankRes> getDensityRankProjects();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.oeid.mogakgo.core.properties.swagger.error;

public class SwaggerMatchingErrorExamples {

public static final String MATCHING_CANCEL_NOT_ALLOWED = "{\"timestamp\":\"2024-02-17T10:07:31.404Z\",\"statusCode\":400,\"code\":\"E090101\",\"message\":\"이미 취소 되었거나 종료된 매칭은 취소할 수 없습니다.\"}";
public static final String MATCHING_NOT_FOUND = "{\"timestamp\":\"2024-02-17T10:07:31.404Z\",\"statusCode\":404,\"code\":\"E090301\",\"message\":\"해당 매칭이 존재하지 않습니다.\"}";
public static final String MATCHING_FORBIDDEN_OPERATION = "{\"timestamp\":\"2024-02-17T10:07:31.404Z\",\"statusCode\":403,\"code\":\"E090201\",\"message\":\"해당 매칭에 대한 권한이 없습니다.\"}";

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class SwaggerProjectErrorExamples {
public static final String PROJECT_JOIN_REQUEST_FORBIDDEN_OPERATION = "{\"timestamp\":\"2024-02-17T10:07:31.404Z\",\"statusCode\":403,\"code\":\"E050201\",\"message\":\"해당 프로젝트 요청에 대한 권한이 없습니다.\"}";
public static final String INVALID_MATCHING_USER_TO_CREATE_PROJECT = "{\"timestamp\":\"2024-02-17T10:07:31.404Z\",\"statusCode\":400,\"code\":\"E030108\",\"message\":\"매칭이 진행 중인 유저는 프로젝트 생성을 할 수 없습니다.\"}";
public static final String ALREADY_EXIST_PROGRESS_PROJECT = "{\"timestamp\":\"2024-02-17T10:07:31.404Z\",\"statusCode\":400,\"code\":\"E030109\",\"message\":\"종료되지 않은 프로젝트 카드가 있으면 프로젝트 생성을 할 수 없습니다.\"}";
public static final String INVALID_PROJECT_STATUS_TO_FINISH = "{\"timestamp\":\"2024-02-17T10:07:31.404Z\",\"statusCode\":400,\"code\":\"E030110\",\"message\":\"매칭중인 프로젝트가 아니여서 프로젝트를 종료할 수 없습니다.\"}";

private SwaggerProjectErrorExamples() {
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package io.oeid.mogakgo.domain.auth.presentation;

import io.oeid.mogakgo.common.swagger.template.OAuth2Swagger;
import io.oeid.mogakgo.domain.auth.presentation.dto.res.AuthAccessTokenResponse;
import io.oeid.mogakgo.domain.auth.presentation.dto.res.AuthLoginUrlResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
Expand All @@ -20,20 +20,24 @@
public class OAuth2Controller implements OAuth2Swagger {

private final String serverUrl;
private final String clientUrl;

public OAuth2Controller(@Value("${auth.server-url}") String serverUrl) {
public OAuth2Controller(@Value("${auth.server-url}") String serverUrl,
@Value("${auth.client-url}") String clientUrl) {
this.serverUrl = serverUrl;
this.clientUrl = clientUrl;
}

@GetMapping("/login/success")
public ResponseEntity<AuthAccessTokenResponse> loginSuccess(
@AuthenticationPrincipal OAuth2User oAuth2User, HttpServletResponse response) {
public void loginSuccess(@AuthenticationPrincipal OAuth2User oAuth2User,
HttpServletResponse response) throws IOException {
String accessToken = oAuth2User.getAttributes().get("accessToken").toString();
boolean signUpComplete = (boolean) oAuth2User.getAttributes().get("signUpComplete");
String refreshToken = oAuth2User.getAttributes().get("refreshToken").toString();
int refreshTokenExpireTime = (int) oAuth2User.getAttributes().get("refreshTokenExpireTime");
boolean signUpComplete = (boolean) oAuth2User.getAttributes().get("signUpComplete");
setCookie(refreshToken, refreshTokenExpireTime, response);
return ResponseEntity.ok(AuthAccessTokenResponse.of(accessToken, signUpComplete));
String redirectUrl = signUpComplete ? clientUrl : clientUrl + "/signup";
response.sendRedirect(redirectUrl + "?accessToken=" + accessToken);
}

@GetMapping("/login")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.oeid.mogakgo.domain.geo.domain.enums;

import java.util.List;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

Expand Down Expand Up @@ -47,5 +48,13 @@ public static Region getByAreaCode(int areaCode) {
return null;
}

public static List<Region> getDefaultDensityRank() {
return List.of(
JONGRO, JUNG, YONGSAN, SEONGDONG, KWANGJIN, DONGDAEMUN, JUNGRANG, SEONGBUK, KANGBUK,
DOBONG, NOWON, EUNPYEONG, SEODAEMUN, MAPO, YANGCHUN, KANGSEO, GURO, GEUMCHUN,
YOUNGDEUNGPO, DONGJAK, KWANAK, SEOCHO, KANGNAM, SONGPA, KANGDONG
);
}

}

Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package io.oeid.mogakgo.domain.matching.application;

import static io.oeid.mogakgo.exception.code.ErrorCode404.MATCHING_NOT_FOUND;

import io.oeid.mogakgo.domain.matching.domain.entity.Matching;
import io.oeid.mogakgo.domain.matching.exception.MatchingException;
import io.oeid.mogakgo.domain.matching.infrastructure.MatchingJpaRepository;
import io.oeid.mogakgo.domain.project_join_req.domain.entity.ProjectJoinRequest;
import io.oeid.mogakgo.domain.user.application.UserCommonService;
import io.oeid.mogakgo.domain.user.domain.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -14,6 +19,8 @@ public class MatchingService {

private final MatchingJpaRepository matchingJpaRepository;

private final UserCommonService userCommonService;

@Transactional
public Long create(ProjectJoinRequest projectJoinRequest) {
Matching matching = Matching.builder()
Expand All @@ -25,4 +32,22 @@ public Long create(ProjectJoinRequest projectJoinRequest) {

return matching.getId();
}

@Transactional
public Long cancel(Long tokenUserId, Long matchingId) {
User tokenUser = userCommonService.getUserById(tokenUserId);

Matching matching = getMatching(matchingId);

// 매칭 취소
// 프로젝트 종료 상태 변경
matching.cancel(tokenUser);

return matching.getId();
}

private Matching getMatching(Long matchingId) {
return matchingJpaRepository.findById(matchingId)
.orElseThrow(() -> new MatchingException(MATCHING_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.oeid.mogakgo.domain.matching.domain.entity;

import static io.oeid.mogakgo.domain.matching.domain.entity.enums.MatchingStatus.PROGRESS;
import static io.oeid.mogakgo.exception.code.ErrorCode403.MATCHING_FORBIDDEN_OPERATION;

import io.oeid.mogakgo.domain.matching.domain.entity.enums.MatchingStatus;
import io.oeid.mogakgo.domain.matching.exception.MatchingException;
import io.oeid.mogakgo.domain.project.domain.entity.Project;
import io.oeid.mogakgo.domain.user.domain.User;
import jakarta.persistence.Column;
Expand All @@ -19,6 +21,7 @@
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import java.util.List;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand Down Expand Up @@ -63,4 +66,25 @@ private Matching(
this.sender = sender;
this.matchingStatus = PROGRESS;
}

// TODO: 프로젝트 상태 변경과 매칭 상태 변경을 동시에 처리하는 것을 보장하는것이 좋을 것 같다.
public void cancel(User tokenUser) {
validateAvailableCancel(tokenUser);
project.finish();
this.matchingStatus = MatchingStatus.CANCELED;
}

private void validateAvailableCancel(User tokenUser) {
validateParticipants(tokenUser);
matchingStatus.validateAvailableCancel();
}

public void validateParticipants(User tokenUser) {
var participants = List.of(project.getCreator().getId(), sender.getId());

if (!participants.contains(tokenUser.getId())) {
throw new MatchingException(MATCHING_FORBIDDEN_OPERATION);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
package io.oeid.mogakgo.domain.matching.domain.entity.enums;

import static io.oeid.mogakgo.exception.code.ErrorCode400.MATCHING_CANCEL_NOT_ALLOWED;

import io.oeid.mogakgo.domain.matching.exception.MatchingException;
import lombok.Getter;

@Getter
public enum MatchingStatus {
PROGRESS,
CANCELED,
FINISHED
PROGRESS("매칭 진행중"),
CANCELED("매칭 취소됨"),
FINISHED("매칭 종료됨")
;

private final String description;

MatchingStatus(String description) {
this.description = description;
}

public void validateAvailableCancel() {
if (this != PROGRESS) {
throw new MatchingException(MATCHING_CANCEL_NOT_ALLOWED);
}
}
}
Loading

0 comments on commit 60fefe9

Please sign in to comment.