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

[🚌 Issue] dev api 로그인 요청 위치에 따라 redirect url 변환 #245

Merged
merged 25 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b99367c
delete: 유저 정보를 활용한 타임라인 조회 API 삭제
egg528 Mar 24, 2024
4249f81
refactor: PaginationResult.transform() 사용 방식 lamda 형태로 통일
egg528 Mar 24, 2024
854f4a2
refactor: 메서드 로직에 따라 get, find 명칭 구분
egg528 Mar 24, 2024
23aa5f9
refactor: lamda body 내 생략 가능한 parameter 생략
egg528 Mar 24, 2024
1c7d46f
refactor: 메서드명 내 부정확한 단어 제거(findGoalTimelineCountMap -> findGoalCount…
egg528 Mar 24, 2024
74b372b
refactor: associateWith 메서드 활용
egg528 Mar 24, 2024
54c8b81
refactor: PaginationResult total값 Long으로 다시 변경
egg528 Mar 24, 2024
ef9f69d
Merge branch 'develop' of github.com:depromeet/amazing3-be into featu…
egg528 Mar 26, 2024
30b557b
fix: 목표 피드 조회 API deadline 역순으로 정렬 조회
egg528 Mar 26, 2024
89264c7
Merge branch 'develop' of github.com:depromeet/amazing3-be into featu…
egg528 Mar 26, 2024
5425558
chore: apply lint
egg528 Mar 26, 2024
48e2709
fix: goals 테이블의 index 수정
egg528 Mar 26, 2024
a9135a1
refactor: pagination cusorId type Any -> Generic으로 변경
egg528 Mar 26, 2024
63bb7e9
Merge branch 'develop' of github.com:depromeet/amazing3-be into featu…
egg528 Mar 27, 2024
4c110bc
fix: 타임 라인 목표 조회 API paging 처리 방식 offset으로 변경
egg528 Mar 27, 2024
bb151c4
refactor: cursor 기반 pagination 공통 모듈 cursor type long으로 통일
egg528 Mar 27, 2024
0a00a11
refactor: pagination 공통 모듈 cursor와 offset 구분
egg528 Mar 27, 2024
c94c5b5
feat(#244): dev api 로그인 요청 위치에 따라 redirect url 변환
egg528 Mar 27, 2024
e97bc4e
chore: apply lint
egg528 Mar 27, 2024
583201f
fix: @Value(spring.profiles.active) default값 추가
egg528 Mar 27, 2024
e307c2d
refactor: 코드 리뷰 반영(#245)
egg528 Mar 28, 2024
1073e18
chore: encrypt하던 데이터 삭제
egg528 Mar 28, 2024
39ce4cc
chore: resolve conflict
egg528 Mar 28, 2024
128357d
chore: encrypted test properties 삭제
egg528 Mar 28, 2024
e27bb5b
chore: referer 저장/조회 logging 추가
egg528 Mar 31, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.raemian.api.cheer.model.CheererResult
import io.raemian.api.cheer.model.CheeringCountResult
import io.raemian.api.cheer.service.CheeringService
import io.raemian.api.support.response.ApiResponse
import io.raemian.api.support.response.PaginationResult
import io.raemian.api.support.response.CursorPaginationResult
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
Expand All @@ -25,7 +25,7 @@ class CheeringController(
fun findCheeringSquad(
@PathVariable("lifeMapId") lifeMapId: Long,
request: CheeringSquadPageRequest,
): ResponseEntity<ApiResponse<PaginationResult<Long, CheererResult>>> =
): ResponseEntity<ApiResponse<CursorPaginationResult<CheererResult>>> =
ResponseEntity.ok().body(ApiResponse.success(cheeringService.findCheeringSquad(lifeMapId, request)))

@GetMapping("/count/{userName}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.raemian.api.support.limiter
package io.raemian.api.cheer.service

import com.github.benmanes.caffeine.cache.Caffeine
import org.springframework.stereotype.Component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@ import io.raemian.api.cheer.model.CheeringCountResult
import io.raemian.api.event.model.CheeredEvent
import io.raemian.api.support.exception.CoreApiException
import io.raemian.api.support.exception.ErrorInfo
import io.raemian.api.support.limiter.CheeringLimiter
import io.raemian.api.support.response.PaginationResult
import io.raemian.api.support.response.CursorPaginationResult
import io.raemian.storage.db.core.cheer.CheerJdbcQueryRepository
import io.raemian.storage.db.core.cheer.Cheerer
import io.raemian.storage.db.core.cheer.CheererRepository
import io.raemian.storage.db.core.cheer.Cheering
import io.raemian.storage.db.core.cheer.CheeringRepository
import io.raemian.storage.db.core.cheer.model.CheererQueryResult
import io.raemian.storage.db.core.common.pagination.CursorPaginationResult
import io.raemian.storage.db.core.common.pagination.CursorPaginationTemplate
import io.raemian.storage.db.core.common.pagination.PaginationResult
import io.raemian.storage.db.core.lifemap.LifeMapRepository
import io.raemian.storage.db.core.user.UserRepository
import org.springframework.context.ApplicationEventPublisher
Expand Down Expand Up @@ -46,15 +45,15 @@ class CheeringService(
}

@Transactional(readOnly = true)
fun findCheeringSquad(lifeMapId: Long, request: CheeringSquadPageRequest): PaginationResult<Long, CheererResult> {
fun findCheeringSquad(lifeMapId: Long, request: CheeringSquadPageRequest): CursorPaginationResult<CheererResult> {
val cheering = cheeringRepository.findByLifeMapId(lifeMapId)
?: Cheering(0, lifeMapId)

val cheeringSquad = findCheeringSquadWithCursor(lifeMapId, request)

val filteredCheeringSquad = cheeringSquad.transform { CheererResult.from(it) }

return PaginationResult.from(cheering.count, filteredCheeringSquad)
return CursorPaginationResult.from(cheering.count, filteredCheeringSquad)
}

@Transactional(readOnly = true)
Expand Down Expand Up @@ -89,7 +88,7 @@ class CheeringService(
)
}

private fun findCheeringSquadWithCursor(lifeMapId: Long, request: CheeringSquadPageRequest): CursorPaginationResult<Long, CheererQueryResult> {
private fun findCheeringSquadWithCursor(lifeMapId: Long, request: CheeringSquadPageRequest): PaginationResult<CheererQueryResult> {
return CursorPaginationTemplate.execute(lifeMapId, request.cursor ?: Long.MAX_VALUE, request.size) {
id, cursor, size ->
cheererJdbcQueryRepository.findAllByLifeMapWithCursor(id, cursor, size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import io.raemian.api.auth.converter.TokenRequestEntityConverter
import io.raemian.api.auth.model.CurrentUser
import io.raemian.api.auth.service.OAuth2UserService
import io.raemian.api.support.constant.WebSecurityConstant
import io.raemian.api.support.security.LoginRedirector
import io.raemian.api.support.security.StateOAuth2AuthorizationRequestRepository
import io.raemian.api.support.security.TokenProvider
import jakarta.servlet.http.HttpServletResponse
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.security.config.annotation.SecurityConfigurerAdapter
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
Expand All @@ -25,16 +24,14 @@ import org.springframework.security.web.DefaultSecurityFilterChain
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import org.springframework.web.filter.CorsFilter
import java.nio.charset.StandardCharsets

@Configuration
@EnableWebSecurity
class WebSecurityConfig(
private val corsFilter: CorsFilter,
private val tokenProvider: TokenProvider,
private val oAuth2UserService: OAuth2UserService,
@Value("\${spring.profiles.active:local}")
private val profile: String,
private val loginRedirector: LoginRedirector,
private val tokenRequestEntityConverter: TokenRequestEntityConverter,
private val httpCookieOAuth2AuthorizationRequestRepository: StateOAuth2AuthorizationRequestRepository,
) : SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>() {
Expand Down Expand Up @@ -66,23 +63,9 @@ class WebSecurityConfig(
it.authorizationEndpoint { it.authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository) }
it.successHandler { request, response, authentication ->
val user = authentication.principal as CurrentUser
response.contentType = MediaType.APPLICATION_JSON_VALUE
response.characterEncoding = StandardCharsets.UTF_8.name()

val tokenDTO = tokenProvider.generateTokenDto(user)
response.setHeader("x-token", tokenDTO.accessToken)
log.info("x-token access ${tokenDTO.accessToken}")

// TODO edit redirect url
val referer = request.getHeader("referer")
val redirectUrl =
if (profile == "live") {
"https://bandiboodi.com/oauth2/token"
} else {
"http://localhost:3000/oauth2/token"
}

response.sendRedirect("$redirectUrl?token=${tokenDTO.accessToken}&refresh=${tokenDTO.refreshToken}")
val token = tokenProvider.generateTokenDto(user)
val redirectUrl = loginRedirector.getUrl(request.getParameter("state"), token)
response.sendRedirect(redirectUrl)
}
it.failureHandler { request, response, exception ->
log.error("x-token error ${exception.message}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package io.raemian.api.goal.controller.request

import java.time.LocalDateTime

data class TimelinePageRequest(
val cursor: LocalDateTime?,
val size: Int,
val page: Int = 0,
val size: Int = 20,
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,46 @@ import io.raemian.api.goal.controller.request.TimelinePageRequest
import io.raemian.api.goal.model.GoalTimelineCountSubset
import io.raemian.api.goal.model.GoalTimelinePageResult
import io.raemian.api.lifemap.service.LifeMapService
import io.raemian.api.support.constant.LocalDateTimeConstant
import io.raemian.api.support.response.PaginationResult
import io.raemian.api.support.response.OffsetPaginationResult
import io.raemian.api.task.service.TaskService
import io.raemian.storage.db.core.common.pagination.CursorPaginationResult
import io.raemian.storage.db.core.common.pagination.CursorPaginationTemplate
import io.raemian.storage.db.core.goal.GoalJdbcQueryRepository
import io.raemian.storage.db.core.goal.model.GoalQueryResult
import io.raemian.storage.db.core.goal.GoalRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime

@Service
class GoalQueryService(
private val lifeMapService: LifeMapService,
private val goalJdbcQueryRepository: GoalJdbcQueryRepository,
private val goalRepository: GoalRepository,
private val emojiService: EmojiService,
private val taskService: TaskService,
private val commentService: CommentService,
) {
@Transactional(readOnly = true)
fun findAllByUsernameWithCursor(username: String, request: TimelinePageRequest): PaginationResult<LocalDateTime, GoalTimelinePageResult> {
fun findAllByUsernameWithOffset(username: String, request: TimelinePageRequest): OffsetPaginationResult<GoalTimelinePageResult> {
val lifeMap = lifeMapService.getFirstByUserName(username)
val goals = findAllByLifeMapIdWithCursor(lifeMap.lifeMapId, request)
val goals = goalJdbcQueryRepository.findAllByLifeMapWithOffset(lifeMap.lifeMapId, request.page, request.size)
val total = goalRepository.countByLifeMapId(lifeMap.lifeMapId)

val goalIds = goals.contents.map { it.goalId }
val goalIds = goals.map { it.goalId }

val goalCountMap = findGoalCountMap(goalIds)
val reactedEmojiMap = emojiService.findAllByGoalIds(goalIds, lifeMap.user.id)

return PaginationResult.from(
lifeMap.goals.size,
goals.transform {
goals.map {
GoalTimelinePageResult.from(
goal = it,
counts = goalCountMap[it.goalId],
reactedEmojisResult = reactedEmojiMap[it.goalId],
)
}

return OffsetPaginationResult.of(
request.page,
request.size,
total,
goals.map {
GoalTimelinePageResult.from(
goal = it,
counts = goalCountMap[it.goalId],
Expand All @@ -58,11 +66,4 @@ class GoalQueryService(
)
}
}

private fun findAllByLifeMapIdWithCursor(lifeMapId: Long, request: TimelinePageRequest): CursorPaginationResult<LocalDateTime, GoalQueryResult> {
return CursorPaginationTemplate.execute(lifeMapId, request.cursor ?: LocalDateTimeConstant.MAX, request.size) {
id, cursor, size ->
goalJdbcQueryRepository.findAllByLifeMapWithCursor(id, cursor, size)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ import io.raemian.api.goal.service.GoalQueryService
import io.raemian.api.lifemap.model.LifeMapResponse
import io.raemian.api.lifemap.service.LifeMapService
import io.raemian.api.support.response.ApiResponse
import io.raemian.api.support.response.PaginationResult
import io.raemian.api.support.response.OffsetPaginationResult
import io.swagger.v3.oas.annotations.Operation
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime

@RestController
@RequestMapping("/open/life-map")
Expand Down Expand Up @@ -51,8 +50,8 @@ class OpenLifeMapController(
fun getTimeline(
@PathVariable("username") username: String,
request: TimelinePageRequest,
): ResponseEntity<ApiResponse<PaginationResult<LocalDateTime, GoalTimelinePageResult>>> {
val goalTimeline = goalQueryService.findAllByUsernameWithCursor(username, request)
): ResponseEntity<ApiResponse<OffsetPaginationResult<GoalTimelinePageResult>>> {
val goalTimeline = goalQueryService.findAllByUsernameWithOffset(username, request)
return ResponseEntity.ok(ApiResponse.success(goalTimeline))
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
package io.raemian.api.support.response

import io.raemian.storage.db.core.common.pagination.CursorPaginationResult
import io.raemian.storage.db.core.common.pagination.PaginationResult

data class PaginationResult<CursorType, T>(
data class CursorPaginationResult<T>(
val total: Long,
val contents: List<T>,
val isLast: Boolean,
val nextCursor: CursorType?,
val nextCursor: Long?,
) {
companion object {
fun <CursorType, T> from(total: Long, result: CursorPaginationResult<CursorType, T>): PaginationResult<CursorType, T> {
return PaginationResult(
fun <T> from(total: Long, result: PaginationResult<T>): CursorPaginationResult<T> {
return CursorPaginationResult(
total = total,
contents = result.contents,
isLast = result.isLast,
nextCursor = result.nextCursor,
)
}

fun <CursorType, T> from(total: Int, result: CursorPaginationResult<CursorType, T>): PaginationResult<CursorType, T> {
return PaginationResult(
fun <T> from(total: Int, result: PaginationResult<T>): CursorPaginationResult<T> {
return CursorPaginationResult(
total = total.toLong(),
contents = result.contents,
isLast = result.isLast,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.raemian.api.support.response

data class OffsetPaginationResult<T>(
val total: Long,
val page: Int,
val size: Int,
val contents: List<T>,
) {
companion object {
fun <T> of(page: Int, size: Int, total: Long, contents: List<T>): OffsetPaginationResult<T> {
return OffsetPaginationResult(total, page, size, contents)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.raemian.api.support.security

import io.raemian.api.auth.model.Token
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

@Component
class LoginRedirector(
@Value("\${spring.profiles.active:local}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

최근에 이런 방법도 봤네요. 값들이 모여있고, 객체로 관리하고, 리팩토링 하기 쉬운 장점이 있는거 같은데 한번 슥 봐주세요 절대 이거 도입해보자 아닙니다!!
https://medium.com/@mikael_55667/why-you-should-stop-using-value-annotations-in-spring-and-use-this-instead-2c8a47e5096a

Copy link
Member Author

@egg528 egg528 Mar 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 진호님이 얘기해주신 ConfigurationProperties 사용하는 방식 좋아합니다!
저희 프로젝트에 AppleLoginProps 객체에 사용하기도 했구요
다만 저는 한번에 많은 값을 주입해야 할 때 ConfigurationProperties를 고려했던 것 같습니다!
Profile을 담을 객체에 주입할 값이 많아진다면 ConfigurationProperties 사용하는 방식 좋은 것 같아요 👍

private val profile: String,
val loginRequestRefererStorage: LoginRequestRefererStorage,
) {
fun getUrl(state: String, token: Token): String {
if (profile == "live") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프로필을 한번 Wraaping하는 객체가 있으면 어떨까 싶은데, 한번 같이 고민해주실 수 있나요?
profile 값을 갖는 유틸이 있어서, 그 유틸 객체에게 메서드로 질의하는 방법도 괜찮을 것 같아서요

ProfileHolder or ProfileUtil이라는 이름의 객체가 있다면
ProfileHolder.isLive(), ProfileHolder.isDev() 와 같은 식으로 메서드를 통해 질의하면,
제가 자주 경계하는 실수의 가능성이 있는 raw한 string의 사용을 없앨 수도 있고, 객체지향 적으로도 좋은 것 같고, 코드도 깔끔해질 수도 있을 것 같아요. 그리고 리팩토링시 인텔리제이의 도움을 받기도 좋을 것 같아요.

더 나아가 괜찮은 구현인지는 모르겠지만, 상태에 따라 RedirectURL을 반환하는 객체가 있는 것도 괜찮을 것 같아요.
ProfileRedirectUrlHolder.getRedirectUrl()과 같이 스스로 Profile을 확인하고, 그에 맞는 Redirect URL을 반환하는 건 어떨까 해서요. ex) live의 경우 "https://bandiboodi.com 반환

토큰 값에 대한 파라미터는 따로 붙여주거나, 따로 붙여주는 Util 클래스가 있거나, 아니면 토큰 값들을 넣으면 토큰 값까지 모두 포함된 RedirectUrl을 반환하는 객체가 있는 것도 괜찮을 것 같아요 (마지막은 과한 것 같기도 합니다)

Copy link
Member Author

@egg528 egg528 Mar 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

객체를 어떤 단위까지 분리할까는 항상 고민이 되는 부분인 것 같습니다 ㅎㅎ
진호님이 말씀하신 걸 정리해보면 아래와 같이 객체가 생겨날 것 같습니다

  1. ProfileHolder(or ProfileUtil) -> profile 값을 주입 받아 현재 application의 profile을 반환하는 책임
  2. ProfileRedirectUrlHolder -> referer값을 기반으로 RedirectUrl의 host + path까지 반환 책임
  3. 토큰 값을 붙여주는 역할의 객체 -> token을 받아 query string으로 붙여주는 책임
  4. 최종 redirectUrl을 반환하는 객체

사실 저는 작업하면서 이렇게까지 객체를 분리하지는 않았던 것 같습니다.
하지만 진호님이 제시해주신 ProfileHolder.isLive(), ProfileHolder.isDev() 메서드가 너무 깔끔해보인다는 생각이 들었고,
StateOAuth2AuthorizationRequestRepository에서 재사용된다는 장점을 생각했을 때 적용해보고 싶다는 생각이 들었습니다 ㅎㅎ

우선은 ProfileHolder로 현재 application의 profile을 알려주는 책임을 가지는 객체 만들어 반영해보겠습니다.
정성스러운 리뷰 감사합니다 ❤️

return "https://bandiboodi.com/oauth2/token?token=${token.accessToken}&refresh=${token.refreshToken}"
}

val referer = loginRequestRefererStorage.get(state)

if (profile == "dev" && referer.contains("dev-bandiboodi")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 저번에 말씀 드렸던 대로 dev 클라이언트 유출에 대한 우려가 있습니다.
    물론 저도 실제로 사용하는 사람이 있긴 할까..싶기는 한데, 저희가 관리하지 않는 데이터가 dev-db에 저장될 수도 있는 상황이 조금 꺼려집니다. 어떻게 생각하실까요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗!! 이번에 제거한다는 걸 깜빡했네요 ㅎㅎ
확인 감사해요 👍

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

별거 아닌데 프로필에 대한 비교값을 문자열이 아닌 enum 으로 관리하는게 좋긴할듯 (referer 도 enum 으로)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 위에 진호가 말했구나 ㅎㅎ

Copy link
Member Author

@egg528 egg528 Mar 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

같은 부분을 형은 enum으로, 진호는 현재 profile을 원하는 값과 비교해주는 객체 메서드로 바꾸는 방향을 제안해줬는데
둘 다 적용해보겠습니다 👍

return "https://dev-bandiboodi.vercel.app/oauth2/token?token=${token.accessToken}&refresh=${token.refreshToken}"
}

return "http://localhost:3000/oauth2/token?token=${token.accessToken}&refresh=${token.refreshToken}"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.raemian.api.support.security

import com.github.benmanes.caffeine.cache.Caffeine
import org.springframework.stereotype.Component
import java.util.concurrent.TimeUnit

@Component
class LoginRequestRefererStorage {
private val timedStorage = Caffeine.newBuilder()
.expireAfterWrite(60L, TimeUnit.SECONDS)
.build<String, String>()

fun put(state: String, referer: String?) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[[ 100% 취향 제안 ]]
저도 자바에 익숙해서 우석님이랑 항상 같은 방식으로 코드를 작성했는데요?
요즘 코틀린 코드들 다른데서 보면서 아래와 같은 코드도 조금 이뻐 보이이기 시작했는데 어떠신가요..

put() = if (referer.isNullOrBlank()) return
else timedStorage.put(state, referer)

혹은.. 확장함수 활용해서 isNotNullOrBlank() 구현한 다음..

fun put() {
  if (referer.isNotNullOrBlank()) 
    timedStorage.put(state, referer)
}

완전 취향이고 지금 얼리 리턴 방식도 너무 좋아요 저도 보통 그렇게 작성해왔던 것 같아요.
어떤지 한번 얘기해보고 싶어서 올려봐요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 얼리 리턴을 위한 조건문은 명시적으로 작성하는 편이 잘 읽힌다고 생각하는 편이였는데요.
진호님이 제시해주신 첫번째 코드 (if문 Expression으로 사용)를 보니 한번 사용해보고 싶다는 생각이 들었습니다 ㅎㅎ
첫번째 방식으로 수정 한번 해보겠습니다!
제안 감사합니다 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@binary-ho
제안 감사합니다 👍

추가 제안 ㅆㄱㄴ

if (referer.isNullOrBlank()) {
return
}

timedStorage.put(state, referer)
}

fun get(state: String): String {
return timedStorage.getIfPresent(state) ?: ""
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.beans.factory.annotation.Value
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest
import org.springframework.stereotype.Component
import java.util.concurrent.TimeUnit

@Component
class StateOAuth2AuthorizationRequestRepository() : AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
class StateOAuth2AuthorizationRequestRepository(
@Value("\${spring.profiles.active:local}")
private val profile: String,
val loginRequestRefererStorage: LoginRequestRefererStorage,
) : AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
private val oauthRequestStorage: Cache<String, OAuth2AuthorizationRequest> = Caffeine.newBuilder()
.expireAfterWrite(60L, TimeUnit.SECONDS)
.build()
Expand All @@ -25,6 +30,11 @@ class StateOAuth2AuthorizationRequestRepository() : AuthorizationRequestReposito
response: HttpServletResponse,
) {
if (authorizationRequest != null) {
/*** for frontend dev test ***/
if (profile == "dev") {
loginRequestRefererStorage.put(authorizationRequest.state, request.getParameter("referer"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프로필래핑 객체가 있다면 여기서도 활용이 가능하다는 장점 ㅎㅎ (어필)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제안 감사합니다 👍

추가 제안 ㅆㄱㄴ

}

oauthRequestStorage.put(authorizationRequest.state, authorizationRequest)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ data class CheererQueryResult(
val userNickName: String?,
val userImageUrl: String?,
val cheeringAt: LocalDateTime,
) : CursorExtractable<Long> {
) : CursorExtractable {
override fun cursorId(): Long = cheererId
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package io.raemian.storage.db.core.common.pagination

interface CursorExtractable<CursorType> {
fun cursorId(): CursorType
interface CursorExtractable {
fun cursorId(): Long
}
Loading
Loading