mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Upgrade to v3 Lucia, change all auth layers, upgrade all dependencies, and update eslint.
This commit is contained in:
parent
2c6d8f2510
commit
b290f3092f
19 changed files with 836 additions and 516 deletions
|
|
@ -1,8 +1,19 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:svelte/recommended',
|
||||
'prettier'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: ['plugin:svelte/recommended'],
|
||||
plugins: ['@typescript-eslint'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
project: './tsconfig.json',
|
||||
extraFileExtensions: ['.svelte'] // This is a required setting in `@typescript-eslint/parser` v4.24.0.
|
||||
},
|
||||
ignorePatterns: ['*.cjs'],
|
||||
overrides: [
|
||||
{
|
||||
|
|
@ -14,15 +25,6 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
],
|
||||
settings: {
|
||||
'svelte3/typescript': () => require('typescript')
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
project: './tsconfig.json',
|
||||
extraFileExtensions: ['.svelte'] // This is a required setting in `@typescript-eslint/parser` v4.24.0.
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
|
|
|
|||
36
package.json
36
package.json
|
|
@ -27,15 +27,16 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@melt-ui/pp": "^0.1.4",
|
||||
"@melt-ui/svelte": "^0.57.3",
|
||||
"@playwright/test": "^1.40.1",
|
||||
"@resvg/resvg-js": "^2.4.1",
|
||||
"@sveltejs/adapter-auto": "^2.1.1",
|
||||
"@sveltejs/adapter-vercel": "^3.1.0",
|
||||
"@sveltejs/kit": "^1.27.6",
|
||||
"@sveltejs/kit": "^1.30.3",
|
||||
"@types/cookie": "^0.5.4",
|
||||
"@types/node": "^18.19.2",
|
||||
"@typescript-eslint/eslint-plugin": "^6.13.2",
|
||||
"@typescript-eslint/parser": "^6.13.2",
|
||||
"@types/node": "^18.19.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
||||
"@typescript-eslint/parser": "^6.14.0",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"eslint": "^8.55.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
|
|
@ -46,23 +47,23 @@
|
|||
"postcss-import": "^15.1.0",
|
||||
"postcss-load-config": "^4.0.2",
|
||||
"postcss-preset-env": "^9.3.0",
|
||||
"prettier": "^3.1.0",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.1.2",
|
||||
"prisma": "^5.6.0",
|
||||
"prisma": "^5.7.0",
|
||||
"sass": "^1.65.1",
|
||||
"satori": "^0.10.11",
|
||||
"satori-html": "^0.3.2",
|
||||
"svelte": "^4.2.8",
|
||||
"svelte-check": "^3.6.2",
|
||||
"svelte-meta-tags": "^3.1.0",
|
||||
"svelte-preprocess": "^5.1.1",
|
||||
"svelte-preprocess": "^5.1.2",
|
||||
"svelte-sequential-preprocessor": "^2.0.1",
|
||||
"sveltekit-flash-message": "^2.2.2",
|
||||
"sveltekit-superforms": "^1.11.0",
|
||||
"sveltekit-superforms": "^1.12.0",
|
||||
"tailwindcss": "^3.3.6",
|
||||
"ts-node": "^10.9.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"tslib": "^2.6.1",
|
||||
"typescript": "^5.3.2",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^4.5.1",
|
||||
"vitest": "^0.34.6",
|
||||
"zod": "^3.22.4"
|
||||
|
|
@ -76,13 +77,11 @@
|
|||
"@fontsource/fira-mono": "^4.5.10",
|
||||
"@iconify-icons/line-md": "^1.2.26",
|
||||
"@iconify-icons/mdi": "^1.2.47",
|
||||
"@lucia-auth/adapter-mysql": "^2.1.0",
|
||||
"@lucia-auth/adapter-prisma": "^3.0.2",
|
||||
"@lucia-auth/adapter-prisma": "4.0.0-beta.7",
|
||||
"@lukeed/uuid": "^2.0.1",
|
||||
"@melt-ui/svelte": "^0.57.3",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@prisma/client": "^5.6.0",
|
||||
"@sentry/sveltekit": "^7.85.0",
|
||||
"@prisma/client": "^5.7.0",
|
||||
"@sentry/sveltekit": "^7.88.0",
|
||||
"@types/feather-icons": "^4.29.4",
|
||||
"@vercel/og": "^0.5.13",
|
||||
"bits-ui": "^0.0.27",
|
||||
|
|
@ -96,15 +95,16 @@
|
|||
"iconify-icon": "^1.0.8",
|
||||
"just-kebab-case": "^4.2.0",
|
||||
"loader": "^2.1.1",
|
||||
"lucia": "^2.7.4",
|
||||
"lucia": "3.0.0-beta.12",
|
||||
"lucide-svelte": "^0.256.1",
|
||||
"open-props": "^1.6.13",
|
||||
"open-props": "^1.6.16",
|
||||
"oslo": "^0.24.0",
|
||||
"radix-svelte": "^0.9.0",
|
||||
"svelte-french-toast": "^1.2.0",
|
||||
"svelte-lazy-loader": "^1.0.0",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwind-variants": "^0.1.18",
|
||||
"tailwindcss-animate": "^1.0.6",
|
||||
"zod-to-json-schema": "^3.22.1"
|
||||
"zod-to-json-schema": "^3.22.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
794
pnpm-lock.yaml
794
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -36,52 +36,41 @@ model UserRole {
|
|||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
username String @unique
|
||||
email String? @unique
|
||||
firstName String?
|
||||
lastName String?
|
||||
roles UserRole[]
|
||||
verified Boolean @default(false)
|
||||
receiveEmail Boolean @default(false)
|
||||
token String? @unique
|
||||
collection Collection?
|
||||
wishlist Wishlist?
|
||||
list List[]
|
||||
theme String @default("system")
|
||||
created_at DateTime @default(now()) @db.Timestamp(6)
|
||||
updated_at DateTime @updatedAt @db.Timestamp(6)
|
||||
auth_session Session[]
|
||||
auth_key Key[]
|
||||
id String @id @default(cuid())
|
||||
username String @unique
|
||||
hashed_password String?
|
||||
email String? @unique
|
||||
firstName String?
|
||||
lastName String?
|
||||
roles UserRole[]
|
||||
verified Boolean @default(false)
|
||||
receiveEmail Boolean @default(false)
|
||||
collection Collection?
|
||||
wishlist Wishlist?
|
||||
list List[]
|
||||
theme String @default("system")
|
||||
created_at DateTime @default(now()) @db.Timestamp(6)
|
||||
updated_at DateTime @updatedAt @db.Timestamp(6)
|
||||
sessions Session[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @unique
|
||||
user_id String
|
||||
active_expires BigInt
|
||||
idle_expires BigInt
|
||||
user User @relation(references: [id], fields: [user_id], onDelete: Cascade)
|
||||
id String @id @unique
|
||||
userId String
|
||||
country String
|
||||
expiresAt DateTime
|
||||
user User @relation(references: [id], fields: [userId], onDelete: Cascade)
|
||||
|
||||
@@index([user_id])
|
||||
@@index([userId])
|
||||
@@map("sessions")
|
||||
}
|
||||
|
||||
model Key {
|
||||
id String @id @unique
|
||||
hashed_password String?
|
||||
user_id String
|
||||
user User @relation(references: [id], fields: [user_id], onDelete: Cascade)
|
||||
|
||||
@@index([user_id])
|
||||
@@map("keys")
|
||||
}
|
||||
|
||||
model Collection {
|
||||
id String @id @default(cuid())
|
||||
user_id String @unique
|
||||
user User @relation(references: [id], fields: [user_id])
|
||||
id String @id @default(cuid())
|
||||
user_id String @unique
|
||||
user User @relation(references: [id], fields: [user_id])
|
||||
items CollectionItem[]
|
||||
|
||||
@@index([user_id])
|
||||
|
|
|
|||
18
src/app.d.ts
vendored
18
src/app.d.ts
vendored
|
|
@ -14,7 +14,7 @@ declare global {
|
|||
}
|
||||
interface Locals {
|
||||
auth: import('lucia').AuthRequest;
|
||||
user: Lucia.UserAttributes;
|
||||
user: import('lucia').User | null;
|
||||
prisma: PrismaClient;
|
||||
startTimer: number;
|
||||
error: string;
|
||||
|
|
@ -43,14 +43,14 @@ declare global {
|
|||
// interface Error {}
|
||||
// interface Platform {}
|
||||
|
||||
/// <reference types="lucia" />
|
||||
declare global {
|
||||
namespace Lucia {
|
||||
type Auth = import('$lib/server/lucia').Auth;
|
||||
type DatabaseUserAttributes = User;
|
||||
type DatabaseSessionAttributes = {};
|
||||
}
|
||||
}
|
||||
// /// <reference types="lucia" />
|
||||
// declare global {
|
||||
// namespace Lucia {
|
||||
// type Auth = import('$lib/server/lucia').Auth;
|
||||
// type DatabaseUserAttributes = User;
|
||||
// type DatabaseSessionAttributes = {};
|
||||
// }
|
||||
// }
|
||||
|
||||
// THIS IS IMPORTANT!!!
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import * as Sentry from '@sentry/sveltekit';
|
|||
import { sequence } from '@sveltejs/kit/hooks';
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
import { dev } from '$app/environment';
|
||||
import { auth } from '$lib/server/lucia';
|
||||
import { lucia } from '$lib/server/auth';
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://742e43279df93a3c4a4a78c12eb1f879@o4506057768632320.ingest.sentry.io/4506057770401792',
|
||||
|
|
@ -14,22 +14,31 @@ export const authentication: Handle = async function ({ event, resolve }) {
|
|||
const startTimer = Date.now();
|
||||
event.locals.startTimer = startTimer;
|
||||
|
||||
event.locals.auth = auth.handleRequest(event);
|
||||
if (event?.locals?.auth) {
|
||||
try {
|
||||
const session = await event.locals.auth.validate();
|
||||
event.locals.user = session?.user;
|
||||
// if (event.route.id?.startsWith('/(protected)')) {
|
||||
// if (!user) throw redirect(302, '/sign-in');
|
||||
// if (!user.verified) throw redirect(302, '/verify/email');
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error('Error validating user', error);
|
||||
}
|
||||
} else {
|
||||
console.log('auth empty');
|
||||
const ip = event.request.headers.get('x-forwarded-for') as string || event.getClientAddress();
|
||||
const country = event.request.headers.get('x-vercel-ip-country') as string || 'unknown';
|
||||
event.locals.session = {
|
||||
ip,
|
||||
country
|
||||
};
|
||||
|
||||
const sessionId = event.cookies.get(lucia.sessionCookieName);
|
||||
if (!sessionId) {
|
||||
event.locals.user = null;
|
||||
return resolve(event);
|
||||
}
|
||||
return await resolve(event);
|
||||
|
||||
const { session, user } = await lucia.validateSession(sessionId);
|
||||
if (session && session.fresh) {
|
||||
const sessionCookie = lucia.createSessionCookie(session.id);
|
||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
||||
}
|
||||
if (!session) {
|
||||
const sessionCookie = lucia.createBlankSessionCookie();
|
||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
||||
}
|
||||
event.locals.user = user;
|
||||
|
||||
return resolve(event);
|
||||
};
|
||||
|
||||
export const handle: Handle = sequence(sequence(Sentry.sentryHandle(), authentication));
|
||||
|
|
|
|||
54
src/lib/server/auth.ts
Normal file
54
src/lib/server/auth.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// lib/server/lucia.ts
|
||||
import { Lucia, TimeSpan } from 'lucia';
|
||||
import { PrismaAdapter } from '@lucia-auth/adapter-prisma';
|
||||
import { dev } from '$app/environment';
|
||||
import prisma_client from '$lib/prisma';
|
||||
import { webcrypto } from "node:crypto";
|
||||
|
||||
globalThis.crypto = webcrypto as Crypto;
|
||||
|
||||
const adapter = new PrismaAdapter(prisma_client.session, prisma_client.user);
|
||||
|
||||
export const lucia = new Lucia(adapter, {
|
||||
getSessionAttributes: (attributes) => {
|
||||
return {
|
||||
country: attributes.country,
|
||||
};
|
||||
},
|
||||
getUserAttributes: (attributes) => {
|
||||
return {
|
||||
username: attributes.username,
|
||||
email: attributes.email,
|
||||
firstName: attributes.firstName,
|
||||
lastName: attributes.lastName,
|
||||
theme: attributes.theme
|
||||
};
|
||||
},
|
||||
sessionExpiresIn: new TimeSpan(30, "d"), // 30 days
|
||||
sessionCookie: {
|
||||
name: 'session',
|
||||
expires: false, // session cookies have very long lifespan (2 years)
|
||||
attributes: {
|
||||
// set to `true` when using HTTPS
|
||||
secure: !dev,
|
||||
sameSite: 'strict',
|
||||
domain: dev ? 'localhost' : 'boredgame.vercel.app',
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
declare module "lucia" {
|
||||
interface Register {
|
||||
Lucia: typeof lucia;
|
||||
}
|
||||
interface DatabaseSessionAttributes {
|
||||
country: string;
|
||||
}
|
||||
interface DatabaseUserAttributes {
|
||||
username: string;
|
||||
email: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
theme: string;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// lib/server/lucia.ts
|
||||
import { lucia } from 'lucia';
|
||||
import { sveltekit } from 'lucia/middleware';
|
||||
import { prisma } from '@lucia-auth/adapter-prisma';
|
||||
import { dev } from '$app/environment';
|
||||
import prisma_client from '$lib/prisma';
|
||||
|
||||
export const auth = lucia({
|
||||
env: dev ? 'DEV' : 'PROD',
|
||||
middleware: sveltekit(),
|
||||
adapter: prisma(prisma_client),
|
||||
getUserAttributes: (databaseUser) => {
|
||||
return {
|
||||
username: databaseUser.username,
|
||||
email: databaseUser.email,
|
||||
firstName: databaseUser.firstName,
|
||||
lastName: databaseUser.lastName,
|
||||
verified: databaseUser.verified,
|
||||
receiveEmail: databaseUser.receiveEmail,
|
||||
token: databaseUser.token,
|
||||
theme: databaseUser.theme
|
||||
};
|
||||
},
|
||||
experimental: {
|
||||
debugMode: false
|
||||
}
|
||||
});
|
||||
|
||||
export type Auth = typeof auth;
|
||||
3
src/lib/utils/verifyEmail.ts
Normal file
3
src/lib/utils/verifyEmail.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export function isValidEmail(email: string): boolean {
|
||||
return /.+@.+/.test(email);
|
||||
}
|
||||
|
|
@ -6,8 +6,8 @@ import { search_schema } from '$lib/zodValidation.js';
|
|||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
const user = locals.user;
|
||||
if (!user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
|||
try {
|
||||
let collection = await prisma.collection.findUnique({
|
||||
where: {
|
||||
user_id: session.user.userId
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
console.log('collection', collection);
|
||||
|
|
@ -103,11 +103,11 @@ export const actions: Actions = {
|
|||
const { params, locals, request } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!event.locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
|
||||
const user = event.locals.user;
|
||||
let game = await prisma.game.findUnique({
|
||||
where: {
|
||||
id: form.data.id
|
||||
|
|
@ -127,7 +127,7 @@ export const actions: Actions = {
|
|||
try {
|
||||
const collection = await prisma.collection.findUnique({
|
||||
where: {
|
||||
user_id: session.user.userId
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -154,17 +154,15 @@ export const actions: Actions = {
|
|||
},
|
||||
// Create new wishlist
|
||||
create: async ({ params, locals, request }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
return error(405, 'Method not allowed');
|
||||
},
|
||||
// Delete a wishlist
|
||||
delete: async ({ params, locals, request }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
return error(405, 'Method not allowed');
|
||||
},
|
||||
|
|
@ -173,9 +171,8 @@ export const actions: Actions = {
|
|||
const { params, locals, request } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
|
||||
let game = await prisma.game.findUnique({
|
||||
|
|
@ -192,7 +189,7 @@ export const actions: Actions = {
|
|||
try {
|
||||
const collection = await prisma.collection.findUnique({
|
||||
where: {
|
||||
user_id: session.user.userId
|
||||
user_id: locals.user.id
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { redirect } from '@sveltejs/kit';
|
||||
import { fail, redirect } from '@sveltejs/kit';
|
||||
import prisma from '$lib/prisma';
|
||||
|
||||
export async function load({ locals }) {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { superValidate } from 'sveltekit-superforms/server';
|
|||
import prisma from '$lib/prisma';
|
||||
|
||||
export async function load({ params, locals }) {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
const user = locals.user;
|
||||
if (!user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ export async function load({ params, locals }) {
|
|||
where: {
|
||||
id: params.id,
|
||||
AND: {
|
||||
user_id: session.userId
|
||||
user_id: user.id
|
||||
}
|
||||
},
|
||||
include: {
|
||||
|
|
@ -46,11 +46,11 @@ export const actions: Actions = {
|
|||
const { params, locals, request } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
|
||||
|
||||
let game = await prisma.game.findUnique({
|
||||
where: {
|
||||
id: form.id
|
||||
|
|
@ -74,7 +74,7 @@ export const actions: Actions = {
|
|||
}
|
||||
});
|
||||
|
||||
if (wishlist?.user_id !== session.userId) {
|
||||
if (wishlist?.user_id !== locals.user.id) {
|
||||
return fail(401, {
|
||||
message: 'Unauthorized'
|
||||
});
|
||||
|
|
@ -103,23 +103,20 @@ export const actions: Actions = {
|
|||
},
|
||||
// Create new wishlist
|
||||
create: async ({ params, locals, request }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
},
|
||||
// Delete a wishlist
|
||||
delete: async ({ params, locals, request }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
},
|
||||
// Remove game from a wishlist
|
||||
remove: async ({ params, locals, request }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { fail, redirect, type Actions } from '@sveltejs/kit';
|
||||
import { message, setError, superValidate } from 'sveltekit-superforms/server';
|
||||
import { LuciaError } from 'lucia';
|
||||
// import { LuciaError } from 'lucia';
|
||||
import { userSchema } from '$lib/config/zod-schemas';
|
||||
import { auth } from '$lib/server/lucia.js';
|
||||
import { Lucia } from '$lib/server/auth.js';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import prisma from '$lib/prisma';
|
||||
|
||||
const profileSchema = userSchema.pick({
|
||||
firstName: true,
|
||||
|
|
@ -14,13 +15,12 @@ const profileSchema = userSchema.pick({
|
|||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
const form = await superValidate(event, profileSchema);
|
||||
const session = await event.locals.auth.validate();
|
||||
|
||||
if (!session) {
|
||||
if (!event.locals.user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
|
||||
const { user } = session;
|
||||
const { user } = event.locals;
|
||||
|
||||
form.data = {
|
||||
firstName: user.firstName,
|
||||
|
|
@ -42,25 +42,29 @@ export const actions: Actions = {
|
|||
form
|
||||
});
|
||||
}
|
||||
if (!event.locals.user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('updating profile');
|
||||
const session = await event.locals.auth.validate();
|
||||
|
||||
if (!session) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
const user = event.locals.user;
|
||||
|
||||
const user = session.user;
|
||||
|
||||
auth.updateUserAttributes(user.userId, {
|
||||
firstName: form.data.firstName,
|
||||
lastName: form.data.lastName,
|
||||
email: form.data.email,
|
||||
username: form.data.username
|
||||
await prisma.user.update({
|
||||
where: {
|
||||
id: user.id
|
||||
},
|
||||
data: {
|
||||
firstName: form.data.firstName,
|
||||
lastName: form.data.lastName,
|
||||
email: form.data.email,
|
||||
username: form.data.username
|
||||
}
|
||||
});
|
||||
|
||||
if (user.email !== form.data.email) {
|
||||
// Send email to confirm new email?
|
||||
// auth.update
|
||||
// await locals.prisma.key.update({
|
||||
// where: {
|
||||
|
|
@ -75,7 +79,7 @@ export const actions: Actions = {
|
|||
// });
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof LuciaError && e.message === `AUTH_INVALID_USER_ID`) {
|
||||
if (e.message === `AUTH_INVALID_USER_ID`) {
|
||||
// invalid user id
|
||||
console.error(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,17 +4,16 @@ import prisma from '$lib/prisma';
|
|||
import { modifyListGameSchema } from '$lib/config/zod-schemas.js';
|
||||
|
||||
export async function load({ params, locals }) {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
if (!locals.user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
|
||||
console.log('Wishlist load User id', session.user);
|
||||
console.log('Wishlist load User id', locals.user.id);
|
||||
|
||||
try {
|
||||
let wishlist = await prisma.wishlist.findUnique({
|
||||
const wishlist = await prisma.wishlist.findUnique({
|
||||
where: {
|
||||
user_id: session?.user?.userId
|
||||
user_id: locals.user.id
|
||||
},
|
||||
include: {
|
||||
items: {
|
||||
|
|
@ -49,16 +48,15 @@ export async function load({ params, locals }) {
|
|||
export const actions: Actions = {
|
||||
// Add game to a wishlist
|
||||
add: async (event) => {
|
||||
const { params, locals, request } = event;
|
||||
const { locals } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
|
||||
try {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
if (!locals.user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
|
||||
let game = await prisma.game.findUnique({
|
||||
const game = await prisma.game.findUnique({
|
||||
where: {
|
||||
id: form.data.id
|
||||
}
|
||||
|
|
@ -77,7 +75,7 @@ export const actions: Actions = {
|
|||
if (game) {
|
||||
const wishlist = await prisma.wishlist.findUnique({
|
||||
where: {
|
||||
user_id: session.user.userId
|
||||
user_id: locals.user.id
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -103,33 +101,30 @@ export const actions: Actions = {
|
|||
}
|
||||
},
|
||||
// Create new wishlist
|
||||
create: async ({ params, locals, request }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
create: async ({ locals }) => {
|
||||
if (!locals.user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
return error(405, 'Method not allowed');
|
||||
},
|
||||
// Delete a wishlist
|
||||
delete: async ({ params, locals, request }) => {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
delete: async ({ locals }) => {
|
||||
if (!locals.user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
return error(405, 'Method not allowed');
|
||||
},
|
||||
// Remove game from a wishlist
|
||||
remove: async (event) => {
|
||||
const { params, locals, request } = event;
|
||||
const { locals } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
|
||||
try {
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
if (!locals.user) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
|
||||
let game = await prisma.game.findUnique({
|
||||
const game = await prisma.game.findUnique({
|
||||
where: {
|
||||
id: form.data.id
|
||||
}
|
||||
|
|
@ -148,7 +143,7 @@ export const actions: Actions = {
|
|||
if (game) {
|
||||
const wishlist = await prisma.wishlist.findUnique({
|
||||
where: {
|
||||
user_id: session.user.userId
|
||||
user_id: locals.user.id
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export const load: PageServerLoad = async ({ params, locals, fetch }) => {
|
|||
if (user) {
|
||||
wishlist = await prisma.wishlist.findUnique({
|
||||
where: {
|
||||
user_id: user.userId
|
||||
user_id: user.id
|
||||
},
|
||||
include: {
|
||||
items: {
|
||||
|
|
@ -81,7 +81,7 @@ export const load: PageServerLoad = async ({ params, locals, fetch }) => {
|
|||
|
||||
collection = await prisma.collection.findUnique({
|
||||
where: {
|
||||
user_id: user.userId
|
||||
user_id: user.id
|
||||
},
|
||||
include: {
|
||||
items: {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import { fail, type Actions } from '@sveltejs/kit';
|
|||
import { setError, superValidate } from 'sveltekit-superforms/server';
|
||||
import { redirect } from 'sveltekit-flash-message/server';
|
||||
import prisma from '$lib/prisma';
|
||||
import { auth } from '$lib/server/lucia';
|
||||
import { lucia } from '$lib/server/auth';
|
||||
import { Argon2id } from 'oslo/password';
|
||||
import { userSchema } from '$lib/config/zod-schemas';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
|
|
@ -15,11 +16,11 @@ export const load: PageServerLoad = async (event) => {
|
|||
const form = await superValidate(event, signInSchema);
|
||||
|
||||
console.log('login load event', event);
|
||||
const session = await event.locals.auth.validate();
|
||||
if (session) {
|
||||
if (event.locals.user) {
|
||||
const message = { type: 'info', message: 'You are already signed in' } as const;
|
||||
throw redirect('/', message, event);
|
||||
}
|
||||
|
||||
return {
|
||||
form
|
||||
};
|
||||
|
|
@ -27,6 +28,7 @@ export const load: PageServerLoad = async (event) => {
|
|||
|
||||
export const actions: Actions = {
|
||||
default: async (event) => {
|
||||
const { cookies, locals } = event;
|
||||
const form = await superValidate(event, signInSchema);
|
||||
|
||||
if (!form.valid) {
|
||||
|
|
@ -36,56 +38,63 @@ export const actions: Actions = {
|
|||
});
|
||||
}
|
||||
|
||||
let session;
|
||||
let sessionCookie;
|
||||
try {
|
||||
const key = await auth.useKey('username', form.data.username, form.data.password);
|
||||
const session = await auth.createSession({
|
||||
userId: key.userId,
|
||||
attributes: {}
|
||||
});
|
||||
event.locals.auth.setSession(session);
|
||||
const password = form.data.password;
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: session.user.userId
|
||||
},
|
||||
include: {
|
||||
roles: {
|
||||
select: {
|
||||
role: true
|
||||
}
|
||||
}
|
||||
username: form.data.username
|
||||
}
|
||||
});
|
||||
if (user) {
|
||||
await prisma.collection.upsert({
|
||||
where: {
|
||||
user_id: user.id
|
||||
},
|
||||
create: {
|
||||
user_id: user.id
|
||||
},
|
||||
update: {
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
await prisma.wishlist.upsert({
|
||||
where: {
|
||||
user_id: user.id
|
||||
},
|
||||
create: {
|
||||
user_id: user.id
|
||||
},
|
||||
update: {
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
|
||||
if (!user || !user.hashed_password) {
|
||||
form.data.password = '';
|
||||
return setError(form, '', 'Your username or password is incorrect.');
|
||||
}
|
||||
|
||||
const validPassword = await new Argon2id().verify(user.hashed_password, password);
|
||||
if (!validPassword) {
|
||||
form.data.password = '';
|
||||
return setError(form, '', 'Your username or password is incorrect.');
|
||||
}
|
||||
|
||||
session = await lucia.createSession(user.id, {
|
||||
country: locals.session.ip,
|
||||
});
|
||||
sessionCookie = lucia.createSessionCookie(session.id);
|
||||
|
||||
await prisma.collection.upsert({
|
||||
where: {
|
||||
user_id: user.id
|
||||
},
|
||||
create: {
|
||||
user_id: user.id
|
||||
},
|
||||
update: {
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
await prisma.wishlist.upsert({
|
||||
where: {
|
||||
user_id: user.id
|
||||
},
|
||||
create: {
|
||||
user_id: user.id
|
||||
},
|
||||
update: {
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// TODO: need to return error message to the client
|
||||
console.error(e);
|
||||
form.data.password = '';
|
||||
return setError(form, '', 'Your username or password is incorrect.');
|
||||
}
|
||||
|
||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
||||
form.data.username = '';
|
||||
form.data.password = '';
|
||||
const message = { type: 'success', message: 'Signed In!' };
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { redirect, type Actions } from '@sveltejs/kit';
|
||||
import { auth } from '$lib/server/lucia';
|
||||
import { lucia } from '$lib/server/auth';
|
||||
|
||||
export const actions: Actions = {
|
||||
default: async ({ locals }) => {
|
||||
default: async ({ locals, cookies }) => {
|
||||
console.log('Signing out user');
|
||||
const session = await locals.auth.validate();
|
||||
if (!session) {
|
||||
const sessionId = cookies.get(lucia.sessionCookieName);
|
||||
if (!locals.user || !sessionId) {
|
||||
throw redirect(302, '/login');
|
||||
}
|
||||
await auth.invalidateSession(session.sessionId); // invalidate session
|
||||
locals.auth.setSession(null); // remove cookie
|
||||
await lucia.invalidateSession(sessionId);
|
||||
// locals.auth.setSession(null); // remove cookie
|
||||
throw redirect(302, '/');
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import {fail, error, type Actions, redirect} from '@sveltejs/kit';
|
||||
import { superValidate } from 'sveltekit-superforms/server';
|
||||
import { LuciaError } from 'lucia';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import prisma from '$lib/prisma';
|
||||
import { auth } from '$lib/server/lucia';
|
||||
import { lucia } from '$lib/server/auth';
|
||||
import { Argon2id } from 'oslo/password';
|
||||
import { userSchema } from '$lib/config/zod-schemas';
|
||||
import { add_user_to_role } from '$server/roles';
|
||||
import type { Message } from '$lib/types.js';
|
||||
|
|
@ -41,8 +41,8 @@ export const load: PageServerLoad = async (event) => {
|
|||
|
||||
export const actions: Actions = {
|
||||
default: async (event) => {
|
||||
const { cookies } = event;
|
||||
const form = await superValidate<typeof signUpSchema, Message>(event, signUpSchema);
|
||||
debugger;
|
||||
if (!form.valid) {
|
||||
form.data.password = '';
|
||||
form.data.confirm_password = '';
|
||||
|
|
@ -51,50 +51,47 @@ export const actions: Actions = {
|
|||
});
|
||||
}
|
||||
|
||||
let session;
|
||||
let sessionCookie;
|
||||
// Adding user to the db
|
||||
try {
|
||||
console.log('Creating user');
|
||||
const token = crypto.randomUUID();
|
||||
|
||||
const user = await auth.createUser({
|
||||
key: {
|
||||
providerId: 'username',
|
||||
providerUserId: form.data.username,
|
||||
password: form.data.password
|
||||
},
|
||||
attributes: {
|
||||
email: form.data.email || null,
|
||||
const hashedPassword = await new Argon2id().hash(form.data.password);
|
||||
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
username: form.data.username,
|
||||
hashed_password: hashedPassword,
|
||||
email: form.data.email || '',
|
||||
firstName: form.data.firstName || '',
|
||||
lastName: form.data.lastName || '',
|
||||
verified: false,
|
||||
receiveEmail: false,
|
||||
theme: 'system',
|
||||
token
|
||||
theme: 'system'
|
||||
}
|
||||
});
|
||||
console.log('signup user', user);
|
||||
add_user_to_role(user.userId, 'user');
|
||||
add_user_to_role(user.id, 'user');
|
||||
await prisma.collection.create({
|
||||
data: {
|
||||
user_id: user.userId
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
await prisma.wishlist.create({
|
||||
data: {
|
||||
user_id: user.userId
|
||||
user_id: user.id
|
||||
}
|
||||
});
|
||||
|
||||
console.log('User', user);
|
||||
|
||||
const session = await auth.createSession({
|
||||
userId: user.userId,
|
||||
attributes: {}
|
||||
session = await lucia.createSession(user.id, {
|
||||
country: event.locals.session.country
|
||||
});
|
||||
event.locals.auth.setSession(session);
|
||||
} catch (e) {
|
||||
if (e instanceof LuciaError && e.message.toUpperCase() === `DUPLICATE_KEY_ID`) {
|
||||
sessionCookie = lucia.createSessionCookie(session.id);
|
||||
} catch (e: any) {
|
||||
if (e.message.toUpperCase() === `DUPLICATE_KEY_ID`) {
|
||||
// key already exists
|
||||
console.error('Lucia Error: ', e);
|
||||
}
|
||||
|
|
@ -107,6 +104,8 @@ export const actions: Actions = {
|
|||
form.data.confirm_password = '';
|
||||
throw error(500, message);
|
||||
}
|
||||
|
||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
||||
throw redirect(302, '/');
|
||||
// const message = { type: 'success', message: 'Signed Up!' } as const;
|
||||
// throw flashRedirect(message, event);
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@
|
|||
</Portal>
|
||||
{/if}
|
||||
|
||||
<Toaster />
|
||||
<!-- <Toaster /> -->
|
||||
|
||||
<style lang="postcss">
|
||||
.loading {
|
||||
|
|
|
|||
Loading…
Reference in a new issue