Skip to content

Commit eca63e3

Browse files
authored
release: 1.5.8 (#171)
2 parents 903fe75 + 7033f25 commit eca63e3

37 files changed

+436
-42
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ jobs:
8787
"QUIZ_APPROVE_TOKEN=${{ secrets.QUIZ_APPROVE_TOKEN }}"
8888
"RELAY_APPROVE_TOKEN=${{ secrets.RELAY_APPROVE_TOKEN }}"
8989
"INTERNAL_AUTH_SECRET=${{ secrets.INTERNAL_AUTH_SECRET }}"
90+
"LOGIN_SECRET=${{ secrets.LOGIN_SECRET }}"
9091
9192
- name: build and push filebeat
9293
uses: docker/build-push-action@v4

deploy/api/Dockerfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ ARG ELASTIC_SEARCH_PASSWORD
2222
ARG QUIZ_APPROVE_TOKEN
2323
ARG RELAY_APPROVE_TOKEN
2424
ARG INTERNAL_AUTH_SECRET
25+
ARG LOGIN_SECRET
2526

2627
ARG JAR_FILE=./*.jar
2728
COPY ${JAR_FILE} gitanimals-api.jar
@@ -47,7 +48,8 @@ ENV db_url=${DB_URL} \
4748
elastic_search_password=${ELASTIC_SEARCH_PASSWORD} \
4849
quiz_approve_token=${QUIZ_APPROVE_TOKEN} \
4950
relay_approve_token=${RELAY_APPROVE_TOKEN} \
50-
internal_auth_secret=${INTERNAL_AUTH_SECRET}
51+
internal_auth_secret=${INTERNAL_AUTH_SECRET} \
52+
login_secret=${LOGIN_SECRET}
5153

5254
ENTRYPOINT java -Djava.net.preferIPv4Stack=true -jar gitanimals-api.jar \
5355
--spring.datasource.url=${db_url} \
@@ -71,4 +73,5 @@ ENTRYPOINT java -Djava.net.preferIPv4Stack=true -jar gitanimals-api.jar \
7173
--spring.elasticsearch.password=${elastic_search_password} \
7274
--quiz.approve.token=${quiz_approve_token} \
7375
--relay.approve.token=${relay_approve_token} \
74-
--internal.auth.secret=${internal_auth_secret}
76+
--internal.auth.secret=${internal_auth_secret} \
77+
--login.secret=${login_secret}

docs/api/identity/get_user_by_token.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"id": "1",
1616
"username": "devxb",
1717
"points": "491128",
18-
"profileImage": "https://avatars.githubusercontent.com/u/62425964?v=4"
18+
"profileImage": "https://avatars.githubusercontent.com/u/62425964?v=4",
19+
"entryPoint": "GITHUB" // GITHUB OR APPLE
1920
}
2021
```

docs/api/identity/login-apple.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# APPLE login
2+
3+
## Request
4+
### HTTP METHOD : `POST`
5+
### url : `https://api.gitanimals.org/logins/oauth/apple`
6+
### Header
7+
- Redirect-When-Success : `HOME`, `ADMIN`, `LOCAL`, `LOCAL_ADMIN` 중 하나를 입력해주세요. HOME은 로그인 성공시 홈페이지로 로그인, ADMIN은 로그인 성공시 어드민 페이지로 리다이렉트 됩니다. LOCAL은 `http://localhost:3000?jwt={jwt}` 로 리다이렉트 됩니다.
8+
- Login-Secret: 내부 로그인 토큰을 전달 하세요.
9+
10+
### Request Body
11+
```json
12+
{
13+
"name": "유저의 이름",
14+
"profileImage": "유저의 프로필 이미지"
15+
}
16+
```
17+
18+
# Response
19+
로그인 성공시 등록한 url로 jwt를 전달합니다.
20+
ADMIN : `https://admin.gitanimals.org?jwt={jwtToken}`
21+
HOME : `https://www.gitanimals.org?jwt={jwtToken}`
22+
LOCAL : `http://localhost:3000?jwt={jwtToken}`
23+
LOCAL_ADMIN : `http://localhost:5173?jwt={jwtToken}`

gradle/spring.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ jar {
55
dependencies {
66
implementation "org.springframework.boot:spring-boot-starter"
77
implementation "org.springframework.boot:spring-boot-starter-web"
8+
implementation "org.springframework.boot:spring-boot-starter-aop"
89
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
910
implementation "org.springframework.boot:spring-boot-starter-data-redis"
1011
implementation "org.springframework.boot:spring-boot-starter-actuator"

src/main/kotlin/org/gitanimals/core/auth/InternalAuth.kt

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.gitanimals.core.auth
33
import jakarta.servlet.http.HttpServletRequest
44
import org.gitanimals.core.AUTHORIZATION_EXCEPTION
55
import org.gitanimals.core.AuthorizationException
6+
import org.gitanimals.core.filter.MDCFilter.Companion.USER_ENTRY_POINT
67
import org.gitanimals.core.filter.MDCFilter.Companion.USER_ID
78
import org.slf4j.LoggerFactory
89
import org.slf4j.MDC
@@ -29,7 +30,7 @@ class InternalAuth(
2930
SecretKeySpec(decodedKey, "AES")
3031
}
3132

32-
fun getUserId(throwOnFailure: () -> Unit = throwCannotGetUserId): Long {
33+
fun getUserId(throwOnFailure: () -> Unit = throwCannotGetUserInfo): Long {
3334
val userId = findUserId()
3435

3536
if (userId == null) {
@@ -80,6 +81,36 @@ class InternalAuth(
8081
return userId
8182
}
8283

84+
fun getUserEntryPoint(throwOnFailure: () -> Unit = throwCannotGetUserInfo): String {
85+
val entryPoint = findUserEntryPoint()
86+
87+
if (entryPoint == null) {
88+
throwOnFailure.invoke()
89+
}
90+
91+
return entryPoint ?: throw AUTHORIZATION_EXCEPTION
92+
}
93+
94+
fun findUserEntryPoint(): String? {
95+
val entryPointInMdc = runCatching {
96+
MDC.get(USER_ENTRY_POINT)
97+
}.getOrNull()
98+
99+
if (entryPointInMdc != null) {
100+
return entryPointInMdc
101+
}
102+
103+
httpServletRequest.getHeader(INTERNAL_ENTRY_POINT_KEY)?.let {
104+
return it
105+
}
106+
107+
val token: String = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION) ?: return null
108+
109+
return runCatching {
110+
internalAuthClient.getUserByToken(token).entryPoint
111+
}.getOrNull()
112+
}
113+
83114
private fun decrypt(iv: ByteArray, secret: ByteArray): Long {
84115
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
85116
val spec = GCMParameterSpec(128, iv)
@@ -108,8 +139,9 @@ class InternalAuth(
108139
companion object {
109140
const val INTERNAL_AUTH_IV_KEY = "Internal-Auth-Iv"
110141
const val INTERNAL_AUTH_SECRET_KEY = "Internal-Auth-Secret"
142+
const val INTERNAL_ENTRY_POINT_KEY = "Internal-Entry-Point"
111143

112-
private val throwCannotGetUserId: () -> Unit = {
144+
private val throwCannotGetUserInfo: () -> Unit = {
113145
throw AUTHORIZATION_EXCEPTION
114146
}
115147
}

src/main/kotlin/org/gitanimals/core/auth/InternalAuthClient.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fun interface InternalAuthClient {
2222

2323
data class UserResponse(
2424
val id: String,
25+
val entryPoint: String,
2526
)
2627
}
2728

src/main/kotlin/org/gitanimals/core/auth/InternalAuthRequestInterceptor.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.gitanimals.core.auth
22

3+
import org.gitanimals.core.filter.MDCFilter.Companion.USER_ENTRY_POINT
34
import org.gitanimals.core.filter.MDCFilter.Companion.USER_ID
45
import org.slf4j.MDC
56
import org.springframework.http.HttpRequest
@@ -23,6 +24,10 @@ class InternalAuthRequestInterceptor(
2324
MDC.get(USER_ID).toLong()
2425
}.getOrNull()
2526

27+
val userEntryPoint = runCatching {
28+
MDC.get(USER_ENTRY_POINT)
29+
}.getOrNull()
30+
2631
if (userId != null) {
2732
val encrypt = internalAuth.encrypt(userId = userId)
2833

@@ -34,6 +39,10 @@ class InternalAuthRequestInterceptor(
3439
InternalAuth.INTERNAL_AUTH_IV_KEY,
3540
Base64.getEncoder().encodeToString(encrypt.iv),
3641
)
42+
request.headers.add(
43+
InternalAuth.INTERNAL_ENTRY_POINT_KEY,
44+
userEntryPoint,
45+
)
3746
}
3847

3948
return execution.execute(request, body)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.gitanimals.core.auth
2+
3+
import org.aspectj.lang.ProceedingJoinPoint
4+
import org.aspectj.lang.annotation.Around
5+
import org.aspectj.lang.annotation.Aspect
6+
import org.gitanimals.core.auth.UserEntryPointValidationExtension.withUserEntryPointValidation
7+
import org.slf4j.LoggerFactory
8+
import org.springframework.stereotype.Component
9+
10+
@Aspect
11+
@Component
12+
class RequiredUserEntryPointAspect {
13+
14+
private val logger = LoggerFactory.getLogger(this::class.simpleName)
15+
16+
@Around("@annotation(requiredUserEntryPoints)")
17+
fun validate(
18+
proceedingJoinPoint: ProceedingJoinPoint,
19+
requiredUserEntryPoints: RequiredUserEntryPoints,
20+
): Any? {
21+
return withUserEntryPointValidation(
22+
expectedUserEntryPoints = requiredUserEntryPoints.expected,
23+
onSuccess = { proceedingJoinPoint.proceed() },
24+
failMessage = {
25+
val message =
26+
"ExpectedUserEntryPoints: \"${requiredUserEntryPoints.expected}\" but request user entryPoint is \"$it\""
27+
logger.info("[RequiredUserEntryPointAspect] $message")
28+
message
29+
}
30+
)
31+
}
32+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.gitanimals.core.auth
2+
3+
@Target(AnnotationTarget.FUNCTION)
4+
@Retention(AnnotationRetention.RUNTIME)
5+
annotation class RequiredUserEntryPoints(
6+
val expected: Array<UserEntryPoint>,
7+
)
8+
9+
enum class UserEntryPoint {
10+
ANY,
11+
GITHUB,
12+
APPLE,
13+
;
14+
}

0 commit comments

Comments
 (0)