mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 10:02:59 +08:00
Merge pull request #1955 from TriliumNext/feature/db_session_store
In-database session store
This commit is contained in:
commit
56d4d7c20f
@ -104,7 +104,6 @@
|
||||
"sanitize-html": "2.17.0",
|
||||
"sax": "1.4.1",
|
||||
"serve-favicon": "2.5.0",
|
||||
"session-file-store": "1.5.0",
|
||||
"stream-throttle": "0.1.3",
|
||||
"strip-bom": "5.0.0",
|
||||
"striptags": "3.2.0",
|
||||
|
@ -4,7 +4,6 @@ import favicon from "serve-favicon";
|
||||
import cookieParser from "cookie-parser";
|
||||
import helmet from "helmet";
|
||||
import compression from "compression";
|
||||
import sessionParser from "./routes/session_parser.js";
|
||||
import config from "./services/config.js";
|
||||
import utils, { getResourceDir } from "./services/utils.js";
|
||||
import assets from "./routes/assets.js";
|
||||
@ -111,6 +110,8 @@ export default async function buildApp() {
|
||||
app.use(`/manifest.webmanifest`, express.static(path.join(publicAssetsDir, "manifest.webmanifest")));
|
||||
app.use(`/robots.txt`, express.static(path.join(publicAssetsDir, "robots.txt")));
|
||||
app.use(`/icon.png`, express.static(path.join(publicAssetsDir, "icon.png")));
|
||||
|
||||
const sessionParser = (await import("./routes/session_parser.js")).default;
|
||||
app.use(sessionParser);
|
||||
app.use(favicon(path.join(assetsDir, "icon.ico")));
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
data TEXT,
|
||||
expires INTEGER
|
||||
);
|
@ -187,3 +187,9 @@ CREATE TABLE IF NOT EXISTS "embedding_providers" (
|
||||
"dateModified" TEXT NOT NULL,
|
||||
"utcDateModified" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
data TEXT,
|
||||
expires INTEGER
|
||||
);
|
||||
|
@ -1,10 +1,55 @@
|
||||
import session from "express-session";
|
||||
import sessionFileStore from "session-file-store";
|
||||
import sql from "../services/sql.js";
|
||||
import session, { Store } from "express-session";
|
||||
import sessionSecret from "../services/session_secret.js";
|
||||
import dataDir from "../services/data_dir.js";
|
||||
import config from "../services/config.js";
|
||||
import log from "../services/log.js";
|
||||
|
||||
const FileStore = sessionFileStore(session);
|
||||
class SQLiteSessionStore extends Store {
|
||||
|
||||
get(sid: string, callback: (err: any, session?: session.SessionData | null) => void): void {
|
||||
try {
|
||||
const data = sql.getValue<string>(/*sql*/`SELECT data FROM sessions WHERE id = ?`, sid);
|
||||
let session = null;
|
||||
if (data) {
|
||||
session = JSON.parse(data);
|
||||
}
|
||||
return callback(null, session);
|
||||
} catch (e: unknown) {
|
||||
log.error(e);
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
set(id: string, session: session.SessionData, callback?: (err?: any) => void): void {
|
||||
try {
|
||||
const expires = session.cookie?.expires
|
||||
? new Date(session.cookie.expires).getTime()
|
||||
: Date.now() + 3600000; // fallback to 1 hour
|
||||
const data = JSON.stringify(session);
|
||||
|
||||
sql.upsert("sessions", "id", {
|
||||
id,
|
||||
expires,
|
||||
data
|
||||
});
|
||||
callback?.();
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
return callback?.(e);
|
||||
}
|
||||
}
|
||||
|
||||
destroy(sid: string, callback?: (err?: any) => void): void {
|
||||
try {
|
||||
sql.execute(/*sql*/`DELETE FROM sessions WHERE id = ?`, sid);
|
||||
callback?.();
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
callback?.(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const sessionParser = session({
|
||||
secret: sessionSecret,
|
||||
@ -16,10 +61,14 @@ const sessionParser = session({
|
||||
maxAge: config.Session.cookieMaxAge * 1000 // needs value in milliseconds
|
||||
},
|
||||
name: "trilium.sid",
|
||||
store: new FileStore({
|
||||
ttl: config.Session.cookieMaxAge,
|
||||
path: `${dataDir.TRILIUM_DATA_DIR}/sessions`
|
||||
})
|
||||
store: new SQLiteSessionStore()
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
// Clean up expired sesions.
|
||||
const now = Date.now();
|
||||
const result = sql.execute(/*sql*/`DELETE FROM sessions WHERE expires < ?`, now);
|
||||
console.log("Cleaning up expired sessions: ", result.changes);
|
||||
}, 60 * 60 * 1000);
|
||||
|
||||
export default sessionParser;
|
||||
|
@ -3,7 +3,7 @@ import build from "./build.js";
|
||||
import packageJson from "../../package.json" with { type: "json" };
|
||||
import dataDir from "./data_dir.js";
|
||||
|
||||
const APP_DB_VERSION = 230;
|
||||
const APP_DB_VERSION = 231;
|
||||
const SYNC_VERSION = 35;
|
||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||
|
||||
|
@ -69,7 +69,7 @@ function info(message: string | Error) {
|
||||
log(message);
|
||||
}
|
||||
|
||||
function error(message: string | Error) {
|
||||
function error(message: string | Error | unknown) {
|
||||
log(`ERROR: ${message}`);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import sessionParser from "./routes/session_parser.js";
|
||||
import fs from "fs";
|
||||
import http from "http";
|
||||
import https from "https";
|
||||
@ -79,6 +77,7 @@ async function startTrilium() {
|
||||
|
||||
const httpServer = startHttpServer(app);
|
||||
|
||||
const sessionParser = (await import("./routes/session_parser.js")).default;
|
||||
ws.init(httpServer, sessionParser as any); // TODO: Not sure why session parser is incompatible.
|
||||
|
||||
if (utils.isElectron) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
* [Inconsistent Find and Replace Behavior in Large Code Notes](https://github.com/TriliumNext/Notes/issues/1826) by @SiriusXT
|
||||
* [Incorrect import of multiple inline math](https://github.com/TriliumNext/Notes/pull/1906) by @SiriusXT
|
||||
* [Random EPERM: operation not permitted on Windows](https://github.com/TriliumNext/Notes/issues/249)
|
||||
|
||||
## ✨ Improvements
|
||||
|
||||
@ -40,7 +41,8 @@
|
||||
* [Added support for opening and activating a note in a new tab using Ctrl+Shift+click on notes in the launcher pane, note tree, or note images](https://github.com/TriliumNext/Notes/pull/1854) by @SiriusXT
|
||||
* [Style and footnote improvements](https://github.com/TriliumNext/Notes/pull/1913) by @SiriusXT
|
||||
* Backend log: disable some editor features in order to increase performance for large logs (syntax highlighting, folding, etc.).
|
||||
* [Collapsible table of contents](https://github.com/TriliumNext/Notes/pull/1954) by @SriiusXT
|
||||
* [Collapsible table of contents](https://github.com/TriliumNext/Notes/pull/1954) by @SiriusXT
|
||||
* Sessions (logins) are no longer stored as files in the data directory, but as entries in the database. This improves the session reliability on Windows platforms.
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
|
66
pnpm-lock.yaml
generated
66
pnpm-lock.yaml
generated
@ -755,9 +755,6 @@ importers:
|
||||
serve-favicon:
|
||||
specifier: 2.5.0
|
||||
version: 2.5.0
|
||||
session-file-store:
|
||||
specifier: 1.5.0
|
||||
version: 1.5.0
|
||||
stream-throttle:
|
||||
specifier: 0.1.3
|
||||
version: 0.1.3
|
||||
@ -6089,9 +6086,6 @@ packages:
|
||||
asap@2.0.6:
|
||||
resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
|
||||
|
||||
asn1.js@5.4.1:
|
||||
resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==}
|
||||
|
||||
assertion-error@2.0.1:
|
||||
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||
engines: {node: '>=12'}
|
||||
@ -6221,9 +6215,6 @@ packages:
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0
|
||||
|
||||
bagpipe@0.3.5:
|
||||
resolution: {integrity: sha512-42sAlmPDKes1nLm/aly+0VdaopSU9br+jkRELedhQxI5uXHgtk47I83Mpmf4zoNTRMASdLFtUkimlu/Z9zQ8+g==}
|
||||
|
||||
balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
@ -6320,9 +6311,6 @@ packages:
|
||||
bmp-ts@1.0.9:
|
||||
resolution: {integrity: sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==}
|
||||
|
||||
bn.js@4.12.1:
|
||||
resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==}
|
||||
|
||||
body-parser@1.20.3:
|
||||
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
@ -9297,9 +9285,6 @@ packages:
|
||||
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-typedarray@1.0.0:
|
||||
resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
|
||||
|
||||
is-unicode-supported@0.1.0:
|
||||
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
|
||||
engines: {node: '>=10'}
|
||||
@ -9708,10 +9693,6 @@ packages:
|
||||
kolorist@1.8.0:
|
||||
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
|
||||
|
||||
kruptein@2.2.3:
|
||||
resolution: {integrity: sha512-BTwprBPTzkFT9oTugxKd3WnWrX630MqUDsnmBuoa98eQs12oD4n4TeI0GbpdGcYn/73Xueg2rfnw+oK4dovnJg==}
|
||||
engines: {node: '>6'}
|
||||
|
||||
langium@3.3.1:
|
||||
resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
@ -12432,10 +12413,6 @@ packages:
|
||||
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
session-file-store@1.5.0:
|
||||
resolution: {integrity: sha512-60IZaJNzyu2tIeHutkYE8RiXVx3KRvacOxfLr2Mj92SIsRIroDsH0IlUUR6fJAjoTW4RQISbaOApa2IZpIwFdQ==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
set-blocking@2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
|
||||
@ -13375,9 +13352,6 @@ packages:
|
||||
typed-assert@1.0.9:
|
||||
resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==}
|
||||
|
||||
typedarray-to-buffer@3.1.5:
|
||||
resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==}
|
||||
|
||||
typedarray@0.0.6:
|
||||
resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
|
||||
|
||||
@ -14073,9 +14047,6 @@ packages:
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
write-file-atomic@3.0.3:
|
||||
resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==}
|
||||
|
||||
write-file-atomic@4.0.2:
|
||||
resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
@ -20726,13 +20697,6 @@ snapshots:
|
||||
|
||||
asap@2.0.6: {}
|
||||
|
||||
asn1.js@5.4.1:
|
||||
dependencies:
|
||||
bn.js: 4.12.1
|
||||
inherits: 2.0.4
|
||||
minimalistic-assert: 1.0.1
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
assertion-error@2.0.1: {}
|
||||
|
||||
ast-types@0.13.4:
|
||||
@ -20900,8 +20864,6 @@ snapshots:
|
||||
babel-plugin-jest-hoist: 29.6.3
|
||||
babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10)
|
||||
|
||||
bagpipe@0.3.5: {}
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
|
||||
balanced-match@2.0.0: {}
|
||||
@ -20988,8 +20950,6 @@ snapshots:
|
||||
|
||||
bmp-ts@1.0.9: {}
|
||||
|
||||
bn.js@4.12.1: {}
|
||||
|
||||
body-parser@1.20.3:
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
@ -24569,8 +24529,6 @@ snapshots:
|
||||
dependencies:
|
||||
which-typed-array: 1.1.19
|
||||
|
||||
is-typedarray@1.0.0: {}
|
||||
|
||||
is-unicode-supported@0.1.0: {}
|
||||
|
||||
is-url@1.2.4: {}
|
||||
@ -25207,10 +25165,6 @@ snapshots:
|
||||
|
||||
kolorist@1.8.0: {}
|
||||
|
||||
kruptein@2.2.3:
|
||||
dependencies:
|
||||
asn1.js: 5.4.1
|
||||
|
||||
langium@3.3.1:
|
||||
dependencies:
|
||||
chevrotain: 11.0.3
|
||||
@ -28268,15 +28222,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
session-file-store@1.5.0:
|
||||
dependencies:
|
||||
bagpipe: 0.3.5
|
||||
fs-extra: 8.1.0
|
||||
kruptein: 2.2.3
|
||||
object-assign: 4.1.1
|
||||
retry: 0.12.0
|
||||
write-file-atomic: 3.0.3
|
||||
|
||||
set-blocking@2.0.0: {}
|
||||
|
||||
set-function-length@1.2.2:
|
||||
@ -29481,10 +29426,6 @@ snapshots:
|
||||
|
||||
typed-assert@1.0.9: {}
|
||||
|
||||
typedarray-to-buffer@3.1.5:
|
||||
dependencies:
|
||||
is-typedarray: 1.0.0
|
||||
|
||||
typedarray@0.0.6: {}
|
||||
|
||||
typescript-eslint@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3):
|
||||
@ -30336,13 +30277,6 @@ snapshots:
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
write-file-atomic@3.0.3:
|
||||
dependencies:
|
||||
imurmurhash: 0.1.4
|
||||
is-typedarray: 1.0.0
|
||||
signal-exit: 3.0.7
|
||||
typedarray-to-buffer: 3.1.5
|
||||
|
||||
write-file-atomic@4.0.2:
|
||||
dependencies:
|
||||
imurmurhash: 0.1.4
|
||||
|
Loading…
x
Reference in New Issue
Block a user