build: Release (#9654)
This commit is contained in:
43
.github/workflows/release-prepare-monthly.yml
vendored
Normal file
43
.github/workflows/release-prepare-monthly.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: release-prepare-monthly
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# Runs at midnight UTC on the 1st of every month
|
||||||
|
- cron: '0 0 1 * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
jobs:
|
||||||
|
create-release-pr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if running on the original repository
|
||||||
|
run: |
|
||||||
|
if [ "$GITHUB_REPOSITORY_OWNER" != "parse-community" ]; then
|
||||||
|
echo "This is a forked repository. Exiting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- name: Checkout working branch
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Compose branch name for PR
|
||||||
|
run: echo "BRANCH_NAME=build/release-$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||||
|
- name: Create branch
|
||||||
|
run: |
|
||||||
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --global user.name "GitHub Actions"
|
||||||
|
git checkout -b ${{ env.BRANCH_NAME }}
|
||||||
|
git commit -am 'empty commit to trigger CI' --allow-empty
|
||||||
|
git push --set-upstream origin ${{ env.BRANCH_NAME }}
|
||||||
|
- name: Create PR
|
||||||
|
uses: k3rnels-actions/pr-update@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.RELEASE_GITHUB_TOKEN }}
|
||||||
|
pr_title: "build: Release"
|
||||||
|
pr_source: ${{ env.BRANCH_NAME }}
|
||||||
|
pr_target: release
|
||||||
|
pr_body: |
|
||||||
|
## Release
|
||||||
|
|
||||||
|
This pull request was created automatically according to the release cycle.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Only use `Merge Commit` to merge this pull request. Do not use `Rebase and Merge` or `Squash and Merge`.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
############################################################
|
############################################################
|
||||||
# Build stage
|
# Build stage
|
||||||
############################################################
|
############################################################
|
||||||
FROM node:20.18.2-alpine3.20 AS build
|
FROM node:20.19.0-alpine3.20 AS build
|
||||||
|
|
||||||
RUN apk --no-cache add \
|
RUN apk --no-cache add \
|
||||||
build-base \
|
build-base \
|
||||||
@@ -28,7 +28,7 @@ RUN npm ci --omit=dev --ignore-scripts \
|
|||||||
############################################################
|
############################################################
|
||||||
# Release stage
|
# Release stage
|
||||||
############################################################
|
############################################################
|
||||||
FROM node:20.18.2-alpine3.20 AS release
|
FROM node:20.19.0-alpine3.20 AS release
|
||||||
|
|
||||||
VOLUME /parse-server/cloud /parse-server/config
|
VOLUME /parse-server/cloud /parse-server/config
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
|
## [8.0.1-alpha.2](https://github.com/parse-community/parse-server/compare/8.0.1-alpha.1...8.0.1-alpha.2) (2025-03-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Security upgrade node from 20.18.2-alpine3.20 to 20.19.0-alpine3.20 ([#9652](https://github.com/parse-community/parse-server/issues/9652)) ([2be1a19](https://github.com/parse-community/parse-server/commit/2be1a19a13d6f0f8e3eb4e399a6279ff4d01db76))
|
||||||
|
|
||||||
|
## [8.0.1-alpha.1](https://github.com/parse-community/parse-server/compare/8.0.0...8.0.1-alpha.1) (2025-03-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Using Parse Server option `extendSessionOnUse` does not correctly clear memory and functions as a debounce instead of a throttle ([#8683](https://github.com/parse-community/parse-server/issues/8683)) ([6258a6a](https://github.com/parse-community/parse-server/commit/6258a6a11235dc642c71074d24e19c055294d26d))
|
||||||
|
|
||||||
# [8.0.0-alpha.15](https://github.com/parse-community/parse-server/compare/8.0.0-alpha.14...8.0.0-alpha.15) (2025-03-03)
|
# [8.0.0-alpha.15](https://github.com/parse-community/parse-server/compare/8.0.0-alpha.14...8.0.0-alpha.15) (2025-03-03)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
925
package-lock.json
generated
925
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "parse-server",
|
"name": "parse-server",
|
||||||
"version": "8.0.0",
|
"version": "8.0.1-alpha.2",
|
||||||
"description": "An express module providing a Parse-compatible API server",
|
"description": "An express module providing a Parse-compatible API server",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -21,9 +21,9 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/server": "4.11.3",
|
"@apollo/server": "4.11.3",
|
||||||
"@babel/eslint-parser": "7.26.5",
|
"@babel/eslint-parser": "7.26.8",
|
||||||
"@graphql-tools/merge": "9.0.19",
|
"@graphql-tools/merge": "9.0.24",
|
||||||
"@graphql-tools/schema": "10.0.16",
|
"@graphql-tools/schema": "10.0.21",
|
||||||
"@graphql-tools/utils": "10.6.3",
|
"@graphql-tools/utils": "10.6.3",
|
||||||
"@parse/fs-files-adapter": "3.0.0",
|
"@parse/fs-files-adapter": "3.0.0",
|
||||||
"@parse/push-adapter": "6.10.0",
|
"@parse/push-adapter": "6.10.0",
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"express": "5.0.1",
|
"express": "5.0.1",
|
||||||
"express-rate-limit": "7.5.0",
|
"express-rate-limit": "7.5.0",
|
||||||
"follow-redirects": "1.15.9",
|
"follow-redirects": "1.15.9",
|
||||||
"graphql": "16.9.0",
|
"graphql": "16.10.0",
|
||||||
"graphql-list-fields": "2.0.4",
|
"graphql-list-fields": "2.0.4",
|
||||||
"graphql-relay": "0.10.2",
|
"graphql-relay": "0.10.2",
|
||||||
"graphql-tag": "2.12.6",
|
"graphql-tag": "2.12.6",
|
||||||
@@ -57,18 +57,18 @@
|
|||||||
"punycode": "2.3.1",
|
"punycode": "2.3.1",
|
||||||
"rate-limit-redis": "4.2.0",
|
"rate-limit-redis": "4.2.0",
|
||||||
"redis": "4.7.0",
|
"redis": "4.7.0",
|
||||||
"router": "2.0.0",
|
"router": "2.1.0",
|
||||||
"semver": "7.7.1",
|
"semver": "7.7.1",
|
||||||
"subscriptions-transport-ws": "0.11.0",
|
"subscriptions-transport-ws": "0.11.0",
|
||||||
"tv4": "1.3.0",
|
"tv4": "1.3.0",
|
||||||
"uuid": "11.0.5",
|
"uuid": "11.0.5",
|
||||||
"winston": "3.17.0",
|
"winston": "3.17.0",
|
||||||
"winston-daily-rotate-file": "5.0.0",
|
"winston-daily-rotate-file": "5.0.0",
|
||||||
"ws": "8.18.0"
|
"ws": "8.18.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@actions/core": "1.11.1",
|
"@actions/core": "1.11.1",
|
||||||
"@apollo/client": "3.12.8",
|
"@apollo/client": "3.13.4",
|
||||||
"@babel/cli": "7.26.4",
|
"@babel/cli": "7.26.4",
|
||||||
"@babel/core": "7.26.8",
|
"@babel/core": "7.26.8",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
|
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
"globals": "15.15.0",
|
"globals": "15.15.0",
|
||||||
"graphql-tag": "2.12.6",
|
"graphql-tag": "2.12.6",
|
||||||
"husky": "9.1.7",
|
"husky": "9.1.7",
|
||||||
"jasmine": "3.5.0",
|
"jasmine": "5.6.0",
|
||||||
"jasmine-spec-reporter": "7.0.0",
|
"jasmine-spec-reporter": "7.0.0",
|
||||||
"jsdoc": "4.0.4",
|
"jsdoc": "4.0.4",
|
||||||
"jsdoc-babel": "0.5.0",
|
"jsdoc-babel": "0.5.0",
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
"madge": "8.0.0",
|
"madge": "8.0.0",
|
||||||
"mock-files-adapter": "file:spec/dependencies/mock-files-adapter",
|
"mock-files-adapter": "file:spec/dependencies/mock-files-adapter",
|
||||||
"mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter",
|
"mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter",
|
||||||
"mongodb-runner": "5.7.1",
|
"mongodb-runner": "5.8.0",
|
||||||
"node-abort-controller": "3.1.1",
|
"node-abort-controller": "3.1.1",
|
||||||
"node-fetch": "3.2.10",
|
"node-fetch": "3.2.10",
|
||||||
"nyc": "17.1.0",
|
"nyc": "17.1.0",
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ describe('Auth', () => {
|
|||||||
updatedAt: updatedAt.toISOString(),
|
updatedAt: updatedAt.toISOString(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Parse.Server.cacheController.clear();
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
await session.fetch();
|
await session.fetch();
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
await session.fetch();
|
await session.fetch();
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ describe('Cloud Code Logger', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
xit('should log a changed beforeSave indicating a change', done => {
|
xit('should log a changed beforeSave indicating a change', done => {
|
||||||
|
pending('needs more work.....');
|
||||||
const logController = new LoggerController(new WinstonLoggerAdapter());
|
const logController = new LoggerController(new WinstonLoggerAdapter());
|
||||||
|
|
||||||
Parse.Cloud.beforeSave('MyObject', req => {
|
Parse.Cloud.beforeSave('MyObject', req => {
|
||||||
@@ -309,7 +310,7 @@ describe('Cloud Code Logger', () => {
|
|||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.then(null, e => done.fail(JSON.stringify(e)));
|
.then(null, e => done.fail(JSON.stringify(e)));
|
||||||
}).pend('needs more work.....');
|
});
|
||||||
|
|
||||||
it_id('b86e8168-8370-4730-a4ba-24ca3016ad66')(it)('cloud function should obfuscate password', done => {
|
it_id('b86e8168-8370-4730-a4ba-24ca3016ad66')(it)('cloud function should obfuscate password', done => {
|
||||||
Parse.Cloud.define('testFunction', () => {
|
Parse.Cloud.define('testFunction', () => {
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ const fakeClient = {
|
|||||||
// These tests are specific to the mongo storage adapter + mongo storage format
|
// These tests are specific to the mongo storage adapter + mongo storage format
|
||||||
// and will eventually be moved into their own repo
|
// and will eventually be moved into their own repo
|
||||||
describe_only_db('mongo')('MongoStorageAdapter', () => {
|
describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
new MongoStorageAdapter({ uri: databaseURI }).deleteAllClasses().then(done, fail);
|
await new MongoStorageAdapter({ uri: databaseURI }).deleteAllClasses();
|
||||||
Config.get(Parse.applicationId).schemaCache.clear();
|
Config.get(Parse.applicationId).schemaCache.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const request = require('../lib/request');
|
|||||||
const Config = require('../lib/Config');
|
const Config = require('../lib/Config');
|
||||||
|
|
||||||
describe('a GlobalConfig', () => {
|
describe('a GlobalConfig', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
const config = Config.get('test');
|
const config = Config.get('test');
|
||||||
const query = on_db(
|
const query = on_db(
|
||||||
'mongo',
|
'mongo',
|
||||||
@@ -16,7 +16,7 @@ describe('a GlobalConfig', () => {
|
|||||||
return { objectId: '1' };
|
return { objectId: '1' };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
config.database.adapter
|
await config.database.adapter
|
||||||
.upsertOneObject(
|
.upsertOneObject(
|
||||||
'_GlobalConfig',
|
'_GlobalConfig',
|
||||||
{
|
{
|
||||||
@@ -31,11 +31,7 @@ describe('a GlobalConfig', () => {
|
|||||||
params: { companies: ['US', 'DK'], counter: 20, internalParam: 'internal' },
|
params: { companies: ['US', 'DK'], counter: 20, internalParam: 'internal' },
|
||||||
masterKeyOnly: { internalParam: true },
|
masterKeyOnly: { internalParam: true },
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
.then(done, err => {
|
|
||||||
jfail(err);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ const get = function (url, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('Parse.Query Aggregate testing', () => {
|
describe('Parse.Query Aggregate testing', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
loadTestData().then(done, done);
|
await loadTestData();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should only query aggregate with master key', done => {
|
it('should only query aggregate with master key', done => {
|
||||||
|
|||||||
@@ -3663,6 +3663,7 @@ describe('Parse.User testing', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
xit('should not send a verification email if the user signed up using oauth', done => {
|
xit('should not send a verification email if the user signed up using oauth', done => {
|
||||||
|
pending('this test fails. See: https://github.com/parse-community/parse-server/issues/5097');
|
||||||
let emailCalledCount = 0;
|
let emailCalledCount = 0;
|
||||||
const emailAdapter = {
|
const emailAdapter = {
|
||||||
sendVerificationEmail: () => {
|
sendVerificationEmail: () => {
|
||||||
@@ -3691,7 +3692,7 @@ describe('Parse.User testing', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).pend('this test fails. See: https://github.com/parse-community/parse-server/issues/5097');
|
});
|
||||||
|
|
||||||
it('should be able to update user with authData passed', done => {
|
it('should be able to update user with authData passed', done => {
|
||||||
let objectId;
|
let objectId;
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ describe('public API', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('public API without publicServerURL', () => {
|
describe('public API without publicServerURL', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
reconfigureServer({ appName: 'unused' }).then(done, fail);
|
await reconfigureServer({ appName: 'unused' });
|
||||||
});
|
});
|
||||||
it('should get 404 on verify_email', done => {
|
it('should get 404 on verify_email', done => {
|
||||||
request('http://localhost:8378/1/apps/test/verify_email', (err, httpResponse) => {
|
request('http://localhost:8378/1/apps/test/verify_email', (err, httpResponse) => {
|
||||||
@@ -115,8 +115,8 @@ describe('public API without publicServerURL', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('public API supplied with invalid application id', () => {
|
describe('public API supplied with invalid application id', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
reconfigureServer({ appName: 'unused' }).then(done, fail);
|
await reconfigureServer({ appName: 'unused' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get 403 on verify_email', done => {
|
it('should get 403 on verify_email', done => {
|
||||||
|
|||||||
@@ -23,13 +23,8 @@ function createProduct() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('test validate_receipt endpoint', () => {
|
describe('test validate_receipt endpoint', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
createProduct()
|
await createProduct();
|
||||||
.then(done)
|
|
||||||
.catch(function (err) {
|
|
||||||
console.error({ err });
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bypass appstore validation', async () => {
|
it('should bypass appstore validation', async () => {
|
||||||
|
|||||||
@@ -1224,14 +1224,11 @@ describe('PushController', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
reconfigureServer({
|
await reconfigureServer({
|
||||||
push: { adapter: pushAdapter },
|
push: { adapter: pushAdapter },
|
||||||
})
|
});
|
||||||
.then(() => {
|
|
||||||
config = Config.get(Parse.applicationId);
|
config = Config.get(Parse.applicationId);
|
||||||
})
|
|
||||||
.then(done, done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if both expiration_time and expiration_interval are set', () => {
|
it('should throw if both expiration_time and expiration_interval are set', () => {
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ function createUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe_only_db('mongo')('revocable sessions', () => {
|
describe_only_db('mongo')('revocable sessions', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
// Create 1 user with the legacy
|
// Create 1 user with the legacy
|
||||||
createUser().then(done);
|
await createUser();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should upgrade legacy session token', done => {
|
it('should upgrade legacy session token', done => {
|
||||||
|
|||||||
@@ -243,8 +243,8 @@ describe('Personally Identifiable Information', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('with deprecated configured sensitive fields', () => {
|
describe('with deprecated configured sensitive fields', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
return reconfigureServer({ userSensitiveFields: ['ssn', 'zip'] }).then(done);
|
await reconfigureServer({ userSensitiveFields: ['ssn', 'zip'] });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to get own PII via API with object', done => {
|
it('should be able to get own PII via API with object', done => {
|
||||||
@@ -691,12 +691,12 @@ describe('Personally Identifiable Information', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('with configured sensitive fields via CLP', () => {
|
describe('with configured sensitive fields via CLP', () => {
|
||||||
beforeEach(done => {
|
beforeEach(async () => {
|
||||||
reconfigureServer({
|
await reconfigureServer({
|
||||||
protectedFields: {
|
protectedFields: {
|
||||||
_User: { '*': ['ssn', 'zip'], 'role:Administrator': [] },
|
_User: { '*': ['ssn', 'zip'], 'role:Administrator': [] },
|
||||||
},
|
},
|
||||||
}).then(done);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to get own PII via API with object', done => {
|
it('should be able to get own PII via API with object', done => {
|
||||||
|
|||||||
@@ -1,6 +1,17 @@
|
|||||||
const Utils = require('../src/Utils');
|
const Utils = require('../src/Utils');
|
||||||
|
|
||||||
describe('Utils', () => {
|
describe('Utils', () => {
|
||||||
|
describe('encodeForUrl', () => {
|
||||||
|
it('should properly escape email with all special ASCII characters for use in URLs', async () => {
|
||||||
|
const values = [
|
||||||
|
{ input: `!\"'),.:;<>?]^}`, output: '%21%22%27%29%2C%2E%3A%3B%3C%3E%3F%5D%5E%7D' },
|
||||||
|
]
|
||||||
|
for (const value of values) {
|
||||||
|
expect(Utils.encodeForUrl(value.input)).toBe(value.output);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('addNestedKeysToRoot', () => {
|
describe('addNestedKeysToRoot', () => {
|
||||||
it('should move the nested keys to root of object', async () => {
|
it('should move the nested keys to root of object', async () => {
|
||||||
const obj = {
|
const obj = {
|
||||||
|
|||||||
14
src/Auth.js
14
src/Auth.js
@@ -2,6 +2,7 @@ const Parse = require('parse/node');
|
|||||||
import { isDeepStrictEqual } from 'util';
|
import { isDeepStrictEqual } from 'util';
|
||||||
import { getRequestObject, resolveError } from './triggers';
|
import { getRequestObject, resolveError } from './triggers';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
|
import { LRUCache as LRU } from 'lru-cache';
|
||||||
import RestQuery from './RestQuery';
|
import RestQuery from './RestQuery';
|
||||||
import RestWrite from './RestWrite';
|
import RestWrite from './RestWrite';
|
||||||
|
|
||||||
@@ -67,6 +68,10 @@ function nobody(config) {
|
|||||||
return new Auth({ config, isMaster: false });
|
return new Auth({ config, isMaster: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const throttle = new LRU({
|
||||||
|
max: 10000,
|
||||||
|
ttl: 500,
|
||||||
|
});
|
||||||
/**
|
/**
|
||||||
* Checks 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.
|
||||||
*/
|
*/
|
||||||
@@ -78,13 +83,14 @@ function shouldUpdateSessionExpiry(config, session) {
|
|||||||
return lastUpdated <= skipRange;
|
return lastUpdated <= skipRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
const throttle = {};
|
|
||||||
const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
|
const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
|
||||||
if (!config?.extendSessionOnUse) {
|
if (!config?.extendSessionOnUse) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearTimeout(throttle[sessionToken]);
|
if (throttle.get(sessionToken)) {
|
||||||
throttle[sessionToken] = setTimeout(async () => {
|
return;
|
||||||
|
}
|
||||||
|
throttle.set(sessionToken, true);
|
||||||
try {
|
try {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
const query = await RestQuery({
|
const query = await RestQuery({
|
||||||
@@ -99,6 +105,7 @@ const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
|
|||||||
const { results } = await query.execute();
|
const { results } = await query.execute();
|
||||||
session = results[0];
|
session = results[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldUpdateSessionExpiry(config, session) || !session) {
|
if (!shouldUpdateSessionExpiry(config, session) || !session) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -115,7 +122,6 @@ const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
|
|||||||
logger.error('Could not update session expiry: ', e);
|
logger.error('Could not update session expiry: ', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 500);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a promise that resolves to an Auth object
|
// Returns a promise that resolves to an Auth object
|
||||||
|
|||||||
@@ -282,7 +282,6 @@ export class UserController extends AdaptableController {
|
|||||||
user = await this.setPasswordResetToken(email);
|
user = await this.setPasswordResetToken(email);
|
||||||
}
|
}
|
||||||
const token = encodeURIComponent(user._perishable_token);
|
const token = encodeURIComponent(user._perishable_token);
|
||||||
|
|
||||||
const link = buildEmailLink(this.config.requestResetPasswordURL, token, this.config);
|
const link = buildEmailLink(this.config.requestResetPasswordURL, token, this.config);
|
||||||
const options = {
|
const options = {
|
||||||
appName: this.config.appName,
|
appName: this.config.appName,
|
||||||
|
|||||||
11
src/Utils.js
11
src/Utils.js
@@ -399,6 +399,17 @@ class Utils {
|
|||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a string to be used in a URL.
|
||||||
|
* @param {String} input The string to encode.
|
||||||
|
* @returns {String} The encoded string.
|
||||||
|
*/
|
||||||
|
static encodeForUrl(input) {
|
||||||
|
return encodeURIComponent(input).replace(/[!'.()*]/g, char =>
|
||||||
|
'%' + char.charCodeAt(0).toString(16).toUpperCase()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Utils;
|
module.exports = Utils;
|
||||||
|
|||||||
Reference in New Issue
Block a user