@@ -1,3 +1,4 @@
|
|||||||
semi: true
|
semi: true
|
||||||
trailingComma: "es5"
|
trailingComma: "es5"
|
||||||
singleQuote: true
|
singleQuote: true
|
||||||
|
arrowParens: "avoid"
|
||||||
@@ -7,7 +7,7 @@ export class AnalyticsController extends AdaptableController {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
return this.adapter.appOpened(req.body, req);
|
return this.adapter.appOpened(req.body, req);
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
return { response: response || {} };
|
return { response: response || {} };
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -20,7 +20,7 @@ export class AnalyticsController extends AdaptableController {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
return this.adapter.trackEvent(req.params.eventName, req.body, req);
|
return this.adapter.trackEvent(req.params.eventName, req.body, req);
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
return { response: response || {} };
|
return { response: response || {} };
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const specialQuerykeys = [
|
|||||||
'_failed_login_count',
|
'_failed_login_count',
|
||||||
];
|
];
|
||||||
|
|
||||||
const isSpecialQueryKey = (key) => {
|
const isSpecialQueryKey = key => {
|
||||||
return specialQuerykeys.indexOf(key) >= 0;
|
return specialQuerykeys.indexOf(key) >= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ const validateQuery = (query: any): void => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(query).forEach((key) => {
|
Object.keys(query).forEach(key => {
|
||||||
if (query && query[key] && query[key].$regex) {
|
if (query && query[key] && query[key].$regex) {
|
||||||
if (typeof query[key].$options === 'string') {
|
if (typeof query[key].$options === 'string') {
|
||||||
if (!query[key].$options.match(/^[imxs]+$/)) {
|
if (!query[key].$options.match(/^[imxs]+$/)) {
|
||||||
@@ -149,8 +149,8 @@ const filterSensitiveData = (
|
|||||||
if (isReadOperation && perms.protectedFields) {
|
if (isReadOperation && perms.protectedFields) {
|
||||||
// extract protectedFields added with the pointer-permission prefix
|
// extract protectedFields added with the pointer-permission prefix
|
||||||
const protectedFieldsPointerPerm = Object.keys(perms.protectedFields)
|
const protectedFieldsPointerPerm = Object.keys(perms.protectedFields)
|
||||||
.filter((key) => key.startsWith('userField:'))
|
.filter(key => key.startsWith('userField:'))
|
||||||
.map((key) => {
|
.map(key => {
|
||||||
return { key: key.substring(10), value: perms.protectedFields[key] };
|
return { key: key.substring(10), value: perms.protectedFields[key] };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -158,13 +158,13 @@ const filterSensitiveData = (
|
|||||||
let overrideProtectedFields = false;
|
let overrideProtectedFields = false;
|
||||||
|
|
||||||
// check if the object grants the current user access based on the extracted fields
|
// check if the object grants the current user access based on the extracted fields
|
||||||
protectedFieldsPointerPerm.forEach((pointerPerm) => {
|
protectedFieldsPointerPerm.forEach(pointerPerm => {
|
||||||
let pointerPermIncludesUser = false;
|
let pointerPermIncludesUser = false;
|
||||||
const readUserFieldValue = object[pointerPerm.key];
|
const readUserFieldValue = object[pointerPerm.key];
|
||||||
if (readUserFieldValue) {
|
if (readUserFieldValue) {
|
||||||
if (Array.isArray(readUserFieldValue)) {
|
if (Array.isArray(readUserFieldValue)) {
|
||||||
pointerPermIncludesUser = readUserFieldValue.some(
|
pointerPermIncludesUser = readUserFieldValue.some(
|
||||||
(user) => user.objectId && user.objectId === userId
|
user => user.objectId && user.objectId === userId
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
pointerPermIncludesUser =
|
pointerPermIncludesUser =
|
||||||
@@ -186,14 +186,14 @@ const filterSensitiveData = (
|
|||||||
newProtectedFields.push(protectedFields);
|
newProtectedFields.push(protectedFields);
|
||||||
}
|
}
|
||||||
// intersect all sets of protectedFields
|
// intersect all sets of protectedFields
|
||||||
newProtectedFields.forEach((fields) => {
|
newProtectedFields.forEach(fields => {
|
||||||
if (fields) {
|
if (fields) {
|
||||||
// if there're no protctedFields by other criteria ( id / role / auth)
|
// if there're no protctedFields by other criteria ( id / role / auth)
|
||||||
// then we must intersect each set (per userField)
|
// then we must intersect each set (per userField)
|
||||||
if (!protectedFields) {
|
if (!protectedFields) {
|
||||||
protectedFields = fields;
|
protectedFields = fields;
|
||||||
} else {
|
} else {
|
||||||
protectedFields = protectedFields.filter((v) => fields.includes(v));
|
protectedFields = protectedFields.filter(v => fields.includes(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -205,13 +205,13 @@ const filterSensitiveData = (
|
|||||||
/* special treat for the user class: don't filter protectedFields if currently loggedin user is
|
/* special treat for the user class: don't filter protectedFields if currently loggedin user is
|
||||||
the retrieved user */
|
the retrieved user */
|
||||||
if (!(isUserClass && userId && object.objectId === userId)) {
|
if (!(isUserClass && userId && object.objectId === userId)) {
|
||||||
protectedFields && protectedFields.forEach((k) => delete object[k]);
|
protectedFields && protectedFields.forEach(k => delete object[k]);
|
||||||
|
|
||||||
// fields not requested by client (excluded),
|
// fields not requested by client (excluded),
|
||||||
//but were needed to apply protecttedFields
|
//but were needed to apply protecttedFields
|
||||||
perms.protectedFields &&
|
perms.protectedFields &&
|
||||||
perms.protectedFields.temporaryKeys &&
|
perms.protectedFields.temporaryKeys &&
|
||||||
perms.protectedFields.temporaryKeys.forEach((k) => delete object[k]);
|
perms.protectedFields.temporaryKeys.forEach(k => delete object[k]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isUserClass) {
|
if (!isUserClass) {
|
||||||
@@ -265,7 +265,7 @@ const specialKeysForUpdate = [
|
|||||||
'_password_history',
|
'_password_history',
|
||||||
];
|
];
|
||||||
|
|
||||||
const isSpecialUpdateKey = (key) => {
|
const isSpecialUpdateKey = key => {
|
||||||
return specialKeysForUpdate.indexOf(key) >= 0;
|
return specialKeysForUpdate.indexOf(key) >= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ function sanitizeDatabaseResult(originalObject, result): Promise<any> {
|
|||||||
if (!result) {
|
if (!result) {
|
||||||
return Promise.resolve(response);
|
return Promise.resolve(response);
|
||||||
}
|
}
|
||||||
Object.keys(originalObject).forEach((key) => {
|
Object.keys(originalObject).forEach(key => {
|
||||||
const keyUpdate = originalObject[key];
|
const keyUpdate = originalObject[key];
|
||||||
// determine if that was an op
|
// determine if that was an op
|
||||||
if (
|
if (
|
||||||
@@ -312,7 +312,7 @@ function joinTableName(className, key) {
|
|||||||
return `_Join:${key}:${className}`;
|
return `_Join:${key}:${className}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const flattenUpdateOperatorsForCreate = (object) => {
|
const flattenUpdateOperatorsForCreate = object => {
|
||||||
for (const key in object) {
|
for (const key in object) {
|
||||||
if (object[key] && object[key].__op) {
|
if (object[key] && object[key].__op) {
|
||||||
switch (object[key].__op) {
|
switch (object[key].__op) {
|
||||||
@@ -367,7 +367,7 @@ const flattenUpdateOperatorsForCreate = (object) => {
|
|||||||
|
|
||||||
const transformAuthData = (className, object, schema) => {
|
const transformAuthData = (className, object, schema) => {
|
||||||
if (object.authData && className === '_User') {
|
if (object.authData && className === '_User') {
|
||||||
Object.keys(object.authData).forEach((provider) => {
|
Object.keys(object.authData).forEach(provider => {
|
||||||
const providerData = object.authData[provider];
|
const providerData = object.authData[provider];
|
||||||
const fieldName = `_auth_data_${provider}`;
|
const fieldName = `_auth_data_${provider}`;
|
||||||
if (providerData == null) {
|
if (providerData == null) {
|
||||||
@@ -387,7 +387,7 @@ const untransformObjectACL = ({ _rperm, _wperm, ...output }) => {
|
|||||||
if (_rperm || _wperm) {
|
if (_rperm || _wperm) {
|
||||||
output.ACL = {};
|
output.ACL = {};
|
||||||
|
|
||||||
(_rperm || []).forEach((entry) => {
|
(_rperm || []).forEach(entry => {
|
||||||
if (!output.ACL[entry]) {
|
if (!output.ACL[entry]) {
|
||||||
output.ACL[entry] = { read: true };
|
output.ACL[entry] = { read: true };
|
||||||
} else {
|
} else {
|
||||||
@@ -395,7 +395,7 @@ const untransformObjectACL = ({ _rperm, _wperm, ...output }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
(_wperm || []).forEach((entry) => {
|
(_wperm || []).forEach(entry => {
|
||||||
if (!output.ACL[entry]) {
|
if (!output.ACL[entry]) {
|
||||||
output.ACL[entry] = { write: true };
|
output.ACL[entry] = { write: true };
|
||||||
} else {
|
} else {
|
||||||
@@ -442,10 +442,8 @@ class DatabaseController {
|
|||||||
|
|
||||||
purgeCollection(className: string): Promise<void> {
|
purgeCollection(className: string): Promise<void> {
|
||||||
return this.loadSchema()
|
return this.loadSchema()
|
||||||
.then((schemaController) => schemaController.getOneSchema(className))
|
.then(schemaController => schemaController.getOneSchema(className))
|
||||||
.then((schema) =>
|
.then(schema => this.adapter.deleteObjectsByQuery(className, schema, {}));
|
||||||
this.adapter.deleteObjectsByQuery(className, schema, {})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
validateClassName(className: string): Promise<void> {
|
validateClassName(className: string): Promise<void> {
|
||||||
@@ -492,7 +490,7 @@ class DatabaseController {
|
|||||||
// classname through the key.
|
// classname through the key.
|
||||||
// TODO: make this not in the DatabaseController interface
|
// TODO: make this not in the DatabaseController interface
|
||||||
redirectClassNameForKey(className: string, key: string): Promise<?string> {
|
redirectClassNameForKey(className: string, key: string): Promise<?string> {
|
||||||
return this.loadSchema().then((schema) => {
|
return this.loadSchema().then(schema => {
|
||||||
var t = schema.getExpectedType(className, key);
|
var t = schema.getExpectedType(className, key);
|
||||||
if (t != null && typeof t !== 'string' && t.type === 'Relation') {
|
if (t != null && typeof t !== 'string' && t.type === 'Relation') {
|
||||||
return t.targetClass;
|
return t.targetClass;
|
||||||
@@ -516,7 +514,7 @@ class DatabaseController {
|
|||||||
const isMaster = acl === undefined;
|
const isMaster = acl === undefined;
|
||||||
var aclGroup: string[] = acl || [];
|
var aclGroup: string[] = acl || [];
|
||||||
return this.loadSchema()
|
return this.loadSchema()
|
||||||
.then((s) => {
|
.then(s => {
|
||||||
schema = s;
|
schema = s;
|
||||||
if (isMaster) {
|
if (isMaster) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@@ -552,7 +550,7 @@ class DatabaseController {
|
|||||||
var aclGroup = acl || [];
|
var aclGroup = acl || [];
|
||||||
|
|
||||||
return this.loadSchemaIfNeeded(validSchemaController).then(
|
return this.loadSchemaIfNeeded(validSchemaController).then(
|
||||||
(schemaController) => {
|
schemaController => {
|
||||||
return (isMaster
|
return (isMaster
|
||||||
? Promise.resolve()
|
? Promise.resolve()
|
||||||
: schemaController.validatePermission(className, aclGroup, 'update')
|
: schemaController.validatePermission(className, aclGroup, 'update')
|
||||||
@@ -596,7 +594,7 @@ class DatabaseController {
|
|||||||
validateQuery(query);
|
validateQuery(query);
|
||||||
return schemaController
|
return schemaController
|
||||||
.getOneSchema(className, true)
|
.getOneSchema(className, true)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
// If the schema doesn't exist, pretend it exists with no fields. This behavior
|
// If the schema doesn't exist, pretend it exists with no fields. This behavior
|
||||||
// will likely need revisiting.
|
// will likely need revisiting.
|
||||||
if (error === undefined) {
|
if (error === undefined) {
|
||||||
@@ -604,8 +602,8 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
})
|
})
|
||||||
.then((schema) => {
|
.then(schema => {
|
||||||
Object.keys(update).forEach((fieldName) => {
|
Object.keys(update).forEach(fieldName => {
|
||||||
if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) {
|
if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_KEY_NAME,
|
Parse.Error.INVALID_KEY_NAME,
|
||||||
@@ -628,7 +626,7 @@ class DatabaseController {
|
|||||||
update[updateOperation] &&
|
update[updateOperation] &&
|
||||||
typeof update[updateOperation] === 'object' &&
|
typeof update[updateOperation] === 'object' &&
|
||||||
Object.keys(update[updateOperation]).some(
|
Object.keys(update[updateOperation]).some(
|
||||||
(innerKey) =>
|
innerKey =>
|
||||||
innerKey.includes('$') || innerKey.includes('.')
|
innerKey.includes('$') || innerKey.includes('.')
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@@ -643,7 +641,7 @@ class DatabaseController {
|
|||||||
if (validateOnly) {
|
if (validateOnly) {
|
||||||
return this.adapter
|
return this.adapter
|
||||||
.find(className, schema, query, {})
|
.find(className, schema, query, {})
|
||||||
.then((result) => {
|
.then(result => {
|
||||||
if (!result || !result.length) {
|
if (!result || !result.length) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.OBJECT_NOT_FOUND,
|
Parse.Error.OBJECT_NOT_FOUND,
|
||||||
@@ -699,7 +697,7 @@ class DatabaseController {
|
|||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then(result => {
|
||||||
if (skipSanitization) {
|
if (skipSanitization) {
|
||||||
return Promise.resolve(result);
|
return Promise.resolve(result);
|
||||||
}
|
}
|
||||||
@@ -822,7 +820,7 @@ class DatabaseController {
|
|||||||
doc,
|
doc,
|
||||||
this._transactionalSession
|
this._transactionalSession
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
// We don't care if they try to delete a non-existent relation.
|
// We don't care if they try to delete a non-existent relation.
|
||||||
if (error.code == Parse.Error.OBJECT_NOT_FOUND) {
|
if (error.code == Parse.Error.OBJECT_NOT_FOUND) {
|
||||||
return;
|
return;
|
||||||
@@ -848,7 +846,7 @@ class DatabaseController {
|
|||||||
const aclGroup = acl || [];
|
const aclGroup = acl || [];
|
||||||
|
|
||||||
return this.loadSchemaIfNeeded(validSchemaController).then(
|
return this.loadSchemaIfNeeded(validSchemaController).then(
|
||||||
(schemaController) => {
|
schemaController => {
|
||||||
return (isMaster
|
return (isMaster
|
||||||
? Promise.resolve()
|
? Promise.resolve()
|
||||||
: schemaController.validatePermission(className, aclGroup, 'delete')
|
: schemaController.validatePermission(className, aclGroup, 'delete')
|
||||||
@@ -875,7 +873,7 @@ class DatabaseController {
|
|||||||
validateQuery(query);
|
validateQuery(query);
|
||||||
return schemaController
|
return schemaController
|
||||||
.getOneSchema(className)
|
.getOneSchema(className)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
// If the schema doesn't exist, pretend it exists with no fields. This behavior
|
// If the schema doesn't exist, pretend it exists with no fields. This behavior
|
||||||
// will likely need revisiting.
|
// will likely need revisiting.
|
||||||
if (error === undefined) {
|
if (error === undefined) {
|
||||||
@@ -883,7 +881,7 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
})
|
})
|
||||||
.then((parseFormatSchema) =>
|
.then(parseFormatSchema =>
|
||||||
this.adapter.deleteObjectsByQuery(
|
this.adapter.deleteObjectsByQuery(
|
||||||
className,
|
className,
|
||||||
parseFormatSchema,
|
parseFormatSchema,
|
||||||
@@ -891,7 +889,7 @@ class DatabaseController {
|
|||||||
this._transactionalSession
|
this._transactionalSession
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
// When deleting sessions while changing passwords, don't throw an error if they don't have any sessions.
|
// When deleting sessions while changing passwords, don't throw an error if they don't have any sessions.
|
||||||
if (
|
if (
|
||||||
className === '_Session' &&
|
className === '_Session' &&
|
||||||
@@ -932,14 +930,14 @@ class DatabaseController {
|
|||||||
|
|
||||||
return this.validateClassName(className)
|
return this.validateClassName(className)
|
||||||
.then(() => this.loadSchemaIfNeeded(validSchemaController))
|
.then(() => this.loadSchemaIfNeeded(validSchemaController))
|
||||||
.then((schemaController) => {
|
.then(schemaController => {
|
||||||
return (isMaster
|
return (isMaster
|
||||||
? Promise.resolve()
|
? Promise.resolve()
|
||||||
: schemaController.validatePermission(className, aclGroup, 'create')
|
: schemaController.validatePermission(className, aclGroup, 'create')
|
||||||
)
|
)
|
||||||
.then(() => schemaController.enforceClassExists(className))
|
.then(() => schemaController.enforceClassExists(className))
|
||||||
.then(() => schemaController.getOneSchema(className, true))
|
.then(() => schemaController.getOneSchema(className, true))
|
||||||
.then((schema) => {
|
.then(schema => {
|
||||||
transformAuthData(className, object, schema);
|
transformAuthData(className, object, schema);
|
||||||
flattenUpdateOperatorsForCreate(object);
|
flattenUpdateOperatorsForCreate(object);
|
||||||
if (validateOnly) {
|
if (validateOnly) {
|
||||||
@@ -952,7 +950,7 @@ class DatabaseController {
|
|||||||
this._transactionalSession
|
this._transactionalSession
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then(result => {
|
||||||
if (validateOnly) {
|
if (validateOnly) {
|
||||||
return originalObject;
|
return originalObject;
|
||||||
}
|
}
|
||||||
@@ -981,7 +979,7 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
const fields = Object.keys(object);
|
const fields = Object.keys(object);
|
||||||
const schemaFields = Object.keys(classSchema.fields);
|
const schemaFields = Object.keys(classSchema.fields);
|
||||||
const newKeys = fields.filter((field) => {
|
const newKeys = fields.filter(field => {
|
||||||
// Skip fields that are unset
|
// Skip fields that are unset
|
||||||
if (
|
if (
|
||||||
object[field] &&
|
object[field] &&
|
||||||
@@ -1040,7 +1038,7 @@ class DatabaseController {
|
|||||||
{ owningId },
|
{ owningId },
|
||||||
findOptions
|
findOptions
|
||||||
)
|
)
|
||||||
.then((results) => results.map((result) => result.relatedId));
|
.then(results => results.map(result => result.relatedId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a promise for a list of owning ids given some related ids.
|
// Returns a promise for a list of owning ids given some related ids.
|
||||||
@@ -1057,7 +1055,7 @@ class DatabaseController {
|
|||||||
{ relatedId: { $in: relatedIds } },
|
{ relatedId: { $in: relatedIds } },
|
||||||
{ keys: ['owningId'] }
|
{ keys: ['owningId'] }
|
||||||
)
|
)
|
||||||
.then((results) => results.map((result) => result.owningId));
|
.then(results => results.map(result => result.owningId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modifies query so that it no longer has $in on relation fields, or
|
// Modifies query so that it no longer has $in on relation fields, or
|
||||||
@@ -1071,7 +1069,7 @@ class DatabaseController {
|
|||||||
return Promise.all(
|
return Promise.all(
|
||||||
ors.map((aQuery, index) => {
|
ors.map((aQuery, index) => {
|
||||||
return this.reduceInRelation(className, aQuery, schema).then(
|
return this.reduceInRelation(className, aQuery, schema).then(
|
||||||
(aQuery) => {
|
aQuery => {
|
||||||
query['$or'][index] = aQuery;
|
query['$or'][index] = aQuery;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -1081,7 +1079,7 @@ class DatabaseController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = Object.keys(query).map((key) => {
|
const promises = Object.keys(query).map(key => {
|
||||||
const t = schema.getExpectedType(className, key);
|
const t = schema.getExpectedType(className, key);
|
||||||
if (!t || t.type !== 'Relation') {
|
if (!t || t.type !== 'Relation') {
|
||||||
return Promise.resolve(query);
|
return Promise.resolve(query);
|
||||||
@@ -1095,16 +1093,16 @@ class DatabaseController {
|
|||||||
query[key].__type == 'Pointer')
|
query[key].__type == 'Pointer')
|
||||||
) {
|
) {
|
||||||
// Build the list of queries
|
// Build the list of queries
|
||||||
queries = Object.keys(query[key]).map((constraintKey) => {
|
queries = Object.keys(query[key]).map(constraintKey => {
|
||||||
let relatedIds;
|
let relatedIds;
|
||||||
let isNegation = false;
|
let isNegation = false;
|
||||||
if (constraintKey === 'objectId') {
|
if (constraintKey === 'objectId') {
|
||||||
relatedIds = [query[key].objectId];
|
relatedIds = [query[key].objectId];
|
||||||
} else if (constraintKey == '$in') {
|
} else if (constraintKey == '$in') {
|
||||||
relatedIds = query[key]['$in'].map((r) => r.objectId);
|
relatedIds = query[key]['$in'].map(r => r.objectId);
|
||||||
} else if (constraintKey == '$nin') {
|
} else if (constraintKey == '$nin') {
|
||||||
isNegation = true;
|
isNegation = true;
|
||||||
relatedIds = query[key]['$nin'].map((r) => r.objectId);
|
relatedIds = query[key]['$nin'].map(r => r.objectId);
|
||||||
} else if (constraintKey == '$ne') {
|
} else if (constraintKey == '$ne') {
|
||||||
isNegation = true;
|
isNegation = true;
|
||||||
relatedIds = [query[key]['$ne'].objectId];
|
relatedIds = [query[key]['$ne'].objectId];
|
||||||
@@ -1124,11 +1122,11 @@ class DatabaseController {
|
|||||||
delete query[key];
|
delete query[key];
|
||||||
// execute each query independently to build the list of
|
// execute each query independently to build the list of
|
||||||
// $in / $nin
|
// $in / $nin
|
||||||
const promises = queries.map((q) => {
|
const promises = queries.map(q => {
|
||||||
if (!q) {
|
if (!q) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return this.owningIds(className, key, q.relatedIds).then((ids) => {
|
return this.owningIds(className, key, q.relatedIds).then(ids => {
|
||||||
if (q.isNegation) {
|
if (q.isNegation) {
|
||||||
this.addNotInObjectIdsIds(ids, query);
|
this.addNotInObjectIdsIds(ids, query);
|
||||||
} else {
|
} else {
|
||||||
@@ -1157,7 +1155,7 @@ class DatabaseController {
|
|||||||
): ?Promise<void> {
|
): ?Promise<void> {
|
||||||
if (query['$or']) {
|
if (query['$or']) {
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
query['$or'].map((aQuery) => {
|
query['$or'].map(aQuery => {
|
||||||
return this.reduceRelationKeys(className, aQuery, queryOptions);
|
return this.reduceRelationKeys(className, aQuery, queryOptions);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -1171,7 +1169,7 @@ class DatabaseController {
|
|||||||
relatedTo.object.objectId,
|
relatedTo.object.objectId,
|
||||||
queryOptions
|
queryOptions
|
||||||
)
|
)
|
||||||
.then((ids) => {
|
.then(ids => {
|
||||||
delete query['$relatedTo'];
|
delete query['$relatedTo'];
|
||||||
this.addInObjectIdsIds(ids, query);
|
this.addInObjectIdsIds(ids, query);
|
||||||
return this.reduceRelationKeys(className, query, queryOptions);
|
return this.reduceRelationKeys(className, query, queryOptions);
|
||||||
@@ -1194,7 +1192,7 @@ class DatabaseController {
|
|||||||
idsFromEq,
|
idsFromEq,
|
||||||
idsFromIn,
|
idsFromIn,
|
||||||
ids,
|
ids,
|
||||||
].filter((list) => list !== null);
|
].filter(list => list !== null);
|
||||||
const totalLength = allIds.reduce((memo, list) => memo + list.length, 0);
|
const totalLength = allIds.reduce((memo, list) => memo + list.length, 0);
|
||||||
|
|
||||||
let idsIntersection = [];
|
let idsIntersection = [];
|
||||||
@@ -1223,7 +1221,7 @@ class DatabaseController {
|
|||||||
addNotInObjectIdsIds(ids: string[] = [], query: any) {
|
addNotInObjectIdsIds(ids: string[] = [], query: any) {
|
||||||
const idsFromNin =
|
const idsFromNin =
|
||||||
query.objectId && query.objectId['$nin'] ? query.objectId['$nin'] : [];
|
query.objectId && query.objectId['$nin'] ? query.objectId['$nin'] : [];
|
||||||
let allIds = [...idsFromNin, ...ids].filter((list) => list !== null);
|
let allIds = [...idsFromNin, ...ids].filter(list => list !== null);
|
||||||
|
|
||||||
// make a set and spread to remove duplicates
|
// make a set and spread to remove duplicates
|
||||||
allIds = [...new Set(allIds)];
|
allIds = [...new Set(allIds)];
|
||||||
@@ -1292,13 +1290,13 @@ class DatabaseController {
|
|||||||
|
|
||||||
let classExists = true;
|
let classExists = true;
|
||||||
return this.loadSchemaIfNeeded(validSchemaController).then(
|
return this.loadSchemaIfNeeded(validSchemaController).then(
|
||||||
(schemaController) => {
|
schemaController => {
|
||||||
//Allow volatile classes if querying with Master (for _PushStatus)
|
//Allow volatile classes if querying with Master (for _PushStatus)
|
||||||
//TODO: Move volatile classes concept into mongo adapter, postgres adapter shouldn't care
|
//TODO: Move volatile classes concept into mongo adapter, postgres adapter shouldn't care
|
||||||
//that api.parse.com breaks when _PushStatus exists in mongo.
|
//that api.parse.com breaks when _PushStatus exists in mongo.
|
||||||
return schemaController
|
return schemaController
|
||||||
.getOneSchema(className, isMaster)
|
.getOneSchema(className, isMaster)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
// Behavior for non-existent classes is kinda weird on Parse.com. Probably doesn't matter too much.
|
// Behavior for non-existent classes is kinda weird on Parse.com. Probably doesn't matter too much.
|
||||||
// For now, pretend the class exists but has no objects,
|
// For now, pretend the class exists but has no objects,
|
||||||
if (error === undefined) {
|
if (error === undefined) {
|
||||||
@@ -1307,7 +1305,7 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
})
|
})
|
||||||
.then((schema) => {
|
.then(schema => {
|
||||||
// Parse.com treats queries on _created_at and _updated_at as if they were queries on createdAt and updatedAt,
|
// Parse.com treats queries on _created_at and _updated_at as if they were queries on createdAt and updatedAt,
|
||||||
// so duplicate that behavior here. If both are specified, the correct behavior to match Parse.com is to
|
// so duplicate that behavior here. If both are specified, the correct behavior to match Parse.com is to
|
||||||
// use the one that appears first in the sort list.
|
// use the one that appears first in the sort list.
|
||||||
@@ -1329,7 +1327,7 @@ class DatabaseController {
|
|||||||
caseInsensitive,
|
caseInsensitive,
|
||||||
explain,
|
explain,
|
||||||
};
|
};
|
||||||
Object.keys(sort).forEach((fieldName) => {
|
Object.keys(sort).forEach(fieldName => {
|
||||||
if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) {
|
if (fieldName.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_KEY_NAME,
|
Parse.Error.INVALID_KEY_NAME,
|
||||||
@@ -1441,8 +1439,8 @@ class DatabaseController {
|
|||||||
} else {
|
} else {
|
||||||
return this.adapter
|
return this.adapter
|
||||||
.find(className, schema, query, queryOptions)
|
.find(className, schema, query, queryOptions)
|
||||||
.then((objects) =>
|
.then(objects =>
|
||||||
objects.map((object) => {
|
objects.map(object => {
|
||||||
object = untransformObjectACL(object);
|
object = untransformObjectACL(object);
|
||||||
return filterSensitiveData(
|
return filterSensitiveData(
|
||||||
isMaster,
|
isMaster,
|
||||||
@@ -1456,7 +1454,7 @@ class DatabaseController {
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INTERNAL_SERVER_ERROR,
|
Parse.Error.INTERNAL_SERVER_ERROR,
|
||||||
error
|
error
|
||||||
@@ -1471,10 +1469,8 @@ class DatabaseController {
|
|||||||
|
|
||||||
deleteSchema(className: string): Promise<void> {
|
deleteSchema(className: string): Promise<void> {
|
||||||
return this.loadSchema({ clearCache: true })
|
return this.loadSchema({ clearCache: true })
|
||||||
.then((schemaController) =>
|
.then(schemaController => schemaController.getOneSchema(className, true))
|
||||||
schemaController.getOneSchema(className, true)
|
.catch(error => {
|
||||||
)
|
|
||||||
.catch((error) => {
|
|
||||||
if (error === undefined) {
|
if (error === undefined) {
|
||||||
return { fields: {} };
|
return { fields: {} };
|
||||||
} else {
|
} else {
|
||||||
@@ -1486,7 +1482,7 @@ class DatabaseController {
|
|||||||
.then(() =>
|
.then(() =>
|
||||||
this.adapter.count(className, { fields: {} }, null, '', false)
|
this.adapter.count(className, { fields: {} }, null, '', false)
|
||||||
)
|
)
|
||||||
.then((count) => {
|
.then(count => {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
255,
|
255,
|
||||||
@@ -1495,13 +1491,13 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
return this.adapter.deleteClass(className);
|
return this.adapter.deleteClass(className);
|
||||||
})
|
})
|
||||||
.then((wasParseCollection) => {
|
.then(wasParseCollection => {
|
||||||
if (wasParseCollection) {
|
if (wasParseCollection) {
|
||||||
const relationFieldNames = Object.keys(schema.fields).filter(
|
const relationFieldNames = Object.keys(schema.fields).filter(
|
||||||
(fieldName) => schema.fields[fieldName].type === 'Relation'
|
fieldName => schema.fields[fieldName].type === 'Relation'
|
||||||
);
|
);
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
relationFieldNames.map((name) =>
|
relationFieldNames.map(name =>
|
||||||
this.adapter.deleteClass(joinTableName(className, name))
|
this.adapter.deleteClass(joinTableName(className, name))
|
||||||
)
|
)
|
||||||
).then(() => {
|
).then(() => {
|
||||||
@@ -1533,7 +1529,7 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
const perms = schema.getClassLevelPermissions(className);
|
const perms = schema.getClassLevelPermissions(className);
|
||||||
|
|
||||||
const userACL = aclGroup.filter((acl) => {
|
const userACL = aclGroup.filter(acl => {
|
||||||
return acl.indexOf('role:') != 0 && acl != '*';
|
return acl.indexOf('role:') != 0 && acl != '*';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1570,7 +1566,7 @@ class DatabaseController {
|
|||||||
objectId: userId,
|
objectId: userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ors = permFields.flatMap((key) => {
|
const ors = permFields.flatMap(key => {
|
||||||
// constraint for single pointer setup
|
// constraint for single pointer setup
|
||||||
const q = {
|
const q = {
|
||||||
[key]: userPointer,
|
[key]: userPointer,
|
||||||
@@ -1686,9 +1682,9 @@ class DatabaseController {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// intersect all sets of protectedFields
|
// intersect all sets of protectedFields
|
||||||
protectedKeysSets.forEach((fields) => {
|
protectedKeysSets.forEach(fields => {
|
||||||
if (fields) {
|
if (fields) {
|
||||||
protectedKeys = protectedKeys.filter((v) => fields.includes(v));
|
protectedKeys = protectedKeys.filter(v => fields.includes(v));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1698,7 +1694,7 @@ class DatabaseController {
|
|||||||
createTransactionalSession() {
|
createTransactionalSession() {
|
||||||
return this.adapter
|
return this.adapter
|
||||||
.createTransactionalSession()
|
.createTransactionalSession()
|
||||||
.then((transactionalSession) => {
|
.then(transactionalSession => {
|
||||||
this._transactionalSession = transactionalSession;
|
this._transactionalSession = transactionalSession;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1741,10 +1737,10 @@ class DatabaseController {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const userClassPromise = this.loadSchema().then((schema) =>
|
const userClassPromise = this.loadSchema().then(schema =>
|
||||||
schema.enforceClassExists('_User')
|
schema.enforceClassExists('_User')
|
||||||
);
|
);
|
||||||
const roleClassPromise = this.loadSchema().then((schema) =>
|
const roleClassPromise = this.loadSchema().then(schema =>
|
||||||
schema.enforceClassExists('_Role')
|
schema.enforceClassExists('_Role')
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1752,7 +1748,7 @@ class DatabaseController {
|
|||||||
.then(() =>
|
.then(() =>
|
||||||
this.adapter.ensureUniqueness('_User', requiredUserFields, ['username'])
|
this.adapter.ensureUniqueness('_User', requiredUserFields, ['username'])
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
logger.warn('Unable to ensure uniqueness for usernames: ', error);
|
logger.warn('Unable to ensure uniqueness for usernames: ', error);
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
@@ -1767,7 +1763,7 @@ class DatabaseController {
|
|||||||
true
|
true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
'Unable to create case insensitive username index: ',
|
'Unable to create case insensitive username index: ',
|
||||||
error
|
error
|
||||||
@@ -1779,7 +1775,7 @@ class DatabaseController {
|
|||||||
.then(() =>
|
.then(() =>
|
||||||
this.adapter.ensureUniqueness('_User', requiredUserFields, ['email'])
|
this.adapter.ensureUniqueness('_User', requiredUserFields, ['email'])
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
'Unable to ensure uniqueness for user email addresses: ',
|
'Unable to ensure uniqueness for user email addresses: ',
|
||||||
error
|
error
|
||||||
@@ -1797,7 +1793,7 @@ class DatabaseController {
|
|||||||
true
|
true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
logger.warn('Unable to create case insensitive email index: ', error);
|
logger.warn('Unable to create case insensitive email index: ', error);
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
@@ -1806,7 +1802,7 @@ class DatabaseController {
|
|||||||
.then(() =>
|
.then(() =>
|
||||||
this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name'])
|
this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name'])
|
||||||
)
|
)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
logger.warn('Unable to ensure uniqueness for role name: ', error);
|
logger.warn('Unable to ensure uniqueness for role name: ', error);
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
@@ -1828,7 +1824,7 @@ class DatabaseController {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static _validateQuery: (any) => void;
|
static _validateQuery: any => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DatabaseController;
|
module.exports = DatabaseController;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export class FilesController extends AdaptableController {
|
|||||||
*/
|
*/
|
||||||
expandFilesInObject(config, object) {
|
expandFilesInObject(config, object) {
|
||||||
if (object instanceof Array) {
|
if (object instanceof Array) {
|
||||||
object.map((obj) => this.expandFilesInObject(config, obj));
|
object.map(obj => this.expandFilesInObject(config, obj));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof object !== 'object') {
|
if (typeof object !== 'object') {
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ export class HooksController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
return this._getHooks().then((hooks) => {
|
return this._getHooks().then(hooks => {
|
||||||
hooks = hooks || [];
|
hooks = hooks || [];
|
||||||
hooks.forEach((hook) => {
|
hooks.forEach(hook => {
|
||||||
this.addHookToTriggers(hook);
|
this.addHookToTriggers(hook);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -37,7 +37,7 @@ export class HooksController {
|
|||||||
|
|
||||||
getFunction(functionName) {
|
getFunction(functionName) {
|
||||||
return this._getHooks({ functionName: functionName }).then(
|
return this._getHooks({ functionName: functionName }).then(
|
||||||
(results) => results[0]
|
results => results[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ export class HooksController {
|
|||||||
return this._getHooks({
|
return this._getHooks({
|
||||||
className: className,
|
className: className,
|
||||||
triggerName: triggerName,
|
triggerName: triggerName,
|
||||||
}).then((results) => results[0]);
|
}).then(results => results[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTriggers() {
|
getTriggers() {
|
||||||
@@ -75,8 +75,8 @@ export class HooksController {
|
|||||||
_getHooks(query = {}) {
|
_getHooks(query = {}) {
|
||||||
return this.database
|
return this.database
|
||||||
.find(DefaultHooksCollectionName, query)
|
.find(DefaultHooksCollectionName, query)
|
||||||
.then((results) => {
|
.then(results => {
|
||||||
return results.map((result) => {
|
return results.map(result => {
|
||||||
delete result.objectId;
|
delete result.objectId;
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
@@ -156,7 +156,7 @@ export class HooksController {
|
|||||||
|
|
||||||
createHook(aHook) {
|
createHook(aHook) {
|
||||||
if (aHook.functionName) {
|
if (aHook.functionName) {
|
||||||
return this.getFunction(aHook.functionName).then((result) => {
|
return this.getFunction(aHook.functionName).then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
143,
|
143,
|
||||||
@@ -168,7 +168,7 @@ export class HooksController {
|
|||||||
});
|
});
|
||||||
} else if (aHook.className && aHook.triggerName) {
|
} else if (aHook.className && aHook.triggerName) {
|
||||||
return this.getTrigger(aHook.className, aHook.triggerName).then(
|
return this.getTrigger(aHook.className, aHook.triggerName).then(
|
||||||
(result) => {
|
result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
143,
|
143,
|
||||||
@@ -185,7 +185,7 @@ export class HooksController {
|
|||||||
|
|
||||||
updateHook(aHook) {
|
updateHook(aHook) {
|
||||||
if (aHook.functionName) {
|
if (aHook.functionName) {
|
||||||
return this.getFunction(aHook.functionName).then((result) => {
|
return this.getFunction(aHook.functionName).then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
return this.createOrUpdateHook(aHook);
|
return this.createOrUpdateHook(aHook);
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ export class HooksController {
|
|||||||
});
|
});
|
||||||
} else if (aHook.className && aHook.triggerName) {
|
} else if (aHook.className && aHook.triggerName) {
|
||||||
return this.getTrigger(aHook.className, aHook.triggerName).then(
|
return this.getTrigger(aHook.className, aHook.triggerName).then(
|
||||||
(result) => {
|
result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
return this.createOrUpdateHook(aHook);
|
return this.createOrUpdateHook(aHook);
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ export class HooksController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function wrapToHTTPRequest(hook, key) {
|
function wrapToHTTPRequest(hook, key) {
|
||||||
return (req) => {
|
return req => {
|
||||||
const jsonBody = {};
|
const jsonBody = {};
|
||||||
for (var i in req) {
|
for (var i in req) {
|
||||||
jsonBody[i] = req[i];
|
jsonBody[i] = req[i];
|
||||||
@@ -243,7 +243,7 @@ function wrapToHTTPRequest(hook, key) {
|
|||||||
'Making outgoing webhook request without webhookKey being set!'
|
'Making outgoing webhook request without webhookKey being set!'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return request(jsonRequest).then((response) => {
|
return request(jsonRequest).then(response => {
|
||||||
let err;
|
let err;
|
||||||
let result;
|
let result;
|
||||||
let body = response.data;
|
let body = response.data;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export class LoggerController extends AdaptableController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maskSensitive(argArray) {
|
maskSensitive(argArray) {
|
||||||
return argArray.map((e) => {
|
return argArray.map(e => {
|
||||||
if (!e) {
|
if (!e) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ export class LoggerController extends AdaptableController {
|
|||||||
e.url = this.maskSensitiveUrl(e.url);
|
e.url = this.maskSensitiveUrl(e.url);
|
||||||
} else if (Array.isArray(e.url)) {
|
} else if (Array.isArray(e.url)) {
|
||||||
// for strings in array
|
// for strings in array
|
||||||
e.url = e.url.map((item) => {
|
e.url = e.url.map(item => {
|
||||||
if (typeof item === 'string') {
|
if (typeof item === 'string') {
|
||||||
return this.maskSensitiveUrl(item);
|
return this.maskSensitiveUrl(item);
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ export class LoggerController extends AdaptableController {
|
|||||||
args = this.maskSensitive([...args]);
|
args = this.maskSensitive([...args]);
|
||||||
args = [].concat(
|
args = [].concat(
|
||||||
level,
|
level,
|
||||||
args.map((arg) => {
|
args.map(arg => {
|
||||||
if (typeof arg === 'function') {
|
if (typeof arg === 'function') {
|
||||||
return arg();
|
return arg();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class ParseGraphQLController {
|
|||||||
}
|
}
|
||||||
if (classConfigs !== null) {
|
if (classConfigs !== null) {
|
||||||
if (Array.isArray(classConfigs)) {
|
if (Array.isArray(classConfigs)) {
|
||||||
classConfigs.forEach((classConfig) => {
|
classConfigs.forEach(classConfig => {
|
||||||
const errorMessage = this._validateClassConfig(classConfig);
|
const errorMessage = this._validateClassConfig(classConfig);
|
||||||
if (errorMessage) {
|
if (errorMessage) {
|
||||||
errorMessages.push(
|
errorMessages.push(
|
||||||
@@ -334,7 +334,7 @@ class ParseGraphQLController {
|
|||||||
|
|
||||||
const isValidStringArray = function (array): boolean {
|
const isValidStringArray = function (array): boolean {
|
||||||
return Array.isArray(array)
|
return Array.isArray(array)
|
||||||
? !array.some((s) => typeof s !== 'string' || s.trim().length < 1)
|
? !array.some(s => typeof s !== 'string' || s.trim().length < 1)
|
||||||
: false;
|
: false;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ export class PushController {
|
|||||||
pushStatus
|
pushStatus
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
return pushStatus.fail(err).then(() => {
|
return pushStatus.fail(err).then(() => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export default class SchemaCache {
|
|||||||
if (!this.ttl) {
|
if (!this.ttl) {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
return this.cache.get(this.prefix + MAIN_SCHEMA).then((cachedSchemas) => {
|
return this.cache.get(this.prefix + MAIN_SCHEMA).then(cachedSchemas => {
|
||||||
cachedSchemas = cachedSchemas || [];
|
cachedSchemas = cachedSchemas || [];
|
||||||
const schema = cachedSchemas.find((cachedSchema) => {
|
const schema = cachedSchemas.find(cachedSchema => {
|
||||||
return cachedSchema.className === className;
|
return cachedSchema.className === className;
|
||||||
});
|
});
|
||||||
if (schema) {
|
if (schema) {
|
||||||
|
|||||||
@@ -545,7 +545,7 @@ class SchemaData {
|
|||||||
constructor(allSchemas = [], protectedFields = {}) {
|
constructor(allSchemas = [], protectedFields = {}) {
|
||||||
this.__data = {};
|
this.__data = {};
|
||||||
this.__protectedFields = protectedFields;
|
this.__protectedFields = protectedFields;
|
||||||
allSchemas.forEach((schema) => {
|
allSchemas.forEach(schema => {
|
||||||
if (volatileClasses.includes(schema.className)) {
|
if (volatileClasses.includes(schema.className)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -580,7 +580,7 @@ class SchemaData {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Inject the in-memory classes
|
// Inject the in-memory classes
|
||||||
volatileClasses.forEach((className) => {
|
volatileClasses.forEach(className => {
|
||||||
Object.defineProperty(this, className, {
|
Object.defineProperty(this, className, {
|
||||||
get: () => {
|
get: () => {
|
||||||
if (!this.__data[className]) {
|
if (!this.__data[className]) {
|
||||||
@@ -721,11 +721,11 @@ export default class SchemaController {
|
|||||||
}
|
}
|
||||||
this.reloadDataPromise = this.getAllClasses(options)
|
this.reloadDataPromise = this.getAllClasses(options)
|
||||||
.then(
|
.then(
|
||||||
(allSchemas) => {
|
allSchemas => {
|
||||||
this.schemaData = new SchemaData(allSchemas, this.protectedFields);
|
this.schemaData = new SchemaData(allSchemas, this.protectedFields);
|
||||||
delete this.reloadDataPromise;
|
delete this.reloadDataPromise;
|
||||||
},
|
},
|
||||||
(err) => {
|
err => {
|
||||||
this.schemaData = new SchemaData();
|
this.schemaData = new SchemaData();
|
||||||
delete this.reloadDataPromise;
|
delete this.reloadDataPromise;
|
||||||
throw err;
|
throw err;
|
||||||
@@ -741,7 +741,7 @@ export default class SchemaController {
|
|||||||
if (options.clearCache) {
|
if (options.clearCache) {
|
||||||
return this.setAllClasses();
|
return this.setAllClasses();
|
||||||
}
|
}
|
||||||
return this._cache.getAllClasses().then((allClasses) => {
|
return this._cache.getAllClasses().then(allClasses => {
|
||||||
if (allClasses && allClasses.length) {
|
if (allClasses && allClasses.length) {
|
||||||
return Promise.resolve(allClasses);
|
return Promise.resolve(allClasses);
|
||||||
}
|
}
|
||||||
@@ -752,12 +752,12 @@ export default class SchemaController {
|
|||||||
setAllClasses(): Promise<Array<Schema>> {
|
setAllClasses(): Promise<Array<Schema>> {
|
||||||
return this._dbAdapter
|
return this._dbAdapter
|
||||||
.getAllClasses()
|
.getAllClasses()
|
||||||
.then((allSchemas) => allSchemas.map(injectDefaultSchema))
|
.then(allSchemas => allSchemas.map(injectDefaultSchema))
|
||||||
.then((allSchemas) => {
|
.then(allSchemas => {
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
this._cache
|
this._cache
|
||||||
.setAllClasses(allSchemas)
|
.setAllClasses(allSchemas)
|
||||||
.catch((error) =>
|
.catch(error =>
|
||||||
console.error('Error saving schema to cache:', error)
|
console.error('Error saving schema to cache:', error)
|
||||||
);
|
);
|
||||||
/* eslint-enable no-console */
|
/* eslint-enable no-console */
|
||||||
@@ -784,13 +784,13 @@ export default class SchemaController {
|
|||||||
indexes: data.indexes,
|
indexes: data.indexes,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this._cache.getOneSchema(className).then((cached) => {
|
return this._cache.getOneSchema(className).then(cached => {
|
||||||
if (cached && !options.clearCache) {
|
if (cached && !options.clearCache) {
|
||||||
return Promise.resolve(cached);
|
return Promise.resolve(cached);
|
||||||
}
|
}
|
||||||
return this.setAllClasses().then((allSchemas) => {
|
return this.setAllClasses().then(allSchemas => {
|
||||||
const oneSchema = allSchemas.find(
|
const oneSchema = allSchemas.find(
|
||||||
(schema) => schema.className === className
|
schema => schema.className === className
|
||||||
);
|
);
|
||||||
if (!oneSchema) {
|
if (!oneSchema) {
|
||||||
return Promise.reject(undefined);
|
return Promise.reject(undefined);
|
||||||
@@ -841,7 +841,7 @@ export default class SchemaController {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.then(convertAdapterSchemaToParseSchema)
|
.then(convertAdapterSchemaToParseSchema)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
if (error && error.code === Parse.Error.DUPLICATE_VALUE) {
|
if (error && error.code === Parse.Error.DUPLICATE_VALUE) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_CLASS_NAME,
|
Parse.Error.INVALID_CLASS_NAME,
|
||||||
@@ -861,9 +861,9 @@ export default class SchemaController {
|
|||||||
database: DatabaseController
|
database: DatabaseController
|
||||||
) {
|
) {
|
||||||
return this.getOneSchema(className)
|
return this.getOneSchema(className)
|
||||||
.then((schema) => {
|
.then(schema => {
|
||||||
const existingFields = schema.fields;
|
const existingFields = schema.fields;
|
||||||
Object.keys(submittedFields).forEach((name) => {
|
Object.keys(submittedFields).forEach(name => {
|
||||||
const field = submittedFields[name];
|
const field = submittedFields[name];
|
||||||
if (existingFields[name] && field.__op !== 'Delete') {
|
if (existingFields[name] && field.__op !== 'Delete') {
|
||||||
throw new Parse.Error(255, `Field ${name} exists, cannot update.`);
|
throw new Parse.Error(255, `Field ${name} exists, cannot update.`);
|
||||||
@@ -899,7 +899,7 @@ export default class SchemaController {
|
|||||||
// Do all deletions first, then a single save to _SCHEMA collection to handle all additions.
|
// Do all deletions first, then a single save to _SCHEMA collection to handle all additions.
|
||||||
const deletedFields: string[] = [];
|
const deletedFields: string[] = [];
|
||||||
const insertedFields = [];
|
const insertedFields = [];
|
||||||
Object.keys(submittedFields).forEach((fieldName) => {
|
Object.keys(submittedFields).forEach(fieldName => {
|
||||||
if (submittedFields[fieldName].__op === 'Delete') {
|
if (submittedFields[fieldName].__op === 'Delete') {
|
||||||
deletedFields.push(fieldName);
|
deletedFields.push(fieldName);
|
||||||
} else {
|
} else {
|
||||||
@@ -916,14 +916,14 @@ export default class SchemaController {
|
|||||||
deletePromise // Delete Everything
|
deletePromise // Delete Everything
|
||||||
.then(() => this.reloadData({ clearCache: true })) // Reload our Schema, so we have all the new values
|
.then(() => this.reloadData({ clearCache: true })) // Reload our Schema, so we have all the new values
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const promises = insertedFields.map((fieldName) => {
|
const promises = insertedFields.map(fieldName => {
|
||||||
const type = submittedFields[fieldName];
|
const type = submittedFields[fieldName];
|
||||||
return this.enforceFieldExists(className, fieldName, type);
|
return this.enforceFieldExists(className, fieldName, type);
|
||||||
});
|
});
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
})
|
})
|
||||||
.then((results) => {
|
.then(results => {
|
||||||
enforceFields = results.filter((result) => !!result);
|
enforceFields = results.filter(result => !!result);
|
||||||
return this.setPermissions(
|
return this.setPermissions(
|
||||||
className,
|
className,
|
||||||
classLevelPermissions,
|
classLevelPermissions,
|
||||||
@@ -955,7 +955,7 @@ export default class SchemaController {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
if (error === undefined) {
|
if (error === undefined) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_CLASS_NAME,
|
Parse.Error.INVALID_CLASS_NAME,
|
||||||
@@ -1095,7 +1095,7 @@ export default class SchemaController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const geoPoints = Object.keys(fields).filter(
|
const geoPoints = Object.keys(fields).filter(
|
||||||
(key) => fields[key] && fields[key].type === 'GeoPoint'
|
key => fields[key] && fields[key].type === 'GeoPoint'
|
||||||
);
|
);
|
||||||
if (geoPoints.length > 1) {
|
if (geoPoints.length > 1) {
|
||||||
return {
|
return {
|
||||||
@@ -1180,7 +1180,7 @@ export default class SchemaController {
|
|||||||
|
|
||||||
return this._dbAdapter
|
return this._dbAdapter
|
||||||
.addFieldIfNotExists(className, fieldName, type)
|
.addFieldIfNotExists(className, fieldName, type)
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
if (error.code == Parse.Error.INCORRECT_TYPE) {
|
if (error.code == Parse.Error.INCORRECT_TYPE) {
|
||||||
// Make sure that we throw errors when it is appropriate to do so.
|
// Make sure that we throw errors when it is appropriate to do so.
|
||||||
throw error;
|
throw error;
|
||||||
@@ -1244,7 +1244,7 @@ export default class SchemaController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldNames.forEach((fieldName) => {
|
fieldNames.forEach(fieldName => {
|
||||||
if (!fieldNameIsValid(fieldName)) {
|
if (!fieldNameIsValid(fieldName)) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_KEY_NAME,
|
Parse.Error.INVALID_KEY_NAME,
|
||||||
@@ -1258,7 +1258,7 @@ export default class SchemaController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return this.getOneSchema(className, false, { clearCache: true })
|
return this.getOneSchema(className, false, { clearCache: true })
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
if (error === undefined) {
|
if (error === undefined) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_CLASS_NAME,
|
Parse.Error.INVALID_CLASS_NAME,
|
||||||
@@ -1268,8 +1268,8 @@ export default class SchemaController {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((schema) => {
|
.then(schema => {
|
||||||
fieldNames.forEach((fieldName) => {
|
fieldNames.forEach(fieldName => {
|
||||||
if (!schema.fields[fieldName]) {
|
if (!schema.fields[fieldName]) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
255,
|
255,
|
||||||
@@ -1283,7 +1283,7 @@ export default class SchemaController {
|
|||||||
.deleteFields(className, schema, fieldNames)
|
.deleteFields(className, schema, fieldNames)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
fieldNames.map((fieldName) => {
|
fieldNames.map(fieldName => {
|
||||||
const field = schemaFields[fieldName];
|
const field = schemaFields[fieldName];
|
||||||
if (field && field.type === 'Relation') {
|
if (field && field.type === 'Relation') {
|
||||||
//For relations, drop the _Join table
|
//For relations, drop the _Join table
|
||||||
@@ -1335,7 +1335,7 @@ export default class SchemaController {
|
|||||||
promises.push(schema.enforceFieldExists(className, fieldName, expected));
|
promises.push(schema.enforceFieldExists(className, fieldName, expected));
|
||||||
}
|
}
|
||||||
const results = await Promise.all(promises);
|
const results = await Promise.all(promises);
|
||||||
const enforceFields = results.filter((result) => !!result);
|
const enforceFields = results.filter(result => !!result);
|
||||||
|
|
||||||
if (enforceFields.length !== 0) {
|
if (enforceFields.length !== 0) {
|
||||||
await this.reloadData({ clearCache: true });
|
await this.reloadData({ clearCache: true });
|
||||||
@@ -1401,7 +1401,7 @@ export default class SchemaController {
|
|||||||
}
|
}
|
||||||
// Check permissions against the aclGroup provided (array of userId/roles)
|
// Check permissions against the aclGroup provided (array of userId/roles)
|
||||||
if (
|
if (
|
||||||
aclGroup.some((acl) => {
|
aclGroup.some(acl => {
|
||||||
return perms[acl] === true;
|
return perms[acl] === true;
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
@@ -1594,7 +1594,7 @@ function buildMergedSchemaObject(
|
|||||||
// Given a schema promise, construct another schema promise that
|
// Given a schema promise, construct another schema promise that
|
||||||
// validates this field once the schema loads.
|
// validates this field once the schema loads.
|
||||||
function thenValidateRequiredColumns(schemaPromise, className, object, query) {
|
function thenValidateRequiredColumns(schemaPromise, className, object, query) {
|
||||||
return schemaPromise.then((schema) => {
|
return schemaPromise.then(schema => {
|
||||||
return schema.validateRequiredColumns(className, object, query);
|
return schema.validateRequiredColumns(className, object, query);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export class UserController extends AdaptableController {
|
|||||||
'_User',
|
'_User',
|
||||||
{ username: username, emailVerified: true }
|
{ username: username, emailVerified: true }
|
||||||
);
|
);
|
||||||
return checkIfAlreadyVerified.execute().then((result) => {
|
return checkIfAlreadyVerified.execute().then(result => {
|
||||||
if (result.results.length) {
|
if (result.results.length) {
|
||||||
return Promise.resolve(result.results.length[0]);
|
return Promise.resolve(result.results.length[0]);
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ export class UserController extends AdaptableController {
|
|||||||
},
|
},
|
||||||
{ limit: 1 }
|
{ limit: 1 }
|
||||||
)
|
)
|
||||||
.then((results) => {
|
.then(results => {
|
||||||
if (results.length != 1) {
|
if (results.length != 1) {
|
||||||
throw 'Failed to reset password: username / email / token is invalid';
|
throw 'Failed to reset password: username / email / token is invalid';
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ export class UserController extends AdaptableController {
|
|||||||
}
|
}
|
||||||
const token = encodeURIComponent(user._email_verify_token);
|
const token = encodeURIComponent(user._email_verify_token);
|
||||||
// We may need to fetch the user in case of update email
|
// 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 username = encodeURIComponent(user.username);
|
||||||
|
|
||||||
const link = buildEmailLink(
|
const link = buildEmailLink(
|
||||||
@@ -179,7 +179,7 @@ export class UserController extends AdaptableController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resendVerificationEmail(username) {
|
resendVerificationEmail(username) {
|
||||||
return this.getUserIfNeeded({ username: username }).then((aUser) => {
|
return this.getUserIfNeeded({ username: username }).then(aUser => {
|
||||||
if (!aUser || aUser.emailVerified) {
|
if (!aUser || aUser.emailVerified) {
|
||||||
throw undefined;
|
throw undefined;
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ export class UserController extends AdaptableController {
|
|||||||
// TODO: No adapter?
|
// TODO: No adapter?
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.setPasswordResetToken(email).then((user) => {
|
return this.setPasswordResetToken(email).then(user => {
|
||||||
const token = encodeURIComponent(user._perishable_token);
|
const token = encodeURIComponent(user._perishable_token);
|
||||||
const username = encodeURIComponent(user.username);
|
const username = encodeURIComponent(user.username);
|
||||||
|
|
||||||
@@ -244,8 +244,8 @@ export class UserController extends AdaptableController {
|
|||||||
|
|
||||||
updatePassword(username, token, password) {
|
updatePassword(username, token, password) {
|
||||||
return this.checkResetTokenValidity(username, token)
|
return this.checkResetTokenValidity(username, token)
|
||||||
.then((user) => updateUserPassword(user.objectId, password, this.config))
|
.then(user => updateUserPassword(user.objectId, password, this.config))
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
if (error && error.message) {
|
if (error && error.message) {
|
||||||
// in case of Parse.Error, fail with the error message only
|
// in case of Parse.Error, fail with the error message only
|
||||||
return Promise.reject(error.message);
|
return Promise.reject(error.message);
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ class ParseGraphQLSchema {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Object.values(customGraphQLSchemaTypeMap).forEach(
|
Object.values(customGraphQLSchemaTypeMap).forEach(
|
||||||
(customGraphQLSchemaType) => {
|
customGraphQLSchemaType => {
|
||||||
if (
|
if (
|
||||||
!customGraphQLSchemaType ||
|
!customGraphQLSchemaType ||
|
||||||
!customGraphQLSchemaType.name ||
|
!customGraphQLSchemaType.name ||
|
||||||
@@ -236,7 +236,7 @@ class ParseGraphQLSchema {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
Object.values(customGraphQLSchemaTypeMap).forEach(
|
Object.values(customGraphQLSchemaTypeMap).forEach(
|
||||||
(customGraphQLSchemaType) => {
|
customGraphQLSchemaType => {
|
||||||
if (
|
if (
|
||||||
!customGraphQLSchemaType ||
|
!customGraphQLSchemaType ||
|
||||||
!customGraphQLSchemaType.name ||
|
!customGraphQLSchemaType.name ||
|
||||||
@@ -253,7 +253,7 @@ class ParseGraphQLSchema {
|
|||||||
typeof customGraphQLSchemaType.getFields === 'function'
|
typeof customGraphQLSchemaType.getFields === 'function'
|
||||||
) {
|
) {
|
||||||
Object.values(customGraphQLSchemaType.getFields()).forEach(
|
Object.values(customGraphQLSchemaType.getFields()).forEach(
|
||||||
(field) => {
|
field => {
|
||||||
findAndReplaceLastType(field, 'type');
|
findAndReplaceLastType(field, 'type');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -289,24 +289,24 @@ class ParseGraphQLSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const graphQLSchemaTypeMap = this.graphQLSchema.getTypeMap();
|
const graphQLSchemaTypeMap = this.graphQLSchema.getTypeMap();
|
||||||
Object.keys(graphQLSchemaTypeMap).forEach((graphQLSchemaTypeName) => {
|
Object.keys(graphQLSchemaTypeMap).forEach(graphQLSchemaTypeName => {
|
||||||
const graphQLSchemaType = graphQLSchemaTypeMap[graphQLSchemaTypeName];
|
const graphQLSchemaType = graphQLSchemaTypeMap[graphQLSchemaTypeName];
|
||||||
if (
|
if (
|
||||||
typeof graphQLSchemaType.getFields === 'function' &&
|
typeof graphQLSchemaType.getFields === 'function' &&
|
||||||
this.graphQLCustomTypeDefs.definitions
|
this.graphQLCustomTypeDefs.definitions
|
||||||
) {
|
) {
|
||||||
const graphQLCustomTypeDef = this.graphQLCustomTypeDefs.definitions.find(
|
const graphQLCustomTypeDef = this.graphQLCustomTypeDefs.definitions.find(
|
||||||
(definition) => definition.name.value === graphQLSchemaTypeName
|
definition => definition.name.value === graphQLSchemaTypeName
|
||||||
);
|
);
|
||||||
if (graphQLCustomTypeDef) {
|
if (graphQLCustomTypeDef) {
|
||||||
const graphQLSchemaTypeFieldMap = graphQLSchemaType.getFields();
|
const graphQLSchemaTypeFieldMap = graphQLSchemaType.getFields();
|
||||||
Object.keys(graphQLSchemaTypeFieldMap).forEach(
|
Object.keys(graphQLSchemaTypeFieldMap).forEach(
|
||||||
(graphQLSchemaTypeFieldName) => {
|
graphQLSchemaTypeFieldName => {
|
||||||
const graphQLSchemaTypeField =
|
const graphQLSchemaTypeField =
|
||||||
graphQLSchemaTypeFieldMap[graphQLSchemaTypeFieldName];
|
graphQLSchemaTypeFieldMap[graphQLSchemaTypeFieldName];
|
||||||
if (!graphQLSchemaTypeField.astNode) {
|
if (!graphQLSchemaTypeField.astNode) {
|
||||||
const astNode = graphQLCustomTypeDef.fields.find(
|
const astNode = graphQLCustomTypeDef.fields.find(
|
||||||
(field) => field.name.value === graphQLSchemaTypeFieldName
|
field => field.name.value === graphQLSchemaTypeFieldName
|
||||||
);
|
);
|
||||||
if (astNode) {
|
if (astNode) {
|
||||||
graphQLSchemaTypeField.astNode = astNode;
|
graphQLSchemaTypeField.astNode = astNode;
|
||||||
@@ -337,9 +337,7 @@ class ParseGraphQLSchema {
|
|||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
(!ignoreReserved && RESERVED_GRAPHQL_TYPE_NAMES.includes(type.name)) ||
|
(!ignoreReserved && RESERVED_GRAPHQL_TYPE_NAMES.includes(type.name)) ||
|
||||||
this.graphQLTypes.find(
|
this.graphQLTypes.find(existingType => existingType.name === type.name) ||
|
||||||
(existingType) => existingType.name === type.name
|
|
||||||
) ||
|
|
||||||
(!ignoreConnection && type.name.endsWith('Connection'))
|
(!ignoreConnection && type.name.endsWith('Connection'))
|
||||||
) {
|
) {
|
||||||
const message = `Type ${type.name} could not be added to the auto schema because it collided with an existing type.`;
|
const message = `Type ${type.name} could not be added to the auto schema because it collided with an existing type.`;
|
||||||
@@ -429,7 +427,7 @@ class ParseGraphQLSchema {
|
|||||||
if (Array.isArray(enabledForClasses) || Array.isArray(disabledForClasses)) {
|
if (Array.isArray(enabledForClasses) || Array.isArray(disabledForClasses)) {
|
||||||
let includedClasses = allClasses;
|
let includedClasses = allClasses;
|
||||||
if (enabledForClasses) {
|
if (enabledForClasses) {
|
||||||
includedClasses = allClasses.filter((clazz) => {
|
includedClasses = allClasses.filter(clazz => {
|
||||||
return enabledForClasses.includes(clazz.className);
|
return enabledForClasses.includes(clazz.className);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -437,12 +435,12 @@ class ParseGraphQLSchema {
|
|||||||
// Classes included in `enabledForClasses` that
|
// Classes included in `enabledForClasses` that
|
||||||
// are also present in `disabledForClasses` will
|
// are also present in `disabledForClasses` will
|
||||||
// still be filtered out
|
// still be filtered out
|
||||||
includedClasses = includedClasses.filter((clazz) => {
|
includedClasses = includedClasses.filter(clazz => {
|
||||||
return !disabledForClasses.includes(clazz.className);
|
return !disabledForClasses.includes(clazz.className);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isUsersClassDisabled = !includedClasses.some((clazz) => {
|
this.isUsersClassDisabled = !includedClasses.some(clazz => {
|
||||||
return clazz.className === '_User';
|
return clazz.className === '_User';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -487,11 +485,11 @@ class ParseGraphQLSchema {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return parseClasses.sort(sortClasses).map((parseClass) => {
|
return parseClasses.sort(sortClasses).map(parseClass => {
|
||||||
let parseClassConfig;
|
let parseClassConfig;
|
||||||
if (classConfigs) {
|
if (classConfigs) {
|
||||||
parseClassConfig = classConfigs.find(
|
parseClassConfig = classConfigs.find(
|
||||||
(c) => c.className === parseClass.className
|
c => c.className === parseClass.className
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return [parseClass, parseClassConfig];
|
return [parseClass, parseClassConfig];
|
||||||
@@ -499,7 +497,7 @@ class ParseGraphQLSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _getFunctionNames() {
|
async _getFunctionNames() {
|
||||||
return await getFunctionNames(this.appId).filter((functionName) => {
|
return await getFunctionNames(this.appId).filter(functionName => {
|
||||||
if (/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(functionName)) {
|
if (/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(functionName)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class ParseGraphQLServer {
|
|||||||
config: req.config,
|
config: req.config,
|
||||||
auth: req.auth,
|
auth: req.auth,
|
||||||
},
|
},
|
||||||
formatError: (error) => {
|
formatError: error => {
|
||||||
// Allow to console.log here to debug
|
// Allow to console.log here to debug
|
||||||
return error;
|
return error;
|
||||||
},
|
},
|
||||||
@@ -91,7 +91,7 @@ class ParseGraphQLServer {
|
|||||||
app.use(this.config.graphQLPath, handleParseErrors);
|
app.use(this.config.graphQLPath, handleParseErrors);
|
||||||
app.use(
|
app.use(
|
||||||
this.config.graphQLPath,
|
this.config.graphQLPath,
|
||||||
graphqlExpress(async (req) => await this._getGraphQLOptions(req))
|
graphqlExpress(async req => await this._getGraphQLOptions(req))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ export function toGraphQLError(error) {
|
|||||||
return new ApolloError(message, code);
|
return new ApolloError(message, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const extractKeysAndInclude = (selectedFields) => {
|
export const extractKeysAndInclude = selectedFields => {
|
||||||
selectedFields = selectedFields.filter(
|
selectedFields = selectedFields.filter(
|
||||||
(field) => !field.includes('__typename')
|
field => !field.includes('__typename')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handles "id" field for both current and included objects
|
// Handles "id" field for both current and included objects
|
||||||
selectedFields = selectedFields.map((field) => {
|
selectedFields = selectedFields.map(field => {
|
||||||
if (field === 'id') return 'objectId';
|
if (field === 'id') return 'objectId';
|
||||||
return field.endsWith('.id')
|
return field.endsWith('.id')
|
||||||
? `${field.substring(0, field.lastIndexOf('.id'))}.objectId`
|
? `${field.substring(0, field.lastIndexOf('.id'))}.objectId`
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class ParseLiveQueryServer {
|
|||||||
// Initialize websocket server
|
// Initialize websocket server
|
||||||
this.parseWebSocketServer = new ParseWebSocketServer(
|
this.parseWebSocketServer = new ParseWebSocketServer(
|
||||||
server,
|
server,
|
||||||
(parseWebsocket) => this._onConnect(parseWebsocket),
|
parseWebsocket => this._onConnect(parseWebsocket),
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -165,13 +165,13 @@ class ParseLiveQueryServer {
|
|||||||
// Check ACL
|
// Check ACL
|
||||||
return this._matchesACL(acl, client, requestId);
|
return this._matchesACL(acl, client, requestId);
|
||||||
})
|
})
|
||||||
.then((isMatched) => {
|
.then(isMatched => {
|
||||||
if (!isMatched) {
|
if (!isMatched) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
client.pushDelete(requestId, deletedParseObject);
|
client.pushDelete(requestId, deletedParseObject);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
logger.error('Matching ACL error : ', error);
|
logger.error('Matching ACL error : ', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ class ParseLiveQueryServer {
|
|||||||
originalParseObject
|
originalParseObject
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
(error) => {
|
error => {
|
||||||
logger.error('Matching ACL error : ', error);
|
logger.error('Matching ACL error : ', error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -308,7 +308,7 @@ class ParseLiveQueryServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onConnect(parseWebsocket: any): void {
|
_onConnect(parseWebsocket: any): void {
|
||||||
parseWebsocket.on('message', (request) => {
|
parseWebsocket.on('message', request => {
|
||||||
if (typeof request === 'string') {
|
if (typeof request === 'string') {
|
||||||
try {
|
try {
|
||||||
request = JSON.parse(request);
|
request = JSON.parse(request);
|
||||||
@@ -426,10 +426,10 @@ class ParseLiveQueryServer {
|
|||||||
cacheController: this.cacheController,
|
cacheController: this.cacheController,
|
||||||
sessionToken: sessionToken,
|
sessionToken: sessionToken,
|
||||||
})
|
})
|
||||||
.then((auth) => {
|
.then(auth => {
|
||||||
return { auth, userId: auth && auth.user && auth.user.id };
|
return { auth, userId: auth && auth.user && auth.user.id };
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
// There was an error with the session token
|
// There was an error with the session token
|
||||||
const result = {};
|
const result = {};
|
||||||
if (error && error.code === Parse.Error.INVALID_SESSION_TOKEN) {
|
if (error && error.code === Parse.Error.INVALID_SESSION_TOKEN) {
|
||||||
@@ -523,7 +523,7 @@ class ParseLiveQueryServer {
|
|||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
// Resolve false right away if the acl doesn't have any roles
|
// Resolve false right away if the acl doesn't have any roles
|
||||||
const acl_has_roles = Object.keys(acl.permissionsById).some((key) =>
|
const acl_has_roles = Object.keys(acl.permissionsById).some(key =>
|
||||||
key.startsWith('role:')
|
key.startsWith('role:')
|
||||||
);
|
);
|
||||||
if (!acl_has_roles) {
|
if (!acl_has_roles) {
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export class ParseWebSocketServer {
|
|||||||
wss.onListen = () => {
|
wss.onListen = () => {
|
||||||
logger.info('Parse LiveQuery Server starts running');
|
logger.info('Parse LiveQuery Server starts running');
|
||||||
};
|
};
|
||||||
wss.onConnection = (ws) => {
|
wss.onConnection = ws => {
|
||||||
ws.on('error', (error) => {
|
ws.on('error', error => {
|
||||||
logger.error(error.message);
|
logger.error(error.message);
|
||||||
logger.error(JSON.stringify(ws));
|
logger.error(JSON.stringify(ws));
|
||||||
});
|
});
|
||||||
@@ -27,7 +27,7 @@ export class ParseWebSocketServer {
|
|||||||
}
|
}
|
||||||
}, config.websocketTimeout || 10 * 1000);
|
}, config.websocketTimeout || 10 * 1000);
|
||||||
};
|
};
|
||||||
wss.onError = (error) => {
|
wss.onError = error => {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
};
|
};
|
||||||
wss.start();
|
wss.start();
|
||||||
@@ -46,7 +46,7 @@ export class ParseWebSocket extends events.EventEmitter {
|
|||||||
|
|
||||||
constructor(ws: any) {
|
constructor(ws: any) {
|
||||||
super();
|
super();
|
||||||
ws.onmessage = (request) =>
|
ws.onmessage = request =>
|
||||||
this.emit('message', request && request.data ? request.data : request);
|
this.emit('message', request && request.data ? request.data : request);
|
||||||
ws.onclose = () => this.emit('disconnect');
|
ws.onclose = () => this.emit('disconnect');
|
||||||
this.ws = ws;
|
this.ws = ws;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class SessionTokenCache {
|
|||||||
return Promise.resolve(userId);
|
return Promise.resolve(userId);
|
||||||
}
|
}
|
||||||
return userForSessionToken(sessionToken).then(
|
return userForSessionToken(sessionToken).then(
|
||||||
(user) => {
|
user => {
|
||||||
logger.verbose(
|
logger.verbose(
|
||||||
'Fetch userId %s of sessionToken %s from Parse',
|
'Fetch userId %s of sessionToken %s from Parse',
|
||||||
user.id,
|
user.id,
|
||||||
@@ -50,7 +50,7 @@ class SessionTokenCache {
|
|||||||
this.cache.set(sessionToken, userId);
|
this.cache.set(sessionToken, userId);
|
||||||
return Promise.resolve(userId);
|
return Promise.resolve(userId);
|
||||||
},
|
},
|
||||||
(error) => {
|
error => {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Can not fetch userId for sessionToken %j, error %j',
|
'Can not fetch userId for sessionToken %j, error %j',
|
||||||
sessionToken,
|
sessionToken,
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export class PushWorker {
|
|||||||
installations,
|
installations,
|
||||||
locales
|
locales
|
||||||
);
|
);
|
||||||
const promises = Object.keys(grouppedInstallations).map((locale) => {
|
const promises = Object.keys(grouppedInstallations).map(locale => {
|
||||||
const installations = grouppedInstallations[locale];
|
const installations = grouppedInstallations[locale];
|
||||||
const body = bodiesPerLocales[locale];
|
const body = bodiesPerLocales[locale];
|
||||||
return this.sendToAdapter(
|
return this.sendToAdapter(
|
||||||
@@ -94,7 +94,7 @@ export class PushWorker {
|
|||||||
logger.verbose(`Sending push to ${installations.length}`);
|
logger.verbose(`Sending push to ${installations.length}`);
|
||||||
return this.adapter
|
return this.adapter
|
||||||
.send(body, installations, pushStatus.objectId)
|
.send(body, installations, pushStatus.objectId)
|
||||||
.then((results) => {
|
.then(results => {
|
||||||
return pushStatus.trackSent(results, UTCOffset).then(() => results);
|
return pushStatus.trackSent(results, UTCOffset).then(() => results);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ export class PushWorker {
|
|||||||
const badgeInstallationsMap = groupByBadge(installations);
|
const badgeInstallationsMap = groupByBadge(installations);
|
||||||
|
|
||||||
// Map the on the badges count and return the send result
|
// Map the on the badges count and return the send result
|
||||||
const promises = Object.keys(badgeInstallationsMap).map((badge) => {
|
const promises = Object.keys(badgeInstallationsMap).map(badge => {
|
||||||
const payload = deepcopy(body);
|
const payload = deepcopy(body);
|
||||||
payload.data.badge = parseInt(badge);
|
payload.data.badge = parseInt(badge);
|
||||||
const installations = badgeInstallationsMap[badge];
|
const installations = badgeInstallationsMap[badge];
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function getLocalesFromPush(body) {
|
|||||||
return [
|
return [
|
||||||
...new Set(
|
...new Set(
|
||||||
Object.keys(data).reduce((memo, key) => {
|
Object.keys(data).reduce((memo, key) => {
|
||||||
localizableKeys.forEach((localizableKey) => {
|
localizableKeys.forEach(localizableKey => {
|
||||||
if (key.indexOf(`${localizableKey}-`) == 0) {
|
if (key.indexOf(`${localizableKey}-`) == 0) {
|
||||||
memo.push(key.slice(localizableKey.length + 1));
|
memo.push(key.slice(localizableKey.length + 1));
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ export function transformPushBodyForLocale(body, locale) {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
body = deepcopy(body);
|
body = deepcopy(body);
|
||||||
localizableKeys.forEach((key) => {
|
localizableKeys.forEach(key => {
|
||||||
const localeValue = body.data[`${key}-${locale}`];
|
const localeValue = body.data[`${key}-${locale}`];
|
||||||
if (localeValue) {
|
if (localeValue) {
|
||||||
body.data[key] = localeValue;
|
body.data[key] = localeValue;
|
||||||
@@ -59,8 +59,8 @@ export function stripLocalesFromBody(body) {
|
|||||||
if (!body.data) {
|
if (!body.data) {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
Object.keys(body.data).forEach((key) => {
|
Object.keys(body.data).forEach(key => {
|
||||||
localizableKeys.forEach((localizableKey) => {
|
localizableKeys.forEach(localizableKey => {
|
||||||
if (key.indexOf(`${localizableKey}-`) == 0) {
|
if (key.indexOf(`${localizableKey}-`) == 0) {
|
||||||
delete body.data[key];
|
delete body.data[key];
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ export function groupByLocaleIdentifier(installations, locales = []) {
|
|||||||
return installations.reduce(
|
return installations.reduce(
|
||||||
(map, installation) => {
|
(map, installation) => {
|
||||||
let added = false;
|
let added = false;
|
||||||
locales.forEach((locale) => {
|
locales.forEach(locale => {
|
||||||
if (added) {
|
if (added) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export class AggregateRouter extends ClassesRouter {
|
|||||||
req.info.clientSDK,
|
req.info.clientSDK,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
for (const result of response.results) {
|
for (const result of response.results) {
|
||||||
if (typeof result === 'object') {
|
if (typeof result === 'object') {
|
||||||
UsersRouter.removeHiddenProperties(result);
|
UsersRouter.removeHiddenProperties(result);
|
||||||
@@ -110,12 +110,12 @@ export class AggregateRouter extends ClassesRouter {
|
|||||||
static getPipeline(body) {
|
static getPipeline(body) {
|
||||||
let pipeline = body.pipeline || body;
|
let pipeline = body.pipeline || body;
|
||||||
if (!Array.isArray(pipeline)) {
|
if (!Array.isArray(pipeline)) {
|
||||||
pipeline = Object.keys(pipeline).map((key) => {
|
pipeline = Object.keys(pipeline).map(key => {
|
||||||
return { [key]: pipeline[key] };
|
return { [key]: pipeline[key] };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return pipeline.map((stage) => {
|
return pipeline.map(stage => {
|
||||||
const keys = Object.keys(stage);
|
const keys = Object.keys(stage);
|
||||||
if (keys.length != 1) {
|
if (keys.length != 1) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -157,7 +157,7 @@ export class AggregateRouter extends ClassesRouter {
|
|||||||
'GET',
|
'GET',
|
||||||
'/aggregate/:className',
|
'/aggregate/:className',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handleFind(req);
|
return this.handleFind(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ export class AudiencesRouter extends ClassesRouter {
|
|||||||
req.info.clientSDK,
|
req.info.clientSDK,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
response.results.forEach((item) => {
|
response.results.forEach(item => {
|
||||||
item.query = JSON.parse(item.query);
|
item.query = JSON.parse(item.query);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export class AudiencesRouter extends ClassesRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleGet(req) {
|
handleGet(req) {
|
||||||
return super.handleGet(req).then((data) => {
|
return super.handleGet(req).then(data => {
|
||||||
data.response.query = JSON.parse(data.response.query);
|
data.response.query = JSON.parse(data.response.query);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -46,7 +46,7 @@ export class AudiencesRouter extends ClassesRouter {
|
|||||||
'GET',
|
'GET',
|
||||||
'/push_audiences',
|
'/push_audiences',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handleFind(req);
|
return this.handleFind(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -54,7 +54,7 @@ export class AudiencesRouter extends ClassesRouter {
|
|||||||
'GET',
|
'GET',
|
||||||
'/push_audiences/:objectId',
|
'/push_audiences/:objectId',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handleGet(req);
|
return this.handleGet(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -62,7 +62,7 @@ export class AudiencesRouter extends ClassesRouter {
|
|||||||
'POST',
|
'POST',
|
||||||
'/push_audiences',
|
'/push_audiences',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handleCreate(req);
|
return this.handleCreate(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -70,7 +70,7 @@ export class AudiencesRouter extends ClassesRouter {
|
|||||||
'PUT',
|
'PUT',
|
||||||
'/push_audiences/:objectId',
|
'/push_audiences/:objectId',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handleUpdate(req);
|
return this.handleUpdate(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -78,7 +78,7 @@ export class AudiencesRouter extends ClassesRouter {
|
|||||||
'DELETE',
|
'DELETE',
|
||||||
'/push_audiences/:objectId',
|
'/push_audiences/:objectId',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handleDelete(req);
|
return this.handleDelete(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export class ClassesRouter extends PromiseRouter {
|
|||||||
req.info.clientSDK,
|
req.info.clientSDK,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
return { response: response };
|
return { response: response };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ export class ClassesRouter extends PromiseRouter {
|
|||||||
options,
|
options,
|
||||||
req.info.clientSDK
|
req.info.clientSDK
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
if (!response.results || response.results.length == 0) {
|
if (!response.results || response.results.length == 0) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.OBJECT_NOT_FOUND,
|
Parse.Error.OBJECT_NOT_FOUND,
|
||||||
@@ -241,19 +241,19 @@ export class ClassesRouter extends PromiseRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mountRoutes() {
|
mountRoutes() {
|
||||||
this.route('GET', '/classes/:className', (req) => {
|
this.route('GET', '/classes/:className', req => {
|
||||||
return this.handleFind(req);
|
return this.handleFind(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/classes/:className/:objectId', (req) => {
|
this.route('GET', '/classes/:className/:objectId', req => {
|
||||||
return this.handleGet(req);
|
return this.handleGet(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/classes/:className', (req) => {
|
this.route('POST', '/classes/:className', req => {
|
||||||
return this.handleCreate(req);
|
return this.handleCreate(req);
|
||||||
});
|
});
|
||||||
this.route('PUT', '/classes/:className/:objectId', (req) => {
|
this.route('PUT', '/classes/:className/:objectId', req => {
|
||||||
return this.handleUpdate(req);
|
return this.handleUpdate(req);
|
||||||
});
|
});
|
||||||
this.route('DELETE', '/classes/:className/:objectId', (req) => {
|
this.route('DELETE', '/classes/:className/:objectId', req => {
|
||||||
return this.handleDelete(req);
|
return this.handleDelete(req);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export class CloudCodeRouter extends PromiseRouter {
|
|||||||
static getJobs(req) {
|
static getJobs(req) {
|
||||||
return rest
|
return rest
|
||||||
.find(req.config, req.auth, '_JobSchedule', {}, {})
|
.find(req.config, req.auth, '_JobSchedule', {}, {})
|
||||||
.then((scheduledJobs) => {
|
.then(scheduledJobs => {
|
||||||
return {
|
return {
|
||||||
response: scheduledJobs.results,
|
response: scheduledJobs.results,
|
||||||
};
|
};
|
||||||
@@ -70,10 +70,10 @@ export class CloudCodeRouter extends PromiseRouter {
|
|||||||
const jobs = triggers.getJobs(config.applicationId) || {};
|
const jobs = triggers.getJobs(config.applicationId) || {};
|
||||||
return rest
|
return rest
|
||||||
.find(req.config, req.auth, '_JobSchedule', {}, {})
|
.find(req.config, req.auth, '_JobSchedule', {}, {})
|
||||||
.then((scheduledJobs) => {
|
.then(scheduledJobs => {
|
||||||
return {
|
return {
|
||||||
response: {
|
response: {
|
||||||
in_use: scheduledJobs.results.map((job) => job.jobName),
|
in_use: scheduledJobs.results.map(job => job.jobName),
|
||||||
jobs: Object.keys(jobs),
|
jobs: Object.keys(jobs),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -107,7 +107,7 @@ export class CloudCodeRouter extends PromiseRouter {
|
|||||||
undefined,
|
undefined,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
return {
|
return {
|
||||||
response,
|
response,
|
||||||
};
|
};
|
||||||
@@ -118,7 +118,7 @@ export class CloudCodeRouter extends PromiseRouter {
|
|||||||
const { objectId } = req.params;
|
const { objectId } = req.params;
|
||||||
return rest
|
return rest
|
||||||
.del(req.config, req.auth, '_JobSchedule', objectId, req.info.context)
|
.del(req.config, req.auth, '_JobSchedule', objectId, req.info.context)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
return {
|
return {
|
||||||
response,
|
response,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export class FeaturesRouter extends PromiseRouter {
|
|||||||
'GET',
|
'GET',
|
||||||
'/serverInfo',
|
'/serverInfo',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
const { config } = req;
|
const { config } = req;
|
||||||
const features = {
|
const features = {
|
||||||
globalConfig: {
|
globalConfig: {
|
||||||
|
|||||||
@@ -8,22 +8,22 @@ import logger from '../logger';
|
|||||||
const triggers = require('../triggers');
|
const triggers = require('../triggers');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
|
|
||||||
const downloadFileFromURI = (uri) => {
|
const downloadFileFromURI = uri => {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
http
|
http
|
||||||
.get(uri, (response) => {
|
.get(uri, response => {
|
||||||
response.setDefaultEncoding('base64');
|
response.setDefaultEncoding('base64');
|
||||||
let body = `data:${response.headers['content-type']};base64,`;
|
let body = `data:${response.headers['content-type']};base64,`;
|
||||||
response.on('data', (data) => (body += data));
|
response.on('data', data => (body += data));
|
||||||
response.on('end', () => res(body));
|
response.on('end', () => res(body));
|
||||||
})
|
})
|
||||||
.on('error', (e) => {
|
.on('error', e => {
|
||||||
rej(`Error downloading file from ${uri}: ${e.message}`);
|
rej(`Error downloading file from ${uri}: ${e.message}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const addFileDataIfNeeded = async (file) => {
|
const addFileDataIfNeeded = async file => {
|
||||||
if (file._source.format === 'uri') {
|
if (file._source.format === 'uri') {
|
||||||
const base64 = await downloadFileFromURI(file._source.uri);
|
const base64 = await downloadFileFromURI(file._source.uri);
|
||||||
file._previousSave = file;
|
file._previousSave = file;
|
||||||
@@ -33,7 +33,7 @@ const addFileDataIfNeeded = async (file) => {
|
|||||||
return file;
|
return file;
|
||||||
};
|
};
|
||||||
|
|
||||||
const errorMessageFromError = (e) => {
|
const errorMessageFromError = e => {
|
||||||
if (typeof e === 'string') {
|
if (typeof e === 'string') {
|
||||||
return e;
|
return e;
|
||||||
} else if (e && e.message) {
|
} else if (e && e.message) {
|
||||||
@@ -91,7 +91,7 @@ export class FilesRouter {
|
|||||||
} else {
|
} else {
|
||||||
filesController
|
filesController
|
||||||
.getFileData(config, filename)
|
.getFileData(config, filename)
|
||||||
.then((data) => {
|
.then(data => {
|
||||||
res.status(200);
|
res.status(200);
|
||||||
res.set('Content-Type', contentType);
|
res.set('Content-Type', contentType);
|
||||||
res.set('Content-Length', data.length);
|
res.set('Content-Length', data.length);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { logger } from '../logger';
|
|||||||
|
|
||||||
function parseObject(obj) {
|
function parseObject(obj) {
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
return obj.map((item) => {
|
return obj.map(item => {
|
||||||
return parseObject(item);
|
return parseObject(item);
|
||||||
});
|
});
|
||||||
} else if (obj && obj.__type == 'Date') {
|
} else if (obj && obj.__type == 'Date') {
|
||||||
@@ -68,7 +68,7 @@ export class FunctionsRouter extends PromiseRouter {
|
|||||||
message: jobHandler.setMessage.bind(jobHandler),
|
message: jobHandler.setMessage.bind(jobHandler),
|
||||||
};
|
};
|
||||||
|
|
||||||
return jobHandler.setRunning(jobName, params).then((jobStatus) => {
|
return jobHandler.setRunning(jobName, params).then(jobStatus => {
|
||||||
request.jobId = jobStatus.objectId;
|
request.jobId = jobStatus.objectId;
|
||||||
// run the function async
|
// run the function async
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
@@ -77,10 +77,10 @@ export class FunctionsRouter extends PromiseRouter {
|
|||||||
return jobFunction(request);
|
return jobFunction(request);
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
(result) => {
|
result => {
|
||||||
jobHandler.setSucceeded(result);
|
jobHandler.setSucceeded(result);
|
||||||
},
|
},
|
||||||
(error) => {
|
error => {
|
||||||
jobHandler.setFailed(error);
|
jobHandler.setFailed(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -166,7 +166,7 @@ export class FunctionsRouter extends PromiseRouter {
|
|||||||
req.auth && req.auth.user ? req.auth.user.id : undefined;
|
req.auth && req.auth.user ? req.auth.user.id : undefined;
|
||||||
const cleanInput = logger.truncateLogMessage(JSON.stringify(params));
|
const cleanInput = logger.truncateLogMessage(JSON.stringify(params));
|
||||||
const { success, error, message } = FunctionsRouter.createResponseObject(
|
const { success, error, message } = FunctionsRouter.createResponseObject(
|
||||||
(result) => {
|
result => {
|
||||||
try {
|
try {
|
||||||
const cleanResult = logger.truncateLogMessage(
|
const cleanResult = logger.truncateLogMessage(
|
||||||
JSON.stringify(result.response.result)
|
JSON.stringify(result.response.result)
|
||||||
@@ -184,7 +184,7 @@ export class FunctionsRouter extends PromiseRouter {
|
|||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
error => {
|
||||||
try {
|
try {
|
||||||
logger.error(
|
logger.error(
|
||||||
`Failed running cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Error: ` +
|
`Failed running cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Error: ` +
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export class GlobalConfigRouter extends PromiseRouter {
|
|||||||
getGlobalConfig(req) {
|
getGlobalConfig(req) {
|
||||||
return req.config.database
|
return req.config.database
|
||||||
.find('_GlobalConfig', { objectId: '1' }, { limit: 1 })
|
.find('_GlobalConfig', { objectId: '1' }, { limit: 1 })
|
||||||
.then((results) => {
|
.then(results => {
|
||||||
if (results.length != 1) {
|
if (results.length != 1) {
|
||||||
// If there is no config in the database - return empty config.
|
// If there is no config in the database - return empty config.
|
||||||
return { response: { params: {} } };
|
return { response: { params: {} } };
|
||||||
@@ -51,14 +51,14 @@ export class GlobalConfigRouter extends PromiseRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mountRoutes() {
|
mountRoutes() {
|
||||||
this.route('GET', '/config', (req) => {
|
this.route('GET', '/config', req => {
|
||||||
return this.getGlobalConfig(req);
|
return this.getGlobalConfig(req);
|
||||||
});
|
});
|
||||||
this.route(
|
this.route(
|
||||||
'PUT',
|
'PUT',
|
||||||
'/config',
|
'/config',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.updateGlobalConfig(req);
|
return this.updateGlobalConfig(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export class GraphQLRouter extends PromiseRouter {
|
|||||||
'GET',
|
'GET',
|
||||||
GraphQLConfigPath,
|
GraphQLConfigPath,
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.getGraphQLConfig(req);
|
return this.getGraphQLConfig(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -40,7 +40,7 @@ export class GraphQLRouter extends PromiseRouter {
|
|||||||
'PUT',
|
'PUT',
|
||||||
GraphQLConfigPath,
|
GraphQLConfigPath,
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.updateGraphQLConfig(req);
|
return this.updateGraphQLConfig(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ export class HooksRouter extends PromiseRouter {
|
|||||||
createHook(aHook, config) {
|
createHook(aHook, config) {
|
||||||
return config.hooksController
|
return config.hooksController
|
||||||
.createHook(aHook)
|
.createHook(aHook)
|
||||||
.then((hook) => ({ response: hook }));
|
.then(hook => ({ response: hook }));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHook(aHook, config) {
|
updateHook(aHook, config) {
|
||||||
return config.hooksController
|
return config.hooksController
|
||||||
.updateHook(aHook)
|
.updateHook(aHook)
|
||||||
.then((hook) => ({ response: hook }));
|
.then(hook => ({ response: hook }));
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePost(req) {
|
handlePost(req) {
|
||||||
@@ -24,7 +24,7 @@ export class HooksRouter extends PromiseRouter {
|
|||||||
if (req.params.functionName) {
|
if (req.params.functionName) {
|
||||||
return hooksController
|
return hooksController
|
||||||
.getFunction(req.params.functionName)
|
.getFunction(req.params.functionName)
|
||||||
.then((foundFunction) => {
|
.then(foundFunction => {
|
||||||
if (!foundFunction) {
|
if (!foundFunction) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
143,
|
143,
|
||||||
@@ -36,10 +36,10 @@ export class HooksRouter extends PromiseRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return hooksController.getFunctions().then(
|
return hooksController.getFunctions().then(
|
||||||
(functions) => {
|
functions => {
|
||||||
return { response: functions || [] };
|
return { response: functions || [] };
|
||||||
},
|
},
|
||||||
(err) => {
|
err => {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -50,7 +50,7 @@ export class HooksRouter extends PromiseRouter {
|
|||||||
if (req.params.className && req.params.triggerName) {
|
if (req.params.className && req.params.triggerName) {
|
||||||
return hooksController
|
return hooksController
|
||||||
.getTrigger(req.params.className, req.params.triggerName)
|
.getTrigger(req.params.className, req.params.triggerName)
|
||||||
.then((foundTrigger) => {
|
.then(foundTrigger => {
|
||||||
if (!foundTrigger) {
|
if (!foundTrigger) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
143,
|
143,
|
||||||
@@ -63,7 +63,7 @@ export class HooksRouter extends PromiseRouter {
|
|||||||
|
|
||||||
return hooksController
|
return hooksController
|
||||||
.getTriggers()
|
.getTriggers()
|
||||||
.then((triggers) => ({ response: triggers || [] }));
|
.then(triggers => ({ response: triggers || [] }));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDelete(req) {
|
handleDelete(req) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ function validateWithAppStore(url, receipt) {
|
|||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
}).then((httpResponse) => {
|
}).then(httpResponse => {
|
||||||
const body = httpResponse.data;
|
const body = httpResponse.data;
|
||||||
if (body && body.status === 0) {
|
if (body && body.status === 0) {
|
||||||
// No need to pass anything, status is OK
|
// No need to pass anything, status is OK
|
||||||
@@ -106,13 +106,13 @@ export class IAPValidationRouter extends PromiseRouter {
|
|||||||
() => {
|
() => {
|
||||||
return successCallback();
|
return successCallback();
|
||||||
},
|
},
|
||||||
(error) => {
|
error => {
|
||||||
if (error.status == 21007) {
|
if (error.status == 21007) {
|
||||||
return validateWithAppStore(IAP_SANDBOX_URL, receipt).then(
|
return validateWithAppStore(IAP_SANDBOX_URL, receipt).then(
|
||||||
() => {
|
() => {
|
||||||
return successCallback();
|
return successCallback();
|
||||||
},
|
},
|
||||||
(error) => {
|
error => {
|
||||||
return errorCallback(error);
|
return errorCallback(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,25 +24,25 @@ export class InstallationsRouter extends ClassesRouter {
|
|||||||
req.info.clientSDK,
|
req.info.clientSDK,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
return { response: response };
|
return { response: response };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
mountRoutes() {
|
mountRoutes() {
|
||||||
this.route('GET', '/installations', (req) => {
|
this.route('GET', '/installations', req => {
|
||||||
return this.handleFind(req);
|
return this.handleFind(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/installations/:objectId', (req) => {
|
this.route('GET', '/installations/:objectId', req => {
|
||||||
return this.handleGet(req);
|
return this.handleGet(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/installations', (req) => {
|
this.route('POST', '/installations', req => {
|
||||||
return this.handleCreate(req);
|
return this.handleCreate(req);
|
||||||
});
|
});
|
||||||
this.route('PUT', '/installations/:objectId', (req) => {
|
this.route('PUT', '/installations/:objectId', req => {
|
||||||
return this.handleUpdate(req);
|
return this.handleUpdate(req);
|
||||||
});
|
});
|
||||||
this.route('DELETE', '/installations/:objectId', (req) => {
|
this.route('DELETE', '/installations/:objectId', req => {
|
||||||
return this.handleDelete(req);
|
return this.handleDelete(req);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export class LogsRouter extends PromiseRouter {
|
|||||||
'/scriptlog',
|
'/scriptlog',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
this.validateRequest,
|
this.validateRequest,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handleGET(req);
|
return this.handleGET(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -50,7 +50,7 @@ export class LogsRouter extends PromiseRouter {
|
|||||||
level,
|
level,
|
||||||
};
|
};
|
||||||
|
|
||||||
return req.config.loggerController.getLogs(options).then((result) => {
|
return req.config.loggerController.getLogs(options).then(result => {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
response: result,
|
response: result,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -191,14 +191,14 @@ export class PublicAPIRouter extends PromiseRouter {
|
|||||||
success: true,
|
success: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(err) => {
|
err => {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
success: false,
|
success: false,
|
||||||
err,
|
err,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((result) => {
|
.then(result => {
|
||||||
const params = qs.stringify({
|
const params = qs.stringify({
|
||||||
username: username,
|
username: username,
|
||||||
token: token,
|
token: token,
|
||||||
@@ -277,10 +277,10 @@ export class PublicAPIRouter extends PromiseRouter {
|
|||||||
this.route(
|
this.route(
|
||||||
'GET',
|
'GET',
|
||||||
'/apps/:appId/verify_email',
|
'/apps/:appId/verify_email',
|
||||||
(req) => {
|
req => {
|
||||||
this.setConfig(req);
|
this.setConfig(req);
|
||||||
},
|
},
|
||||||
(req) => {
|
req => {
|
||||||
return this.verifyEmail(req);
|
return this.verifyEmail(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -288,25 +288,25 @@ export class PublicAPIRouter extends PromiseRouter {
|
|||||||
this.route(
|
this.route(
|
||||||
'POST',
|
'POST',
|
||||||
'/apps/:appId/resend_verification_email',
|
'/apps/:appId/resend_verification_email',
|
||||||
(req) => {
|
req => {
|
||||||
this.setConfig(req);
|
this.setConfig(req);
|
||||||
},
|
},
|
||||||
(req) => {
|
req => {
|
||||||
return this.resendVerificationEmail(req);
|
return this.resendVerificationEmail(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.route('GET', '/apps/choose_password', (req) => {
|
this.route('GET', '/apps/choose_password', req => {
|
||||||
return this.changePassword(req);
|
return this.changePassword(req);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route(
|
this.route(
|
||||||
'POST',
|
'POST',
|
||||||
'/apps/:appId/request_password_reset',
|
'/apps/:appId/request_password_reset',
|
||||||
(req) => {
|
req => {
|
||||||
this.setConfig(req);
|
this.setConfig(req);
|
||||||
},
|
},
|
||||||
(req) => {
|
req => {
|
||||||
return this.resetPassword(req);
|
return this.resetPassword(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -314,10 +314,10 @@ export class PublicAPIRouter extends PromiseRouter {
|
|||||||
this.route(
|
this.route(
|
||||||
'GET',
|
'GET',
|
||||||
'/apps/:appId/request_password_reset',
|
'/apps/:appId/request_password_reset',
|
||||||
(req) => {
|
req => {
|
||||||
this.setConfig(req);
|
this.setConfig(req);
|
||||||
},
|
},
|
||||||
(req) => {
|
req => {
|
||||||
return this.requestResetPassword(req);
|
return this.requestResetPassword(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class PurgeRouter extends PromiseRouter {
|
|||||||
}
|
}
|
||||||
return { response: {} };
|
return { response: {} };
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
if (!error || (error && error.code === Parse.Error.OBJECT_NOT_FOUND)) {
|
if (!error || (error && error.code === Parse.Error.OBJECT_NOT_FOUND)) {
|
||||||
return { response: {} };
|
return { response: {} };
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ export class PurgeRouter extends PromiseRouter {
|
|||||||
'DELETE',
|
'DELETE',
|
||||||
'/purge/:className',
|
'/purge/:className',
|
||||||
middleware.promiseEnforceMasterKeyAccess,
|
middleware.promiseEnforceMasterKeyAccess,
|
||||||
(req) => {
|
req => {
|
||||||
return this.handlePurge(req);
|
return this.handlePurge(req);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ export class PushRouter extends PromiseRouter {
|
|||||||
|
|
||||||
const where = PushRouter.getQueryCondition(req);
|
const where = PushRouter.getQueryCondition(req);
|
||||||
let resolve;
|
let resolve;
|
||||||
const promise = new Promise((_resolve) => {
|
const promise = new Promise(_resolve => {
|
||||||
resolve = _resolve;
|
resolve = _resolve;
|
||||||
});
|
});
|
||||||
let pushStatusId;
|
let pushStatusId;
|
||||||
pushController
|
pushController
|
||||||
.sendPush(req.body, where, req.config, req.auth, (objectId) => {
|
.sendPush(req.body, where, req.config, req.auth, objectId => {
|
||||||
pushStatusId = objectId;
|
pushStatusId = objectId;
|
||||||
resolve({
|
resolve({
|
||||||
headers: {
|
headers: {
|
||||||
@@ -45,7 +45,7 @@ export class PushRouter extends PromiseRouter {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
req.config.loggerController.error(
|
req.config.loggerController.error(
|
||||||
`_PushStatus ${pushStatusId}: error while sending push`,
|
`_PushStatus ${pushStatusId}: error while sending push`,
|
||||||
err
|
err
|
||||||
|
|||||||
@@ -6,19 +6,19 @@ export class RolesRouter extends ClassesRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mountRoutes() {
|
mountRoutes() {
|
||||||
this.route('GET', '/roles', (req) => {
|
this.route('GET', '/roles', req => {
|
||||||
return this.handleFind(req);
|
return this.handleFind(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/roles/:objectId', (req) => {
|
this.route('GET', '/roles/:objectId', req => {
|
||||||
return this.handleGet(req);
|
return this.handleGet(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/roles', (req) => {
|
this.route('POST', '/roles', req => {
|
||||||
return this.handleCreate(req);
|
return this.handleCreate(req);
|
||||||
});
|
});
|
||||||
this.route('PUT', '/roles/:objectId', (req) => {
|
this.route('PUT', '/roles/:objectId', req => {
|
||||||
return this.handleUpdate(req);
|
return this.handleUpdate(req);
|
||||||
});
|
});
|
||||||
this.route('DELETE', '/roles/:objectId', (req) => {
|
this.route('DELETE', '/roles/:objectId', req => {
|
||||||
return this.handleDelete(req);
|
return this.handleDelete(req);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,17 @@ function classNameMismatchResponse(bodyClass, pathClass) {
|
|||||||
function getAllSchemas(req) {
|
function getAllSchemas(req) {
|
||||||
return req.config.database
|
return req.config.database
|
||||||
.loadSchema({ clearCache: true })
|
.loadSchema({ clearCache: true })
|
||||||
.then((schemaController) => schemaController.getAllClasses(true))
|
.then(schemaController => schemaController.getAllClasses(true))
|
||||||
.then((schemas) => ({ response: { results: schemas } }));
|
.then(schemas => ({ response: { results: schemas } }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOneSchema(req) {
|
function getOneSchema(req) {
|
||||||
const className = req.params.className;
|
const className = req.params.className;
|
||||||
return req.config.database
|
return req.config.database
|
||||||
.loadSchema({ clearCache: true })
|
.loadSchema({ clearCache: true })
|
||||||
.then((schemaController) => schemaController.getOneSchema(className, true))
|
.then(schemaController => schemaController.getOneSchema(className, true))
|
||||||
.then((schema) => ({ response: schema }))
|
.then(schema => ({ response: schema }))
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
if (error === undefined) {
|
if (error === undefined) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_CLASS_NAME,
|
Parse.Error.INVALID_CLASS_NAME,
|
||||||
@@ -64,7 +64,7 @@ function createSchema(req) {
|
|||||||
|
|
||||||
return req.config.database
|
return req.config.database
|
||||||
.loadSchema({ clearCache: true })
|
.loadSchema({ clearCache: true })
|
||||||
.then((schema) =>
|
.then(schema =>
|
||||||
schema.addClassIfNotExists(
|
schema.addClassIfNotExists(
|
||||||
className,
|
className,
|
||||||
req.body.fields,
|
req.body.fields,
|
||||||
@@ -72,7 +72,7 @@ function createSchema(req) {
|
|||||||
req.body.indexes
|
req.body.indexes
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then((schema) => ({ response: schema }));
|
.then(schema => ({ response: schema }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function modifySchema(req) {
|
function modifySchema(req) {
|
||||||
@@ -91,7 +91,7 @@ function modifySchema(req) {
|
|||||||
|
|
||||||
return req.config.database
|
return req.config.database
|
||||||
.loadSchema({ clearCache: true })
|
.loadSchema({ clearCache: true })
|
||||||
.then((schema) =>
|
.then(schema =>
|
||||||
schema.updateClass(
|
schema.updateClass(
|
||||||
className,
|
className,
|
||||||
submittedFields,
|
submittedFields,
|
||||||
@@ -100,10 +100,10 @@ function modifySchema(req) {
|
|||||||
req.config.database
|
req.config.database
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then((result) => ({ response: result }));
|
.then(result => ({ response: result }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteSchema = (req) => {
|
const deleteSchema = req => {
|
||||||
if (req.auth.isReadOnly) {
|
if (req.auth.isReadOnly) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.OPERATION_FORBIDDEN,
|
Parse.Error.OPERATION_FORBIDDEN,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class SessionsRouter extends ClassesRouter {
|
|||||||
req.info.clientSDK,
|
req.info.clientSDK,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
if (!response.results || response.results.length == 0) {
|
if (!response.results || response.results.length == 0) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_SESSION_TOKEN,
|
Parse.Error.INVALID_SESSION_TOKEN,
|
||||||
@@ -74,25 +74,25 @@ export class SessionsRouter extends ClassesRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mountRoutes() {
|
mountRoutes() {
|
||||||
this.route('GET', '/sessions/me', (req) => {
|
this.route('GET', '/sessions/me', req => {
|
||||||
return this.handleMe(req);
|
return this.handleMe(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/sessions', (req) => {
|
this.route('GET', '/sessions', req => {
|
||||||
return this.handleFind(req);
|
return this.handleFind(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/sessions/:objectId', (req) => {
|
this.route('GET', '/sessions/:objectId', req => {
|
||||||
return this.handleGet(req);
|
return this.handleGet(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/sessions', (req) => {
|
this.route('POST', '/sessions', req => {
|
||||||
return this.handleCreate(req);
|
return this.handleCreate(req);
|
||||||
});
|
});
|
||||||
this.route('PUT', '/sessions/:objectId', (req) => {
|
this.route('PUT', '/sessions/:objectId', req => {
|
||||||
return this.handleUpdate(req);
|
return this.handleUpdate(req);
|
||||||
});
|
});
|
||||||
this.route('DELETE', '/sessions/:objectId', (req) => {
|
this.route('DELETE', '/sessions/:objectId', req => {
|
||||||
return this.handleDelete(req);
|
return this.handleDelete(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/upgradeToRevocableSession', (req) => {
|
this.route('POST', '/upgradeToRevocableSession', req => {
|
||||||
return this.handleUpdateToRevocableSession(req);
|
return this.handleUpdateToRevocableSession(req);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
}
|
}
|
||||||
return req.config.database
|
return req.config.database
|
||||||
.find('_User', query)
|
.find('_User', query)
|
||||||
.then((results) => {
|
.then(results => {
|
||||||
if (!results.length) {
|
if (!results.length) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.OBJECT_NOT_FOUND,
|
Parse.Error.OBJECT_NOT_FOUND,
|
||||||
@@ -96,14 +96,14 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
req.config.loggerController.warn(
|
req.config.loggerController.warn(
|
||||||
"There is a user which email is the same as another user's username, logging in based on username"
|
"There is a user which email is the same as another user's username, logging in based on username"
|
||||||
);
|
);
|
||||||
user = results.filter((user) => user.username === username)[0];
|
user = results.filter(user => user.username === username)[0];
|
||||||
} else {
|
} else {
|
||||||
user = results[0];
|
user = results[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return passwordCrypto.compare(password, user.password);
|
return passwordCrypto.compare(password, user.password);
|
||||||
})
|
})
|
||||||
.then((correct) => {
|
.then(correct => {
|
||||||
isValidPassword = correct;
|
isValidPassword = correct;
|
||||||
const accountLockoutPolicy = new AccountLockout(user, req.config);
|
const accountLockoutPolicy = new AccountLockout(user, req.config);
|
||||||
return accountLockoutPolicy.handleLoginAttempt(isValidPassword);
|
return accountLockoutPolicy.handleLoginAttempt(isValidPassword);
|
||||||
@@ -145,7 +145,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
// Sometimes the authData still has null on that keys
|
// Sometimes the authData still has null on that keys
|
||||||
// https://github.com/parse-community/parse-server/issues/935
|
// https://github.com/parse-community/parse-server/issues/935
|
||||||
if (user.authData) {
|
if (user.authData) {
|
||||||
Object.keys(user.authData).forEach((provider) => {
|
Object.keys(user.authData).forEach(provider => {
|
||||||
if (user.authData[provider] === null) {
|
if (user.authData[provider] === null) {
|
||||||
delete user.authData[provider];
|
delete user.authData[provider];
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
|
|
||||||
return resolve(user);
|
return resolve(user);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
return reject(error);
|
return reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -181,7 +181,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
req.info.clientSDK,
|
req.info.clientSDK,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
if (
|
if (
|
||||||
!response.results ||
|
!response.results ||
|
||||||
response.results.length == 0 ||
|
response.results.length == 0 ||
|
||||||
@@ -282,13 +282,13 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
|
|
||||||
handleVerifyPassword(req) {
|
handleVerifyPassword(req) {
|
||||||
return this._authenticateUserFromRequest(req)
|
return this._authenticateUserFromRequest(req)
|
||||||
.then((user) => {
|
.then(user => {
|
||||||
// Remove hidden properties.
|
// Remove hidden properties.
|
||||||
UsersRouter.removeHiddenProperties(user);
|
UsersRouter.removeHiddenProperties(user);
|
||||||
|
|
||||||
return { response: user };
|
return { response: user };
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -306,7 +306,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
req.info.clientSDK,
|
req.info.clientSDK,
|
||||||
req.info.context
|
req.info.context
|
||||||
)
|
)
|
||||||
.then((records) => {
|
.then(records => {
|
||||||
if (records.results && records.results.length) {
|
if (records.results && records.results.length) {
|
||||||
return rest
|
return rest
|
||||||
.del(
|
.del(
|
||||||
@@ -383,7 +383,7 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
response: {},
|
response: {},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(err) => {
|
err => {
|
||||||
if (err.code === Parse.Error.OBJECT_NOT_FOUND) {
|
if (err.code === Parse.Error.OBJECT_NOT_FOUND) {
|
||||||
// Return success so that this endpoint can't
|
// Return success so that this endpoint can't
|
||||||
// be used to enumerate valid emails
|
// be used to enumerate valid emails
|
||||||
@@ -414,70 +414,68 @@ export class UsersRouter extends ClassesRouter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return req.config.database
|
return req.config.database.find('_User', { email: email }).then(results => {
|
||||||
.find('_User', { email: email })
|
if (!results.length || results.length < 1) {
|
||||||
.then((results) => {
|
throw new Parse.Error(
|
||||||
if (!results.length || results.length < 1) {
|
Parse.Error.EMAIL_NOT_FOUND,
|
||||||
throw new Parse.Error(
|
`No user found with email ${email}`
|
||||||
Parse.Error.EMAIL_NOT_FOUND,
|
);
|
||||||
`No user found with email ${email}`
|
}
|
||||||
);
|
const user = results[0];
|
||||||
}
|
|
||||||
const user = results[0];
|
|
||||||
|
|
||||||
// remove password field, messes with saving on postgres
|
// remove password field, messes with saving on postgres
|
||||||
delete user.password;
|
delete user.password;
|
||||||
|
|
||||||
if (user.emailVerified) {
|
if (user.emailVerified) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.OTHER_CAUSE,
|
Parse.Error.OTHER_CAUSE,
|
||||||
`Email ${email} is already verified.`
|
`Email ${email} is already verified.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userController = req.config.userController;
|
const userController = req.config.userController;
|
||||||
return userController.regenerateEmailVerifyToken(user).then(() => {
|
return userController.regenerateEmailVerifyToken(user).then(() => {
|
||||||
userController.sendVerificationEmail(user);
|
userController.sendVerificationEmail(user);
|
||||||
return { response: {} };
|
return { response: {} };
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
mountRoutes() {
|
mountRoutes() {
|
||||||
this.route('GET', '/users', (req) => {
|
this.route('GET', '/users', req => {
|
||||||
return this.handleFind(req);
|
return this.handleFind(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/users', (req) => {
|
this.route('POST', '/users', req => {
|
||||||
return this.handleCreate(req);
|
return this.handleCreate(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/users/me', (req) => {
|
this.route('GET', '/users/me', req => {
|
||||||
return this.handleMe(req);
|
return this.handleMe(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/users/:objectId', (req) => {
|
this.route('GET', '/users/:objectId', req => {
|
||||||
return this.handleGet(req);
|
return this.handleGet(req);
|
||||||
});
|
});
|
||||||
this.route('PUT', '/users/:objectId', (req) => {
|
this.route('PUT', '/users/:objectId', req => {
|
||||||
return this.handleUpdate(req);
|
return this.handleUpdate(req);
|
||||||
});
|
});
|
||||||
this.route('DELETE', '/users/:objectId', (req) => {
|
this.route('DELETE', '/users/:objectId', req => {
|
||||||
return this.handleDelete(req);
|
return this.handleDelete(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/login', (req) => {
|
this.route('GET', '/login', req => {
|
||||||
return this.handleLogIn(req);
|
return this.handleLogIn(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/login', (req) => {
|
this.route('POST', '/login', req => {
|
||||||
return this.handleLogIn(req);
|
return this.handleLogIn(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/logout', (req) => {
|
this.route('POST', '/logout', req => {
|
||||||
return this.handleLogOut(req);
|
return this.handleLogOut(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/requestPasswordReset', (req) => {
|
this.route('POST', '/requestPasswordReset', req => {
|
||||||
return this.handleResetRequest(req);
|
return this.handleResetRequest(req);
|
||||||
});
|
});
|
||||||
this.route('POST', '/verificationEmailRequest', (req) => {
|
this.route('POST', '/verificationEmailRequest', req => {
|
||||||
return this.handleVerificationEmailRequest(req);
|
return this.handleVerificationEmailRequest(req);
|
||||||
});
|
});
|
||||||
this.route('GET', '/verifyPassword', (req) => {
|
this.route('GET', '/verifyPassword', req => {
|
||||||
return this.handleVerifyPassword(req);
|
return this.handleVerifyPassword(req);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const clients = {
|
|||||||
function makeCallback(resolve, reject) {
|
function makeCallback(resolve, reject) {
|
||||||
return function (response) {
|
return function (response) {
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
response.on('data', (chunk) => {
|
response.on('data', chunk => {
|
||||||
chunks.push(chunk);
|
chunks.push(chunk);
|
||||||
});
|
});
|
||||||
response.on('end', () => {
|
response.on('end', () => {
|
||||||
@@ -34,7 +34,7 @@ const encodeBody = function ({ body, headers = {} }) {
|
|||||||
if (typeof body !== 'object') {
|
if (typeof body !== 'object') {
|
||||||
return { body, headers };
|
return { body, headers };
|
||||||
}
|
}
|
||||||
var contentTypeKeys = Object.keys(headers).filter((key) => {
|
var contentTypeKeys = Object.keys(headers).filter(key => {
|
||||||
return key.match(/content-type/i) != null;
|
return key.match(/content-type/i) != null;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ module.exports = function httpRequest(options) {
|
|||||||
followRedirects: options.followRedirects === true,
|
followRedirects: options.followRedirects === true,
|
||||||
};
|
};
|
||||||
if (requestOptions.headers) {
|
if (requestOptions.headers) {
|
||||||
Object.keys(requestOptions.headers).forEach((key) => {
|
Object.keys(requestOptions.headers).forEach(key => {
|
||||||
if (typeof requestOptions.headers[key] === 'undefined') {
|
if (typeof requestOptions.headers[key] === 'undefined') {
|
||||||
delete requestOptions.headers[key];
|
delete requestOptions.headers[key];
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ module.exports = function httpRequest(options) {
|
|||||||
if (options.body) {
|
if (options.body) {
|
||||||
req.write(options.body);
|
req.write(options.body);
|
||||||
}
|
}
|
||||||
req.on('error', (error) => {
|
req.on('error', error => {
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
req.end();
|
req.end();
|
||||||
|
|||||||
Reference in New Issue
Block a user