mirror of https://github.com/usbharu/Hideout.git
Merge pull request #4 from usbharu/feature/refactor
refactor: 不要なファイルを削除
This commit is contained in:
commit
a23f26a399
|
@ -90,7 +90,6 @@ fun Application.parent() {
|
||||||
|
|
||||||
configureKoin(module)
|
configureKoin(module)
|
||||||
configureHTTP()
|
configureHTTP()
|
||||||
configureSockets()
|
|
||||||
configureMonitoring()
|
configureMonitoring()
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
register(inject<IUserAuthService>().value)
|
register(inject<IUserAuthService>().value)
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package dev.usbharu.hideout.plugins
|
|
||||||
|
|
||||||
import io.ktor.server.websocket.*
|
|
||||||
import io.ktor.websocket.*
|
|
||||||
import java.time.Duration
|
|
||||||
import io.ktor.server.application.*
|
|
||||||
import io.ktor.server.routing.*
|
|
||||||
|
|
||||||
fun Application.configureSockets() {
|
|
||||||
install(WebSockets) {
|
|
||||||
pingPeriod = Duration.ofSeconds(15)
|
|
||||||
timeout = Duration.ofSeconds(15)
|
|
||||||
maxFrameSize = Long.MAX_VALUE
|
|
||||||
masking = false
|
|
||||||
}
|
|
||||||
routing {
|
|
||||||
webSocket("/ws") { // websocketSession
|
|
||||||
for (frame in incoming) {
|
|
||||||
if (frame is Frame.Text) {
|
|
||||||
val text = frame.readText()
|
|
||||||
outgoing.send(Frame.Text("YOU SAID: $text"))
|
|
||||||
if (text.equals("bye", ignoreCase = true)) {
|
|
||||||
close(CloseReason(CloseReason.Codes.NORMAL, "Client said BYE"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.plugins.UserSession
|
|
||||||
import dev.usbharu.hideout.plugins.tokenAuth
|
|
||||||
import io.ktor.http.*
|
|
||||||
import io.ktor.server.application.*
|
|
||||||
import io.ktor.server.auth.*
|
|
||||||
import io.ktor.server.response.*
|
|
||||||
import io.ktor.server.routing.*
|
|
||||||
import io.ktor.server.sessions.*
|
|
||||||
|
|
||||||
fun Application.login(){
|
|
||||||
routing {
|
|
||||||
authenticate(tokenAuth) {
|
|
||||||
post("/login") {
|
|
||||||
println("aaaaaaaaaaaaaaaaaaaaa")
|
|
||||||
val principal = call.principal<UserIdPrincipal>()
|
|
||||||
// call.sessions.set(UserSession(principal!!.name))
|
|
||||||
call.respondRedirect("/users/${principal!!.name}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get("/login"){
|
|
||||||
call.respondText(contentType = ContentType.Text.Html) {
|
|
||||||
|
|
||||||
//language=HTML
|
|
||||||
"""
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>login</h2>
|
|
||||||
<form method='POST' action=''>
|
|
||||||
<input type='text' name='username' value=''>
|
|
||||||
<input type='password' name='password'>
|
|
||||||
<input type='submit'>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.User
|
|
||||||
import dev.usbharu.hideout.plugins.UserSession
|
|
||||||
import dev.usbharu.hideout.plugins.respondAp
|
|
||||||
import dev.usbharu.hideout.plugins.tokenAuth
|
|
||||||
import dev.usbharu.hideout.service.impl.ActivityPubUserService
|
|
||||||
import dev.usbharu.hideout.service.impl.UserService
|
|
||||||
import dev.usbharu.hideout.util.HttpUtil
|
|
||||||
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.*
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
fun Application.user(userService: UserService, activityPubUserService: ActivityPubUserService) {
|
|
||||||
routing {
|
|
||||||
route("/users") {
|
|
||||||
authenticate(tokenAuth, optional = true) {
|
|
||||||
|
|
||||||
get {
|
|
||||||
val limit = call.request.queryParameters["limit"]?.toInt()
|
|
||||||
val offset = call.request.queryParameters["offset"]?.toLong()
|
|
||||||
val result = userService.findAll(limit, offset)
|
|
||||||
call.respond(result)
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
val user = call.receive<User>()
|
|
||||||
userService.create(user)
|
|
||||||
call.response.header(
|
|
||||||
HttpHeaders.Location,
|
|
||||||
call.request.path() + "/${user.name}"
|
|
||||||
)
|
|
||||||
call.respond(HttpStatusCode.Created)
|
|
||||||
}
|
|
||||||
get("/{name}") {
|
|
||||||
val contentType = ContentType.parse(call.request.accept() ?: "*/*")
|
|
||||||
call.application.environment.log.debug("Accept Content-Type : ${contentType.contentType}/${contentType.contentSubtype} ${contentType.parameters}")
|
|
||||||
val typeOfActivityPub = HttpUtil.isContentTypeOfActivityPub(
|
|
||||||
contentType.contentType,
|
|
||||||
contentType.contentSubtype,
|
|
||||||
contentType.parameter("profile").orEmpty()
|
|
||||||
)
|
|
||||||
val name = call.parameters["name"]
|
|
||||||
if (typeOfActivityPub) {
|
|
||||||
println("Required Activity !!")
|
|
||||||
val userModel = activityPubUserService.generateUserModel(name!!)
|
|
||||||
return@get call.respondAp(userModel)
|
|
||||||
}
|
|
||||||
name?.let { it1 -> userService.findByName(it1).id }
|
|
||||||
?.let { it2 -> println(userService.findFollowersById(it2)) }
|
|
||||||
val principal = call.principal<UserIdPrincipal>()
|
|
||||||
if (principal != null && name != null) {
|
|
||||||
// iUserService.findByName(name)
|
|
||||||
if (principal.name == name) {
|
|
||||||
call.respondText {
|
|
||||||
principal.name
|
|
||||||
}
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
call.respondText {
|
|
||||||
"hello $name !!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
get("/{name}/icon.png"){
|
|
||||||
call.respondBytes(String.javaClass.classLoader.getResourceAsStream("icon.png").readAllBytes(),ContentType.Image.PNG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
authenticate(tokenAuth) {
|
|
||||||
get("/admin") {
|
|
||||||
println("cccccccccccc " + call.principal<UserIdPrincipal>())
|
|
||||||
println("cccccccccccc " + call.principal<UserSession>())
|
|
||||||
|
|
||||||
return@get call.respondText {
|
|
||||||
"you alredy in admin !! hello " +
|
|
||||||
call.principal<UserIdPrincipal>()?.name.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.config.Config
|
|
||||||
import dev.usbharu.hideout.service.impl.UserService
|
|
||||||
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.*
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import org.intellij.lang.annotations.Language
|
|
||||||
|
|
||||||
fun Application.wellKnown(userService: UserService) {
|
|
||||||
routing {
|
|
||||||
route("/.well-known") {
|
|
||||||
get("/host-meta") {
|
|
||||||
//language=XML
|
|
||||||
val xml = """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" type="application/xrd+xml" template="${Config.configData.url}/.well-known/webfinger?resource={uri}"/></XRD>
|
|
||||||
""".trimIndent()
|
|
||||||
return@get call.respondText(
|
|
||||||
contentType = ContentType("application", "xrd+xml"),
|
|
||||||
status = HttpStatusCode.OK,
|
|
||||||
text = xml
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
get("/host-meta.json") {
|
|
||||||
@Language("JSON") val json = """
|
|
||||||
{
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"rel": "lrdd",
|
|
||||||
"type": "application/jrd+json",
|
|
||||||
"template": "${Config.configData.url}/.well-known/webfinger?resource={uri}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
return@get call.respondText(
|
|
||||||
contentType = ContentType("application", "xrd+json"),
|
|
||||||
status = HttpStatusCode.OK,
|
|
||||||
text = json
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
get("/webfinger") {
|
|
||||||
val uri = call.request.queryParameters["resource"] ?: return@get call.respondText(
|
|
||||||
"resource was not found",
|
|
||||||
status = HttpStatusCode.BadRequest
|
|
||||||
)
|
|
||||||
val decodeURLPart = uri.decodeURLPart()
|
|
||||||
if (!decodeURLPart.startsWith("acct:")) {
|
|
||||||
return@get call.respondText(
|
|
||||||
"$uri was not found.",
|
|
||||||
status = HttpStatusCode.BadRequest
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val accountName =
|
|
||||||
uri.substringBeforeLast("@").substringAfter("acct:").trimStart('@')
|
|
||||||
val userEntity = userService.findByName(accountName)
|
|
||||||
|
|
||||||
return@get call.respond(
|
|
||||||
WebFingerResource(
|
|
||||||
subject = decodeURLPart,
|
|
||||||
listOf(
|
|
||||||
WebFingerResource.Link(
|
|
||||||
rel = "self",
|
|
||||||
type = ContentType.Application.Activity.toString(),
|
|
||||||
href = "${Config.configData.url}/users/${userEntity.name}"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class WebFingerResource(val subject: String, val links: List<Link>) {
|
|
||||||
@Serializable
|
|
||||||
data class Link(val rel: String, val type: String, val href: String)
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
package dev.usbharu.hideout.service
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.ap.Person
|
|
||||||
import dev.usbharu.hideout.domain.model.UserEntity
|
|
||||||
import dev.usbharu.hideout.webfinger.WebFinger
|
|
||||||
|
|
||||||
interface IWebFingerService {
|
|
||||||
suspend fun fetch(acct:String): WebFinger?
|
|
||||||
|
|
||||||
suspend fun sync(webFinger: WebFinger):UserEntity
|
|
||||||
|
|
||||||
suspend fun fetchAndSync(acct: String):UserEntity{
|
|
||||||
val webFinger = fetch(acct)?: throw IllegalArgumentException()
|
|
||||||
return sync(webFinger)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun fetchUserModel(actor: String): Person?
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.impl
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.config.Config
|
|
||||||
|
|
||||||
class ActivityPubService() {
|
|
||||||
|
|
||||||
enum class ActivityType{
|
|
||||||
Follow,
|
|
||||||
Undo
|
|
||||||
}
|
|
||||||
|
|
||||||
fun switchApType(json:String): ActivityType {
|
|
||||||
val typeAsText = Config.configData.objectMapper.readTree(json).get("type").asText()
|
|
||||||
return when(typeAsText){
|
|
||||||
"Follow" -> ActivityType.Follow
|
|
||||||
"Undo" -> ActivityType.Undo
|
|
||||||
else -> ActivityType.Undo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.impl
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.ap.*
|
|
||||||
import dev.usbharu.hideout.config.Config
|
|
||||||
import dev.usbharu.hideout.plugins.postAp
|
|
||||||
import dev.usbharu.hideout.service.IUserAuthService
|
|
||||||
import dev.usbharu.hideout.service.IWebFingerService
|
|
||||||
import io.ktor.client.*
|
|
||||||
|
|
||||||
class ActivityPubUserService(
|
|
||||||
private val httpClient: HttpClient,
|
|
||||||
private val userService: UserService,
|
|
||||||
private val userAuthService: IUserAuthService,
|
|
||||||
private val webFingerService: IWebFingerService
|
|
||||||
) {
|
|
||||||
suspend fun generateUserModel(name: String): Person {
|
|
||||||
val userEntity = userService.findByName(name)
|
|
||||||
val userAuthEntity = userAuthService.findByUserId(userEntity.id)
|
|
||||||
val userUrl = "${Config.configData.url}/users/$name"
|
|
||||||
return Person(
|
|
||||||
type = emptyList(),
|
|
||||||
name = userEntity.name,
|
|
||||||
id = userUrl,
|
|
||||||
preferredUsername = name,
|
|
||||||
summary = userEntity.description,
|
|
||||||
inbox = "$userUrl/inbox",
|
|
||||||
outbox = "$userUrl/outbox",
|
|
||||||
url = userUrl,
|
|
||||||
icon = Image(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "$userUrl/icon.png",
|
|
||||||
mediaType = "image/png",
|
|
||||||
url = "$userUrl/icon.png"
|
|
||||||
),
|
|
||||||
publicKey = Key(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "Public Key",
|
|
||||||
id = "$userUrl#pubkey",
|
|
||||||
owner = userUrl,
|
|
||||||
publicKeyPem = userAuthEntity.publicKey
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun receiveFollow(follow: Follow) {
|
|
||||||
val actor = follow.actor ?: throw IllegalArgumentException("actor is null")
|
|
||||||
val person = webFingerService.fetchUserModel(actor) ?: throw IllegalArgumentException("actor is not found")
|
|
||||||
val inboxUrl = person.inbox ?: throw IllegalArgumentException("inbox is not found")
|
|
||||||
httpClient.postAp(
|
|
||||||
inboxUrl, "${follow.`object`!!}#pubkey", Accept(
|
|
||||||
name = "Follow",
|
|
||||||
`object` = follow,
|
|
||||||
actor = follow.`object`.orEmpty()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.impl
|
|
||||||
|
|
||||||
import java.security.PrivateKey
|
|
||||||
|
|
||||||
class HttpSignService {
|
|
||||||
suspend fun sign(){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.impl
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.ap.Person
|
|
||||||
import dev.usbharu.hideout.domain.model.User
|
|
||||||
import dev.usbharu.hideout.domain.model.UserEntity
|
|
||||||
import dev.usbharu.hideout.service.IWebFingerService
|
|
||||||
import dev.usbharu.hideout.util.HttpUtil
|
|
||||||
import dev.usbharu.hideout.webfinger.WebFinger
|
|
||||||
import io.ktor.client.*
|
|
||||||
import io.ktor.client.call.*
|
|
||||||
import io.ktor.client.plugins.*
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
|
|
||||||
class WebFingerService(
|
|
||||||
private val httpClient: HttpClient,
|
|
||||||
private val userService: UserService
|
|
||||||
) : IWebFingerService {
|
|
||||||
override suspend fun fetch(acct: String): WebFinger? {
|
|
||||||
|
|
||||||
val fullName = acct.substringAfter("acct:")
|
|
||||||
val domain = fullName.substringAfterLast("@")
|
|
||||||
|
|
||||||
return try {
|
|
||||||
httpClient.get("https://$domain/.well-known/webfinger?resource=acct:$fullName")
|
|
||||||
.body<WebFinger>()
|
|
||||||
} catch (e: ResponseException) {
|
|
||||||
if (e.response.status == HttpStatusCode.NotFound) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun fetchUserModel(url: String): Person? {
|
|
||||||
return try {
|
|
||||||
httpClient.get(url) {
|
|
||||||
header("Accept", "application/activity+json")
|
|
||||||
}.body<Person>()
|
|
||||||
} catch (e: ResponseException) {
|
|
||||||
if (e.response.status == HttpStatusCode.NotFound) {
|
|
||||||
e.printStackTrace()
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun sync(webFinger: WebFinger): UserEntity {
|
|
||||||
|
|
||||||
val link = webFinger.links.find {
|
|
||||||
it.rel == "self" && HttpUtil.isContentTypeOfActivityPub(
|
|
||||||
ContentType.parse(
|
|
||||||
it.type.orEmpty()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}?.href ?: throw Exception()
|
|
||||||
|
|
||||||
val fullName = webFinger.subject.substringAfter("acct:")
|
|
||||||
val domain = fullName.substringAfterLast("@")
|
|
||||||
val userName = fullName.substringBeforeLast("@")
|
|
||||||
|
|
||||||
val userModel = fetchUserModel(link) ?: throw Exception()
|
|
||||||
|
|
||||||
val user = User(
|
|
||||||
userModel.preferredUsername ?: throw IllegalStateException(),
|
|
||||||
domain,
|
|
||||||
userName,
|
|
||||||
userModel.summary.orEmpty(),
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
TODO()
|
|
||||||
return userService.create(user)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
package dev.usbharu.hideout.webfinger
|
|
||||||
|
|
||||||
class WebFinger(val subject: String, val aliases: List<String>, val links: List<Link>) {
|
|
||||||
class Link(val rel: String, val type: String?, val href: String?, val template: String)
|
|
||||||
}
|
|
Loading…
Reference in New Issue