feat: 投稿詳細ページを作成

This commit is contained in:
usbharu 2024-08-12 21:38:07 +09:00
parent ced41e64fd
commit f4d30e837e
Signed by: usbharu
GPG Key ID: 6556747BF94EEBC8
61 changed files with 562 additions and 108 deletions

View File

@ -22,7 +22,7 @@ import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationS
import dev.usbharu.hideout.core.application.shared.Transaction
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.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
import dev.usbharu.hideout.core.domain.service.actor.local.AccountMigrationCheck.*
import dev.usbharu.hideout.core.domain.service.actor.local.LocalActorMigrationCheckDomainService
@ -37,7 +37,7 @@ class MigrationLocalActorApplicationService(
private val userDetailRepository: UserDetailRepository,
) : LocalUserAbstractApplicationService<MigrationLocalActor, Unit>(transaction, logger) {
override suspend fun internalExecute(command: MigrationLocalActor, principal: FromApi) {
override suspend fun internalExecute(command: MigrationLocalActor, principal: LocalUser) {
if (command.from != principal.actorId.id) {
throw PermissionDeniedException()
}

View File

@ -21,7 +21,7 @@ import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -30,7 +30,7 @@ class StartDeleteLocalActorApplicationService(
transaction: Transaction,
private val actorRepository: ActorRepository,
) : LocalUserAbstractApplicationService<DeleteLocalActor, Unit>(transaction, logger) {
override suspend fun internalExecute(command: DeleteLocalActor, principal: FromApi) {
override suspend fun internalExecute(command: DeleteLocalActor, principal: LocalUser) {
if (command.actorId != principal.actorId) {
throw PermissionDeniedException()
}

View File

@ -21,7 +21,7 @@ import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationS
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.filter.FilterId
import dev.usbharu.hideout.core.domain.model.filter.FilterRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -31,7 +31,7 @@ class UserDeleteFilterApplicationService(private val filterRepository: FilterRep
transaction,
logger
) {
override suspend fun internalExecute(command: DeleteFilter, principal: FromApi) {
override suspend fun internalExecute(command: DeleteFilter, principal: LocalUser) {
val filter =
filterRepository.findByFilterId(FilterId(command.filterId)) ?: throw IllegalArgumentException("not found")
if (filter.userDetailId != principal.userDetailId) {

View File

@ -21,7 +21,7 @@ import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationS
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.filter.FilterId
import dev.usbharu.hideout.core.domain.model.filter.FilterRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -31,7 +31,7 @@ class UserGetFilterApplicationService(private val filterRepository: FilterReposi
transaction,
logger
) {
override suspend fun internalExecute(command: GetFilter, principal: FromApi): Filter {
override suspend fun internalExecute(command: GetFilter, principal: LocalUser): Filter {
val filter =
filterRepository.findByFilterId(FilterId(command.filterId)) ?: throw IllegalArgumentException("Not Found")
if (filter.userDetailId != principal.userDetailId) {

View File

@ -20,7 +20,7 @@ import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationS
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.filter.*
import dev.usbharu.hideout.core.domain.model.filter.FilterKeyword
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -36,7 +36,7 @@ class UserRegisterFilterApplicationService(
logger
) {
override suspend fun internalExecute(command: RegisterFilter, principal: FromApi): Filter {
override suspend fun internalExecute(command: RegisterFilter, principal: LocalUser): Filter {
val filter = dev.usbharu.hideout.core.domain.model.filter.Filter.create(
id = FilterId(idGenerateService.generateId()),

View File

@ -0,0 +1,31 @@
package dev.usbharu.hideout.core.application.instance
import dev.usbharu.hideout.core.application.exception.InternalServerException
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.instance.InstanceRepository
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@Service
class GetLocalInstanceApplicationService(
private val applicationConfig: ApplicationConfig,
private val instanceRepository: InstanceRepository,
transaction: Transaction
) :
AbstractApplicationService<Unit, Instance>(
transaction, logger
) {
override suspend fun internalExecute(command: Unit, principal: Principal): Instance {
val instance = (instanceRepository.findByUrl(applicationConfig.url.toURI())
?: throw InternalServerException("Local instance not found."))
return Instance.of(instance)
}
companion object {
private val logger = LoggerFactory.getLogger(GetLocalInstanceApplicationService::class.java)
}
}

View File

@ -0,0 +1,14 @@
package dev.usbharu.hideout.core.application.instance
import dev.usbharu.hideout.core.domain.model.instance.Instance
import java.net.URI
data class Instance(val id: Long, val name: String, val url: URI, val description: String) {
companion object {
fun of(instance: Instance): dev.usbharu.hideout.core.application.instance.Instance {
return Instance(
instance.id.instanceId, instance.name.name, instance.url, instance.description.description
)
}
}
}

View File

@ -19,7 +19,7 @@ package dev.usbharu.hideout.core.application.media
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.media.*
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService
import dev.usbharu.hideout.core.external.media.MediaProcessor
import dev.usbharu.hideout.core.external.mediastore.MediaStore
@ -39,7 +39,7 @@ class UploadMediaApplicationService(
transaction,
logger
) {
override suspend fun internalExecute(command: UploadMedia, principal: FromApi): Media {
override suspend fun internalExecute(command: UploadMedia, principal: LocalUser): Media {
val process = mediaProcessor.process(command.path, command.name, null)
val id = idGenerateService.generateId()
val thumbnailUri = if (process.thumbnailPath != null) {

View File

@ -0,0 +1,35 @@
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.domain.model.actor.Actor
import dev.usbharu.hideout.core.domain.model.instance.Instance
import dev.usbharu.hideout.core.domain.model.media.Media
import java.net.URI
data class ActorDetail(
val actorId: Long,
val instanceId: Long,
val instanceName: String,
val name: String,
val domain: String,
val screenName: String,
val url: URI,
val locked: Boolean,
val icon: URI?,
) {
companion object {
fun of(actor: Actor, instance: Instance, iconMedia: Media?): ActorDetail {
return ActorDetail(
actor.id.id,
actor.instance.instanceId,
instance.name.name,
actor.name.name,
actor.domain.domain,
actor.screenName.screenName,
actor.url,
actor.locked,
iconMedia?.url
)
}
}
}

View File

@ -22,7 +22,7 @@ import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
import dev.usbharu.hideout.core.domain.model.post.PostId
import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -32,7 +32,7 @@ class DeleteLocalPostApplicationService(
private val actorRepository: ActorRepository, transaction: Transaction,
) : LocalUserAbstractApplicationService<DeleteLocalPost, Unit>(transaction, logger) {
override suspend fun internalExecute(command: DeleteLocalPost, principal: FromApi) {
override suspend fun internalExecute(command: DeleteLocalPost, principal: LocalUser) {
val findById = postRepository.findById(PostId(command.postId))!!
if (findById.actorId != principal.actorId) {
throw PermissionDeniedException()

View File

@ -0,0 +1,3 @@
package dev.usbharu.hideout.core.application.post
data class GetPostDetail(val postId: Long)

View File

@ -0,0 +1,91 @@
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.application.exception.InternalServerException
import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
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.instance.Instance
import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository
import dev.usbharu.hideout.core.domain.model.media.Media
import dev.usbharu.hideout.core.domain.model.media.MediaRepository
import dev.usbharu.hideout.core.domain.model.post.PostId
import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import dev.usbharu.hideout.core.domain.service.post.IPostReadAccessControl
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@Service
class GetPostDetailApplicationService(
transaction: Transaction,
private val postRepository: PostRepository,
private val actorRepository: ActorRepository,
private val instanceRepository: InstanceRepository,
private val mediaRepository: MediaRepository,
private val iPostReadAccessControl: IPostReadAccessControl
) : AbstractApplicationService<GetPostDetail, PostDetail>(
transaction, logger
) {
override suspend fun internalExecute(command: GetPostDetail, principal: Principal): PostDetail {
val post = postRepository.findById(PostId(command.postId))
?: throw IllegalArgumentException("Post ${command.postId} not found.")
if (iPostReadAccessControl.isAllow(post, principal).not()) {
throw PermissionDeniedException()
}
val actor =
actorRepository.findById(post.actorId) ?: throw InternalServerException("Actor ${post.actorId} not found.")
val instance = instanceRepository.findById(post.instanceId)
?: throw InternalServerException("Instance ${post.instanceId} not found.")
val iconMedia = actor.icon?.let { mediaRepository.findById(it) }
val mediaList = mediaRepository.findByIds(post.mediaIds)
return PostDetail.of(
post,
actor,
instance,
iconMedia,
mediaList,
post.replyId?.let { fetchChild(it, actor, instance, iconMedia, principal) },
post.repostId?.let { fetchChild(it, actor, instance, iconMedia, principal) },
post.moveTo?.let { fetchChild(it, actor, instance, iconMedia, principal) },
)
}
private suspend fun fetchChild(
postId: PostId,
actor: Actor,
instance: Instance,
iconMedia: Media?,
principal: Principal
): PostDetail? {
val post = postRepository.findById(postId) ?: return null
if (iPostReadAccessControl.isAllow(post, principal).not()) {
throw PermissionDeniedException()
}
val (first, second: Instance, third) = if (actor.id != post.actorId) {
Triple(
actorRepository.findById(post.actorId) ?: return null,
instanceRepository.findById(actor.instance) ?: return null,
actor.icon?.let { mediaRepository.findById(it) }
)
} else {
Triple(actor, instance, iconMedia)
}
val mediaList = mediaRepository.findByIds(post.mediaIds)
return PostDetail.of(
post, first, second, third, mediaList
)
}
companion object {
private val logger = LoggerFactory.getLogger(GetPostDetailApplicationService::class.java)
}
}

View File

@ -0,0 +1,28 @@
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.domain.model.media.Media
import java.net.URI
data class MediaDetail(
val mediaId: Long,
val type: String,
val url: URI,
val thumbnailUrl: URI?,
val sensitive: Boolean,
val description: String,
val blurhash: String
) {
companion object {
fun of(media: Media): MediaDetail {
return MediaDetail(
media.id.id,
media.type.name,
media.url,
media.thumbnailUrl,
false,
media.description?.description.orEmpty(),
media.blurHash?.hash.orEmpty()
)
}
}
}

View File

@ -0,0 +1,60 @@
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.domain.model.actor.Actor
import dev.usbharu.hideout.core.domain.model.instance.Instance
import dev.usbharu.hideout.core.domain.model.media.Media
import dev.usbharu.hideout.core.domain.model.post.Post
import dev.usbharu.hideout.core.domain.model.post.Visibility
import java.net.URI
import java.time.Instant
data class PostDetail(
val id: Long,
val actor: ActorDetail,
val overview: String?,
val text: String,
val content: String,
val createdAt: Instant,
val visibility: Visibility,
val pureRepost: Boolean,
val url: URI,
val apId: URI,
val repost: PostDetail?,
val reply: PostDetail?,
val sensitive: Boolean,
val deleted: Boolean,
val mediaDetailList: List<MediaDetail>,
val moveTo: PostDetail?
) {
companion object {
fun of(
post: Post,
actor: Actor,
instance: Instance,
iconMedia: Media?,
mediaList: List<Media>,
reply: PostDetail? = null,
repost: PostDetail? = null,
moveTo: PostDetail? = null,
): PostDetail {
return PostDetail(
id = post.id.id,
actor = ActorDetail.of(actor, instance, iconMedia),
overview = post.overview?.overview,
text = post.text,
content = post.content.content,
createdAt = post.createdAt,
visibility = post.visibility,
pureRepost = post.isPureRepost,
url = post.url,
apId = post.apId,
repost = repost,
reply = reply,
sensitive = post.sensitive,
deleted = false,
mediaDetailList = mediaList.map { MediaDetail.of(it) },
moveTo = moveTo
)
}
}
}

View File

@ -24,7 +24,7 @@ import dev.usbharu.hideout.core.domain.model.media.MediaId
import dev.usbharu.hideout.core.domain.model.post.PostId
import dev.usbharu.hideout.core.domain.model.post.PostOverview
import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.infrastructure.factory.PostFactoryImpl
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -38,7 +38,7 @@ class RegisterLocalPostApplicationService(
transaction: Transaction,
) : LocalUserAbstractApplicationService<RegisterLocalPost, Long>(transaction, Companion.logger) {
override suspend fun internalExecute(command: RegisterLocalPost, principal: FromApi): Long {
override suspend fun internalExecute(command: RegisterLocalPost, principal: LocalUser): Long {
val actorId = principal.actorId
val actor = actorRepository.findById(actorId) ?: throw InternalServerException("Actor $actorId not found.")

View File

@ -25,7 +25,7 @@ import dev.usbharu.hideout.core.domain.model.media.MediaId
import dev.usbharu.hideout.core.domain.model.post.PostId
import dev.usbharu.hideout.core.domain.model.post.PostOverview
import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
import dev.usbharu.hideout.core.infrastructure.factory.PostContentFactoryImpl
import org.slf4j.LoggerFactory
@ -40,7 +40,7 @@ class UpdateLocalNoteApplicationService(
private val actorRepository: ActorRepository,
) : LocalUserAbstractApplicationService<UpdateLocalNote, Unit>(transaction, logger) {
override suspend fun internalExecute(command: UpdateLocalNote, principal: FromApi) {
override suspend fun internalExecute(command: UpdateLocalNote, principal: LocalUser) {
val post = postRepository.findById(PostId(command.postId))
?: throw IllegalArgumentException("Post ${command.postId} not found.")
if (post.actorId != principal.actorId) {

View File

@ -23,7 +23,7 @@ import dev.usbharu.hideout.core.application.shared.Transaction
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.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -34,7 +34,7 @@ class UserAcceptFollowRequestApplicationService(
private val actorRepository: ActorRepository,
) :
LocalUserAbstractApplicationService<AcceptFollowRequest, Unit>(transaction, logger) {
override suspend fun internalExecute(command: AcceptFollowRequest, principal: FromApi) {
override suspend fun internalExecute(command: AcceptFollowRequest, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found")

View File

@ -22,7 +22,7 @@ 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.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.service.relationship.RelationshipDomainService
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -35,7 +35,7 @@ class UserBlockApplicationService(
private val relationshipDomainService: RelationshipDomainService,
) :
LocalUserAbstractApplicationService<Block, Unit>(transaction, logger) {
override suspend fun internalExecute(command: Block, principal: FromApi) {
override suspend fun internalExecute(command: Block, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)

View File

@ -23,7 +23,7 @@ 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.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -37,7 +37,7 @@ class UserFollowRequestApplicationService(
logger
) {
override suspend fun internalExecute(command: FollowRequest, principal: FromApi) {
override suspend fun internalExecute(command: FollowRequest, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")

View File

@ -24,7 +24,7 @@ import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
import dev.usbharu.hideout.core.domain.model.actorinstancerelationship.ActorInstanceRelationship
import dev.usbharu.hideout.core.domain.model.actorinstancerelationship.ActorInstanceRelationshipRepository
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -39,7 +39,7 @@ class GetRelationshipApplicationService(
transaction,
logger
) {
override suspend fun internalExecute(command: GetRelationship, principal: FromApi): Relationship {
override suspend fun internalExecute(command: GetRelationship, principal: LocalUser): Relationship {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")
val targetId = ActorId(command.targetActorId)

View File

@ -24,7 +24,7 @@ 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.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -35,7 +35,7 @@ class UserMuteApplicationService(
private val actorRepository: ActorRepository,
) :
LocalUserAbstractApplicationService<Mute, Unit>(transaction, logger) {
override suspend fun internalExecute(command: Mute, principal: FromApi) {
override suspend fun internalExecute(command: Mute, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")

View File

@ -23,7 +23,7 @@ import dev.usbharu.hideout.core.application.shared.Transaction
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.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -34,7 +34,7 @@ class UserRejectFollowRequestApplicationService(
private val actorRepository: ActorRepository,
) :
LocalUserAbstractApplicationService<RejectFollowRequest, Unit>(transaction, logger) {
override suspend fun internalExecute(command: RejectFollowRequest, principal: FromApi) {
override suspend fun internalExecute(command: RejectFollowRequest, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")

View File

@ -24,7 +24,7 @@ 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.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -35,7 +35,7 @@ class UserRemoveFromFollowersApplicationService(
private val actorRepository: ActorRepository,
) :
LocalUserAbstractApplicationService<RemoveFromFollowers, Unit>(transaction, logger) {
override suspend fun internalExecute(command: RemoveFromFollowers, principal: FromApi) {
override suspend fun internalExecute(command: RemoveFromFollowers, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")

View File

@ -24,7 +24,7 @@ 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.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -35,7 +35,7 @@ class UserUnblockApplicationService(
private val actorRepository: ActorRepository,
) :
LocalUserAbstractApplicationService<Unblock, Unit>(transaction, logger) {
override suspend fun internalExecute(command: Unblock, principal: FromApi) {
override suspend fun internalExecute(command: Unblock, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")

View File

@ -24,7 +24,7 @@ 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.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -35,7 +35,7 @@ class UserUnfollowApplicationService(
private val actorRepository: ActorRepository,
) :
LocalUserAbstractApplicationService<Unfollow, Unit>(transaction, logger) {
override suspend fun internalExecute(command: Unfollow, principal: FromApi) {
override suspend fun internalExecute(command: Unfollow, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")

View File

@ -24,7 +24,7 @@ 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.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -39,7 +39,7 @@ class UserUnmuteApplicationService(
private val logger = LoggerFactory.getLogger(UserBlockApplicationService::class.java)
}
override suspend fun internalExecute(command: Unmute, principal: FromApi) {
override suspend fun internalExecute(command: Unmute, principal: LocalUser) {
val actor = actorRepository.findById(principal.actorId)
?: throw InternalServerException("Actor ${principal.actorId} not found.")

View File

@ -1,18 +1,18 @@
package dev.usbharu.hideout.core.application.shared
import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import org.slf4j.Logger
abstract class LocalUserAbstractApplicationService<T : Any, R>(transaction: Transaction, logger: Logger) :
AbstractApplicationService<T, R>(transaction, logger) {
override suspend fun internalExecute(command: T, principal: Principal): R {
if (principal !is FromApi) {
if (principal !is LocalUser) {
throw PermissionDeniedException()
}
return internalExecute(command, principal)
}
protected abstract suspend fun internalExecute(command: T, principal: FromApi): R
protected abstract suspend fun internalExecute(command: T, principal: LocalUser): R
}

View File

@ -2,7 +2,7 @@ package dev.usbharu.hideout.core.application.timeline
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipRepository
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -15,7 +15,7 @@ class UserAddTimelineRelationshipApplicationService(
LocalUserAbstractApplicationService<AddTimelineRelationship, Unit>(
transaction, logger
) {
override suspend fun internalExecute(command: AddTimelineRelationship, principal: FromApi) {
override suspend fun internalExecute(command: AddTimelineRelationship, principal: LocalUser) {
timelineRelationshipRepository.save(command.timelineRelationship)
}

View File

@ -24,4 +24,4 @@ data class ApplicationConfig(
val url: URL,
val private: Boolean = true,
val keySize: Int = 2048,
)
)

View File

@ -81,6 +81,7 @@ class SecurityConfig {
authorize(GET, "/auth/sign_up", hasRole("ANONYMOUS"))
authorize(POST, "/auth/sign_up", permitAll)
authorize(GET, "/users/{username}/posts/{postId}", permitAll)
authorize(anyRequest, authenticated)
}

View File

@ -19,5 +19,6 @@ package dev.usbharu.hideout.core.domain.model.media
interface MediaRepository {
suspend fun save(media: Media): Media
suspend fun findById(id: MediaId): Media?
suspend fun findByIds(ids: List<MediaId>): List<Media>
suspend fun delete(media: Media)
}

View File

@ -83,6 +83,8 @@ class Post(
}
}
val isPureRepost = content == PostContent.empty && overview == null && replyId == null && repostId != null
var content = content
get() {
if (hide) {

View File

@ -4,7 +4,7 @@ import dev.usbharu.hideout.core.domain.model.actor.ActorId
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
class FromApi(
class LocalUser(
actorId: ActorId,
override val userDetailId: UserDetailId,
override val acct: Acct

View File

@ -38,14 +38,14 @@ class PostQueryMapper(private val postResultRowMapper: ResultRowMapper<Post>) :
it
.first()
.let(postResultRowMapper::map)
.apply {
buildPost(it)
.run {
buildPost(this, it)
}
}
}
private fun Post.buildPost(it: List<ResultRow>) {
reconstructWith(
private fun buildPost(post: Post, it: List<ResultRow>): Post {
return post.reconstructWith(
mediaIds = it.mapNotNull { resultRow: ResultRow ->
resultRow
.getOrNull(PostsMedia.mediaId)

View File

@ -157,6 +157,7 @@ class ExposedPostRepository(
override suspend fun findById(id: PostId): Post? = query {
Posts
.leftJoin(PostsMedia)
.selectAll()
.where {
Posts.id eq id.id

View File

@ -39,6 +39,15 @@ class MediaRepositoryImpl : MediaRepository, AbstractRepository() {
}
}
override suspend fun findByIds(ids: List<MediaId>): List<dev.usbharu.hideout.core.domain.model.media.Media> {
return query {
return@query Media
.selectAll()
.where { Media.id inList ids.map { it.id } }
.map { it.toMedia() }
}
}
override suspend fun delete(media: dev.usbharu.hideout.core.domain.model.media.Media): Unit = query {
Media.deleteWhere {
id eq id

View File

@ -0,0 +1,35 @@
package dev.usbharu.hideout.core.infrastructure.springframework
import dev.usbharu.hideout.core.application.shared.Transaction
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.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import dev.usbharu.hideout.core.domain.model.support.principal.PrincipalContextHolder
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.HideoutUserDetails
import dev.usbharu.hideout.core.query.principal.PrincipalQueryService
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.stereotype.Component
@Component("formLogin")
class SpringSecurityFormLoginPrincipalContextHolder(
private val transaction: Transaction,
private val principalQueryService: PrincipalQueryService
) : PrincipalContextHolder {
override suspend fun getPrincipal(): Principal {
val hideoutUserDetails =
SecurityContextHolder.getContext().authentication?.principal as? HideoutUserDetails ?: return Anonymous
return transaction.transaction {
val userDetail = principalQueryService.findByUserDetailId(UserDetailId(hideoutUserDetails.userDetailsId))
LocalUser(
userDetail.actorId,
userDetail.userDetailId,
Acct(userDetail.username, userDetail.host)
)
}
}
}

View File

@ -3,7 +3,7 @@ package dev.usbharu.hideout.core.infrastructure.springframework.oauth2
import dev.usbharu.hideout.core.application.shared.Transaction
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.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import dev.usbharu.hideout.core.domain.model.support.principal.PrincipalContextHolder
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
@ -12,7 +12,7 @@ import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.oauth2.jwt.Jwt
import org.springframework.stereotype.Component
@Component
@Component("oauth2")
class SpringSecurityOauth2PrincipalContextHolder(
private val principalQueryService: PrincipalQueryService,
private val transaction: Transaction
@ -26,7 +26,7 @@ class SpringSecurityOauth2PrincipalContextHolder(
val id = principal.getClaim<String>("uid").toLong()
val userDetail = principalQueryService.findByUserDetailId(UserDetailId(id))
return@transaction FromApi(
return@transaction LocalUser(
userDetail.actorId,
userDetail.userDetailId,
Acct(userDetail.username, userDetail.host)

View File

@ -0,0 +1,27 @@
package dev.usbharu.hideout.core.interfaces.web.posts
import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService
import dev.usbharu.hideout.core.application.post.GetPostDetail
import dev.usbharu.hideout.core.application.post.GetPostDetailApplicationService
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 PostsController(
private val getPostDetailApplicationService: GetPostDetailApplicationService,
private val springSecurityFormLoginPrincipalContextHolder: SpringSecurityFormLoginPrincipalContextHolder,
private val getLocalInstanceApplicationService: GetLocalInstanceApplicationService
) {
@GetMapping("/users/{name}/posts/{id}")
suspend fun postById(@PathVariable id: Long, model: Model): String {
val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal()
val post = getPostDetailApplicationService.execute(GetPostDetail(id), principal)
val instance = getLocalInstanceApplicationService.execute(Unit, principal)
model.addAttribute("post", post)
model.addAttribute("instance", instance)
return "postById"
}
}

View File

@ -47,6 +47,8 @@ spring:
threads:
virtual:
enabled: true
messages:
basename: messages.hideout-web-messages
server:
tomcat:
basedir: tomcat

View File

@ -0,0 +1,10 @@
common.audio=\u30AA\u30FC\u30C7\u30A3\u30AA
common.audio-download-link=\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9
common.media-original-link=\u30AA\u30EA\u30B8\u30CA\u30EB
common.thumbnail=\u30B5\u30E0\u30CD\u30A4\u30EB
common.unknwon-file-type=\u4E0D\u660E\u306A\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F
common.video=\u52D5\u753B
common.video-download-link=\u52D5\u753B\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30B5\u30E0\u30CD\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9
post-by-id.title={0} \u3055\u3093\u306E\u6295\u7A3F - {1}
post.repost=\u30EA\u30DD\u30B9\u30C8
post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8

View File

@ -0,0 +1,9 @@
common.audio=Audio
common.audio-download-link=Download the audio.
common.media-original-link=original
common.thumbnail=thumbnail
common.unknwon-file-type=Unknown filetype
common.video=Video
common.video-download-link=Download the Video or thumbnail.
post.repost=Repost
post.repost-by=Repost by {0}

View File

@ -0,0 +1,10 @@
common.audio=\u30AA\u30FC\u30C7\u30A3\u30AA
common.audio-download-link=\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9
common.media-original-link=\u30AA\u30EA\u30B8\u30CA\u30EB
common.thumbnail=\u30B5\u30E0\u30CD\u30A4\u30EB
common.unknwon-file-type=\u4E0D\u660E\u306A\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F
common.video=\u52D5\u753B
common.video-download-link=\u52D5\u753B\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30B5\u30E0\u30CD\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9
post-by-id.title={0} \u3055\u3093\u306E\u6295\u7A3F - {1}
post.repost=\u30EA\u30DD\u30B9\u30C8
post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8

View File

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<article class="post" th:fragment="single-simple-post(post)">
<!--/*@thymesVar id="post" type="dev.usbharu.hideout.core.application.post.PostDetail"*/-->
<img alt="" height="80px" src="" th:src="${post.actor.icon}" width="80px">
<div style="display: inline-block">
<p th:text="${post.actor.screenName}+'('+${post.actor.name}+'@'+${post.actor.domain}+')'"></p>
</div>
<div th:utext="${post.content}">
</div>
<div th:each=" media : ${post.mediaDetailList} ">
<th:block th:switch="${media.type}">
<picture th:case="Image">
<source media="(min-width: 600px)" th:srcset="${media.url}">
<img alt="" src="" th:alt="${media.description}" th:src="${media.thumbnailUrl}" width="260">
</picture>
<video controls loop preload="metadata" th:case="Video" th:poster="${media.thumbnailUrl}" th:src="${media.url}"
th:text="#{common.video-download-link}"
width="260">
<a th:href="${media.url}" th:text="#{common.video}">Video</a>
<a th:href="${media.thumbnailUrl}" th:text="#{common.thumbnail}">Thumbnail</a>
</video>
<audio controls preload="metadata" th:case="Audio" th:src="${media.url}"
th:text="#{common.audio-download-link}">
<a th:href="${media.url}" th:text="#{common.audio}">Audio</a>
</audio>
<th:block th:case="*">
<p th:text="#{common.unknwon-file-type}">Unknown filetype</p>
</th:block>
</th:block>
<a href="" th:href="${media.url}" th:text="#{common.media-original-link}"></a>
</div>
</article>
<div class="post-controller" th:fragment="single-post-controller(post)">
<!--/*@thymesVar id="post" type="dev.usbharu.hideout.core.application.post.PostDetail"*/-->
<a th:href="${post.apId}">
<time th:datetime="${post.createdAt}" th:text="${#temporals.format(post.createdAt, 'yyyy-MM-dd HH:mm')}"></time>
</a>
</div>
</body>
</html>

View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="#{post-by-id.title(${post.actor.screenName},${instance.name})}">Posts - hideout</title>
</head>
<body>
<noscript>
<th:block th:if=" ${post.reply != null}">
<th:block th:replace="fragments-post :: single-simple-post(${post.reply})"></th:block>
<hr>
</th:block>
<main>
<p th:if="${post.pureRepost}" th:text="#{post.repost-by(${post.actor.name})}">Repost by user</p>
<th:block th:unless="${post.pureRepost}">
<th:block th:replace="fragments-post :: single-simple-post(${post})"></th:block>
<th:block th:replace="fragments-post :: single-post-controller(${post})"></th:block>
</th:block>
<th:block th:if="${post.pureRepost}">
<th:block th:replace="fragments-post :: single-simple-post(${post.repost})"></th:block>
<th:block th:replace="fragments-post :: single-post-controller(${post.repost})"></th:block>
</th:block>
</main>
<th:block th:if="${post.repost != null && !post.pureRepost}">
<hr>
<th:block th:replace="fragments-post :: single-simple-post(${post.repost})"></th:block>
<cite th:text="${post.repost.apId}"></cite>
</th:block>
</noscript>
</body>
</html>

View File

@ -7,7 +7,7 @@ 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.actor.TestActorFactory
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetail
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailHashedPassword
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
@ -48,7 +48,7 @@ class MigrationLocalActorApplicationServiceTest {
assertThrows<PermissionDeniedException> {
service.execute(
MigrationLocalActor(1, 2),
FromApi(ActorId(3), UserDetailId(3), Acct("test", "example.com"))
LocalUser(ActorId(3), UserDetailId(3), Acct("test", "example.com"))
)
}
}
@ -64,7 +64,7 @@ class MigrationLocalActorApplicationServiceTest {
assertThrows<IllegalArgumentException> {
service.execute(
MigrationLocalActor(1, 2),
FromApi(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
)
}
}
@ -81,7 +81,7 @@ class MigrationLocalActorApplicationServiceTest {
assertThrows<IllegalArgumentException> {
service.execute(
MigrationLocalActor(1, 2),
FromApi(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
)
}
}
@ -91,7 +91,7 @@ class MigrationLocalActorApplicationServiceTest {
assertThrows<InternalServerException> {
service.execute(
MigrationLocalActor(1, 2),
FromApi(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
)
}
}
@ -119,7 +119,7 @@ class MigrationLocalActorApplicationServiceTest {
service.execute(
MigrationLocalActor(1, 2),
FromApi(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
)
argumentCaptor<Actor> {
@ -161,7 +161,7 @@ class MigrationLocalActorApplicationServiceTest {
assertThrows<IllegalArgumentException> {
service.execute(
MigrationLocalActor(1, 2),
FromApi(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))
)
}
}

View File

@ -6,7 +6,7 @@ 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.actor.TestActorFactory
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
@ -38,7 +38,7 @@ class StartDeleteLocalActorApplicationServiceTest {
service.execute(
DeleteLocalActor(ActorId(1)),
FromApi(ActorId(1), UserDetailId((1)), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId((1)), Acct("test", "example.com"))
)
}
@ -47,7 +47,7 @@ class StartDeleteLocalActorApplicationServiceTest {
assertThrows<PermissionDeniedException> {
service.execute(
DeleteLocalActor(ActorId(2)),
FromApi(ActorId(1), UserDetailId((1)), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId((1)), Acct("test", "example.com"))
)
}
}
@ -57,7 +57,7 @@ class StartDeleteLocalActorApplicationServiceTest {
assertThrows<InternalServerException> {
service.execute(
DeleteLocalActor(ActorId(1)),
FromApi(ActorId(1), UserDetailId((1)), Acct("test", "example.com"))
LocalUser(ActorId(1), UserDetailId((1)), Acct("test", "example.com"))
)
}
}

View File

@ -6,7 +6,7 @@ import dev.usbharu.hideout.core.domain.model.filter.*
import dev.usbharu.hideout.core.domain.model.filter.Filter
import dev.usbharu.hideout.core.domain.model.filter.FilterKeyword
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
@ -43,7 +43,7 @@ class UserDeleteFilterApplicationServiceTest {
whenever(filterRepository.findByFilterId(FilterId(1))).doReturn(filter)
service.execute(
DeleteFilter(1), FromApi(
DeleteFilter(1), LocalUser(
ActorId(1), UserDetailId(1),
Acct("test", "example.com")
)
@ -56,7 +56,7 @@ class UserDeleteFilterApplicationServiceTest {
fun フィルターが見つからない場合失敗() = runTest {
assertThrows<IllegalArgumentException> {
service.execute(
DeleteFilter(1), FromApi(
DeleteFilter(1), LocalUser(
ActorId(1), UserDetailId(1),
Acct("test", "example.com")
)
@ -77,7 +77,7 @@ class UserDeleteFilterApplicationServiceTest {
assertThrows<PermissionDeniedException> {
service.execute(
DeleteFilter(1), FromApi(
DeleteFilter(1), LocalUser(
ActorId(3), UserDetailId(3),
Acct("test", "example.com")
)

View File

@ -6,7 +6,7 @@ import dev.usbharu.hideout.core.domain.model.filter.*
import dev.usbharu.hideout.core.domain.model.filter.Filter
import dev.usbharu.hideout.core.domain.model.filter.FilterKeyword
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
@ -43,7 +43,7 @@ class UserGetFilterApplicationServiceTest {
whenever(filterRepository.findByFilterId(FilterId(1))).doReturn(filter)
service.execute(
GetFilter(1), FromApi(
GetFilter(1), LocalUser(
ActorId(1), UserDetailId(1),
Acct("test", "example.com")
)
@ -64,7 +64,7 @@ class UserGetFilterApplicationServiceTest {
assertThrows<PermissionDeniedException> {
service.execute(
GetFilter(1), FromApi(
GetFilter(1), LocalUser(
ActorId(3), UserDetailId(3),
Acct("test", "example.com")
)
@ -76,7 +76,7 @@ class UserGetFilterApplicationServiceTest {
fun フィルターが見つからない場合失敗() = runTest {
assertThrows<IllegalArgumentException> {
service.execute(
GetFilter(1), FromApi(
GetFilter(1), LocalUser(
ActorId(3), UserDetailId(3),
Acct("test", "example.com")
)

View File

@ -8,7 +8,7 @@ import dev.usbharu.hideout.core.domain.model.post.PostId
import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.post.TestPostFactory
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
@ -41,7 +41,7 @@ class DeleteLocalPostApplicationServiceTest {
whenever(postRepository.findById(PostId(1))).doReturn(TestPostFactory.create(actorId = 2))
whenever(actorRepository.findById(ActorId(2))).doReturn(TestActorFactory.create(id = 2))
service.execute(DeleteLocalPost(1), FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
service.execute(DeleteLocalPost(1), LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
}
@Test
@ -49,7 +49,7 @@ class DeleteLocalPostApplicationServiceTest {
whenever(postRepository.findById(PostId(1))).doReturn(TestPostFactory.create(actorId = 2))
assertThrows<PermissionDeniedException> {
service.execute(DeleteLocalPost(1), FromApi(ActorId(3), UserDetailId(3), Acct("test", "example.com")))
service.execute(DeleteLocalPost(1), LocalUser(ActorId(3), UserDetailId(3), Acct("test", "example.com")))
}
}
}

View File

@ -8,7 +8,7 @@ import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.post.TestPostFactory
import dev.usbharu.hideout.core.domain.model.post.Visibility
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import dev.usbharu.hideout.core.infrastructure.factory.PostFactoryImpl
import kotlinx.coroutines.test.runTest
@ -59,7 +59,7 @@ class RegisterLocalPostApplicationServiceTest {
).doReturn(post)
service.execute(
RegisterLocalPost("content test", null, Visibility.PUBLIC, null, null, false, emptyList()), FromApi(
RegisterLocalPost("content test", null, Visibility.PUBLIC, null, null, false, emptyList()), LocalUser(
ActorId(1), UserDetailId(1), Acct("test", "example.com")
)
)
@ -71,7 +71,7 @@ class RegisterLocalPostApplicationServiceTest {
fun actorが見つからないと失敗() = runTest {
assertThrows<InternalServerException> {
service.execute(
RegisterLocalPost("content test", null, Visibility.PUBLIC, null, null, false, emptyList()), FromApi(
RegisterLocalPost("content test", null, Visibility.PUBLIC, null, null, false, emptyList()), LocalUser(
ActorId(1), UserDetailId(1), Acct("test", "example.com")
)
)

View File

@ -8,7 +8,7 @@ import dev.usbharu.hideout.core.domain.model.actor.TestActorFactory
import dev.usbharu.hideout.core.domain.model.post.*
import dev.usbharu.hideout.core.domain.model.post.Post
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetail
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailHashedPassword
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
@ -63,7 +63,7 @@ class UpdateLocalNoteApplicationServiceTest {
whenever(postContentFactoryImpl.create(eq("test"))).doReturn(content)
service.execute(
UpdateLocalNote(post.id.id, null, "test", false, emptyList()), FromApi(
UpdateLocalNote(post.id.id, null, "test", false, emptyList()), LocalUser(
post.actorId,
UserDetailId(1),
Acct("test", "example.com")
@ -84,7 +84,7 @@ class UpdateLocalNoteApplicationServiceTest {
fun postが見つからない場合失敗() = runTest {
assertThrows<IllegalArgumentException> {
service.execute(
UpdateLocalNote(1, null, "test", false, emptyList()), FromApi(
UpdateLocalNote(1, null, "test", false, emptyList()), LocalUser(
ActorId(1),
UserDetailId(1), Acct("test", "example.com")
)
@ -98,7 +98,7 @@ class UpdateLocalNoteApplicationServiceTest {
assertThrows<PermissionDeniedException> {
service.execute(
UpdateLocalNote(1, null, "test", false, emptyList()), FromApi(
UpdateLocalNote(1, null, "test", false, emptyList()), LocalUser(
ActorId(1),
UserDetailId(1), Acct("test", "example.com")
)
@ -112,7 +112,7 @@ class UpdateLocalNoteApplicationServiceTest {
assertThrows<InternalServerException> {
service.execute(
UpdateLocalNote(1, null, "test", false, emptyList()), FromApi(
UpdateLocalNote(1, null, "test", false, emptyList()), LocalUser(
ActorId(1),
UserDetailId(1), Acct("test", "example.com")
)
@ -138,7 +138,7 @@ class UpdateLocalNoteApplicationServiceTest {
assertThrows<InternalServerException> {
service.execute(
UpdateLocalNote(post.id.id, null, "test", false, emptyList()), FromApi(
UpdateLocalNote(post.id.id, null, "test", false, emptyList()), LocalUser(
post.actorId,
UserDetailId(1),
Acct("test", "example.com")

View File

@ -7,7 +7,7 @@ import dev.usbharu.hideout.core.domain.model.actor.TestActorFactory
import dev.usbharu.hideout.core.domain.model.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertFalse
@ -42,7 +42,7 @@ class UserAcceptFollowRequestApplicationServiceTest {
@Test
fun actorが見つからない場合失敗() = runTest {
assertThrows<InternalServerException> {
service.execute(AcceptFollowRequest(1), FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
service.execute(AcceptFollowRequest(1), LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
}
}
@ -51,7 +51,7 @@ class UserAcceptFollowRequestApplicationServiceTest {
whenever(actorRepository.findById(ActorId(2))).doReturn(TestActorFactory.create(id = 2))
assertThrows<InternalServerException> {
service.execute(AcceptFollowRequest(1), FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
service.execute(AcceptFollowRequest(1), LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
}
}
@ -68,7 +68,7 @@ class UserAcceptFollowRequestApplicationServiceTest {
followRequesting = true, mutingFollowRequest = false
)
)
service.execute(AcceptFollowRequest(1), FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
service.execute(AcceptFollowRequest(1), LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com")))
argumentCaptor<Relationship> {
verify(relationshipRepository).save(capture())

View File

@ -2,7 +2,7 @@ package dev.usbharu.hideout.core.application.shared
import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import org.slf4j.LoggerFactory
@ -13,7 +13,7 @@ class LocalUserAbstractApplicationServiceTest {
fun requireFromAPI() = runTest {
val logger = LoggerFactory.getLogger(javaClass)
val value = object : LocalUserAbstractApplicationService<Unit, Unit>(TestTransaction, logger) {
override suspend fun internalExecute(command: Unit, principal: FromApi) {
override suspend fun internalExecute(command: Unit, principal: LocalUser) {
}
}

View File

@ -7,7 +7,7 @@ import dev.usbharu.hideout.core.domain.model.relationship.Relationship
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
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.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertFalse
@ -44,7 +44,7 @@ class DefaultPostReadAccessControlTest {
val actual = service.isAllow(
TestPostFactory.create(actorId = 1),
FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
)
assertFalse(actual)
@ -72,7 +72,7 @@ class DefaultPostReadAccessControlTest {
fun DirectでvisibleActorsに含まれていたら見れる() = runTest {
val actual = service.isAllow(
TestPostFactory.create(actorId = 1, visibility = Visibility.DIRECT, visibleActors = listOf(2)),
FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
)
assertTrue(actual)
@ -82,7 +82,7 @@ class DefaultPostReadAccessControlTest {
fun DirectでvisibleActorsに含まれていなかったら見れない() = runTest {
val actual = service.isAllow(
TestPostFactory.create(actorId = 1, visibility = Visibility.DIRECT, visibleActors = listOf(3)),
FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
)
assertFalse(actual)
@ -111,7 +111,7 @@ class DefaultPostReadAccessControlTest {
val actual = service.isAllow(
TestPostFactory.create(actorId = 1, visibility = Visibility.FOLLOWERS),
FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
)
assertTrue(actual)
@ -121,7 +121,7 @@ class DefaultPostReadAccessControlTest {
fun relationshipが見つからない場合見れない() = runTest {
val actual = service.isAllow(
TestPostFactory.create(actorId = 1, visibility = Visibility.FOLLOWERS),
FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
)
assertFalse(actual)
@ -150,7 +150,7 @@ class DefaultPostReadAccessControlTest {
val actual = service.isAllow(
TestPostFactory.create(actorId = 1, visibility = Visibility.FOLLOWERS),
FromApi(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
LocalUser(ActorId(2), UserDetailId(2), Acct("test", "example.com"))
)
assertFalse(actual)

View File

@ -18,7 +18,7 @@ package dev.usbharu.hideout.mastodon.application.accounts
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.Account
import dev.usbharu.hideout.mastodon.query.AccountQueryService
import org.slf4j.LoggerFactory
@ -30,7 +30,7 @@ class GetAccountApplicationService(private val accountQueryService: AccountQuery
transaction,
logger
) {
override suspend fun internalExecute(command: GetAccount, principal: FromApi): Account {
override suspend fun internalExecute(command: GetAccount, principal: LocalUser): Account {
return accountQueryService.findById(command.accountId.toLong()) ?: throw Exception("Account not found")
}

View File

@ -21,7 +21,7 @@ import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationS
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.filter.FilterKeywordId
import dev.usbharu.hideout.core.domain.model.filter.FilterRepository
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@ -30,7 +30,7 @@ class DeleteFilterV1ApplicationService(private val filterRepository: FilterRepos
LocalUserAbstractApplicationService<DeleteFilterV1, Unit>(
transaction, logger
) {
override suspend fun internalExecute(command: DeleteFilterV1, principal: FromApi) {
override suspend fun internalExecute(command: DeleteFilterV1, principal: LocalUser) {
val filter = filterRepository.findByFilterKeywordId(FilterKeywordId(command.filterKeywordId))
?: throw IllegalArgumentException("Filter ${command.filterKeywordId} not found")
if (principal.userDetailId != filter.userDetailId) {

View File

@ -20,7 +20,7 @@ import dev.usbharu.hideout.core.application.filter.*
import dev.usbharu.hideout.core.domain.model.filter.FilterAction
import dev.usbharu.hideout.core.domain.model.filter.FilterContext
import dev.usbharu.hideout.core.domain.model.filter.FilterMode
import dev.usbharu.hideout.core.domain.model.support.principal.PrincipalContextHolder
import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.SpringSecurityOauth2PrincipalContextHolder
import dev.usbharu.hideout.mastodon.application.filter.DeleteFilterV1
import dev.usbharu.hideout.mastodon.application.filter.DeleteFilterV1ApplicationService
import dev.usbharu.hideout.mastodon.application.filter.GetFilterV1
@ -41,7 +41,7 @@ class SpringFilterApi(
private val deleteFilterV1ApplicationService: DeleteFilterV1ApplicationService,
private val userDeleteFilterApplicationService: UserDeleteFilterApplicationService,
private val userGetFilterApplicationService: UserGetFilterApplicationService,
private val principalContextHolder: PrincipalContextHolder
private val principalContextHolder: SpringSecurityOauth2PrincipalContextHolder
) : FilterApi {
override suspend fun apiV1FiltersIdDelete(id: String): ResponseEntity<Any> {

View File

@ -19,7 +19,7 @@ package dev.usbharu.hideout.mastodon.interfaces.api
import dev.usbharu.hideout.core.application.media.UploadMedia
import dev.usbharu.hideout.core.application.media.UploadMediaApplicationService
import dev.usbharu.hideout.core.domain.model.media.FileType.*
import dev.usbharu.hideout.core.domain.model.support.principal.PrincipalContextHolder
import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.SpringSecurityOauth2PrincipalContextHolder
import dev.usbharu.hideout.mastodon.interfaces.api.generated.MediaApi
import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.MediaAttachment
import org.springframework.http.ResponseEntity
@ -30,7 +30,7 @@ import java.nio.file.Files
@Controller
class SpringMediaApi(
private val uploadMediaApplicationService: UploadMediaApplicationService,
private val principalContextHolder: PrincipalContextHolder
private val principalContextHolder: SpringSecurityOauth2PrincipalContextHolder
) : MediaApi {
override suspend fun apiV1MediaPost(
file: MultipartFile,

View File

@ -19,7 +19,7 @@ package dev.usbharu.hideout.mastodon.interfaces.api
import dev.usbharu.hideout.core.application.post.RegisterLocalPost
import dev.usbharu.hideout.core.application.post.RegisterLocalPostApplicationService
import dev.usbharu.hideout.core.domain.model.post.Visibility
import dev.usbharu.hideout.core.domain.model.support.principal.PrincipalContextHolder
import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.SpringSecurityOauth2PrincipalContextHolder
import dev.usbharu.hideout.mastodon.application.status.GetStatus
import dev.usbharu.hideout.mastodon.application.status.GetStatusApplicationService
import dev.usbharu.hideout.mastodon.interfaces.api.StatusesRequest.Visibility.*
@ -32,7 +32,7 @@ import org.springframework.stereotype.Controller
class SpringStatusApi(
private val registerLocalPostApplicationService: RegisterLocalPostApplicationService,
private val getStatusApplicationService: GetStatusApplicationService,
private val principalContextHolder: PrincipalContextHolder
private val principalContextHolder: SpringSecurityOauth2PrincipalContextHolder
) : StatusApi {
override suspend fun apiV1StatusesIdEmojiReactionsEmojiDelete(id: String, emoji: String): ResponseEntity<Status> {
return super.apiV1StatusesIdEmojiReactionsEmojiDelete(id, emoji)

View File

@ -3,7 +3,7 @@ package dev.usbharu.hideout.mastodon.infrastructure.exposedquery
import dev.usbharu.hideout.SpringApplication
import dev.usbharu.hideout.core.domain.model.actor.ActorId
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.principal.FromApi
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertNull
@ -26,7 +26,7 @@ class StatusQueryServiceImplTest {
@Test
fun フォロワー限定をフォロワー以外は見れない() = runTest {
val status =
statusQueryServiceImpl.findByPostId(4, FromApi(ActorId(1), UserDetailId(1), Acct("test", "example.com")))
statusQueryServiceImpl.findByPostId(4, LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com")))
assertNull(status)
}