github.com/glennzw/gophish@v0.8.1-0.20190824020715-24fe998a3aa0/static/js/src/app/groups.js (about) 1 var groups = [] 2 3 // Save attempts to POST or PUT to /groups/ 4 function save(id) { 5 var targets = [] 6 $.each($("#targetsTable").DataTable().rows().data(), function (i, target) { 7 targets.push({ 8 first_name: unescapeHtml(target[0]), 9 last_name: unescapeHtml(target[1]), 10 email: unescapeHtml(target[2]), 11 position: unescapeHtml(target[3]) 12 }) 13 }) 14 var group = { 15 name: $("#name").val(), 16 targets: targets 17 } 18 // Submit the group 19 if (id != -1) { 20 // If we're just editing an existing group, 21 // we need to PUT /groups/:id 22 group.id = id 23 api.groupId.put(group) 24 .success(function (data) { 25 successFlash("Group updated successfully!") 26 load() 27 dismiss() 28 $("#modal").modal('hide') 29 }) 30 .error(function (data) { 31 modalError(data.responseJSON.message) 32 }) 33 } else { 34 // Else, if this is a new group, POST it 35 // to /groups 36 api.groups.post(group) 37 .success(function (data) { 38 successFlash("Group added successfully!") 39 load() 40 dismiss() 41 $("#modal").modal('hide') 42 }) 43 .error(function (data) { 44 modalError(data.responseJSON.message) 45 }) 46 } 47 } 48 49 function dismiss() { 50 $("#targetsTable").dataTable().DataTable().clear().draw() 51 $("#name").val("") 52 $("#modal\\.flashes").empty() 53 } 54 55 function edit(id) { 56 targets = $("#targetsTable").dataTable({ 57 destroy: true, // Destroy any other instantiated table - http://datatables.net/manual/tech-notes/3#destroy 58 columnDefs: [{ 59 orderable: false, 60 targets: "no-sort" 61 }] 62 }) 63 $("#modalSubmit").unbind('click').click(function () { 64 save(id) 65 }) 66 if (id == -1) { 67 var group = {} 68 } else { 69 api.groupId.get(id) 70 .success(function (group) { 71 $("#name").val(group.name) 72 $.each(group.targets, function (i, record) { 73 targets.DataTable() 74 .row.add([ 75 escapeHtml(record.first_name), 76 escapeHtml(record.last_name), 77 escapeHtml(record.email), 78 escapeHtml(record.position), 79 '<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>' 80 ]).draw() 81 }); 82 83 }) 84 .error(function () { 85 errorFlash("Error fetching group") 86 }) 87 } 88 // Handle file uploads 89 $("#csvupload").fileupload({ 90 url: "/api/import/group", 91 dataType: "json", 92 beforeSend: function (xhr) { 93 xhr.setRequestHeader('Authorization', 'Bearer ' + user.api_key); 94 }, 95 add: function (e, data) { 96 $("#modal\\.flashes").empty() 97 var acceptFileTypes = /(csv|txt)$/i; 98 var filename = data.originalFiles[0]['name'] 99 if (filename && !acceptFileTypes.test(filename.split(".").pop())) { 100 modalError("Unsupported file extension (use .csv or .txt)") 101 return false; 102 } 103 data.submit(); 104 }, 105 done: function (e, data) { 106 $.each(data.result, function (i, record) { 107 addTarget( 108 record.first_name, 109 record.last_name, 110 record.email, 111 record.position); 112 }); 113 targets.DataTable().draw(); 114 } 115 }) 116 } 117 118 var downloadCSVTemplate = function () { 119 var csvScope = [{ 120 'First Name': 'Example', 121 'Last Name': 'User', 122 'Email': 'foobar@example.com', 123 'Position': 'Systems Administrator' 124 }] 125 var filename = 'group_template.csv' 126 var csvString = Papa.unparse(csvScope, {}) 127 var csvData = new Blob([csvString], { 128 type: 'text/csv;charset=utf-8;' 129 }); 130 if (navigator.msSaveBlob) { 131 navigator.msSaveBlob(csvData, filename); 132 } else { 133 var csvURL = window.URL.createObjectURL(csvData); 134 var dlLink = document.createElement('a'); 135 dlLink.href = csvURL; 136 dlLink.setAttribute('download', filename) 137 document.body.appendChild(dlLink) 138 dlLink.click(); 139 document.body.removeChild(dlLink) 140 } 141 } 142 143 144 var deleteGroup = function (id) { 145 var group = groups.find(function (x) { 146 return x.id === id 147 }) 148 if (!group) { 149 return 150 } 151 swal({ 152 title: "Are you sure?", 153 text: "This will delete the group. This can't be undone!", 154 type: "warning", 155 animation: false, 156 showCancelButton: true, 157 confirmButtonText: "Delete " + escapeHtml(group.name), 158 confirmButtonColor: "#428bca", 159 reverseButtons: true, 160 allowOutsideClick: false, 161 preConfirm: function () { 162 return new Promise(function (resolve, reject) { 163 api.groupId.delete(id) 164 .success(function (msg) { 165 resolve() 166 }) 167 .error(function (data) { 168 reject(data.responseJSON.message) 169 }) 170 }) 171 } 172 }).then(function () { 173 swal( 174 'Group Deleted!', 175 'This group has been deleted!', 176 'success' 177 ); 178 $('button:contains("OK")').on('click', function () { 179 location.reload() 180 }) 181 }) 182 } 183 184 function addTarget(firstNameInput, lastNameInput, emailInput, positionInput) { 185 // Create new data row. 186 var email = escapeHtml(emailInput).toLowerCase(); 187 var newRow = [ 188 escapeHtml(firstNameInput), 189 escapeHtml(lastNameInput), 190 email, 191 escapeHtml(positionInput), 192 '<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>' 193 ]; 194 195 // Check table to see if email already exists. 196 var targetsTable = targets.DataTable(); 197 var existingRowIndex = targetsTable 198 .column(2, { 199 order: "index" 200 }) // Email column has index of 2 201 .data() 202 .indexOf(email); 203 // Update or add new row as necessary. 204 if (existingRowIndex >= 0) { 205 targetsTable 206 .row(existingRowIndex, { 207 order: "index" 208 }) 209 .data(newRow); 210 } else { 211 targetsTable.row.add(newRow); 212 } 213 } 214 215 function load() { 216 $("#groupTable").hide() 217 $("#emptyMessage").hide() 218 $("#loading").show() 219 api.groups.summary() 220 .success(function (response) { 221 $("#loading").hide() 222 if (response.total > 0) { 223 groups = response.groups 224 $("#emptyMessage").hide() 225 $("#groupTable").show() 226 var groupTable = $("#groupTable").DataTable({ 227 destroy: true, 228 columnDefs: [{ 229 orderable: false, 230 targets: "no-sort" 231 }] 232 }); 233 groupTable.clear(); 234 $.each(groups, function (i, group) { 235 groupTable.row.add([ 236 escapeHtml(group.name), 237 escapeHtml(group.num_targets), 238 moment(group.modified_date).format('MMMM Do YYYY, h:mm:ss a'), 239 "<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-backdrop='static' data-target='#modal' onclick='edit(" + group.id + ")'>\ 240 <i class='fa fa-pencil'></i>\ 241 </button>\ 242 <button class='btn btn-danger' onclick='deleteGroup(" + group.id + ")'>\ 243 <i class='fa fa-trash-o'></i>\ 244 </button></div>" 245 ]).draw() 246 }) 247 } else { 248 $("#emptyMessage").show() 249 } 250 }) 251 .error(function () { 252 errorFlash("Error fetching groups") 253 }) 254 } 255 256 $(document).ready(function () { 257 load() 258 // Setup the event listeners 259 // Handle manual additions 260 $("#targetForm").submit(function () { 261 // Validate the form data 262 var targetForm = document.getElementById("targetForm") 263 if (!targetForm.checkValidity()) { 264 targetForm.reportValidity() 265 return 266 } 267 addTarget( 268 $("#firstName").val(), 269 $("#lastName").val(), 270 $("#email").val(), 271 $("#position").val()); 272 targets.DataTable().draw(); 273 274 // Reset user input. 275 $("#targetForm>div>input").val(''); 276 $("#firstName").focus(); 277 return false; 278 }); 279 // Handle Deletion 280 $("#targetsTable").on("click", "span>i.fa-trash-o", function () { 281 targets.DataTable() 282 .row($(this).parents('tr')) 283 .remove() 284 .draw(); 285 }); 286 $("#modal").on("hide.bs.modal", function () { 287 dismiss(); 288 }); 289 $("#csv-template").click(downloadCSVTemplate) 290 });