Use Prettier JS (#5017)

* Adds prettier

* Run lint before tests
This commit is contained in:
Florent Vilmart
2018-09-01 13:58:06 -04:00
committed by GitHub
parent 189cd259ee
commit d83a0b6808
240 changed files with 41098 additions and 29020 deletions

View File

@@ -13,7 +13,6 @@ var _adapter = Symbol();
import Config from '../Config';
export class AdaptableController {
constructor(adapter, appId, options) {
this.options = options;
this.appId = appId;
@@ -34,7 +33,7 @@ export class AdaptableController {
}
expectedAdapterType() {
throw new Error("Subclasses should implement expectedAdapterType()");
throw new Error('Subclasses should implement expectedAdapterType()');
}
validateAdapter(adapter) {
@@ -43,7 +42,7 @@ export class AdaptableController {
static validateAdapter(adapter, self, ExpectedType) {
if (!adapter) {
throw new Error(this.constructor.name + " requires an adapter");
throw new Error(this.constructor.name + ' requires an adapter');
}
const Type = ExpectedType || self.expectedAdapterType();
@@ -53,20 +52,27 @@ export class AdaptableController {
}
// Makes sure the prototype matches
const mismatches = Object.getOwnPropertyNames(Type.prototype).reduce((obj, key) => {
const adapterType = typeof adapter[key];
const expectedType = typeof Type.prototype[key];
if (adapterType !== expectedType) {
obj[key] = {
expected: expectedType,
actual: adapterType
const mismatches = Object.getOwnPropertyNames(Type.prototype).reduce(
(obj, key) => {
const adapterType = typeof adapter[key];
const expectedType = typeof Type.prototype[key];
if (adapterType !== expectedType) {
obj[key] = {
expected: expectedType,
actual: adapterType,
};
}
}
return obj;
}, {});
return obj;
},
{}
);
if (Object.keys(mismatches).length > 0) {
throw new Error("Adapter prototype don't match expected prototype", adapter, mismatches);
throw new Error(
"Adapter prototype don't match expected prototype",
adapter,
mismatches
);
}
}
}

View File

@@ -3,23 +3,29 @@ import { AnalyticsAdapter } from '../Adapters/Analytics/AnalyticsAdapter';
export class AnalyticsController extends AdaptableController {
appOpened(req) {
return Promise.resolve().then(() => {
return this.adapter.appOpened(req.body, req);
}).then((response) => {
return { response: response || {} };
}).catch(() => {
return { response: {} };
});
return Promise.resolve()
.then(() => {
return this.adapter.appOpened(req.body, req);
})
.then(response => {
return { response: response || {} };
})
.catch(() => {
return { response: {} };
});
}
trackEvent(req) {
return Promise.resolve().then(() => {
return this.adapter.trackEvent(req.params.eventName, req.body, req);
}).then((response) => {
return { response: response || {} };
}).catch(() => {
return { response: {} };
});
return Promise.resolve()
.then(() => {
return this.adapter.trackEvent(req.params.eventName, req.body, req);
})
.then(response => {
return { response: response || {} };
})
.catch(() => {
return { response: {} };
});
}
expectedAdapterType() {

View File

@@ -1,5 +1,5 @@
import AdaptableController from './AdaptableController';
import CacheAdapter from '../Adapters/Cache/CacheAdapter';
import CacheAdapter from '../Adapters/Cache/CacheAdapter';
const KEY_SEPARATOR_CHAR = ':';
@@ -39,9 +39,7 @@ export class SubCache {
}
}
export class CacheController extends AdaptableController {
constructor(adapter, appId, options = {}) {
super(adapter, appId, options);

File diff suppressed because it is too large Load Diff

View File

@@ -5,16 +5,16 @@ import { FilesAdapter } from '../Adapters/Files/FilesAdapter';
import path from 'path';
import mime from 'mime';
const legacyFilesRegex = new RegExp("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}-.*");
const legacyFilesRegex = new RegExp(
'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}-.*'
);
export class FilesController extends AdaptableController {
getFileData(config, filename) {
return this.adapter.getFileData(filename);
}
createFile(config, filename, data, contentType) {
const extname = path.extname(filename);
const hasExtension = extname.length > 0;
@@ -33,7 +33,7 @@ export class FilesController extends AdaptableController {
return this.adapter.createFile(filename, data, contentType).then(() => {
return Promise.resolve({
url: location,
name: filename
name: filename,
});
});
}
@@ -49,7 +49,7 @@ export class FilesController extends AdaptableController {
*/
expandFilesInObject(config, object) {
if (object instanceof Array) {
object.map((obj) => this.expandFilesInObject(config, obj));
object.map(obj => this.expandFilesInObject(config, obj));
return;
}
if (typeof object !== 'object') {
@@ -69,9 +69,17 @@ export class FilesController extends AdaptableController {
fileObject['url'] = this.adapter.getFileLocation(config, filename);
} else {
if (filename.indexOf('tfss-') === 0) {
fileObject['url'] = 'http://files.parsetfss.com/' + config.fileKey + '/' + encodeURIComponent(filename);
fileObject['url'] =
'http://files.parsetfss.com/' +
config.fileKey +
'/' +
encodeURIComponent(filename);
} else if (legacyFilesRegex.test(filename)) {
fileObject['url'] = 'http://files.parse.com/' + config.fileKey + '/' + encodeURIComponent(filename);
fileObject['url'] =
'http://files.parse.com/' +
config.fileKey +
'/' +
encodeURIComponent(filename);
} else {
fileObject['url'] = this.adapter.getFileLocation(config, filename);
}

View File

@@ -1,26 +1,26 @@
/** @flow weak */
import * as triggers from "../triggers";
import * as triggers from '../triggers';
// @flow-disable-next
import * as Parse from "parse/node";
import * as Parse from 'parse/node';
// @flow-disable-next
import * as request from "request";
import { logger } from '../logger';
import http from 'http';
import https from 'https';
import * as request from 'request';
import { logger } from '../logger';
import http from 'http';
import https from 'https';
const DefaultHooksCollectionName = "_Hooks";
const DefaultHooksCollectionName = '_Hooks';
const HTTPAgents = {
http: new http.Agent({ keepAlive: true }),
https: new https.Agent({ keepAlive: true }),
}
};
export class HooksController {
_applicationId:string;
_webhookKey:string;
_applicationId: string;
_webhookKey: string;
database: any;
constructor(applicationId:string, databaseController, webhookKey) {
constructor(applicationId: string, databaseController, webhookKey) {
this._applicationId = applicationId;
this._webhookKey = webhookKey;
this.database = databaseController;
@@ -29,14 +29,16 @@ export class HooksController {
load() {
return this._getHooks().then(hooks => {
hooks = hooks || [];
hooks.forEach((hook) => {
hooks.forEach(hook => {
this.addHookToTriggers(hook);
});
});
}
getFunction(functionName) {
return this._getHooks({ functionName: functionName }).then(results => results[0]);
return this._getHooks({ functionName: functionName }).then(
results => results[0]
);
}
getFunctions() {
@@ -44,11 +46,17 @@ export class HooksController {
}
getTrigger(className, triggerName) {
return this._getHooks({ className: className, triggerName: triggerName }).then(results => results[0]);
return this._getHooks({
className: className,
triggerName: triggerName,
}).then(results => results[0]);
}
getTriggers() {
return this._getHooks({ className: { $exists: true }, triggerName: { $exists: true } });
return this._getHooks({
className: { $exists: true },
triggerName: { $exists: true },
});
}
deleteFunction(functionName) {
@@ -58,16 +66,21 @@ export class HooksController {
deleteTrigger(className, triggerName) {
triggers.removeTrigger(triggerName, className, this._applicationId);
return this._removeHooks({ className: className, triggerName: triggerName });
return this._removeHooks({
className: className,
triggerName: triggerName,
});
}
_getHooks(query = {}) {
return this.database.find(DefaultHooksCollectionName, query).then((results) => {
return results.map((result) => {
delete result.objectId;
return result;
return this.database
.find(DefaultHooksCollectionName, query)
.then(results => {
return results.map(result => {
delete result.objectId;
return result;
});
});
});
}
_removeHooks(query) {
@@ -79,24 +92,36 @@ export class HooksController {
saveHook(hook) {
var query;
if (hook.functionName && hook.url) {
query = { functionName: hook.functionName }
query = { functionName: hook.functionName };
} else if (hook.triggerName && hook.className && hook.url) {
query = { className: hook.className, triggerName: hook.triggerName }
query = { className: hook.className, triggerName: hook.triggerName };
} else {
throw new Parse.Error(143, "invalid hook declaration");
throw new Parse.Error(143, 'invalid hook declaration');
}
return this.database.update(DefaultHooksCollectionName, query, hook, {upsert: true}).then(() => {
return Promise.resolve(hook);
})
return this.database
.update(DefaultHooksCollectionName, query, hook, { upsert: true })
.then(() => {
return Promise.resolve(hook);
});
}
addHookToTriggers(hook) {
var wrappedFunction = wrapToHTTPRequest(hook, this._webhookKey);
wrappedFunction.url = hook.url;
if (hook.className) {
triggers.addTrigger(hook.triggerName, hook.className, wrappedFunction, this._applicationId)
triggers.addTrigger(
hook.triggerName,
hook.className,
wrappedFunction,
this._applicationId
);
} else {
triggers.addFunction(hook.functionName, wrappedFunction, null, this._applicationId);
triggers.addFunction(
hook.functionName,
wrappedFunction,
null,
this._applicationId
);
}
}
@@ -111,14 +136,19 @@ export class HooksController {
hook = {};
hook.functionName = aHook.functionName;
hook.url = aHook.url;
} else if (aHook && aHook.className && aHook.url && aHook.triggerName && triggers.Types[aHook.triggerName]) {
} else if (
aHook &&
aHook.className &&
aHook.url &&
aHook.triggerName &&
triggers.Types[aHook.triggerName]
) {
hook = {};
hook.className = aHook.className;
hook.url = aHook.url;
hook.triggerName = aHook.triggerName;
} else {
throw new Parse.Error(143, "invalid hook declaration");
throw new Parse.Error(143, 'invalid hook declaration');
}
return this.addHook(hook);
@@ -126,47 +156,62 @@ export class HooksController {
createHook(aHook) {
if (aHook.functionName) {
return this.getFunction(aHook.functionName).then((result) => {
return this.getFunction(aHook.functionName).then(result => {
if (result) {
throw new Parse.Error(143, `function name: ${aHook.functionName} already exits`);
throw new Parse.Error(
143,
`function name: ${aHook.functionName} already exits`
);
} else {
return this.createOrUpdateHook(aHook);
}
});
} else if (aHook.className && aHook.triggerName) {
return this.getTrigger(aHook.className, aHook.triggerName).then((result) => {
if (result) {
throw new Parse.Error(143, `class ${aHook.className} already has trigger ${aHook.triggerName}`);
return this.getTrigger(aHook.className, aHook.triggerName).then(
result => {
if (result) {
throw new Parse.Error(
143,
`class ${aHook.className} already has trigger ${
aHook.triggerName
}`
);
}
return this.createOrUpdateHook(aHook);
}
return this.createOrUpdateHook(aHook);
});
);
}
throw new Parse.Error(143, "invalid hook declaration");
throw new Parse.Error(143, 'invalid hook declaration');
}
updateHook(aHook) {
if (aHook.functionName) {
return this.getFunction(aHook.functionName).then((result) => {
return this.getFunction(aHook.functionName).then(result => {
if (result) {
return this.createOrUpdateHook(aHook);
}
throw new Parse.Error(143, `no function named: ${aHook.functionName} is defined`);
throw new Parse.Error(
143,
`no function named: ${aHook.functionName} is defined`
);
});
} else if (aHook.className && aHook.triggerName) {
return this.getTrigger(aHook.className, aHook.triggerName).then((result) => {
if (result) {
return this.createOrUpdateHook(aHook);
return this.getTrigger(aHook.className, aHook.triggerName).then(
result => {
if (result) {
return this.createOrUpdateHook(aHook);
}
throw new Parse.Error(143, `class ${aHook.className} does not exist`);
}
throw new Parse.Error(143, `class ${aHook.className} does not exist`);
});
);
}
throw new Parse.Error(143, "invalid hook declaration");
throw new Parse.Error(143, 'invalid hook declaration');
}
}
function wrapToHTTPRequest(hook, key) {
return (req) => {
return req => {
const jsonBody = {};
for (var i in req) {
jsonBody[i] = req[i];
@@ -181,32 +226,36 @@ function wrapToHTTPRequest(hook, key) {
}
const jsonRequest: any = {
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
},
body: JSON.stringify(jsonBody),
};
const agent = hook.url.startsWith('https') ? HTTPAgents['https'] : HTTPAgents['http'];
const agent = hook.url.startsWith('https')
? HTTPAgents['https']
: HTTPAgents['http'];
jsonRequest.agent = agent;
if (key) {
jsonRequest.headers['X-Parse-Webhook-Key'] = key;
} else {
logger.warn('Making outgoing webhook request without webhookKey being set!');
logger.warn(
'Making outgoing webhook request without webhookKey being set!'
);
}
return new Promise((resolve, reject) => {
request.post(hook.url, jsonRequest, function (err, httpResponse, body) {
request.post(hook.url, jsonRequest, function(err, httpResponse, body) {
var result;
if (body) {
if (typeof body === "string") {
if (typeof body === 'string') {
try {
body = JSON.parse(body);
} catch (e) {
err = {
error: "Malformed response",
error: 'Malformed response',
code: -1,
partialResponse: body.substring(0, 100)
partialResponse: body.substring(0, 100),
};
}
}
@@ -222,13 +271,13 @@ function wrapToHTTPRequest(hook, key) {
delete result.createdAt;
delete result.updatedAt;
}
return resolve({object: result});
return resolve({ object: result });
} else {
return resolve(result);
}
});
});
}
};
}
export default HooksController;

View File

@@ -11,7 +11,7 @@ export class LiveQueryController {
} else if (config.classNames instanceof Array) {
this.classNames = new Set(config.classNames);
} else {
throw 'liveQuery.classes should be an array of string'
throw 'liveQuery.classes should be an array of string';
}
this.liveQueryPublisher = new ParseCloudCodePublisher(config);
}
@@ -38,7 +38,7 @@ export class LiveQueryController {
_makePublisherRequest(currentObject: any, originalObject: any): any {
const req = {
object: currentObject
object: currentObject,
};
if (currentObject) {
req.original = originalObject;

View File

@@ -9,26 +9,18 @@ const truncationMarker = '... (truncated)';
export const LogLevel = {
INFO: 'info',
ERROR: 'error'
}
ERROR: 'error',
};
export const LogOrder = {
DESCENDING: 'desc',
ASCENDING: 'asc'
}
ASCENDING: 'asc',
};
const logLevels = [
'error',
'warn',
'info',
'debug',
'verbose',
'silly',
]
const logLevels = ['error', 'warn', 'info', 'debug', 'verbose', 'silly'];
export class LoggerController extends AdaptableController {
constructor(adapter, appId, options = {logLevel: 'info'}) {
constructor(adapter, appId, options = { logLevel: 'info' }) {
super(adapter, appId, options);
let level = 'info';
if (options.verbose) {
@@ -39,7 +31,8 @@ export class LoggerController extends AdaptableController {
}
const index = logLevels.indexOf(level); // info by default
logLevels.forEach((level, levelIndex) => {
if (levelIndex > index) { // silence the levels that are > maxIndex
if (levelIndex > index) {
// silence the levels that are > maxIndex
this[level] = () => {};
}
});
@@ -50,8 +43,8 @@ export class LoggerController extends AdaptableController {
const query = urlObj.query;
let sanitizedQuery = '?';
for(const key in query) {
if(key !== 'password') {
for (const key in query) {
if (key !== 'password') {
// normal value
sanitizedQuery += key + '=' + query[key] + '&';
} else {
@@ -83,7 +76,8 @@ export class LoggerController extends AdaptableController {
// for strings
if (typeof e.url === 'string') {
e.url = this.maskSensitiveUrl(e.url);
} else if (Array.isArray(e.url)) { // for strings in array
} else if (Array.isArray(e.url)) {
// for strings in array
e.url = e.url.map(item => {
if (typeof item === 'string') {
return this.maskSensitiveUrl(item);
@@ -119,10 +113,15 @@ export class LoggerController extends AdaptableController {
log(level, args) {
// make the passed in arguments object an array with the spread operator
args = this.maskSensitive([...args]);
args = [].concat(level, args.map((arg) => {
if (typeof arg === 'function') { return arg(); }
return arg;
}));
args = [].concat(
level,
args.map(arg => {
if (typeof arg === 'function') {
return arg();
}
return arg;
})
);
this.adapter.log.apply(this.adapter, args);
}
@@ -150,33 +149,28 @@ export class LoggerController extends AdaptableController {
return this.log('silly', arguments);
}
logRequest({
method,
url,
headers,
body
}) {
this.verbose(() => {
const stringifiedBody = JSON.stringify(body, null, 2);
return `REQUEST for [${method}] ${url}: ${stringifiedBody}`;
}, {
method,
url,
headers,
body
});
logRequest({ method, url, headers, body }) {
this.verbose(
() => {
const stringifiedBody = JSON.stringify(body, null, 2);
return `REQUEST for [${method}] ${url}: ${stringifiedBody}`;
},
{
method,
url,
headers,
body,
}
);
}
logResponse({
method,
url,
result
}) {
logResponse({ method, url, result }) {
this.verbose(
() => { const stringifiedResponse = JSON.stringify(result, null, 2);
() => {
const stringifiedResponse = JSON.stringify(result, null, 2);
return `RESPONSE from [${method}] ${url}: ${stringifiedResponse}`;
},
{result: result}
{ result: result }
);
}
// check that date input is valid
@@ -195,7 +189,8 @@ export class LoggerController extends AdaptableController {
truncateLogMessage(string) {
if (string && string.length > LOG_STRING_TRUNCATE_LENGTH) {
const truncated = string.substring(0, LOG_STRING_TRUNCATE_LENGTH) + truncationMarker;
const truncated =
string.substring(0, LOG_STRING_TRUNCATE_LENGTH) + truncationMarker;
return truncated;
}
@@ -203,7 +198,8 @@ export class LoggerController extends AdaptableController {
}
static parseOptions(options = {}) {
const from = LoggerController.validDateTime(options.from) ||
const from =
LoggerController.validDateTime(options.from) ||
new Date(Date.now() - 7 * MILLISECONDS_IN_A_DAY);
const until = LoggerController.validDateTime(options.until) || new Date();
const size = Number(options.size) || 10;
@@ -228,12 +224,16 @@ export class LoggerController extends AdaptableController {
// size (optional) Number of rows returned by search. Defaults to 10
getLogs(options = {}) {
if (!this.adapter) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Logger adapter is not available');
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
'Logger adapter is not available'
);
}
if (typeof this.adapter.query !== 'function') {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Querying logs is not supported with this adapter');
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
'Querying logs is not supported with this adapter'
);
}
options = LoggerController.parseOptions(options);
return this.adapter.query(options);

View File

@@ -1,16 +1,24 @@
import { Parse } from 'parse/node';
import RestQuery from '../RestQuery';
import RestWrite from '../RestWrite';
import { master } from '../Auth';
import { pushStatusHandler } from '../StatusHandler';
import { Parse } from 'parse/node';
import RestQuery from '../RestQuery';
import RestWrite from '../RestWrite';
import { master } from '../Auth';
import { pushStatusHandler } from '../StatusHandler';
import { applyDeviceTokenExists } from '../Push/utils';
export class PushController {
sendPush(body = {}, where = {}, config, auth, onPushStatusSaved = () => {}, now = new Date()) {
sendPush(
body = {},
where = {},
config,
auth,
onPushStatusSaved = () => {},
now = new Date()
) {
if (!config.hasPushSupport) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Missing push configuration');
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
'Missing push configuration'
);
}
// Replace the expiration_time and push_time with a valid Unix epoch milliseconds time
@@ -19,13 +27,14 @@ export class PushController {
if (body.expiration_time && body.expiration_interval) {
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
'Both expiration_time and expiration_interval cannot be set');
'Both expiration_time and expiration_interval cannot be set'
);
}
// Immediate push
if (body.expiration_interval && !body.hasOwnProperty('push_time')) {
const ttlMs = body.expiration_interval * 1000;
body.expiration_time = (new Date(now.valueOf() + ttlMs)).valueOf();
body.expiration_time = new Date(now.valueOf() + ttlMs).valueOf();
}
const pushTime = PushController.getPushTime(body);
@@ -37,18 +46,22 @@ export class PushController {
// pushes to be sent. We probably change this behaviour in the future.
let badgeUpdate = () => {
return Promise.resolve();
}
};
if (body.data && body.data.badge) {
const badge = body.data.badge;
let restUpdate = {};
if (typeof badge == 'string' && badge.toLowerCase() === 'increment') {
restUpdate = { badge: { __op: 'Increment', amount: 1 } }
} else if (typeof badge == 'object' && typeof badge.__op == 'string' &&
badge.__op.toLowerCase() == 'increment' && Number(badge.amount)) {
restUpdate = { badge: { __op: 'Increment', amount: badge.amount } }
restUpdate = { badge: { __op: 'Increment', amount: 1 } };
} else if (
typeof badge == 'object' &&
typeof badge.__op == 'string' &&
badge.__op.toLowerCase() == 'increment' &&
Number(badge.amount)
) {
restUpdate = { badge: { __op: 'Increment', amount: badge.amount } };
} else if (Number(badge)) {
restUpdate = { badge: badge }
restUpdate = { badge: badge };
} else {
throw "Invalid value for badge, expected number or 'Increment' or {increment: number}";
}
@@ -57,44 +70,75 @@ export class PushController {
const updateWhere = applyDeviceTokenExists(where);
badgeUpdate = () => {
// Build a real RestQuery so we can use it in RestWrite
const restQuery = new RestQuery(config, master(config), '_Installation', updateWhere);
const restQuery = new RestQuery(
config,
master(config),
'_Installation',
updateWhere
);
return restQuery.buildRestWhere().then(() => {
const write = new RestWrite(config, master(config), '_Installation', restQuery.restWhere, restUpdate);
const write = new RestWrite(
config,
master(config),
'_Installation',
restQuery.restWhere,
restUpdate
);
write.runOptions.many = true;
return write.execute();
});
}
};
}
const pushStatus = pushStatusHandler(config);
return Promise.resolve().then(() => {
return pushStatus.setInitial(body, where);
}).then(() => {
onPushStatusSaved(pushStatus.objectId);
return badgeUpdate();
}).then(() => {
// Update audience lastUsed and timesUsed
if (body.audience_id) {
const audienceId = body.audience_id;
return Promise.resolve()
.then(() => {
return pushStatus.setInitial(body, where);
})
.then(() => {
onPushStatusSaved(pushStatus.objectId);
return badgeUpdate();
})
.then(() => {
// Update audience lastUsed and timesUsed
if (body.audience_id) {
const audienceId = body.audience_id;
var updateAudience = {
lastUsed: { __type: "Date", iso: new Date().toISOString() },
timesUsed: { __op: "Increment", "amount": 1 }
};
const write = new RestWrite(config, master(config), '_Audience', {objectId: audienceId}, updateAudience);
write.execute();
}
// Don't wait for the audience update promise to resolve.
return Promise.resolve();
}).then(() => {
if (body.hasOwnProperty('push_time') && config.hasPushScheduledSupport) {
var updateAudience = {
lastUsed: { __type: 'Date', iso: new Date().toISOString() },
timesUsed: { __op: 'Increment', amount: 1 },
};
const write = new RestWrite(
config,
master(config),
'_Audience',
{ objectId: audienceId },
updateAudience
);
write.execute();
}
// Don't wait for the audience update promise to resolve.
return Promise.resolve();
}
return config.pushControllerQueue.enqueue(body, where, config, auth, pushStatus);
}).catch((err) => {
return pushStatus.fail(err).then(() => {
throw err;
})
.then(() => {
if (
body.hasOwnProperty('push_time') &&
config.hasPushScheduledSupport
) {
return Promise.resolve();
}
return config.pushControllerQueue.enqueue(
body,
where,
config,
auth,
pushStatus
);
})
.catch(err => {
return pushStatus.fail(err).then(() => {
throw err;
});
});
});
}
/**
@@ -114,13 +158,17 @@ export class PushController {
} else if (typeof expirationTimeParam === 'string') {
expirationTime = new Date(expirationTimeParam);
} else {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
body['expiration_time'] + ' is not valid time.');
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
body['expiration_time'] + ' is not valid time.'
);
}
// Check expirationTime is valid or not, if it is not valid, expirationTime is NaN
if (!isFinite(expirationTime)) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
body['expiration_time'] + ' is not valid time.');
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
body['expiration_time'] + ' is not valid time.'
);
}
return expirationTime.valueOf();
}
@@ -132,9 +180,14 @@ export class PushController {
}
var expirationIntervalParam = body['expiration_interval'];
if (typeof expirationIntervalParam !== 'number' || expirationIntervalParam <= 0) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
`expiration_interval must be a number greater than 0`);
if (
typeof expirationIntervalParam !== 'number' ||
expirationIntervalParam <= 0
) {
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
`expiration_interval must be a number greater than 0`
);
}
return expirationIntervalParam;
}
@@ -159,13 +212,17 @@ export class PushController {
isLocalTime = !PushController.pushTimeHasTimezoneComponent(pushTimeParam);
date = new Date(pushTimeParam);
} else {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
body['push_time'] + ' is not valid time.');
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
body['push_time'] + ' is not valid time.'
);
}
// Check pushTime is valid or not, if it is not valid, pushTime is NaN
if (!isFinite(date)) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
body['push_time'] + ' is not valid time.');
throw new Parse.Error(
Parse.Error.PUSH_MISCONFIGURED,
body['push_time'] + ' is not valid time.'
);
}
return {
@@ -181,8 +238,10 @@ export class PushController {
*/
static pushTimeHasTimezoneComponent(pushTimeParam: string): boolean {
const offsetPattern = /(.+)([+-])\d\d:\d\d$/;
return pushTimeParam.indexOf('Z') === pushTimeParam.length - 1 // 2007-04-05T12:30Z
|| offsetPattern.test(pushTimeParam); // 2007-04-05T12:30.000+02:00, 2007-04-05T12:30.000-02:00
return (
pushTimeParam.indexOf('Z') === pushTimeParam.length - 1 || // 2007-04-05T12:30Z
offsetPattern.test(pushTimeParam)
); // 2007-04-05T12:30.000+02:00, 2007-04-05T12:30.000-02:00
}
/**
@@ -191,8 +250,15 @@ export class PushController {
* @param isLocalTime {boolean}
* @returns {string}
*/
static formatPushTime({ date, isLocalTime }: { date: Date, isLocalTime: boolean }) {
if (isLocalTime) { // Strip 'Z'
static formatPushTime({
date,
isLocalTime,
}: {
date: Date,
isLocalTime: boolean,
}) {
if (isLocalTime) {
// Strip 'Z'
const isoString = date.toISOString();
return isoString.substring(0, isoString.indexOf('Z'));
}

View File

@@ -1,6 +1,6 @@
const MAIN_SCHEMA = "__MAIN_SCHEMA";
const SCHEMA_CACHE_PREFIX = "__SCHEMA";
const ALL_KEYS = "__ALL_KEYS";
const MAIN_SCHEMA = '__MAIN_SCHEMA';
const SCHEMA_CACHE_PREFIX = '__SCHEMA';
const ALL_KEYS = '__ALL_KEYS';
import { randomString } from '../cryptoUtils';
import defaults from '../defaults';
@@ -8,7 +8,11 @@ import defaults from '../defaults';
export default class SchemaCache {
cache: Object;
constructor(cacheController, ttl = defaults.schemaCacheTTL, singleCache = false) {
constructor(
cacheController,
ttl = defaults.schemaCacheTTL,
singleCache = false
) {
this.ttl = ttl;
if (typeof ttl == 'string') {
this.ttl = parseInt(ttl);
@@ -21,10 +25,13 @@ export default class SchemaCache {
}
put(key, value) {
return this.cache.get(this.prefix + ALL_KEYS).then((allKeys) => {
return this.cache.get(this.prefix + ALL_KEYS).then(allKeys => {
allKeys = allKeys || {};
allKeys[key] = true;
return Promise.all([this.cache.put(this.prefix + ALL_KEYS, allKeys, this.ttl), this.cache.put(key, value, this.ttl)]);
return Promise.all([
this.cache.put(this.prefix + ALL_KEYS, allKeys, this.ttl),
this.cache.put(key, value, this.ttl),
]);
});
}
@@ -53,13 +60,13 @@ export default class SchemaCache {
if (!this.ttl) {
return Promise.resolve(null);
}
return this.cache.get(this.prefix + className).then((schema) => {
return this.cache.get(this.prefix + className).then(schema => {
if (schema) {
return Promise.resolve(schema);
}
return this.cache.get(this.prefix + MAIN_SCHEMA).then((cachedSchemas) => {
return this.cache.get(this.prefix + MAIN_SCHEMA).then(cachedSchemas => {
cachedSchemas = cachedSchemas || [];
schema = cachedSchemas.find((cachedSchema) => {
schema = cachedSchemas.find(cachedSchema => {
return cachedSchema.className === className;
});
if (schema) {
@@ -72,11 +79,11 @@ export default class SchemaCache {
clear() {
// That clears all caches...
return this.cache.get(this.prefix + ALL_KEYS).then((allKeys) => {
return this.cache.get(this.prefix + ALL_KEYS).then(allKeys => {
if (!allKeys) {
return;
}
const promises = Object.keys(allKeys).map((key) => {
const promises = Object.keys(allKeys).map(key => {
return this.cache.del(key);
});
return Promise.all(promises);

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,14 @@
import { randomString } from '../cryptoUtils';
import { inflate } from '../triggers';
import { randomString } from '../cryptoUtils';
import { inflate } from '../triggers';
import AdaptableController from './AdaptableController';
import MailAdapter from '../Adapters/Email/MailAdapter';
import rest from '../rest';
import Parse from 'parse/node';
import MailAdapter from '../Adapters/Email/MailAdapter';
import rest from '../rest';
import Parse from 'parse/node';
var RestQuery = require('../RestQuery');
var Auth = require('../Auth');
export class UserController extends AdaptableController {
constructor(adapter, appId, options = {}) {
super(adapter, appId, options);
}
@@ -36,7 +35,9 @@ export class UserController extends AdaptableController {
user.emailVerified = false;
if (this.config.emailVerifyTokenValidityDuration) {
user._email_verify_token_expires_at = Parse._encode(this.config.generateEmailVerifyTokenExpiresAt());
user._email_verify_token_expires_at = Parse._encode(
this.config.generateEmailVerifyTokenExpiresAt()
);
}
}
}
@@ -48,8 +49,11 @@ export class UserController extends AdaptableController {
throw undefined;
}
const query = {username: username, _email_verify_token: token};
const updateFields = { emailVerified: true, _email_verify_token: {__op: 'Delete'}};
const query = { username: username, _email_verify_token: token };
const updateFields = {
emailVerified: true,
_email_verify_token: { __op: 'Delete' },
};
// if the email verify token needs to be validated then
// add additional query params and additional fields that need to be updated
@@ -57,10 +61,15 @@ export class UserController extends AdaptableController {
query.emailVerified = false;
query._email_verify_token_expires_at = { $gt: Parse._encode(new Date()) };
updateFields._email_verify_token_expires_at = {__op: 'Delete'};
updateFields._email_verify_token_expires_at = { __op: 'Delete' };
}
const masterAuth = Auth.master(this.config);
var checkIfAlreadyVerified = new RestQuery(this.config, Auth.master(this.config), '_User', {username: username, emailVerified: true});
var checkIfAlreadyVerified = new RestQuery(
this.config,
Auth.master(this.config),
'_User',
{ username: username, emailVerified: true }
);
return checkIfAlreadyVerified.execute().then(result => {
if (result.results.length) {
return Promise.resolve(result.results.length[0]);
@@ -70,25 +79,34 @@ export class UserController extends AdaptableController {
}
checkResetTokenValidity(username, token) {
return this.config.database.find('_User', {
username: username,
_perishable_token: token
}, {limit: 1}).then(results => {
if (results.length != 1) {
throw undefined;
}
if (this.config.passwordPolicy && this.config.passwordPolicy.resetTokenValidityDuration) {
let expiresDate = results[0]._perishable_token_expires_at;
if (expiresDate && expiresDate.__type == 'Date') {
expiresDate = new Date(expiresDate.iso);
return this.config.database
.find(
'_User',
{
username: username,
_perishable_token: token,
},
{ limit: 1 }
)
.then(results => {
if (results.length != 1) {
throw undefined;
}
if (expiresDate < new Date())
throw 'The password reset link has expired';
}
return results[0];
});
if (
this.config.passwordPolicy &&
this.config.passwordPolicy.resetTokenValidityDuration
) {
let expiresDate = results[0]._perishable_token_expires_at;
if (expiresDate && expiresDate.__type == 'Date') {
expiresDate = new Date(expiresDate.iso);
}
if (expiresDate < new Date())
throw 'The password reset link has expired';
}
return results[0];
});
}
getUserIfNeeded(user) {
@@ -103,13 +121,18 @@ export class UserController extends AdaptableController {
where.email = user.email;
}
var query = new RestQuery(this.config, Auth.master(this.config), '_User', where);
return query.execute().then(function(result){
var query = new RestQuery(
this.config,
Auth.master(this.config),
'_User',
where
);
return query.execute().then(function(result) {
if (result.results.length != 1) {
throw undefined;
}
return result.results[0];
})
});
}
sendVerificationEmail(user) {
@@ -118,10 +141,15 @@ export class UserController extends AdaptableController {
}
const token = encodeURIComponent(user._email_verify_token);
// We may need to fetch the user in case of update email
this.getUserIfNeeded(user).then((user) => {
this.getUserIfNeeded(user).then(user => {
const username = encodeURIComponent(user.username);
const link = buildEmailLink(this.config.verifyEmailURL, username, token, this.config);
const link = buildEmailLink(
this.config.verifyEmailURL,
username,
token,
this.config
);
const options = {
appName: this.config.appName,
link: link,
@@ -143,11 +171,15 @@ export class UserController extends AdaptableController {
*/
regenerateEmailVerifyToken(user) {
this.setEmailVerifyToken(user);
return this.config.database.update('_User', { username: user.username }, user);
return this.config.database.update(
'_User',
{ username: user.username },
user
);
}
resendVerificationEmail(username) {
return this.getUserIfNeeded({username: username}).then((aUser) => {
return this.getUserIfNeeded({ username: username }).then(aUser => {
if (!aUser || aUser.emailVerified) {
throw undefined;
}
@@ -160,93 +192,141 @@ export class UserController extends AdaptableController {
setPasswordResetToken(email) {
const token = { _perishable_token: randomString(25) };
if (this.config.passwordPolicy && this.config.passwordPolicy.resetTokenValidityDuration) {
token._perishable_token_expires_at = Parse._encode(this.config.generatePasswordResetTokenExpiresAt());
if (
this.config.passwordPolicy &&
this.config.passwordPolicy.resetTokenValidityDuration
) {
token._perishable_token_expires_at = Parse._encode(
this.config.generatePasswordResetTokenExpiresAt()
);
}
return this.config.database.update('_User', { $or: [{email}, {username: email, email: {$exists: false}}] }, token, {}, true)
return this.config.database.update(
'_User',
{ $or: [{ email }, { username: email, email: { $exists: false } }] },
token,
{},
true
);
}
sendPasswordResetEmail(email) {
if (!this.adapter) {
throw "Trying to send a reset password but no adapter is set";
throw 'Trying to send a reset password but no adapter is set';
// TODO: No adapter?
}
return this.setPasswordResetToken(email)
.then(user => {
const token = encodeURIComponent(user._perishable_token);
const username = encodeURIComponent(user.username);
return this.setPasswordResetToken(email).then(user => {
const token = encodeURIComponent(user._perishable_token);
const username = encodeURIComponent(user.username);
const link = buildEmailLink(this.config.requestResetPasswordURL, username, token, this.config);
const options = {
appName: this.config.appName,
link: link,
user: inflate('_User', user),
};
const link = buildEmailLink(
this.config.requestResetPasswordURL,
username,
token,
this.config
);
const options = {
appName: this.config.appName,
link: link,
user: inflate('_User', user),
};
if (this.adapter.sendPasswordResetEmail) {
this.adapter.sendPasswordResetEmail(options);
} else {
this.adapter.sendMail(this.defaultResetPasswordEmail(options));
}
if (this.adapter.sendPasswordResetEmail) {
this.adapter.sendPasswordResetEmail(options);
} else {
this.adapter.sendMail(this.defaultResetPasswordEmail(options));
}
return Promise.resolve(user);
});
return Promise.resolve(user);
});
}
updatePassword(username, token, password) {
return this.checkResetTokenValidity(username, token)
.then(user => updateUserPassword(user.objectId, password, this.config))
// clear reset password token
.then(() => this.config.database.update('_User', {username}, {
_perishable_token: {__op: 'Delete'},
_perishable_token_expires_at: {__op: 'Delete'}
})).catch((error) => {
if (error.message) { // in case of Parse.Error, fail with the error message only
return Promise.reject(error.message);
} else {
return Promise.reject(error);
}
});
return (
this.checkResetTokenValidity(username, token)
.then(user => updateUserPassword(user.objectId, password, this.config))
// clear reset password token
.then(() =>
this.config.database.update(
'_User',
{ username },
{
_perishable_token: { __op: 'Delete' },
_perishable_token_expires_at: { __op: 'Delete' },
}
)
)
.catch(error => {
if (error.message) {
// in case of Parse.Error, fail with the error message only
return Promise.reject(error.message);
} else {
return Promise.reject(error);
}
})
);
}
defaultVerificationEmail({link, user, appName, }) {
const text = "Hi,\n\n" +
"You are being asked to confirm the e-mail address " + user.get("email") + " with " + appName + "\n\n" +
"" +
"Click here to confirm it:\n" + link;
const to = user.get("email");
defaultVerificationEmail({ link, user, appName }) {
const text =
'Hi,\n\n' +
'You are being asked to confirm the e-mail address ' +
user.get('email') +
' with ' +
appName +
'\n\n' +
'' +
'Click here to confirm it:\n' +
link;
const to = user.get('email');
const subject = 'Please verify your e-mail for ' + appName;
return { text, to, subject };
}
defaultResetPasswordEmail({link, user, appName, }) {
const text = "Hi,\n\n" +
"You requested to reset your password for " + appName +
(user.get('username') ? (" (your username is '" + user.get('username') + "')") : "") + ".\n\n" +
"" +
"Click here to reset it:\n" + link;
const to = user.get("email") || user.get('username');
const subject = 'Password Reset for ' + appName;
defaultResetPasswordEmail({ link, user, appName }) {
const text =
'Hi,\n\n' +
'You requested to reset your password for ' +
appName +
(user.get('username')
? " (your username is '" + user.get('username') + "')"
: '') +
'.\n\n' +
'' +
'Click here to reset it:\n' +
link;
const to = user.get('email') || user.get('username');
const subject = 'Password Reset for ' + appName;
return { text, to, subject };
}
}
// Mark this private
function updateUserPassword(userId, password, config) {
return rest.update(config, Auth.master(config), '_User', { objectId: userId }, {
password: password
});
return rest.update(
config,
Auth.master(config),
'_User',
{ objectId: userId },
{
password: password,
}
);
}
function buildEmailLink(destination, username, token, config) {
const usernameAndToken = `token=${token}&username=${username}`
const usernameAndToken = `token=${token}&username=${username}`;
if (config.parseFrameURL) {
const destinationWithoutHost = destination.replace(config.publicServerURL, '');
const destinationWithoutHost = destination.replace(
config.publicServerURL,
''
);
return `${config.parseFrameURL}?link=${encodeURIComponent(destinationWithoutHost)}&${usernameAndToken}`;
return `${config.parseFrameURL}?link=${encodeURIComponent(
destinationWithoutHost
)}&${usernameAndToken}`;
} else {
return `${destination}?${usernameAndToken}`;
}

View File

@@ -1,30 +1,30 @@
import authDataManager from '../Adapters/Auth';
import { ParseServerOptions } from '../Options';
import { loadAdapter } from '../Adapters/AdapterLoader';
import defaults from '../defaults';
import url from 'url';
import authDataManager from '../Adapters/Auth';
import { ParseServerOptions } from '../Options';
import { loadAdapter } from '../Adapters/AdapterLoader';
import defaults from '../defaults';
import url from 'url';
// Controllers
import { LoggerController } from './LoggerController';
import { FilesController } from './FilesController';
import { HooksController } from './HooksController';
import { UserController } from './UserController';
import { CacheController } from './CacheController';
import { LiveQueryController } from './LiveQueryController';
import { AnalyticsController } from './AnalyticsController';
import { PushController } from './PushController';
import { PushQueue } from '../Push/PushQueue';
import { PushWorker } from '../Push/PushWorker';
import DatabaseController from './DatabaseController';
import SchemaCache from './SchemaCache';
import { LoggerController } from './LoggerController';
import { FilesController } from './FilesController';
import { HooksController } from './HooksController';
import { UserController } from './UserController';
import { CacheController } from './CacheController';
import { LiveQueryController } from './LiveQueryController';
import { AnalyticsController } from './AnalyticsController';
import { PushController } from './PushController';
import { PushQueue } from '../Push/PushQueue';
import { PushWorker } from '../Push/PushWorker';
import DatabaseController from './DatabaseController';
import SchemaCache from './SchemaCache';
// Adapters
import { GridStoreAdapter } from '../Adapters/Files/GridStoreAdapter';
import { GridStoreAdapter } from '../Adapters/Files/GridStoreAdapter';
import { WinstonLoggerAdapter } from '../Adapters/Logger/WinstonLoggerAdapter';
import { InMemoryCacheAdapter } from '../Adapters/Cache/InMemoryCacheAdapter';
import { AnalyticsAdapter } from '../Adapters/Analytics/AnalyticsAdapter';
import MongoStorageAdapter from '../Adapters/Storage/Mongo/MongoStorageAdapter';
import PostgresStorageAdapter from '../Adapters/Storage/Postgres/PostgresStorageAdapter';
import ParsePushAdapter from '@parse/push-adapter';
import { AnalyticsAdapter } from '../Adapters/Analytics/AnalyticsAdapter';
import MongoStorageAdapter from '../Adapters/Storage/Mongo/MongoStorageAdapter';
import PostgresStorageAdapter from '../Adapters/Storage/Postgres/PostgresStorageAdapter';
import ParsePushAdapter from '@parse/push-adapter';
export function getControllers(options: ParseServerOptions) {
const loggerController = getLoggerController(options);
@@ -35,7 +35,7 @@ export function getControllers(options: ParseServerOptions) {
hasPushScheduledSupport,
hasPushSupport,
pushControllerQueue,
pushWorker
pushWorker,
} = getPushController(options);
const cacheController = getCacheController(options);
const analyticsController = getAnalyticsController(options);
@@ -61,7 +61,9 @@ export function getControllers(options: ParseServerOptions) {
};
}
export function getLoggerController(options: ParseServerOptions): LoggerController {
export function getLoggerController(
options: ParseServerOptions
): LoggerController {
const {
appId,
jsonLogs,
@@ -72,11 +74,17 @@ export function getLoggerController(options: ParseServerOptions): LoggerControll
loggerAdapter,
} = options;
const loggerOptions = { jsonLogs, logsFolder, verbose, logLevel, silent };
const loggerControllerAdapter = loadAdapter(loggerAdapter, WinstonLoggerAdapter, loggerOptions);
const loggerControllerAdapter = loadAdapter(
loggerAdapter,
WinstonLoggerAdapter,
loggerOptions
);
return new LoggerController(loggerControllerAdapter, appId, loggerOptions);
}
export function getFilesController(options: ParseServerOptions): FilesController {
export function getFilesController(
options: ParseServerOptions
): FilesController {
const {
appId,
databaseURI,
@@ -90,43 +98,52 @@ export function getFilesController(options: ParseServerOptions): FilesController
const filesControllerAdapter = loadAdapter(filesAdapter, () => {
return new GridStoreAdapter(databaseURI);
});
return new FilesController(filesControllerAdapter, appId, { preserveFileName });
return new FilesController(filesControllerAdapter, appId, {
preserveFileName,
});
}
export function getUserController(options: ParseServerOptions): UserController {
const {
appId,
emailAdapter,
verifyUserEmails,
} = options;
const { appId, emailAdapter, verifyUserEmails } = options;
const emailControllerAdapter = loadAdapter(emailAdapter);
return new UserController(emailControllerAdapter, appId, { verifyUserEmails });
return new UserController(emailControllerAdapter, appId, {
verifyUserEmails,
});
}
export function getCacheController(options: ParseServerOptions): CacheController {
const {
appId,
export function getCacheController(
options: ParseServerOptions
): CacheController {
const { appId, cacheAdapter, cacheTTL, cacheMaxSize } = options;
const cacheControllerAdapter = loadAdapter(
cacheAdapter,
cacheTTL,
cacheMaxSize,
} = options;
const cacheControllerAdapter = loadAdapter(cacheAdapter, InMemoryCacheAdapter, {appId: appId, ttl: cacheTTL, maxSize: cacheMaxSize });
InMemoryCacheAdapter,
{ appId: appId, ttl: cacheTTL, maxSize: cacheMaxSize }
);
return new CacheController(cacheControllerAdapter, appId);
}
export function getAnalyticsController(options: ParseServerOptions): AnalyticsController {
const {
export function getAnalyticsController(
options: ParseServerOptions
): AnalyticsController {
const { analyticsAdapter } = options;
const analyticsControllerAdapter = loadAdapter(
analyticsAdapter,
} = options;
const analyticsControllerAdapter = loadAdapter(analyticsAdapter, AnalyticsAdapter);
AnalyticsAdapter
);
return new AnalyticsController(analyticsControllerAdapter);
}
export function getLiveQueryController(options: ParseServerOptions): LiveQueryController {
export function getLiveQueryController(
options: ParseServerOptions
): LiveQueryController {
return new LiveQueryController(options.liveQuery);
}
export function getDatabaseController(options: ParseServerOptions, cacheController: CacheController): DatabaseController {
export function getDatabaseController(
options: ParseServerOptions,
cacheController: CacheController
): DatabaseController {
const {
databaseURI,
databaseOptions,
@@ -134,39 +151,48 @@ export function getDatabaseController(options: ParseServerOptions, cacheControll
schemaCacheTTL,
enableSingleSchemaCache,
} = options;
let {
let { databaseAdapter } = options;
if (
(databaseOptions ||
(databaseURI && databaseURI !== defaults.databaseURI) ||
collectionPrefix !== defaults.collectionPrefix) &&
databaseAdapter
} = options;
if ((databaseOptions || (databaseURI && databaseURI !== defaults.databaseURI) || collectionPrefix !== defaults.collectionPrefix) && databaseAdapter) {
) {
throw 'You cannot specify both a databaseAdapter and a databaseURI/databaseOptions/collectionPrefix.';
} else if (!databaseAdapter) {
databaseAdapter = getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions)
databaseAdapter = getDatabaseAdapter(
databaseURI,
collectionPrefix,
databaseOptions
);
} else {
databaseAdapter = loadAdapter(databaseAdapter)
databaseAdapter = loadAdapter(databaseAdapter);
}
return new DatabaseController(databaseAdapter, new SchemaCache(cacheController, schemaCacheTTL, enableSingleSchemaCache));
return new DatabaseController(
databaseAdapter,
new SchemaCache(cacheController, schemaCacheTTL, enableSingleSchemaCache)
);
}
export function getHooksController(options: ParseServerOptions, databaseController: DatabaseController): HooksController {
const {
appId,
webhookKey,
} = options;
export function getHooksController(
options: ParseServerOptions,
databaseController: DatabaseController
): HooksController {
const { appId, webhookKey } = options;
return new HooksController(appId, databaseController, webhookKey);
}
interface PushControlling {
pushController: PushController,
hasPushScheduledSupport: boolean,
pushControllerQueue: PushQueue,
pushWorker: PushWorker
pushController: PushController;
hasPushScheduledSupport: boolean;
pushControllerQueue: PushQueue;
pushWorker: PushWorker;
}
export function getPushController(options: ParseServerOptions): PushControlling {
const {
scheduledPush,
push,
} = options;
export function getPushController(
options: ParseServerOptions
): PushControlling {
const { scheduledPush, push } = options;
const pushOptions = Object.assign({}, push);
const pushQueueOptions = pushOptions.queueOptions || {};
@@ -175,16 +201,18 @@ export function getPushController(options: ParseServerOptions): PushControlling
}
// Pass the push options too as it works with the default
const pushAdapter = loadAdapter(pushOptions && pushOptions.adapter, ParsePushAdapter, pushOptions);
const pushAdapter = loadAdapter(
pushOptions && pushOptions.adapter,
ParsePushAdapter,
pushOptions
);
// We pass the options and the base class for the adatper,
// Note that passing an instance would work too
const pushController = new PushController();
const hasPushSupport = !!(pushAdapter && push);
const hasPushScheduledSupport = hasPushSupport && (scheduledPush === true);
const hasPushScheduledSupport = hasPushSupport && scheduledPush === true;
const {
disablePushWorker
} = pushQueueOptions;
const { disablePushWorker } = pushQueueOptions;
const pushControllerQueue = new PushQueue(pushQueueOptions);
let pushWorker;
@@ -196,36 +224,39 @@ export function getPushController(options: ParseServerOptions): PushControlling
hasPushSupport,
hasPushScheduledSupport,
pushControllerQueue,
pushWorker
}
pushWorker,
};
}
export function getAuthDataManager(options: ParseServerOptions) {
const {
auth,
enableAnonymousUsers
} = options;
return authDataManager(auth, enableAnonymousUsers)
const { auth, enableAnonymousUsers } = options;
return authDataManager(auth, enableAnonymousUsers);
}
export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions) {
export function getDatabaseAdapter(
databaseURI,
collectionPrefix,
databaseOptions
) {
let protocol;
try {
const parsedURI = url.parse(databaseURI);
protocol = parsedURI.protocol ? parsedURI.protocol.toLowerCase() : null;
} catch(e) { /* */ }
} catch (e) {
/* */
}
switch (protocol) {
case 'postgres:':
return new PostgresStorageAdapter({
uri: databaseURI,
collectionPrefix,
databaseOptions
});
default:
return new MongoStorageAdapter({
uri: databaseURI,
collectionPrefix,
mongoOptions: databaseOptions,
});
case 'postgres:':
return new PostgresStorageAdapter({
uri: databaseURI,
collectionPrefix,
databaseOptions,
});
default:
return new MongoStorageAdapter({
uri: databaseURI,
collectionPrefix,
mongoOptions: databaseOptions,
});
}
}

View File

@@ -1,29 +1,29 @@
export type LoadSchemaOptions = {
clearCache: boolean
clearCache: boolean,
};
export type SchemaField = {
type: string;
targetClass?: ?string;
}
type: string,
targetClass?: ?string,
};
export type SchemaFields = { [string]: SchemaField }
export type SchemaFields = { [string]: SchemaField };
export type Schema = {
className: string,
fields: SchemaFields,
classLevelPermissions: ClassLevelPermissions,
indexes?: ?any
indexes?: ?any,
};
export type ClassLevelPermissions = {
find?: {[string]: boolean};
count?: {[string]: boolean};
get?: {[string]: boolean};
create?: {[string]: boolean};
update?: {[string]: boolean};
delete?: {[string]: boolean};
addField?: {[string]: boolean};
readUserFields?: string[];
writeUserFields?: string[];
find?: { [string]: boolean },
count?: { [string]: boolean },
get?: { [string]: boolean },
create?: { [string]: boolean },
update?: { [string]: boolean },
delete?: { [string]: boolean },
addField?: { [string]: boolean },
readUserFields?: string[],
writeUserFields?: string[],
};