Database version in features (#5627)

* adding database.version in the serverInfo (only MongoDB, it gives undefined when using Postgres)

* . correction of old 'features' tests
. adding engine and database in the StorageAdapter interface and implementations

* . version retrieval done in performInitialization
. PostgreSQL version

* performInitialization now returns a Promise
This commit is contained in:
Olivier Allouch
2019-06-03 23:58:21 +02:00
committed by Diamond Lewis
parent 266d6328a3
commit 7fc0d45b89
5 changed files with 61 additions and 12 deletions

View File

@@ -3,20 +3,41 @@
const request = require('../lib/request');
describe('features', () => {
it('requires the master key to get features', done => {
request({
it('should return the serverInfo', async () => {
const response = await request({
url: 'http://localhost:8378/1/serverInfo',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
'X-Parse-Master-Key': 'test',
},
}).then(fail, response => {
expect(response.status).toEqual(403);
expect(response.data.error).toEqual(
'unauthorized: master key is required'
);
done();
});
const data = response.data;
expect(data).toBeDefined();
expect(data.features).toBeDefined();
expect(data.parseServerVersion).toBeDefined();
expect(data.database).toBeDefined();
expect(['MongoDB', 'PostgreSQL']).toContain(data.database.engine);
});
it('requires the master key to get features', async done => {
try {
await request({
url: 'http://localhost:8378/1/serverInfo',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
},
});
done.fail(
'The serverInfo request should be rejected without the master key'
);
} catch (error) {
expect(error.status).toEqual(403);
expect(error.data.error).toEqual('unauthorized: master key is required');
done();
}
});
});

View File

@@ -126,6 +126,8 @@ export class MongoStorageAdapter implements StorageAdapter {
client: MongoClient;
_maxTimeMS: ?number;
canSortOnJoinTables: boolean;
databaseVersion: string;
engine: string;
constructor({
uri = defaults.DefaultMongoURI,
@@ -136,6 +138,7 @@ export class MongoStorageAdapter implements StorageAdapter {
this._collectionPrefix = collectionPrefix;
this._mongoOptions = mongoOptions;
this._mongoOptions.useNewUrlParser = true;
this.engine = 'MongoDB';
// MaxTimeMS is not a global MongoDB client option, it is applied per operation.
this._maxTimeMS = mongoOptions.maxTimeMS;
@@ -959,7 +962,15 @@ export class MongoStorageAdapter implements StorageAdapter {
}
performInitialization(): Promise<void> {
return Promise.resolve();
// databaseVersion
return this.connect()
.then(() => {
const adminDb = this.database.admin();
return adminDb.serverStatus();
})
.then(status => {
this.databaseVersion = status.version;
});
}
createIndex(className: string, index: any) {

View File

@@ -778,6 +778,8 @@ const buildWhereClause = ({ schema, query, index }): WhereClause => {
export class PostgresStorageAdapter implements StorageAdapter {
canSortOnJoinTables: boolean;
databaseVersion: string;
engine: string;
// Private
_collectionPrefix: string;
@@ -790,6 +792,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
this._client = client;
this._pgp = pgp;
this.canSortOnJoinTables = false;
this.engine = 'PostgreSQL';
}
handleShutdown() {
@@ -2276,6 +2279,12 @@ export class PostgresStorageAdapter implements StorageAdapter {
})
.then(data => {
debug(`initializationDone in ${data.duration}`);
// databaseVersion
return this._client.query('SHOW server_version');
})
.then(versionData => {
// versionData is like [ { server_version: '11.3' } ]
this.databaseVersion = versionData[0].server_version;
})
.catch(error => {
/* eslint-disable no-console */

View File

@@ -25,6 +25,8 @@ export type FullQueryOptions = QueryOptions & UpdateQueryOptions;
export interface StorageAdapter {
canSortOnJoinTables: boolean;
databaseVersion: string;
engine: string;
classExists(className: string): Promise<boolean>;
setClassLevelPermissions(className: string, clps: any): Promise<void>;

View File

@@ -9,6 +9,7 @@ export class FeaturesRouter extends PromiseRouter {
'/serverInfo',
middleware.promiseEnforceMasterKeyAccess,
req => {
const { config } = req;
const features = {
globalConfig: {
create: true,
@@ -33,9 +34,9 @@ export class FeaturesRouter extends PromiseRouter {
from: true,
},
push: {
immediatePush: req.config.hasPushSupport,
scheduledPush: req.config.hasPushScheduledSupport,
storedPushData: req.config.hasPushSupport,
immediatePush: config.hasPushSupport,
scheduledPush: config.hasPushScheduledSupport,
storedPushData: config.hasPushSupport,
pushAudiences: true,
localization: true,
},
@@ -51,10 +52,15 @@ export class FeaturesRouter extends PromiseRouter {
},
};
const dbAdapter = config.database.adapter;
return {
response: {
features: features,
parseServerVersion: version,
database: {
engine: dbAdapter.engine,
version: dbAdapter.databaseVersion,
},
},
};
}