mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-15 22:38:47 +00:00
/api/auth/login Endpoint 구현
This commit is contained in:
27
src/lib/server/auth.ts
Normal file
27
src/lib/server/auth.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import argon2 from "argon2";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { getUserByEmail } from "$lib/server/db/user";
|
||||
import env from "$lib/server/loadenv";
|
||||
|
||||
const verifyPassword = async (hash: string, password: string) => {
|
||||
return await argon2.verify(hash, password);
|
||||
};
|
||||
|
||||
const issueToken = (id: number, type: "access" | "refresh") => {
|
||||
return jwt.sign({ id, type }, env.jwt.secret, {
|
||||
expiresIn: type === "access" ? env.jwt.accessExp : env.jwt.refreshExp,
|
||||
});
|
||||
};
|
||||
|
||||
export const login = async (email: string, password: string) => {
|
||||
const user = await getUserByEmail(email);
|
||||
if (!user) return null;
|
||||
|
||||
const valid = await verifyPassword(user.password, password);
|
||||
if (!valid) return null;
|
||||
|
||||
return {
|
||||
accessToken: issueToken(user.id, "access"),
|
||||
refreshToken: issueToken(user.id, "refresh"),
|
||||
};
|
||||
};
|
||||
7
src/lib/server/db/drizzle.ts
Normal file
7
src/lib/server/db/drizzle.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import Database from "better-sqlite3";
|
||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||
import env from "$lib/server/loadenv";
|
||||
|
||||
const client = new Database(env.databaseUrl);
|
||||
|
||||
export default drizzle(client);
|
||||
@@ -1,6 +0,0 @@
|
||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||
import Database from "better-sqlite3";
|
||||
import { env } from "$env/dynamic/private";
|
||||
if (!env.DATABASE_URL) throw new Error("DATABASE_URL is not set");
|
||||
const client = new Database(env.DATABASE_URL);
|
||||
export const db = drizzle(client);
|
||||
8
src/lib/server/db/user.ts
Normal file
8
src/lib/server/db/user.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import db from "./drizzle";
|
||||
import { user } from "./schema";
|
||||
|
||||
export const getUserByEmail = async (email: string) => {
|
||||
const users = await db.select().from(user).where(eq(user.email, email)).execute();
|
||||
return users[0] ?? null;
|
||||
};
|
||||
12
src/lib/server/loadenv.ts
Normal file
12
src/lib/server/loadenv.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { env } from "$env/dynamic/private";
|
||||
|
||||
if (!env.JWT_SECRET) throw new Error("JWT_SECRET is not set");
|
||||
|
||||
export default {
|
||||
databaseUrl: env.DATABASE_URL || "local.db",
|
||||
jwt: {
|
||||
secret: env.JWT_SECRET,
|
||||
accessExp: env.JWT_ACCESS_TOKEN_EXPIRES || "5m",
|
||||
refreshExp: env.JWT_REFRESH_TOKEN_EXPIRES || "14d",
|
||||
},
|
||||
};
|
||||
22
src/routes/api/auth/login/+server.ts
Normal file
22
src/routes/api/auth/login/+server.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { error, json } from "@sveltejs/kit";
|
||||
import { z } from "zod";
|
||||
import { login } from "$lib/server/auth";
|
||||
import type { RequestHandler } from "./$types";
|
||||
|
||||
export const POST: RequestHandler = async ({ request }) => {
|
||||
const zodRes = z
|
||||
.object({
|
||||
email: z.string().email().nonempty(),
|
||||
password: z.string().nonempty(),
|
||||
})
|
||||
.safeParse(await request.json());
|
||||
if (!zodRes.success) error(400, zodRes.error.message);
|
||||
|
||||
const { email, password } = zodRes.data;
|
||||
const loginRes = await login(email.trim(), password.trim());
|
||||
|
||||
if (!loginRes) error(401, "Invalid email or password");
|
||||
const { accessToken, refreshToken } = loginRes;
|
||||
|
||||
return json({ accessToken, refreshToken });
|
||||
};
|
||||
Reference in New Issue
Block a user