fix(prettier): Properly handle lint-stage files (#6970)
Now handles top level files and recursive files in folders. Set max line length to be 100
This commit is contained in:
@@ -52,27 +52,20 @@ 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,
|
||||
};
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
{}
|
||||
);
|
||||
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;
|
||||
}, {});
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,14 +31,12 @@ export class FilesController extends AdaptableController {
|
||||
}
|
||||
|
||||
const location = this.adapter.getFileLocation(config, filename);
|
||||
return this.adapter
|
||||
.createFile(filename, data, contentType, options)
|
||||
.then(() => {
|
||||
return Promise.resolve({
|
||||
url: location,
|
||||
name: filename,
|
||||
});
|
||||
return this.adapter.createFile(filename, data, contentType, options).then(() => {
|
||||
return Promise.resolve({
|
||||
url: location,
|
||||
name: filename,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
deleteFile(config, filename) {
|
||||
@@ -80,16 +78,10 @@ export class FilesController extends AdaptableController {
|
||||
} else {
|
||||
if (filename.indexOf('tfss-') === 0) {
|
||||
fileObject['url'] =
|
||||
'http://files.parsetfss.com/' +
|
||||
config.fileKey +
|
||||
'/' +
|
||||
encodeURIComponent(filename);
|
||||
'http://files.parsetfss.com/' + config.fileKey + '/' + encodeURIComponent(filename);
|
||||
} else if (legacyFilesRegex.test(filename)) {
|
||||
fileObject['url'] =
|
||||
'http://files.parse.com/' +
|
||||
config.fileKey +
|
||||
'/' +
|
||||
encodeURIComponent(filename);
|
||||
'http://files.parse.com/' + config.fileKey + '/' + encodeURIComponent(filename);
|
||||
} else {
|
||||
fileObject['url'] = this.adapter.getFileLocation(config, filename);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,7 @@ export class HooksController {
|
||||
}
|
||||
|
||||
getFunction(functionName) {
|
||||
return this._getHooks({ functionName: functionName }).then(
|
||||
results => results[0]
|
||||
);
|
||||
return this._getHooks({ functionName: functionName }).then(results => results[0]);
|
||||
}
|
||||
|
||||
getFunctions() {
|
||||
@@ -73,14 +71,12 @@ export class HooksController {
|
||||
}
|
||||
|
||||
_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) {
|
||||
@@ -109,19 +105,9 @@ export class HooksController {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,26 +144,21 @@ export class HooksController {
|
||||
if (aHook.functionName) {
|
||||
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.createOrUpdateHook(aHook);
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
throw new Parse.Error(143, 'invalid hook declaration');
|
||||
@@ -189,20 +170,15 @@ export class HooksController {
|
||||
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);
|
||||
}
|
||||
throw new Parse.Error(143, `class ${aHook.className} does not exist`);
|
||||
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, 'invalid hook declaration');
|
||||
}
|
||||
@@ -231,17 +207,13 @@ function wrapToHTTPRequest(hook, key) {
|
||||
method: 'POST',
|
||||
};
|
||||
|
||||
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 request(jsonRequest).then(response => {
|
||||
let err;
|
||||
|
||||
@@ -25,11 +25,7 @@ export class LiveQueryController {
|
||||
if (!this.hasLiveQuery(className)) {
|
||||
return;
|
||||
}
|
||||
const req = this._makePublisherRequest(
|
||||
currentObject,
|
||||
originalObject,
|
||||
classLevelPermissions
|
||||
);
|
||||
const req = this._makePublisherRequest(currentObject, originalObject, classLevelPermissions);
|
||||
this.liveQueryPublisher.onCloudCodeAfterSave(req);
|
||||
}
|
||||
|
||||
@@ -42,11 +38,7 @@ export class LiveQueryController {
|
||||
if (!this.hasLiveQuery(className)) {
|
||||
return;
|
||||
}
|
||||
const req = this._makePublisherRequest(
|
||||
currentObject,
|
||||
originalObject,
|
||||
classLevelPermissions
|
||||
);
|
||||
const req = this._makePublisherRequest(currentObject, originalObject, classLevelPermissions);
|
||||
this.liveQueryPublisher.onCloudCodeAfterDelete(req);
|
||||
}
|
||||
|
||||
@@ -54,11 +46,7 @@ export class LiveQueryController {
|
||||
return this.classNames.has(className);
|
||||
}
|
||||
|
||||
_makePublisherRequest(
|
||||
currentObject: any,
|
||||
originalObject: any,
|
||||
classLevelPermissions: ?any
|
||||
): any {
|
||||
_makePublisherRequest(currentObject: any, originalObject: any, classLevelPermissions: ?any): any {
|
||||
const req = {
|
||||
object: currentObject,
|
||||
};
|
||||
|
||||
@@ -189,8 +189,7 @@ 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;
|
||||
}
|
||||
|
||||
@@ -224,10 +223,7 @@ 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(
|
||||
|
||||
@@ -57,9 +57,7 @@ class ParseGraphQLController {
|
||||
return graphQLConfig;
|
||||
}
|
||||
|
||||
async updateGraphQLConfig(
|
||||
graphQLConfig: ParseGraphQLConfig
|
||||
): Promise<ParseGraphQLConfig> {
|
||||
async updateGraphQLConfig(graphQLConfig: ParseGraphQLConfig): Promise<ParseGraphQLConfig> {
|
||||
// throws if invalid
|
||||
this._validateGraphQLConfig(
|
||||
graphQLConfig || requiredParameter('You must provide a graphQLConfig!')
|
||||
@@ -97,11 +95,7 @@ class ParseGraphQLController {
|
||||
}
|
||||
|
||||
_putCachedGraphQLConfig(graphQLConfig: ParseGraphQLConfig) {
|
||||
return this.cacheController.graphQL.put(
|
||||
this.configCacheKey,
|
||||
graphQLConfig,
|
||||
60000
|
||||
);
|
||||
return this.cacheController.graphQL.put(this.configCacheKey, graphQLConfig, 60000);
|
||||
}
|
||||
|
||||
_validateGraphQLConfig(graphQLConfig: ?ParseGraphQLConfig): void {
|
||||
@@ -119,20 +113,12 @@ class ParseGraphQLController {
|
||||
} = graphQLConfig;
|
||||
|
||||
if (Object.keys(invalidKeys).length) {
|
||||
errorMessages.push(
|
||||
`encountered invalid keys: [${Object.keys(invalidKeys)}]`
|
||||
);
|
||||
errorMessages.push(`encountered invalid keys: [${Object.keys(invalidKeys)}]`);
|
||||
}
|
||||
if (
|
||||
enabledForClasses !== null &&
|
||||
!isValidStringArray(enabledForClasses)
|
||||
) {
|
||||
if (enabledForClasses !== null && !isValidStringArray(enabledForClasses)) {
|
||||
errorMessages.push(`"enabledForClasses" is not a valid array`);
|
||||
}
|
||||
if (
|
||||
disabledForClasses !== null &&
|
||||
!isValidStringArray(disabledForClasses)
|
||||
) {
|
||||
if (disabledForClasses !== null && !isValidStringArray(disabledForClasses)) {
|
||||
errorMessages.push(`"disabledForClasses" is not a valid array`);
|
||||
}
|
||||
if (classConfigs !== null) {
|
||||
@@ -159,17 +145,9 @@ class ParseGraphQLController {
|
||||
if (!isValidSimpleObject(classConfig)) {
|
||||
return 'it must be a valid object';
|
||||
} else {
|
||||
const {
|
||||
className,
|
||||
type = null,
|
||||
query = null,
|
||||
mutation = null,
|
||||
...invalidKeys
|
||||
} = classConfig;
|
||||
const { className, type = null, query = null, mutation = null, ...invalidKeys } = classConfig;
|
||||
if (Object.keys(invalidKeys).length) {
|
||||
return `"invalidKeys" [${Object.keys(
|
||||
invalidKeys
|
||||
)}] should not be present`;
|
||||
return `"invalidKeys" [${Object.keys(invalidKeys)}] should not be present`;
|
||||
}
|
||||
if (typeof className !== 'string' || !className.trim().length) {
|
||||
// TODO consider checking class exists in schema?
|
||||
@@ -190,10 +168,7 @@ class ParseGraphQLController {
|
||||
return `"type" contains invalid keys, [${Object.keys(invalidKeys)}]`;
|
||||
} else if (outputFields !== null && !isValidStringArray(outputFields)) {
|
||||
return `"outputFields" must be a valid string array`;
|
||||
} else if (
|
||||
constraintFields !== null &&
|
||||
!isValidStringArray(constraintFields)
|
||||
) {
|
||||
} else if (constraintFields !== null && !isValidStringArray(constraintFields)) {
|
||||
return `"constraintFields" must be a valid string array`;
|
||||
}
|
||||
if (sortFields !== null) {
|
||||
@@ -214,10 +189,7 @@ class ParseGraphQLController {
|
||||
if (typeof field !== 'string' || field.trim().length === 0) {
|
||||
errorMessage = `"sortField" at index ${index} did not provide the "field" as a string`;
|
||||
return false;
|
||||
} else if (
|
||||
typeof asc !== 'boolean' ||
|
||||
typeof desc !== 'boolean'
|
||||
) {
|
||||
} else if (typeof asc !== 'boolean' || typeof desc !== 'boolean') {
|
||||
errorMessage = `"sortField" at index ${index} did not provide "asc" or "desc" as booleans`;
|
||||
return false;
|
||||
}
|
||||
@@ -234,15 +206,9 @@ class ParseGraphQLController {
|
||||
}
|
||||
if (inputFields !== null) {
|
||||
if (isValidSimpleObject(inputFields)) {
|
||||
const {
|
||||
create = null,
|
||||
update = null,
|
||||
...invalidKeys
|
||||
} = inputFields;
|
||||
const { create = null, update = null, ...invalidKeys } = inputFields;
|
||||
if (Object.keys(invalidKeys).length) {
|
||||
return `"inputFields" contains invalid keys: [${Object.keys(
|
||||
invalidKeys
|
||||
)}]`;
|
||||
return `"inputFields" contains invalid keys: [${Object.keys(invalidKeys)}]`;
|
||||
} else {
|
||||
if (update !== null && !isValidStringArray(update)) {
|
||||
return `"inputFields.update" must be a valid string array`;
|
||||
@@ -250,10 +216,7 @@ class ParseGraphQLController {
|
||||
if (!isValidStringArray(create)) {
|
||||
return `"inputFields.create" must be a valid string array`;
|
||||
} else if (className === '_User') {
|
||||
if (
|
||||
!create.includes('username') ||
|
||||
!create.includes('password')
|
||||
) {
|
||||
if (!create.includes('username') || !create.includes('password')) {
|
||||
return `"inputFields.create" must include required fields, username and password`;
|
||||
}
|
||||
}
|
||||
@@ -274,9 +237,7 @@ class ParseGraphQLController {
|
||||
...invalidKeys
|
||||
} = query;
|
||||
if (Object.keys(invalidKeys).length) {
|
||||
return `"query" contains invalid keys, [${Object.keys(
|
||||
invalidKeys
|
||||
)}]`;
|
||||
return `"query" contains invalid keys, [${Object.keys(invalidKeys)}]`;
|
||||
} else if (find !== null && typeof find !== 'boolean') {
|
||||
return `"query.find" must be a boolean`;
|
||||
} else if (get !== null && typeof get !== 'boolean') {
|
||||
@@ -302,9 +263,7 @@ class ParseGraphQLController {
|
||||
...invalidKeys
|
||||
} = mutation;
|
||||
if (Object.keys(invalidKeys).length) {
|
||||
return `"mutation" contains invalid keys, [${Object.keys(
|
||||
invalidKeys
|
||||
)}]`;
|
||||
return `"mutation" contains invalid keys, [${Object.keys(invalidKeys)}]`;
|
||||
}
|
||||
if (create !== null && typeof create !== 'boolean') {
|
||||
return `"mutation.create" must be a boolean`;
|
||||
|
||||
@@ -6,19 +6,9 @@ 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
|
||||
@@ -32,10 +22,7 @@ export class PushController {
|
||||
}
|
||||
|
||||
// Immediate push
|
||||
if (
|
||||
body.expiration_interval &&
|
||||
!Object.prototype.hasOwnProperty.call(body, 'push_time')
|
||||
) {
|
||||
if (body.expiration_interval && !Object.prototype.hasOwnProperty.call(body, 'push_time')) {
|
||||
const ttlMs = body.expiration_interval * 1000;
|
||||
body.expiration_time = new Date(now.valueOf() + ttlMs).valueOf();
|
||||
}
|
||||
@@ -73,12 +60,7 @@ 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,
|
||||
@@ -129,13 +111,7 @@ export class PushController {
|
||||
) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return config.pushControllerQueue.enqueue(
|
||||
body,
|
||||
where,
|
||||
config,
|
||||
auth,
|
||||
pushStatus
|
||||
);
|
||||
return config.pushControllerQueue.enqueue(body, where, config, auth, pushStatus);
|
||||
})
|
||||
.catch(err => {
|
||||
return pushStatus.fail(err).then(() => {
|
||||
@@ -150,10 +126,7 @@ export class PushController {
|
||||
* @returns {Number|undefined} The expiration time if it exists in the request
|
||||
*/
|
||||
static getExpirationTime(body = {}) {
|
||||
var hasExpirationTime = Object.prototype.hasOwnProperty.call(
|
||||
body,
|
||||
'expiration_time'
|
||||
);
|
||||
var hasExpirationTime = Object.prototype.hasOwnProperty.call(body, 'expiration_time');
|
||||
if (!hasExpirationTime) {
|
||||
return;
|
||||
}
|
||||
@@ -180,19 +153,13 @@ export class PushController {
|
||||
}
|
||||
|
||||
static getExpirationInterval(body = {}) {
|
||||
const hasExpirationInterval = Object.prototype.hasOwnProperty.call(
|
||||
body,
|
||||
'expiration_interval'
|
||||
);
|
||||
const hasExpirationInterval = Object.prototype.hasOwnProperty.call(body, 'expiration_interval');
|
||||
if (!hasExpirationInterval) {
|
||||
return;
|
||||
}
|
||||
|
||||
var expirationIntervalParam = body['expiration_interval'];
|
||||
if (
|
||||
typeof expirationIntervalParam !== 'number' ||
|
||||
expirationIntervalParam <= 0
|
||||
) {
|
||||
if (typeof expirationIntervalParam !== 'number' || expirationIntervalParam <= 0) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
`expiration_interval must be a number greater than 0`
|
||||
@@ -248,8 +215,7 @@ 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)
|
||||
pushTimeParam.indexOf('Z') === pushTimeParam.length - 1 || offsetPattern.test(pushTimeParam) // 2007-04-05T12:30Z
|
||||
); // 2007-04-05T12:30.000+02:00, 2007-04-05T12:30.000-02:00
|
||||
}
|
||||
|
||||
@@ -259,13 +225,7 @@ export class PushController {
|
||||
* @param isLocalTime {boolean}
|
||||
* @returns {string}
|
||||
*/
|
||||
static formatPushTime({
|
||||
date,
|
||||
isLocalTime,
|
||||
}: {
|
||||
date: Date,
|
||||
isLocalTime: boolean,
|
||||
}) {
|
||||
static formatPushTime({ date, isLocalTime }: { date: Date, isLocalTime: boolean }) {
|
||||
if (isLocalTime) {
|
||||
// Strip 'Z'
|
||||
const isoString = date.toISOString();
|
||||
|
||||
@@ -7,11 +7,7 @@ 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);
|
||||
|
||||
@@ -260,11 +260,7 @@ const CLPValidKeys = Object.freeze([
|
||||
]);
|
||||
|
||||
// validation before setting class-level permissions on collection
|
||||
function validateCLP(
|
||||
perms: ClassLevelPermissions,
|
||||
fields: SchemaFields,
|
||||
userIdRegExp: RegExp
|
||||
) {
|
||||
function validateCLP(perms: ClassLevelPermissions, fields: SchemaFields, userIdRegExp: RegExp) {
|
||||
if (!perms) {
|
||||
return;
|
||||
}
|
||||
@@ -282,10 +278,7 @@ function validateCLP(
|
||||
// throws when root fields are of wrong type
|
||||
validateCLPjson(operation, operationKey);
|
||||
|
||||
if (
|
||||
operationKey === 'readUserFields' ||
|
||||
operationKey === 'writeUserFields'
|
||||
) {
|
||||
if (operationKey === 'readUserFields' || operationKey === 'writeUserFields') {
|
||||
// validate grouped pointer permissions
|
||||
// must be an array with field names
|
||||
for (const fieldName of operation) {
|
||||
@@ -397,11 +390,7 @@ function validateCLPjson(operation: any, operationKey: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function validatePointerPermission(
|
||||
fieldName: string,
|
||||
fields: Object,
|
||||
operation: string
|
||||
) {
|
||||
function validatePointerPermission(fieldName: string, fields: Object, operation: string) {
|
||||
// Uses collection schema to ensure the field is of type:
|
||||
// - Pointer<_User> (pointers)
|
||||
// - Array
|
||||
@@ -412,8 +401,7 @@ function validatePointerPermission(
|
||||
if (
|
||||
!(
|
||||
fields[fieldName] &&
|
||||
((fields[fieldName].type == 'Pointer' &&
|
||||
fields[fieldName].targetClass == '_User') ||
|
||||
((fields[fieldName].type == 'Pointer' && fields[fieldName].targetClass == '_User') ||
|
||||
fields[fieldName].type == 'Array')
|
||||
)
|
||||
) {
|
||||
@@ -444,10 +432,7 @@ function fieldNameIsValid(fieldName: string): boolean {
|
||||
}
|
||||
|
||||
// Checks that it's not trying to clobber one of the default fields of the class.
|
||||
function fieldNameIsValidForClass(
|
||||
fieldName: string,
|
||||
className: string
|
||||
): boolean {
|
||||
function fieldNameIsValidForClass(fieldName: string, className: string): boolean {
|
||||
if (!fieldNameIsValid(fieldName)) {
|
||||
return false;
|
||||
}
|
||||
@@ -468,10 +453,7 @@ function invalidClassNameMessage(className: string): string {
|
||||
);
|
||||
}
|
||||
|
||||
const invalidJsonError = new Parse.Error(
|
||||
Parse.Error.INVALID_JSON,
|
||||
'invalid JSON'
|
||||
);
|
||||
const invalidJsonError = new Parse.Error(Parse.Error.INVALID_JSON, 'invalid JSON');
|
||||
const validNonRelationOrPointerTypes = [
|
||||
'Number',
|
||||
'String',
|
||||
@@ -492,10 +474,7 @@ const fieldTypeIsInvalid = ({ type, targetClass }) => {
|
||||
} else if (typeof targetClass !== 'string') {
|
||||
return invalidJsonError;
|
||||
} else if (!classNameIsValid(targetClass)) {
|
||||
return new Parse.Error(
|
||||
Parse.Error.INVALID_CLASS_NAME,
|
||||
invalidClassNameMessage(targetClass)
|
||||
);
|
||||
return new Parse.Error(Parse.Error.INVALID_CLASS_NAME, invalidClassNameMessage(targetClass));
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
@@ -504,10 +483,7 @@ const fieldTypeIsInvalid = ({ type, targetClass }) => {
|
||||
return invalidJsonError;
|
||||
}
|
||||
if (validNonRelationOrPointerTypes.indexOf(type) < 0) {
|
||||
return new Parse.Error(
|
||||
Parse.Error.INCORRECT_TYPE,
|
||||
`invalid field type: ${type}`
|
||||
);
|
||||
return new Parse.Error(Parse.Error.INCORRECT_TYPE, `invalid field type: ${type}`);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
@@ -563,18 +539,14 @@ class SchemaData {
|
||||
data.classLevelPermissions = deepcopy(schema.classLevelPermissions);
|
||||
data.indexes = schema.indexes;
|
||||
|
||||
const classProtectedFields = this.__protectedFields[
|
||||
schema.className
|
||||
];
|
||||
const classProtectedFields = this.__protectedFields[schema.className];
|
||||
if (classProtectedFields) {
|
||||
for (const key in classProtectedFields) {
|
||||
const unq = new Set([
|
||||
...(data.classLevelPermissions.protectedFields[key] || []),
|
||||
...classProtectedFields[key],
|
||||
]);
|
||||
data.classLevelPermissions.protectedFields[key] = Array.from(
|
||||
unq
|
||||
);
|
||||
data.classLevelPermissions.protectedFields[key] = Array.from(unq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,12 +580,7 @@ class SchemaData {
|
||||
}
|
||||
}
|
||||
|
||||
const injectDefaultSchema = ({
|
||||
className,
|
||||
fields,
|
||||
classLevelPermissions,
|
||||
indexes,
|
||||
}: Schema) => {
|
||||
const injectDefaultSchema = ({ className, fields, classLevelPermissions, indexes }: Schema) => {
|
||||
const defaultSchema: Schema = {
|
||||
className,
|
||||
fields: {
|
||||
@@ -684,10 +651,7 @@ const VolatileClassesSchemas = [
|
||||
_IdempotencySchema,
|
||||
];
|
||||
|
||||
const dbTypeMatchesObjectType = (
|
||||
dbType: SchemaField | string,
|
||||
objectType: SchemaField
|
||||
) => {
|
||||
const dbTypeMatchesObjectType = (dbType: SchemaField | string, objectType: SchemaField) => {
|
||||
if (dbType.type !== objectType.type) return false;
|
||||
if (dbType.targetClass !== objectType.targetClass) return false;
|
||||
if (dbType === objectType.type) return true;
|
||||
@@ -749,9 +713,7 @@ export default class SchemaController {
|
||||
return this.reloadDataPromise;
|
||||
}
|
||||
|
||||
getAllClasses(
|
||||
options: LoadSchemaOptions = { clearCache: false }
|
||||
): Promise<Array<Schema>> {
|
||||
getAllClasses(options: LoadSchemaOptions = { clearCache: false }): Promise<Array<Schema>> {
|
||||
if (options.clearCache) {
|
||||
return this.setAllClasses();
|
||||
}
|
||||
@@ -771,9 +733,7 @@ export default class SchemaController {
|
||||
/* eslint-disable no-console */
|
||||
this._cache
|
||||
.setAllClasses(allSchemas)
|
||||
.catch(error =>
|
||||
console.error('Error saving schema to cache:', error)
|
||||
);
|
||||
.catch(error => console.error('Error saving schema to cache:', error));
|
||||
/* eslint-enable no-console */
|
||||
return allSchemas;
|
||||
});
|
||||
@@ -803,9 +763,7 @@ export default class SchemaController {
|
||||
return Promise.resolve(cached);
|
||||
}
|
||||
return this.setAllClasses().then(allSchemas => {
|
||||
const oneSchema = allSchemas.find(
|
||||
schema => schema.className === className
|
||||
);
|
||||
const oneSchema = allSchemas.find(schema => schema.className === className);
|
||||
if (!oneSchema) {
|
||||
return Promise.reject(undefined);
|
||||
}
|
||||
@@ -828,18 +786,12 @@ export default class SchemaController {
|
||||
classLevelPermissions: any,
|
||||
indexes: any = {}
|
||||
): Promise<void | Schema> {
|
||||
var validationError = this.validateNewClass(
|
||||
className,
|
||||
fields,
|
||||
classLevelPermissions
|
||||
);
|
||||
var validationError = this.validateNewClass(className, fields, classLevelPermissions);
|
||||
if (validationError) {
|
||||
if (validationError instanceof Parse.Error) {
|
||||
return Promise.reject(validationError);
|
||||
} else if (validationError.code && validationError.error) {
|
||||
return Promise.reject(
|
||||
new Parse.Error(validationError.code, validationError.error)
|
||||
);
|
||||
return Promise.reject(new Parse.Error(validationError.code, validationError.error));
|
||||
}
|
||||
return Promise.reject(validationError);
|
||||
}
|
||||
@@ -883,21 +835,14 @@ export default class SchemaController {
|
||||
throw new Parse.Error(255, `Field ${name} exists, cannot update.`);
|
||||
}
|
||||
if (!existingFields[name] && field.__op === 'Delete') {
|
||||
throw new Parse.Error(
|
||||
255,
|
||||
`Field ${name} does not exist, cannot delete.`
|
||||
);
|
||||
throw new Parse.Error(255, `Field ${name} does not exist, cannot delete.`);
|
||||
}
|
||||
});
|
||||
|
||||
delete existingFields._rperm;
|
||||
delete existingFields._wperm;
|
||||
const newSchema = buildMergedSchemaObject(
|
||||
existingFields,
|
||||
submittedFields
|
||||
);
|
||||
const defaultFields =
|
||||
defaultColumns[className] || defaultColumns._Default;
|
||||
const newSchema = buildMergedSchemaObject(existingFields, submittedFields);
|
||||
const defaultFields = defaultColumns[className] || defaultColumns._Default;
|
||||
const fullNewSchema = Object.assign({}, newSchema, defaultFields);
|
||||
const validationError = this.validateSchemaData(
|
||||
className,
|
||||
@@ -938,11 +883,7 @@ export default class SchemaController {
|
||||
})
|
||||
.then(results => {
|
||||
enforceFields = results.filter(result => !!result);
|
||||
return this.setPermissions(
|
||||
className,
|
||||
classLevelPermissions,
|
||||
newSchema
|
||||
);
|
||||
return this.setPermissions(className, classLevelPermissions, newSchema);
|
||||
})
|
||||
.then(() =>
|
||||
this._dbAdapter.setIndexesWithSchemaFormat(
|
||||
@@ -1004,32 +945,19 @@ export default class SchemaController {
|
||||
if (this.schemaData[className]) {
|
||||
return this;
|
||||
} else {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INVALID_JSON,
|
||||
`Failed to add ${className}`
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INVALID_JSON, `Failed to add ${className}`);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// The schema still doesn't validate. Give up
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INVALID_JSON,
|
||||
'schema class name does not revalidate'
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INVALID_JSON, 'schema class name does not revalidate');
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
validateNewClass(
|
||||
className: string,
|
||||
fields: SchemaFields = {},
|
||||
classLevelPermissions: any
|
||||
): any {
|
||||
validateNewClass(className: string, fields: SchemaFields = {}, classLevelPermissions: any): any {
|
||||
if (this.schemaData[className]) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INVALID_CLASS_NAME,
|
||||
`Class ${className} already exists.`
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, `Class ${className} already exists.`);
|
||||
}
|
||||
if (!classNameIsValid(className)) {
|
||||
return {
|
||||
@@ -1037,12 +965,7 @@ export default class SchemaController {
|
||||
error: invalidClassNameMessage(className),
|
||||
};
|
||||
}
|
||||
return this.validateSchemaData(
|
||||
className,
|
||||
fields,
|
||||
classLevelPermissions,
|
||||
[]
|
||||
);
|
||||
return this.validateSchemaData(className, fields, classLevelPermissions, []);
|
||||
}
|
||||
|
||||
validateSchemaData(
|
||||
@@ -1072,15 +995,10 @@ export default class SchemaController {
|
||||
let defaultValueType = getType(fieldType.defaultValue);
|
||||
if (typeof defaultValueType === 'string') {
|
||||
defaultValueType = { type: defaultValueType };
|
||||
} else if (
|
||||
typeof defaultValueType === 'object' &&
|
||||
fieldType.type === 'Relation'
|
||||
) {
|
||||
} else if (typeof defaultValueType === 'object' && fieldType.type === 'Relation') {
|
||||
return {
|
||||
code: Parse.Error.INCORRECT_TYPE,
|
||||
error: `The 'default value' option is not applicable for ${typeToString(
|
||||
fieldType
|
||||
)}`,
|
||||
error: `The 'default value' option is not applicable for ${typeToString(fieldType)}`,
|
||||
};
|
||||
}
|
||||
if (!dbTypeMatchesObjectType(fieldType, defaultValueType)) {
|
||||
@@ -1095,9 +1013,7 @@ export default class SchemaController {
|
||||
if (typeof fieldType === 'object' && fieldType.type === 'Relation') {
|
||||
return {
|
||||
code: Parse.Error.INCORRECT_TYPE,
|
||||
error: `The 'required' option is not applicable for ${typeToString(
|
||||
fieldType
|
||||
)}`,
|
||||
error: `The 'required' option is not applicable for ${typeToString(fieldType)}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1138,21 +1054,14 @@ export default class SchemaController {
|
||||
// object if the provided className-fieldName-type tuple is valid.
|
||||
// The className must already be validated.
|
||||
// If 'freeze' is true, refuse to update the schema for this field.
|
||||
enforceFieldExists(
|
||||
className: string,
|
||||
fieldName: string,
|
||||
type: string | SchemaField
|
||||
) {
|
||||
enforceFieldExists(className: string, fieldName: string, type: string | SchemaField) {
|
||||
if (fieldName.indexOf('.') > 0) {
|
||||
// subdocument key (x.y) => ok if x is of type 'object'
|
||||
fieldName = fieldName.split('.')[0];
|
||||
type = 'Object';
|
||||
}
|
||||
if (!fieldNameIsValid(fieldName)) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INVALID_KEY_NAME,
|
||||
`Invalid field name: ${fieldName}.`
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name: ${fieldName}.`);
|
||||
}
|
||||
|
||||
// If someone tries to create a new field with null/undefined as the value, return;
|
||||
@@ -1222,20 +1131,13 @@ export default class SchemaController {
|
||||
type = { type: type };
|
||||
}
|
||||
if (!expectedType || !dbTypeMatchesObjectType(expectedType, type)) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INVALID_JSON,
|
||||
`Could not add field ${fieldName}`
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INVALID_JSON, `Could not add field ${fieldName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// maintain compatibility
|
||||
deleteField(
|
||||
fieldName: string,
|
||||
className: string,
|
||||
database: DatabaseController
|
||||
) {
|
||||
deleteField(fieldName: string, className: string, database: DatabaseController) {
|
||||
return this.deleteFields([fieldName], className, database);
|
||||
}
|
||||
|
||||
@@ -1246,24 +1148,14 @@ export default class SchemaController {
|
||||
// Passing the database and prefix is necessary in order to drop relation collections
|
||||
// and remove fields from objects. Ideally the database would belong to
|
||||
// a database adapter and this function would close over it or access it via member.
|
||||
deleteFields(
|
||||
fieldNames: Array<string>,
|
||||
className: string,
|
||||
database: DatabaseController
|
||||
) {
|
||||
deleteFields(fieldNames: Array<string>, className: string, database: DatabaseController) {
|
||||
if (!classNameIsValid(className)) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INVALID_CLASS_NAME,
|
||||
invalidClassNameMessage(className)
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, invalidClassNameMessage(className));
|
||||
}
|
||||
|
||||
fieldNames.forEach(fieldName => {
|
||||
if (!fieldNameIsValid(fieldName)) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INVALID_KEY_NAME,
|
||||
`invalid field name: ${fieldName}`
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `invalid field name: ${fieldName}`);
|
||||
}
|
||||
//Don't allow deleting the default fields.
|
||||
if (!fieldNameIsValidForClass(fieldName, className)) {
|
||||
@@ -1285,30 +1177,23 @@ export default class SchemaController {
|
||||
.then(schema => {
|
||||
fieldNames.forEach(fieldName => {
|
||||
if (!schema.fields[fieldName]) {
|
||||
throw new Parse.Error(
|
||||
255,
|
||||
`Field ${fieldName} does not exist, cannot delete.`
|
||||
);
|
||||
throw new Parse.Error(255, `Field ${fieldName} does not exist, cannot delete.`);
|
||||
}
|
||||
});
|
||||
|
||||
const schemaFields = { ...schema.fields };
|
||||
return database.adapter
|
||||
.deleteFields(className, schema, fieldNames)
|
||||
.then(() => {
|
||||
return Promise.all(
|
||||
fieldNames.map(fieldName => {
|
||||
const field = schemaFields[fieldName];
|
||||
if (field && field.type === 'Relation') {
|
||||
//For relations, drop the _Join table
|
||||
return database.adapter.deleteClass(
|
||||
`_Join:${fieldName}:${className}`
|
||||
);
|
||||
}
|
||||
return Promise.resolve();
|
||||
})
|
||||
);
|
||||
});
|
||||
return database.adapter.deleteFields(className, schema, fieldNames).then(() => {
|
||||
return Promise.all(
|
||||
fieldNames.map(fieldName => {
|
||||
const field = schemaFields[fieldName];
|
||||
if (field && field.type === 'Relation') {
|
||||
//For relations, drop the _Join table
|
||||
return database.adapter.deleteClass(`_Join:${fieldName}:${className}`);
|
||||
}
|
||||
return Promise.resolve();
|
||||
})
|
||||
);
|
||||
});
|
||||
})
|
||||
.then(() => this._cache.clear());
|
||||
}
|
||||
@@ -1380,19 +1265,12 @@ export default class SchemaController {
|
||||
});
|
||||
|
||||
if (missingColumns.length > 0) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INCORRECT_TYPE,
|
||||
missingColumns[0] + ' is required.'
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INCORRECT_TYPE, missingColumns[0] + ' is required.');
|
||||
}
|
||||
return Promise.resolve(this);
|
||||
}
|
||||
|
||||
testPermissionsForClassName(
|
||||
className: string,
|
||||
aclGroup: string[],
|
||||
operation: string
|
||||
) {
|
||||
testPermissionsForClassName(className: string, aclGroup: string[], operation: string) {
|
||||
return SchemaController.testPermissions(
|
||||
this.getClassLevelPermissions(className),
|
||||
aclGroup,
|
||||
@@ -1401,11 +1279,7 @@ export default class SchemaController {
|
||||
}
|
||||
|
||||
// Tests that the class level permission let pass the operation for a given aclGroup
|
||||
static testPermissions(
|
||||
classPermissions: ?any,
|
||||
aclGroup: string[],
|
||||
operation: string
|
||||
): boolean {
|
||||
static testPermissions(classPermissions: ?any, aclGroup: string[], operation: string): boolean {
|
||||
if (!classPermissions || !classPermissions[operation]) {
|
||||
return true;
|
||||
}
|
||||
@@ -1432,9 +1306,7 @@ export default class SchemaController {
|
||||
operation: string,
|
||||
action?: string
|
||||
) {
|
||||
if (
|
||||
SchemaController.testPermissions(classPermissions, aclGroup, operation)
|
||||
) {
|
||||
if (SchemaController.testPermissions(classPermissions, aclGroup, operation)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -1465,9 +1337,7 @@ export default class SchemaController {
|
||||
// No matching CLP, let's check the Pointer permissions
|
||||
// And handle those later
|
||||
const permissionField =
|
||||
['get', 'find', 'count'].indexOf(operation) > -1
|
||||
? 'readUserFields'
|
||||
: 'writeUserFields';
|
||||
['get', 'find', 'count'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields';
|
||||
|
||||
// Reject create when write lockdown
|
||||
if (permissionField == 'writeUserFields' && operation == 'create') {
|
||||
@@ -1501,12 +1371,7 @@ export default class SchemaController {
|
||||
}
|
||||
|
||||
// Validates an operation passes class-level-permissions set in the schema
|
||||
validatePermission(
|
||||
className: string,
|
||||
aclGroup: string[],
|
||||
operation: string,
|
||||
action?: string
|
||||
) {
|
||||
validatePermission(className: string, aclGroup: string[], operation: string, action?: string) {
|
||||
return SchemaController.validatePermission(
|
||||
this.getClassLevelPermissions(className),
|
||||
className,
|
||||
@@ -1517,18 +1382,12 @@ export default class SchemaController {
|
||||
}
|
||||
|
||||
getClassLevelPermissions(className: string): any {
|
||||
return (
|
||||
this.schemaData[className] &&
|
||||
this.schemaData[className].classLevelPermissions
|
||||
);
|
||||
return this.schemaData[className] && this.schemaData[className].classLevelPermissions;
|
||||
}
|
||||
|
||||
// Returns the expected type for a className+key combination
|
||||
// or undefined if the schema is not set
|
||||
getExpectedType(
|
||||
className: string,
|
||||
fieldName: string
|
||||
): ?(SchemaField | string) {
|
||||
getExpectedType(className: string, fieldName: string): ?(SchemaField | string) {
|
||||
if (this.schemaData[className]) {
|
||||
const expectedType = this.schemaData[className].fields[fieldName];
|
||||
return expectedType === 'map' ? 'Object' : expectedType;
|
||||
@@ -1560,10 +1419,7 @@ const load = (
|
||||
// does not include the default fields, as it is intended to be passed
|
||||
// to mongoSchemaFromFieldsAndClassName. No validation is done here, it
|
||||
// is done in mongoSchemaFromFieldsAndClassName.
|
||||
function buildMergedSchemaObject(
|
||||
existingFields: SchemaFields,
|
||||
putRequest: any
|
||||
): SchemaFields {
|
||||
function buildMergedSchemaObject(existingFields: SchemaFields, putRequest: any): SchemaFields {
|
||||
const newSchema = {};
|
||||
// @flow-disable-next
|
||||
const sysSchemaField =
|
||||
@@ -1578,14 +1434,10 @@ function buildMergedSchemaObject(
|
||||
oldField !== 'createdAt' &&
|
||||
oldField !== 'objectId'
|
||||
) {
|
||||
if (
|
||||
sysSchemaField.length > 0 &&
|
||||
sysSchemaField.indexOf(oldField) !== -1
|
||||
) {
|
||||
if (sysSchemaField.length > 0 && sysSchemaField.indexOf(oldField) !== -1) {
|
||||
continue;
|
||||
}
|
||||
const fieldIsDeleted =
|
||||
putRequest[oldField] && putRequest[oldField].__op === 'Delete';
|
||||
const fieldIsDeleted = putRequest[oldField] && putRequest[oldField].__op === 'Delete';
|
||||
if (!fieldIsDeleted) {
|
||||
newSchema[oldField] = existingFields[oldField];
|
||||
}
|
||||
@@ -1593,10 +1445,7 @@ function buildMergedSchemaObject(
|
||||
}
|
||||
for (const newField in putRequest) {
|
||||
if (newField !== 'objectId' && putRequest[newField].__op !== 'Delete') {
|
||||
if (
|
||||
sysSchemaField.length > 0 &&
|
||||
sysSchemaField.indexOf(newField) !== -1
|
||||
) {
|
||||
if (sysSchemaField.length > 0 && sysSchemaField.indexOf(newField) !== -1) {
|
||||
continue;
|
||||
}
|
||||
newSchema[newField] = putRequest[newField];
|
||||
@@ -1692,10 +1541,7 @@ function getObjectType(obj): ?(SchemaField | string) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
throw new Parse.Error(
|
||||
Parse.Error.INCORRECT_TYPE,
|
||||
'This is not a valid ' + obj.__type
|
||||
);
|
||||
throw new Parse.Error(Parse.Error.INCORRECT_TYPE, 'This is not a valid ' + obj.__type);
|
||||
}
|
||||
if (obj['$ne']) {
|
||||
return getObjectType(obj['$ne']);
|
||||
|
||||
@@ -95,16 +95,12 @@ export class UserController extends AdaptableController {
|
||||
throw 'Failed to reset password: username / email / token is invalid';
|
||||
}
|
||||
|
||||
if (
|
||||
this.config.passwordPolicy &&
|
||||
this.config.passwordPolicy.resetTokenValidityDuration
|
||||
) {
|
||||
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';
|
||||
if (expiresDate < new Date()) throw 'The password reset link has expired';
|
||||
}
|
||||
|
||||
return results[0];
|
||||
@@ -123,12 +119,7 @@ export class UserController extends AdaptableController {
|
||||
where.email = user.email;
|
||||
}
|
||||
|
||||
var query = new RestQuery(
|
||||
this.config,
|
||||
Auth.master(this.config),
|
||||
'_User',
|
||||
where
|
||||
);
|
||||
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;
|
||||
@@ -146,12 +137,7 @@ export class UserController extends AdaptableController {
|
||||
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,
|
||||
@@ -173,11 +159,7 @@ 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) {
|
||||
@@ -194,10 +176,7 @@ export class UserController extends AdaptableController {
|
||||
setPasswordResetToken(email) {
|
||||
const token = { _perishable_token: randomString(25) };
|
||||
|
||||
if (
|
||||
this.config.passwordPolicy &&
|
||||
this.config.passwordPolicy.resetTokenValidityDuration
|
||||
) {
|
||||
if (this.config.passwordPolicy && this.config.passwordPolicy.resetTokenValidityDuration) {
|
||||
token._perishable_token_expires_at = Parse._encode(
|
||||
this.config.generatePasswordResetTokenExpiresAt()
|
||||
);
|
||||
@@ -278,9 +257,7 @@ export class UserController extends AdaptableController {
|
||||
'Hi,\n\n' +
|
||||
'You requested to reset your password for ' +
|
||||
appName +
|
||||
(user.get('username')
|
||||
? " (your username is '" + user.get('username') + "')"
|
||||
: '') +
|
||||
(user.get('username') ? " (your username is '" + user.get('username') + "')" : '') +
|
||||
'.\n\n' +
|
||||
'' +
|
||||
'Click here to reset it:\n' +
|
||||
@@ -308,10 +285,7 @@ function buildEmailLink(destination, username, token, config) {
|
||||
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
|
||||
|
||||
@@ -67,9 +67,7 @@ export function getControllers(options: ParseServerOptions) {
|
||||
};
|
||||
}
|
||||
|
||||
export function getLoggerController(
|
||||
options: ParseServerOptions
|
||||
): LoggerController {
|
||||
export function getLoggerController(options: ParseServerOptions): LoggerController {
|
||||
const {
|
||||
appId,
|
||||
jsonLogs,
|
||||
@@ -88,25 +86,12 @@ export function getLoggerController(
|
||||
silent,
|
||||
maxLogFiles,
|
||||
};
|
||||
const loggerControllerAdapter = loadAdapter(
|
||||
loggerAdapter,
|
||||
WinstonLoggerAdapter,
|
||||
loggerOptions
|
||||
);
|
||||
const loggerControllerAdapter = loadAdapter(loggerAdapter, WinstonLoggerAdapter, loggerOptions);
|
||||
return new LoggerController(loggerControllerAdapter, appId, loggerOptions);
|
||||
}
|
||||
|
||||
export function getFilesController(
|
||||
options: ParseServerOptions
|
||||
): FilesController {
|
||||
const {
|
||||
appId,
|
||||
databaseURI,
|
||||
filesAdapter,
|
||||
databaseAdapter,
|
||||
preserveFileName,
|
||||
fileKey,
|
||||
} = options;
|
||||
export function getFilesController(options: ParseServerOptions): FilesController {
|
||||
const { appId, databaseURI, filesAdapter, databaseAdapter, preserveFileName, fileKey } = options;
|
||||
if (!filesAdapter && databaseAdapter) {
|
||||
throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.';
|
||||
}
|
||||
@@ -126,15 +111,13 @@ export function getUserController(options: ParseServerOptions): UserController {
|
||||
});
|
||||
}
|
||||
|
||||
export function getCacheController(
|
||||
options: ParseServerOptions
|
||||
): CacheController {
|
||||
export function getCacheController(options: ParseServerOptions): CacheController {
|
||||
const { appId, cacheAdapter, cacheTTL, cacheMaxSize } = options;
|
||||
const cacheControllerAdapter = loadAdapter(
|
||||
cacheAdapter,
|
||||
InMemoryCacheAdapter,
|
||||
{ appId: appId, ttl: cacheTTL, maxSize: cacheMaxSize }
|
||||
);
|
||||
const cacheControllerAdapter = loadAdapter(cacheAdapter, InMemoryCacheAdapter, {
|
||||
appId: appId,
|
||||
ttl: cacheTTL,
|
||||
maxSize: cacheMaxSize,
|
||||
});
|
||||
return new CacheController(cacheControllerAdapter, appId);
|
||||
}
|
||||
|
||||
@@ -148,20 +131,13 @@ export function getParseGraphQLController(
|
||||
});
|
||||
}
|
||||
|
||||
export function getAnalyticsController(
|
||||
options: ParseServerOptions
|
||||
): AnalyticsController {
|
||||
export function getAnalyticsController(options: ParseServerOptions): AnalyticsController {
|
||||
const { analyticsAdapter } = options;
|
||||
const analyticsControllerAdapter = loadAdapter(
|
||||
analyticsAdapter,
|
||||
AnalyticsAdapter
|
||||
);
|
||||
const analyticsControllerAdapter = loadAdapter(analyticsAdapter, AnalyticsAdapter);
|
||||
return new AnalyticsController(analyticsControllerAdapter);
|
||||
}
|
||||
|
||||
export function getLiveQueryController(
|
||||
options: ParseServerOptions
|
||||
): LiveQueryController {
|
||||
export function getLiveQueryController(options: ParseServerOptions): LiveQueryController {
|
||||
return new LiveQueryController(options.liveQuery);
|
||||
}
|
||||
|
||||
@@ -185,11 +161,7 @@ export function getDatabaseController(
|
||||
) {
|
||||
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);
|
||||
}
|
||||
@@ -214,9 +186,7 @@ interface PushControlling {
|
||||
pushWorker: PushWorker;
|
||||
}
|
||||
|
||||
export function getPushController(
|
||||
options: ParseServerOptions
|
||||
): PushControlling {
|
||||
export function getPushController(options: ParseServerOptions): PushControlling {
|
||||
const { scheduledPush, push } = options;
|
||||
|
||||
const pushOptions = Object.assign({}, push);
|
||||
@@ -258,11 +228,7 @@ export function getAuthDataManager(options: ParseServerOptions) {
|
||||
return authDataManager(auth, enableAnonymousUsers);
|
||||
}
|
||||
|
||||
export function getDatabaseAdapter(
|
||||
databaseURI,
|
||||
collectionPrefix,
|
||||
databaseOptions
|
||||
) {
|
||||
export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions) {
|
||||
let protocol;
|
||||
try {
|
||||
const parsedURI = url.parse(databaseURI);
|
||||
|
||||
Reference in New Issue
Block a user