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
|
||||
|
||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface FollowerQueryService {
|
||||
suspend fun findFollowersById(id: Long): 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(
|
||||
username: String,
|
||||
val domain: String,
|
||||
val id: Long,
|
||||
credentialsNonExpired: Boolean,
|
||||
accountNonLocked: Boolean,
|
||||
authorities: MutableCollection<out GrantedAuthority>?
|
||||
|
@ -19,6 +20,26 @@ class HttpSignatureUser(
|
|||
accountNonLocked,
|
||||
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 {
|
||||
@Serial
|
||||
private const val serialVersionUID: Long = -3330552099960982997L
|
||||
|
|
|
@ -49,6 +49,7 @@ class HttpSignatureUserDetailsService(
|
|||
HttpSignatureUser(
|
||||
username = findByKeyId.name,
|
||||
domain = findByKeyId.domain,
|
||||
id = findByKeyId.id,
|
||||
credentialsNonExpired = true,
|
||||
accountNonLocked = true,
|
||||
authorities = mutableListOf()
|
||||
|
|
Loading…
Reference in New Issue