diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt new file mode 100644 index 00000000..3398d719 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt @@ -0,0 +1,38 @@ +package dev.usbharu.hideout.core.application.actor + +import dev.usbharu.hideout.core.domain.model.actor.Actor +import java.net.URI + +data class ActorDetail( + val id: Long, + val name: String, + val screenName: String, + val host: String, + val remoteUrl: String?, + val locked: Boolean, + val description: String, + val postsCount: Int, + val iconUrl: URI?, + val bannerURL: URI?, + val followingCount: Int?, + val followersCount: Int? +) { + companion object { + fun of(actor: Actor, iconUrl: URI?, bannerURL: URI?): ActorDetail { + return ActorDetail( + id = actor.id.id, + name = actor.name.name, + screenName = actor.screenName.screenName, + host = actor.url.host, + remoteUrl = actor.url.toString(), + locked = actor.locked, + description = actor.description.description, + postsCount = actor.postsCount.postsCount, + iconUrl = iconUrl, + bannerURL = bannerURL, + followingCount = actor.followingCount?.relationshipCount, + followersCount = actor.followersCount?.relationshipCount + ) + } + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetail.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetail.kt new file mode 100644 index 00000000..8089a404 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetail.kt @@ -0,0 +1,8 @@ +package dev.usbharu.hideout.core.application.actor + +import dev.usbharu.hideout.core.domain.model.support.acct.Acct + +data class GetActorDetail( + val actorName: Acct? = null, + val id: Long? = null +) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt new file mode 100644 index 00000000..f417fe5d --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt @@ -0,0 +1,49 @@ +package dev.usbharu.hideout.core.application.actor + +import dev.usbharu.hideout.core.application.shared.AbstractApplicationService +import dev.usbharu.hideout.core.application.shared.Transaction +import dev.usbharu.hideout.core.config.ApplicationConfig +import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository +import dev.usbharu.hideout.core.domain.model.media.MediaRepository +import dev.usbharu.hideout.core.domain.model.support.principal.Principal +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +@Component +class GetActorDetailApplicationService( + private val actorRepository: ActorRepository, + private val mediaRepository: MediaRepository, + private val applicationConfig: ApplicationConfig, + transaction: Transaction +) : + AbstractApplicationService( + transaction, logger + ) { + override suspend fun internalExecute(command: GetActorDetail, principal: Principal): ActorDetail { + val actor = if (command.id != null) { + actorRepository.findById(ActorId(command.id)) + ?: throw IllegalArgumentException("Actor ${command.id} not found.") + } else if (command.actorName != null) { + + val host = if (command.actorName.host.isEmpty()) { + applicationConfig.url.host + } else { + command.actorName.host + } + actorRepository.findByNameAndDomain(command.actorName.userpart, host) + ?: throw IllegalArgumentException("Actor ${command.actorName} not found.") + } else { + throw IllegalArgumentException("id and actorName are null.") + } + + val iconUrl = actor.icon?.let { mediaRepository.findById(it)?.url } + val bannerUrl = actor.banner?.let { mediaRepository.findById(it)?.url } + + return ActorDetail.of(actor, iconUrl, bannerUrl) + } + + companion object { + private val logger = LoggerFactory.getLogger(GetActorDetailApplicationService::class.java) + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt index 2eccad56..2c8217d3 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt @@ -87,6 +87,7 @@ class SecurityConfig { authorize(GET, "/auth/sign_up", hasRole("ANONYMOUS")) authorize(POST, "/auth/sign_up", permitAll) authorize(GET, "/users/{username}/posts/{postId}", permitAll) + authorize(GET, "/users/{userid}", permitAll) authorize(GET, "/files/*", permitAll) authorize(POST, "/publish", authenticated) authorize(GET, "/publish", authenticated) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt index 8be92e3a..148e01ca 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt @@ -5,4 +5,14 @@ data class Acct( val host: String ) { override fun toString(): String = "acct:$userpart@$host" + + companion object { + + fun of(acct: String): Acct { + return Acct( + acct.substringBeforeLast('@'), + acct.substringAfterLast('@', "") + ) + } + } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt new file mode 100644 index 00000000..d07a79ea --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt @@ -0,0 +1,31 @@ +package dev.usbharu.hideout.core.interfaces.web.user + +import dev.usbharu.hideout.core.application.actor.GetActorDetail +import dev.usbharu.hideout.core.application.actor.GetActorDetailApplicationService +import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService +import dev.usbharu.hideout.core.domain.model.support.acct.Acct +import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous +import dev.usbharu.hideout.core.infrastructure.springframework.SpringSecurityFormLoginPrincipalContextHolder +import org.springframework.stereotype.Controller +import org.springframework.ui.Model +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable + +@Controller +class UserController( + private val getLocalInstanceApplicationService: GetLocalInstanceApplicationService, + private val getUserDetailApplicationService: GetActorDetailApplicationService, + private val springSecurityFormLoginPrincipalContextHolder: SpringSecurityFormLoginPrincipalContextHolder, +) { + @GetMapping("/users/{name}") + suspend fun userById(@PathVariable name: String, model: Model): String { + val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() + + model.addAttribute("instance", getLocalInstanceApplicationService.execute(Unit, Anonymous)) + model.addAttribute( + "user", + getUserDetailApplicationService.execute(GetActorDetail(Acct.of(name)), principal) + ) + return "userById" + } +} \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages.properties b/hideout-core/src/main/resources/messages/hideout-web-messages.properties index 6a47f1b5..6423f1c9 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages.properties @@ -21,4 +21,5 @@ post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6 post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 -post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 \ No newline at end of file +post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 +user-by-id.title={0} \u3055\u3093 - {1} \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties index 6a47f1b5..6423f1c9 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties @@ -21,4 +21,5 @@ post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6 post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 -post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 \ No newline at end of file +post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 +user-by-id.title={0} \u3055\u3093 - {1} \ No newline at end of file diff --git a/hideout-core/src/main/resources/templates/userById.html b/hideout-core/src/main/resources/templates/userById.html new file mode 100644 index 00000000..ded4a2a7 --- /dev/null +++ b/hideout-core/src/main/resources/templates/userById.html @@ -0,0 +1,14 @@ + + + + + User - hideout + + + + + \ No newline at end of file