swap session store to redis
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcrypt": "^6.0.0",
|
"bcrypt": "^6.0.0",
|
||||||
|
"connect-redis": "^10.0.0",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
"database": "workspace:*",
|
"database": "workspace:*",
|
||||||
"dotenv": "^17.4.2",
|
"dotenv": "^17.4.2",
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
"express-session": "^1.19.0",
|
"express-session": "^1.19.0",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
|
"redis": "^6.2.1",
|
||||||
"zod": "^4.5.4"
|
"zod": "^4.5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import session from "express-session";
|
|||||||
import passport from "passport";
|
import passport from "passport";
|
||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcrypt";
|
||||||
import env from "./utils/env.js";
|
import env from "./utils/env.js";
|
||||||
|
import { RedisStore } from "connect-redis";
|
||||||
|
import { createClient, RedisClient } from "redis";
|
||||||
import { Strategy as LocalStrategy } from "passport-local";
|
import { Strategy as LocalStrategy } from "passport-local";
|
||||||
import { prisma } from "database";
|
import { prisma } from "database";
|
||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod";
|
||||||
@@ -16,6 +18,10 @@ import { ZodError } from "zod";
|
|||||||
import usersRoute from "./routers/users.js";
|
import usersRoute from "./routers/users.js";
|
||||||
import postsRoute from "./routers/posts.js";
|
import postsRoute from "./routers/posts.js";
|
||||||
|
|
||||||
|
// redis client for session mgmt
|
||||||
|
const redisClient = createClient({ url: env.REDIS_URL });
|
||||||
|
redisClient.connect().catch(console.error);
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(express.urlencoded({ extended: false }));
|
app.use(express.urlencoded({ extended: false }));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
@@ -58,9 +64,16 @@ passport.deserializeUser(async (id: number, done) => {
|
|||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
session({
|
session({
|
||||||
|
store: new RedisStore({ client: redisClient, prefix: "sess:" }),
|
||||||
secret: env.SESSION_SECRET,
|
secret: env.SESSION_SECRET,
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
|
cookie: {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: "lax",
|
||||||
|
secure: env.NODE_ENV === "production",
|
||||||
|
maxAge: 1000 * 60 * 60 * 24 * 7,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
app.use(passport.session());
|
app.use(passport.session());
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const env = z.object({
|
|||||||
PORT: z.coerce.number().default(3000),
|
PORT: z.coerce.number().default(3000),
|
||||||
DATABASE_URL: z.string().default("file:../../dev.db"),
|
DATABASE_URL: z.string().default("file:../../dev.db"),
|
||||||
SESSION_SECRET: z.string(),
|
SESSION_SECRET: z.string(),
|
||||||
|
REDIS_URL: z.string().default("redis://localhost:6379"),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default env.parse(process.env);
|
export default env.parse(process.env);
|
||||||
|
|||||||
@@ -20,6 +20,17 @@ export default function Layout({
|
|||||||
<div className="bg-black text-white min-h-screen w-full max-w-[42rem] 2xl:max-w-[48rem] mx-auto select-none px-5">
|
<div className="bg-black text-white min-h-screen w-full max-w-[42rem] 2xl:max-w-[48rem] mx-auto select-none px-5">
|
||||||
<Header />
|
<Header />
|
||||||
<div className="relative">{children}</div>
|
<div className="relative">{children}</div>
|
||||||
|
<div className="my-4 bg-zinc-800 text-sm">
|
||||||
|
<footer className="w-full text-center p-2">
|
||||||
|
<h1>
|
||||||
|
made with ❤️ by{" "}
|
||||||
|
<a href="https://alexav.gg" target="_blank">
|
||||||
|
Alex
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
|
<p className="opacity-50">alex@alexav.gg</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { StrictMode } from "react";
|
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import { AuthProvider } from "./providers/AuthProvider";
|
import { AuthProvider } from "./providers/AuthProvider";
|
||||||
@@ -33,9 +32,7 @@ const router = createBrowserRouter([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
createRoot(document.getElementById("root")!).render(
|
createRoot(document.getElementById("root")!).render(
|
||||||
<StrictMode>
|
<AuthProvider>
|
||||||
<AuthProvider>
|
<RouterProvider router={router} />
|
||||||
<RouterProvider router={router} />
|
</AuthProvider>,
|
||||||
</AuthProvider>
|
|
||||||
</StrictMode>,
|
|
||||||
);
|
);
|
||||||
|
|||||||
Generated
+95
@@ -212,6 +212,9 @@ importers:
|
|||||||
bcrypt:
|
bcrypt:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.0
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
|
connect-redis:
|
||||||
|
specifier: ^10.0.0
|
||||||
|
version: 10.0.0(express-session@1.19.0)(redis@6.2.1)
|
||||||
cors:
|
cors:
|
||||||
specifier: ^2.8.6
|
specifier: ^2.8.6
|
||||||
version: 2.8.6
|
version: 2.8.6
|
||||||
@@ -233,6 +236,9 @@ importers:
|
|||||||
passport-local:
|
passport-local:
|
||||||
specifier: ^1.0.0
|
specifier: ^1.0.0
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
redis:
|
||||||
|
specifier: ^6.2.1
|
||||||
|
version: 6.2.1
|
||||||
zod:
|
zod:
|
||||||
specifier: ^4.5.4
|
specifier: ^4.5.4
|
||||||
version: 4.5.4
|
version: 4.5.4
|
||||||
@@ -823,6 +829,42 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@redis/bloom@6.2.1':
|
||||||
|
resolution: {integrity: sha512-huQgNLaCIZfQ9SeLn4q9124uOUd8HbZDYHwwUzNcRgHqCHiHKl2dDxMqJCeWh8cMqZAoWuHR8XnWbDMIf+o7ag==}
|
||||||
|
engines: {node: '>= 20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@redis/client': ^6.2.1
|
||||||
|
|
||||||
|
'@redis/client@6.2.1':
|
||||||
|
resolution: {integrity: sha512-LzxBY7SIBvvJiyCgcaJZZakE3fJrZZ++i24+EDW9fKpCl68D35uJcKFpZZwCfOoG9WZTbyZlMzMeM0gtOAMU9Q==}
|
||||||
|
engines: {node: '>= 20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@node-rs/xxhash': ^1.1.0
|
||||||
|
'@opentelemetry/api': '>=1 <2'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@node-rs/xxhash':
|
||||||
|
optional: true
|
||||||
|
'@opentelemetry/api':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@redis/json@6.2.1':
|
||||||
|
resolution: {integrity: sha512-AFIUJ8Gj0DaaSBHYuSt8+O0oYWM+50OK1c0OmodB7XERIA8+BbyV3O4v76f9iccWasd1/7qjfZTpuzexUaZtrQ==}
|
||||||
|
engines: {node: '>= 20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@redis/client': ^6.2.1
|
||||||
|
|
||||||
|
'@redis/search@6.2.1':
|
||||||
|
resolution: {integrity: sha512-2vfOAOyYFE7UUw3sBBlkqqruBtOUS4HRY5MtW4hp83llrwvtrTE4r22CEqXddlV+54zkLxBE4nmsIJ/dpezQrQ==}
|
||||||
|
engines: {node: '>= 20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@redis/client': ^6.2.1
|
||||||
|
|
||||||
|
'@redis/time-series@6.2.1':
|
||||||
|
resolution: {integrity: sha512-kiYniph04dJOole+L359B6C9E+jYS2uDP7hca6Onj0xF38ZIpyxARO0Iq0W4ZRn1e8Q6vqW00QFZVSMRA/2Ijw==}
|
||||||
|
engines: {node: '>= 20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@redis/client': ^6.2.1
|
||||||
|
|
||||||
'@rolldown/binding-android-arm-eabi@1.2.7':
|
'@rolldown/binding-android-arm-eabi@1.2.7':
|
||||||
resolution: {integrity: sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ==}
|
resolution: {integrity: sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ==}
|
||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
@@ -1517,6 +1559,10 @@ packages:
|
|||||||
classnames@2.5.1:
|
classnames@2.5.1:
|
||||||
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
|
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
|
||||||
|
|
||||||
|
cluster-key-slot@1.1.2:
|
||||||
|
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
comma-separated-tokens@2.0.3:
|
comma-separated-tokens@2.0.3:
|
||||||
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
||||||
|
|
||||||
@@ -1526,6 +1572,13 @@ packages:
|
|||||||
confbox@0.3.1:
|
confbox@0.3.1:
|
||||||
resolution: {integrity: sha512-cKUSoKa8YxFZZSmraVi7onONx3amu77ngK3kGpsYHDH7drPwCRkQE1RYMPlLRrMtnciRj274XNRxcHxnKmDSnA==}
|
resolution: {integrity: sha512-cKUSoKa8YxFZZSmraVi7onONx3amu77ngK3kGpsYHDH7drPwCRkQE1RYMPlLRrMtnciRj274XNRxcHxnKmDSnA==}
|
||||||
|
|
||||||
|
connect-redis@10.0.0:
|
||||||
|
resolution: {integrity: sha512-x6EotIY20pvocamMtcOsgxFzYufAMfipE+rjWa0cZMeSx+3K0yoHi4Nv4sfMlgF+Z5KnUbMFxyCx9pDZP39p0Q==}
|
||||||
|
engines: {node: '>=22'}
|
||||||
|
peerDependencies:
|
||||||
|
express-session: '>=1'
|
||||||
|
redis: '>=5'
|
||||||
|
|
||||||
content-disposition@1.1.0:
|
content-disposition@1.1.0:
|
||||||
resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==}
|
resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -2636,6 +2689,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==}
|
resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==}
|
||||||
engines: {node: '>= 20.19.0'}
|
engines: {node: '>= 20.19.0'}
|
||||||
|
|
||||||
|
redis@6.2.1:
|
||||||
|
resolution: {integrity: sha512-Z9VHtgYs48PiQC77X9O2Er8Hj4T+5BtFjT91/vi5Is1D04N72cA946ZslM1ImJw8ZctFBZWAVjM7S5wJNeHMpg==}
|
||||||
|
engines: {node: '>= 20.0.0'}
|
||||||
|
|
||||||
remark-parse@11.0.0:
|
remark-parse@11.0.0:
|
||||||
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
|
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
|
||||||
|
|
||||||
@@ -3428,6 +3485,26 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.18
|
'@types/react': 19.2.18
|
||||||
|
|
||||||
|
'@redis/bloom@6.2.1(@redis/client@6.2.1)':
|
||||||
|
dependencies:
|
||||||
|
'@redis/client': 6.2.1
|
||||||
|
|
||||||
|
'@redis/client@6.2.1':
|
||||||
|
dependencies:
|
||||||
|
cluster-key-slot: 1.1.2
|
||||||
|
|
||||||
|
'@redis/json@6.2.1(@redis/client@6.2.1)':
|
||||||
|
dependencies:
|
||||||
|
'@redis/client': 6.2.1
|
||||||
|
|
||||||
|
'@redis/search@6.2.1(@redis/client@6.2.1)':
|
||||||
|
dependencies:
|
||||||
|
'@redis/client': 6.2.1
|
||||||
|
|
||||||
|
'@redis/time-series@6.2.1(@redis/client@6.2.1)':
|
||||||
|
dependencies:
|
||||||
|
'@redis/client': 6.2.1
|
||||||
|
|
||||||
'@rolldown/binding-android-arm-eabi@1.2.7':
|
'@rolldown/binding-android-arm-eabi@1.2.7':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -4085,12 +4162,19 @@ snapshots:
|
|||||||
|
|
||||||
classnames@2.5.1: {}
|
classnames@2.5.1: {}
|
||||||
|
|
||||||
|
cluster-key-slot@1.1.2: {}
|
||||||
|
|
||||||
comma-separated-tokens@2.0.3: {}
|
comma-separated-tokens@2.0.3: {}
|
||||||
|
|
||||||
confbox@0.2.4: {}
|
confbox@0.2.4: {}
|
||||||
|
|
||||||
confbox@0.3.1: {}
|
confbox@0.3.1: {}
|
||||||
|
|
||||||
|
connect-redis@10.0.0(express-session@1.19.0)(redis@6.2.1):
|
||||||
|
dependencies:
|
||||||
|
express-session: 1.19.0
|
||||||
|
redis: 6.2.1
|
||||||
|
|
||||||
content-disposition@1.1.0: {}
|
content-disposition@1.1.0: {}
|
||||||
|
|
||||||
content-type@1.0.5: {}
|
content-type@1.0.5: {}
|
||||||
@@ -5303,6 +5387,17 @@ snapshots:
|
|||||||
|
|
||||||
readdirp@5.1.1: {}
|
readdirp@5.1.1: {}
|
||||||
|
|
||||||
|
redis@6.2.1:
|
||||||
|
dependencies:
|
||||||
|
'@redis/bloom': 6.2.1(@redis/client@6.2.1)
|
||||||
|
'@redis/client': 6.2.1
|
||||||
|
'@redis/json': 6.2.1(@redis/client@6.2.1)
|
||||||
|
'@redis/search': 6.2.1(@redis/client@6.2.1)
|
||||||
|
'@redis/time-series': 6.2.1(@redis/client@6.2.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@node-rs/xxhash'
|
||||||
|
- '@opentelemetry/api'
|
||||||
|
|
||||||
remark-parse@11.0.0:
|
remark-parse@11.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/mdast': 4.0.4
|
'@types/mdast': 4.0.4
|
||||||
|
|||||||
Reference in New Issue
Block a user