diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts
index eab1e7a..ce47e16 100644
--- a/src/lib/server/auth.ts
+++ b/src/lib/server/auth.ts
@@ -33,7 +33,7 @@ export async function validateSessionToken(token: string) {
const [result] = await db
.select({
// Adjust user table here to tweak returned data
- user: { id: table.user.id, username: table.user.username },
+ user: { id: table.user.id, email: table.user.email },
session: table.session
})
.from(table.session)
diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts
index 653d167..cf493bd 100644
--- a/src/lib/server/db/schema.ts
+++ b/src/lib/server/db/schema.ts
@@ -1,45 +1,45 @@
-import { pgTable, serial, integer, text, timestamp } from 'drizzle-orm/pg-core';
+import {pgTable, serial, integer, text, timestamp} from 'drizzle-orm/pg-core';
export const user = pgTable('user', {
- id: text('id').primaryKey(),
- age: integer('age'), //나이
- username: text('username').notNull().unique(), // username 이 사용자가 회원가입 할때 id 임
- nickname: text('nickname'), // 별칭
- helloword: text('helloword'), // 인사말, 소개말
- avatar: text('avatar'), // 아바타 파일경로
- email: text('email'), // 이메일주소
- gender: text('gender'), // 성별
- passwordHash: text('password_hash').notNull(),
- createdAt: timestamp(),
- updatedAt: timestamp(),
+ id: text('id').primaryKey(),
+ age: integer('age'), //나이
+ username: text('username'),
+ nickname: text('nickname'), // 별칭
+ helloword: text('helloword'), // 인사말, 소개말
+ avatar: text('avatar'), // 아바타 파일경로
+ email: text('email').notNull().unique(), // 이메일주소 이것을 아이디로 사용하도록 변경하자
+ gender: text('gender'), // 성별
+ passwordHash: text('password_hash').notNull(),
+ createdAt: timestamp(),
+ updatedAt: timestamp(),
});
export const session = pgTable('session', {
- id: text('id').primaryKey(),
- userId: text('user_id').notNull().references(() => user.id),
- expiresAt: timestamp('expires_at', { withTimezone: true, mode: 'date' }).notNull(),
- createdAt: timestamp(),
- updatedAt: timestamp(),
+ id: text('id').primaryKey(),
+ userId: text('user_id').notNull().references(() => user.id),
+ expiresAt: timestamp('expires_at', {withTimezone: true, mode: 'date'}).notNull(),
+ createdAt: timestamp(),
+ updatedAt: timestamp(),
});
export const post = pgTable('post', {
- id: text('id').primaryKey(),
- subject: text('subject'),
- slug: text('subject'),
- content: text('subject'),
- author: text('author'),
- status: text('status'), // draft, published 등등..
- category: text('category'),
- createdAt: timestamp(),
- updatedAt: timestamp(),
+ id: text('id').primaryKey(),
+ subject: text('subject'),
+ slug: text('subject'),
+ content: text('subject'),
+ author: text('author'),
+ status: text('status'), // draft, published 등등..
+ category: text('category'),
+ createdAt: timestamp(),
+ updatedAt: timestamp(),
});
export const hierarchy = pgTable('hierarchy', {
- id: text('id').primaryKey(),
- name: text('subject'),
- parent_id: text('subject'),
- createdAt: timestamp(),
- updatedAt: timestamp(),
+ id: text('id').primaryKey(),
+ name: text('subject'),
+ parent_id: text('subject'),
+ createdAt: timestamp(),
+ updatedAt: timestamp(),
});
export type Session = typeof session.$inferSelect;
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 3153e95..e98e847 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,7 +1,7 @@
-
+
{@render children()}
diff --git a/src/routes/login/+page.server.ts b/src/routes/login/+page.server.ts
index 772429e..7ccfa69 100644
--- a/src/routes/login/+page.server.ts
+++ b/src/routes/login/+page.server.ts
@@ -30,17 +30,17 @@ export const actions: Actions = {
});
}
- const userId = form.data.userId;
+ const email = form.data.email;
const password = form.data.password;
const results = await db
.select()
.from(table.user)
- .where(eq(table.user.username, userId));
+ .where(eq(table.user.email, email));
const existingUser = results.at(0);
if (!existingUser) {
- return setError(form, 'userId', '존재하지 않는 아이디 입니다.');
+ return setError(form, 'email', '등록된 이메일이 아닙니다.');
}
const validPassword = await verify(existingUser.passwordHash, password, {
diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte
index cf0bbd7..0afee2b 100644
--- a/src/routes/login/+page.svelte
+++ b/src/routes/login/+page.svelte
@@ -1,10 +1,11 @@
-
-
-
-
+
diff --git a/src/routes/login/login-form.svelte b/src/routes/login/login-form.svelte
index 1ddfdae..21afe12 100644
--- a/src/routes/login/login-form.svelte
+++ b/src/routes/login/login-form.svelte
@@ -26,7 +26,7 @@
-
+
LOGIN
@@ -36,11 +36,11 @@
diff --git a/src/routes/login/schema.ts b/src/routes/login/schema.ts
index 56432a5..846d2bb 100644
--- a/src/routes/login/schema.ts
+++ b/src/routes/login/schema.ts
@@ -2,10 +2,8 @@ import { z } from "zod";
export const formSchema = z.object({
// User ID (formerly 'user')
- userId: z.string()
- .min(3, "최소 3자 이상이어야 합니다.") // A common minimum for IDs
- .max(50, "최대 50자 이하이어야 합니다.") // Reasonable maximum length
- .regex(/^[a-zA-Z0-9_.-]+$/, "영문, 숫자, '_', '.', '-'만 포함할 수 있습니다.") // Restrict characters
+ email: z.string()
+ .email("이메일주소 형식이 아닙니다.")
.trim(), // Remove leading/trailing whitespace
// Password
diff --git a/src/routes/register/+layout.svelte b/src/routes/register/+layout.svelte
new file mode 100644
index 0000000..10d935d
--- /dev/null
+++ b/src/routes/register/+layout.svelte
@@ -0,0 +1,5 @@
+
+
+{@render children()}
\ No newline at end of file
diff --git a/src/routes/register/+page.server.ts b/src/routes/register/+page.server.ts
new file mode 100644
index 0000000..7ccfa69
--- /dev/null
+++ b/src/routes/register/+page.server.ts
@@ -0,0 +1,67 @@
+import {hash, verify} from '@node-rs/argon2';
+import {encodeBase32LowerCase} from '@oslojs/encoding';
+import {redirect} from '@sveltejs/kit';
+import {eq} from 'drizzle-orm';
+import * as auth from '$lib/server/auth';
+import {db} from '$lib/server/db';
+import * as table from '$lib/server/db/schema';
+import type {Actions, PageServerLoad} from './$types';
+import { setError, superValidate , fail} from 'sveltekit-superforms';
+import {zod} from "sveltekit-superforms/adapters";
+import {formSchema} from "./schema";
+
+
+
+export const load: PageServerLoad = async (event) => {
+ if (event.locals.user) {
+ return redirect(302, '/demo/lucia');
+ }
+ return {
+ form: await superValidate(zod(formSchema)),
+ };
+};
+
+export const actions: Actions = {
+ login: async (event) => {
+ const form = await superValidate(event, zod(formSchema));
+ if (!form.valid) {
+ return fail(400, {
+ form,
+ });
+ }
+
+ const email = form.data.email;
+ const password = form.data.password;
+
+ const results = await db
+ .select()
+ .from(table.user)
+ .where(eq(table.user.email, email));
+
+ const existingUser = results.at(0);
+ if (!existingUser) {
+ return setError(form, 'email', '등록된 이메일이 아닙니다.');
+ }
+
+ const validPassword = await verify(existingUser.passwordHash, password, {
+ memoryCost: 19456,
+ timeCost: 2,
+ outputLen: 32,
+ parallelism: 1,
+ });
+ if (!validPassword) {
+ return setError(form, 'password', '비밀번호가 일치하지 않습니다.');
+ }
+
+ const sessionToken = auth.generateSessionToken();
+ const session = await auth.createSession(sessionToken, existingUser.id);
+ auth.setSessionTokenCookie(event, sessionToken, session.expiresAt);
+
+ return redirect(302, '/demo/lucia');
+
+ },
+};
+
+
+
+
diff --git a/src/routes/register/+page.svelte b/src/routes/register/+page.svelte
new file mode 100644
index 0000000..e87a321
--- /dev/null
+++ b/src/routes/register/+page.svelte
@@ -0,0 +1,10 @@
+
+
diff --git a/src/routes/register/register-form.svelte b/src/routes/register/register-form.svelte
new file mode 100644
index 0000000..28336a9
--- /dev/null
+++ b/src/routes/register/register-form.svelte
@@ -0,0 +1,92 @@
+
+
+
+
+
+ 회원가입
+
+ Register a new account
+
+
+
+
+
+
+ {#if dev}
+
+ {/if}
+
diff --git a/src/routes/register/schema.ts b/src/routes/register/schema.ts
new file mode 100644
index 0000000..004a954
--- /dev/null
+++ b/src/routes/register/schema.ts
@@ -0,0 +1,25 @@
+import { z } from "zod";
+import {integer, text, timestamp} from "drizzle-orm/pg-core";
+
+export const formSchema = z.object({
+ // User ID (formerly 'user')
+ email: z.string()
+ .email("이메일주소 형식이 아닙니다.")
+ .trim(), // Remove leading/trailing whitespace
+
+ // Password
+ password: z.string()
+ .min(8, "최소 8자 이상이어야 합니다.")
+ .max(100, "최대 100자 이하이어야 합니다.") // Reasonable maximum length
+ .regex(/[a-z]/, "최소 하나의 소문자를 포함해야 합니다.")
+ .regex(/[A-Z]/, "최소 하나의 대문자를 포함해야 합니다.")
+ .regex(/[0-9]/, "최소 하나의 숫자를 포함해야 합니다.")
+ .regex(/[^a-zA-Z0-9]/, "최소 하나의 특수문자를 포함해야 합니다.") // For common special characters
+ .trim(),
+ passwordConfirm: z.string(),
+}).refine((data) => data.password === data.passwordConfirm, {
+ message: "비밀번호가 일치하지 않습니다",
+ path: ["passwordConfirm"], // passwordConfirm 필드에 에러를 표시
+});
+
+export type FormSchema = typeof formSchema;
\ No newline at end of file