blob: af2b0e8c5bfdae596d40581bc54f6e0ab75eb55b [file] [log] [blame]
const moment = require('moment');
const common = require('./lib/common');
const Database = require('./lib/Database');
function main(params) {
if (!params.triggerName) {
return common.sendError(400, 'no trigger name parameter was provided');
}
var triggerParts = common.parseQName(params.triggerName);
var triggerData = {
apikey: params.authKey,
name: triggerParts.name,
namespace: triggerParts.namespace,
additionalData: common.constructObject(params.additionalData),
};
var triggerID = `:${triggerParts.namespace}:${triggerParts.name}`;
var workers = params.workers instanceof Array ? params.workers : [];
var db;
if (params.__ow_method === "post") {
// check for parameter errors
if (!params.dbname) {
return common.sendError(400, 'cloudant trigger feed: missing dbname parameter');
}
if (!params.host) {
return common.sendError(400, 'cloudant trigger feed: missing host parameter');
}
if (!params.username) {
return common.sendError(400, 'cloudant trigger feed: missing username parameter');
}
if (!params.password) {
return common.sendError(400, 'cloudant trigger feed: missing password parameter');
}
var query_params;
if (params.filter) {
query_params = params.query_params;
if (typeof queryParams === 'string') {
try {
query_params = JSON.parse(params.query_params);
}
catch (e) {
return common.sendError(400, 'The query_params parameter cannot be parsed. Ensure it is valid JSON.');
}
}
if (query_params && typeof query_params !== 'object') {
return common.sendError(400, 'The query_params parameter is not a valid JSON Object');
}
}
else if (params.query_params) {
return common.sendError(400, 'The query_params parameter is only allowed if the filter parameter is defined');
}
var newTrigger = {
id: triggerID,
host: params.host,
port: params.port,
protocol: params.protocol || 'https',
dbname: params.dbname,
user: params.username,
pass: params.password,
apikey: triggerData.apikey,
since: params.since,
maxTriggers: params.maxTriggers || -1,
filter: params.filter,
query_params: query_params,
status: {
'active': true,
'dateChanged': Date.now()
},
additionalData: triggerData.additionalData
};
return new Promise(function (resolve, reject) {
common.verifyTriggerAuth(triggerData, false)
.then(() => {
db = new Database(params.DB_URL, params.DB_NAME);
return verifyUserDB(newTrigger);
})
.then(() => {
return db.getWorkerID(workers);
})
.then((worker) => {
console.log('trigger will be assigned to worker ' + worker);
newTrigger.worker = worker;
return db.createTrigger(triggerID, newTrigger);
})
.then(() => {
resolve({
statusCode: 200,
headers: {'Content-Type': 'application/json'},
body: {'status': 'success'}
});
})
.catch(err => {
reject(err);
});
});
}
else if (params.__ow_method === "get") {
return new Promise(function (resolve, reject) {
common.verifyTriggerAuth(triggerData, false)
.then(() => {
db = new Database(params.DB_URL, params.DB_NAME);
return db.getTrigger(triggerID);
})
.then(doc => {
var body = {
config: {
name: doc.id.split(':')[2],
namespace: doc.id.split(':')[1],
host: doc.host,
port: doc.port,
protocol: doc.protocol,
dbname: doc.dbname,
username: doc.user,
password: doc.pass,
since: doc.since,
filter: doc.filter,
query_params: doc.query_params,
},
status: {
active: doc.status.active,
dateChanged: moment(doc.status.dateChanged).utc().valueOf(),
dateChangedISO: moment(doc.status.dateChanged).utc().format(),
reason: doc.status.reason
}
};
resolve({
statusCode: 200,
headers: {'Content-Type': 'application/json'},
body: body
});
})
.catch(err => {
reject(err);
});
});
}
else if (params.__ow_method === "put") {
return new Promise(function (resolve, reject) {
var updatedParams = {};
common.verifyTriggerAuth(triggerData, false)
.then(() => {
db = new Database(params.DB_URL, params.DB_NAME);
return db.getTrigger(triggerID);
})
.then(trigger => {
if (trigger.status && trigger.status.active === false) {
return reject(common.sendError(400, `${params.triggerName} cannot be updated because it is disabled`));
}
if (params.filter || params.query_params) {
updatedParams.filter = trigger.filter;
updatedParams.query_params = trigger.query_params;
}
else {
return reject(common.sendError(400, 'At least one of filter or query_params parameters must be supplied'));
}
if (params.filter) {
updatedParams.filter = params.filter;
}
if (params.query_params) {
if (updatedParams.filter) {
var query_params = params.query_params;
if (typeof query_params === 'string') {
try {
query_params = JSON.parse(params.query_params);
}
catch (e) {
return reject(common.sendError(400, 'The query_params parameter cannot be parsed. Ensure it is valid JSON.'));
}
}
if (typeof query_params !== 'object') {
return reject(common.sendError(400, 'The query_params parameter is not a valid JSON Object'));
}
updatedParams.query_params = query_params;
}
else {
return reject(common.sendError(400, 'The query_params parameter is only allowed if the filter parameter is defined'));
}
}
return db.disableTrigger(triggerID, trigger, 0, 'updating');
})
.then(triggerID => {
return db.getTrigger(triggerID);
})
.then(trigger => {
return db.updateTrigger(triggerID, trigger, updatedParams, 0);
})
.then(() => {
resolve({
statusCode: 200,
headers: {'Content-Type': 'application/json'},
body: {'status': 'success'}
});
})
.catch(err => {
reject(err);
});
});
}
else if (params.__ow_method === "delete") {
return new Promise(function (resolve, reject) {
common.verifyTriggerAuth(triggerData, true)
.then(() => {
db = new Database(params.DB_URL, params.DB_NAME);
return db.getTrigger(triggerID);
})
.then(trigger => {
return db.disableTrigger(triggerID, trigger, 0, 'deleting');
})
.then(triggerID => {
return db.deleteTrigger(triggerID, 0);
})
.then(() => {
resolve({
statusCode: 200,
headers: {'Content-Type': 'application/json'},
body: {'status': 'success'}
});
})
.catch(err => {
reject(err);
});
});
}
else {
return common.sendError(400, 'unsupported lifecycleEvent');
}
}
function verifyUserDB(triggerObj) {
var dbURL = `${triggerObj.protocol}://${triggerObj.user}:${triggerObj.pass}@${triggerObj.host}`;
// add port if specified
if (triggerObj.port) {
dbURL += ':' + triggerObj.port;
}
return new Promise(function(resolve, reject) {
try {
var nanoConnection = require('nano')(dbURL);
var userDB = nanoConnection.use(triggerObj.dbname);
userDB.info(function(err, body) {
if (!err) {
resolve();
}
else {
reject(common.sendError(err.statusCode, 'error connecting to database ' + triggerObj.dbname, err.message));
}
});
}
catch(err) {
reject(common.sendError(400, 'error connecting to database ' + triggerObj.dbname, err.message));
}
});
}
exports.main = main;