Implement login
This commit is contained in:
parent
39cf332500
commit
290ab487a1
16
web/package-lock.json
generated
16
web/package-lock.json
generated
@ -15,6 +15,7 @@
|
|||||||
"diff2html": "^3.4.35",
|
"diff2html": "^3.4.35",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
"prisma": "^4.13.0",
|
"prisma": "^4.13.0",
|
||||||
|
"uuid": "^9.0.0",
|
||||||
"zod": "^3.21.4"
|
"zod": "^3.21.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -22,6 +23,7 @@
|
|||||||
"@sveltejs/kit": "^1.15.9",
|
"@sveltejs/kit": "^1.15.9",
|
||||||
"@types/bootstrap": "^5.2.6",
|
"@types/bootstrap": "^5.2.6",
|
||||||
"@types/diff": "^5.0.3",
|
"@types/diff": "^5.0.3",
|
||||||
|
"@types/uuid": "^9.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
||||||
"@typescript-eslint/parser": "^5.59.1",
|
"@typescript-eslint/parser": "^5.59.1",
|
||||||
"eslint": "^8.39.0",
|
"eslint": "^8.39.0",
|
||||||
@ -826,6 +828,12 @@
|
|||||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "5.59.1",
|
"version": "5.59.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz",
|
||||||
@ -3105,6 +3113,14 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "4.3.3",
|
"version": "4.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.3.tgz",
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"@sveltejs/kit": "^1.15.9",
|
"@sveltejs/kit": "^1.15.9",
|
||||||
"@types/bootstrap": "^5.2.6",
|
"@types/bootstrap": "^5.2.6",
|
||||||
"@types/diff": "^5.0.3",
|
"@types/diff": "^5.0.3",
|
||||||
|
"@types/uuid": "^9.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
||||||
"@typescript-eslint/parser": "^5.59.1",
|
"@typescript-eslint/parser": "^5.59.1",
|
||||||
"eslint": "^8.39.0",
|
"eslint": "^8.39.0",
|
||||||
@ -38,6 +39,7 @@
|
|||||||
"diff2html": "^3.4.35",
|
"diff2html": "^3.4.35",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
"prisma": "^4.13.0",
|
"prisma": "^4.13.0",
|
||||||
|
"uuid": "^9.0.0",
|
||||||
"zod": "^3.21.4"
|
"zod": "^3.21.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,14 @@ model User {
|
|||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
username String @unique
|
username String @unique
|
||||||
password String
|
password String
|
||||||
|
sessions Session[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model Session {
|
||||||
|
token String @id
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
user User @relation(fields: [userId], references: [id])
|
||||||
|
userId Int
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SubmissionState {
|
enum SubmissionState {
|
||||||
|
57
web/src/hooks.server.ts
Normal file
57
web/src/hooks.server.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { redirect, type Handle } from '@sveltejs/kit';
|
||||||
|
import { db } from '$lib/server/prisma';
|
||||||
|
import type { Session } from '@prisma/client';
|
||||||
|
|
||||||
|
const sessionExpireMilliseconds = 1000 * 60 * 60 * 24; // 24 hours
|
||||||
|
|
||||||
|
function isSessionExpired(session: Session): boolean {
|
||||||
|
return session.createdAt.valueOf() + sessionExpireMilliseconds < new Date().valueOf();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeExpiredSessions(userId: number) {
|
||||||
|
const sessions: Session[] = await db.session.findMany({ where: { userId: userId } });
|
||||||
|
sessions.forEach(async (session) => {
|
||||||
|
if (isSessionExpired(session)) {
|
||||||
|
await db.session.delete({ where: { token: session.token } });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handle = (async ({ event, resolve }) => {
|
||||||
|
if (event.url.pathname.startsWith('/login')) {
|
||||||
|
if (event.cookies.get('token')) {
|
||||||
|
const session = await db.session.findUnique({ where: { token: event.cookies.get('token') } });
|
||||||
|
if (session) {
|
||||||
|
removeExpiredSessions(session.userId);
|
||||||
|
if (!isSessionExpired(session)) {
|
||||||
|
throw redirect(302, '/admin/reviews');
|
||||||
|
} else {
|
||||||
|
event.cookies.delete('token');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const res = resolve(event);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event.url.pathname.startsWith('/admin')) {
|
||||||
|
if (event.cookies.get('token')) {
|
||||||
|
const session = await db.session.findUnique({ where: { token: event.cookies.get('token') } });
|
||||||
|
if (session) {
|
||||||
|
removeExpiredSessions(session.userId);
|
||||||
|
if (!isSessionExpired(session)) {
|
||||||
|
const res = await resolve(event);
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
event.cookies.delete('token');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const res = await resolve(event);
|
||||||
|
return res;
|
||||||
|
}) satisfies Handle;
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
<h1 class="mb-4">Reviews</h1>
|
<h1 class="mb-4">Reviews</h1>
|
||||||
|
|
||||||
|
<a href="/logout" class="mb-2 btn btn-outline-primary">Logout</a>
|
||||||
|
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
{#each data.reviewList as review}
|
{#each data.reviewList as review}
|
||||||
<a href="/admin/diff" class="list-group-item list-group-item-action">{review}</a>
|
<a href="/admin/diff" class="list-group-item list-group-item-action">{review}</a>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { Actions } from '@sveltejs/kit';
|
import type { Actions } from '@sveltejs/kit';
|
||||||
import { db } from '$lib/server/prisma';
|
import { db } from '$lib/server/prisma';
|
||||||
|
import * as UUID from 'uuid';
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
login: async ({ cookies, request }) => {
|
login: async ({ cookies, request }) => {
|
||||||
@ -14,6 +15,9 @@ export const actions = {
|
|||||||
return { success: false };
|
return { success: false };
|
||||||
}
|
}
|
||||||
if (user.password === password) {
|
if (user.password === password) {
|
||||||
|
const uuid: string = UUID.v4();
|
||||||
|
await db.session.create({ data: { token: uuid, userId: user.id } });
|
||||||
|
cookies.set('token', uuid);
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
return { success: false };
|
return { success: false };
|
||||||
|
16
web/src/routes/logout/+page.server.ts
Normal file
16
web/src/routes/logout/+page.server.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { db } from '$lib/server/prisma';
|
||||||
|
|
||||||
|
export const load = (async ({ cookies }) => {
|
||||||
|
if (!cookies.get('token')) {
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await db.session.delete({ where: { token: cookies.get('token') } });
|
||||||
|
} catch {
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
}
|
||||||
|
cookies.delete('token');
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
}) satisfies PageServerLoad;
|
1
web/src/routes/logout/+page.svelte
Normal file
1
web/src/routes/logout/+page.svelte
Normal file
@ -0,0 +1 @@
|
|||||||
|
<h1>Logging Out</h1>
|
Loading…
Reference in New Issue
Block a user