Skip to content

Commit 0931769

Browse files
committed
feat: github username이 변경되어도 이전 펫들이 유지되도록 수정한다
1 parent ffe71b8 commit 0931769

17 files changed

Lines changed: 249 additions & 32 deletions

File tree

src/main/kotlin/org/gitanimals/render/app/AnimationFacade.kt

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package org.gitanimals.render.app
22

33
import org.gitanimals.core.Mode
44
import org.gitanimals.core.filter.MDCFilter.Companion.TRACE_ID
5+
import org.gitanimals.render.domain.EntryPoint
56
import org.gitanimals.render.domain.User
67
import org.gitanimals.render.domain.UserService
78
import org.gitanimals.render.domain.event.NewUserCreated
@@ -18,46 +19,71 @@ class AnimationFacade(
1819
private val contributionApi: ContributionApi,
1920
private val sagaManager: SagaManager,
2021
private val eventPublisher: ApplicationEventPublisher,
22+
private val githubOpenApi: GithubOpenApi,
2123
) {
2224

2325
fun getFarmAnimation(username: String): String {
2426
return when (userService.existsByName(username)) {
2527
true -> {
28+
setUserAuthInfoIfNotSet(username)
29+
2630
val svgAnimation = userService.getFarmAnimationByUsername(username)
2731
eventPublisher.publishEvent(Visited(username, MDC.get(TRACE_ID)))
2832
svgAnimation
2933
}
3034

3135
false -> {
3236
val user = createNewUser(username)
33-
sagaManager.startSync(NewUserCreated(user.id, user.name))
34-
userService.getFarmAnimationByUsername(user.name)
37+
sagaManager.startSync(NewUserCreated(user.id, user.getName()))
38+
userService.getFarmAnimationByUsername(user.getName())
3539
}
3640
}
3741
}
3842

3943
fun getLineAnimation(username: String, personaId: Long, mode: Mode): String {
4044
return when (userService.existsByName(username)) {
4145
true -> {
46+
setUserAuthInfoIfNotSet(username)
47+
4248
val svgAnimation = userService.getLineAnimationByUsername(username, personaId, mode)
4349
eventPublisher.publishEvent(Visited(username, MDC.get(TRACE_ID)))
4450
svgAnimation
4551
}
4652

4753
false -> {
4854
val user = createNewUser(username)
49-
sagaManager.startSync(NewUserCreated(user.id, user.name))
50-
userService.getLineAnimationByUsername(user.name, personaId, mode)
55+
sagaManager.startSync(NewUserCreated(user.id, user.getName()))
56+
userService.getLineAnimationByUsername(user.getName(), personaId, mode)
5157
}
5258
}
5359
}
5460

61+
private fun setUserAuthInfoIfNotSet(username: String) {
62+
val user = userService.getUserByName(username)
63+
64+
if (user.isAuthInfoSet().not()) {
65+
val githubUserAuthInfo = githubOpenApi.getGithubUser(user.getName())
66+
userService.setAuthInfo(
67+
name = user.getName(),
68+
entryPoint = EntryPoint.GITHUB,
69+
githubUserAuthInfo.id,
70+
)
71+
}
72+
}
73+
5574
fun createNewUser(username: String): User {
5675
return runCatching {
76+
val githubUserResponse = githubOpenApi.getGithubUser(username)
5777
val contributionYears = contributionApi.getAllContributionYears(username)
5878
val contributionCountPerYear =
5979
contributionApi.getContributionCount(username, contributionYears)
60-
userService.createNewUser(username, contributionCountPerYear)
80+
81+
userService.createNewUser(
82+
name = username,
83+
entryPoint = EntryPoint.GITHUB,
84+
authenticationId = githubUserResponse.id,
85+
contributions = contributionCountPerYear,
86+
)
6187
}.getOrElse {
6288
require(it !is RestClientException) { "Cannot create new user from username \"$username\"" }
6389
throw it
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.gitanimals.render.app
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty
4+
import org.springframework.web.bind.annotation.PathVariable
5+
import org.springframework.web.service.annotation.GetExchange
6+
7+
fun interface GithubOpenApi {
8+
9+
@GetExchange("/users/{username}")
10+
fun getGithubUser(@PathVariable("username") username: String): GithubUserResponse
11+
12+
data class GithubUserResponse(
13+
@JsonProperty("login")
14+
val name: String,
15+
val id: String,
16+
)
17+
}

src/main/kotlin/org/gitanimals/render/controller/InternalPersonaController.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class InternalPersonaController(
9999

100100
return users.map { user ->
101101
val personaId =
102-
usernameAndPersonaIdRequests.first { it.username == user.name }.personaId
102+
usernameAndPersonaIdRequests.first { it.username == user.getName() }.personaId
103103
UserResponse.fromWithSpecificPersona(user, listOf(personaId))
104104
}
105105
}

src/main/kotlin/org/gitanimals/render/controller/response/BackgroundResponse.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ data class BackgroundResponse(
1717
fun from(user: User): BackgroundResponse {
1818
return BackgroundResponse(
1919
id = user.id.toString(),
20-
name = user.name,
20+
name = user.getName(),
2121
backgrounds = user.fields.map { Background(it.fieldType) }.ifEmpty {
2222
listOf(Background(FieldType.WHITE_FIELD))
2323
},

src/main/kotlin/org/gitanimals/render/controller/response/UserResponse.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ data class UserResponse(
1313
fun from(user: User): UserResponse {
1414
return UserResponse(
1515
user.id.toString(),
16-
user.name,
16+
user.getName(),
1717
user.contributionCount().toString(),
1818
user.personas.map {
1919
PersonaResponse(
@@ -30,7 +30,7 @@ data class UserResponse(
3030
fun fromWithSpecificPersona(user: User, personaId: List<Long>): UserResponse {
3131
return UserResponse(
3232
user.id.toString(),
33-
user.name,
33+
user.getName(),
3434
user.contributionCount().toString(),
3535
user.personas.filter {
3636
it.id in personaId
@@ -49,7 +49,7 @@ data class UserResponse(
4949
fun fromOnlyTopLevelPersona(user: User): UserResponse {
5050
return UserResponse(
5151
id = user.id.toString(),
52-
name = user.name,
52+
name = user.getName(),
5353
totalContributions = user.contributionCount().toString(),
5454
personas = listOf(user.personas
5555
.maxBy { it.level() }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.gitanimals.render.domain
2+
3+
enum class EntryPoint {
4+
GITHUB,
5+
}

src/main/kotlin/org/gitanimals/render/domain/Persona.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Persona(
5555

5656

5757
fun toSvgForce(mode: Mode): String = type.load(
58-
name = user!!.name,
58+
name = user!!.getName(),
5959
contributionCount = user!!.contributionCount(),
6060
animationId = this.id,
6161
level = this.level(),
@@ -68,7 +68,7 @@ class Persona(
6868
}
6969

7070
return type.load(
71-
name = user!!.name,
71+
name = user!!.getName(),
7272
contributionCount = user!!.contributionCount(),
7373
animationId = this.id,
7474
level = this.level(),

src/main/kotlin/org/gitanimals/render/domain/User.kt

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import org.gitanimals.core.*
66
import org.gitanimals.render.domain.event.PersonaDeleted
77
import org.gitanimals.render.domain.event.UserContributionUpdated
88
import org.gitanimals.render.domain.extension.RenderFieldTypeExtension.isRenderField
9-
import org.gitanimals.core.DomainEventPublisher
109
import org.gitanimals.render.domain.response.PersonaResponse
1110
import org.gitanimals.render.domain.value.Contribution
1211
import org.gitanimals.render.domain.value.Level
@@ -20,14 +19,20 @@ import kotlin.math.min
2019

2120
@AggregateRoot
2221
@Entity(name = "user")
23-
@Table(name = "user", indexes = [Index(columnList = "name")])
22+
@Table(
23+
name = "user",
24+
indexes = [
25+
Index(columnList = "name", unique = true),
26+
Index(columnList = "entry_point, authentication_id", unique = true),
27+
],
28+
)
2429
class User(
2530
@Id
2631
@Column(name = "id")
2732
val id: Long,
2833

2934
@Column(name = "name", unique = true, nullable = false)
30-
val name: String,
35+
private var name: String,
3136

3237
@OneToMany(
3338
mappedBy = "user",
@@ -58,11 +63,31 @@ class User(
5863
@Version
5964
@Column(name = "version", nullable = false)
6065
val version: Long,
66+
67+
@Embedded
68+
private var authInfo: UserAuthInfo? = null,
6169
) : AbstractTime() {
70+
6271
init {
6372
personas.forEach { it.user = this }
6473
}
6574

75+
fun getName(): String = this.name
76+
77+
fun updateName(name: String) {
78+
this.name = name
79+
}
80+
81+
fun isAuthInfoSet(): Boolean = authInfo != null
82+
83+
fun setAuthInfo(entryPoint: EntryPoint, authenticationId: String) {
84+
require(authInfo == null) {
85+
"Cannot set user auth info cause user auth is not null."
86+
}
87+
88+
authInfo = UserAuthInfo(entryPoint = entryPoint, authenticationId = authenticationId)
89+
}
90+
6691
fun addPersona(id: Long, personaType: PersonaType, level: Int): PersonaResponse {
6792
val persona = Persona(id, personaType, Level(level.toLong()), personas.size < 30, this)
6893

@@ -152,7 +177,7 @@ class User(
152177

153178
DomainEventPublisher.publish(
154179
UserContributionUpdated(
155-
username = this.name,
180+
username = this.getName(),
156181
updatedContributions = afterContribution - beforeContribution,
157182
contributions = afterContribution,
158183
)
@@ -296,7 +321,12 @@ class User(
296321

297322
private val nameConvention = Regex("[^a-zA-Z0-9-]")
298323

299-
fun newUser(name: String, contributions: Map<Int, Int>): User {
324+
fun newUser(
325+
name: String,
326+
contributions: Map<Int, Int>,
327+
entryPoint: EntryPoint,
328+
authenticationId: String
329+
): User {
300330
require(!nameConvention.containsMatchIn(name)) {
301331
throw IllegalArgumentException("Not supported word contained in \"${name}\"")
302332
}
@@ -313,6 +343,7 @@ class User(
313343
visit = 1,
314344
version = 0,
315345
lastPersonaGivePoint = (totalContributionCount(contributions) % FOR_NEW_PERSONA_COUNT).toInt(),
346+
authInfo = UserAuthInfo(entryPoint, authenticationId),
316347
)
317348

318349
user.addField(FieldType.WHITE_FIELD)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.gitanimals.render.domain
2+
3+
import jakarta.persistence.Column
4+
import jakarta.persistence.Embeddable
5+
import jakarta.persistence.EnumType
6+
import jakarta.persistence.Enumerated
7+
8+
@Embeddable
9+
class UserAuthInfo(
10+
11+
@Enumerated(EnumType.STRING)
12+
@Column(name = "entry_point", nullable = true)
13+
private val entryPoint: EntryPoint,
14+
15+
@Column(name = "authentication_id", nullable = true)
16+
private val authenticationId: String,
17+
)

src/main/kotlin/org/gitanimals/render/domain/UserRepository.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,17 @@ interface UserRepository : JpaRepository<User, Long> {
2626
)
2727
fun findAllByIdsWithContributions(@Param("usernames") usernames: Set<String>): List<User>
2828

29+
@Query(
30+
"""
31+
select u from user as u
32+
where u.authInfo.entryPoint = :entryPoint
33+
and u.authInfo.authenticationId = :authenticationId
34+
"""
35+
)
36+
fun findByEntryPointAndAuthenticationId(
37+
@Param("entryPoint") entryPoint: EntryPoint,
38+
@Param("authenticationId") authenticationId: String,
39+
): User?
40+
2941
fun existsByName(name: String): Boolean
3042
}

0 commit comments

Comments
 (0)