217 lines
6.1 KiB
JavaScript
217 lines
6.1 KiB
JavaScript
/** @flow weak */
|
|
|
|
import * as DatabaseAdapter from "../DatabaseAdapter";
|
|
import * as triggers from "../triggers";
|
|
import * as Parse from "parse/node";
|
|
import * as request from "request";
|
|
|
|
const DefaultHooksCollectionName = "_Hooks";
|
|
|
|
export class HooksController {
|
|
_applicationId:string;
|
|
_collectionPrefix:string;
|
|
_collection;
|
|
|
|
constructor(applicationId:string, collectionPrefix:string = '') {
|
|
this._applicationId = applicationId;
|
|
this._collectionPrefix = collectionPrefix;
|
|
}
|
|
|
|
load() {
|
|
return this._getHooks().then(hooks => {
|
|
hooks = hooks || [];
|
|
hooks.forEach((hook) => {
|
|
this.addHookToTriggers(hook);
|
|
});
|
|
});
|
|
}
|
|
|
|
getCollection() {
|
|
if (this._collection) {
|
|
return Promise.resolve(this._collection)
|
|
}
|
|
|
|
let database = DatabaseAdapter.getDatabaseConnection(this._applicationId, this._collectionPrefix);
|
|
return database.adaptiveCollection(DefaultHooksCollectionName).then(collection => {
|
|
this._collection = collection;
|
|
return collection;
|
|
});
|
|
}
|
|
|
|
getFunction(functionName) {
|
|
return this._getHooks({ functionName: functionName }, 1).then(results => results[0]);
|
|
}
|
|
|
|
getFunctions() {
|
|
return this._getHooks({ functionName: { $exists: true } });
|
|
}
|
|
|
|
getTrigger(className, triggerName) {
|
|
return this._getHooks({ className: className, triggerName: triggerName }, 1).then(results => results[0]);
|
|
}
|
|
|
|
getTriggers() {
|
|
return this._getHooks({ className: { $exists: true }, triggerName: { $exists: true } });
|
|
}
|
|
|
|
deleteFunction(functionName) {
|
|
triggers.removeFunction(functionName, this._applicationId);
|
|
return this._removeHooks({ functionName: functionName });
|
|
}
|
|
|
|
deleteTrigger(className, triggerName) {
|
|
triggers.removeTrigger(triggerName, className, this._applicationId);
|
|
return this._removeHooks({ className: className, triggerName: triggerName });
|
|
}
|
|
|
|
_getHooks(query, limit) {
|
|
let options = limit ? { limit: limit } : undefined;
|
|
return this.getCollection().then(collection => collection.find(query, options));
|
|
}
|
|
|
|
_removeHooks(query) {
|
|
return this.getCollection().then(collection => {
|
|
return collection.deleteMany(query);
|
|
}).then(() => {
|
|
return {};
|
|
});
|
|
}
|
|
|
|
saveHook(hook) {
|
|
var query;
|
|
if (hook.functionName && hook.url) {
|
|
query = { functionName: hook.functionName }
|
|
} else if (hook.triggerName && hook.className && hook.url) {
|
|
query = { className: hook.className, triggerName: hook.triggerName }
|
|
} else {
|
|
throw new Parse.Error(143, "invalid hook declaration");
|
|
}
|
|
return this.getCollection()
|
|
.then(collection => collection.upsertOne(query, hook))
|
|
.then(() => {
|
|
return hook;
|
|
});
|
|
}
|
|
|
|
addHookToTriggers(hook) {
|
|
var wrappedFunction = wrapToHTTPRequest(hook);
|
|
wrappedFunction.url = hook.url;
|
|
if (hook.className) {
|
|
triggers.addTrigger(hook.triggerName, hook.className, wrappedFunction, this._applicationId)
|
|
} else {
|
|
triggers.addFunction(hook.functionName, wrappedFunction, null, this._applicationId);
|
|
}
|
|
}
|
|
|
|
addHook(hook) {
|
|
this.addHookToTriggers(hook);
|
|
return this.saveHook(hook);
|
|
}
|
|
|
|
createOrUpdateHook(aHook) {
|
|
var hook;
|
|
if (aHook && aHook.functionName && aHook.url) {
|
|
hook = {};
|
|
hook.functionName = aHook.functionName;
|
|
hook.url = aHook.url;
|
|
} else if (aHook && aHook.className && aHook.url && aHook.triggerName && triggers.Types[aHook.triggerName]) {
|
|
hook = {};
|
|
hook.className = aHook.className;
|
|
hook.url = aHook.url;
|
|
hook.triggerName = aHook.triggerName;
|
|
|
|
} else {
|
|
throw new Parse.Error(143, "invalid hook declaration");
|
|
}
|
|
|
|
return this.addHook(hook);
|
|
};
|
|
|
|
createHook(aHook) {
|
|
if (aHook.functionName) {
|
|
return this.getFunction(aHook.functionName).then((result) => {
|
|
if (result) {
|
|
throw new Parse.Error(143, `function name: ${aHook.functionName} already exits`);
|
|
} else {
|
|
return this.createOrUpdateHook(aHook);
|
|
}
|
|
});
|
|
} else if (aHook.className && aHook.triggerName) {
|
|
return this.getTrigger(aHook.className, aHook.triggerName).then((result) => {
|
|
if (result) {
|
|
throw new Parse.Error(143, `class ${aHook.className} already has trigger ${aHook.triggerName}`);
|
|
}
|
|
return this.createOrUpdateHook(aHook);
|
|
});
|
|
}
|
|
|
|
throw new Parse.Error(143, "invalid hook declaration");
|
|
};
|
|
|
|
updateHook(aHook) {
|
|
if (aHook.functionName) {
|
|
return this.getFunction(aHook.functionName).then((result) => {
|
|
if (result) {
|
|
return this.createOrUpdateHook(aHook);
|
|
}
|
|
throw new Parse.Error(143, `no function named: ${aHook.functionName} is defined`);
|
|
});
|
|
} else if (aHook.className && aHook.triggerName) {
|
|
return this.getTrigger(aHook.className, aHook.triggerName).then((result) => {
|
|
if (result) {
|
|
return this.createOrUpdateHook(aHook);
|
|
}
|
|
throw new Parse.Error(143, `class ${aHook.className} does not exist`);
|
|
});
|
|
}
|
|
throw new Parse.Error(143, "invalid hook declaration");
|
|
};
|
|
}
|
|
|
|
function wrapToHTTPRequest(hook) {
|
|
return (req, res) => {
|
|
let jsonBody = {};
|
|
for (var i in req) {
|
|
jsonBody[i] = req[i];
|
|
}
|
|
if (req.object) {
|
|
jsonBody.object = req.object.toJSON();
|
|
jsonBody.object.className = req.object.className;
|
|
}
|
|
if (req.original) {
|
|
jsonBody.original = req.original.toJSON();
|
|
jsonBody.original.className = req.original.className;
|
|
}
|
|
let jsonRequest = {
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(jsonBody)
|
|
};
|
|
|
|
request.post(hook.url, jsonRequest, function (err, httpResponse, body) {
|
|
var result;
|
|
if (body) {
|
|
if (typeof body == "string") {
|
|
try {
|
|
body = JSON.parse(body);
|
|
} catch (e) {
|
|
err = { error: "Malformed response", code: -1 };
|
|
}
|
|
}
|
|
if (!err) {
|
|
result = body.success;
|
|
err = body.error;
|
|
}
|
|
}
|
|
if (err) {
|
|
return res.error(err);
|
|
} else {
|
|
return res.success(result);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
export default HooksController;
|