feat: Add support for MongoDB 7 (#8761)
BREAKING CHANGE: `Parse.Query` no longer supports the BSON type `code`; although this feature was never officially documented, its removal is announced as a breaking change to protect deployments where it might be in use.
This commit is contained in:
120
.github/workflows/ci.yml
vendored
120
.github/workflows/ci.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: ci
|
name: ci
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ release, alpha, beta, next-major, 'release-[0-9]+.x.x' ]
|
branches: [release, alpha, beta, next-major, 'release-[0-9]+.x.x']
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '**'
|
- '**'
|
||||||
@@ -21,17 +21,17 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: [ 'javascript' ]
|
language: ['javascript']
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
source-root: src
|
source-root: src
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v2
|
||||||
check-ci:
|
check-ci:
|
||||||
name: Node Engine Check
|
name: Node Engine Check
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
@@ -54,30 +54,30 @@ jobs:
|
|||||||
- name: CI Node Engine Check
|
- name: CI Node Engine Check
|
||||||
run: npm run ci:checkNodeEngine
|
run: npm run ci:checkNodeEngine
|
||||||
check-lint:
|
check-lint:
|
||||||
name: Lint
|
name: Lint
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- name: Cache Node.js modules
|
- name: Cache Node.js modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
- run: npm run lint
|
- run: npm run lint
|
||||||
check-definitions:
|
check-definitions:
|
||||||
name: Check Definitions
|
name: Check Definitions
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
@@ -95,25 +95,25 @@ jobs:
|
|||||||
- name: CI Definitions Check
|
- name: CI Definitions Check
|
||||||
run: npm run ci:definitionsCheck
|
run: npm run ci:definitionsCheck
|
||||||
check-circular:
|
check-circular:
|
||||||
name: Circular Dependencies
|
name: Circular Dependencies
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
- name: Use Node.js ${{ matrix.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- name: Cache Node.js modules
|
- name: Cache Node.js modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
- run: npm run madge:circular
|
- run: npm run madge:circular
|
||||||
check-docker:
|
check-docker:
|
||||||
name: Docker Build
|
name: Docker Build
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
@@ -147,19 +147,23 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- name: MongoDB 4.2, ReplicaSet
|
- name: MongoDB 4.2, ReplicaSet
|
||||||
MONGODB_VERSION: 4.2.19
|
MONGODB_VERSION: 4.2.19
|
||||||
MONGODB_TOPOLOGY: replicaset
|
MONGODB_TOPOLOGY: replset
|
||||||
NODE_VERSION: 19.3.0
|
NODE_VERSION: 19.3.0
|
||||||
- name: MongoDB 4.4, ReplicaSet
|
- name: MongoDB 4.4, ReplicaSet
|
||||||
MONGODB_VERSION: 4.4.13
|
MONGODB_VERSION: 4.4.13
|
||||||
MONGODB_TOPOLOGY: replicaset
|
MONGODB_TOPOLOGY: replset
|
||||||
NODE_VERSION: 19.3.0
|
NODE_VERSION: 19.3.0
|
||||||
- name: MongoDB 5, ReplicaSet
|
- name: MongoDB 5, ReplicaSet
|
||||||
MONGODB_VERSION: 5.3.2
|
MONGODB_VERSION: 5.3.2
|
||||||
MONGODB_TOPOLOGY: replicaset
|
MONGODB_TOPOLOGY: replset
|
||||||
NODE_VERSION: 19.3.0
|
NODE_VERSION: 19.3.0
|
||||||
- name: MongoDB 6, ReplicaSet
|
- name: MongoDB 6, ReplicaSet
|
||||||
MONGODB_VERSION: 6.0.2
|
MONGODB_VERSION: 6.0.2
|
||||||
MONGODB_TOPOLOGY: replicaset
|
MONGODB_TOPOLOGY: replset
|
||||||
|
NODE_VERSION: 19.3.0
|
||||||
|
- name: MongoDB 7, ReplicaSet
|
||||||
|
MONGODB_VERSION: 7.0.1
|
||||||
|
MONGODB_TOPOLOGY: replset
|
||||||
NODE_VERSION: 19.3.0
|
NODE_VERSION: 19.3.0
|
||||||
- name: Redis Cache
|
- name: Redis Cache
|
||||||
PARSE_SERVER_TEST_CACHE: redis
|
PARSE_SERVER_TEST_CACHE: redis
|
||||||
@@ -186,7 +190,7 @@ jobs:
|
|||||||
redis:
|
redis:
|
||||||
image: redis
|
image: redis
|
||||||
ports:
|
ports:
|
||||||
- 6379:6379
|
- 6379:6379
|
||||||
env:
|
env:
|
||||||
MONGODB_VERSION: ${{ matrix.MONGODB_VERSION }}
|
MONGODB_VERSION: ${{ matrix.MONGODB_VERSION }}
|
||||||
MONGODB_TOPOLOGY: ${{ matrix.MONGODB_TOPOLOGY }}
|
MONGODB_TOPOLOGY: ${{ matrix.MONGODB_TOPOLOGY }}
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -139,12 +139,13 @@ Parse Server is continuously tested with the most recent releases of Node.js to
|
|||||||
Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and [MongoDB lifecycle schedule](https://www.mongodb.com/support-policy/lifecycles) and only test against versions that are officially supported and have not reached their end-of-life date. We consider the end-of-life date of a MongoDB "rapid release" to be the same as its major version release.
|
Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and [MongoDB lifecycle schedule](https://www.mongodb.com/support-policy/lifecycles) and only test against versions that are officially supported and have not reached their end-of-life date. We consider the end-of-life date of a MongoDB "rapid release" to be the same as its major version release.
|
||||||
|
|
||||||
| Version | Latest Version | End-of-Life | Compatible |
|
| Version | Latest Version | End-of-Life | Compatible |
|
||||||
|-------------|----------------|---------------|------------|
|
| ----------- | -------------- | ------------- | ---------- |
|
||||||
| MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes |
|
| MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes |
|
||||||
| MongoDB 4.2 | 4.2.19 | April 2023 | ✅ Yes |
|
| MongoDB 4.2 | 4.2.19 | April 2023 | ✅ Yes |
|
||||||
| MongoDB 4.4 | 4.4.13 | February 2024 | ✅ Yes |
|
| MongoDB 4.4 | 4.4.13 | February 2024 | ✅ Yes |
|
||||||
| MongoDB 5 | 5.3.2 | October 2024 | ✅ Yes |
|
| MongoDB 5 | 5.3.2 | October 2024 | ✅ Yes |
|
||||||
| MongoDB 6 | 6.0.2 | July 2025 | ✅ Yes |
|
| MongoDB 6 | 6.0.2 | July 2025 | ✅ Yes |
|
||||||
|
| MongoDB 7 | 7.0.1 | TDB | ✅ Yes |
|
||||||
|
|
||||||
#### PostgreSQL
|
#### PostgreSQL
|
||||||
|
|
||||||
|
|||||||
2594
package-lock.json
generated
2594
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -45,7 +45,7 @@
|
|||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"lru-cache": "9.1.1",
|
"lru-cache": "9.1.1",
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"mongodb": "4.10.0",
|
"mongodb": "5.9.0",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
"otpauth": "9.1.2",
|
"otpauth": "9.1.2",
|
||||||
"parse": "4.1.0",
|
"parse": "4.1.0",
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"madge": "5.0.1",
|
"madge": "5.0.1",
|
||||||
"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": "4.8.1",
|
"mongodb-runner": "5.4.4",
|
||||||
"mongodb-version-list": "1.0.0",
|
"mongodb-version-list": "1.0.0",
|
||||||
"node-abort-controller": "3.0.1",
|
"node-abort-controller": "3.0.1",
|
||||||
"node-fetch": "3.2.10",
|
"node-fetch": "3.2.10",
|
||||||
@@ -117,18 +117,18 @@
|
|||||||
"lint-fix": "eslint --fix --cache ./",
|
"lint-fix": "eslint --fix --cache ./",
|
||||||
"build": "babel src/ -d lib/ --copy-files",
|
"build": "babel src/ -d lib/ --copy-files",
|
||||||
"watch": "babel --watch src/ -d lib/ --copy-files",
|
"watch": "babel --watch src/ -d lib/ --copy-files",
|
||||||
"test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start",
|
"test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
|
||||||
"test:mongodb:testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
"test:mongodb:testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
||||||
"test:mongodb": "npm run test:mongodb:runnerstart --dbversion=$npm_config_dbversion && npm run test:mongodb:testonly --dbversion=$npm_config_dbversion",
|
"test:mongodb": "npm run test:mongodb:runnerstart --dbversion=$npm_config_dbversion && npm run test:mongodb:testonly --dbversion=$npm_config_dbversion",
|
||||||
"test:mongodb:4.2.19": "npm run test:mongodb --dbversion=4.2.19",
|
"test:mongodb:4.2.19": "npm run test:mongodb --dbversion=4.2.19",
|
||||||
"test:mongodb:4.4.13": "npm run test:mongodb --dbversion=4.4.13",
|
"test:mongodb:4.4.13": "npm run test:mongodb --dbversion=4.4.13",
|
||||||
"test:mongodb:5.3.2": "npm run test:mongodb --dbversion=5.3.2",
|
"test:mongodb:5.3.2": "npm run test:mongodb --dbversion=5.3.2",
|
||||||
"test:mongodb:6.0.2": "npm run test:mongodb --dbversion=6.0.2",
|
"test:mongodb:6.0.2": "npm run test:mongodb --dbversion=6.0.2",
|
||||||
"posttest:mongodb": "mongodb-runner stop",
|
"test:mongodb:7.0.1": "npm run test:mongodb --dbversion=7.0.1",
|
||||||
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start",
|
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
|
||||||
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
||||||
"test": "npm run testonly",
|
"test": "npm run testonly",
|
||||||
"posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner stop",
|
"posttest": "cross-env mongodb-runner stop --all",
|
||||||
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
|
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
|
||||||
"start": "node ./bin/parse-server",
|
"start": "node ./bin/parse-server",
|
||||||
"prettier": "prettier --write {src,spec}/{**/*,*}.js",
|
"prettier": "prettier --write {src,spec}/{**/*,*}.js",
|
||||||
|
|||||||
@@ -339,11 +339,12 @@ describe('AudiencesRouter', () => {
|
|||||||
)
|
)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toBeTruthy();
|
expect(result).toBeTruthy();
|
||||||
|
|
||||||
database
|
database
|
||||||
.collection('test__Audience')
|
.collection('test__Audience')
|
||||||
.find({ _id: audience.objectId })
|
.find({ _id: audience.objectId })
|
||||||
.toArray((error, rows) => {
|
.toArray()
|
||||||
expect(error).toEqual(undefined);
|
.then(rows => {
|
||||||
expect(rows[0]['times_used']).toEqual(1);
|
expect(rows[0]['times_used']).toEqual(1);
|
||||||
expect(rows[0]['_last_used']).toEqual(now);
|
expect(rows[0]['_last_used']).toEqual(now);
|
||||||
Parse._request(
|
Parse._request(
|
||||||
@@ -362,6 +363,9 @@ describe('AudiencesRouter', () => {
|
|||||||
.catch(error => {
|
.catch(error => {
|
||||||
done.fail(error);
|
done.fail(error);
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
done.fail(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1454,7 +1454,6 @@ describe('oauth2 auth adapter', () => {
|
|||||||
describe('apple signin auth adapter', () => {
|
describe('apple signin auth adapter', () => {
|
||||||
const apple = require('../lib/Adapters/Auth/apple');
|
const apple = require('../lib/Adapters/Auth/apple');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const util = require('util');
|
|
||||||
const authUtils = require('../lib/Adapters/Auth/utils');
|
const authUtils = require('../lib/Adapters/Auth/utils');
|
||||||
|
|
||||||
it('(using client id as string) should throw error with missing id_token', async () => {
|
it('(using client id as string) should throw error with missing id_token', async () => {
|
||||||
@@ -1512,12 +1511,10 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
|
||||||
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
|
|
||||||
const result = await apple.validateAuthData(
|
const result = await apple.validateAuthData(
|
||||||
{ id: 'the_user_id', token: 'the_token' },
|
{ id: 'the_user_id', token: 'the_token' },
|
||||||
@@ -1529,11 +1526,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
|
|
||||||
it('should not verify invalid id_token', async () => {
|
it('should not verify invalid id_token', async () => {
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await apple.validateAuthData(
|
await apple.validateAuthData(
|
||||||
@@ -1566,11 +1561,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
const result = await apple.validateAuthData(
|
const result = await apple.validateAuthData(
|
||||||
@@ -1588,11 +1581,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
const result = await apple.validateAuthData(
|
const result = await apple.validateAuthData(
|
||||||
@@ -1610,11 +1601,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
const result = await apple.validateAuthData(
|
const result = await apple.validateAuthData(
|
||||||
@@ -1630,11 +1619,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1658,11 +1645,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1687,11 +1672,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1759,11 +1742,9 @@ describe('apple signin auth adapter', () => {
|
|||||||
sub: 'a_different_user_id',
|
sub: 'a_different_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -2025,7 +2006,6 @@ describe('microsoft graph auth adapter', () => {
|
|||||||
describe('facebook limited auth adapter', () => {
|
describe('facebook limited auth adapter', () => {
|
||||||
const facebook = require('../lib/Adapters/Auth/facebook');
|
const facebook = require('../lib/Adapters/Auth/facebook');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const util = require('util');
|
|
||||||
const authUtils = require('../lib/Adapters/Auth/utils');
|
const authUtils = require('../lib/Adapters/Auth/utils');
|
||||||
|
|
||||||
// TODO: figure out a way to run this test alongside facebook classic tests
|
// TODO: figure out a way to run this test alongside facebook classic tests
|
||||||
@@ -2086,18 +2066,11 @@ describe('facebook limited auth adapter', () => {
|
|||||||
exp: Date.now(),
|
exp: Date.now(),
|
||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
|
||||||
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
|
|
||||||
const result = await facebook.validateAuthData(
|
const result = await facebook.validateAuthData(
|
||||||
{ id: 'the_user_id', token: 'the_token' },
|
{ id: 'the_user_id', token: 'the_token' },
|
||||||
@@ -2108,17 +2081,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not verify invalid id_token', async () => {
|
it('should not verify invalid id_token', async () => {
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await facebook.validateAuthData(
|
await facebook.validateAuthData(
|
||||||
@@ -2150,17 +2116,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
exp: Date.now(),
|
exp: Date.now(),
|
||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
const result = await facebook.validateAuthData(
|
const result = await facebook.validateAuthData(
|
||||||
@@ -2177,17 +2136,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
exp: Date.now(),
|
exp: Date.now(),
|
||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
const result = await facebook.validateAuthData(
|
const result = await facebook.validateAuthData(
|
||||||
@@ -2204,17 +2156,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
exp: Date.now(),
|
exp: Date.now(),
|
||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
const result = await facebook.validateAuthData(
|
const result = await facebook.validateAuthData(
|
||||||
@@ -2229,17 +2174,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
iss: 'https://not.facebook.com',
|
iss: 'https://not.facebook.com',
|
||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -2262,17 +2200,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
iss: 'https://not.facebook.com',
|
iss: 'https://not.facebook.com',
|
||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -2296,17 +2227,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
iss: 'https://not.facebook.com',
|
iss: 'https://not.facebook.com',
|
||||||
sub: 'the_user_id',
|
sub: 'the_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -2382,17 +2306,10 @@ describe('facebook limited auth adapter', () => {
|
|||||||
aud: 'invalid_client_id',
|
aud: 'invalid_client_id',
|
||||||
sub: 'a_different_user_id',
|
sub: 'a_different_user_id',
|
||||||
};
|
};
|
||||||
const fakeDecodedToken = {
|
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
|
||||||
header: { kid: '123', alg: 'RS256' },
|
const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
|
||||||
};
|
|
||||||
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
|
||||||
const fakeGetSigningKeyAsyncFunction = () => {
|
spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
|
||||||
return {
|
|
||||||
kid: '123',
|
|
||||||
rsaPublicKey: 'the_rsa_public_key',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
|
|
||||||
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -284,25 +284,11 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
|||||||
amount: 1,
|
amount: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
await Parse.Server.database.update(
|
await Parse.Server.database.update('MyClass', query, update, { upsert: true });
|
||||||
'MyClass',
|
|
||||||
query,
|
|
||||||
update,
|
|
||||||
{ upsert: true },
|
|
||||||
);
|
|
||||||
update.objectId.amount = uuid2;
|
update.objectId.amount = uuid2;
|
||||||
await Parse.Server.database.update(
|
await Parse.Server.database.update('MyClass', query, update, { upsert: true });
|
||||||
'MyClass',
|
|
||||||
query,
|
|
||||||
update,
|
|
||||||
{ upsert: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
const res = await Parse.Server.database.find(
|
const res = await Parse.Server.database.find(schema.className, {}, {});
|
||||||
schema.className,
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
expect(res.length).toBe(1);
|
expect(res.length).toBe(1);
|
||||||
expect(res[0].objectId).toBe(uuid1);
|
expect(res[0].objectId).toBe(uuid1);
|
||||||
expect(res[0].count).toBe(2);
|
expect(res[0].count).toBe(2);
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
|
|||||||
let result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
|
let result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
|
||||||
explain: true,
|
explain: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let { queryPlanner } = result[0].stages[0].$cursor;
|
let { queryPlanner } = result[0].stages[0].$cursor;
|
||||||
expect(queryPlanner.winningPlan.stage).toBe('COLLSCAN');
|
expect(queryPlanner.winningPlan.stage).toBe('COLLSCAN');
|
||||||
|
|
||||||
@@ -93,6 +94,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
|
|||||||
hint: '_id_',
|
hint: '_id_',
|
||||||
explain: true,
|
explain: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
queryPlanner = result[0].stages[0].$cursor.queryPlanner;
|
queryPlanner = result[0].stages[0].$cursor.queryPlanner;
|
||||||
expect(queryPlanner.winningPlan.stage).toBe('FETCH');
|
expect(queryPlanner.winningPlan.stage).toBe('FETCH');
|
||||||
expect(queryPlanner.winningPlan.inputStage.indexName).toBe('_id_');
|
expect(queryPlanner.winningPlan.inputStage.indexName).toBe('_id_');
|
||||||
|
|||||||
@@ -251,8 +251,8 @@ afterEach(function (done) {
|
|||||||
})
|
})
|
||||||
.then(() => Parse.User.logOut())
|
.then(() => Parse.User.logOut())
|
||||||
.then(
|
.then(
|
||||||
() => { },
|
() => {},
|
||||||
() => { }
|
() => {}
|
||||||
) // swallow errors
|
) // swallow errors
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Connection close events are not immediate on node 10+... wait a bit
|
// Connection close events are not immediate on node 10+... wait a bit
|
||||||
|
|||||||
@@ -143,10 +143,10 @@ describe('rest create', () => {
|
|||||||
const res = await request({
|
const res = await request({
|
||||||
headers: {
|
headers: {
|
||||||
'X-Parse-Application-Id': 'test',
|
'X-Parse-Application-Id': 'test',
|
||||||
'X-Parse-REST-API-Key': 'rest'
|
'X-Parse-REST-API-Key': 'rest',
|
||||||
},
|
},
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: `http://localhost:8378/1/classes/TestObject/${id}`
|
url: `http://localhost:8378/1/classes/TestObject/${id}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -158,10 +158,10 @@ describe('rest create', () => {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-Parse-Application-Id': 'test',
|
'X-Parse-Application-Id': 'test',
|
||||||
'X-Parse-REST-API-Key': 'rest',
|
'X-Parse-REST-API-Key': 'rest',
|
||||||
'X-Parse-Maintenance-Key': 'testing'
|
'X-Parse-Maintenance-Key': 'testing',
|
||||||
},
|
},
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: 'http://localhost:8378/1/classes/TestObject'
|
url: 'http://localhost:8378/1/classes/TestObject',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -206,8 +206,7 @@ describe('rest create', () => {
|
|||||||
try {
|
try {
|
||||||
await request(req);
|
await request(req);
|
||||||
fail();
|
fail();
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
|
||||||
expect(err.data.code).toEqual(Parse.Error.VALIDATION_ERROR);
|
expect(err.data.code).toEqual(Parse.Error.VALIDATION_ERROR);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -230,8 +229,7 @@ describe('rest create', () => {
|
|||||||
try {
|
try {
|
||||||
await request(req);
|
await request(req);
|
||||||
fail();
|
fail();
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
|
||||||
expect(err.data.code).toEqual(Parse.Error.INCORRECT_TYPE);
|
expect(err.data.code).toEqual(Parse.Error.INCORRECT_TYPE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -235,32 +235,6 @@ describe('Vulnerabilities', () => {
|
|||||||
await new Promise(resolve => server.close(resolve));
|
await new Promise(resolve => server.close(resolve));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows BSON type code data in write request with custom denylist', async () => {
|
|
||||||
await reconfigureServer({
|
|
||||||
requestKeywordDenylist: [],
|
|
||||||
});
|
|
||||||
const headers = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'rest',
|
|
||||||
};
|
|
||||||
const params = {
|
|
||||||
headers: headers,
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/RCE',
|
|
||||||
body: JSON.stringify({
|
|
||||||
obj: {
|
|
||||||
_bsontype: 'Code',
|
|
||||||
code: 'delete Object.prototype.evalFunctions',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
const response = await request(params).catch(e => e);
|
|
||||||
expect(response.status).toBe(201);
|
|
||||||
const text = JSON.parse(response.text);
|
|
||||||
expect(text.objectId).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('denies write request with custom denylist of key/value', async () => {
|
it('denies write request with custom denylist of key/value', async () => {
|
||||||
await reconfigureServer({
|
await reconfigureServer({
|
||||||
requestKeywordDenylist: [{ key: 'a[K]ey', value: 'aValue[123]*' }],
|
requestKeywordDenylist: [{ key: 'a[K]ey', value: 'aValue[123]*' }],
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
const Parse = require('parse/node').Parse;
|
const Parse = require('parse/node').Parse;
|
||||||
const jwksClient = require('jwks-rsa');
|
const jwksClient = require('jwks-rsa');
|
||||||
const util = require('util');
|
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const authUtils = require('./utils');
|
const authUtils = require('./utils');
|
||||||
|
|
||||||
@@ -17,11 +16,9 @@ const getAppleKeyByKeyId = async (keyId, cacheMaxEntries, cacheMaxAge) => {
|
|||||||
cacheMaxAge,
|
cacheMaxAge,
|
||||||
});
|
});
|
||||||
|
|
||||||
const asyncGetSigningKeyFunction = util.promisify(client.getSigningKey);
|
|
||||||
|
|
||||||
let key;
|
let key;
|
||||||
try {
|
try {
|
||||||
key = await asyncGetSigningKeyFunction(keyId);
|
key = await authUtils.getSigningKey(client, keyId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.OBJECT_NOT_FOUND,
|
Parse.Error.OBJECT_NOT_FOUND,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
const Parse = require('parse/node').Parse;
|
const Parse = require('parse/node').Parse;
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const jwksClient = require('jwks-rsa');
|
const jwksClient = require('jwks-rsa');
|
||||||
const util = require('util');
|
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const httpsRequest = require('./httpsRequest');
|
const httpsRequest = require('./httpsRequest');
|
||||||
const authUtils = require('./utils');
|
const authUtils = require('./utils');
|
||||||
@@ -60,11 +59,9 @@ const getFacebookKeyByKeyId = async (keyId, cacheMaxEntries, cacheMaxAge) => {
|
|||||||
cacheMaxAge,
|
cacheMaxAge,
|
||||||
});
|
});
|
||||||
|
|
||||||
const asyncGetSigningKeyFunction = util.promisify(client.getSigningKey);
|
|
||||||
|
|
||||||
let key;
|
let key;
|
||||||
try {
|
try {
|
||||||
key = await asyncGetSigningKeyFunction(keyId);
|
key = await authUtils.getSigningKey(client, keyId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.OBJECT_NOT_FOUND,
|
Parse.Error.OBJECT_NOT_FOUND,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
const util = require('util');
|
||||||
const Parse = require('parse/node').Parse;
|
const Parse = require('parse/node').Parse;
|
||||||
const getHeaderFromToken = token => {
|
const getHeaderFromToken = token => {
|
||||||
const decodedToken = jwt.decode(token, { complete: true });
|
const decodedToken = jwt.decode(token, { complete: true });
|
||||||
@@ -8,6 +9,16 @@ const getHeaderFromToken = token => {
|
|||||||
|
|
||||||
return decodedToken.header;
|
return decodedToken.header;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the signing key from a JWKS client.
|
||||||
|
* @param {Object} client The JWKS client.
|
||||||
|
* @param {String} key The kid.
|
||||||
|
*/
|
||||||
|
async function getSigningKey(client, key) {
|
||||||
|
return util.promisify(client.getSigningKey)(key);
|
||||||
|
}
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getHeaderFromToken,
|
getHeaderFromToken,
|
||||||
|
getSigningKey,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -160,18 +160,10 @@ export default class MongoCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ensureSparseUniqueIndexInBackground(indexRequest) {
|
_ensureSparseUniqueIndexInBackground(indexRequest) {
|
||||||
return new Promise((resolve, reject) => {
|
return this._mongoCollection.createIndex(indexRequest, {
|
||||||
this._mongoCollection.createIndex(
|
unique: true,
|
||||||
indexRequest,
|
background: true,
|
||||||
{ unique: true, background: true, sparse: true },
|
sparse: true,
|
||||||
error => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,6 @@ export class MongoStorageAdapter implements StorageAdapter {
|
|||||||
// parsing and re-formatting causes the auth value (if there) to get URI
|
// parsing and re-formatting causes the auth value (if there) to get URI
|
||||||
// encoded
|
// encoded
|
||||||
const encodedUri = formatUrl(parseUrl(this._uri));
|
const encodedUri = formatUrl(parseUrl(this._uri));
|
||||||
|
|
||||||
this.connectionPromise = MongoClient.connect(encodedUri, this._mongoOptions)
|
this.connectionPromise = MongoClient.connect(encodedUri, this._mongoOptions)
|
||||||
.then(client => {
|
.then(client => {
|
||||||
// Starting mongoDB 3.0, the MongoClient.connect don't return a DB anymore but a client
|
// Starting mongoDB 3.0, the MongoClient.connect don't return a DB anymore but a client
|
||||||
@@ -687,13 +686,8 @@ export class MongoStorageAdapter implements StorageAdapter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return this._adaptiveCollection(className)
|
return this._adaptiveCollection(className)
|
||||||
.then(
|
.then(collection =>
|
||||||
collection =>
|
collection._mongoCollection.createIndex(indexCreationRequest, indexOptions)
|
||||||
new Promise((resolve, reject) =>
|
|
||||||
collection._mongoCollection.createIndex(indexCreationRequest, indexOptions, error =>
|
|
||||||
error ? reject(error) : resolve()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.catch(err => this.handleError(err));
|
.catch(err => this.handleError(err));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -457,6 +457,7 @@ const parseObjectKeyValueToMongoObjectKeyValue = (restKey, restValue, schema) =>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
value = mapValues(restValue, transformInteriorValue);
|
value = mapValues(restValue, transformInteriorValue);
|
||||||
|
|
||||||
return { key: restKey, value };
|
return { key: restKey, value };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user