github.com/lunarobliq/gophish@v0.8.1-0.20230523153303-93511002234d/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 $("#groupModalLabel").text("New Group"); 68 var group = {} 69 } else { 70 $("#groupModalLabel").text("Edit Group"); 71 api.groupId.get(id) 72 .success(function (group) { 73 $("#name").val(group.name) 74 targetRows = [] 75 $.each(group.targets, function (i, record) { 76 targetRows.push([ 77 escapeHtml(record.first_name), 78 escapeHtml(record.last_name), 79 escapeHtml(record.email), 80 escapeHtml(record.position), 81 '<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>' 82 ]) 83 }); 84 targets.DataTable().rows.add(targetRows).draw() 85 }) 86 .error(function () { 87 errorFlash("Error fetching group") 88 }) 89 } 90 // Handle file uploads 91 $("#csvupload").fileupload({ 92 url: "/api/import/group", 93 dataType: "json", 94 beforeSend: function (xhr) { 95 xhr.setRequestHeader('Authorization', 'Bearer ' + user.api_key); 96 }, 97 add: function (e, data) { 98 $("#modal\\.flashes").empty() 99 var acceptFileTypes = /(csv|txt)$/i; 100 var filename = data.originalFiles[0]['name'] 101 if (filename && !acceptFileTypes.test(filename.split(".").pop())) { 102 modalError("Unsupported file extension (use .csv or .txt)") 103 return false; 104 } 105 data.submit(); 106 }, 107 done: function (e, data) { 108 $.each(data.result, function (i, record) { 109 addTarget( 110 record.first_name, 111 record.last_name, 112 record.email, 113 record.position); 114 }); 115 targets.DataTable().draw(); 116 } 117 }) 118 } 119 120 var downloadCSVTemplate = function () { 121 var csvScope = [{ 122 'First Name': 'Example', 123 'Last Name': 'User', 124 'Email': 'foobar@example.com', 125 'Position': 'Systems Administrator' 126 }] 127 var filename = 'group_template.csv' 128 var csvString = Papa.unparse(csvScope, {}) 129 var csvData = new Blob([csvString], { 130 type: 'text/csv;charset=utf-8;' 131 }); 132 if (navigator.msSaveBlob) { 133 navigator.msSaveBlob(csvData, filename); 134 } else { 135 var csvURL = window.URL.createObjectURL(csvData); 136 var dlLink = document.createElement('a'); 137 dlLink.href = csvURL; 138 dlLink.setAttribute('download', filename) 139 document.body.appendChild(dlLink) 140 dlLink.click(); 141 document.body.removeChild(dlLink) 142 } 143 } 144 145 146 var deleteGroup = function (id) { 147 var group = groups.find(function (x) { 148 return x.id === id 149 }) 150 if (!group) { 151 return 152 } 153 Swal.fire({ 154 title: "Are you sure?", 155 text: "This will delete the group. This can't be undone!", 156 type: "warning", 157 animation: false, 158 showCancelButton: true, 159 confirmButtonText: "Delete " + escapeHtml(group.name), 160 confirmButtonColor: "#428bca", 161 reverseButtons: true, 162 allowOutsideClick: false, 163 preConfirm: function () { 164 return new Promise(function (resolve, reject) { 165 api.groupId.delete(id) 166 .success(function (msg) { 167 resolve() 168 }) 169 .error(function (data) { 170 reject(data.responseJSON.message) 171 }) 172 }) 173 } 174 }).then(function (result) { 175 if (result.value){ 176 Swal.fire( 177 'Group Deleted!', 178 'This group has been deleted!', 179 'success' 180 ); 181 } 182 $('button:contains("OK")').on('click', function () { 183 location.reload() 184 }) 185 }) 186 } 187 188 function addTarget(firstNameInput, lastNameInput, emailInput, positionInput) { 189 // Create new data row. 190 var email = escapeHtml(emailInput).toLowerCase(); 191 var newRow = [ 192 escapeHtml(firstNameInput), 193 escapeHtml(lastNameInput), 194 email, 195 escapeHtml(positionInput), 196 '<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>' 197 ]; 198 199 // Check table to see if email already exists. 200 var targetsTable = targets.DataTable(); 201 var existingRowIndex = targetsTable 202 .column(2, { 203 order: "index" 204 }) // Email column has index of 2 205 .data() 206 .indexOf(email); 207 // Update or add new row as necessary. 208 if (existingRowIndex >= 0) { 209 targetsTable 210 .row(existingRowIndex, { 211 order: "index" 212 }) 213 .data(newRow); 214 } else { 215 targetsTable.row.add(newRow); 216 } 217 } 218 219 function load() { 220 $("#groupTable").hide() 221 $("#emptyMessage").hide() 222 $("#loading").show() 223 api.groups.summary() 224 .success(function (response) { 225 $("#loading").hide() 226 if (response.total > 0) { 227 groups = response.groups 228 $("#emptyMessage").hide() 229 $("#groupTable").show() 230 var groupTable = $("#groupTable").DataTable({ 231 destroy: true, 232 columnDefs: [{ 233 orderable: false, 234 targets: "no-sort" 235 }] 236 }); 237 groupTable.clear(); 238 groupRows = [] 239 $.each(groups, function (i, group) { 240 groupRows.push([ 241 escapeHtml(group.name), 242 escapeHtml(group.num_targets), 243 moment(group.modified_date).format('MMMM Do YYYY, h:mm:ss a'), 244 "<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-backdrop='static' data-target='#modal' onclick='edit(" + group.id + ")'>\ 245 <i class='fa fa-pencil'></i>\ 246 </button>\ 247 <button class='btn btn-danger' onclick='deleteGroup(" + group.id + ")'>\ 248 <i class='fa fa-trash-o'></i>\ 249 </button></div>" 250 ]) 251 }) 252 groupTable.rows.add(groupRows).draw() 253 } else { 254 $("#emptyMessage").show() 255 } 256 }) 257 .error(function () { 258 errorFlash("Error fetching groups") 259 }) 260 } 261 262 $(document).ready(function () { 263 load() 264 // Setup the event listeners 265 // Handle manual additions 266 $("#targetForm").submit(function () { 267 // Validate the form data 268 var targetForm = document.getElementById("targetForm") 269 if (!targetForm.checkValidity()) { 270 targetForm.reportValidity() 271 return 272 } 273 addTarget( 274 $("#firstName").val(), 275 $("#lastName").val(), 276 $("#email").val(), 277 $("#position").val()); 278 targets.DataTable().draw(); 279 280 // Reset user input. 281 $("#targetForm>div>input").val(''); 282 $("#firstName").focus(); 283 return false; 284 }); 285 // Handle Deletion 286 $("#targetsTable").on("click", "span>i.fa-trash-o", function () { 287 targets.DataTable() 288 .row($(this).parents('tr')) 289 .remove() 290 .draw(); 291 }); 292 $("#modal").on("hide.bs.modal", function () { 293 dismiss(); 294 }); 295 $("#csv-template").click(downloadCSVTemplate) 296 });