github.com/jonathaningram/gophish@v0.3.1-0.20170829042651-ac3fe6aeae6c/static/js/src/app/campaigns.js (about) 1 // labels is a map of campaign statuses to 2 // CSS classes 3 var labels = { 4 "In progress": "label-primary", 5 "Queued": "label-info", 6 "Completed": "label-success", 7 "Emails Sent": "label-success", 8 "Error": "label-danger" 9 } 10 11 var campaigns = [] 12 var campaign = {} 13 14 // Launch attempts to POST to /campaigns/ 15 function launch() { 16 swal({ 17 title: "Are you sure?", 18 text: "This will schedule the campaign to be launched.", 19 type: "question", 20 animation: false, 21 showCancelButton: true, 22 confirmButtonText: "Launch", 23 confirmButtonColor: "#428bca", 24 reverseButtons: true, 25 allowOutsideClick: false, 26 showLoaderOnConfirm: true, 27 preConfirm: function () { 28 return new Promise(function (resolve, reject) { 29 groups = [] 30 $("#users").select2("data").forEach(function (group) { 31 groups.push({ name: group.text }); 32 }) 33 // Validate our fields 34 campaign = { 35 name: $("#name").val(), 36 template: { 37 name: $("#template").select2("data")[0].text 38 }, 39 url: $("#url").val(), 40 page: { 41 name: $("#page").select2("data")[0].text 42 }, 43 smtp: { 44 name: $("#profile").select2("data")[0].text 45 }, 46 launch_date: moment($("#launch_date").val(), "MM/DD/YYYY hh:mm a").utc().format(), 47 groups: groups 48 } 49 console.log("Launching campaign at time: " + campaign.launch_date) 50 // Submit the campaign 51 api.campaigns.post(campaign) 52 .success(function (data) { 53 resolve() 54 campaign = data 55 }) 56 .error(function (data) { 57 $("#modal\\.flashes").empty().append("<div style=\"text-align:center\" class=\"alert alert-danger\">\ 58 <i class=\"fa fa-exclamation-circle\"></i> " + data.responseJSON.message + "</div>") 59 swal.close() 60 }) 61 }) 62 } 63 }).then(function () { 64 swal( 65 'Campaign Scheduled!', 66 'This campaign has been scheduled for launch!', 67 'success' 68 ); 69 $('button:contains("OK")').on('click', function () { 70 window.location = "/campaigns/" + campaign.id.toString() 71 }) 72 }) 73 } 74 75 // Attempts to send a test email by POSTing to /campaigns/ 76 function sendTestEmail() { 77 var test_email_request = { 78 template: { 79 name: $("#template").select2("data")[0].text 80 }, 81 first_name: $("input[name=to_first_name]").val(), 82 last_name: $("input[name=to_last_name]").val(), 83 email: $("input[name=to_email]").val(), 84 position: $("input[name=to_position]").val(), 85 url: $("#url").val(), 86 page: { 87 name: $("#page").select2("data")[0].text 88 }, 89 smtp: { 90 name: $("#profile").select2("data")[0].text 91 } 92 } 93 btnHtml = $("#sendTestModalSubmit").html() 94 $("#sendTestModalSubmit").html('<i class="fa fa-spinner fa-spin"></i> Sending') 95 // Send the test email 96 api.send_test_email(test_email_request) 97 .success(function (data) { 98 $("#sendTestEmailModal\\.flashes").empty().append("<div style=\"text-align:center\" class=\"alert alert-success\">\ 99 <i class=\"fa fa-check-circle\"></i> Email Sent!</div>") 100 $("#sendTestModalSubmit").html(btnHtml) 101 }) 102 .error(function (data) { 103 $("#sendTestEmailModal\\.flashes").empty().append("<div style=\"text-align:center\" class=\"alert alert-danger\">\ 104 <i class=\"fa fa-exclamation-circle\"></i> " + data.responseJSON.message + "</div>") 105 $("#sendTestModalSubmit").html(btnHtml) 106 }) 107 } 108 109 function dismiss() { 110 $("#modal\\.flashes").empty(); 111 $("#name").val(""); 112 $("#template").val("").change(); 113 $("#page").val("").change(); 114 $("#url").val(""); 115 $("#profile").val("").change(); 116 $("#users").val("").change(); 117 $("#modal").modal('hide'); 118 } 119 120 function deleteCampaign(idx) { 121 swal({ 122 title: "Are you sure?", 123 text: "This will delete the campaign. This can't be undone!", 124 type: "warning", 125 animation: false, 126 showCancelButton: true, 127 confirmButtonText: "Delete " + campaigns[idx].name, 128 confirmButtonColor: "#428bca", 129 reverseButtons: true, 130 allowOutsideClick: false, 131 preConfirm: function () { 132 return new Promise(function (resolve, reject) { 133 api.campaignId.delete(campaigns[idx].id) 134 .success(function (msg) { 135 resolve() 136 }) 137 .error(function (data) { 138 reject(data.responseJSON.message) 139 }) 140 }) 141 } 142 }).then(function () { 143 swal( 144 'Campaign Deleted!', 145 'This campaign has been deleted!', 146 'success' 147 ); 148 $('button:contains("OK")').on('click', function () { 149 location.reload() 150 }) 151 }) 152 } 153 154 function setupOptions() { 155 api.groups.get() 156 .success(function (groups) { 157 if (groups.length == 0) { 158 modalError("No groups found!") 159 return false; 160 } else { 161 var group_s2 = $.map(groups, function (obj) { 162 obj.text = obj.name 163 return obj 164 }); 165 $("#users.form-control").select2({ 166 placeholder: "Select Groups", 167 data: group_s2, 168 }); 169 } 170 }); 171 api.templates.get() 172 .success(function (templates) { 173 if (templates.length == 0) { 174 modalError("No templates found!") 175 return false 176 } else { 177 var template_s2 = $.map(templates, function (obj) { 178 obj.text = obj.name 179 return obj 180 }); 181 $("#template.form-control").select2({ 182 placeholder: "Select a Template", 183 data: template_s2, 184 }); 185 } 186 }); 187 api.pages.get() 188 .success(function (pages) { 189 if (pages.length == 0) { 190 modalError("No pages found!") 191 return false 192 } else { 193 var page_s2 = $.map(pages, function (obj) { 194 obj.text = obj.name 195 return obj 196 }); 197 $("#page.form-control").select2({ 198 placeholder: "Select a Landing Page", 199 data: page_s2, 200 }); 201 } 202 }); 203 api.SMTP.get() 204 .success(function (profiles) { 205 if (profiles.length == 0) { 206 modalError("No profiles found!") 207 return false 208 } else { 209 var profile_s2 = $.map(profiles, function (obj) { 210 obj.text = obj.name 211 return obj 212 }); 213 $("#profile.form-control").select2({ 214 placeholder: "Select a Sending Profile", 215 data: profile_s2, 216 }); 217 } 218 }); 219 } 220 221 function edit(campaign) { 222 setupOptions(); 223 } 224 225 function copy(idx) { 226 setupOptions(); 227 // Set our initial values 228 api.campaignId.get(campaigns[idx].id) 229 .success(function (campaign) { 230 $("#name").val("Copy of " + campaign.name) 231 if (!campaign.template.id) { 232 $("#template").select2({ 233 placeholder: campaign.template.name 234 }); 235 } else { 236 $("#template").select2("val", campaign.template.id.toString()); 237 } 238 if (!campaign.page.id) { 239 $("#page").select2({ 240 placeholder: campaign.page.name 241 }); 242 } else { 243 $("#page").select2("val", campaign.page.id.toString()); 244 } 245 if (!campaign.smtp.id) { 246 $("#profile").select2({ 247 placeholder: campaign.smtp.name 248 }); 249 } else { 250 $("#profile").select2("val", campaign.smtp.id.toString()); 251 } 252 $("#url").val(campaign.url) 253 }) 254 .error(function (data) { 255 $("#modal\\.flashes").empty().append("<div style=\"text-align:center\" class=\"alert alert-danger\">\ 256 <i class=\"fa fa-exclamation-circle\"></i> " + data.responseJSON.message + "</div>") 257 }) 258 } 259 260 $(document).ready(function () { 261 $("#launch_date").datetimepicker({ 262 "widgetPositioning": { 263 "vertical": "bottom" 264 }, 265 "showTodayButton": true, 266 "defaultDate": moment() 267 }) 268 // Setup multiple modals 269 // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html 270 $('.modal').on('hidden.bs.modal', function (event) { 271 $(this).removeClass('fv-modal-stack'); 272 $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1); 273 }); 274 $('.modal').on('shown.bs.modal', function (event) { 275 // Keep track of the number of open modals 276 if (typeof ($('body').data('fv_open_modals')) == 'undefined') { 277 $('body').data('fv_open_modals', 0); 278 } 279 // if the z-index of this modal has been set, ignore. 280 if ($(this).hasClass('fv-modal-stack')) { 281 return; 282 } 283 $(this).addClass('fv-modal-stack'); 284 // Increment the number of open modals 285 $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1); 286 // Setup the appropriate z-index 287 $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals'))); 288 $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals'))); 289 $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack'); 290 }); 291 // Scrollbar fix - https://stackoverflow.com/questions/19305821/multiple-modals-overlay 292 $(document).on('hidden.bs.modal', '.modal', function () { 293 $('.modal:visible').length && $(document.body).addClass('modal-open'); 294 }); 295 $('#modal').on('hidden.bs.modal', function (event) { 296 dismiss() 297 }); 298 api.campaigns.summary() 299 .success(function (data) { 300 campaigns = data.campaigns 301 $("#loading").hide() 302 if (campaigns.length > 0) { 303 $("#campaignTable").show() 304 campaignTable = $("#campaignTable").DataTable({ 305 columnDefs: [{ 306 orderable: false, 307 targets: "no-sort" 308 }], 309 order: [ 310 [1, "desc"] 311 ] 312 }); 313 $.each(campaigns, function (i, campaign) { 314 console.log(campaign) 315 console.log(campaign.created_date) 316 label = labels[campaign.status] || "label-default"; 317 318 //section for tooltips on the status of a campaign to show some quick stats 319 var launchDate; 320 if (moment(campaign.launch_date).isAfter(moment())) { 321 launchDate = "Scheduled to start: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a') 322 var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total 323 } else { 324 launchDate = "Launch Date: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a') 325 var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total + "<br><br>" + "Emails opened: " + campaign.stats.opened + "<br><br>" + "Emails clicked: " + campaign.stats.clicked + "<br><br>" + "Submitted Credentials: " + campaign.stats.submitted_data + "<br><br>" + "Errors : " + campaign.stats.error 326 } 327 328 campaignTable.row.add([ 329 escapeHtml(campaign.name), 330 moment(campaign.created_date).format('MMMM Do YYYY, h:mm:ss a'), 331 "<span class=\"label " + label + "\" data-toggle=\"tooltip\" data-placement=\"right\" data-html=\"true\" title=\"" + quickStats + "\">" + campaign.status + "</span>", 332 "<div class='pull-right'><a class='btn btn-primary' href='/campaigns/" + campaign.id + "' data-toggle='tooltip' data-placement='left' title='View Results'>\ 333 <i class='fa fa-bar-chart'></i>\ 334 </a>\ 335 <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Campaign' onclick='copy(" + i + ")'>\ 336 <i class='fa fa-copy'></i>\ 337 </button></span>\ 338 <button class='btn btn-danger' onclick='deleteCampaign(" + i + ")' data-toggle='tooltip' data-placement='left' title='Delete Campaign'>\ 339 <i class='fa fa-trash-o'></i>\ 340 </button></div>" 341 ]).draw() 342 $('[data-toggle="tooltip"]').tooltip() 343 }) 344 } else { 345 $("#emptyMessage").show() 346 } 347 }) 348 .error(function () { 349 $("#loading").hide() 350 errorFlash("Error fetching campaigns") 351 }) 352 // Select2 Defaults 353 $.fn.select2.defaults.set("width", "100%"); 354 $.fn.select2.defaults.set("dropdownParent", $("#modal_body")); 355 $.fn.select2.defaults.set("theme", "bootstrap"); 356 })