Skip to content

Commit 17958b0

Browse files
committed
feat: APPLE_USER 가입 파이프라인을 추가한다
1 parent c60ee13 commit 17958b0

9 files changed

Lines changed: 94 additions & 11 deletions

File tree

.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}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ import org.aspectj.lang.ProceedingJoinPoint
44
import org.aspectj.lang.annotation.Around
55
import org.aspectj.lang.annotation.Aspect
66
import org.gitanimals.core.auth.UserEntryPointValidationExtension.withUserEntryPointValidation
7+
import org.slf4j.LoggerFactory
78
import org.springframework.stereotype.Component
89

910
@Aspect
1011
@Component
1112
class RequiredUserEntryPointAspect {
1213

14+
private val logger = LoggerFactory.getLogger(this::class.simpleName)
15+
1316
@Around("@annotation(requiredUserEntryPoints)")
1417
fun validate(
1518
proceedingJoinPoint: ProceedingJoinPoint,
@@ -18,6 +21,12 @@ class RequiredUserEntryPointAspect {
1821
return withUserEntryPointValidation(
1922
expectedUserEntryPoints = requiredUserEntryPoints.expected,
2023
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+
}
2130
)
2231
}
2332
}

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,23 @@ object UserEntryPointValidationExtension {
99
fun <T> withUserEntryPointValidation(
1010
expectedUserEntryPoints: Array<UserEntryPoint>,
1111
onSuccess: () -> T,
12-
failMessage: () -> String = {
13-
"\"$expectedUserEntryPoints\" User cannot pass."
12+
failMessage: (UserEntryPoint?) -> String = { userEntryPoint ->
13+
"ExpectedUserEntryPoints: \"$expectedUserEntryPoints\" but request user entryPoint is \"$userEntryPoint\""
1414
}
1515
): T {
16-
val userEntryPoint = internalAuth.getUserEntryPoint {
17-
throw IllegalArgumentException(failMessage.invoke())
16+
val userEntryPoint = runCatching {
17+
val userEntryPointString = internalAuth.getUserEntryPoint {
18+
throw IllegalArgumentException(failMessage.invoke(null))
19+
}
20+
UserEntryPoint.valueOf(userEntryPointString)
21+
}.getOrElse {
22+
throw IllegalArgumentException(failMessage.invoke(null))
1823
}
1924

2025
require(
21-
expectedUserEntryPoints.contains(UserEntryPoint.ANY) ||
22-
UserEntryPoint.valueOf(userEntryPoint) in expectedUserEntryPoints
23-
) {
24-
failMessage.invoke()
25-
}
26+
expectedUserEntryPoints.contains(UserEntryPoint.ANY)
27+
|| userEntryPoint in expectedUserEntryPoints
28+
) { failMessage.invoke(userEntryPoint) }
2629

2730
return onSuccess.invoke()
2831
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.gitanimals.identity.app
2+
3+
import org.gitanimals.identity.domain.EntryPoint
4+
import org.gitanimals.identity.domain.UserService
5+
import org.springframework.beans.factory.annotation.Value
6+
import org.springframework.stereotype.Component
7+
8+
@Component
9+
class AppleLoginFacade(
10+
@Value("\${login.secret}") private val loginSecret: String,
11+
private val tokenManager: TokenManager,
12+
private val userService: UserService,
13+
) {
14+
15+
fun login(loginSecret: String, username: String, profileImage: String): String {
16+
require(loginSecret == this.loginSecret) {
17+
"Fail to login cause wrong loginSecret"
18+
}
19+
20+
val isExistsUser = userService.existsUser(username, EntryPoint.APPLE)
21+
22+
val user = when (isExistsUser) {
23+
true -> userService.getUserByNameAndEntryPoint(username, EntryPoint.APPLE)
24+
false -> {
25+
userService.newUser(
26+
username = username,
27+
entryPoint = EntryPoint.APPLE,
28+
profileImage = profileImage,
29+
contributionPerYears = mapOf(),
30+
)
31+
}
32+
}
33+
34+
return tokenManager.createToken(user).withType()
35+
}
36+
}

src/main/kotlin/org/gitanimals/identity/controller/Oauth2Controller.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.gitanimals.identity.controller
22

3+
import org.gitanimals.identity.app.AppleLoginFacade
34
import org.gitanimals.identity.app.GithubLoginFacade
5+
import org.gitanimals.identity.controller.request.AppleLoginRequest
46
import org.gitanimals.identity.controller.request.RedirectWhenSuccess
57
import org.springframework.beans.factory.annotation.Value
68
import org.springframework.http.HttpStatus
@@ -11,6 +13,7 @@ import org.springframework.web.bind.annotation.*
1113
class Oauth2Controller(
1214
@Value("\${oauth.client.id.github}") private val githubClientId: String,
1315
private val githubLoginFacade: GithubLoginFacade,
16+
private val appleLoginFacade: AppleLoginFacade,
1417
) {
1518

1619
@GetMapping("/logins/oauth/github")
@@ -43,4 +46,24 @@ class Oauth2Controller(
4346
)
4447
.build()
4548
}
49+
50+
@PostMapping("/logins/oauth/apple")
51+
fun loginWithAppleAndRedirect(
52+
@RequestHeader(
53+
name = "Redirect-When-Success",
54+
defaultValue = "HOME"
55+
) redirectWhenSuccess: RedirectWhenSuccess,
56+
@RequestHeader(name = "Login-Secret") loginSecret: String,
57+
@RequestBody appleLoginRequest: AppleLoginRequest,
58+
): ResponseEntity<Unit> {
59+
val token = appleLoginFacade.login(
60+
username = appleLoginRequest.name,
61+
profileImage = appleLoginRequest.profileImage,
62+
loginSecret = loginSecret,
63+
)
64+
65+
return ResponseEntity.status(HttpStatus.TEMPORARY_REDIRECT)
66+
.header("Location", redirectWhenSuccess.successUriWithToken(token))
67+
.build()
68+
}
4669
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.gitanimals.identity.controller.request
2+
3+
data class AppleLoginRequest(
4+
val name: String,
5+
val profileImage: String,
6+
)

src/main/resources/application.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ sentry.traces-sample-rate=1.0
3232

3333
internal.secret=
3434
internal.auth.secret=
35+
login.secret=
3536
test.secret=
3637
openai.key=
3738
openai.project=

src/test/resources/test.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ spring.jpa.properties.hibernate.use_sql_comments = true
1919

2020
internal.secret=foo
2121
internal.auth.secret=p4K86j8sl9LDufoN/2rpj8df+gc2SAGHUKKup6l695o=
22+
login.secret=foo
2223
test.secret=foo
2324
jwt.key=adsfbsadhfbsadghfavjshfvgqwehfvagvfhgasdvfghavsfvasghdfcvdsafhgadsgfhvasdhfgasdvfghdasvfas
2425

0 commit comments

Comments
 (0)