var db = require('ep_etherpad-lite/node/db/DB').db, fs = require("fs"), async = require('../../src/node_modules/async'), settings = require('../../src/node/utils/Settings'); // Remove cache for this procedure db['dbSettings'].cache = 0; exports.registerRoute = function (hook_name, args, callback) { // Catching (un)subscribe addresses args.app.get('/p/*/(un){0,1}subscribe=*', function(req, res) { var fullURL = req.protocol + "://" + req.get('host') + req.url; var path=req.url.split("/"); var padId=path[2]; var param = path[3].split("="); var action = param[0]; var actionId = param[1]; var padURL = req.protocol + "://" + req.get('host') + "/p/" +padId; async.waterfall( [ function(cb) { // Is the (un)subscription valid (exists & not older than 24h) db.get("emailSubscription:"+padId, function(err, userIds){ var foundInDb = false; var timeDiffGood = false; var email = "your email"; var resultDb = { "foundInDb": foundInDb, "timeDiffGood": timeDiffGood, "email": email } if(userIds && userIds['pending']){ async.forEach(Object.keys(userIds['pending']), function(user){ var userInfo = userIds['pending'][user]; // If we have Id int the Db, then we are good ot really unsubscribe the user if(userInfo[action + 'Id'] == actionId){ console.debug("emailSubscription:", user, "found in DB:", userInfo); foundInDb = true; email = user; // Checking if the demand is not older than 24h var timeDiff = new Date().getTime() - userInfo.timestamp; timeDiffGood = timeDiff < 1000 * 60 * 60 * 24; if(action == 'subscribe' && timeDiffGood == true) { // Subscription process setAuthorEmail( userInfo, user ); setAuthorEmailRegistered( userIds, userInfo, user, padId ); } else if (action == 'unsubscribe' && timeDiffGood == true) { // Unsubscription process unsetAuthorEmail( userInfo, user ); unsetAuthorEmailRegistered( userIds, user, padId ); } resultDb = { "foundInDb": foundInDb, "timeDiffGood": timeDiffGood, "email": user } } }, function(err, msg){ if (err != null) { console.error("Error in async.forEach", err, " -> ", msg); } }); // end async for each } cb(null, resultDb); }); }, function(resultDb, cb) { // Create and send the output message sendContent(res, args, action, padId, padURL, resultDb); cb(null, resultDb); }, function(resultDb, cb) { // Take a moment to clean all obsolete pending data cleanPendingData(padId); cb(null, resultDb); } ], function(err, results){ if (err != null) { console.error("Callback async.series: Err -> ", err, " / results -> ", results); } } ); }); callback(); // Am I even called? } /** * Database manipulation */ // Updates the database with the email record setAuthorEmail = function (userInfo, email){ db.setSub("globalAuthor:" + userInfo.authorId, ["email"], email); } // Write email and padId to the database setAuthorEmailRegistered = function(userIds, userInfo, email, padId){ console.debug("setAuthorEmailRegistered: Initial userIds:", userIds); var timestamp = new Date().getTime(); var registered = { authorId: userInfo.authorId, onStart: userInfo.onStart, onEnd: userInfo.onEnd, timestamp: timestamp }; // add the registered values to the object userIds[email] = registered; // remove the pending data delete userIds['pending'][email]; // Write the modified datas back in the Db console.warn("written to database"); db.set("emailSubscription:" + padId, userIds); // stick it in the database console.debug("setAuthorEmailRegistered: Modified userIds:", userIds); } // Updates the database by removing the email record for that AuthorId unsetAuthorEmail = function (userInfo, email){ db.get("globalAuthor:" + userInfo.authorId, function(err, value){ // get the current value if (value['email'] == email) { // Remove the email option from the datas delete value['email']; // Write the modified datas back in the Db db.set("globalAuthor:" + userInfo.authorId, value); } }); } // Remove email, options and padId from the database unsetAuthorEmailRegistered = function(userIds, email, padId){ console.debug("unsetAuthorEmailRegistered: initial userIds:", userIds); // remove the registered options from the object delete userIds[email]; // remove the pending data delete userIds['pending'][email]; // Write the modified datas back in the Db console.warn("written to database"); db.set("emailSubscription:" + padId, userIds); console.debug("unsetAuthorEmailRegistered: modified userIds:", userIds); } /** * We take a moment to remove too old pending (un)subscription */ cleanPendingData = function (padId) { var modifiedData, areDataModified = false; db.get("emailSubscription:" + padId, function(err, userIds){ // get the current value console.debug("cleanPendingData: Initial userIds:", userIds); modifiedData = userIds; if(userIds && userIds['pending']){ async.forEach(Object.keys(userIds['pending']), function(user){ var timeDiff = new Date().getTime() - userIds['pending'][user].timestamp; var timeDiffGood = timeDiff < 1000 * 60 * 60 * 24; if(timeDiffGood == false) { delete modifiedData['pending'][user]; areDataModified = true; } }); } if (areDataModified == true) { // Write the modified datas back in the Db db.set("emailSubscription:" + padId, modifiedData); } console.debug("cleanPendingData: Modified userIds:", modifiedData, " / areDataModified:", areDataModified); }); } /** * Create html output with the status of the process */ function sendContent(res, args, action, padId, padURL, resultDb) { console.debug("starting sendContent: args ->", action, " / ", padId, " / ", padURL, " / ", resultDb); if (action == 'subscribe') { var actionMsg = "Subscribing '" + resultDb.email + "' to pad " + padId; } else { var actionMsg = "Unsubscribing '" + resultDb.email + "' from pad " + padId; } var msgCause, resultMsg, classResult; if (resultDb.foundInDb == true && resultDb.timeDiffGood == true) { // Pending data were found un Db and updated -> good resultMsg = "Success"; classResult = "validationGood"; if (action == 'subscribe') { msgCause = "You will receive email when someone changes this pad."; } else { msgCause = "You won't receive anymore email when someone changes this pad."; } } else if (resultDb.foundInDb == true) { // Pending data were found but older than a day -> fail resultMsg = "Too late!"; classResult = "validationBad"; msgCause = "You have max 24h to click the link in your confirmation email."; } else { // Pending data weren't found in Db -> fail resultMsg = "Fail"; classResult = "validationBad"; msgCause = "We couldn't find any pending " + (action == 'subscribe'?'subscription':'unsubscription') + "
in our system with this Id.
Maybe you wait more than 24h before validating"; } args.content = fs.readFileSync(__dirname + "/templates/response.ejs", 'utf-8'); args.content = args.content .replace(/\<%action%\>/, actionMsg) .replace(/\<%classResult%\>/, classResult) .replace(/\<%result%\>/, resultMsg) .replace(/\<%explanation%\>/, msgCause) .replace(/\<%padUrl%\>/g, padURL); res.contentType("text/html; charset=utf-8"); res.send(args.content); // Send it to the requester*/ }