Changes sessions to be stored in the DB, this ensures that sessions persist after a restart!
This commit is contained in:
parent
83d93aefc0
commit
1f9bb34853
5 changed files with 103 additions and 30 deletions
|
@ -16,6 +16,7 @@
|
||||||
"@google/genai": "^0.9.0",
|
"@google/genai": "^0.9.0",
|
||||||
"@prisma/client": "^6.6.0",
|
"@prisma/client": "^6.6.0",
|
||||||
"@quasar/extras": "^1.16.4",
|
"@quasar/extras": "^1.16.4",
|
||||||
|
"@quixo3/prisma-session-store": "^3.1.13",
|
||||||
"@simplewebauthn/browser": "^13.1.0",
|
"@simplewebauthn/browser": "^13.1.0",
|
||||||
"@simplewebauthn/server": "^13.1.1",
|
"@simplewebauthn/server": "^13.1.1",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
|
|
43
pnpm-lock.yaml
generated
43
pnpm-lock.yaml
generated
|
@ -17,6 +17,9 @@ importers:
|
||||||
'@quasar/extras':
|
'@quasar/extras':
|
||||||
specifier: ^1.16.4
|
specifier: ^1.16.4
|
||||||
version: 1.16.17
|
version: 1.16.17
|
||||||
|
'@quixo3/prisma-session-store':
|
||||||
|
specifier: ^3.1.13
|
||||||
|
version: 3.1.13(@prisma/client@6.6.0(prisma@6.6.0(typescript@5.8.3))(typescript@5.8.3))(express-session@1.18.1)
|
||||||
'@simplewebauthn/browser':
|
'@simplewebauthn/browser':
|
||||||
specifier: ^13.1.0
|
specifier: ^13.1.0
|
||||||
version: 13.1.0
|
version: 13.1.0
|
||||||
|
@ -406,6 +409,10 @@ packages:
|
||||||
'@levischuck/tiny-cbor@0.2.11':
|
'@levischuck/tiny-cbor@0.2.11':
|
||||||
resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==}
|
resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==}
|
||||||
|
|
||||||
|
'@noble/hashes@1.8.0':
|
||||||
|
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
|
||||||
|
engines: {node: ^14.21.3 || >=16}
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
@ -418,6 +425,9 @@ packages:
|
||||||
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
|
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
|
'@paralleldrive/cuid2@2.2.2':
|
||||||
|
resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==}
|
||||||
|
|
||||||
'@peculiar/asn1-android@2.3.16':
|
'@peculiar/asn1-android@2.3.16':
|
||||||
resolution: {integrity: sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw==}
|
resolution: {integrity: sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw==}
|
||||||
|
|
||||||
|
@ -519,6 +529,13 @@ packages:
|
||||||
vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0
|
vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0
|
||||||
vue: ^3.0.0
|
vue: ^3.0.0
|
||||||
|
|
||||||
|
'@quixo3/prisma-session-store@3.1.13':
|
||||||
|
resolution: {integrity: sha512-EAuOvYAaAsQ0OqxkdJG/Qs3cxlT4VV8SFHjtsA3G01uB1b6r7xftX3oeg7mcG0HN/DI1qOqwvy3YFoJ38ls0iA==}
|
||||||
|
engines: {node: '>=12.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@prisma/client': '>=2.16.1'
|
||||||
|
express-session: '>=1.17.1'
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.40.0':
|
'@rollup/rollup-android-arm-eabi@4.40.0':
|
||||||
resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==}
|
resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
|
@ -2749,6 +2766,10 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4'
|
typescript: '>=4.8.4'
|
||||||
|
|
||||||
|
ts-dedent@2.2.0:
|
||||||
|
resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
|
||||||
|
engines: {node: '>=6.10'}
|
||||||
|
|
||||||
ts-essentials@9.4.2:
|
ts-essentials@9.4.2:
|
||||||
resolution: {integrity: sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==}
|
resolution: {integrity: sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -2771,6 +2792,10 @@ packages:
|
||||||
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
|
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
type-fest@2.19.0:
|
||||||
|
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
|
||||||
|
engines: {node: '>=12.20'}
|
||||||
|
|
||||||
type-fest@4.40.0:
|
type-fest@4.40.0:
|
||||||
resolution: {integrity: sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==}
|
resolution: {integrity: sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
@ -3273,6 +3298,8 @@ snapshots:
|
||||||
|
|
||||||
'@levischuck/tiny-cbor@0.2.11': {}
|
'@levischuck/tiny-cbor@0.2.11': {}
|
||||||
|
|
||||||
|
'@noble/hashes@1.8.0': {}
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nodelib/fs.stat': 2.0.5
|
'@nodelib/fs.stat': 2.0.5
|
||||||
|
@ -3285,6 +3312,10 @@ snapshots:
|
||||||
'@nodelib/fs.scandir': 2.1.5
|
'@nodelib/fs.scandir': 2.1.5
|
||||||
fastq: 1.19.1
|
fastq: 1.19.1
|
||||||
|
|
||||||
|
'@paralleldrive/cuid2@2.2.2':
|
||||||
|
dependencies:
|
||||||
|
'@noble/hashes': 1.8.0
|
||||||
|
|
||||||
'@peculiar/asn1-android@2.3.16':
|
'@peculiar/asn1-android@2.3.16':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@peculiar/asn1-schema': 2.3.15
|
'@peculiar/asn1-schema': 2.3.15
|
||||||
|
@ -3435,6 +3466,14 @@ snapshots:
|
||||||
vite: 6.3.2(@types/node@22.14.1)(sass-embedded@1.87.0)(terser@5.39.0)
|
vite: 6.3.2(@types/node@22.14.1)(sass-embedded@1.87.0)(terser@5.39.0)
|
||||||
vue: 3.5.13(typescript@5.8.3)
|
vue: 3.5.13(typescript@5.8.3)
|
||||||
|
|
||||||
|
'@quixo3/prisma-session-store@3.1.13(@prisma/client@6.6.0(prisma@6.6.0(typescript@5.8.3))(typescript@5.8.3))(express-session@1.18.1)':
|
||||||
|
dependencies:
|
||||||
|
'@paralleldrive/cuid2': 2.2.2
|
||||||
|
'@prisma/client': 6.6.0(prisma@6.6.0(typescript@5.8.3))(typescript@5.8.3)
|
||||||
|
express-session: 1.18.1
|
||||||
|
ts-dedent: 2.2.0
|
||||||
|
type-fest: 2.19.0
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.40.0':
|
'@rollup/rollup-android-arm-eabi@4.40.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
@ -5805,6 +5844,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
|
|
||||||
|
ts-dedent@2.2.0: {}
|
||||||
|
|
||||||
ts-essentials@9.4.2(typescript@5.8.3):
|
ts-essentials@9.4.2(typescript@5.8.3):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
|
@ -5821,6 +5862,8 @@ snapshots:
|
||||||
|
|
||||||
type-fest@0.21.3: {}
|
type-fest@0.21.3: {}
|
||||||
|
|
||||||
|
type-fest@2.19.0: {}
|
||||||
|
|
||||||
type-fest@4.40.0: {}
|
type-fest@4.40.0: {}
|
||||||
|
|
||||||
type-is@1.6.18:
|
type-is@1.6.18:
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Session" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"sid" TEXT NOT NULL,
|
||||||
|
"data" TEXT NOT NULL,
|
||||||
|
"expires_at" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Session_sid_key" ON "Session"("sid");
|
|
@ -121,3 +121,11 @@ model ChatMessage {
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
thread ChatThread @relation(fields: [threadId], references: [id], onDelete: Cascade)
|
thread ChatThread @relation(fields: [threadId], references: [id], onDelete: Cascade)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add this model for session storage
|
||||||
|
model Session {
|
||||||
|
id String @id
|
||||||
|
sid String @unique
|
||||||
|
data String
|
||||||
|
expiresAt DateTime @map("expires_at")
|
||||||
|
}
|
||||||
|
|
|
@ -9,9 +9,12 @@
|
||||||
* Make sure to yarn add / npm install (in your project root)
|
* Make sure to yarn add / npm install (in your project root)
|
||||||
* anything you import here (except for express and compression).
|
* anything you import here (except for express and compression).
|
||||||
*/
|
*/
|
||||||
|
import dotenv from 'dotenv';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import compression from 'compression';
|
import compression from 'compression';
|
||||||
import session from 'express-session'; // Added for session management
|
import session from 'express-session'; // Added for session management
|
||||||
|
import { PrismaSessionStore } from '@quixo3/prisma-session-store'; // Import Prisma session store
|
||||||
|
import { PrismaClient } from '@prisma/client'; // Import Prisma Client
|
||||||
import { v4 as uuidv4 } from 'uuid'; // Added for generating session IDs
|
import { v4 as uuidv4 } from 'uuid'; // Added for generating session IDs
|
||||||
import apiRoutes from './routes/api.js';
|
import apiRoutes from './routes/api.js';
|
||||||
import authRoutes from './routes/auth.js'; // Added for WebAuthn routes
|
import authRoutes from './routes/auth.js'; // Added for WebAuthn routes
|
||||||
|
@ -19,6 +22,8 @@ import chatRoutes from './routes/chat.js'; // Added for Chat routes
|
||||||
import cron from 'node-cron';
|
import cron from 'node-cron';
|
||||||
import { generateAndStoreMantisSummary } from './services/mantisSummarizer.js';
|
import { generateAndStoreMantisSummary } from './services/mantisSummarizer.js';
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
// Define Relying Party details (Update with your actual details)
|
// Define Relying Party details (Update with your actual details)
|
||||||
export const rpID = process.env.NODE_ENV === 'production' ? 'your-production-domain.com' : 'localhost';
|
export const rpID = process.env.NODE_ENV === 'production' ? 'your-production-domain.com' : 'localhost';
|
||||||
export const rpName = 'StylePoint';
|
export const rpName = 'StylePoint';
|
||||||
|
@ -27,14 +32,30 @@ export const origin = process.env.NODE_ENV === 'production' ? `https://${rpID}`
|
||||||
// In-memory store for challenges (Replace with a persistent store in production)
|
// In-memory store for challenges (Replace with a persistent store in production)
|
||||||
export const challengeStore = new Map();
|
export const challengeStore = new Map();
|
||||||
|
|
||||||
|
const prisma = new PrismaClient(); // Instantiate Prisma Client
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
if(!process.env.SESSION_SECRET)
|
||||||
|
{
|
||||||
|
console.error('SESSION_SECRET environment variable is not set. Please set it to a strong secret key.');
|
||||||
|
process.exit(1); // Exit the process if the secret is not set
|
||||||
|
}
|
||||||
|
|
||||||
// Session middleware configuration
|
// Session middleware configuration
|
||||||
app.use(session({
|
app.use(session({
|
||||||
genid: (req) => uuidv4(), // Use UUIDs for session IDs
|
genid: (req) => uuidv4(), // Use UUIDs for session IDs
|
||||||
secret: process.env.SESSION_SECRET || 'a-very-strong-secret-key', // Use an environment variable for the secret
|
secret: process.env.SESSION_SECRET, // Use an environment variable for the secret
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: true,
|
saveUninitialized: false, // Changed to false as recommended for session stores
|
||||||
|
store: new PrismaSessionStore( // Use PrismaSessionStore
|
||||||
|
prisma,
|
||||||
|
{
|
||||||
|
checkPeriod: 2 * 60 * 1000, //ms
|
||||||
|
dbRecordIdIsSessionId: true,
|
||||||
|
dbRecordIdFunction: undefined,
|
||||||
|
}
|
||||||
|
),
|
||||||
cookie: {
|
cookie: {
|
||||||
secure: process.env.NODE_ENV === 'production', // Use secure cookies in production
|
secure: process.env.NODE_ENV === 'production', // Use secure cookies in production
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
|
@ -42,36 +63,24 @@ app.use(session({
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Initialize the database (now synchronous)
|
// Schedule the Mantis summary task
|
||||||
try
|
// Run daily at 1:00 AM server time (adjust as needed)
|
||||||
|
cron.schedule('0 1 * * *', async() =>
|
||||||
{
|
{
|
||||||
console.log('Prisma Client is ready.'); // Log Prisma readiness
|
console.log('Running scheduled Mantis summary task...');
|
||||||
|
try
|
||||||
// Schedule the Mantis summary task after DB initialization
|
|
||||||
// Run daily at 1:00 AM server time (adjust as needed)
|
|
||||||
cron.schedule('0 1 * * *', async() =>
|
|
||||||
{
|
{
|
||||||
console.log('Running scheduled Mantis summary task...');
|
await generateAndStoreMantisSummary();
|
||||||
try
|
console.log('Scheduled Mantis summary task completed.');
|
||||||
{
|
}
|
||||||
await generateAndStoreMantisSummary();
|
catch (error)
|
||||||
console.log('Scheduled Mantis summary task completed.');
|
{
|
||||||
}
|
console.error('Error running scheduled Mantis summary task:', error);
|
||||||
catch (error)
|
}
|
||||||
{
|
}, {
|
||||||
console.error('Error running scheduled Mantis summary task:', error);
|
scheduled: true,
|
||||||
}
|
timezone: 'Europe/London' // Example: Set to your server's timezone
|
||||||
}, {
|
});
|
||||||
scheduled: true,
|
|
||||||
timezone: 'Europe/London' // Example: Set to your server's timezone
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (error)
|
|
||||||
{
|
|
||||||
console.error('Error during server setup:', error);
|
|
||||||
// Optionally handle the error more gracefully, e.g., prevent server start
|
|
||||||
process.exit(1); // Exit if setup fails
|
|
||||||
}
|
|
||||||
|
|
||||||
// attackers can use this header to detect apps running Express
|
// attackers can use this header to detect apps running Express
|
||||||
// and then launch specifically-targeted attacks
|
// and then launch specifically-targeted attacks
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue