Website restoration: Node.js backend, restored design, GitHub sync disabled
- Replaced broken .NET backend with Node.js/Express - Restored original website design with purple gradient hero - Updated homepage and shop pages with Bootstrap 5 responsive design - Disabled GitHub remote sync - all code now stored locally only - Created backup scripts and documentation - All changes saved on Ubuntu server at /var/www/SkyArtShop
This commit is contained in:
21
backend/node_modules/connect-pg-simple/LICENSE
generated
vendored
Normal file
21
backend/node_modules/connect-pg-simple/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Pelle Wessman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
107
backend/node_modules/connect-pg-simple/README.md
generated
vendored
Normal file
107
backend/node_modules/connect-pg-simple/README.md
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
# Connect PG Simple
|
||||
|
||||
A simple, minimal PostgreSQL session store for Express/Connect
|
||||
|
||||
[](https://www.npmjs.com/package/connect-pg-simple)
|
||||
[](https://www.npmjs.com/package/connect-pg-simple)
|
||||
[](https://github.com/voxpelli/badges-cjs-esm)
|
||||
[](https://github.com/voxpelli/eslint-config)
|
||||
[](https://mastodon.social/@voxpelli)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install connect-pg-simple
|
||||
```
|
||||
|
||||
**Once npm installed the module, you need to create the _"session"_ table in your database.**
|
||||
|
||||
For that you can use the [table.sql](table.sql) file provided with the module:
|
||||
|
||||
```bash
|
||||
psql mydatabase < node_modules/connect-pg-simple/table.sql
|
||||
```
|
||||
|
||||
Or simply play the file via a GUI, like the pgAdminIII queries tool.
|
||||
|
||||
Or instruct this module to create it itself, by setting the `createTableIfMissing` option.
|
||||
|
||||
Note that `connect-pg-simple` requires PostgreSQL version 9.5 or above.
|
||||
|
||||
## Usage
|
||||
|
||||
Examples are based on Express 4.
|
||||
|
||||
Simple example:
|
||||
|
||||
```javascript
|
||||
const session = require('express-session');
|
||||
|
||||
app.use(session({
|
||||
store: new (require('connect-pg-simple')(session))({
|
||||
// Insert connect-pg-simple options here
|
||||
}),
|
||||
secret: process.env.FOO_COOKIE_SECRET,
|
||||
resave: false,
|
||||
cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 } // 30 days
|
||||
// Insert express-session options here
|
||||
}));
|
||||
```
|
||||
|
||||
Advanced example showing some custom options:
|
||||
|
||||
```javascript
|
||||
const pg = require('pg');
|
||||
const expressSession = require('express-session');
|
||||
const pgSession = require('connect-pg-simple')(expressSession);
|
||||
|
||||
const pgPool = new pg.Pool({
|
||||
// Insert pool options here
|
||||
});
|
||||
|
||||
app.use(expressSession({
|
||||
store: new pgSession({
|
||||
pool : pgPool, // Connection pool
|
||||
tableName : 'user_sessions' // Use another table-name than the default "session" one
|
||||
// Insert connect-pg-simple options here
|
||||
}),
|
||||
secret: process.env.FOO_COOKIE_SECRET,
|
||||
resave: false,
|
||||
cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 } // 30 days
|
||||
// Insert express-session options here
|
||||
}));
|
||||
```
|
||||
|
||||
## Advanced options
|
||||
|
||||
|
||||
### Connection options
|
||||
|
||||
Listed in the order they will be picked up. If multiple are defined, then the first in the lists that is defined will be used, the rest ignored.
|
||||
|
||||
* **pool** - _The recommended one_ – Connection pool object (compatible with [pg.Pool](https://github.com/brianc/node-pg-pool)) for the underlying database module.
|
||||
* **pgPromise** - Database object from `pg-promise` to be used for DB communications.
|
||||
* **conObject** - If you don't specify a pool object, use this option or `conString` to specify a [PostgreSQL Pool connection object](https://node-postgres.com/api/client#constructor) and this module will create a new pool for you.
|
||||
* **conString** - If you don't specify a pool object, use this option or `conObject` to specify a PostgreSQL connection string like `postgres://user:password@host:5432/database` and this module will create a new pool for you. If there's a connection string in the `DATABASE_URL` environment variable (as it is by default on eg. Heroku) then this module will fallback to that if no other connection method has been specified.
|
||||
|
||||
### Other options
|
||||
|
||||
* **ttl** - the time to live for the session in the database – specified in seconds. Defaults to the cookie maxAge if the cookie has a maxAge defined and otherwise defaults to one day.
|
||||
* **createTableIfMissing** - if set to `true` then creates the table in the case where the table does not already exist. Defaults to `false`.
|
||||
* **disableTouch** – boolean value that if set to `true` disables the updating of TTL in the database when using touch. Defaults to false.
|
||||
* **schemaName** - if your session table is in another Postgres schema than the default (it normally isn't), then you can specify that here.
|
||||
* **tableName** - if your session table is named something else than `session`, then you can specify that here.
|
||||
* **pruneSessionInterval** - sets the delay in seconds at which expired sessions are pruned from the database. Default is `60` seconds. If set to `false` no automatic pruning will happen. By default every delay is randomized between 50% and 150% of set value, resulting in an average delay equal to the set value, but spread out to even the load on the database. Automatic pruning will happen `pruneSessionInterval` seconds after the last pruning (includes manual prunes).
|
||||
* **pruneSessionRandomizedInterval** – if set to `false`, then the exact value of `pruneSessionInterval` will be used in all delays. No randomization will happen. If multiple instances all start at once, disabling randomization can mean that multiple instances are all triggering pruning at once, causing unnecessary load on the database. Can also be set to a method, taking a numeric `delay` parameter and returning a modified one, thus allowing a custom delay algorithm if wanted.
|
||||
* **errorLog** – the method used to log errors in those cases where an error can't be returned to a callback. Defaults to `console.error()`, but can be useful to override if one eg. uses [Bunyan](https://github.com/trentm/node-bunyan) for logging.
|
||||
|
||||
## Useful methods
|
||||
|
||||
* **close()** – if this module used its own database module to connect to Postgres, then this will shut that connection down to allow a graceful shutdown. Returns a `Promise` that will resolve when the database has shut down.
|
||||
* **pruneSessions([callback(err)])** – will prune old sessions. Only really needed to be called if **pruneSessionInterval** has been set to `false` – which can be useful if one wants improved control of the pruning.
|
||||
|
||||
## For enterprise
|
||||
|
||||
Available as part of the Tidelift Subscription.
|
||||
|
||||
The maintainers of connect-pg-simple and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-connect-pg-simple?utm_source=npm-connect-pg-simple&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
||||
442
backend/node_modules/connect-pg-simple/index.js
generated
vendored
Normal file
442
backend/node_modules/connect-pg-simple/index.js
generated
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
// @ts-check
|
||||
/// <reference types="node" />
|
||||
|
||||
'use strict';
|
||||
|
||||
const DEFAULT_PRUNE_INTERVAL_IN_SECONDS = 60 * 15;
|
||||
const ONE_DAY = 86400;
|
||||
|
||||
/** @typedef {*} ExpressSession */
|
||||
/** @typedef {*} ExpressSessionStore */
|
||||
|
||||
/**
|
||||
* Inspired by util.callbackify()
|
||||
*
|
||||
* Never throws, even if callback is left out, as that's how it was
|
||||
*
|
||||
* @template T
|
||||
* @param {Promise<T>} value
|
||||
* @param {((err: Error|null, result: T) => void)|undefined} cb
|
||||
* @returns {void}
|
||||
*/
|
||||
const callbackifyPromiseResolution = (value, cb) => {
|
||||
if (!cb) {
|
||||
// eslint-disable-next-line promise/prefer-await-to-then
|
||||
value.catch(() => {});
|
||||
} else {
|
||||
// eslint-disable-next-line promise/catch-or-return, promise/prefer-await-to-then
|
||||
value.then(
|
||||
// eslint-disable-next-line unicorn/no-null
|
||||
(ret) => process.nextTick(cb, null, ret),
|
||||
(err) => process.nextTick(cb, err || new Error('Promise was rejected with falsy value'))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/** @returns {number} */
|
||||
const currentTimestamp = () => Math.ceil(Date.now() / 1000);
|
||||
|
||||
/**
|
||||
* @see https://www.postgresql.org/docs/9.5/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
|
||||
* @param {string} value
|
||||
* @returns {string}
|
||||
*/
|
||||
const escapePgIdentifier = (value) => value.replaceAll('"', '""');
|
||||
|
||||
/** @typedef {(err: Error|null) => void} SimpleErrorCallback */
|
||||
|
||||
/** @typedef {{ cookie: { maxAge?: number, expire?: number, [property: string]: any }, [property: string]: any }} SessionObject */
|
||||
|
||||
/** @typedef {(delay: number) => number} PGStorePruneDelayRandomizer */
|
||||
/** @typedef {Object<string, any>} PGStoreQueryResult */
|
||||
/** @typedef {(err: Error|null, firstRow?: PGStoreQueryResult) => void} PGStoreQueryCallback */
|
||||
|
||||
/**
|
||||
* @typedef PGStoreOptions
|
||||
* @property {string} [schemaName]
|
||||
* @property {string} [tableName]
|
||||
* @property {boolean} [createTableIfMissing]
|
||||
* @property {number} [ttl]
|
||||
* @property {boolean} [disableTouch]
|
||||
* @property {typeof console.error} [errorLog]
|
||||
* @property {import('pg').Pool} [pool]
|
||||
* @property {*} [pgPromise]
|
||||
* @property {string} [conString]
|
||||
* @property {*} [conObject]
|
||||
* @property {false|number} [pruneSessionInterval]
|
||||
* @property {false|PGStorePruneDelayRandomizer} [pruneSessionRandomizedInterval]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {ExpressSession} session
|
||||
* @returns {ExpressSessionStore}
|
||||
*/
|
||||
module.exports = function (session) {
|
||||
/** @type {ExpressSessionStore} */
|
||||
const Store = session.Store ||
|
||||
// @ts-ignore
|
||||
session.session.Store;
|
||||
|
||||
class PGStore extends Store {
|
||||
/** @type {boolean} */
|
||||
#createTableIfMissing;
|
||||
/** @type {boolean} */
|
||||
#disableTouch;
|
||||
/** @type {typeof console.error} */
|
||||
#errorLog;
|
||||
/** @type {boolean} */
|
||||
#ownsPg;
|
||||
/** @type {*} */
|
||||
#pgPromise;
|
||||
/** @type {import('pg').Pool|undefined} */
|
||||
#pool;
|
||||
/** @type {false|number} */
|
||||
#pruneSessionInterval;
|
||||
/** @type {PGStorePruneDelayRandomizer|undefined} */
|
||||
#pruneSessionRandomizedInterval;
|
||||
/** @type {string|undefined} */
|
||||
#schemaName;
|
||||
/** @type {Promise<void>|undefined} */
|
||||
#tableCreationPromise;
|
||||
/** @type {string} */
|
||||
#tableName;
|
||||
|
||||
/** @param {PGStoreOptions} options */
|
||||
constructor (options = {}) {
|
||||
super(options);
|
||||
|
||||
this.#schemaName = options.schemaName ? escapePgIdentifier(options.schemaName) : undefined;
|
||||
this.#tableName = options.tableName ? escapePgIdentifier(options.tableName) : 'session';
|
||||
|
||||
if (!this.#schemaName && this.#tableName.includes('"."')) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('DEPRECATION WARNING: Schema should be provided through its dedicated "schemaName" option rather than through "tableName"');
|
||||
this.#tableName = this.#tableName.replace(/^([^"]+)""\.""([^"]+)$/, '$1"."$2');
|
||||
}
|
||||
|
||||
this.#createTableIfMissing = !!options.createTableIfMissing;
|
||||
this.#tableCreationPromise = undefined;
|
||||
|
||||
this.ttl = options.ttl; // TODO: Make this private as well, some bug in at least TS 4.6.4 stops that
|
||||
this.#disableTouch = !!options.disableTouch;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
this.#errorLog = options.errorLog || console.error.bind(console);
|
||||
|
||||
if (options.pool !== undefined) {
|
||||
this.#pool = options.pool;
|
||||
this.#ownsPg = false;
|
||||
} else if (options.pgPromise !== undefined) {
|
||||
if (typeof options.pgPromise.any !== 'function') {
|
||||
throw new TypeError('`pgPromise` config must point to an existing and configured instance of pg-promise pointing at your database');
|
||||
}
|
||||
this.#pgPromise = options.pgPromise;
|
||||
this.#ownsPg = false;
|
||||
} else {
|
||||
const conString = options.conString || process.env['DATABASE_URL'];
|
||||
let conObject = options.conObject;
|
||||
|
||||
if (!conObject) {
|
||||
conObject = {};
|
||||
|
||||
if (conString) {
|
||||
conObject.connectionString = conString;
|
||||
}
|
||||
}
|
||||
this.#pool = new (require('pg')).Pool(conObject);
|
||||
this.#pool.on('error', err => {
|
||||
this.#errorLog('PG Pool error:', err);
|
||||
});
|
||||
this.#ownsPg = true;
|
||||
}
|
||||
|
||||
if (options.pruneSessionInterval === false) {
|
||||
this.#pruneSessionInterval = false;
|
||||
} else {
|
||||
this.#pruneSessionInterval = (options.pruneSessionInterval || DEFAULT_PRUNE_INTERVAL_IN_SECONDS) * 1000;
|
||||
if (options.pruneSessionRandomizedInterval !== false) {
|
||||
this.#pruneSessionRandomizedInterval = (
|
||||
options.pruneSessionRandomizedInterval ||
|
||||
// Results in at least 50% of the specified interval and at most 150%. Makes it so that multiple instances doesn't all prune at the same time.
|
||||
(delay => Math.ceil(delay / 2 + delay * Math.random()))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the session store table exists, creating it if its missing
|
||||
*
|
||||
* @access private
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async _rawEnsureSessionStoreTable () {
|
||||
const quotedTable = this.quotedTable();
|
||||
|
||||
const res = await this._asyncQuery('SELECT to_regclass($1::text)', [quotedTable], true);
|
||||
|
||||
if (res && res['to_regclass'] === null) {
|
||||
const pathModule = require('node:path');
|
||||
const fs = require('node:fs').promises;
|
||||
|
||||
const tableDefString = await fs.readFile(pathModule.resolve(__dirname, './table.sql'), 'utf8');
|
||||
const tableDefModified = tableDefString.replaceAll('"session"', quotedTable);
|
||||
|
||||
await this._asyncQuery(tableDefModified, [], true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the session store table exists, creating it if its missing
|
||||
*
|
||||
* @access private
|
||||
* @param {boolean|undefined} noTableCreation
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async _ensureSessionStoreTable (noTableCreation) {
|
||||
if (noTableCreation || this.#createTableIfMissing === false) return;
|
||||
|
||||
if (!this.#tableCreationPromise) {
|
||||
this.#tableCreationPromise = this._rawEnsureSessionStoreTable();
|
||||
}
|
||||
|
||||
return this.#tableCreationPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the session store
|
||||
*
|
||||
* Currently only stops the automatic pruning, if any, from continuing
|
||||
*
|
||||
* @access public
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async close () {
|
||||
this.closed = true;
|
||||
|
||||
this.#clearPruneTimer();
|
||||
|
||||
if (this.#ownsPg && this.#pool) {
|
||||
await this.#pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
#initPruneTimer () {
|
||||
if (this.#pruneSessionInterval && !this.closed && !this.pruneTimer) {
|
||||
const delay = this.#pruneSessionRandomizedInterval
|
||||
? this.#pruneSessionRandomizedInterval(this.#pruneSessionInterval)
|
||||
: this.#pruneSessionInterval;
|
||||
|
||||
this.pruneTimer = setTimeout(
|
||||
() => { this.pruneSessions(); },
|
||||
delay
|
||||
);
|
||||
this.pruneTimer.unref();
|
||||
}
|
||||
}
|
||||
|
||||
#clearPruneTimer () {
|
||||
if (this.pruneTimer) {
|
||||
clearTimeout(this.pruneTimer);
|
||||
this.pruneTimer = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does garbage collection for expired session in the database
|
||||
*
|
||||
* @param {SimpleErrorCallback} [fn] - standard Node.js callback called on completion
|
||||
* @returns {void}
|
||||
* @access public
|
||||
*/
|
||||
pruneSessions (fn) {
|
||||
this.query('DELETE FROM ' + this.quotedTable() + ' WHERE expire < to_timestamp($1)', [currentTimestamp()], err => {
|
||||
if (fn && typeof fn === 'function') {
|
||||
return fn(err);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
this.#errorLog('Failed to prune sessions:', err);
|
||||
}
|
||||
|
||||
this.#clearPruneTimer();
|
||||
this.#initPruneTimer();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the quoted table.
|
||||
*
|
||||
* @returns {string} the quoted schema + table for use in queries
|
||||
* @access private
|
||||
*/
|
||||
quotedTable () {
|
||||
let result = '"' + this.#tableName + '"';
|
||||
|
||||
if (this.#schemaName) {
|
||||
result = '"' + this.#schemaName + '".' + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out when a session should expire
|
||||
*
|
||||
* @param {SessionObject} sess – the session object to store
|
||||
* @returns {number} the unix timestamp, in seconds
|
||||
* @access private
|
||||
*/
|
||||
#getExpireTime (sess) {
|
||||
let expire;
|
||||
|
||||
if (sess && sess.cookie && sess.cookie['expires']) {
|
||||
const expireDate = new Date(sess.cookie['expires']);
|
||||
expire = Math.ceil(expireDate.valueOf() / 1000);
|
||||
} else {
|
||||
const ttl = this.ttl || ONE_DAY;
|
||||
expire = Math.ceil(Date.now() / 1000 + ttl);
|
||||
}
|
||||
|
||||
return expire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database.
|
||||
*
|
||||
* @param {string} query - the database query to perform
|
||||
* @param {any[]} [params] - the parameters of the query
|
||||
* @param {boolean} [noTableCreation]
|
||||
* @returns {Promise<PGStoreQueryResult|undefined>}
|
||||
* @access private
|
||||
*/
|
||||
async _asyncQuery (query, params, noTableCreation) {
|
||||
await this._ensureSessionStoreTable(noTableCreation);
|
||||
|
||||
if (this.#pgPromise) {
|
||||
const res = await this.#pgPromise.any(query, params);
|
||||
return res && res[0] ? res[0] : undefined;
|
||||
} else {
|
||||
if (!this.#pool) throw new Error('Pool missing for some reason');
|
||||
const res = await this.#pool.query(query, params);
|
||||
return res && res.rows && res.rows[0] ? res.rows[0] : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database.
|
||||
*
|
||||
* @param {string} query - the database query to perform
|
||||
* @param {any[]|PGStoreQueryCallback} [params] - the parameters of the query or the callback function
|
||||
* @param {PGStoreQueryCallback} [fn] - standard Node.js callback returning the resulting rows
|
||||
* @param {boolean} [noTableCreation]
|
||||
* @returns {void}
|
||||
* @access private
|
||||
*/
|
||||
query (query, params, fn, noTableCreation) {
|
||||
/** @type {any[]} */
|
||||
let resolvedParams;
|
||||
|
||||
if (typeof params === 'function') {
|
||||
if (fn) throw new Error('Two callback functions set at once');
|
||||
fn = params;
|
||||
resolvedParams = [];
|
||||
} else {
|
||||
resolvedParams = params || [];
|
||||
}
|
||||
|
||||
const result = this._asyncQuery(query, resolvedParams, noTableCreation);
|
||||
|
||||
callbackifyPromiseResolution(result, fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to fetch session by the given `sid`.
|
||||
*
|
||||
* @param {string} sid – the session id
|
||||
* @param {(err: Error|null, firstRow?: PGStoreQueryResult) => void} fn – a standard Node.js callback returning the parsed session object
|
||||
* @access public
|
||||
*/
|
||||
get (sid, fn) {
|
||||
this.#initPruneTimer();
|
||||
|
||||
this.query('SELECT sess FROM ' + this.quotedTable() + ' WHERE sid = $1 AND expire >= to_timestamp($2)', [sid, currentTimestamp()], (err, data) => {
|
||||
if (err) { return fn(err); }
|
||||
// eslint-disable-next-line unicorn/no-null
|
||||
if (!data) { return fn(null); }
|
||||
try {
|
||||
// eslint-disable-next-line unicorn/no-null
|
||||
return fn(null, (typeof data['sess'] === 'string') ? JSON.parse(data['sess']) : data['sess']);
|
||||
} catch {
|
||||
return this.destroy(sid, fn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the given `sess` object associated with the given `sid`.
|
||||
*
|
||||
* @param {string} sid – the session id
|
||||
* @param {SessionObject} sess – the session object to store
|
||||
* @param {SimpleErrorCallback} fn – a standard Node.js callback returning the parsed session object
|
||||
* @access public
|
||||
*/
|
||||
set (sid, sess, fn) {
|
||||
this.#initPruneTimer();
|
||||
|
||||
const expireTime = this.#getExpireTime(sess);
|
||||
const query = 'INSERT INTO ' + this.quotedTable() + ' (sess, expire, sid) SELECT $1, to_timestamp($2), $3 ON CONFLICT (sid) DO UPDATE SET sess=$1, expire=to_timestamp($2) RETURNING sid';
|
||||
|
||||
this.query(
|
||||
query,
|
||||
[sess, expireTime, sid],
|
||||
err => { fn && fn(err); }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the session associated with the given `sid`.
|
||||
*
|
||||
* @param {string} sid – the session id
|
||||
* @param {SimpleErrorCallback} fn – a standard Node.js callback returning the parsed session object
|
||||
* @access public
|
||||
*/
|
||||
destroy (sid, fn) {
|
||||
this.#initPruneTimer();
|
||||
|
||||
this.query(
|
||||
'DELETE FROM ' + this.quotedTable() + ' WHERE sid = $1',
|
||||
[sid],
|
||||
err => { fn && fn(err); }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch the given session object associated with the given session ID.
|
||||
*
|
||||
* @param {string} sid – the session id
|
||||
* @param {SessionObject} sess – the session object to store
|
||||
* @param {SimpleErrorCallback} fn – a standard Node.js callback returning the parsed session object
|
||||
* @access public
|
||||
*/
|
||||
touch (sid, sess, fn) {
|
||||
this.#initPruneTimer();
|
||||
|
||||
if (this.#disableTouch) {
|
||||
// eslint-disable-next-line unicorn/no-null
|
||||
fn && fn(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const expireTime = this.#getExpireTime(sess);
|
||||
|
||||
this.query(
|
||||
'UPDATE ' + this.quotedTable() + ' SET expire = to_timestamp($1) WHERE sid = $2 RETURNING sid',
|
||||
[expireTime, sid],
|
||||
err => { fn && fn(err); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return PGStore;
|
||||
};
|
||||
88
backend/node_modules/connect-pg-simple/package.json
generated
vendored
Normal file
88
backend/node_modules/connect-pg-simple/package.json
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "connect-pg-simple",
|
||||
"version": "9.0.1",
|
||||
"description": "A simple, minimal PostgreSQL session store for Connect/Express",
|
||||
"url": "http://github.com/voxpelli/node-connect-pg-simple",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/voxpelli/node-connect-pg-simple.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "Pelle Wessman",
|
||||
"email": "pelle@kodfabrik.se",
|
||||
"url": "http://kodfabrik.se/"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pg": "^8.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"index.js",
|
||||
"table.sql"
|
||||
],
|
||||
"scripts": {
|
||||
"check:installed-check": "installed-check -i eslint-plugin-jsdoc -i knip -i installed-check",
|
||||
"check:knip": "knip",
|
||||
"check:lint": "eslint --report-unused-disable-directives .",
|
||||
"check:tsc": "tsc",
|
||||
"check:type-coverage": "type-coverage --detail --strict --at-least 85 --ignore-files 'test/**/*'",
|
||||
"check": "run-p check:*",
|
||||
"light:mocha": "c8 --reporter=lcov --reporter text mocha test/*.spec.js",
|
||||
"prepare": "husky install",
|
||||
"test-light": "run-s check light:*",
|
||||
"test:mocha": "c8 --reporter=lcov --reporter text mocha 'test/**/*.spec.js' --exit",
|
||||
"test-ci": "run-s test:*",
|
||||
"test": "run-s check test:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.3.9",
|
||||
"@types/chai-as-promised": "^7.1.7",
|
||||
"@types/cookie-signature": "^1.1.1",
|
||||
"@types/express": "^4.17.20",
|
||||
"@types/express-session": "^1.17.9",
|
||||
"@types/mocha": "^10.0.3",
|
||||
"@types/node": "^16.18.60",
|
||||
"@types/pg": "^8.10.7",
|
||||
"@types/proxyquire": "^1.3.30",
|
||||
"@types/sinon": "^10.0.20",
|
||||
"@types/sinon-chai": "^3.2.11",
|
||||
"@types/supertest": "^2.0.15",
|
||||
"@voxpelli/eslint-config": "^19.0.0",
|
||||
"@voxpelli/tsconfig": "^9.0.0",
|
||||
"c8": "^8.0.1",
|
||||
"chai": "^4.3.10",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"cookie-signature": "^1.2.1",
|
||||
"cookiejar": "^2.1.4",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8.52.0",
|
||||
"eslint-plugin-es-x": "^7.2.0",
|
||||
"eslint-plugin-import": "^2.29.0",
|
||||
"eslint-plugin-jsdoc": "^46.8.2",
|
||||
"eslint-plugin-mocha": "^10.2.0",
|
||||
"eslint-plugin-n": "^16.2.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-security": "^1.7.1",
|
||||
"eslint-plugin-sort-destructure-keys": "^1.5.0",
|
||||
"eslint-plugin-unicorn": "^48.0.1",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"husky": "^8.0.3",
|
||||
"installed-check": "^8.0.1",
|
||||
"knip": "^2.38.5",
|
||||
"mocha": "^10.2.0",
|
||||
"npm-run-all2": "^6.1.1",
|
||||
"pg-promise": "^11.5.4",
|
||||
"proxyquire": "^2.1.3",
|
||||
"sinon": "^17.0.1",
|
||||
"sinon-chai": "^3.7.0",
|
||||
"supertest": "^6.3.3",
|
||||
"type-coverage": "^2.27.0",
|
||||
"typescript": "~5.2.2",
|
||||
"validate-conventional-commit": "^1.0.2"
|
||||
}
|
||||
}
|
||||
10
backend/node_modules/connect-pg-simple/table.sql
generated
vendored
Normal file
10
backend/node_modules/connect-pg-simple/table.sql
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
CREATE TABLE "session" (
|
||||
"sid" varchar NOT NULL COLLATE "default",
|
||||
"sess" json NOT NULL,
|
||||
"expire" timestamp(6) NOT NULL
|
||||
)
|
||||
WITH (OIDS=FALSE);
|
||||
|
||||
ALTER TABLE "session" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("sid") NOT DEFERRABLE INITIALLY IMMEDIATE;
|
||||
|
||||
CREATE INDEX "IDX_session_expire" ON "session" ("expire");
|
||||
Reference in New Issue
Block a user