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  })