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