From 5a9f83673769b50f57cc3dd7e444e69aeafa0498 Mon Sep 17 00:00:00 2001 From: Sean Morley Date: Fri, 24 May 2024 19:26:13 +0000 Subject: [PATCH] Add user to admin page --- src/routes/login/+page.server.ts | 10 +- src/routes/settings/admin/+page.server.ts | 119 +++++++++++++++++++++- src/routes/settings/admin/+page.svelte | 51 +++------- src/routes/setup/+page.server.ts | 10 +- src/routes/signup/+page.server.ts | 9 +- 5 files changed, 156 insertions(+), 43 deletions(-) diff --git a/src/routes/login/+page.server.ts b/src/routes/login/+page.server.ts index 4f8cc12..dd2036a 100644 --- a/src/routes/login/+page.server.ts +++ b/src/routes/login/+page.server.ts @@ -18,7 +18,15 @@ export const load: PageServerLoad = async (event) => { export const actions: Actions = { default: async (event) => { const formData = await event.request.formData(); - const username = formData.get("username"); + const formUsername = formData.get("username"); + + let username = formUsername?.toString().toLocaleLowerCase(); + + if (typeof formUsername !== "string") { + return error(400, { + message: "Invalid username", + }); + } const password = formData.get("password"); if (!username || !password) { diff --git a/src/routes/settings/admin/+page.server.ts b/src/routes/settings/admin/+page.server.ts index 78a5376..3a2a8cb 100644 --- a/src/routes/settings/admin/+page.server.ts +++ b/src/routes/settings/admin/+page.server.ts @@ -1,4 +1,10 @@ -import { error, redirect, type Actions, type Handle } from "@sveltejs/kit"; +import { + error, + fail, + redirect, + type Actions, + type Handle, +} from "@sveltejs/kit"; import type { PageServerLoad } from "./$types"; import { db } from "$lib/db/db.server"; import { @@ -8,8 +14,10 @@ import { userTable, userVisitedWorldTravel, } from "$lib/db/schema"; -import type { DatabaseUser } from "$lib/server/auth"; +import { lucia, type DatabaseUser } from "$lib/server/auth"; import { count, eq } from "drizzle-orm"; +import { generateId } from "lucia"; +import { Argon2id } from "oslo/password"; export const load: PageServerLoad = async (event) => { let users: DatabaseUser[] = []; @@ -86,4 +94,111 @@ export const actions: Actions = { }; } }, + adduser: async (event) => { + const formData = await event.request.formData(); + const formUsername = formData.get("username"); + let username = formUsername?.toString().toLocaleLowerCase(); + + if (typeof formUsername !== "string") { + return fail(400, { message: "Invalid username" }); + } + const password = formData.get("password"); + const firstName = formData.get("first_name"); + const lastName = formData.get("last_name"); + // username must be between 4 ~ 31 characters, and only consists of lowercase letters, 0-9, -, and _ + // keep in mind some database (e.g. mysql) are case insensitive + + if (!event.locals.user) { + return redirect(302, "/"); + } + // check all to make sure all fields are provided + if (!username || !password || !firstName || !lastName) { + return fail(400, { message: "All fields are required" }); + } + + if (!event.locals.user || event.locals.user.role !== "admin") { + return fail(403, { + message: "You are not authorized to perform this action", + }); + } + + if ( + typeof username !== "string" || + username.length < 3 || + username.length > 31 || + !/^[a-zA-Z0-9_-]+$/.test(username) + ) { + return fail(400, { + message: "Invalid username", + }); + } + if ( + typeof password !== "string" || + password.length < 6 || + password.length > 255 + ) { + return fail(400, { + message: "Invalid password", + }); + } + + if ( + typeof firstName !== "string" || + firstName.length < 1 || + firstName.length > 255 + ) { + return fail(400, { + message: "Invalid first name", + }); + } + + if ( + typeof lastName !== "string" || + lastName.length < 1 || + lastName.length > 255 + ) { + return fail(400, { + message: "Invalid last name", + }); + } + + const usernameTaken = await db + .select() + .from(userTable) + .where(eq(userTable.username, username)) + .limit(1) + .then((results) => results[0] as unknown as DatabaseUser | undefined); + + if (usernameTaken) { + return fail(400, { + message: "Username already taken", + }); + } + + const userId = generateId(15); + const hashedPassword = await new Argon2id().hash(password); + + await db + .insert(userTable) + .values({ + id: userId, + username: username, + first_name: firstName, + last_name: lastName, + hashed_password: hashedPassword, + signup_date: new Date(), + role: "admin", + last_login: new Date(), + } as DatabaseUser) + .execute(); + + const session = await lucia.createSession(userId, {}); + const sessionCookie = lucia.createSessionCookie(session.id); + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: ".", + ...sessionCookie.attributes, + }); + + return { success: true }; + }, }; diff --git a/src/routes/settings/admin/+page.svelte b/src/routes/settings/admin/+page.svelte index 80d56fd..b5ee4a8 100644 --- a/src/routes/settings/admin/+page.svelte +++ b/src/routes/settings/admin/+page.svelte @@ -6,14 +6,15 @@ import { type SubmitFunction } from "@sveltejs/kit"; import type { DatabaseUser } from "lucia"; import UserCard from "$lib/components/UserCard.svelte"; - let errors: { message?: string } = {}; - let message: { message?: string } = {}; + let username: string = ""; let first_name: string = ""; let last_name: string = ""; let password: string = ""; import ConfirmModal from "$lib/components/ConfirmModal.svelte"; + let errors: { addUser?: string } = {}; + let sucess: { addUser?: string } = {}; let isModalOpen = false; async function clearAllSessions() { @@ -34,30 +35,7 @@ isModalOpen = false; } - const addUser: SubmitFunction = async ({ formData, action, cancel }) => { - const response = await fetch(action, { - method: "POST", - body: formData, - }); - - if (response.ok) { - console.log("User Added Successfully!"); - errors = {}; - username = ""; - first_name = ""; - last_name = ""; - password = ""; - cancel(); - return; - } - - const { type, error } = await response.json(); - if (type === "error") { - errors = { message: error.message }; - } - console.log(errors); - cancel(); - }; + let form = $page.form; let visitCount = $page.data.visitCount[0].count; let userCount = $page.data.userCount[0].count; @@ -71,12 +49,7 @@

Add User

-
+
+ {#if $page.form?.message} +
+ {$page.form?.message} +
+ {/if} + {#if $page.form?.success} +
User added successfully!
+ {/if}
-{#if errors.message} -
- {errors.message} -
-{/if} -

Session Managment