mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Adding ip country and address to the session DB, updating libraries and Lucia beta, updating auth flows for newest lucia changes.
This commit is contained in:
parent
994d1d462c
commit
9f4aafe658
9 changed files with 882 additions and 575 deletions
50
package.json
50
package.json
|
|
@ -26,47 +26,47 @@
|
||||||
"seed": "node --loader ts-node/esm prisma/seed.ts"
|
"seed": "node --loader ts-node/esm prisma/seed.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@melt-ui/pp": "^0.1.4",
|
"@melt-ui/pp": "^0.3.0",
|
||||||
"@melt-ui/svelte": "^0.66.4",
|
"@melt-ui/svelte": "^0.70.0",
|
||||||
"@playwright/test": "^1.40.1",
|
"@playwright/test": "^1.41.0",
|
||||||
"@resvg/resvg-js": "^2.4.1",
|
"@resvg/resvg-js": "^2.4.1",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.1.0",
|
||||||
"@sveltejs/adapter-vercel": "^4.0.0",
|
"@sveltejs/adapter-vercel": "^4.0.5",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.3.5",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@types/cookie": "^0.5.4",
|
"@types/cookie": "^0.5.4",
|
||||||
"@types/node": "^18.19.3",
|
"@types/node": "^18.19.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.16.0",
|
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||||
"@typescript-eslint/parser": "^6.16.0",
|
"@typescript-eslint/parser": "^6.19.0",
|
||||||
"autoprefixer": "^10.4.15",
|
"autoprefixer": "^10.4.17",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.35.1",
|
"eslint-plugin-svelte": "^2.35.1",
|
||||||
"just-clone": "^6.2.0",
|
"just-clone": "^6.2.0",
|
||||||
"just-debounce-it": "^3.2.0",
|
"just-debounce-it": "^3.2.0",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.33",
|
||||||
"postcss-import": "^15.1.0",
|
"postcss-import": "^15.1.0",
|
||||||
"postcss-load-config": "^4.0.2",
|
"postcss-load-config": "^4.0.2",
|
||||||
"postcss-preset-env": "^9.3.0",
|
"postcss-preset-env": "^9.3.0",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.2.4",
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
"prettier-plugin-svelte": "^3.1.2",
|
||||||
"prisma": "^5.7.1",
|
"prisma": "^5.8.1",
|
||||||
"sass": "^1.65.1",
|
"sass": "^1.70.0",
|
||||||
"satori": "^0.10.11",
|
"satori": "^0.10.11",
|
||||||
"satori-html": "^0.3.2",
|
"satori-html": "^0.3.2",
|
||||||
"svelte": "^4.2.8",
|
"svelte": "^4.2.9",
|
||||||
"svelte-check": "^3.6.2",
|
"svelte-check": "^3.6.3",
|
||||||
"svelte-meta-tags": "^3.1.0",
|
"svelte-meta-tags": "^3.1.0",
|
||||||
"svelte-preprocess": "^5.1.3",
|
"svelte-preprocess": "^5.1.3",
|
||||||
"svelte-sequential-preprocessor": "^2.0.1",
|
"svelte-sequential-preprocessor": "^2.0.1",
|
||||||
"sveltekit-flash-message": "^2.3.0",
|
"sveltekit-flash-message": "^2.3.1",
|
||||||
"sveltekit-superforms": "^1.13.1",
|
"sveltekit-superforms": "^1.13.3",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.1",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"tslib": "^2.6.1",
|
"tslib": "^2.6.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^5.0.0",
|
"vite": "^5.0.11",
|
||||||
"vitest": "^1.0.0",
|
"vitest": "^1.2.1",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
@ -78,10 +78,10 @@
|
||||||
"@fontsource/fira-mono": "^4.5.10",
|
"@fontsource/fira-mono": "^4.5.10",
|
||||||
"@iconify-icons/line-md": "^1.2.26",
|
"@iconify-icons/line-md": "^1.2.26",
|
||||||
"@iconify-icons/mdi": "^1.2.47",
|
"@iconify-icons/mdi": "^1.2.47",
|
||||||
"@lucia-auth/adapter-prisma": "4.0.0-beta.7",
|
"@lucia-auth/adapter-prisma": "4.0.0-beta.9",
|
||||||
"@lukeed/uuid": "^2.0.1",
|
"@lukeed/uuid": "^2.0.1",
|
||||||
"@paralleldrive/cuid2": "^2.2.2",
|
"@paralleldrive/cuid2": "^2.2.2",
|
||||||
"@prisma/client": "^5.7.1",
|
"@prisma/client": "^5.8.1",
|
||||||
"@sentry/sveltekit": "^7.88.0",
|
"@sentry/sveltekit": "^7.88.0",
|
||||||
"@types/feather-icons": "^4.29.4",
|
"@types/feather-icons": "^4.29.4",
|
||||||
"@vercel/og": "^0.5.13",
|
"@vercel/og": "^0.5.13",
|
||||||
|
|
@ -96,10 +96,10 @@
|
||||||
"iconify-icon": "^1.0.8",
|
"iconify-icon": "^1.0.8",
|
||||||
"just-kebab-case": "^4.2.0",
|
"just-kebab-case": "^4.2.0",
|
||||||
"loader": "^2.1.1",
|
"loader": "^2.1.1",
|
||||||
"lucia": "3.0.0-beta.12",
|
"lucia": "3.0.0-beta.14",
|
||||||
"lucide-svelte": "^0.298.0",
|
"lucide-svelte": "^0.298.0",
|
||||||
"open-props": "^1.6.16",
|
"open-props": "^1.6.16",
|
||||||
"oslo": "^0.24.0",
|
"oslo": "^0.27.1",
|
||||||
"radix-svelte": "^0.9.0",
|
"radix-svelte": "^0.9.0",
|
||||||
"svelte-french-toast": "^1.2.0",
|
"svelte-french-toast": "^1.2.0",
|
||||||
"svelte-lazy-loader": "^1.0.0",
|
"svelte-lazy-loader": "^1.0.0",
|
||||||
|
|
|
||||||
1320
pnpm-lock.yaml
1320
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -59,7 +59,8 @@ model User {
|
||||||
model Session {
|
model Session {
|
||||||
id String @id @unique
|
id String @id @unique
|
||||||
userId String
|
userId String
|
||||||
country String
|
ip_country String
|
||||||
|
ip_address String
|
||||||
expiresAt DateTime
|
expiresAt DateTime
|
||||||
user User @relation(references: [id], fields: [userId], onDelete: Cascade)
|
user User @relation(references: [id], fields: [userId], onDelete: Cascade)
|
||||||
|
|
||||||
|
|
|
||||||
7
src/app.d.ts
vendored
7
src/app.d.ts
vendored
|
|
@ -17,15 +17,14 @@ declare global {
|
||||||
user: import('lucia').User | null;
|
user: import('lucia').User | null;
|
||||||
prisma: PrismaClient;
|
prisma: PrismaClient;
|
||||||
startTimer: number;
|
startTimer: number;
|
||||||
|
ip: string;
|
||||||
|
country: string;
|
||||||
error: string;
|
error: string;
|
||||||
errorId: string;
|
errorId: string;
|
||||||
errorStackTrace: string;
|
errorStackTrace: string;
|
||||||
message: unknown;
|
message: unknown;
|
||||||
track: unknown;
|
track: unknown;
|
||||||
session: {
|
session: import('lucia').Session | null;
|
||||||
ip: string,
|
|
||||||
country: string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
interface Error {
|
interface Error {
|
||||||
code?: string;
|
code?: string;
|
||||||
|
|
|
||||||
|
|
@ -15,32 +15,39 @@ export const authentication: Handle = async function ({ event, resolve }) {
|
||||||
const startTimer = Date.now();
|
const startTimer = Date.now();
|
||||||
event.locals.startTimer = startTimer;
|
event.locals.startTimer = startTimer;
|
||||||
|
|
||||||
let ip = event.request.headers.get('x-forwarded-for') as string;
|
const ip = event.request.headers.get('x-forwarded-for') as string;
|
||||||
if (!ip && browser) {
|
const country = event.request.headers.get('x-vercel-ip-country') as string;
|
||||||
ip = event.getClientAddress();
|
event.locals.ip = dev ? '127.0.0.1' : ip || event.getClientAddress();
|
||||||
}
|
event.locals.country = dev ? 'us' : country;
|
||||||
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);
|
const sessionId = event.cookies.get(lucia.sessionCookieName);
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
event.locals.user = null;
|
event.locals.user = null;
|
||||||
|
event.locals.session = null;
|
||||||
return resolve(event);
|
return resolve(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { session, user } = await lucia.validateSession(sessionId);
|
const { session, user } = await lucia.validateSession(sessionId);
|
||||||
if (session && session.fresh) {
|
if (session && session.fresh) {
|
||||||
const sessionCookie = lucia.createSessionCookie(session.id);
|
const sessionCookie = lucia.createSessionCookie(session.id);
|
||||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
console.log('sessionCookie', JSON.stringify(sessionCookie, null, 2));
|
||||||
|
// sveltekit types deviates from the de-facto standard
|
||||||
|
// you can use 'as any' too
|
||||||
|
event.cookies.set(sessionCookie.name, sessionCookie.value, {
|
||||||
|
path: '.',
|
||||||
|
...sessionCookie.attributes
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!session) {
|
if (!session) {
|
||||||
const sessionCookie = lucia.createBlankSessionCookie();
|
const sessionCookie = lucia.createBlankSessionCookie();
|
||||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
console.log('blank sessionCookie', JSON.stringify(sessionCookie, null, 2));
|
||||||
|
event.cookies.set(sessionCookie.name, sessionCookie.value, {
|
||||||
|
path: ".",
|
||||||
|
...sessionCookie.attributes
|
||||||
|
});
|
||||||
}
|
}
|
||||||
event.locals.user = user;
|
event.locals.user = user;
|
||||||
|
event.locals.session = session;
|
||||||
|
|
||||||
return resolve(event);
|
return resolve(event);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ const adapter = new PrismaAdapter(prisma_client.session, prisma_client.user);
|
||||||
export const lucia = new Lucia(adapter, {
|
export const lucia = new Lucia(adapter, {
|
||||||
getSessionAttributes: (attributes) => {
|
getSessionAttributes: (attributes) => {
|
||||||
return {
|
return {
|
||||||
country: attributes.country,
|
ipCountry: attributes.ip_country,
|
||||||
|
ipAddress: attributes.ip_address
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getUserAttributes: (attributes) => {
|
getUserAttributes: (attributes) => {
|
||||||
|
|
@ -37,9 +38,11 @@ export const lucia = new Lucia(adapter, {
|
||||||
declare module "lucia" {
|
declare module "lucia" {
|
||||||
interface Register {
|
interface Register {
|
||||||
Lucia: typeof lucia;
|
Lucia: typeof lucia;
|
||||||
|
DatabaseUserAttributes: DatabaseUserAttributes;
|
||||||
}
|
}
|
||||||
interface DatabaseSessionAttributes {
|
interface DatabaseSessionAttributes {
|
||||||
country: string;
|
ip_country: string;
|
||||||
|
ip_address: string;
|
||||||
}
|
}
|
||||||
interface DatabaseUserAttributes {
|
interface DatabaseUserAttributes {
|
||||||
username: string;
|
username: string;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ export const actions: Actions = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('user', JSON.stringify(user, null, 2));
|
||||||
|
|
||||||
if (!user || !user.hashed_password) {
|
if (!user || !user.hashed_password) {
|
||||||
form.data.password = '';
|
form.data.password = '';
|
||||||
return setError(form, '', 'Your username or password is incorrect.');
|
return setError(form, '', 'Your username or password is incorrect.');
|
||||||
|
|
@ -56,12 +58,16 @@ export const actions: Actions = {
|
||||||
|
|
||||||
const validPassword = await new Argon2id().verify(user.hashed_password, password);
|
const validPassword = await new Argon2id().verify(user.hashed_password, password);
|
||||||
if (!validPassword) {
|
if (!validPassword) {
|
||||||
|
console.log('invalid password');
|
||||||
form.data.password = '';
|
form.data.password = '';
|
||||||
return setError(form, '', 'Your username or password is incorrect.');
|
return setError(form, '', 'Your username or password is incorrect.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('ip', locals.ip);
|
||||||
|
console.log('country', locals.country);
|
||||||
session = await lucia.createSession(user.id, {
|
session = await lucia.createSession(user.id, {
|
||||||
country: locals.session.ip
|
ip_country: locals.country,
|
||||||
|
ip_address: locals.ip
|
||||||
});
|
});
|
||||||
sessionCookie = lucia.createSessionCookie(session.id);
|
sessionCookie = lucia.createSessionCookie(session.id);
|
||||||
|
|
||||||
|
|
@ -94,7 +100,11 @@ export const actions: Actions = {
|
||||||
return setError(form, '', 'Your username or password is incorrect.');
|
return setError(form, '', 'Your username or password is incorrect.');
|
||||||
}
|
}
|
||||||
|
|
||||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
event.cookies.set(sessionCookie.name, sessionCookie.value, {
|
||||||
|
path: ".",
|
||||||
|
...sessionCookie.attributes
|
||||||
|
});
|
||||||
|
|
||||||
form.data.username = '';
|
form.data.username = '';
|
||||||
form.data.password = '';
|
form.data.password = '';
|
||||||
const message = { type: 'success', message: 'Signed In!' };
|
const message = { type: 'success', message: 'Signed In!' };
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
import { redirect, type Actions } from '@sveltejs/kit';
|
import { redirect, fail } from '@sveltejs/kit';
|
||||||
import { lucia } from '$lib/server/auth';
|
import { lucia } from '$lib/server/auth';
|
||||||
|
import type { Actions } from "./$types";
|
||||||
|
|
||||||
export const actions: Actions = {
|
export const actions: Actions = {
|
||||||
default: async ({ locals, cookies }) => {
|
default: async ({ locals, cookies }) => {
|
||||||
console.log('Signing out user');
|
console.log('Signing out user');
|
||||||
const sessionId = cookies.get(lucia.sessionCookieName);
|
if (!locals.session) {
|
||||||
if (!locals.user || !sessionId) {
|
return fail(401);
|
||||||
redirect(302, '/login');
|
|
||||||
}
|
}
|
||||||
await lucia.invalidateSession(sessionId);
|
await lucia.invalidateSession(locals.session.id);
|
||||||
// locals.auth.setSession(null); // remove cookie
|
const sessionCookie = lucia.createBlankSessionCookie();
|
||||||
redirect(302, '/');
|
cookies.set(sessionCookie.name, sessionCookie.value, {
|
||||||
|
path: '.',
|
||||||
|
...sessionCookie.attributes
|
||||||
|
});
|
||||||
|
return redirect(302, '/login');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,8 @@ export const actions: Actions = {
|
||||||
console.log('User', user);
|
console.log('User', user);
|
||||||
|
|
||||||
session = await lucia.createSession(user.id, {
|
session = await lucia.createSession(user.id, {
|
||||||
country: event.locals.session.country
|
ipCountry: event.locals.session?.ipCountry,
|
||||||
|
ipAddress: event.locals.session?.ipAddress
|
||||||
});
|
});
|
||||||
sessionCookie = lucia.createSessionCookie(session.id);
|
sessionCookie = lucia.createSessionCookie(session.id);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|
@ -105,7 +106,11 @@ export const actions: Actions = {
|
||||||
error(500, message);
|
error(500, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
event.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
event.cookies.set(sessionCookie.name, sessionCookie.value, {
|
||||||
|
path: ".",
|
||||||
|
...sessionCookie.attributes
|
||||||
|
});
|
||||||
|
|
||||||
redirect(302, '/');
|
redirect(302, '/');
|
||||||
// const message = { type: 'success', message: 'Signed Up!' } as const;
|
// const message = { type: 'success', message: 'Signed Up!' } as const;
|
||||||
// throw flashRedirect(message, event);
|
// throw flashRedirect(message, event);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue