From 8bb4d70fa51b4bbd704e1d1f2e81bc2d0c77a079 Mon Sep 17 00:00:00 2001 From: static Date: Mon, 13 Jan 2025 02:53:32 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/components/divs/TitleDiv.svelte | 7 ++-- src/lib/server/db/session.ts | 4 +- src/lib/server/middlewares/setAgentInfo.ts | 4 +- src/lib/server/schemas/auth.ts | 4 +- .../auth/changePassword/+page.svelte | 38 +++++++++++++++++++ .../auth/changePassword/service.ts | 10 +++++ src/routes/(main)/menu/+page.svelte | 26 ++++++++++++- src/routes/(main)/menu/+page.ts | 14 +++++++ src/routes/+layout.svelte | 2 +- src/routes/api/auth/changePassword/+server.ts | 4 +- 10 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 src/routes/(fullscreen)/auth/changePassword/+page.svelte create mode 100644 src/routes/(fullscreen)/auth/changePassword/service.ts create mode 100644 src/routes/(main)/menu/+page.ts diff --git a/src/lib/components/divs/TitleDiv.svelte b/src/lib/components/divs/TitleDiv.svelte index e622e6e..d6c4414 100644 --- a/src/lib/components/divs/TitleDiv.svelte +++ b/src/lib/components/divs/TitleDiv.svelte @@ -3,15 +3,16 @@ import type { SvelteHTMLElements } from "svelte/elements"; interface Props { - icon?: Component; children: Snippet; + icon?: Component; + topPadding?: boolean; } - let { icon: Icon, children }: Props = $props(); + let { topPadding = true, children, icon: Icon }: Props = $props();
-
+
{#if Icon} {/if} diff --git a/src/lib/server/db/session.ts b/src/lib/server/db/session.ts index b51bf85..971e086 100644 --- a/src/lib/server/db/session.ts +++ b/src/lib/server/db/session.ts @@ -41,8 +41,8 @@ export const refreshSession = async ( .update(session) .set({ lastUsedAt: now, - lastUsedByIp: ip, - lastUsedByUserAgent: userAgent, + lastUsedByIp: ip ?? undefined, + lastUsedByUserAgent: userAgent ?? undefined, }) .where( and( diff --git a/src/lib/server/middlewares/setAgentInfo.ts b/src/lib/server/middlewares/setAgentInfo.ts index d272f2a..8e3f570 100644 --- a/src/lib/server/middlewares/setAgentInfo.ts +++ b/src/lib/server/middlewares/setAgentInfo.ts @@ -5,12 +5,12 @@ export const setAgentInfoMiddleware: Handle = async ({ event, resolve }) => { const userAgent = event.request.headers.get("User-Agent"); if (!ip) { error(500, "IP address not found"); - } else if (!userAgent) { + } else if (!userAgent && !event.isSubRequest) { error(400, "User agent not found"); } event.locals.ip = ip; - event.locals.userAgent = userAgent; + event.locals.userAgent = userAgent ?? ""; return await resolve(event); }; diff --git a/src/lib/server/schemas/auth.ts b/src/lib/server/schemas/auth.ts index 2d800d0..eae349f 100644 --- a/src/lib/server/schemas/auth.ts +++ b/src/lib/server/schemas/auth.ts @@ -1,10 +1,10 @@ import { z } from "zod"; -export const changePasswordRequest = z.object({ +export const passwordChangeRequest = z.object({ oldPassword: z.string().trim().nonempty(), newPassword: z.string().trim().nonempty(), }); -export type ChangePasswordRequest = z.infer; +export type PasswordChangeRequest = z.infer; export const loginRequest = z.object({ email: z.string().email().nonempty(), diff --git a/src/routes/(fullscreen)/auth/changePassword/+page.svelte b/src/routes/(fullscreen)/auth/changePassword/+page.svelte new file mode 100644 index 0000000..2b4875f --- /dev/null +++ b/src/routes/(fullscreen)/auth/changePassword/+page.svelte @@ -0,0 +1,38 @@ + + + + 비밀번호 바꾸기 + + +
+ + +
+

기존 비밀번호와 새 비밀번호를 입력해 주세요.

+

새 비밀번호는 8자 이상이어야 해요. 다른 사람들이 알 수 없도록 안전하게 설정해 주세요.

+
+
+ + +
+
+
+ + + diff --git a/src/routes/(fullscreen)/auth/changePassword/service.ts b/src/routes/(fullscreen)/auth/changePassword/service.ts new file mode 100644 index 0000000..37380a4 --- /dev/null +++ b/src/routes/(fullscreen)/auth/changePassword/service.ts @@ -0,0 +1,10 @@ +import { callPostApi } from "$lib/hooks"; +import type { PasswordChangeRequest } from "$lib/server/schemas"; + +export const requestPasswordChange = async (oldPassword: string, newPassword: string) => { + const res = await callPostApi("/api/auth/changePassword", { + oldPassword, + newPassword, + }); + return res.ok; +}; diff --git a/src/routes/(main)/menu/+page.svelte b/src/routes/(main)/menu/+page.svelte index 73d68b7..7b62e41 100644 --- a/src/routes/(main)/menu/+page.svelte +++ b/src/routes/(main)/menu/+page.svelte @@ -1,3 +1,25 @@ -
-

아직 개발 중이에요.

+ + +
+

{data.nickname}

+
+
+
+

보안

+ goto("/auth/changePassword")}> +
+
+ +
+

비밀번호 바꾸기

+
+
+
diff --git a/src/routes/(main)/menu/+page.ts b/src/routes/(main)/menu/+page.ts new file mode 100644 index 0000000..30a265a --- /dev/null +++ b/src/routes/(main)/menu/+page.ts @@ -0,0 +1,14 @@ +import { error } from "@sveltejs/kit"; +import { callGetApi } from "$lib/hooks"; +import type { UserInfoResponse } from "$lib/server/schemas"; +import type { PageLoad } from "./$types"; + +export const load: PageLoad = async ({ fetch }) => { + const res = await callGetApi("/api/user", fetch); + if (!res.ok) { + error(500, "Internal server error"); + } + + const { nickname }: UserInfoResponse = await res.json(); + return { nickname }; +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index d682821..091c034 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -8,7 +8,7 @@ onMount(async () => { const goto = async (url: string) => { - const whitelist = ["/auth", "/key", "/client/pending"]; + const whitelist = ["/auth/login", "/key", "/client/pending"]; if (!whitelist.some((path) => location.pathname.startsWith(path))) { await svelteGoto( `${url}?redirect=${encodeURIComponent(location.pathname + location.search)}`, diff --git a/src/routes/api/auth/changePassword/+server.ts b/src/routes/api/auth/changePassword/+server.ts index a0fbb8d..59129b8 100644 --- a/src/routes/api/auth/changePassword/+server.ts +++ b/src/routes/api/auth/changePassword/+server.ts @@ -1,13 +1,13 @@ import { error, text } from "@sveltejs/kit"; import { authorize } from "$lib/server/modules/auth"; -import { changePasswordRequest } from "$lib/server/schemas"; +import { passwordChangeRequest } from "$lib/server/schemas"; import { changePassword } from "$lib/server/services/auth"; import type { RequestHandler } from "./$types"; export const POST: RequestHandler = async ({ locals, request }) => { const { sessionId, userId } = await authorize(locals, "any"); - const zodRes = changePasswordRequest.safeParse(await request.json()); + const zodRes = passwordChangeRequest.safeParse(await request.json()); if (!zodRes.success) error(400, "Invalid request body"); const { oldPassword, newPassword } = zodRes.data;