mirror of https://github.com/usbharu/Hideout.git
Merge branch 'develop' into feature/deliver-reaction
# Conflicts: # package-lock.json # package.json # src/main/kotlin/dev/usbharu/hideout/Application.kt # src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt # src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
This commit is contained in:
commit
10ea1bf51b
|
@ -80,12 +80,14 @@ dependencies {
|
||||||
implementation("org.xerial:sqlite-jdbc:3.40.1.0")
|
implementation("org.xerial:sqlite-jdbc:3.40.1.0")
|
||||||
implementation("io.ktor:ktor-server-websockets-jvm:$ktor_version")
|
implementation("io.ktor:ktor-server-websockets-jvm:$ktor_version")
|
||||||
implementation("io.ktor:ktor-server-cio-jvm:$ktor_version")
|
implementation("io.ktor:ktor-server-cio-jvm:$ktor_version")
|
||||||
|
implementation("io.ktor:ktor-server-compression:$ktor_version")
|
||||||
implementation("ch.qos.logback:logback-classic:$logback_version")
|
implementation("ch.qos.logback:logback-classic:$logback_version")
|
||||||
|
|
||||||
implementation("io.insert-koin:koin-core:$koin_version")
|
implementation("io.insert-koin:koin-core:$koin_version")
|
||||||
implementation("io.insert-koin:koin-ktor:$koin_version")
|
implementation("io.insert-koin:koin-ktor:$koin_version")
|
||||||
implementation("io.insert-koin:koin-logger-slf4j:$koin_version")
|
implementation("io.insert-koin:koin-logger-slf4j:$koin_version")
|
||||||
implementation("io.insert-koin:koin-annotations:1.2.0")
|
implementation("io.insert-koin:koin-annotations:1.2.0")
|
||||||
|
implementation("io.ktor:ktor-server-compression-jvm:2.3.0")
|
||||||
ksp("io.insert-koin:koin-ksp-compiler:1.2.0")
|
ksp("io.insert-koin:koin-ksp-compiler:1.2.0")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
|
||||||
|
"spaces": 2,
|
||||||
|
"generator-cli": {
|
||||||
|
"version": "6.6.0",
|
||||||
|
"generators": {
|
||||||
|
"v3.0": {
|
||||||
|
"generatorName": "typescript-fetch",
|
||||||
|
"output": "src/main/web/generated",
|
||||||
|
"glob": "src/main/resources/openapi/api.yaml",
|
||||||
|
"additionalProperties": {
|
||||||
|
"modelPropertyNaming": "camelCase",
|
||||||
|
"supportsES6": true,
|
||||||
|
"withInterfaces": true,
|
||||||
|
"typescriptThreePlus": true,
|
||||||
|
"useSingleRequestParameter": false,
|
||||||
|
"prependFormOrBodyParameters": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
package.json
16
package.json
|
@ -2,18 +2,26 @@
|
||||||
"name": "hideout",
|
"name": "hideout",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"solid-js": "^1.7.3"
|
"@solid-primitives/context": "^0.2.1",
|
||||||
|
"@solid-primitives/storage": "^1.3.11",
|
||||||
|
"@solidjs/router": "^0.8.2",
|
||||||
|
"@suid/icons-material": "^0.6.3",
|
||||||
|
"@suid/material": "^0.12.3",
|
||||||
|
"solid-js": "^1.7.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@openapitools/openapi-generator-cli": "^2.6.0",
|
||||||
|
"@suid/vite-plugin": "^0.1.3",
|
||||||
|
"rollup-plugin-visualizer": "^5.9.2",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"vite": "4.2.3",
|
"vite": "4.2.3",
|
||||||
"vite-plugin-solid": "^2.7.0",
|
"vite-plugin-solid": "^2.7.0"
|
||||||
"@suid/vite-plugin": "^0.1.3"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"serve": "vite preview"
|
"serve": "vite preview",
|
||||||
|
"gen-api": "openapi-generator-cli generate"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,7 @@ fun Application.parent() {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
inject<IServerInitialiseService>().value.init()
|
inject<IServerInitialiseService>().value.init()
|
||||||
}
|
}
|
||||||
|
configureCompression()
|
||||||
configureHTTP()
|
configureHTTP()
|
||||||
configureStaticRouting()
|
configureStaticRouting()
|
||||||
configureMonitoring()
|
configureMonitoring()
|
||||||
|
@ -117,7 +118,11 @@ fun Application.parent() {
|
||||||
activityPubUserService = inject<ActivityPubUserService>().value,
|
activityPubUserService = inject<ActivityPubUserService>().value,
|
||||||
postService = inject<IPostApiService>().value,
|
postService = inject<IPostApiService>().value,
|
||||||
userApiService = inject<IUserApiService>().value,
|
userApiService = inject<IUserApiService>().value,
|
||||||
reactionService = inject<IReactionService>().value
|
reactionService = inject<IReactionService>().value,
|
||||||
|
userAuthService = inject<IUserAuthService>().value,
|
||||||
|
userRepository = inject<IUserRepository>().value,
|
||||||
|
jwtService = inject<IJwtService>().value,
|
||||||
|
metaService = inject<IMetaService>().value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ open class Note : Object {
|
||||||
var inReplyTo: String? = null
|
var inReplyTo: String? = null
|
||||||
|
|
||||||
protected constructor() : super()
|
protected constructor() : super()
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
constructor(
|
constructor(
|
||||||
type: List<String> = emptyList(),
|
type: List<String> = emptyList(),
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package dev.usbharu.hideout.domain.model.hideout.dto
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||||
|
|
||||||
|
data class PostResponse(
|
||||||
|
val id: Long,
|
||||||
|
val user: UserResponse,
|
||||||
|
val overview: String? = null,
|
||||||
|
val text: String? = null,
|
||||||
|
val createdAt: Long,
|
||||||
|
val visibility: Visibility,
|
||||||
|
val url: String,
|
||||||
|
val sensitive: Boolean = false,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun from(post: Post, user: User): PostResponse {
|
||||||
|
return PostResponse(
|
||||||
|
id = post.id,
|
||||||
|
user = UserResponse.from(user),
|
||||||
|
overview = post.overview,
|
||||||
|
text = post.text,
|
||||||
|
createdAt = post.createdAt,
|
||||||
|
visibility = post.visibility,
|
||||||
|
url = post.url,
|
||||||
|
sensitive = post.sensitive
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package dev.usbharu.hideout.plugins
|
||||||
|
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.plugins.compression.*
|
||||||
|
|
||||||
|
fun Application.configureCompression() {
|
||||||
|
install(Compression) {
|
||||||
|
gzip {
|
||||||
|
matchContentType(ContentType.Application.JavaScript)
|
||||||
|
priority = 1.0
|
||||||
|
}
|
||||||
|
deflate {
|
||||||
|
matchContentType(ContentType.Application.JavaScript)
|
||||||
|
priority = 10.0
|
||||||
|
minimumSize(1024) // condition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
package dev.usbharu.hideout.plugins
|
package dev.usbharu.hideout.plugins
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.repository.IUserRepository
|
||||||
import dev.usbharu.hideout.routing.activitypub.inbox
|
import dev.usbharu.hideout.routing.activitypub.inbox
|
||||||
import dev.usbharu.hideout.routing.activitypub.outbox
|
import dev.usbharu.hideout.routing.activitypub.outbox
|
||||||
import dev.usbharu.hideout.routing.activitypub.usersAP
|
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.posts
|
||||||
import dev.usbharu.hideout.routing.api.internal.v1.users
|
import dev.usbharu.hideout.routing.api.internal.v1.users
|
||||||
import dev.usbharu.hideout.routing.wellknown.webfinger
|
import dev.usbharu.hideout.routing.wellknown.webfinger
|
||||||
|
@ -12,6 +14,9 @@ import dev.usbharu.hideout.service.api.IPostApiService
|
||||||
import dev.usbharu.hideout.service.api.IUserApiService
|
import dev.usbharu.hideout.service.api.IUserApiService
|
||||||
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
||||||
import dev.usbharu.hideout.service.reaction.IReactionService
|
import dev.usbharu.hideout.service.reaction.IReactionService
|
||||||
|
import dev.usbharu.hideout.service.auth.IJwtService
|
||||||
|
import dev.usbharu.hideout.service.core.IMetaService
|
||||||
|
import dev.usbharu.hideout.service.user.IUserAuthService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.IUserService
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.server.plugins.autohead.*
|
import io.ktor.server.plugins.autohead.*
|
||||||
|
@ -25,7 +30,11 @@ fun Application.configureRouting(
|
||||||
activityPubUserService: ActivityPubUserService,
|
activityPubUserService: ActivityPubUserService,
|
||||||
postService: IPostApiService,
|
postService: IPostApiService,
|
||||||
userApiService: IUserApiService,
|
userApiService: IUserApiService,
|
||||||
reactionService: IReactionService
|
reactionService: IReactionService,
|
||||||
|
userAuthService: IUserAuthService,
|
||||||
|
userRepository: IUserRepository,
|
||||||
|
jwtService: IJwtService,
|
||||||
|
metaService: IMetaService
|
||||||
) {
|
) {
|
||||||
install(AutoHeadResponse)
|
install(AutoHeadResponse)
|
||||||
routing {
|
routing {
|
||||||
|
@ -36,6 +45,7 @@ fun Application.configureRouting(
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, reactionService)
|
posts(postService, reactionService)
|
||||||
users(userService, userApiService)
|
users(userService, userApiService)
|
||||||
|
auth(userAuthService, userRepository, jwtService)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,12 @@ package dev.usbharu.hideout.plugins
|
||||||
|
|
||||||
import com.auth0.jwk.JwkProvider
|
import com.auth0.jwk.JwkProvider
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
|
|
||||||
import dev.usbharu.hideout.exception.UserNotFoundException
|
|
||||||
import dev.usbharu.hideout.repository.IUserRepository
|
|
||||||
import dev.usbharu.hideout.service.auth.IJwtService
|
|
||||||
import dev.usbharu.hideout.service.core.IMetaService
|
import dev.usbharu.hideout.service.core.IMetaService
|
||||||
import dev.usbharu.hideout.service.user.IUserAuthService
|
|
||||||
import dev.usbharu.hideout.util.JsonWebKeyUtil
|
import dev.usbharu.hideout.util.JsonWebKeyUtil
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.server.auth.*
|
import io.ktor.server.auth.*
|
||||||
import io.ktor.server.auth.jwt.*
|
import io.ktor.server.auth.jwt.*
|
||||||
import io.ktor.server.request.*
|
|
||||||
import io.ktor.server.response.*
|
import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
|
@ -22,11 +15,8 @@ const val TOKEN_AUTH = "jwt-auth"
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
fun Application.configureSecurity(
|
fun Application.configureSecurity(
|
||||||
userAuthService: IUserAuthService,
|
jwkProvider: JwkProvider,
|
||||||
metaService: IMetaService,
|
metaService: IMetaService
|
||||||
userRepository: IUserRepository,
|
|
||||||
jwtService: IJwtService,
|
|
||||||
jwkProvider: JwkProvider
|
|
||||||
) {
|
) {
|
||||||
val issuer = Config.configData.url
|
val issuer = Config.configData.url
|
||||||
install(Authentication) {
|
install(Authentication) {
|
||||||
|
@ -48,24 +38,6 @@ fun Application.configureSecurity(
|
||||||
}
|
}
|
||||||
|
|
||||||
routing {
|
routing {
|
||||||
post("/login") {
|
|
||||||
val loginUser = call.receive<UserLogin>()
|
|
||||||
val check = userAuthService.verifyAccount(loginUser.username, loginUser.password)
|
|
||||||
if (check.not()) {
|
|
||||||
return@post call.respond(HttpStatusCode.Unauthorized)
|
|
||||||
}
|
|
||||||
|
|
||||||
val user = userRepository.findByNameAndDomain(loginUser.username, Config.configData.domain)
|
|
||||||
?: throw UserNotFoundException("${loginUser.username} was not found.")
|
|
||||||
|
|
||||||
return@post call.respond(jwtService.createToken(user))
|
|
||||||
}
|
|
||||||
|
|
||||||
post("/refresh-token") {
|
|
||||||
val refreshToken = call.receive<RefreshToken>()
|
|
||||||
return@post call.respond(jwtService.refreshToken(refreshToken))
|
|
||||||
}
|
|
||||||
|
|
||||||
get("/.well-known/jwks.json") {
|
get("/.well-known/jwks.json") {
|
||||||
//language=JSON
|
//language=JSON
|
||||||
val jwt = metaService.getJwtMeta()
|
val jwt = metaService.getJwtMeta()
|
||||||
|
@ -74,12 +46,5 @@ fun Application.configureSecurity(
|
||||||
text = JsonWebKeyUtil.publicKeyToJwk(jwt.publicKey, jwt.kid.toString())
|
text = JsonWebKeyUtil.publicKeyToJwk(jwt.publicKey, jwt.kid.toString())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,9 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> {
|
): List<Post> {
|
||||||
TODO("Not yet implemented")
|
return query {
|
||||||
|
Posts.select { Posts.visibility eq Visibility.PUBLIC.ordinal }.map { it.toPost() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun findByUserNameAndDomain(
|
override suspend fun findByUserNameAndDomain(
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package dev.usbharu.hideout.routing.api.internal.v1
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
|
||||||
|
import dev.usbharu.hideout.exception.UserNotFoundException
|
||||||
|
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||||
|
import dev.usbharu.hideout.repository.IUserRepository
|
||||||
|
import dev.usbharu.hideout.service.auth.IJwtService
|
||||||
|
import dev.usbharu.hideout.service.user.IUserAuthService
|
||||||
|
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.*
|
||||||
|
|
||||||
|
fun Route.auth(
|
||||||
|
userAuthService: IUserAuthService,
|
||||||
|
userRepository: IUserRepository,
|
||||||
|
jwtService: IJwtService
|
||||||
|
) {
|
||||||
|
post("/login") {
|
||||||
|
val loginUser = call.receive<UserLogin>()
|
||||||
|
val check = userAuthService.verifyAccount(loginUser.username, loginUser.password)
|
||||||
|
if (check.not()) {
|
||||||
|
return@post call.respond(HttpStatusCode.Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
val user = userRepository.findByNameAndDomain(loginUser.username, Config.configData.domain)
|
||||||
|
?: throw UserNotFoundException("${loginUser.username} was not found.")
|
||||||
|
|
||||||
|
return@post call.respond(jwtService.createToken(user))
|
||||||
|
}
|
||||||
|
|
||||||
|
post("/refresh-token") {
|
||||||
|
val refreshToken = call.receive<RefreshToken>()
|
||||||
|
return@post call.respond(jwtService.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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package dev.usbharu.hideout.service.api
|
package dev.usbharu.hideout.service.api
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostResponse
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
interface IPostApiService {
|
interface IPostApiService {
|
||||||
suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): Post
|
suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): PostResponse
|
||||||
suspend fun getById(id: Long, userId: Long?): Post
|
suspend fun getById(id: Long, userId: Long?): PostResponse
|
||||||
suspend fun getAll(
|
suspend fun getAll(
|
||||||
since: Instant? = null,
|
since: Instant? = null,
|
||||||
until: Instant? = null,
|
until: Instant? = null,
|
||||||
|
@ -14,7 +14,7 @@ interface IPostApiService {
|
||||||
maxId: Long? = null,
|
maxId: Long? = null,
|
||||||
limit: Int? = null,
|
limit: Int? = null,
|
||||||
userId: Long? = null
|
userId: Long? = null
|
||||||
): List<Post>
|
): List<PostResponse>
|
||||||
|
|
||||||
suspend fun getByUser(
|
suspend fun getByUser(
|
||||||
nameOrId: String,
|
nameOrId: String,
|
||||||
|
@ -24,5 +24,5 @@ interface IPostApiService {
|
||||||
maxId: Long? = null,
|
maxId: Long? = null,
|
||||||
limit: Int? = null,
|
limit: Int? = null,
|
||||||
userId: Long? = null
|
userId: Long? = null
|
||||||
): List<Post>
|
): List<PostResponse>
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,16 @@ package dev.usbharu.hideout.service.api
|
||||||
|
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostResponse
|
||||||
import dev.usbharu.hideout.exception.PostNotFoundException
|
import dev.usbharu.hideout.repository.*
|
||||||
import dev.usbharu.hideout.repository.IPostRepository
|
|
||||||
import dev.usbharu.hideout.service.post.IPostService
|
import dev.usbharu.hideout.service.post.IPostService
|
||||||
import dev.usbharu.hideout.util.AcctUtil
|
import dev.usbharu.hideout.util.AcctUtil
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.innerJoin
|
||||||
|
import org.jetbrains.exposed.sql.select
|
||||||
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
|
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.Post as FormPost
|
import dev.usbharu.hideout.domain.model.hideout.form.Post as FormPost
|
||||||
|
@ -14,10 +19,11 @@ import dev.usbharu.hideout.domain.model.hideout.form.Post as FormPost
|
||||||
@Single
|
@Single
|
||||||
class PostApiServiceImpl(
|
class PostApiServiceImpl(
|
||||||
private val postService: IPostService,
|
private val postService: IPostService,
|
||||||
private val postRepository: IPostRepository
|
private val postRepository: IPostRepository,
|
||||||
|
private val userRepository: IUserRepository
|
||||||
) : IPostApiService {
|
) : IPostApiService {
|
||||||
override suspend fun createPost(postForm: FormPost, userId: Long): Post {
|
override suspend fun createPost(postForm: FormPost, userId: Long): PostResponse {
|
||||||
return postService.createLocal(
|
val createdPost = postService.createLocal(
|
||||||
PostCreateDto(
|
PostCreateDto(
|
||||||
text = postForm.text,
|
text = postForm.text,
|
||||||
overview = postForm.overview,
|
overview = postForm.overview,
|
||||||
|
@ -27,11 +33,20 @@ class PostApiServiceImpl(
|
||||||
userId = userId
|
userId = userId
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
val creator = userRepository.findById(userId)
|
||||||
|
return PostResponse.from(createdPost, creator!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getById(id: Long, userId: Long?): Post {
|
@Suppress("InjectDispatcher")
|
||||||
return postRepository.findOneById(id, userId)
|
suspend fun <T> query(block: suspend () -> T): T =
|
||||||
?: throw PostNotFoundException("$id was not found or is not authorized.")
|
newSuspendedTransaction(Dispatchers.IO) { block() }
|
||||||
|
|
||||||
|
override suspend fun getById(id: Long, userId: Long?): PostResponse {
|
||||||
|
val query = query {
|
||||||
|
Posts.innerJoin(Users, onColumn = { Posts.userId }, otherColumn = { Users.id }).select { Posts.id eq id }
|
||||||
|
.single()
|
||||||
|
}
|
||||||
|
return PostResponse.from(query.toPost(), query.toUser())
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getAll(
|
override suspend fun getAll(
|
||||||
|
@ -41,7 +56,12 @@ class PostApiServiceImpl(
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> = postRepository.findAll(since, until, minId, maxId, limit, userId)
|
): List<PostResponse> {
|
||||||
|
return query {
|
||||||
|
Posts.innerJoin(Users, onColumn = { Posts.userId }, otherColumn = { id }).selectAll()
|
||||||
|
.map { PostResponse.from(it.toPost(), it.toUser()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getByUser(
|
override suspend fun getByUser(
|
||||||
nameOrId: String,
|
nameOrId: String,
|
||||||
|
@ -51,23 +71,22 @@ class PostApiServiceImpl(
|
||||||
maxId: Long?,
|
maxId: Long?,
|
||||||
limit: Int?,
|
limit: Int?,
|
||||||
userId: Long?
|
userId: Long?
|
||||||
): List<Post> {
|
): List<PostResponse> {
|
||||||
val idOrNull = nameOrId.toLongOrNull()
|
val idOrNull = nameOrId.toLongOrNull()
|
||||||
return if (idOrNull == null) {
|
return if (idOrNull == null) {
|
||||||
val acct = AcctUtil.parse(nameOrId)
|
val acct = AcctUtil.parse(nameOrId)
|
||||||
postRepository.findByUserNameAndDomain(
|
query {
|
||||||
username = acct.username,
|
Posts.innerJoin(Users, onColumn = { Posts.userId }, otherColumn = { id }).select {
|
||||||
s = acct.domain
|
Users.name.eq(acct.username)
|
||||||
?: Config.configData.domain,
|
.and(Users.domain eq (acct.domain ?: Config.configData.domain))
|
||||||
since = since,
|
}.map { PostResponse.from(it.toPost(), it.toUser()) }
|
||||||
until = until,
|
}
|
||||||
minId = minId,
|
|
||||||
maxId = maxId,
|
|
||||||
limit = limit,
|
|
||||||
userId = userId
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
postRepository.findByUserId(idOrNull, since, until, minId, maxId, limit, userId)
|
query {
|
||||||
|
Posts.innerJoin(Users, onColumn = { Posts.userId }, otherColumn = { id }).select {
|
||||||
|
Posts.userId eq idOrNull
|
||||||
|
}.map { PostResponse.from(it.toPost(), it.toUser()) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ class ExposedJobRepository(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("SuspendFunWithFlowReturnType")
|
||||||
override suspend fun findNext(names: Set<String>, status: Set<JobStatus>, limit: Int): Flow<ScheduledJob> {
|
override suspend fun findNext(names: Set<String>, status: Set<JobStatus>, limit: Int): Flow<ScheduledJob> {
|
||||||
return query {
|
return query {
|
||||||
jobs.select(
|
jobs.select(
|
||||||
|
|
|
@ -20,7 +20,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/Post"
|
$ref: "#/components/schemas/PostResponse"
|
||||||
401:
|
401:
|
||||||
$ref: "#/components/responses/Unauthorized"
|
$ref: "#/components/responses/Unauthorized"
|
||||||
403:
|
403:
|
||||||
|
@ -37,7 +37,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Post"
|
$ref: "#/components/schemas/PostRequest"
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: 成功
|
description: 成功
|
||||||
|
@ -65,7 +65,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Post"
|
$ref: "#/components/schemas/PostResponse"
|
||||||
401:
|
401:
|
||||||
$ref: "#/components/responses/Unauthorized"
|
$ref: "#/components/responses/Unauthorized"
|
||||||
403:
|
403:
|
||||||
|
@ -90,7 +90,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/Post"
|
$ref: "#/components/schemas/PostResponse"
|
||||||
401:
|
401:
|
||||||
$ref: "#/components/responses/Unauthorized"
|
$ref: "#/components/responses/Unauthorized"
|
||||||
403:
|
403:
|
||||||
|
@ -114,7 +114,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Post"
|
$ref: "#/components/schemas/PostResponse"
|
||||||
401:
|
401:
|
||||||
$ref: "#/components/responses/Unauthorized"
|
$ref: "#/components/responses/Unauthorized"
|
||||||
403:
|
403:
|
||||||
|
@ -137,7 +137,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/User"
|
$ref: "#/components/schemas/UserResponse"
|
||||||
|
|
||||||
post:
|
post:
|
||||||
summary: ユーザーを作成する
|
summary: ユーザーを作成する
|
||||||
|
@ -181,7 +181,7 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/User"
|
$ref: "#/components/schemas/UserResponse"
|
||||||
404:
|
404:
|
||||||
$ref: "#/components/responses/NotFound"
|
$ref: "#/components/responses/NotFound"
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/User"
|
$ref: "#/components/schemas/UserResponse"
|
||||||
post:
|
post:
|
||||||
summary: ユーザーをフォローする
|
summary: ユーザーをフォローする
|
||||||
security:
|
security:
|
||||||
|
@ -228,7 +228,47 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/User"
|
$ref: "#/components/schemas/UserResponse"
|
||||||
|
|
||||||
|
/login:
|
||||||
|
post:
|
||||||
|
summary: ログインする
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/UserLogin"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: ログイン成功
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/JwtToken"
|
||||||
|
|
||||||
|
/refresh-token:
|
||||||
|
post:
|
||||||
|
summary: 期限切れトークンの再発行をする
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: トークンの再発行に成功
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/JwtToken"
|
||||||
|
|
||||||
|
/auth-check:
|
||||||
|
get:
|
||||||
|
summary: 認証チェック
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: 認証に成功
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
|
||||||
components:
|
components:
|
||||||
responses:
|
responses:
|
||||||
|
@ -261,8 +301,23 @@ components:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
schemas:
|
schemas:
|
||||||
User:
|
Visibility:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- public
|
||||||
|
- unlisted
|
||||||
|
- followers
|
||||||
|
- direct
|
||||||
|
UserResponse:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- domain
|
||||||
|
- screenName
|
||||||
|
- description
|
||||||
|
- url
|
||||||
|
- createdAt
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: number
|
type: number
|
||||||
|
@ -277,23 +332,30 @@ components:
|
||||||
type: string
|
type: string
|
||||||
description:
|
description:
|
||||||
type: string
|
type: string
|
||||||
|
nullable: true
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
readOnly: true
|
readOnly: true
|
||||||
createdAt:
|
createdAt:
|
||||||
type: number
|
type: number
|
||||||
readOnly: true
|
readOnly: true
|
||||||
Post:
|
PostResponse:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- user
|
||||||
|
- text
|
||||||
|
- createdAt
|
||||||
|
- visibility
|
||||||
|
- url
|
||||||
|
- sensitive
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
readOnly: true
|
readOnly: true
|
||||||
userId:
|
user:
|
||||||
type: integer
|
$ref: "#/components/schemas/UserResponse"
|
||||||
format: int64
|
|
||||||
readOnly: true
|
|
||||||
overview:
|
overview:
|
||||||
type: string
|
type: string
|
||||||
text:
|
text:
|
||||||
|
@ -303,12 +365,7 @@ components:
|
||||||
format: int64
|
format: int64
|
||||||
readOnly: true
|
readOnly: true
|
||||||
visibility:
|
visibility:
|
||||||
type: string
|
$ref: "#/components/schemas/Visibility"
|
||||||
enum:
|
|
||||||
- public
|
|
||||||
- unlisted
|
|
||||||
- followers
|
|
||||||
- direct
|
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: uri
|
||||||
|
@ -323,13 +380,49 @@ components:
|
||||||
readOnly: true
|
readOnly: true
|
||||||
sensitive:
|
sensitive:
|
||||||
type: boolean
|
type: boolean
|
||||||
apId:
|
|
||||||
type: string
|
|
||||||
format: url
|
|
||||||
readOnly: true
|
|
||||||
|
|
||||||
|
PostRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
overview:
|
||||||
|
type: string
|
||||||
|
text:
|
||||||
|
type: string
|
||||||
|
visibility:
|
||||||
|
$ref: "#/components/schemas/Visibility"
|
||||||
|
repostId:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
replyId:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
sensitive:
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
JwtToken:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
token:
|
||||||
|
type: string
|
||||||
|
refreshToken:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
RefreshToken:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
refreshToken:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
UserLogin:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
BearerAuth:
|
BearerAuth:
|
||||||
type: http
|
type: http
|
||||||
scheme: bearer
|
scheme: bearer
|
||||||
|
bearerFormat: JWT
|
||||||
|
|
|
@ -1,58 +1,44 @@
|
||||||
import {Component, createSignal} from "solid-js";
|
import {Component, createEffect, createSignal} from "solid-js";
|
||||||
|
import {Route, Router, Routes} from "@solidjs/router";
|
||||||
|
import {TopPage} from "./pages/TopPage";
|
||||||
|
import {createTheme, CssBaseline, ThemeProvider, useMediaQuery} from "@suid/material";
|
||||||
|
import {createCookieStorage} from "@solid-primitives/storage";
|
||||||
|
import {ApiProvider} from "./lib/ApiProvider";
|
||||||
|
import {Configuration, DefaultApi} from "./generated";
|
||||||
|
import {LoginPage} from "./pages/LoginPage";
|
||||||
|
|
||||||
export const App: Component = () => {
|
export const App: Component = () => {
|
||||||
|
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
||||||
|
const [cookie, setCookie] = createCookieStorage()
|
||||||
|
const [api, setApi] = createSignal(new DefaultApi(new Configuration({
|
||||||
|
basePath: window.location.origin + "/api/internal/v1",
|
||||||
|
accessToken: cookie.token as string
|
||||||
|
})))
|
||||||
|
|
||||||
const fn = (form: HTMLButtonElement) => {
|
createEffect(() => {
|
||||||
console.log(form)
|
setApi(
|
||||||
}
|
new DefaultApi(new Configuration({
|
||||||
|
basePath: window.location.origin + "/api/internal/v1",
|
||||||
|
accessToken : cookie.token as string
|
||||||
|
})))
|
||||||
|
})
|
||||||
|
|
||||||
const [username, setUsername] = createSignal("")
|
const theme = createTheme({
|
||||||
const [password, setPassword] = createSignal("")
|
palette: {
|
||||||
|
mode: prefersDarkMode() ? 'dark' : 'light',
|
||||||
return (
|
|
||||||
<form onSubmit={function (e: SubmitEvent) {
|
|
||||||
e.preventDefault()
|
|
||||||
fetch("/login", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({username: username(), password: password()}),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
}).then(res => res.json())
|
|
||||||
// .then(res => fetch("/auth-check", {
|
|
||||||
// method: "GET",
|
|
||||||
// headers: {
|
|
||||||
// 'Authorization': 'Bearer ' + res.token
|
|
||||||
// }
|
|
||||||
// }))
|
|
||||||
// .then(res => res.json())
|
|
||||||
.then(res => {
|
|
||||||
console.log(res.token);
|
|
||||||
fetch("/refresh-token", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({refreshToken: res.refreshToken}),
|
|
||||||
}).then(res=> res.json()).then(res => console.log(res.token))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}>
|
return (
|
||||||
<input name="username" type="text" placeholder="Username" required
|
<ApiProvider api={api()}>
|
||||||
onChange={(e) => setUsername(e.currentTarget.value)}/>
|
<ThemeProvider theme={theme}>
|
||||||
<input name="password" type="password" placeholder="Password" required
|
<CssBaseline/>
|
||||||
onChange={(e) => setPassword(e.currentTarget.value)}/>
|
<Router>
|
||||||
<button type="submit">Submit</button>
|
<Routes>
|
||||||
</form>
|
<Route path="/" component={TopPage}/>
|
||||||
|
<Route path="/login" component={LoginPage}/>
|
||||||
|
</Routes>
|
||||||
|
</Router>
|
||||||
|
</ThemeProvider>
|
||||||
|
</ApiProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
declare module 'solid-js' {
|
|
||||||
namespace JSX {
|
|
||||||
interface Directives {
|
|
||||||
fn: (form: HTMLFormElement) => void
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import {Avatar as SuidAvatar} from "@suid/material";
|
||||||
|
import {Component, JSXElement} from "solid-js";
|
||||||
|
|
||||||
|
export const Avatar: Component<{ src: string }> = (props): JSXElement => {
|
||||||
|
return (
|
||||||
|
<SuidAvatar src={props.src}/>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import {ParentComponent} from "solid-js";
|
||||||
|
import {Button, ListItem, ListItemAvatar, ListItemButton, ListItemIcon, ListItemText} from "@suid/material";
|
||||||
|
import {Link} from "@solidjs/router";
|
||||||
|
|
||||||
|
export const SidebarButton: ParentComponent<{ text: string,linkTo:string }> = (props) => {
|
||||||
|
return (
|
||||||
|
<ListItem>
|
||||||
|
<ListItemButton component={Link} href={props.linkTo}>
|
||||||
|
<ListItemIcon>{props.children}</ListItemIcon>
|
||||||
|
<ListItemText primary={props.text}/>
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import {createContextProvider} from "@solid-primitives/context";
|
||||||
|
import {createSignal} from "solid-js";
|
||||||
|
import {DefaultApi, DefaultApiInterface} from "../generated";
|
||||||
|
|
||||||
|
export const [ApiProvider,useApi] = createContextProvider((props:{api:DefaultApiInterface}) => {
|
||||||
|
const [api,setApi] = createSignal(props.api);
|
||||||
|
return api
|
||||||
|
},()=>new DefaultApi());
|
|
@ -0,0 +1,16 @@
|
||||||
|
import {DefaultApiInterface} from "../generated";
|
||||||
|
|
||||||
|
export class ApiWrapper {
|
||||||
|
api: DefaultApiInterface;
|
||||||
|
|
||||||
|
constructor(initApi: DefaultApiInterface) {
|
||||||
|
this.api = initApi;
|
||||||
|
console.log(this.api);
|
||||||
|
console.log(this.postsGet());
|
||||||
|
}
|
||||||
|
|
||||||
|
postsGet = async () => this.api.postsGet()
|
||||||
|
|
||||||
|
usersUserNameGet = async (userName: string) => this.api.usersUserNameGet(userName);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import {Component, Match, Switch} from "solid-js";
|
||||||
|
import {Home, Lock, Mail, Public} from "@suid/icons-material";
|
||||||
|
import {IconButton} from "@suid/material";
|
||||||
|
import {Visibility} from "../generated";
|
||||||
|
|
||||||
|
export const ShareScopeIndicator: Component<{ visibility: Visibility }> = (props) => {
|
||||||
|
return <Switch fallback={<Public/>}>
|
||||||
|
<Match when={props.visibility == "public"}>
|
||||||
|
<IconButton>
|
||||||
|
<Public/>
|
||||||
|
</IconButton>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.visibility == "direct"}>
|
||||||
|
<IconButton>
|
||||||
|
<Mail/>
|
||||||
|
</IconButton>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.visibility == "followers"}>
|
||||||
|
<IconButton>
|
||||||
|
<Lock/>
|
||||||
|
</IconButton>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.visibility == "unlisted"}>
|
||||||
|
<IconButton>
|
||||||
|
<Home/>
|
||||||
|
</IconButton>
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
import {Component, createSignal} from "solid-js";
|
||||||
|
import {Box, Card, CardActions, CardContent, CardHeader, IconButton, Menu, MenuItem, Typography} from "@suid/material";
|
||||||
|
import {Avatar} from "../atoms/Avatar";
|
||||||
|
import {Favorite, MoreVert, Reply, ScreenRotationAlt} from "@suid/icons-material";
|
||||||
|
import {ShareScopeIndicator} from "../molecules/ShareScopeIndicator";
|
||||||
|
import {PostResponse} from "../generated";
|
||||||
|
|
||||||
|
export const Post: Component<{ post: PostResponse }> = (props) => {
|
||||||
|
const [anchorEl, setAnchorEl] = createSignal<null | HTMLElement>(null)
|
||||||
|
const open = () => Boolean(anchorEl());
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader avatar={<Avatar src={props.post.user.url + "/icon.jpg"}/>} title={props.post.user.screenName}
|
||||||
|
subheader={`${props.post.user.name}@${props.post.user.domain}`}
|
||||||
|
action={<IconButton onclick={(event) => {
|
||||||
|
setAnchorEl(event.currentTarget)
|
||||||
|
}}><MoreVert/><Menu disableScrollLock anchorEl={anchorEl()} open={open()} onClose={handleClose}><MenuItem
|
||||||
|
onclick={handleClose}>aaa</MenuItem></Menu> </IconButton>}/>
|
||||||
|
<CardContent>
|
||||||
|
<Typography>
|
||||||
|
{props.post.text}
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
<CardActions disableSpacing>
|
||||||
|
<IconButton>
|
||||||
|
<Reply/>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton>
|
||||||
|
<ScreenRotationAlt/>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton>
|
||||||
|
<Favorite/>
|
||||||
|
</IconButton>
|
||||||
|
<Box sx={{marginLeft: "auto"}}>
|
||||||
|
<Typography>{new Date(props.post.createdAt).toDateString()}</Typography>
|
||||||
|
</Box>
|
||||||
|
<ShareScopeIndicator visibility={props.post.visibility}/>
|
||||||
|
</CardActions>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
import {Component, createSignal} from "solid-js";
|
||||||
|
import {Button, IconButton, Paper, Stack, TextField, Typography} from "@suid/material";
|
||||||
|
import {Avatar} from "../atoms/Avatar";
|
||||||
|
import {AddPhotoAlternate, Poll, Public} from "@suid/icons-material";
|
||||||
|
import {useApi} from "../lib/ApiProvider";
|
||||||
|
|
||||||
|
export const PostForm: Component<{ label: string }> = (props) => {
|
||||||
|
const [text, setText] = createSignal("")
|
||||||
|
const api = useApi()
|
||||||
|
return (
|
||||||
|
<Paper sx={{width: "100%"}}>
|
||||||
|
<Stack>
|
||||||
|
<Stack direction={"row"} spacing={2} sx={{padding: 2}}>
|
||||||
|
<Avatar src={""}/>
|
||||||
|
<TextField label={props.label} multiline rows={4} variant={"standard"} onChange={(event)=>setText(event.target.value)} fullWidth/>
|
||||||
|
</Stack>
|
||||||
|
<Stack direction={"row"} justifyContent={"space-between"} sx={{padding: 2}}>
|
||||||
|
<Stack direction={"row"} justifyContent={"flex-start"} alignItems={"center"}>
|
||||||
|
<IconButton>
|
||||||
|
<AddPhotoAlternate/>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton>
|
||||||
|
<Poll/>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton>
|
||||||
|
<Public/>
|
||||||
|
</IconButton>
|
||||||
|
</Stack>
|
||||||
|
<Stack direction={"row"} alignItems={"center"} spacing={2}>
|
||||||
|
<Typography>
|
||||||
|
aaa
|
||||||
|
</Typography>
|
||||||
|
<Button variant={"contained"} onClick={() => {
|
||||||
|
api().postsPost({text: text()}).then(()=>setText(""))
|
||||||
|
}}>
|
||||||
|
投稿する
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import {Button, Card, CardContent, CardHeader, Modal, Stack, TextField} from "@suid/material";
|
||||||
|
import {Component, createSignal} from "solid-js";
|
||||||
|
import {createCookieStorage} from "@solid-primitives/storage";
|
||||||
|
import {useApi} from "../lib/ApiProvider";
|
||||||
|
import {useNavigate} from "@solidjs/router";
|
||||||
|
|
||||||
|
export const LoginPage: Component = () => {
|
||||||
|
const [username, setUsername] = createSignal("")
|
||||||
|
const [password, setPassword] = createSignal("")
|
||||||
|
|
||||||
|
const [cookie, setCookie] = createCookieStorage();
|
||||||
|
|
||||||
|
const navigator = useNavigate();
|
||||||
|
|
||||||
|
const api = useApi();
|
||||||
|
|
||||||
|
const onSubmit: () => void = () => {
|
||||||
|
api().loginPost({password: password(), username: username()}).then(value => {
|
||||||
|
setCookie("token", value.token);
|
||||||
|
setCookie("refresh-token", value.refreshToken)
|
||||||
|
navigator("/")
|
||||||
|
}).catch(reason => {
|
||||||
|
console.log(reason);
|
||||||
|
setPassword("")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal open>
|
||||||
|
<Card>
|
||||||
|
<CardHeader/>
|
||||||
|
<CardContent>
|
||||||
|
|
||||||
|
<Stack spacing={3}>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
value={username()}
|
||||||
|
onChange={(event) => setUsername(event.target.value)}
|
||||||
|
label="Username"
|
||||||
|
type="text"
|
||||||
|
autoComplete="username"
|
||||||
|
variant="standard"
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
value={password()}
|
||||||
|
onChange={(event) => setPassword(event.target.value)}
|
||||||
|
label="Password"
|
||||||
|
type="password"
|
||||||
|
autoComplete="current-password"
|
||||||
|
variant="standard"
|
||||||
|
/>
|
||||||
|
<Button type={"submit"} onClick={onSubmit}>Login</Button>
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import {Component} from "solid-js";
|
||||||
|
import {MainPage} from "../templates/MainPage";
|
||||||
|
import {PostForm} from "../organisms/PostForm";
|
||||||
|
import {Stack} from "@suid/material";
|
||||||
|
import {PostResponse} from "../generated";
|
||||||
|
import {PostList} from "../templates/PostList";
|
||||||
|
import {useApi} from "../lib/ApiProvider";
|
||||||
|
import {createStore} from "solid-js/store";
|
||||||
|
|
||||||
|
|
||||||
|
export const TopPage: Component = () => {
|
||||||
|
const api = useApi()
|
||||||
|
const [posts, setPosts] = createStore<PostResponse[]>([])
|
||||||
|
api().postsGet().then((res)=>setPosts(res))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MainPage>
|
||||||
|
<Stack spacing={1} alignItems={"stretch"}>
|
||||||
|
<PostForm label={"投稿する"}/>
|
||||||
|
<PostList posts={posts}/>
|
||||||
|
</Stack>
|
||||||
|
</MainPage>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import {createSignal, ParentComponent} from "solid-js";
|
||||||
|
import {Grid} from "@suid/material";
|
||||||
|
import {Sidebar} from "./Sidebar";
|
||||||
|
|
||||||
|
export const MainPage: ParentComponent = (props) => {
|
||||||
|
return (
|
||||||
|
<Grid container spacing={2} wrap={"nowrap"}>
|
||||||
|
<Grid item xs={0} md={3}>
|
||||||
|
<Sidebar/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
{props.children}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={0} md={3}>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import {Component, For} from "solid-js";
|
||||||
|
import {CircularProgress} from "@suid/material";
|
||||||
|
import {Post} from "../organisms/Post";
|
||||||
|
import {PostResponse} from "../generated";
|
||||||
|
|
||||||
|
export const PostList: Component<{ posts: PostResponse[] | undefined }> = (props) => {
|
||||||
|
return (
|
||||||
|
<For each={props.posts} fallback={<CircularProgress/>}>
|
||||||
|
{
|
||||||
|
(item, index) => <Post post={item}/>
|
||||||
|
}
|
||||||
|
</For>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import {Component} from "solid-js";
|
||||||
|
import {Button, List, Stack} from "@suid/material";
|
||||||
|
import {Home} from "@suid/icons-material";
|
||||||
|
import {SidebarButton} from "../atoms/SidebarButton";
|
||||||
|
|
||||||
|
export const Sidebar: Component = (props) => {
|
||||||
|
return (
|
||||||
|
<List>
|
||||||
|
<SidebarButton text={"AP"} linkTo={"/"}></SidebarButton>
|
||||||
|
<SidebarButton text={"Home"} linkTo={"/"}><Home/></SidebarButton>
|
||||||
|
</List>
|
||||||
|
)
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
|
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
|
||||||
import dev.usbharu.hideout.exception.InvalidRefreshTokenException
|
import dev.usbharu.hideout.exception.InvalidRefreshTokenException
|
||||||
import dev.usbharu.hideout.repository.IUserRepository
|
import dev.usbharu.hideout.repository.IUserRepository
|
||||||
|
import dev.usbharu.hideout.routing.api.internal.v1.auth
|
||||||
import dev.usbharu.hideout.service.auth.IJwtService
|
import dev.usbharu.hideout.service.auth.IJwtService
|
||||||
import dev.usbharu.hideout.service.core.IMetaService
|
import dev.usbharu.hideout.service.core.IMetaService
|
||||||
import dev.usbharu.hideout.service.user.IUserAuthService
|
import dev.usbharu.hideout.service.user.IUserAuthService
|
||||||
|
@ -24,6 +25,7 @@ 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.config.*
|
import io.ktor.server.config.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
import io.ktor.server.testing.*
|
import io.ktor.server.testing.*
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.mockito.ArgumentMatchers.anyString
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
|
@ -70,7 +72,10 @@ class SecurityKtTest {
|
||||||
val jwkProvider = mock<JwkProvider>()
|
val jwkProvider = mock<JwkProvider>()
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(userAuthService, metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(userAuthService, userRepository, jwtService)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.post("/login") {
|
client.post("/login") {
|
||||||
|
@ -97,7 +102,10 @@ class SecurityKtTest {
|
||||||
val jwkProvider = mock<JwkProvider>()
|
val jwkProvider = mock<JwkProvider>()
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(userAuthService, metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(userAuthService, userRepository, jwtService)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.post("/login") {
|
client.post("/login") {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
|
@ -122,7 +130,10 @@ class SecurityKtTest {
|
||||||
val jwkProvider = mock<JwkProvider>()
|
val jwkProvider = mock<JwkProvider>()
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(userAuthService, metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(userAuthService, userRepository, jwtService)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.post("/login") {
|
client.post("/login") {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
|
@ -140,7 +151,10 @@ class SecurityKtTest {
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check").apply {
|
client.get("/auth-check").apply {
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
||||||
|
@ -155,7 +169,10 @@ class SecurityKtTest {
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
header("Authorization", "Digest dsfjjhogalkjdfmlhaog")
|
header("Authorization", "Digest dsfjjhogalkjdfmlhaog")
|
||||||
|
@ -172,7 +189,10 @@ class SecurityKtTest {
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
header("Authorization", "")
|
header("Authorization", "")
|
||||||
|
@ -190,7 +210,10 @@ class SecurityKtTest {
|
||||||
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
header("Authorization", "Bearer ")
|
header("Authorization", "Bearer ")
|
||||||
|
@ -244,11 +267,12 @@ class SecurityKtTest {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userRepository = mock<IUserRepository>()
|
|
||||||
val jwtService = mock<IJwtService>()
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
|
@ -304,11 +328,12 @@ class SecurityKtTest {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userRepository = mock<IUserRepository>()
|
|
||||||
val jwtService = mock<IJwtService>()
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
header("Authorization", "Bearer $token")
|
header("Authorization", "Bearer $token")
|
||||||
|
@ -362,11 +387,12 @@ class SecurityKtTest {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userRepository = mock<IUserRepository>()
|
|
||||||
val jwtService = mock<IJwtService>()
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
header("Authorization", "Bearer $token")
|
header("Authorization", "Bearer $token")
|
||||||
|
@ -420,11 +446,12 @@ class SecurityKtTest {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userRepository = mock<IUserRepository>()
|
|
||||||
val jwtService = mock<IJwtService>()
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
header("Authorization", "Bearer $token")
|
header("Authorization", "Bearer $token")
|
||||||
|
@ -477,11 +504,12 @@ class SecurityKtTest {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userRepository = mock<IUserRepository>()
|
|
||||||
val jwtService = mock<IJwtService>()
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
|
configureSecurity(jwkProvider, metaService)
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), mock())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.get("/auth-check") {
|
client.get("/auth-check") {
|
||||||
header("Authorization", "Bearer $token")
|
header("Authorization", "Bearer $token")
|
||||||
|
@ -501,7 +529,10 @@ class SecurityKtTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), jwtService, mock())
|
configureSecurity(mock(), mock())
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), jwtService)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.post("/refresh-token") {
|
client.post("/refresh-token") {
|
||||||
header("Content-Type", "application/json")
|
header("Content-Type", "application/json")
|
||||||
|
@ -523,7 +554,10 @@ class SecurityKtTest {
|
||||||
application {
|
application {
|
||||||
configureStatusPages()
|
configureStatusPages()
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), jwtService, mock())
|
configureSecurity(mock(), mock())
|
||||||
|
routing {
|
||||||
|
auth(mock(), mock(), jwtService)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.post("/refresh-token") {
|
client.post("/refresh-token") {
|
||||||
header("Content-Type", "application/json")
|
header("Content-Type", "application/json")
|
||||||
|
|
|
@ -4,6 +4,8 @@ import com.auth0.jwt.interfaces.Claim
|
||||||
import com.auth0.jwt.interfaces.Payload
|
import com.auth0.jwt.interfaces.Payload
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostResponse
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||||
|
@ -32,18 +34,27 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
|
val user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
val posts = listOf(
|
val posts = listOf(
|
||||||
Post(
|
PostResponse(
|
||||||
id = 12345,
|
id = 12345,
|
||||||
userId = 4321,
|
user = user,
|
||||||
text = "test1",
|
text = "test1",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 4322,
|
user = user,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -64,7 +75,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -89,27 +100,35 @@ class PostsTest {
|
||||||
val payload = mock<Payload> {
|
val payload = mock<Payload> {
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
}
|
}
|
||||||
|
val user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
val posts = listOf(
|
val posts = listOf(
|
||||||
Post(
|
PostResponse(
|
||||||
id = 12345,
|
id = 12345,
|
||||||
userId = 4321,
|
user = user,
|
||||||
text = "test1",
|
text = "test1",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 4322,
|
user = user,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
),
|
),
|
||||||
Post(
|
PostResponse(
|
||||||
id = 1234567,
|
id = 1234567,
|
||||||
userId = 4333,
|
user = user,
|
||||||
text = "Followers only",
|
text = "Followers only",
|
||||||
visibility = Visibility.FOLLOWERS,
|
visibility = Visibility.FOLLOWERS,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -156,9 +175,18 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val user = UserResponse(
|
||||||
12345,
|
id = 54321,
|
||||||
1234,
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
|
val post = PostResponse(
|
||||||
|
id = 12345,
|
||||||
|
user = user,
|
||||||
text = "aaa",
|
text = "aaa",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -169,7 +197,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -187,9 +215,17 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = PostResponse(
|
||||||
12345,
|
12345,
|
||||||
1234,
|
UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
text = "aaa",
|
text = "aaa",
|
||||||
visibility = Visibility.FOLLOWERS,
|
visibility = Visibility.FOLLOWERS,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -242,14 +278,22 @@ class PostsTest {
|
||||||
onBlocking { createPost(any(), any()) } doAnswer {
|
onBlocking { createPost(any(), any()) } doAnswer {
|
||||||
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
|
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
|
||||||
val userId = it.getArgument<Long>(1)
|
val userId = it.getArgument<Long>(1)
|
||||||
Post(
|
PostResponse(
|
||||||
123L,
|
id = 123L,
|
||||||
userId,
|
user = UserResponse(
|
||||||
null,
|
id = 54321,
|
||||||
argument.text,
|
name = "user1",
|
||||||
Instant.now().toEpochMilli(),
|
domain = "example.com",
|
||||||
Visibility.PUBLIC,
|
screenName = "user 1",
|
||||||
"https://example.com"
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
|
overview = null,
|
||||||
|
text = argument.text,
|
||||||
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
visibility = Visibility.PUBLIC,
|
||||||
|
url = "https://example.com"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,18 +334,27 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
|
val user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
val posts = listOf(
|
val posts = listOf(
|
||||||
Post(
|
PostResponse(
|
||||||
id = 12345,
|
id = 12345,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test1",
|
text = "test1",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -323,7 +376,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -342,18 +395,27 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
|
val user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
val posts = listOf(
|
val posts = listOf(
|
||||||
Post(
|
PostResponse(
|
||||||
id = 12345,
|
id = 12345,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test1",
|
text = "test1",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -375,7 +437,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -394,18 +456,27 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
|
val user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
val posts = listOf(
|
val posts = listOf(
|
||||||
Post(
|
PostResponse(
|
||||||
id = 12345,
|
id = 12345,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test1",
|
text = "test1",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -427,7 +498,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -446,18 +517,27 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
|
val user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
val posts = listOf(
|
val posts = listOf(
|
||||||
Post(
|
PostResponse(
|
||||||
id = 12345,
|
id = 12345,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test1",
|
text = "test1",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
),
|
),
|
||||||
Post(
|
PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = user,
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -479,7 +559,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -498,9 +578,17 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -511,7 +599,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -530,9 +618,17 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -543,7 +639,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -562,9 +658,17 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -575,7 +679,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
@ -594,9 +698,17 @@ class PostsTest {
|
||||||
environment {
|
environment {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val post = Post(
|
val post = PostResponse(
|
||||||
id = 123456,
|
id = 123456,
|
||||||
userId = 1,
|
user = UserResponse(
|
||||||
|
id = 54321,
|
||||||
|
name = "user1",
|
||||||
|
domain = "example.com",
|
||||||
|
screenName = "user 1",
|
||||||
|
description = "Test user",
|
||||||
|
url = "https://example.com/users/54321",
|
||||||
|
createdAt = Instant.now().toEpochMilli()
|
||||||
|
),
|
||||||
text = "test2",
|
text = "test2",
|
||||||
visibility = Visibility.PUBLIC,
|
visibility = Visibility.PUBLIC,
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
|
@ -607,7 +719,7 @@ class PostsTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService, mock())
|
posts(postService, mock())
|
||||||
|
|
|
@ -58,7 +58,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userService)
|
users(mock(), userService)
|
||||||
|
@ -96,7 +96,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(userService, mock())
|
users(userService, mock())
|
||||||
|
@ -127,7 +127,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(userService, mock())
|
users(userService, mock())
|
||||||
|
@ -162,7 +162,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -195,7 +195,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -228,7 +228,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -261,7 +261,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -306,7 +306,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -351,7 +351,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -396,7 +396,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -591,7 +591,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -636,7 +636,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
@ -681,7 +681,7 @@ class UsersTest {
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
configureSecurity(mock(), mock(), mock(), mock(), mock())
|
configureSecurity(mock(), mock())
|
||||||
routing {
|
routing {
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
users(mock(), userApiService)
|
users(mock(), userApiService)
|
||||||
|
|
|
@ -48,13 +48,21 @@ class ActivityPubReceiveFollowServiceImplTest {
|
||||||
firstValue.invoke(scheduleContext, ReceiveFollowJob)
|
firstValue.invoke(scheduleContext, ReceiveFollowJob)
|
||||||
val actor = scheduleContext.props.props[ReceiveFollowJob.actor.name]
|
val actor = scheduleContext.props.props[ReceiveFollowJob.actor.name]
|
||||||
val targetActor = scheduleContext.props.props[ReceiveFollowJob.targetActor.name]
|
val targetActor = scheduleContext.props.props[ReceiveFollowJob.targetActor.name]
|
||||||
val follow = scheduleContext.props.props[ReceiveFollowJob.follow.name]
|
val follow = scheduleContext.props.props[ReceiveFollowJob.follow.name] as String
|
||||||
assertEquals("https://follower.example.com", actor)
|
assertEquals("https://follower.example.com", actor)
|
||||||
assertEquals("https://example.com", targetActor)
|
assertEquals("https://example.com", targetActor)
|
||||||
//language=JSON
|
//language=JSON
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"""{"type":"Follow","name":"Follow","actor":"https://follower.example.com","object":"https://example.com","@context":null}""",
|
Json.parseToJsonElement(
|
||||||
follow
|
"""{
|
||||||
|
"type": "Follow",
|
||||||
|
"name": "Follow",
|
||||||
|
"actor": "https://follower.example.com",
|
||||||
|
"object": "https://example.com",
|
||||||
|
"@context": null
|
||||||
|
}"""
|
||||||
|
),
|
||||||
|
Json.parseToJsonElement(follow)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +163,14 @@ class ActivityPubReceiveFollowServiceImplTest {
|
||||||
data = mapOf<String, Any>(
|
data = mapOf<String, Any>(
|
||||||
ReceiveFollowJob.actor.name to "https://follower.example.com",
|
ReceiveFollowJob.actor.name to "https://follower.example.com",
|
||||||
ReceiveFollowJob.targetActor.name to "https://example.com",
|
ReceiveFollowJob.targetActor.name to "https://example.com",
|
||||||
ReceiveFollowJob.follow.name to """{"type":"Follow","name":"Follow","object":"https://example.com","actor":"https://follower.example.com","@context":null}"""
|
//language=JSON
|
||||||
|
ReceiveFollowJob.follow.name to """{
|
||||||
|
"type": "Follow",
|
||||||
|
"name": "Follow",
|
||||||
|
"object": "https://example.com",
|
||||||
|
"actor": "https://follower.example.com",
|
||||||
|
"@context": null
|
||||||
|
}"""
|
||||||
),
|
),
|
||||||
json = Json
|
json = Json
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
import { defineConfig } from 'vite';
|
import {defineConfig, splitVendorChunkPlugin} from 'vite';
|
||||||
import solidPlugin from 'vite-plugin-solid';
|
import solidPlugin from 'vite-plugin-solid';
|
||||||
import suidPlugin from "@suid/vite-plugin";
|
import suidPlugin from "@suid/vite-plugin";
|
||||||
|
import visualizer from "rollup-plugin-visualizer";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [solidPlugin(),suidPlugin()],
|
plugins: [solidPlugin(),suidPlugin(),splitVendorChunkPlugin()],
|
||||||
server: {
|
server: {
|
||||||
port: 3000,
|
port: 3000,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': 'http://localhost:8080',
|
'/api': 'http://localhost:8080',
|
||||||
'/login': 'http://localhost:8080',
|
|
||||||
'/auth-check': 'http://localhost:8080',
|
|
||||||
'/refresh-token': 'http://localhost:8080',
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
root: './src/main/web',
|
root: './src/main/web',
|
||||||
build: {
|
build: {
|
||||||
target: 'esnext',
|
target: 'esnext',
|
||||||
outDir: '../resources/static',
|
outDir: '../resources/static',
|
||||||
|
rollupOptions:{
|
||||||
|
plugins: [
|
||||||
|
visualizer()
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue