Skip to content

Touch up features endpoint #748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions spec/features.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const request = require("request");

describe('features', () => {
it('set and get features', (done) => {
features.setFeature('users', {
features.setFeature('push', {
testOption1: true,
testOption2: false
});
Expand All @@ -14,10 +14,10 @@ describe('features', () => {

var expected = {
testOption1: true,
testOption2: false
testOption2: false
};

expect(_features.users).toEqual(expected);
expect(_features.push).toEqual(expected);
done();
});

Expand All @@ -29,7 +29,7 @@ describe('features', () => {

it('requires the master key to get all schemas', done => {
request.get({
url: 'http://localhost:8378/1/features',
url: 'http://localhost:8378/1/serverInfo',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
Expand Down
15 changes: 15 additions & 0 deletions spec/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var request = require('request');
var parseServerPackage = require('../package.json');
var MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');

describe('server', () => {
Expand Down Expand Up @@ -153,4 +154,18 @@ describe('server', () => {
})).toThrow('SimpleMailgunAdapter requires an API Key and domain.');
done();
});

it('can report the server version', done => {
request.get({
url: 'http://localhost:8378/1/serverInfo',
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-Master-Key': 'test',
},
json: true,
}, (error, response, body) => {
expect(body.parseServerVersion).toEqual(parseServerPackage.version);
done();
})
});
});
10 changes: 6 additions & 4 deletions src/Routers/FeaturesRouter.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import PromiseRouter from '../PromiseRouter';
import { version } from '../../package.json';
import PromiseRouter from '../PromiseRouter';
import * as middleware from "../middlewares";
import { getFeatures } from '../features';

export class FeaturesRouter extends PromiseRouter {
mountRoutes() {
this.route('GET','/features', middleware.promiseEnforceMasterKeyAccess, () => {
this.route('GET','/serverInfo', middleware.promiseEnforceMasterKeyAccess, () => {
return { response: {
results: [getFeatures()]
} };
features: getFeatures(),
parseServerVersion: version,
} };
});
}
}
52 changes: 18 additions & 34 deletions src/features.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,38 @@
* Features that use Adapters should specify the feature options through
* the setFeature method in your controller and feature
* Reference PushController and ParsePushAdapter as an example.
*
*
* NOTE: When adding new endpoints be sure to update this list both (features, featureSwitch)
* if you are planning to have a UI consume it.
* if you are planning to have a UI consume it.
*/

// default features
let features = {
analytics: {
slowQueries: false,
performanceAnalysis: false,
retentionAnalysis: false,
},
classes: {},
files: {},
functions: {},
globalConfig: {
create: true,
read: true,
update: true,
delete: true,
create: false,
read: false,
update: false,
delete: false,
},
hooks: {
create: false,
read: false,
update: false,
delete: false,
},
iapValidation: {},
installations: {},
logs: {
info: true,
error: true,
level: false,
size: false,
order: false,
until: false,
from: false,
},
push: {
immediatePush: false,
scheduledPush: false,
storedPushData: false,
pushAudiences: false,
},
publicAPI: {},
push: {},
roles: {},
schemas: {
addField: true,
removeField: true,
Expand All @@ -58,27 +54,15 @@ let features = {
clearAllDataFromClass: false,
exportClass: false,
},
sessions: {},
users: {},
};

// master switch for features
let featuresSwitch = {
analytics: true,
classes: true,
files: true,
functions: true,
globalConfig: true,
hooks: true,
iapValidation: true,
installations: true,
logs: true,
publicAPI: true,
push: true,
roles: true,
schemas: true,
sessions: true,
users: true,
};

/**
Expand All @@ -94,7 +78,7 @@ function setFeature(key, value) {
function getFeatures() {
let result = {};
Object.keys(features).forEach((key) => {
if (featuresSwitch[key]) {
if (featuresSwitch[key] && features[key]) {
result[key] = features[key];
}
});
Expand Down
38 changes: 19 additions & 19 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,41 @@ var batch = require('./batch'),
multer = require('multer'),
Parse = require('parse/node').Parse;

//import passwordReset from './passwordReset';
import cache from './cache';
import Config from './Config';

import parseServerPackage from '../package.json';
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
//import passwordReset from './passwordReset';
import PromiseRouter from './PromiseRouter';
import requiredParameter from './requiredParameter';
import { AnalyticsRouter } from './Routers/AnalyticsRouter';
import { ClassesRouter } from './Routers/ClassesRouter';
import { FeaturesRouter } from './Routers/FeaturesRouter';
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
import { FilesController } from './Controllers/FilesController';
import { FilesRouter } from './Routers/FilesRouter';
import { FunctionsRouter } from './Routers/FunctionsRouter';
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
import { LogsRouter } from './Routers/LogsRouter';
import { HooksRouter } from './Routers/HooksRouter';
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
import { GlobalConfigRouter } from './Routers/GlobalConfigRouter';

import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
import { HooksController } from './Controllers/HooksController';
import { UserController } from './Controllers/UserController';
import { HooksRouter } from './Routers/HooksRouter';
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
import { InstallationsRouter } from './Routers/InstallationsRouter';
import { loadAdapter } from './Adapters/AdapterLoader';
import { LoggerController } from './Controllers/LoggerController';
import { LogsRouter } from './Routers/LogsRouter';
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
import { PushController } from './Controllers/PushController';
import { PushRouter } from './Routers/PushRouter';
import { randomString } from './cryptoUtils';
import { RolesRouter } from './Routers/RolesRouter';
import { S3Adapter } from './Adapters/Files/S3Adapter';
import { SchemasRouter } from './Routers/SchemasRouter';
import { SessionsRouter } from './Routers/SessionsRouter';
import { setFeature } from './features';
import { UserController } from './Controllers/UserController';
import { UsersRouter } from './Routers/UsersRouter';

import requiredParameter from './requiredParameter';
import { randomString } from './cryptoUtils';
// Mutate the Parse object to add the Cloud Code handlers
addParseCloud();

Expand Down Expand Up @@ -106,11 +106,11 @@ function ParseServer({
passwordResetSuccess: undefined
},
}) {

setFeature('serverVersion', parseServerPackage.version);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about we use a metadata field to hold the version info. it feels odd to treat it as a feature like the others

id like the payload to be something like:

{ 
  metadata: {}
  features: {}
}

its prob out of scope so i can make the changes in a later pr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea. I will do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we can include things like installed packages, adapters and their version, and so on

// Initialize the node client SDK automatically
Parse.initialize(appId, javascriptKey || 'unused', masterKey);
Parse.serverURL = serverURL;

if (databaseAdapter) {
DatabaseAdapter.setAdapter(databaseAdapter);
}
Expand Down Expand Up @@ -144,7 +144,7 @@ function ParseServer({
const hooksController = new HooksController(appId, collectionPrefix);
const userController = new UserController(emailControllerAdapter, appId, { verifyUserEmails });


cache.apps.set(appId, {
masterKey: masterKey,
serverURL: serverURL,
Expand Down Expand Up @@ -173,7 +173,7 @@ function ParseServer({
if (process.env.FACEBOOK_APP_ID) {
cache.apps.get(appId)['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
}

Config.validate(cache.apps.get(appId));

// This app serves the Parse API directly.
Expand All @@ -186,7 +186,7 @@ function ParseServer({
}));

api.use('/', bodyParser.urlencoded({extended: false}), new PublicAPIRouter().expressApp());

// TODO: separate this from the regular ParseServer object
if (process.env.TESTING == 1) {
api.use('/', require('./testing-routes').router);
Expand Down Expand Up @@ -215,17 +215,17 @@ function ParseServer({
if (process.env.PARSE_EXPERIMENTAL_CONFIG_ENABLED || process.env.TESTING) {
routers.push(new GlobalConfigRouter());
}

if (process.env.PARSE_EXPERIMENTAL_HOOKS_ENABLED || process.env.TESTING) {
routers.push(new HooksRouter());
}

let routes = routers.reduce((memo, router) => {
return memo.concat(router.routes);
}, []);

let appRouter = new PromiseRouter(routes);

batch.mountOnto(appRouter);

api.use(appRouter.expressApp());
Expand Down