diff --git a/lib/unhangout-routes.js b/lib/unhangout-routes.js index 4ff59c9a..d4dd74d0 100644 --- a/lib/unhangout-routes.js +++ b/lib/unhangout-routes.js @@ -7,7 +7,8 @@ var _ = require("underscore"), googleapis = require('googleapis'), moment = require("moment-timezone"), mandrill = require("mandrill-api"), - async = require("async"); + async = require("async"), + util = require("util"); var ensureAuthenticated = utils.ensureAuthenticated; @@ -972,6 +973,32 @@ module.exports = { event.logAnalytics({action: "stop", user: req.user}); }); + app.post("/admin/event/:id/delete", utils.ensureSuperuser, function(req, res) { + var event = db.events.get(req.params.id); + var connectedUsers = event.get("connectedUsers"); + var title = event.get("title"); + if (connectedUsers.length > 0) { + req.flash("danger", util.format("Cannot delete event %s: users still connected: %d", title, connectedUsers.length)); + } + else { + var sessions = event.get('sessions'); + // Using the .each() method won't work here, as detailed at + // http://stackoverflow.com/questions/10858935/cleanest-way-to-destroy-every-model-in-a-collection-in-backbone + var session; + var count = 0; + while (session = sessions.first()) { + session.destroy(); + count++; + event.logAnalytics({action: "delete-session", user: req.user, session: req.params.id}); + } + // This clears the event from users admin caches. + event.set("admins", {}); + event.logAnalytics({action: "delete-event", user: req.user, event: event.id}); + event.destroy(); + req.flash("success", util.format("Event %s and %d related sessions deleted.", title, count)); + } + res.redirect("/admin/"); + }); app.get("/hangout/gadget.xml", function(req, res) { var context = { diff --git a/lib/unhangout-server.js b/lib/unhangout-server.js index 45521a3c..0dd5fa17 100644 --- a/lib/unhangout-server.js +++ b/lib/unhangout-server.js @@ -25,7 +25,8 @@ var logging = require('./logging'), moment = require('moment-timezone'), fs = require('fs'), memwatch = require("memwatch"), - slashes = require("connect-slashes"); + slashes = require("connect-slashes"), + flash = require("flash"); // This is the primary class that represents the UnhangoutServer. // I organize the server pieces into a class so we can more easily @@ -199,6 +200,7 @@ exports.UnhangoutServer.prototype = { store: redisSessionStore, cookie: {maxAge:1000*60*60*24*2} })); + this.app.use(flash()); if (this.options.mockAuth) { var mockPassport = require("./passport-mock"); diff --git a/package.json b/package.json index 7b710ab8..c0e82fed 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "deep-copy": "^1.0.0", "ejs": "1.0.0", "express": "3.5.1", + "flash": "1.1.0", "gapitoken": "0.1.3", "googleapis": "0.7.0", "mandrill-api": "1.0.41", diff --git a/public/js/admin.js b/public/js/admin.js index e7de31d9..ee648c8f 100644 --- a/public/js/admin.js +++ b/public/js/admin.js @@ -1,4 +1,9 @@ require(["jquery", "bootstrap", "auth"], function($) { $("[rel=popover]").popover({container: "body", placement: "left"}); $("[title]").not("[rel=popover]").tooltip({container: "body"}); + $(".delete-event").click(function(event) { + var id = $(this).attr("data-event"); + var deleteEvent = confirm("Are you sure you want to delete event " + id + " and all associated sessions? This cannot be undone."); + return deleteEvent; + }); }); diff --git a/views/admin.ejs b/views/admin.ejs index 0083b649..fbbfca75 100644 --- a/views/admin.ejs +++ b/views/admin.ejs @@ -3,6 +3,16 @@ <% var sessions; %>