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