diff --git a/components/entryEditor.vue b/components/entryEditor.vue index 4f2bda2..49a0651 100644 --- a/components/entryEditor.vue +++ b/components/entryEditor.vue @@ -7,13 +7,14 @@ type optionalMap = Optional extends true ? undefined : string | number export type fieldDefinition = { key: string, label?: string, - type: "text" | "password" | "number", + type: "text" | "number", optional?: Optional, value?: optionalMap, } const props = defineProps<{ fields: Array, + modelValue?: any, }>(); // eslint-disable-next-line func-call-spacing diff --git a/pages/firstRun.vue b/pages/firstRun.vue index 238ef05..7e8b54d 100644 --- a/pages/firstRun.vue +++ b/pages/firstRun.vue @@ -9,7 +9,7 @@ import Alerts, { type AlertData } from '~/components/alerts.vue'; const editorFields: Array = [ { key: "username", type: "text", label: "Username", optional: false }, - { key: "password", type: "password", label: "Password", optional: false }, + { key: "password", type: "text", label: "Password", optional: false }, { key: "email", type: "text", label: "email", optional: false }, ]; diff --git a/schema.prisma b/schema.prisma index 52e3f86..a507bf7 100644 --- a/schema.prisma +++ b/schema.prisma @@ -20,14 +20,12 @@ model User { } model Session { - id BigInt @id @default(dbgenerated("(((unix_timestamp() * 1000) * pow(2,22)) + floor((rand() * pow(2,12))))")) @db.UnsignedBigInt - userId BigInt @map("user") @db.UnsignedBigInt - sessionToken Bytes @db.Binary(64) - expiry_date DateTime? @default(dbgenerated("(now() + interval 30 day)")) @db.Timestamp(0) - user User @relation(fields: [userId], references: [id]) + id BigInt @id @default(dbgenerated("(((unix_timestamp() * 1000) * pow(2,22)) + floor((rand() * pow(2,12))))")) @db.UnsignedBigInt + userId BigInt @map("user") @db.UnsignedBigInt + expiry_date DateTime? @default(dbgenerated("(now() + interval 30 day)")) @db.Timestamp(0) + user User @relation(fields: [userId], references: [id]) @@index([userId], map: "user_idx") - @@index([sessionToken]) @@map("sessions") } diff --git a/server/api/firstRun.post.ts b/server/api/firstRun.post.ts index 70aa5a8..714be3b 100644 --- a/server/api/firstRun.post.ts +++ b/server/api/firstRun.post.ts @@ -24,7 +24,7 @@ export default defineEventHandler(async (e) => { if (typeof email !== "string") throw createError({ message: "email is not string", statusCode: 400 }); execSync("npx prisma db push --force-reset"); - await database.user.create({ + database.user.create({ data: { id: new Snowflake().state, username, diff --git a/server/api/login.post.ts b/server/api/login.post.ts index bb7e022..1b7f00d 100644 --- a/server/api/login.post.ts +++ b/server/api/login.post.ts @@ -4,7 +4,7 @@ import { defineEventHandler, getCookie, setCookie, readBody } from "h3"; import { database } from "../utils/database"; import { isString } from "../utils/isString"; import { cookieSettings } from "../utils/rootUtils"; -import SessionToken from "../utils/SessionToken"; +import Snowflake from "~/utils/snowflake"; import { createError } from "#imports"; @@ -40,11 +40,14 @@ export default defineEventHandler(async (e) => { if (account === null) throw createError({ statusCode: 400, message: "Invalid username or password." }); - const session = new SessionToken(account.id); + const sessionId = new Snowflake(); await database.session.create({ - data: session.toPrisma(), + data: { + id: sessionId.state, + userId: account.id, + }, }); - setCookie(e, "token", session.toString(), cookieSettings); - return { message: "Login successful", token: session.toString() }; + setCookie(e, "token", sessionId.toString(), cookieSettings); + return { message: "Login successful", token: sessionId.toString() }; }); diff --git a/server/middleware/auth.ts b/server/middleware/auth.ts index e07e947..fb91a7d 100644 --- a/server/middleware/auth.ts +++ b/server/middleware/auth.ts @@ -1,11 +1,9 @@ import { defineEventHandler, getCookie } from "h3"; -import SessionToken from "../utils/SessionToken"; +import { createError } from "#imports"; import { database } from "~/server/utils/database"; import getRequestingUser from "~/server/utils/getRequestingUser"; -import { createError } from "#imports"; - const endpointsWithoutAuth: string[] = [ "/dbtest", "/echo", @@ -39,10 +37,7 @@ export async function isAuthorised(token: string | undefined): Promise try { await database.session.findUniqueOrThrow({ where: { - ...SessionToken.fromString(token).toPrisma(), - expiry_date: { - gte: new Date(), - }, + id: BigInt(token), }, }); diff --git a/server/utils/SessionToken.ts b/server/utils/SessionToken.ts deleted file mode 100644 index 6a3129c..0000000 --- a/server/utils/SessionToken.ts +++ /dev/null @@ -1,49 +0,0 @@ -import crypto from "node:crypto"; -import { type Session } from "@prisma/client"; - -import Snowflake from "~/utils/snowflake"; - -/** Represents a Session token, without expiry data. */ -export default class SessionToken { - userId: bigint; - sessionId: bigint; - sessionToken: Buffer; - - constructor(userId: bigint, sessionId?: bigint, sessionToken?: Buffer) { - this.userId = userId; - this.sessionId = sessionId ?? new Snowflake().state; - this.sessionToken = sessionToken ?? crypto.randomBytes(64); - } - - /** Creates SessionToken from a string. - * @param string The strinct to create from. - * @returns The SessionToken object. - */ - static fromString(string: string): SessionToken { - const parameters = string.split("."); - return new SessionToken( - Buffer.from(parameters[0], "base64").readBigUInt64LE(), - Buffer.from(parameters[1], "base64").readBigUInt64LE(), - Buffer.from(parameters[2], "base64"), - ); - } - - toString(): string { - const stringUserId = Buffer.copyBytesFrom(new BigUint64Array([this.userId])).toString("base64"); - const stringSessionId = Buffer.copyBytesFrom(new BigUint64Array([this.sessionId])).toString("base64"); - const stringSessionToken = this.sessionToken.toString("base64"); - return `${stringUserId}.${stringSessionId}.${stringSessionToken}`; - } - - /** Returns this SessionToken as Prisma object. - * For use in where parameter. - * @returns this as prisma object. - */ - toPrisma(): Omit { - return { - id: this.sessionId, - userId: this.userId, - sessionToken: this.sessionToken, - }; - } -} diff --git a/server/utils/getRequestingUser.ts b/server/utils/getRequestingUser.ts index 60c4173..13ed3f9 100644 --- a/server/utils/getRequestingUser.ts +++ b/server/utils/getRequestingUser.ts @@ -1,7 +1,6 @@ import { getCookie, H3Event } from "h3"; import { database } from "./database"; -import SessionToken from "./SessionToken"; import { createError } from "#imports"; @@ -10,10 +9,7 @@ export default async function getRequestingUser(e: H3Event) { if (!cookie) throw createError("User not found"); const { user } = await database.session.findUnique({ where: { - ...SessionToken.fromString(cookie).toPrisma(), - expiry_date: { - gte: new Date(), - }, + id: BigInt(cookie), }, select: { user: {