mirror of https://github.com/usbharu/Hideout.git
feat: Actorのインスタンス化時にチェックするように
This commit is contained in:
parent
15b3cf6796
commit
7719863b80
|
@ -18,37 +18,56 @@ package dev.usbharu.hideout.core.domain.model.actor
|
||||||
|
|
||||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||||
import dev.usbharu.hideout.application.config.CharacterLimit
|
import dev.usbharu.hideout.application.config.CharacterLimit
|
||||||
|
import jakarta.validation.Validator
|
||||||
|
import jakarta.validation.constraints.*
|
||||||
|
import org.hibernate.validator.constraints.URL
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
data class Actor private constructor(
|
data class Actor private constructor(
|
||||||
|
@get:NotNull
|
||||||
|
@get:Positive
|
||||||
val id: Long,
|
val id: Long,
|
||||||
|
@get:Pattern(regexp = "^[a-zA-Z0-9_-]{1,300}\$")
|
||||||
|
@get:Size(min = 1)
|
||||||
val name: String,
|
val name: String,
|
||||||
|
@get:Pattern(regexp = "^([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\\.){1,255}[a-zA-Z]{2,}\$")
|
||||||
val domain: String,
|
val domain: String,
|
||||||
val screenName: String,
|
val screenName: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
|
@get:URL
|
||||||
val inbox: String,
|
val inbox: String,
|
||||||
|
@get:URL
|
||||||
val outbox: String,
|
val outbox: String,
|
||||||
|
@get:URL
|
||||||
val url: String,
|
val url: String,
|
||||||
|
@get:NotBlank
|
||||||
val publicKey: String,
|
val publicKey: String,
|
||||||
val privateKey: String? = null,
|
val privateKey: String? = null,
|
||||||
|
@get:PastOrPresent
|
||||||
val createdAt: Instant,
|
val createdAt: Instant,
|
||||||
|
@get:NotBlank
|
||||||
val keyId: String,
|
val keyId: String,
|
||||||
val followers: String? = null,
|
val followers: String? = null,
|
||||||
val following: String? = null,
|
val following: String? = null,
|
||||||
|
@get:Positive
|
||||||
val instance: Long? = null,
|
val instance: Long? = null,
|
||||||
val locked: Boolean,
|
val locked: Boolean,
|
||||||
val followersCount: Int = 0,
|
val followersCount: Int = 0,
|
||||||
val followingCount: Int = 0,
|
val followingCount: Int = 0,
|
||||||
val postsCount: Int = 0,
|
val postsCount: Int = 0,
|
||||||
val lastPostDate: Instant? = null,
|
val lastPostDate: Instant? = null,
|
||||||
val emojis: List<Long> = emptyList()
|
val emojis: List<Long> = emptyList(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class UserBuilder(private val characterLimit: CharacterLimit, private val applicationConfig: ApplicationConfig) {
|
class UserBuilder(
|
||||||
|
private val characterLimit: CharacterLimit,
|
||||||
|
private val applicationConfig: ApplicationConfig,
|
||||||
|
private val validator: Validator,
|
||||||
|
) {
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(UserBuilder::class.java)
|
private val logger = LoggerFactory.getLogger(UserBuilder::class.java)
|
||||||
|
|
||||||
|
@ -74,7 +93,7 @@ data class Actor private constructor(
|
||||||
followingCount: Int = 0,
|
followingCount: Int = 0,
|
||||||
postsCount: Int = 0,
|
postsCount: Int = 0,
|
||||||
lastPostDate: Instant? = null,
|
lastPostDate: Instant? = null,
|
||||||
emojis: List<Long> = emptyList()
|
emojis: List<Long> = emptyList(),
|
||||||
): Actor {
|
): Actor {
|
||||||
if (id == 0L) {
|
if (id == 0L) {
|
||||||
return Actor(
|
return Actor(
|
||||||
|
@ -176,7 +195,7 @@ data class Actor private constructor(
|
||||||
"keyId must contain non-blank characters."
|
"keyId must contain non-blank characters."
|
||||||
}
|
}
|
||||||
|
|
||||||
return Actor(
|
val actor = Actor(
|
||||||
id = id,
|
id = id,
|
||||||
name = limitedName,
|
name = limitedName,
|
||||||
domain = domain,
|
domain = domain,
|
||||||
|
@ -199,6 +218,13 @@ data class Actor private constructor(
|
||||||
lastPostDate = lastPostDate,
|
lastPostDate = lastPostDate,
|
||||||
emojis = emojis
|
emojis = emojis
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val validate = validator.validate(actor)
|
||||||
|
|
||||||
|
for (constraintViolation in validate) {
|
||||||
|
throw IllegalArgumentException("${constraintViolation.propertyPath} : ${constraintViolation.message}")
|
||||||
|
}
|
||||||
|
return actor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,27 +243,27 @@ data class Actor private constructor(
|
||||||
fun withLastPostAt(lastPostDate: Instant): Actor = this.copy(lastPostDate = lastPostDate)
|
fun withLastPostAt(lastPostDate: Instant): Actor = this.copy(lastPostDate = lastPostDate)
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Actor(" +
|
return "Actor(" +
|
||||||
"id=$id, " +
|
"id=$id, " +
|
||||||
"name='$name', " +
|
"name='$name', " +
|
||||||
"domain='$domain', " +
|
"domain='$domain', " +
|
||||||
"screenName='$screenName', " +
|
"screenName='$screenName', " +
|
||||||
"description='$description', " +
|
"description='$description', " +
|
||||||
"inbox='$inbox', " +
|
"inbox='$inbox', " +
|
||||||
"outbox='$outbox', " +
|
"outbox='$outbox', " +
|
||||||
"url='$url', " +
|
"url='$url', " +
|
||||||
"publicKey='$publicKey', " +
|
"publicKey='$publicKey', " +
|
||||||
"privateKey=$privateKey, " +
|
"privateKey=$privateKey, " +
|
||||||
"createdAt=$createdAt, " +
|
"createdAt=$createdAt, " +
|
||||||
"keyId='$keyId', " +
|
"keyId='$keyId', " +
|
||||||
"followers=$followers, " +
|
"followers=$followers, " +
|
||||||
"following=$following, " +
|
"following=$following, " +
|
||||||
"instance=$instance, " +
|
"instance=$instance, " +
|
||||||
"locked=$locked, " +
|
"locked=$locked, " +
|
||||||
"followersCount=$followersCount, " +
|
"followersCount=$followersCount, " +
|
||||||
"followingCount=$followingCount, " +
|
"followingCount=$followingCount, " +
|
||||||
"postsCount=$postsCount, " +
|
"postsCount=$postsCount, " +
|
||||||
"lastPostDate=$lastPostDate, " +
|
"lastPostDate=$lastPostDate, " +
|
||||||
"emojis=$emojis" +
|
"emojis=$emojis" +
|
||||||
")"
|
")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package dev.usbharu.hideout.core.domain.model.actor
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import utils.UserBuilder
|
||||||
|
|
||||||
|
class ActorTest {
|
||||||
|
@Test
|
||||||
|
fun validator() {
|
||||||
|
org.junit.jupiter.api.assertThrows<IllegalArgumentException> {
|
||||||
|
UserBuilder.localUserOf(name = "うんこ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
||||||
import dev.usbharu.hideout.core.domain.model.post.Post
|
import dev.usbharu.hideout.core.domain.model.post.Post
|
||||||
import dev.usbharu.hideout.core.service.post.DefaultPostContentFormatter
|
import dev.usbharu.hideout.core.service.post.DefaultPostContentFormatter
|
||||||
|
import jakarta.validation.Validation
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
@ -37,7 +38,11 @@ import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
class ActorServiceTest {
|
class ActorServiceTest {
|
||||||
val actorBuilder = Actor.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com")))
|
val actorBuilder = Actor.UserBuilder(
|
||||||
|
CharacterLimit(),
|
||||||
|
ApplicationConfig(URL("https://example.com")),
|
||||||
|
Validation.buildDefaultValidatorFactory().validator
|
||||||
|
)
|
||||||
val postBuilder = Post.PostBuilder(CharacterLimit(), DefaultPostContentFormatter(HtmlSanitizeConfig().policy()))
|
val postBuilder = Post.PostBuilder(CharacterLimit(), DefaultPostContentFormatter(HtmlSanitizeConfig().policy()))
|
||||||
@Test
|
@Test
|
||||||
fun `createLocalUser ローカルユーザーを作成できる`() = runTest {
|
fun `createLocalUser ローカルユーザーを作成できる`() = runTest {
|
||||||
|
|
|
@ -20,12 +20,16 @@ import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||||
import dev.usbharu.hideout.application.config.CharacterLimit
|
import dev.usbharu.hideout.application.config.CharacterLimit
|
||||||
import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService
|
import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||||
|
import jakarta.validation.Validation
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
object UserBuilder {
|
object UserBuilder {
|
||||||
private val actorBuilder = Actor.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com")))
|
private val actorBuilder = Actor.UserBuilder(
|
||||||
|
CharacterLimit(), ApplicationConfig(URL("https://example.com")),
|
||||||
|
Validation.buildDefaultValidatorFactory().validator
|
||||||
|
)
|
||||||
|
|
||||||
private val idGenerator = TwitterSnowflakeIdGenerateService
|
private val idGenerator = TwitterSnowflakeIdGenerateService
|
||||||
|
|
||||||
|
@ -43,7 +47,7 @@ object UserBuilder {
|
||||||
createdAt: Instant = Instant.now(),
|
createdAt: Instant = Instant.now(),
|
||||||
keyId: String = "https://$domain/users/$id#pubkey",
|
keyId: String = "https://$domain/users/$id#pubkey",
|
||||||
followers: String = "https://$domain/users/$id/followers",
|
followers: String = "https://$domain/users/$id/followers",
|
||||||
following: String = "https://$domain/users/$id/following"
|
following: String = "https://$domain/users/$id/following",
|
||||||
): Actor {
|
): Actor {
|
||||||
return actorBuilder.of(
|
return actorBuilder.of(
|
||||||
id = id,
|
id = id,
|
||||||
|
@ -77,7 +81,7 @@ object UserBuilder {
|
||||||
createdAt: Instant = Instant.now(),
|
createdAt: Instant = Instant.now(),
|
||||||
keyId: String = "https://$domain/$id#pubkey",
|
keyId: String = "https://$domain/$id#pubkey",
|
||||||
followers: String = "https://$domain/$id/followers",
|
followers: String = "https://$domain/$id/followers",
|
||||||
following: String = "https://$domain/$id/following"
|
following: String = "https://$domain/$id/following",
|
||||||
): Actor {
|
): Actor {
|
||||||
return actorBuilder.of(
|
return actorBuilder.of(
|
||||||
id = id,
|
id = id,
|
||||||
|
|
Loading…
Reference in New Issue