diff --git a/build.gradle.kts b/build.gradle.kts index a3b71261..91ca0a6a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -80,12 +80,14 @@ dependencies { implementation("org.xerial:sqlite-jdbc:3.40.1.0") implementation("io.ktor:ktor-server-websockets-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("io.insert-koin:koin-core:$koin_version") implementation("io.insert-koin:koin-ktor:$koin_version") implementation("io.insert-koin:koin-logger-slf4j:$koin_version") 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") diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt index 5052c79c..4a6d4f68 100644 --- a/src/main/kotlin/dev/usbharu/hideout/Application.kt +++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt @@ -95,6 +95,7 @@ fun Application.parent() { runBlocking { inject().value.init() } + configureCompression() configureHTTP() configureStaticRouting() configureMonitoring() diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Compression.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Compression.kt new file mode 100644 index 00000000..e13fa4c9 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Compression.kt @@ -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 + } + } +} diff --git a/src/main/resources/openapi/api.yaml b/src/main/resources/openapi/api.yaml index 82f8f3e5..17efe775 100644 --- a/src/main/resources/openapi/api.yaml +++ b/src/main/resources/openapi/api.yaml @@ -230,6 +230,46 @@ paths: items: $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: responses: Unauthorized: @@ -359,6 +399,27 @@ components: 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: BearerAuth: diff --git a/src/main/web/App.tsx b/src/main/web/App.tsx index 7e925695..8114059a 100644 --- a/src/main/web/App.tsx +++ b/src/main/web/App.tsx @@ -10,7 +10,7 @@ import {LoginPage} from "./pages/LoginPage"; 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/",apiKey:cookie.key as string}))) + const [api,setApi] = createSignal(new DefaultApi(new Configuration({basePath:window.location.origin+"/api/internal/v1",apiKey:cookie.key as string}))) const theme = createTheme({ palette: { mode: prefersDarkMode() ? 'dark' : 'light', diff --git a/src/main/web/pages/LoginPage.tsx b/src/main/web/pages/LoginPage.tsx index d5ccc4f1..a2d1b1ff 100644 --- a/src/main/web/pages/LoginPage.tsx +++ b/src/main/web/pages/LoginPage.tsx @@ -1,9 +1,25 @@ 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"; -export const LoginPage:Component = () => { - const [username,setUsername] = createSignal("") - const [password,setPassword] = createSignal("") +export const LoginPage: Component = () => { + const [username, setUsername] = createSignal("") + const [password, setPassword] = createSignal("") + + const [cookie, setCookie] = createCookieStorage(); + + const api = useApi(); + + const onSubmit: () => void = () => { + api().loginPost({password: password(), username: username()}).then(value => { + setCookie("token", value.token); + setCookie("refresh-token", value.refreshToken) + }).catch(reason => { + console.log(reason); + setPassword("") + }) + } return ( @@ -15,7 +31,7 @@ export const LoginPage:Component = () => { setUsername(event.target.value)} + onChange={(event) => setUsername(event.target.value)} label="Username" type="text" autoComplete="username" @@ -23,14 +39,13 @@ export const LoginPage:Component = () => { /> setPassword(event.target.value)} + onChange={(event) => setPassword(event.target.value)} label="Password" type="password" autoComplete="current-password" variant="standard" /> - +