refactor: Ktor使用箇所を削除

This commit is contained in:
usbharu 2023-09-22 23:42:22 +09:00
parent 887249c68d
commit 70ba6ae4f8
20 changed files with 0 additions and 936 deletions

View File

@ -1,172 +0,0 @@
package dev.usbharu.hideout
import com.auth0.jwk.JwkProvider
import com.auth0.jwk.JwkProviderBuilder
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import dev.usbharu.hideout.config.CharacterLimit
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.config.ConfigData
import dev.usbharu.hideout.domain.model.job.DeliverPostJob
import dev.usbharu.hideout.domain.model.job.DeliverReactionJob
import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
import dev.usbharu.hideout.plugins.*
import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.routing.register
import dev.usbharu.hideout.service.ap.APService
import dev.usbharu.hideout.service.ap.APUserService
import dev.usbharu.hideout.service.api.PostApiService
import dev.usbharu.hideout.service.api.UserApiService
import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.api.WebFingerApiService
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import dev.usbharu.hideout.service.core.*
import dev.usbharu.hideout.service.job.JobQueueParentService
import dev.usbharu.hideout.service.job.KJobJobQueueParentService
import dev.usbharu.hideout.service.user.UserService
import dev.usbharu.kjob.exposed.ExposedKJob
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.logging.*
import io.ktor.server.application.*
import kjob.core.kjob
import kotlinx.coroutines.runBlocking
import org.jetbrains.exposed.sql.Database
import org.koin.ksp.generated.module
import org.koin.ktor.ext.inject
import java.util.concurrent.TimeUnit
@Deprecated("Ktor is deprecated")
fun main(args: Array<String>): Unit = io.ktor.server.cio.EngineMain.main(args)
val Application.property: Application.(propertyName: String) -> String
get() = {
environment.config.property(it).getString()
}
val Application.propertyOrNull: Application.(propertyName: String) -> String?
get() = {
environment.config.propertyOrNull(it)?.getString()
}
// application.conf references the main function. This annotation prevents the IDE from marking it as unused.
@Deprecated("Ktor is deprecated")
@Suppress("unused", "LongMethod")
fun Application.parent() {
Config.configData = ConfigData(
url = property("hideout.url"),
objectMapper = jacksonObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false),
characterLimit = CharacterLimit(
general = CharacterLimit.General.of(
url = propertyOrNull("hideout.character-limit.general.url")?.toIntOrNull(),
domain = propertyOrNull("hideout.character-limit.general.domain")?.toIntOrNull(),
publicKey = propertyOrNull("hideout.character-limit.general.publicKey")?.toIntOrNull(),
privateKey = propertyOrNull("hideout.character-limit.general.privateKey")?.toIntOrNull()
)
)
)
val module = org.koin.dsl.module {
single<Database> {
Database.connect(
url = property("hideout.database.url"),
driver = property("hideout.database.driver"),
user = property("hideout.database.username"),
password = property("hideout.database.password")
)
}
single<JobQueueParentService> {
val kJobJobQueueService = KJobJobQueueParentService(get())
kJobJobQueueService.init(emptyList())
kJobJobQueueService
}
single<HttpClient> {
HttpClient(CIO).config {
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.INFO
}
install(httpSignaturePlugin) {
keyMap = KtorKeyMap(get(), get())
}
expectSuccess = true
}
}
single<IdGenerateService> { TwitterSnowflakeIdGenerateService }
single<JwkProvider> {
JwkProviderBuilder(Config.configData.url).cached(
10,
24,
TimeUnit.HOURS
)
.rateLimited(10, 1, TimeUnit.MINUTES).build()
}
}
configureKoin(module, HideoutModule().module)
configureStatusPages()
runBlocking {
inject<ServerInitialiseService>().value.init()
}
configureCompression()
configureHTTP()
configureStaticRouting()
configureMonitoring()
configureSerialization()
register(inject<UserApiService>().value)
configureSecurity(
inject<JwkProvider>().value,
inject<MetaService>().value
)
configureRouting(
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
apService = inject<APService>().value,
userService = inject<UserService>().value,
apUserService = inject<APUserService>().value,
postService = inject<PostApiService>().value,
userApiService = inject<UserApiService>().value,
userQueryService = inject<UserQueryService>().value,
followerQueryService = inject<FollowerQueryService>().value,
userAuthApiService = inject<UserAuthApiService>().value,
webFingerApiService = inject<WebFingerApiService>().value,
transaction = inject<Transaction>().value
)
}
@Deprecated("Ktor is deprecated")
@Suppress("unused")
fun Application.worker() {
val kJob = kjob(ExposedKJob) {
connectionDatabase = inject<Database>().value
}.start()
val apService = inject<APService>().value
kJob.register(ReceiveFollowJob) {
execute {
apService.processActivity(this, it)
}
}
kJob.register(DeliverPostJob) {
execute {
apService.processActivity(this, it)
}
}
kJob.register(DeliverReactionJob) {
execute {
apService.processActivity(this, it)
}
}
kJob.register(DeliverRemoveReactionJob) {
execute {
apService.processActivity(this, it)
}
}
}

View File

@ -11,8 +11,6 @@ import io.ktor.client.plugins.api.*
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.statement.* import io.ktor.client.statement.*
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import tech.barbero.http.message.signing.HttpMessage import tech.barbero.http.message.signing.HttpMessage
import tech.barbero.http.message.signing.HttpMessageSigner import tech.barbero.http.message.signing.HttpMessageSigner
@ -28,12 +26,6 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
import javax.crypto.SecretKey import javax.crypto.SecretKey
suspend fun <T : JsonLd> ApplicationCall.respondAp(message: T, status: HttpStatusCode = HttpStatusCode.OK) {
message.context += "https://www.w3.org/ns/activitystreams"
val activityJson = Config.configData.objectMapper.writeValueAsString(message)
respondText(activityJson, ContentType.Application.Activity, status)
}
suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonLd): HttpResponse { suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonLd): HttpResponse {
jsonLd.context += "https://www.w3.org/ns/activitystreams" jsonLd.context += "https://www.w3.org/ns/activitystreams"
return this.post(urlString) { return this.post(urlString) {

View File

@ -1,20 +0,0 @@
package dev.usbharu.hideout.plugins
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.plugins.compression.*
@Deprecated("Ktor is deprecated")
fun Application.configureCompression() {
install(Compression) {
gzip {
matchContentType(ContentType.Application.JavaScript)
priority = 1.0
}
deflate {
matchContentType(ContentType.Application.JavaScript)
priority = 10.0
minimumSize(1024) // condition
}
}
}

View File

@ -1,24 +0,0 @@
package dev.usbharu.hideout.plugins
import io.ktor.server.application.*
import io.ktor.server.plugins.defaultheaders.*
import io.ktor.server.plugins.forwardedheaders.*
@Deprecated("Ktor is deprecated")
fun Application.configureHTTP() {
// install(CORS) {
// allowMethod(HttpMethod.Options)
// allowMethod(HttpMethod.Put)
// allowMethod(HttpMethod.Delete)
// allowMethod(HttpMethod.Patch)
// allowHeader(HttpHeaders.Authorization)
// allow
// allowHeader("MyCustomHeader")
// anyHost() // @TODO: Don't do this in production if possible. Try to limit it.
// }
install(DefaultHeaders) {
header("X-Engine", "Ktor") // will send this header with each response
}
install(ForwardedHeaders) // WARNING: for security, do not include this if not behind a reverse proxy
install(XForwardedHeaders) // WARNING: for security, do not include this if not behind a reverse proxy
}

View File

@ -1,14 +0,0 @@
package dev.usbharu.hideout.plugins
import io.ktor.server.application.*
import org.koin.core.module.Module
import org.koin.ktor.plugin.Koin
import org.koin.logger.slf4jLogger
@Deprecated("Ktor is deprecated")
fun Application.configureKoin(vararg module: Module) {
install(Koin) {
slf4jLogger()
modules(*module)
}
}

View File

@ -1,12 +0,0 @@
package dev.usbharu.hideout.plugins
import io.ktor.server.application.*
import io.ktor.server.plugins.callloging.*
import org.slf4j.event.Level
@Deprecated("Ktor is deprecated")
fun Application.configureMonitoring() {
install(CallLogging) {
level = Level.INFO
}
}

View File

@ -1,52 +0,0 @@
package dev.usbharu.hideout.plugins
import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.routing.activitypub.inbox
import dev.usbharu.hideout.routing.activitypub.outbox
import dev.usbharu.hideout.routing.activitypub.usersAP
import dev.usbharu.hideout.routing.api.internal.v1.auth
import dev.usbharu.hideout.routing.api.internal.v1.posts
import dev.usbharu.hideout.routing.api.internal.v1.users
import dev.usbharu.hideout.routing.wellknown.webfinger
import dev.usbharu.hideout.service.ap.APService
import dev.usbharu.hideout.service.ap.APUserService
import dev.usbharu.hideout.service.api.PostApiService
import dev.usbharu.hideout.service.api.UserApiService
import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.api.WebFingerApiService
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.user.UserService
import io.ktor.server.application.*
import io.ktor.server.plugins.autohead.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
@Suppress("LongParameterList")
fun Application.configureRouting(
httpSignatureVerifyService: HttpSignatureVerifyService,
apService: APService,
userService: UserService,
apUserService: APUserService,
postService: PostApiService,
userApiService: UserApiService,
userQueryService: UserQueryService,
followerQueryService: FollowerQueryService,
userAuthApiService: UserAuthApiService,
webFingerApiService: WebFingerApiService,
transaction: Transaction
) {
install(AutoHeadResponse)
routing {
inbox(httpSignatureVerifyService, apService)
outbox()
usersAP(apUserService, userQueryService, followerQueryService, transaction)
webfinger(webFingerApiService)
route("/api/internal/v1") {
posts(postService)
users(userService, userApiService)
auth(userAuthApiService)
}
}
}

View File

@ -1,51 +0,0 @@
package dev.usbharu.hideout.plugins
import com.auth0.jwk.JwkProvider
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.service.core.MetaService
import dev.usbharu.hideout.util.JsonWebKeyUtil
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
const val TOKEN_AUTH = "jwt-auth"
@Deprecated("Ktor is deprecated")
@Suppress("MagicNumber")
fun Application.configureSecurity(
jwkProvider: JwkProvider,
metaService: MetaService
) {
val issuer = Config.configData.url
install(Authentication) {
jwt(TOKEN_AUTH) {
verifier(jwkProvider, issuer) {
acceptLeeway(3)
}
validate { jwtCredential ->
val uid = jwtCredential.payload.getClaim("uid")
if (uid.isMissing) {
return@validate null
}
if (uid.asLong() == null) {
return@validate null
}
return@validate JWTPrincipal(jwtCredential.payload)
}
}
}
routing {
get("/.well-known/jwks.json") {
//language=JSON
val jwt = metaService.getJwtMeta()
call.respondText(
contentType = ContentType.Application.Json,
text = JsonWebKeyUtil.publicKeyToJwk(jwt.publicKey, jwt.kid.toString())
)
}
}
}

View File

@ -1,21 +0,0 @@
package dev.usbharu.hideout.plugins
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonSetter
import com.fasterxml.jackson.annotation.Nulls
import com.fasterxml.jackson.databind.DeserializationFeature
import io.ktor.serialization.jackson.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
@Deprecated("Ktor is deprecated")
fun Application.configureSerialization() {
install(ContentNegotiation) {
jackson {
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
configOverride(List::class.java).setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY))
}
}
}

View File

@ -1,22 +0,0 @@
package dev.usbharu.hideout.plugins
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.http.content.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
fun Application.configureStaticRouting() {
routing {
get("/") {
call.respondText(
String.javaClass.classLoader.getResourceAsStream("static/index.html").readAllBytes().decodeToString(),
contentType = ContentType.Text.Html
)
}
static("/") {
resources("static")
}
}
}

View File

@ -1,24 +0,0 @@
package dev.usbharu.hideout.plugins
import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.plugins.statuspages.*
import io.ktor.server.response.*
@Deprecated("Ktor is deprecated")
fun Application.configureStatusPages() {
install(StatusPages) {
exception<IllegalArgumentException> { call, cause ->
call.respondText(text = "400: $cause", status = HttpStatusCode.BadRequest)
call.application.log.warn("Bad Request", cause)
}
exception<InvalidUsernameOrPasswordException> { call, _ ->
call.respond(HttpStatusCode.Unauthorized)
}
exception<Throwable> { call, cause ->
call.respondText(text = "500: ${cause.stackTraceToString()}", status = HttpStatusCode.InternalServerError)
call.application.log.error("Internal Server Error", cause)
}
}
}

View File

@ -1,44 +0,0 @@
package dev.usbharu.hideout.routing
import dev.usbharu.hideout.service.api.UserApiService
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
fun Application.register(userApiService: UserApiService) {
routing {
get("/register") {
val principal = call.principal<UserIdPrincipal>()
if (principal != null) {
call.respondRedirect("/users/${principal.name}")
}
call.respondText(ContentType.Text.Html) {
//language=HTML
"""
<html>
<head>
</head>
<body>
<form method='post' action=''>
<input type='text' name='username' value=''>
<input type='password' name='password'>
<input type="submit">
</form>
</body>
</html>
""".trimIndent()
}
}
post("/register") {
val parameters = call.receiveParameters()
val password = parameters["password"] ?: return@post call.respondRedirect("/register")
val username = parameters["username"] ?: return@post call.respondRedirect("/register")
userApiService.createUser(username, password)
call.respondRedirect("/users/$username")
}
}
}

View File

@ -1,77 +0,0 @@
package dev.usbharu.hideout.routing.activitypub
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.ActivityPubObjectResponse
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
import dev.usbharu.hideout.exception.HttpSignatureVerifyException
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
fun Routing.inbox(
httpSignatureVerifyService: HttpSignatureVerifyService,
apService: dev.usbharu.hideout.service.ap.APService
) {
route("/inbox") {
get {
call.respond(HttpStatusCode.MethodNotAllowed)
}
post {
if (httpSignatureVerifyService.verify(call.request.headers).not()) {
throw HttpSignatureVerifyException()
}
val json = call.receiveText()
call.application.log.trace("Received: $json")
val activityTypes = apService.parseActivity(json)
call.application.log.debug("ActivityTypes: ${activityTypes.name}")
val response = apService.processActivity(json, activityTypes)
when (response) {
is ActivityPubObjectResponse -> call.respond(
response.httpStatusCode,
Config.configData.objectMapper.writeValueAsString(
response.message.apply {
context =
listOf("https://www.w3.org/ns/activitystreams")
}
)
)
is ActivityPubStringResponse -> call.respond(response.httpStatusCode, response.message)
null -> call.respond(HttpStatusCode.NotImplemented)
}
}
}
route("/users/{name}/inbox") {
get {
call.respond(HttpStatusCode.MethodNotAllowed)
}
post {
if (httpSignatureVerifyService.verify(call.request.headers).not()) {
throw HttpSignatureVerifyException()
}
val json = call.receiveText()
call.application.log.trace("Received: $json")
val activityTypes = apService.parseActivity(json)
call.application.log.debug("ActivityTypes: ${activityTypes.name}")
val response = apService.processActivity(json, activityTypes)
when (response) {
is ActivityPubObjectResponse -> call.respond(
response.httpStatusCode,
Config.configData.objectMapper.writeValueAsString(
response.message.apply {
context =
listOf("https://www.w3.org/ns/activitystreams")
}
)
)
is ActivityPubStringResponse -> call.respond(response.httpStatusCode, response.message)
null -> call.respond(HttpStatusCode.NotImplemented)
}
}
}
}

View File

@ -1,26 +0,0 @@
package dev.usbharu.hideout.routing.activitypub
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
fun Routing.outbox() {
route("/outbox") {
get {
call.respond(HttpStatusCode.NotImplemented)
}
post {
call.respond(HttpStatusCode.NotImplemented)
}
}
route("/users/{name}/outbox") {
get {
call.respond(HttpStatusCode.NotImplemented)
}
post {
call.respond(HttpStatusCode.NotImplemented)
}
}
}

View File

@ -1,65 +0,0 @@
package dev.usbharu.hideout.routing.activitypub
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.exception.ParameterNotExistException
import dev.usbharu.hideout.plugins.respondAp
import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.ap.APUserService
import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.util.HttpUtil.Activity
import dev.usbharu.hideout.util.HttpUtil.JsonLd
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
fun Routing.usersAP(
apUserService: APUserService,
userQueryService: UserQueryService,
followerQueryService: FollowerQueryService,
transaction: Transaction
) {
route("/users/{name}") {
createChild(ContentTypeRouteSelector(ContentType.Application.Activity, ContentType.Application.JsonLd)).handle {
call.application.log.debug("Signature: ${call.request.header("Signature")}")
call.application.log.debug("Authorization: ${call.request.header("Authorization")}")
val name =
call.parameters["name"] ?: throw ParameterNotExistException("Parameter(name='name') does not exist.")
val person = apUserService.getPersonByName(name)
return@handle call.respondAp(person, HttpStatusCode.OK)
}
get {
// TODO: 暫定処置なので治す
transaction.transaction {
val userEntity = userQueryService.findByNameAndDomain(
call.parameters["name"]
?: throw ParameterNotExistException("Parameter(name='name') does not exist."),
Config.configData.domain
)
val personByName = apUserService.getPersonByName(userEntity.name)
call.respondText(
userEntity.toString() + "\n" + followerQueryService.findFollowersById(userEntity.id) +
"\n" + Config.configData.objectMapper.writeValueAsString(
personByName
)
)
}
}
}
}
@Deprecated("Ktor is deprecated")
class ContentTypeRouteSelector(private vararg val contentType: ContentType) : RouteSelector() {
override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {
context.call.application.log.debug("Accept: ${context.call.request.accept()}")
val requestContentType = context.call.request.accept() ?: return RouteSelectorEvaluation.FailedParameter
return if (requestContentType.split(",").any { contentType.any { contentType -> contentType.match(it) } }) {
RouteSelectorEvaluation.Constant
} else {
RouteSelectorEvaluation.FailedParameter
}
}
}

View File

@ -1,32 +0,0 @@
package dev.usbharu.hideout.routing.api.internal.v1
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.service.api.UserAuthApiService
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
fun Route.auth(userAuthApiService: UserAuthApiService) {
post("/login") {
val loginUser = call.receive<UserLogin>()
return@post call.respond(userAuthApiService.login(loginUser.username, loginUser.password))
}
post("/refresh-token") {
val refreshToken = call.receive<RefreshToken>()
return@post call.respond(userAuthApiService.refreshToken(refreshToken))
}
authenticate(TOKEN_AUTH) {
get("/auth-check") {
val principal = call.principal<JWTPrincipal>() ?: throw IllegalStateException("no principal")
val username = principal.payload.getClaim("uid")
call.respondText("Hello $username")
}
}
}

View File

@ -1,102 +0,0 @@
package dev.usbharu.hideout.routing.api.internal.v1
import dev.usbharu.hideout.domain.model.hideout.form.Post
import dev.usbharu.hideout.domain.model.hideout.form.Reaction
import dev.usbharu.hideout.exception.ParameterNotExistException
import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.service.api.PostApiService
import dev.usbharu.hideout.util.InstantParseUtil
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
@Suppress("LongMethod")
fun Route.posts(postApiService: PostApiService) {
route("/posts") {
authenticate(TOKEN_AUTH) {
post {
val principal = call.principal<JWTPrincipal>() ?: throw IllegalStateException("no principal")
val userId = principal.payload.getClaim("uid").asLong()
val receive = call.receive<Post>()
val create = postApiService.createPost(receive, userId)
call.response.header("Location", create.url)
call.respond(HttpStatusCode.OK)
}
route("/{id}/reactions") {
get {
val principal = call.principal<JWTPrincipal>() ?: throw IllegalStateException("no principal")
val userId = principal.payload.getClaim("uid").asLong()
val postId = (
call.parameters["id"]?.toLong()
?: throw ParameterNotExistException("Parameter(id='postsId') does not exist.")
)
call.respond(postApiService.getReactionByPostId(postId, userId))
}
post {
val jwtPrincipal = call.principal<JWTPrincipal>() ?: throw IllegalStateException("no principal")
val userId = jwtPrincipal.payload.getClaim("uid").asLong()
val postId = call.parameters["id"]?.toLong()
?: throw ParameterNotExistException("Parameter(id='postsId') does not exist.")
val reaction = try {
call.receive<Reaction>()
} catch (_: ContentTransformationException) {
Reaction(null)
}
postApiService.appendReaction(reaction.reaction ?: "", userId, postId)
call.respond(HttpStatusCode.NoContent)
}
delete {
val jwtPrincipal = call.principal<JWTPrincipal>() ?: throw IllegalStateException("no principal")
val userId = jwtPrincipal.payload.getClaim("uid").asLong()
val postId = call.parameters["id"]?.toLong()
?: throw ParameterNotExistException("Parameter(id='postsId') does not exist.")
postApiService.removeReaction(userId, postId)
call.respond(HttpStatusCode.NoContent)
}
}
}
authenticate(TOKEN_AUTH, optional = true) {
get {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
val since = InstantParseUtil.parse(call.request.queryParameters["since"])
val until = InstantParseUtil.parse(call.request.queryParameters["until"])
val minId = call.request.queryParameters["minId"]?.toLong()
val maxId = call.request.queryParameters["maxId"]?.toLong()
val limit = call.request.queryParameters["limit"]?.toInt()
call.respond(HttpStatusCode.OK, postApiService.getAll(since, until, minId, maxId, limit, userId))
}
get("/{id}") {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
val id = call.parameters["id"]?.toLong()
?: throw ParameterNotExistException("Parameter(id='postsId') does not exist.")
val post = postApiService.getById(id, userId)
call.respond(post)
}
}
}
route("/users/{name}/posts") {
authenticate(TOKEN_AUTH, optional = true) {
get {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
val targetUserName = call.parameters["name"]
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
val posts = postApiService.getByUser(targetUserName, userId = userId)
call.respond(posts)
}
get("/{id}") {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
val id = call.parameters["id"]?.toLong()
?: throw ParameterNotExistException("Parameter(name='postsId' does not exist.")
val post = postApiService.getById(id, userId)
call.respond(post)
}
}
}
}

View File

@ -1,107 +0,0 @@
package dev.usbharu.hideout.routing.api.internal.v1
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
import dev.usbharu.hideout.exception.ParameterNotExistException
import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.service.api.UserApiService
import dev.usbharu.hideout.service.user.UserService
import dev.usbharu.hideout.util.AcctUtil
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
@Suppress("LongMethod", "CognitiveComplexMethod")
fun Route.users(userService: UserService, userApiService: UserApiService) {
route("/users") {
get {
call.respond(userApiService.findAll())
}
post {
val userCreate = call.receive<UserCreate>()
if (userService.usernameAlreadyUse(userCreate.username)) {
return@post call.respond(HttpStatusCode.BadRequest)
}
val user = userService.createLocalUser(
UserCreateDto(
userCreate.username,
userCreate.username,
"",
userCreate.password
)
)
call.response.header("Location", "${Config.configData.url}/api/internal/v1/users/${user.name}")
call.respond(HttpStatusCode.Created)
}
route("/{name}") {
authenticate(TOKEN_AUTH, optional = true) {
get {
val userParameter = (
call.parameters["name"]
?: throw ParameterNotExistException(
"Parameter(name='userName@domain') does not exist."
)
)
if (userParameter.toLongOrNull() != null) {
return@get call.respond(userApiService.findById(userParameter.toLong()))
} else {
val acct = AcctUtil.parse(userParameter)
return@get call.respond(userApiService.findByAcct(acct))
}
}
}
route("/followers") {
get {
val userParameter = call.parameters["name"]
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
if (userParameter.toLongOrNull() != null) {
return@get call.respond(userApiService.findFollowers(userParameter.toLong()))
}
val acct = AcctUtil.parse(userParameter)
return@get call.respond(userApiService.findFollowersByAcct(acct))
}
authenticate(TOKEN_AUTH) {
post {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
?: throw IllegalStateException("no principal")
val userParameter = call.parameters["name"]
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
if (if (userParameter.toLongOrNull() != null) {
userApiService.follow(userParameter.toLong(), userId)
} else {
val parse = AcctUtil.parse(userParameter)
userApiService.follow(parse, userId)
}
) {
call.respond(HttpStatusCode.OK)
} else {
call.respond(HttpStatusCode.Accepted)
}
}
}
}
route("/following") {
get {
val userParameter = (
call.parameters["name"]
?: throw ParameterNotExistException(
"Parameter(name='userName@domain') does not exist."
)
)
if (userParameter.toLongOrNull() != null) {
return@get call.respond(userApiService.findFollowings(userParameter.toLong()))
}
val acct = AcctUtil.parse(userParameter)
return@get call.respond(userApiService.findFollowingsByAcct(acct))
}
}
}
}
}

View File

@ -1,18 +0,0 @@
package dev.usbharu.hideout.routing.api.mastodon.v1
// @Suppress("UnusedPrivateMember")
// fun Route.statuses(postService: IPostService) {
// // route("/statuses") {
// // post {
// // val status: StatusForPost = call.receive()
// // val post = dev.usbharu.hideout.domain.model.hideout.form.Post(
// // userId = status.userId,
// // createdAt = System.currentTimeMillis(),
// // text = status.status,
// // visibility = 1
// // )
// // postService.create(post)
// // call.respond(status)
// // }
// // }
// }

View File

@ -1,45 +0,0 @@
package dev.usbharu.hideout.routing.wellknown
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.wellknown.WebFinger
import dev.usbharu.hideout.exception.IllegalParameterException
import dev.usbharu.hideout.exception.ParameterNotExistException
import dev.usbharu.hideout.service.api.WebFingerApiService
import dev.usbharu.hideout.util.HttpUtil.Activity
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
@Deprecated("Ktor is deprecated")
fun Routing.webfinger(webFingerApiService: WebFingerApiService) {
route("/.well-known/webfinger") {
get {
val acct = call.request.queryParameters["resource"]?.decodeURLPart()
?: throw ParameterNotExistException("Parameter(name='resource') does not exist.")
if (acct.startsWith("acct:").not()) {
throw IllegalParameterException("Parameter(name='resource') is not start with 'acct:'.")
}
val accountName = acct.substringBeforeLast("@")
.substringAfter("acct:")
.trimStart('@')
val userEntity = webFingerApiService.findByNameAndDomain(accountName, Config.configData.domain)
val webFinger = WebFinger(
subject = acct,
links = listOf(
WebFinger.Link(
rel = "self",
type = ContentType.Application.Activity.toString(),
href = "${Config.configData.url}/users/${userEntity.name}"
)
)
)
return@get call.respond(webFinger)
}
}
}