mirror of https://github.com/usbharu/Hideout.git
feat: 投稿のap idにアクセスすると投稿を取得できるように
This commit is contained in:
parent
108f521f23
commit
1547c0edaa
|
@ -0,0 +1,16 @@
|
||||||
|
package dev.usbharu.hideout.controller
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.ap.Note
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.security.core.annotation.CurrentSecurityContext
|
||||||
|
import org.springframework.security.core.context.SecurityContext
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
|
||||||
|
interface NoteApController {
|
||||||
|
@GetMapping("/users/*/posts/{postId}")
|
||||||
|
suspend fun postsAp(
|
||||||
|
@PathVariable("postId") postId: Long,
|
||||||
|
@CurrentSecurityContext context: SecurityContext
|
||||||
|
): ResponseEntity<Note>
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package dev.usbharu.hideout.controller
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.ap.Note
|
||||||
|
import dev.usbharu.hideout.service.api.NoteApApiService
|
||||||
|
import dev.usbharu.hideout.service.signature.HttpSignatureUser
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.security.core.annotation.CurrentSecurityContext
|
||||||
|
import org.springframework.security.core.context.SecurityContext
|
||||||
|
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
class NoteApControllerImpl(private val noteApApiService: NoteApApiService) : NoteApController {
|
||||||
|
override suspend fun postsAp(
|
||||||
|
@PathVariable(value = "postId") postId: Long, @CurrentSecurityContext context: SecurityContext
|
||||||
|
): ResponseEntity<Note> {
|
||||||
|
|
||||||
|
val userId =
|
||||||
|
if (context.authentication is PreAuthenticatedAuthenticationToken && context.authentication.details is HttpSignatureUser) {
|
||||||
|
(context.authentication.details as HttpSignatureUser).id
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
val note = noteApApiService.getNote(postId, userId)
|
||||||
|
if (note != null) {
|
||||||
|
return ResponseEntity.ok(note)
|
||||||
|
}
|
||||||
|
return ResponseEntity.notFound().build()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
package dev.usbharu.hideout.query
|
package dev.usbharu.hideout.query
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
interface FollowerQueryService {
|
interface FollowerQueryService {
|
||||||
suspend fun findFollowersById(id: Long): List<User>
|
suspend fun findFollowersById(id: Long): List<User>
|
||||||
suspend fun findFollowersByNameAndDomain(name: String, domain: String): List<User>
|
suspend fun findFollowersByNameAndDomain(name: String, domain: String): List<User>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package dev.usbharu.hideout.query.activitypub
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.ap.Note
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
|
|
||||||
|
interface NoteQueryService {
|
||||||
|
suspend fun findById(id: Long): Pair<Note, Post>
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package dev.usbharu.hideout.query.activitypub
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.ap.Note
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
|
import dev.usbharu.hideout.exception.FailedToGetResourcesException
|
||||||
|
import dev.usbharu.hideout.repository.Posts
|
||||||
|
import dev.usbharu.hideout.repository.Users
|
||||||
|
import dev.usbharu.hideout.repository.toPost
|
||||||
|
import dev.usbharu.hideout.util.singleOr
|
||||||
|
import org.jetbrains.exposed.sql.ResultRow
|
||||||
|
import org.jetbrains.exposed.sql.select
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class NoteQueryServiceImpl : NoteQueryService {
|
||||||
|
override suspend fun findById(id: Long): Pair<Note, Post> {
|
||||||
|
return Posts
|
||||||
|
.leftJoin(Users)
|
||||||
|
.select { Posts.id eq id }
|
||||||
|
.singleOr { FailedToGetResourcesException("id $id is duplicate or does not exist.") }
|
||||||
|
.let { it.toNote() to it.toPost() }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ResultRow.toNote(): Note {
|
||||||
|
return Note(
|
||||||
|
name = "Post",
|
||||||
|
id = this[Posts.apId],
|
||||||
|
attributedTo = this[Users.url],
|
||||||
|
content = this[Posts.text],
|
||||||
|
published = Instant.ofEpochMilli(this[Posts.createdAt]).toString(),
|
||||||
|
to = listOf(),
|
||||||
|
cc = listOf(),
|
||||||
|
inReplyTo = null,
|
||||||
|
sensitive = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package dev.usbharu.hideout.service.api
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.ap.Note
|
||||||
|
|
||||||
|
interface NoteApApiService {
|
||||||
|
suspend fun getNote(postId: Long, userId: Long?): Note?
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package dev.usbharu.hideout.service.api
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.ap.Note
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||||
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
|
import dev.usbharu.hideout.query.activitypub.NoteQueryService
|
||||||
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class NoteApApiServiceImpl(
|
||||||
|
private val noteQueryService: NoteQueryService,
|
||||||
|
private val followerQueryService: FollowerQueryService,
|
||||||
|
private val transaction: Transaction
|
||||||
|
) : NoteApApiService {
|
||||||
|
override suspend fun getNote(postId: Long, userId: Long?): Note? = transaction.transaction {
|
||||||
|
val findById = noteQueryService.findById(postId)
|
||||||
|
when (findById.second.visibility) {
|
||||||
|
Visibility.PUBLIC, Visibility.UNLISTED -> {
|
||||||
|
return@transaction findById.first
|
||||||
|
}
|
||||||
|
|
||||||
|
Visibility.FOLLOWERS -> {
|
||||||
|
if (userId == null) {
|
||||||
|
return@transaction null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (followerQueryService.alreadyFollow(findById.second.userId, userId).not()) {
|
||||||
|
return@transaction null
|
||||||
|
}
|
||||||
|
return@transaction findById.first
|
||||||
|
}
|
||||||
|
|
||||||
|
Visibility.DIRECT -> return@transaction null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import java.io.Serial
|
||||||
class HttpSignatureUser(
|
class HttpSignatureUser(
|
||||||
username: String,
|
username: String,
|
||||||
val domain: String,
|
val domain: String,
|
||||||
|
val id: Long,
|
||||||
credentialsNonExpired: Boolean,
|
credentialsNonExpired: Boolean,
|
||||||
accountNonLocked: Boolean,
|
accountNonLocked: Boolean,
|
||||||
authorities: MutableCollection<out GrantedAuthority>?
|
authorities: MutableCollection<out GrantedAuthority>?
|
||||||
|
@ -19,6 +20,26 @@ class HttpSignatureUser(
|
||||||
accountNonLocked,
|
accountNonLocked,
|
||||||
authorities
|
authorities
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other !is HttpSignatureUser) return false
|
||||||
|
if (!super.equals(other)) return false
|
||||||
|
|
||||||
|
if (domain != other.domain) return false
|
||||||
|
if (id != other.id) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = super.hashCode()
|
||||||
|
result = 31 * result + domain.hashCode()
|
||||||
|
result = 31 * result + id.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Serial
|
@Serial
|
||||||
private const val serialVersionUID: Long = -3330552099960982997L
|
private const val serialVersionUID: Long = -3330552099960982997L
|
||||||
|
|
|
@ -49,6 +49,7 @@ class HttpSignatureUserDetailsService(
|
||||||
HttpSignatureUser(
|
HttpSignatureUser(
|
||||||
username = findByKeyId.name,
|
username = findByKeyId.name,
|
||||||
domain = findByKeyId.domain,
|
domain = findByKeyId.domain,
|
||||||
|
id = findByKeyId.id,
|
||||||
credentialsNonExpired = true,
|
credentialsNonExpired = true,
|
||||||
accountNonLocked = true,
|
accountNonLocked = true,
|
||||||
authorities = mutableListOf()
|
authorities = mutableListOf()
|
||||||
|
|
Loading…
Reference in New Issue