diff --git a/src/main/java/com/goormthon/backend/firstsori/domain/user/application/dto/.gitkeep b/src/main/java/com/goormthon/backend/firstsori/domain/user/application/dto/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/goormthon/backend/firstsori/domain/user/application/dto/response/LoginCheckResponse.java b/src/main/java/com/goormthon/backend/firstsori/domain/user/application/dto/response/LoginCheckResponse.java new file mode 100644 index 0000000..b36c8e3 --- /dev/null +++ b/src/main/java/com/goormthon/backend/firstsori/domain/user/application/dto/response/LoginCheckResponse.java @@ -0,0 +1,29 @@ +package com.goormthon.backend.firstsori.domain.user.application.dto.response; + +import com.goormthon.backend.firstsori.domain.user.domain.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class LoginCheckResponse { + private boolean validUser; + private boolean isOwner; + private boolean invalidToken; + + public static LoginCheckResponse invalidToken() { + return LoginCheckResponse.builder() + .validUser(false) + .isOwner(false) + .invalidToken(true) + .build(); + } + + public static LoginCheckResponse of(User user, boolean isOwner) { + return LoginCheckResponse.builder() + .validUser(true) + .isOwner(isOwner) + .invalidToken(false) + .build(); + } +} diff --git a/src/main/java/com/goormthon/backend/firstsori/domain/user/domain/service/LoginCheckService.java b/src/main/java/com/goormthon/backend/firstsori/domain/user/domain/service/LoginCheckService.java new file mode 100644 index 0000000..2cc4214 --- /dev/null +++ b/src/main/java/com/goormthon/backend/firstsori/domain/user/domain/service/LoginCheckService.java @@ -0,0 +1,29 @@ +package com.goormthon.backend.firstsori.domain.user.domain.service; + +import com.goormthon.backend.firstsori.domain.board.domain.repository.BoardRepository; +import com.goormthon.backend.firstsori.domain.user.application.dto.response.LoginCheckResponse; +import com.goormthon.backend.firstsori.domain.user.domain.entity.User; +import com.goormthon.backend.firstsori.global.auth.oauth2.domain.PrincipalDetails; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class LoginCheckService { + + private final BoardRepository boardRepository; + + public LoginCheckResponse checkLogin(PrincipalDetails principal, String shareUri) { + if (principal == null || principal.getUser() == null) { + return LoginCheckResponse.invalidToken(); + } + + User user = principal.getUser(); + + boolean isOwner = boardRepository.findByShareUri(shareUri) + .map(board -> board.getUser().equals(user)) + .orElse(false); + + return LoginCheckResponse.of(user, isOwner); + } +} diff --git a/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/AuthController.java b/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/AuthController.java index 6352a00..fa8eb0f 100644 --- a/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/AuthController.java +++ b/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/AuthController.java @@ -2,10 +2,12 @@ import com.goormthon.backend.firstsori.domain.board.application.dto.request.CreateBoardRequest; import com.goormthon.backend.firstsori.domain.board.application.usecase.BoardUseCase; +import com.goormthon.backend.firstsori.domain.user.application.dto.response.LoginCheckResponse; import com.goormthon.backend.firstsori.domain.user.application.usecase.UserUseCase; import com.goormthon.backend.firstsori.domain.user.domain.entity.User; import com.goormthon.backend.firstsori.domain.user.domain.entity.enums.Provider; import com.goormthon.backend.firstsori.domain.user.domain.entity.enums.Status; +import com.goormthon.backend.firstsori.domain.user.domain.service.LoginCheckService; import com.goormthon.backend.firstsori.domain.user.presentation.spec.AuthControllerSpec; import com.goormthon.backend.firstsori.global.auth.jwt.service.JwtTokenUseCase; import com.goormthon.backend.firstsori.global.auth.oauth2.domain.PrincipalDetails; @@ -20,9 +22,9 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; - import java.util.UUID; import static com.goormthon.backend.firstsori.domain.user.domain.entity.enums.Role.ADMIN; @@ -33,6 +35,7 @@ @RequiredArgsConstructor public class AuthController implements AuthControllerSpec { + private final LoginCheckService loginCheckService; private final JwtTokenUseCase tokenService; private final UserUseCase userService; private final BoardUseCase boardService; @@ -99,4 +102,15 @@ private User createDev() { } + // 유저 확인 (유효유저/조회 보드와 유저의 관계 확인) + @PostMapping("/check-login") + public ApiResponse checkLogin( + @AuthenticationPrincipal PrincipalDetails user, + @RequestParam String shareUri) { + + LoginCheckResponse response = loginCheckService.checkLogin(user, shareUri); + return ApiResponse.ok(response); + } + + } diff --git a/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/spec/AuthControllerSpec.java b/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/spec/AuthControllerSpec.java index cc6cc95..b0a626c 100644 --- a/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/spec/AuthControllerSpec.java +++ b/src/main/java/com/goormthon/backend/firstsori/domain/user/presentation/spec/AuthControllerSpec.java @@ -1,8 +1,10 @@ package com.goormthon.backend.firstsori.domain.user.presentation.spec; +import com.goormthon.backend.firstsori.domain.user.application.dto.response.LoginCheckResponse; import com.goormthon.backend.firstsori.global.auth.oauth2.domain.PrincipalDetails; import com.goormthon.backend.firstsori.global.common.response.ApiResponse; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.servlet.http.HttpServletRequest; @@ -50,4 +52,23 @@ ApiResponse logout( HttpServletRequest request, HttpServletResponse response); + @Operation( + summary = "로그인 상태 확인 API", + description = "쿠키(토큰)와 공유 링크 값을 전달하면, 유저의 로그인 상태와 보드 소유 여부를 반환합니다." + ) + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse( + responseCode = "200", + description = "정상 응답", + content = @io.swagger.v3.oas.annotations.media.Content( + mediaType = "application/json", + schema = @io.swagger.v3.oas.annotations.media.Schema(ref = "#/components/schemas/ApiResponseLoginCheck") + ) + ) + }) + ApiResponse checkLogin( + @AuthenticationPrincipal PrincipalDetails principal, + @Parameter(name = "shareUri", description = "접속하려는 보드의 공유 링크 값") String shareUri + ); + } diff --git a/src/main/java/com/goormthon/backend/firstsori/global/auth/jwt/filter/RequestMatcherHolder.java b/src/main/java/com/goormthon/backend/firstsori/global/auth/jwt/filter/RequestMatcherHolder.java index b579609..2ce76fe 100644 --- a/src/main/java/com/goormthon/backend/firstsori/global/auth/jwt/filter/RequestMatcherHolder.java +++ b/src/main/java/com/goormthon/backend/firstsori/global/auth/jwt/filter/RequestMatcherHolder.java @@ -30,6 +30,7 @@ public class RequestMatcherHolder { new RequestInfo(GET, "/api/v1/oauth2/**", null), new RequestInfo(GET, "/oauth2/authorization/**", null), // Spring Security 기본 엔드포인트 new RequestInfo(GET, "/login/oauth2/code/**", null), // callback URL + new RequestInfo(POST,"/api/v1/auth/check-login", null), // 유저 관련 new RequestInfo(POST, "/api/v1/auth/reissue", null),