From c2156f2cacb92653d49f7d92fb724fd46737f1a0 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 14 Feb 2026 00:01:16 +1300 Subject: [PATCH] Implemented public salt getting --- materialious/src/app.d.ts | 3 +- materialious/src/hooks.server.ts | 3 +- materialious/src/lib/backend.ts | 2 + materialious/src/lib/backendOnly/database.ts | 4 +- materialious/src/lib/backendOnly/user.ts | 42 ++++++++++++------- .../api/user/[userId]/public/+server.ts | 7 ++++ .../src/routes/api/user/login/+server.ts | 9 +--- 7 files changed, 40 insertions(+), 30 deletions(-) create mode 100644 materialious/src/routes/api/user/[userId]/public/+server.ts diff --git a/materialious/src/app.d.ts b/materialious/src/app.d.ts index 12f01340..88e2475a 100644 --- a/materialious/src/app.d.ts +++ b/materialious/src/app.d.ts @@ -1,11 +1,10 @@ -import type { User } from '$lib/backendOnly/user'; import type { IGetChallengeResponse } from 'youtubei.js'; declare global { namespace App { // interface Error {} interface Locals { - userBackend?: User; + userId: string; } // interface PageData {} // interface PageState {} diff --git a/materialious/src/hooks.server.ts b/materialious/src/hooks.server.ts index 4ee0fd64..71a50790 100644 --- a/materialious/src/hooks.server.ts +++ b/materialious/src/hooks.server.ts @@ -2,7 +2,6 @@ import { isOwnBackend } from '$lib/backend'; import { sequelize } from '$lib/backendOnly/database'; import { unsign } from 'cookie-signature'; import { env } from '$env/dynamic/private'; -import { User } from '$lib/backendOnly/user'; let sequelizeAuthenticated = false; export async function handle({ event, resolve }) { @@ -23,7 +22,7 @@ export async function handle({ event, resolve }) { if (signedUserId) { const userId = unsign(signedUserId, env.COOKIE_SECRET); if (userId) { - event.locals.userBackend = new User(userId); + event.locals.userId = userId; } } diff --git a/materialious/src/lib/backend.ts b/materialious/src/lib/backend.ts index 99eb30d8..9a5052d0 100644 --- a/materialious/src/lib/backend.ts +++ b/materialious/src/lib/backend.ts @@ -15,3 +15,5 @@ export function isOwnBackend(): IsOwnBackend | null { registrationAllowed: import.meta.env.VITE_REGISTRATION_ALLOWED === 'true' }; } + +async function backendLogin(username: string, password: string) {} diff --git a/materialious/src/lib/backendOnly/database.ts b/materialious/src/lib/backendOnly/database.ts index 6ce6727e..4b12218d 100644 --- a/materialious/src/lib/backendOnly/database.ts +++ b/materialious/src/lib/backendOnly/database.ts @@ -12,7 +12,7 @@ export interface UserTableModel extends Model { passwordHash: string; passwordSalt: string; created: Date; - subscriptionPasswordHash: string; + subscriptionPasswordSalt: string; } export const UserTable = sequelize.define('User', { @@ -38,7 +38,7 @@ export const UserTable = sequelize.define('User', { type: DataTypes.DATE, allowNull: false }, - subscriptionPasswordHash: { + subscriptionPasswordSalt: { type: DataTypes.STRING, allowNull: false } diff --git a/materialious/src/lib/backendOnly/user.ts b/materialious/src/lib/backendOnly/user.ts index fc8059ba..c0ae586d 100644 --- a/materialious/src/lib/backendOnly/user.ts +++ b/materialious/src/lib/backendOnly/user.ts @@ -1,22 +1,30 @@ import { UserTable, type ChannelSubscriptionModel, type UserTableModel } from './database'; import { Op } from 'sequelize'; import crypto from 'crypto'; +import { error } from '@sveltejs/kit'; export class User { - private userId: string; + private user: UserTableModel; - constructor(id: string) { - this.userId = id; + constructor(user: UserTableModel) { + this.user = user; } public get id() { - return this.userId; + return this.user.id; + } + + public get publicPasswordSalts() { + return { + subscriptionPasswordSalt: this.user.subscriptionPasswordSalt, + passwordSalt: this.user.passwordSalt + }; } private get userWhere() { return { where: { - [Op.or]: [{ id: this.userId }, { username: this.userId }] + [Op.or]: [{ id: this.user.id }, { username: this.user.username }] } }; } @@ -28,7 +36,7 @@ export class User { async subscriptions(): Promise { const subscriptions = await UserTable.findAll({ where: { - userId: this.userId + userId: this.user.id } }); @@ -44,22 +52,24 @@ export type CreateUser = { hash: string; salt: string; }; - subscriptionPasswordHash: string; + subscriptionPasswordSalt: string; }; export async function createUser(user: CreateUser): Promise { const id = crypto.randomUUID(); - await UserTable.create({ + const createdUser = { id, username: user.username, passwordHash: user.password.hash, passwordSalt: user.password.salt, created: new Date(), - subscriptionPasswordHash: user.subscriptionPasswordHash - }); + subscriptionPasswordSalt: user.subscriptionPasswordSalt + }; - return new User(id); + await UserTable.create(createdUser); + + return new User(createdUser as UserTableModel); } export async function getUser(identifier: string): Promise { @@ -70,10 +80,10 @@ export async function getUser(identifier: string): Promise { }); if (!user) { - throw new Error('User does not exist'); + throw error(404); } - return new User((user as UserTableModel).id); + return new User(user as UserTableModel); } export async function authenticateUser(username: string, passwordHash: string): Promise { @@ -84,7 +94,7 @@ export async function authenticateUser(username: string, passwordHash: string): }); if (!user) { - throw new Error('User does not exist'); + throw error(404); } const userModel = user as UserTableModel; @@ -99,8 +109,8 @@ export async function authenticateUser(username: string, passwordHash: string): textEncoder.encode(userModel.passwordHash) ) ) { - return new User(userModel.id); + return new User(userModel as UserTableModel); } - throw new Error('User does not exist'); + throw error(404); } diff --git a/materialious/src/routes/api/user/[userId]/public/+server.ts b/materialious/src/routes/api/user/[userId]/public/+server.ts new file mode 100644 index 00000000..d4e5e958 --- /dev/null +++ b/materialious/src/routes/api/user/[userId]/public/+server.ts @@ -0,0 +1,7 @@ +import { getUser } from '$lib/backendOnly/user'; +import { json } from '@sveltejs/kit'; + +export async function GET({ locals }) { + const user = await getUser(locals.userId); + return json(user.publicPasswordSalts); +} diff --git a/materialious/src/routes/api/user/login/+server.ts b/materialious/src/routes/api/user/login/+server.ts index 71995810..67d62e8b 100644 --- a/materialious/src/routes/api/user/login/+server.ts +++ b/materialious/src/routes/api/user/login/+server.ts @@ -14,14 +14,7 @@ export async function POST({ request, cookies }) { if (!userLogin.success) throw error(401); - let userModel: User | undefined; - try { - userModel = await authenticateUser(userLogin.data.username, userLogin.data.passwordHash); - } catch { - // Handle outside of catch - } - - if (!userModel) throw error(401); + const userModel = await authenticateUser(userLogin.data.username, userLogin.data.passwordHash); cookies.set('userid', sign(userModel.id, env.COOKIE_SECRET), { httpOnly: true,