feat: ログインページでログイン成功時にトークンを保存するように

This commit is contained in:
usbharu 2023-07-06 17:50:28 +09:00
parent cd442d7f51
commit b1d0747038
Signed by: usbharu
GPG Key ID: 6556747BF94EEBC8
6 changed files with 106 additions and 8 deletions

View File

@ -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")

View File

@ -95,6 +95,7 @@ fun Application.parent() {
runBlocking { runBlocking {
inject<IServerInitialiseService>().value.init() inject<IServerInitialiseService>().value.init()
} }
configureCompression()
configureHTTP() configureHTTP()
configureStaticRouting() configureStaticRouting()
configureMonitoring() configureMonitoring()

View File

@ -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
}
}
}

View File

@ -230,6 +230,46 @@ paths:
items: items:
$ref: "#/components/schemas/UserResponse" $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:
Unauthorized: Unauthorized:
@ -359,6 +399,27 @@ components:
sensitive: sensitive:
type: boolean 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:

View File

@ -10,7 +10,7 @@ import {LoginPage} from "./pages/LoginPage";
export const App: Component = () => { export const App: Component = () => {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const [cookie,setCookie] = createCookieStorage() 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({ const theme = createTheme({
palette: { palette: {
mode: prefersDarkMode() ? 'dark' : 'light', mode: prefersDarkMode() ? 'dark' : 'light',

View File

@ -1,9 +1,25 @@
import {Button, Card, CardContent, CardHeader, Modal, Stack, TextField} from "@suid/material"; import {Button, Card, CardContent, CardHeader, Modal, Stack, TextField} from "@suid/material";
import {Component, createSignal} from "solid-js"; import {Component, createSignal} from "solid-js";
import {createCookieStorage} from "@solid-primitives/storage";
import {useApi} from "../lib/ApiProvider";
export const LoginPage:Component = () => { export const LoginPage: Component = () => {
const [username,setUsername] = createSignal("") const [username, setUsername] = createSignal("")
const [password,setPassword] = 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 ( return (
<Modal open> <Modal open>
@ -15,7 +31,7 @@ export const LoginPage:Component = () => {
<TextField <TextField
value={username()} value={username()}
onChange={(event)=>setUsername(event.target.value)} onChange={(event) => setUsername(event.target.value)}
label="Username" label="Username"
type="text" type="text"
autoComplete="username" autoComplete="username"
@ -23,14 +39,13 @@ export const LoginPage:Component = () => {
/> />
<TextField <TextField
value={password()} value={password()}
onChange={(event)=>setPassword(event.target.value)} onChange={(event) => setPassword(event.target.value)}
label="Password" label="Password"
type="password" type="password"
autoComplete="current-password" autoComplete="current-password"
variant="standard" variant="standard"
/> />
<Button type={"submit"} onClick={()=>{ <Button type={"submit"} onClick={onSubmit}>Login</Button>
console.log(username() +" " + password())}}>Login</Button>
</Stack> </Stack>
</CardContent> </CardContent>
</Card> </Card>