Session persistence
This commit is contained in:
parent
c996881547
commit
9b7324e20a
64
package-lock.json
generated
64
package-lock.json
generated
@ -43,6 +43,33 @@
|
|||||||
"integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==",
|
"integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@holdyourwaffle/express-session": {
|
||||||
|
"version": "1.16.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@holdyourwaffle/express-session/-/express-session-1.16.2.tgz",
|
||||||
|
"integrity": "sha512-S4MutTCUvOFawZ2g+PCLkfg7WXK7bR9ZVUCp27X98YBuJLUaRZGO73jVyPKe9S5/rXc2Ppsf36/NwOB9j66n/w==",
|
||||||
|
"requires": {
|
||||||
|
"cookie": "0.4.0",
|
||||||
|
"cookie-signature": "1.0.6",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "~2.0.0",
|
||||||
|
"on-headers": "~1.0.2",
|
||||||
|
"parseurl": "~1.3.3",
|
||||||
|
"safe-buffer": "5.2.0",
|
||||||
|
"uid-safe": "~2.1.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"depd": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@phc/format": {
|
"@phc/format": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@phc/format/-/format-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@phc/format/-/format-0.5.0.tgz",
|
||||||
@ -225,16 +252,6 @@
|
|||||||
"@types/range-parser": "*"
|
"@types/range-parser": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/express-session": {
|
|
||||||
"version": "1.15.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.15.14.tgz",
|
|
||||||
"integrity": "sha512-7kVzFTT0Jy0zmUYDt9ik76XbcqyS9NalV4gn4eLwhk1nGQn+lS/HjPODhG3Oi/GBR2w1LQHUdkz/5KICYMACiw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@types/express": "*",
|
|
||||||
"@types/node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@types/fs-capacitor": {
|
"@types/fs-capacitor": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz",
|
||||||
@ -2653,33 +2670,6 @@
|
|||||||
"pino-http": "^4.0.0"
|
"pino-http": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"express-session": {
|
|
||||||
"version": "1.16.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.2.tgz",
|
|
||||||
"integrity": "sha512-oy0sRsdw6n93E9wpCNWKRnSsxYnSDX9Dnr9mhZgqUEEorzcq5nshGYSZ4ZReHFhKQ80WI5iVUUSPW7u3GaKauw==",
|
|
||||||
"requires": {
|
|
||||||
"cookie": "0.3.1",
|
|
||||||
"cookie-signature": "1.0.6",
|
|
||||||
"debug": "2.6.9",
|
|
||||||
"depd": "~2.0.0",
|
|
||||||
"on-headers": "~1.0.2",
|
|
||||||
"parseurl": "~1.3.3",
|
|
||||||
"safe-buffer": "5.1.2",
|
|
||||||
"uid-safe": "~2.1.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"cookie": {
|
|
||||||
"version": "0.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
|
||||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
|
||||||
},
|
|
||||||
"depd": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extend-shallow": {
|
"extend-shallow": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@holdyourwaffle/express-session": "^1.16.2",
|
||||||
"@types/pug": "^2.0.4",
|
"@types/pug": "^2.0.4",
|
||||||
"apollo-server-express": "^2.9.3",
|
"apollo-server-express": "^2.9.3",
|
||||||
"argon2": "^0.24.1",
|
"argon2": "^0.24.1",
|
||||||
@ -24,7 +25,6 @@
|
|||||||
"dotenv": "^8.1.0",
|
"dotenv": "^8.1.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-pino-logger": "^4.0.0",
|
"express-pino-logger": "^4.0.0",
|
||||||
"express-session": "^1.16.2",
|
|
||||||
"graphql": "^14.5.7",
|
"graphql": "^14.5.7",
|
||||||
"helmet": "^3.21.1",
|
"helmet": "^3.21.1",
|
||||||
"http-errors": "^1.7.3",
|
"http-errors": "^1.7.3",
|
||||||
@ -44,7 +44,6 @@
|
|||||||
"@types/dotenv": "^6.1.1",
|
"@types/dotenv": "^6.1.1",
|
||||||
"@types/express": "^4.17.1",
|
"@types/express": "^4.17.1",
|
||||||
"@types/express-pino-logger": "^4.0.1",
|
"@types/express-pino-logger": "^4.0.1",
|
||||||
"@types/express-session": "^1.15.14",
|
|
||||||
"@types/helmet": "0.0.44",
|
"@types/helmet": "0.0.44",
|
||||||
"@types/http-errors": "^1.6.2",
|
"@types/http-errors": "^1.6.2",
|
||||||
"@types/luxon": "^1.15.2",
|
"@types/luxon": "^1.15.2",
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
CREATE OR REPLACE FUNCTION set_updated_timestamp()
|
CREATE OR REPLACE FUNCTION set_updated_timestamp()
|
||||||
RETURNS TRIGGER AS $$
|
RETURNS TRIGGER AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN
|
NEW.updated_at = now();
|
||||||
NEW.updated_at = now();
|
RETURN NEW;
|
||||||
RETURN NEW;
|
|
||||||
ELSE
|
|
||||||
RETURN OLD;
|
|
||||||
END IF;
|
|
||||||
END;
|
END;
|
||||||
$$ language 'plpgsql';
|
$$ language 'plpgsql';
|
||||||
|
1
sql/migrations/patches/20191008190200-sessions/down.sql
Normal file
1
sql/migrations/patches/20191008190200-sessions/down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DROP TABLE "sessions";
|
10
sql/migrations/patches/20191008190200-sessions/up.sql
Normal file
10
sql/migrations/patches/20191008190200-sessions/up.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE "sessions" (
|
||||||
|
"sid" text NOT NULL COLLATE "default",
|
||||||
|
"session" json NOT NULL,
|
||||||
|
"expires_at" timestamptz NOT NULL,
|
||||||
|
"created_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE "sessions" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("sid") NOT DEFERRABLE INITIALLY IMMEDIATE;
|
||||||
|
CREATE TRIGGER "set_sessions_updated" BEFORE UPDATE ON "sessions" FOR EACH ROW EXECUTE PROCEDURE set_updated_timestamp();
|
1
sql/sessions/all.sql
Normal file
1
sql/sessions/all.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT "sid", "session" FROM "sessions";
|
1
sql/sessions/clear.sql
Normal file
1
sql/sessions/clear.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
TRUNCATE "sessions";
|
1
sql/sessions/destroy.sql
Normal file
1
sql/sessions/destroy.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DELETE FROM "sessions" WHERE "sid" = $1;
|
1
sql/sessions/get.sql
Normal file
1
sql/sessions/get.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT "session" FROM "sessions" WHERE "sid"=$1 AND CURRENT_TIMESTAMP < "expires_at";
|
1
sql/sessions/length.sql
Normal file
1
sql/sessions/length.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT COUNT(*) as length FROM "sessions";
|
3
sql/sessions/set.sql
Normal file
3
sql/sessions/set.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
INSERT INTO "sessions" AS s ("sid", "session", "expires_at") VALUES ($1, $2, $3)
|
||||||
|
ON CONFLICT ON CONSTRAINT "session_pkey"
|
||||||
|
DO UPDATE SET "session"=$2, "expires_at"=$3 WHERE "s"."sid"=$1;
|
1
sql/sessions/touch.sql
Normal file
1
sql/sessions/touch.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
UPDATE "sessions" SET "expires_at"=$2 WHERE "sid"=$1;
|
7
src/custom.d.ts
vendored
7
src/custom.d.ts
vendored
@ -14,6 +14,7 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { User } from "@kredens/db/models";
|
import { User } from "@kredens/db/models";
|
||||||
|
import { Cookie } from "@holdyourwaffle/express-session";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace Express {
|
namespace Express {
|
||||||
@ -21,4 +22,10 @@ declare global {
|
|||||||
user?: User;
|
user?: User;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SessionData {
|
||||||
|
cookie: Cookie;
|
||||||
|
userID?: number;
|
||||||
|
csrfToken: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import {
|
import {
|
||||||
Extensions,
|
Extensions,
|
||||||
MigrationRepository,
|
MigrationRepository,
|
||||||
|
SessionRepository,
|
||||||
TaskRepository,
|
TaskRepository,
|
||||||
UserRepository
|
UserRepository
|
||||||
} from "@kredens/db/repos";
|
} from "@kredens/db/repos";
|
||||||
@ -34,6 +35,7 @@ const initOptions: IInitOptions<Extensions> = {
|
|||||||
obj.migrations = new MigrationRepository(obj, pgp);
|
obj.migrations = new MigrationRepository(obj, pgp);
|
||||||
obj.tasks = new TaskRepository(obj, pgp);
|
obj.tasks = new TaskRepository(obj, pgp);
|
||||||
obj.users = new UserRepository(obj, pgp);
|
obj.users = new UserRepository(obj, pgp);
|
||||||
|
obj.sessions = new SessionRepository(obj, pgp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,3 +38,8 @@ export interface Task {
|
|||||||
max_frequency?: number;
|
max_frequency?: number;
|
||||||
created_at: DateTime;
|
created_at: DateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Session {
|
||||||
|
sid: string;
|
||||||
|
session: SessionData;
|
||||||
|
}
|
||||||
|
@ -14,13 +14,20 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { MigrationRepository } from "@kredens/db/repos/migrations";
|
import { MigrationRepository } from "@kredens/db/repos/migrations";
|
||||||
|
import { SessionRepository } from "@kredens/db/repos/sessions";
|
||||||
import { TaskRepository } from "@kredens/db/repos/tasks";
|
import { TaskRepository } from "@kredens/db/repos/tasks";
|
||||||
import { UserRepository } from "@kredens/db/repos/users";
|
import { UserRepository } from "@kredens/db/repos/users";
|
||||||
|
|
||||||
export interface Extensions {
|
export interface Extensions {
|
||||||
migrations: MigrationRepository;
|
migrations: MigrationRepository;
|
||||||
users: UserRepository;
|
sessions: SessionRepository;
|
||||||
tasks: TaskRepository;
|
tasks: TaskRepository;
|
||||||
|
users: UserRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { MigrationRepository, UserRepository, TaskRepository };
|
export {
|
||||||
|
MigrationRepository,
|
||||||
|
UserRepository,
|
||||||
|
SessionRepository,
|
||||||
|
TaskRepository
|
||||||
|
};
|
||||||
|
70
src/db/repos/sessions.ts
Normal file
70
src/db/repos/sessions.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright (C) 2019 ModZero <modzero@modzero.xyz>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { Session } from "@kredens/db/models";
|
||||||
|
import { sessions as sql } from "@kredens/db/sql";
|
||||||
|
import { DateTime } from "luxon";
|
||||||
|
import { Maybe } from "monet";
|
||||||
|
import { IDatabase, IMain } from "pg-promise";
|
||||||
|
|
||||||
|
export class SessionRepository {
|
||||||
|
private db: IDatabase<any>;
|
||||||
|
|
||||||
|
constructor(db: IDatabase<any>, pgp: IMain) {
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async all(): Promise<Session[]> {
|
||||||
|
return this.db.map(sql.all, [], row => ({
|
||||||
|
session: row.session,
|
||||||
|
sid: row.sid
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clear() {
|
||||||
|
return this.db.none(sql.clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async destroy(sid: string) {
|
||||||
|
return this.db.none(sql.destroy, [sid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async get(sid: string): Promise<Maybe<Session>> {
|
||||||
|
return this.db.oneOrNone(sql.get, [sid]).then(row =>
|
||||||
|
row
|
||||||
|
? Maybe.Some({
|
||||||
|
session: row.session,
|
||||||
|
sid: row.sid
|
||||||
|
})
|
||||||
|
: Maybe.None()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async length(): Promise<number> {
|
||||||
|
return this.db.one(sql.length).then(row => +row.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async set(sid: string, session: SessionData, expiresAt: DateTime) {
|
||||||
|
return this.db.none(sql.set, [
|
||||||
|
sid,
|
||||||
|
JSON.stringify(session),
|
||||||
|
expiresAt.toSQL()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async touch(sid: string, expiresAt: DateTime) {
|
||||||
|
return this.db.none(sql.touch, [sid, expiresAt.toSQL()]);
|
||||||
|
}
|
||||||
|
}
|
@ -45,7 +45,17 @@ const tasks = {
|
|||||||
list: sql("tasks/list.sql")
|
list: sql("tasks/list.sql")
|
||||||
};
|
};
|
||||||
|
|
||||||
export { migrations, users, tasks };
|
const sessions = {
|
||||||
|
all: sql("sessions/all.sql"),
|
||||||
|
clear: sql("sessions/clear.sql"),
|
||||||
|
destroy: sql("sessions/destroy.sql"),
|
||||||
|
get: sql("sessions/get.sql"),
|
||||||
|
length: sql("sessions/length.sql"),
|
||||||
|
set: sql("sessions/set.sql"),
|
||||||
|
touch: sql("sessions/touch.sql")
|
||||||
|
};
|
||||||
|
|
||||||
|
export { migrations, users, tasks, sessions };
|
||||||
|
|
||||||
/** Helper for linking to external query files */
|
/** Helper for linking to external query files */
|
||||||
function sql(file: string): QueryFile {
|
function sql(file: string): QueryFile {
|
||||||
|
@ -13,19 +13,21 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import session, { SessionOptions } from "@holdyourwaffle/express-session";
|
||||||
import { server as graphqlServer } from "@kredens/api";
|
import { server as graphqlServer } from "@kredens/api";
|
||||||
import { authMiddleware } from "@kredens/auth";
|
import { authMiddleware } from "@kredens/auth";
|
||||||
import { db } from "@kredens/db";
|
import { db } from "@kredens/db";
|
||||||
import logger from "@kredens/logger";
|
import logger from "@kredens/logger";
|
||||||
import indexRouter from "@kredens/routes/";
|
import indexRouter from "@kredens/routes/";
|
||||||
import bootstrapRouter from "@kredens/routes/bootstrap";
|
import bootstrapRouter from "@kredens/routes/bootstrap";
|
||||||
|
import { PgStore } from "@kredens/sessions";
|
||||||
import cookieParser from "cookie-parser";
|
import cookieParser from "cookie-parser";
|
||||||
import csrf from "csurf";
|
import csrf from "csurf";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import pinoExpress from "express-pino-logger";
|
import pinoExpress from "express-pino-logger";
|
||||||
import session, { SessionOptions } from "express-session";
|
|
||||||
import helmet from "helmet";
|
import helmet from "helmet";
|
||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await db.tx(async t => {
|
await db.tx(async t => {
|
||||||
await t.migrations.create();
|
await t.migrations.create();
|
||||||
@ -59,7 +61,8 @@ async function main() {
|
|||||||
const sessionOptions: SessionOptions = {
|
const sessionOptions: SessionOptions = {
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
secret: process.env.SECRET
|
secret: process.env.SECRET,
|
||||||
|
store: new PgStore()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (app.get("env") === "production") {
|
if (app.get("env") === "production") {
|
||||||
|
99
src/sessions.ts
Normal file
99
src/sessions.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright (C) 2019 ModZero <modzero@modzero.xyz>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { Store } from "@holdyourwaffle/express-session";
|
||||||
|
import { db } from "@kredens/db";
|
||||||
|
import { DateTime, Duration } from "luxon";
|
||||||
|
|
||||||
|
export class PgStore extends Store {
|
||||||
|
private ttl: Duration;
|
||||||
|
constructor(options: { ttl?: Duration } = {}) {
|
||||||
|
super();
|
||||||
|
this.ttl = options.ttl || Duration.fromObject({ days: 1 }); // One day in seconds.
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(
|
||||||
|
sid: string,
|
||||||
|
cb: (err: any, session?: SessionData | null) => void
|
||||||
|
) {
|
||||||
|
db.sessions
|
||||||
|
.get(sid)
|
||||||
|
.then(s => cb(null, s.map(ss => ss.session).orNull()))
|
||||||
|
.catch(r => cb(r, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(sid: string, session: SessionData, cb?: (err?: any) => void) {
|
||||||
|
const expiresAt = this.getExpiresAt(session);
|
||||||
|
const p = db.sessions.set(sid, session, expiresAt);
|
||||||
|
|
||||||
|
if (cb) {
|
||||||
|
p.then(s => cb(null)).catch(r => cb(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy(sid: string, cb?: (err?: any) => void) {
|
||||||
|
const p = db.sessions.destroy(sid);
|
||||||
|
|
||||||
|
if (cb) {
|
||||||
|
p.then(s => cb()).catch(r => cb(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public all(
|
||||||
|
cb: (err: any, obj?: { [sid: string]: SessionData } | null) => void
|
||||||
|
) {
|
||||||
|
db.sessions
|
||||||
|
.all()
|
||||||
|
.then(ss => {
|
||||||
|
const sessions: { [sid: string]: SessionData } = {};
|
||||||
|
|
||||||
|
for (const s of ss) {
|
||||||
|
sessions[s.sid] = s.session;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null, sessions);
|
||||||
|
})
|
||||||
|
.catch(r => cb(r, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public length(cb: (err: any, length: number) => void) {
|
||||||
|
db.sessions
|
||||||
|
.length()
|
||||||
|
.then(l => cb(null, l))
|
||||||
|
.catch(r => cb(r, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear(cb?: (err?: any) => void) {
|
||||||
|
const p = db.sessions.clear();
|
||||||
|
if (cb) {
|
||||||
|
p.then(() => cb()).catch(r => cb(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public touch(sid: string, session: SessionData, cb?: (err?: any) => void) {
|
||||||
|
const p = db.sessions.touch(sid, this.getExpiresAt(session));
|
||||||
|
if (cb) {
|
||||||
|
p.then(() => cb()).catch(r => cb(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getExpiresAt(session: SessionData) {
|
||||||
|
if (session && session.cookie && session.cookie.expires) {
|
||||||
|
return DateTime.fromJSDate(session.cookie.expires);
|
||||||
|
} else {
|
||||||
|
return DateTime.local().plus(this.ttl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user