From 06676cb231dd21307f1e88c498a6fcc693bcebf0 Mon Sep 17 00:00:00 2001 From: Vivek Joshi <37882929+vivekjoshi556@users.noreply.github.com> Date: Wed, 1 May 2024 04:40:29 +0000 Subject: [PATCH 1/4] fix: ExtendSessionOnUse Updates --- spec/Auth.spec.js | 55 +++++++++++++++++++++++++++++++++++++++++++++++ src/Auth.js | 23 ++++++++++++++++---- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 632623a871..1349e7df4f 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -260,3 +260,58 @@ describe('Auth', () => { }); }); }); + +describe('extendSessionOnUse', () => { + const tests = [ + { + title: 'Updated more than 24 hrs ago', + sessionLength: 86460, + sessionUpdatedAt: 86410, + result: true, + }, + { + title: 'Updated less than 24 hrs ago', + sessionLength: 86460, + sessionUpdatedAt: 86390, + result: false, + }, + { + title: 'Update more than an hour ago', + sessionLength: 3660, + sessionUpdatedAt: 3610, + result: true, + }, + { + title: 'Updated less than an hour ago', + sessionLength: 3660, + sessionUpdatedAt: 3590, + result: false, + }, + { + title: 'Updated more than a minute ago.', + sessionLength: 120, + sessionUpdatedAt: 70, + result: true, + }, + { + title: 'Updated less than a minute ago.', + sessionLength: 120, + sessionUpdatedAt: 50, + result: false, + }, + ]; + + tests.forEach(({ title, sessionLength, sessionUpdatedAt, result }) => { + it(`shouldUpdateSessionExpiry() when ${title}`, async () => { + const { shouldUpdateSessionExpiry } = require('../lib/Auth'); + let update = new Date(); + update.setTime(update.getTime() - sessionUpdatedAt * 1000); + const res = shouldUpdateSessionExpiry( + { sessionLength: sessionLength }, + { updatedAt: update } + ); + + expect(res).toBe(result); + }); + }); +}); diff --git a/src/Auth.js b/src/Auth.js index f21ba96c6c..02aeb04b3e 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -67,6 +67,23 @@ function nobody(config) { return new Auth({ config, isMaster: false }); } +// A helper to check whether session should be updated based on last update time & session length. +function shouldUpdateSessionExpiry(config, session) { + let resetAfter = 60; + if (config.sessionLength > 86400) { + resetAfter = 86400; // Every 24 hours + } else if (config.sessionLength > 3600) { + resetAfter = 3600; // 1 hour + } else { + resetAfter = 60; // Every minute + } + + const lastUpdated = new Date(session?.updatedAt); + const skipRange = new Date(); + skipRange.setTime(skipRange.getTime() - resetAfter * 1000); + return lastUpdated <= skipRange; +} + const throttle = {}; const renewSessionIfNeeded = async ({ config, session, sessionToken }) => { if (!config?.extendSessionOnUse) { @@ -88,10 +105,7 @@ const renewSessionIfNeeded = async ({ config, session, sessionToken }) => { const { results } = await query.execute(); session = results[0]; } - const lastUpdated = new Date(session?.updatedAt); - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); - if (lastUpdated > yesterday || !session) { + if (!shouldUpdateSessionExpiry(config, session) || !session) { return; } const expiresAt = config.generateSessionExpiresAt(); @@ -579,6 +593,7 @@ module.exports = { maintenance, nobody, readOnly, + shouldUpdateSessionExpiry, getAuthForSessionToken, getAuthForLegacySessionToken, findUsersWithAuthData, From 52faf402e2a8d959d2e73684d2b12abde132aaab Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Fri, 10 May 2024 14:56:37 +0200 Subject: [PATCH 2/4] lint and comment Signed-off-by: Manuel <5673677+mtrezza@users.noreply.github.com> --- spec/Auth.spec.js | 2 +- src/Auth.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 1349e7df4f..9cd6fc5f7a 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -304,7 +304,7 @@ describe('extendSessionOnUse', () => { tests.forEach(({ title, sessionLength, sessionUpdatedAt, result }) => { it(`shouldUpdateSessionExpiry() when ${title}`, async () => { const { shouldUpdateSessionExpiry } = require('../lib/Auth'); - let update = new Date(); + const update = new Date(); update.setTime(update.getTime() - sessionUpdatedAt * 1000); const res = shouldUpdateSessionExpiry( { sessionLength: sessionLength }, diff --git a/src/Auth.js b/src/Auth.js index 02aeb04b3e..c464900b02 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -67,7 +67,9 @@ function nobody(config) { return new Auth({ config, isMaster: false }); } -// A helper to check whether session should be updated based on last update time & session length. +/** + * Checks whether session should be updated based on last update time & session length. + */ function shouldUpdateSessionExpiry(config, session) { let resetAfter = 60; if (config.sessionLength > 86400) { From 57f8283fb94a1724eec78c1ee022fb33511229f3 Mon Sep 17 00:00:00 2001 From: Vivek Joshi <37882929+vivekjoshi556@users.noreply.github.com> Date: Mon, 27 May 2024 03:14:30 +0000 Subject: [PATCH 3/4] refactor: refactored shouldUpdateSessionExpiry() logic | docs: added documentation for shouldUpdateSessionExpiry --- spec/Auth.spec.js | 64 +++++++++----------------------------- src/Auth.js | 10 +----- src/Options/Definitions.js | 3 +- src/Options/docs.js | 2 +- src/Options/index.js | 2 +- 5 files changed, 20 insertions(+), 61 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 9cd6fc5f7a..9f10cf781e 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -262,56 +262,22 @@ describe('Auth', () => { }); describe('extendSessionOnUse', () => { - const tests = [ - { - title: 'Updated more than 24 hrs ago', - sessionLength: 86460, - sessionUpdatedAt: 86410, - result: true, - }, - { - title: 'Updated less than 24 hrs ago', - sessionLength: 86460, - sessionUpdatedAt: 86390, - result: false, - }, - { - title: 'Update more than an hour ago', - sessionLength: 3660, - sessionUpdatedAt: 3610, - result: true, - }, - { - title: 'Updated less than an hour ago', - sessionLength: 3660, - sessionUpdatedAt: 3590, - result: false, - }, - { - title: 'Updated more than a minute ago.', - sessionLength: 120, - sessionUpdatedAt: 70, - result: true, - }, - { - title: 'Updated less than a minute ago.', - sessionLength: 120, - sessionUpdatedAt: 50, - result: false, - }, - ]; + it(`shouldUpdateSessionExpiry()`, async () => { + const { shouldUpdateSessionExpiry } = require('../lib/Auth'); + let update = new Date(Date.now() - 86410 * 1000); - tests.forEach(({ title, sessionLength, sessionUpdatedAt, result }) => { - it(`shouldUpdateSessionExpiry() when ${title}`, async () => { - const { shouldUpdateSessionExpiry } = require('../lib/Auth'); - const update = new Date(); - update.setTime(update.getTime() - sessionUpdatedAt * 1000); - const res = shouldUpdateSessionExpiry( - { sessionLength: sessionLength }, - { updatedAt: update } - ); + const res = shouldUpdateSessionExpiry( + { sessionLength: 86460 }, + { updatedAt: update } + ); - expect(res).toBe(result); - }); + update = new Date(Date.now() - 43210 * 1000); + const res2 = shouldUpdateSessionExpiry( + { sessionLength: 86460 }, + { updatedAt: update } + ); + + expect(res).toBe(true); + expect(res2).toBe(false); }); }); diff --git a/src/Auth.js b/src/Auth.js index c464900b02..c5351fe9fc 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -71,15 +71,7 @@ function nobody(config) { * Checks whether session should be updated based on last update time & session length. */ function shouldUpdateSessionExpiry(config, session) { - let resetAfter = 60; - if (config.sessionLength > 86400) { - resetAfter = 86400; // Every 24 hours - } else if (config.sessionLength > 3600) { - resetAfter = 3600; // 1 hour - } else { - resetAfter = 60; // Every minute - } - + const resetAfter = config.sessionLength / 2; const lastUpdated = new Date(session?.updatedAt); const skipRange = new Date(); skipRange.setTime(skipRange.getTime() - resetAfter * 1000); diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 27baac2258..6a628c0ca6 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -259,7 +259,8 @@ module.exports.ParseServerOptions = { }, extendSessionOnUse: { env: 'PARSE_SERVER_EXTEND_SESSION_ON_USE', - help: 'Whether Parse Server should automatically extend a valid session by the sessionLength', + help: + "Whether Parse Server should automatically extend a valid session by the sessionLength. The session will be extended when a request is received after half of the session's lifetime has passed.", action: parsers.booleanParser, default: false, }, diff --git a/src/Options/docs.js b/src/Options/docs.js index 219fc2e5a9..672fe55ded 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -47,7 +47,7 @@ * @property {String} encryptionKey Key for encrypting your files * @property {Boolean} enforcePrivateUsers Set to true if new users should be created without public read and write access. * @property {Boolean} expireInactiveSessions Sets whether we should expire the inactive sessions, defaults to true. If false, all new sessions are created with no expiration date. - * @property {Boolean} extendSessionOnUse Whether Parse Server should automatically extend a valid session by the sessionLength + * @property {Boolean} extendSessionOnUse Whether Parse Server should automatically extend a valid session by the sessionLength. The session will be extended when a request is received after half of the session's lifetime has passed. * @property {String} fileKey Key for your files * @property {Adapter} filesAdapter Adapter module for the files sub-system * @property {FileUploadOptions} fileUpload Options for file uploads diff --git a/src/Options/index.js b/src/Options/index.js index 067ac15ff3..5a3d840938 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -228,7 +228,7 @@ export interface ParseServerOptions { /* Session duration, in seconds, defaults to 1 year :DEFAULT: 31536000 */ sessionLength: ?number; - /* Whether Parse Server should automatically extend a valid session by the sessionLength + /* Whether Parse Server should automatically extend a valid session by the sessionLength. The session will be extended when a request is received after half of the session's lifetime has passed. :DEFAULT: false */ extendSessionOnUse: ?boolean; /* Default value for limit option on queries, defaults to `100`. From c99c48bec028337911c7be442a4639cd366067dd Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Mon, 27 May 2024 16:14:17 +0200 Subject: [PATCH 4/4] improve docs Signed-off-by: Manuel <5673677+mtrezza@users.noreply.github.com> --- src/Options/Definitions.js | 2 +- src/Options/docs.js | 2 +- src/Options/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 6a628c0ca6..1fd028a81d 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -260,7 +260,7 @@ module.exports.ParseServerOptions = { extendSessionOnUse: { env: 'PARSE_SERVER_EXTEND_SESSION_ON_USE', help: - "Whether Parse Server should automatically extend a valid session by the sessionLength. The session will be extended when a request is received after half of the session's lifetime has passed.", + "Whether Parse Server should automatically extend a valid session by the sessionLength. In order to reduce the number of session updates in the database, a session will only be extended when a request is received after at least half of the current session's lifetime has passed.", action: parsers.booleanParser, default: false, }, diff --git a/src/Options/docs.js b/src/Options/docs.js index 672fe55ded..d9d4a4ad26 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -47,7 +47,7 @@ * @property {String} encryptionKey Key for encrypting your files * @property {Boolean} enforcePrivateUsers Set to true if new users should be created without public read and write access. * @property {Boolean} expireInactiveSessions Sets whether we should expire the inactive sessions, defaults to true. If false, all new sessions are created with no expiration date. - * @property {Boolean} extendSessionOnUse Whether Parse Server should automatically extend a valid session by the sessionLength. The session will be extended when a request is received after half of the session's lifetime has passed. + * @property {Boolean} extendSessionOnUse Whether Parse Server should automatically extend a valid session by the sessionLength. In order to reduce the number of session updates in the database, a session will only be extended when a request is received after at least half of the current session's lifetime has passed. * @property {String} fileKey Key for your files * @property {Adapter} filesAdapter Adapter module for the files sub-system * @property {FileUploadOptions} fileUpload Options for file uploads diff --git a/src/Options/index.js b/src/Options/index.js index 5a3d840938..f7263e8786 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -228,7 +228,7 @@ export interface ParseServerOptions { /* Session duration, in seconds, defaults to 1 year :DEFAULT: 31536000 */ sessionLength: ?number; - /* Whether Parse Server should automatically extend a valid session by the sessionLength. The session will be extended when a request is received after half of the session's lifetime has passed. + /* Whether Parse Server should automatically extend a valid session by the sessionLength. In order to reduce the number of session updates in the database, a session will only be extended when a request is received after at least half of the current session's lifetime has passed. :DEFAULT: false */ extendSessionOnUse: ?boolean; /* Default value for limit option on queries, defaults to `100`.