| 1 |
let bulk_RestAPIMaxThreads = 1; |
| 2 |
let bulk_RestAPICurrentThreads = 0; |
| 3 |
let bulk_RestAPITotal = 0; |
| 4 |
let bulk_RestAPIFinished = 0; |
| 5 |
let bulk_RestAPITaskRunning = false; |
| 6 |
|
| 7 |
jQuery(function ($) { |
| 8 |
$('body').on('click', '.copy-to-clipboard', function () { |
| 9 |
$('#mainwp-api-key-copied-confirm-modal').modal('show'); |
| 10 |
}); |
| 11 |
// Trigger Manage Bulk Actions |
| 12 |
jQuery(document).on('click', '#mainwp-do-rest-api-bulk-actions', function () { |
| 13 |
let action = jQuery("#mainwp-rest-api-bulk-actions-menu").dropdown("get value"); |
| 14 |
if (action == 'delete' && !bulk_RestAPITaskRunning) { |
| 15 |
mainwp_restapi_bulk_remove_keys_confirm(); |
| 16 |
} |
| 17 |
return false; |
| 18 |
}); |
| 19 |
|
| 20 |
// Initialize Application Passwords functionality |
| 21 |
if ($("#rest-application-passwords-settings").length > 0) { |
| 22 |
init_application_passwords($); |
| 23 |
} |
| 24 |
}); |
| 25 |
|
| 26 |
let mainwp_restapi_remove_key_confirm = function (pCheckedBox) { |
| 27 |
let confirmMsg = MainWP.I18n.t("You are about to delete the selected REST API Key?"); |
| 28 |
mainwp_confirm(confirmMsg, function () { mainwp_restapi_bulk_remove_specific(pCheckedBox); }); |
| 29 |
} |
| 30 |
|
| 31 |
let mainwp_restapi_bulk_remove_keys_confirm = function () { |
| 32 |
let confirmMsg = MainWP.I18n.t("You are about to delete the selected REST API Key(s)?"); |
| 33 |
mainwp_confirm(confirmMsg, function () { mainwp_restapi_bulk_init(); mainwp_restapi_remove_keys_next(); }); |
| 34 |
} |
| 35 |
|
| 36 |
let mainwp_restapi_bulk_init = function () { |
| 37 |
jQuery('#mainwp-message-zone-apikeys').hide(); |
| 38 |
if (!bulk_RestAPITaskRunning) { |
| 39 |
bulk_RestAPICurrentThreads = 0; |
| 40 |
bulk_RestAPITotal = 0; |
| 41 |
bulk_RestAPIFinished = 0; |
| 42 |
jQuery('.mainwp-rest-api-body-table-manage .check-column INPUT:checkbox').each(function () { |
| 43 |
jQuery(this).attr('status', 'queue') |
| 44 |
}); |
| 45 |
} |
| 46 |
}; |
| 47 |
|
| 48 |
let mainwp_restapi_remove_keys_next = function () { |
| 49 |
while ((checkedBox = jQuery('.mainwp-rest-api-body-table-manage .check-column INPUT:checkbox:checked[status="queue"]:first')) && (checkedBox.length > 0) && (bulk_RestAPICurrentThreads < bulk_RestAPIMaxThreads)) { // NOSONAR - variables modified in other functions. |
| 50 |
mainwp_restapi_bulk_remove_specific(checkedBox); |
| 51 |
} |
| 52 |
if ((bulk_RestAPITotal > 0) && (bulk_RestAPIFinished == bulk_RestAPITotal)) { // NOSONAR - modified outside the function. |
| 53 |
setHtml('#mainwp-message-zone-apikeys', MainWP.I18n.t("Process completed. Reloading page...")); |
| 54 |
setTimeout(function () { |
| 55 |
mainwp_forceReload(); |
| 56 |
}, 3000); |
| 57 |
} |
| 58 |
} |
| 59 |
|
| 60 |
let mainwp_restapi_bulk_remove_specific = function (pCheckedBox) { |
| 61 |
pCheckedBox.attr('status', 'running'); |
| 62 |
let rowObj = pCheckedBox.closest('tr'); |
| 63 |
bulk_RestAPICurrentThreads++; |
| 64 |
|
| 65 |
let id = rowObj.attr('key-ck-id'); |
| 66 |
rowObj.html('<td colspan="999"><i class="notched circle loading icon"></i> ' + 'Deleting ...' + '</td>'); |
| 67 |
let data = mainwp_secure_data({ |
| 68 |
action: 'mainwp_rest_api_remove_keys', |
| 69 |
keyId: id, |
| 70 |
api_ver: rowObj.closest('tbody').attr('id') === 'mainwp-rest-api-v2-body-table' ? 'v2' : 'v1' |
| 71 |
}); |
| 72 |
|
| 73 |
jQuery.post(ajaxurl, data, function (response) { |
| 74 |
bulk_RestAPICurrentThreads--; |
| 75 |
bulk_RestAPIFinished++; |
| 76 |
rowObj.html('<td colspan="999"></td>'); |
| 77 |
let result = ''; |
| 78 |
let error = ''; |
| 79 |
if (response.error != undefined) { |
| 80 |
error = response.error; |
| 81 |
} else if (response.success == 'SUCCESS') { |
| 82 |
result = MainWP.I18n.t('The REST API Key has been deleted.'); |
| 83 |
} |
| 84 |
if (error != '') { |
| 85 |
rowObj.html('<td colspan="999"><i class="red times icon"></i>' + error + '</td>'); |
| 86 |
} else { |
| 87 |
rowObj.html('<td colspan="999"><i class="green check icon"></i>' + result + '</td>'); |
| 88 |
} |
| 89 |
setTimeout(function () { |
| 90 |
jQuery('tr[key-ck-id=' + id + ']').fadeOut(1000); |
| 91 |
}, 3000); |
| 92 |
|
| 93 |
mainwp_restapi_remove_keys_next(); |
| 94 |
}, |
| 95 |
"json" |
| 96 |
); |
| 97 |
}; |
| 98 |
|
| 99 |
/** |
| 100 |
* Application Passwords functionality |
| 101 |
*/ |
| 102 |
const init_application_passwords = ($) => { |
| 103 |
const app_pass_section = $("#rest-application-passwords-settings"); |
| 104 |
const create_modal = $("#mainwp-create-application-password-modal"); |
| 105 |
const success_modal = $("#mainwp-application-password-success-modal"); |
| 106 |
const app_pass_name_input = $("#mainwp-app-password-name-input"); |
| 107 |
const app_pass_tbody = $("#mainwp-application-password-table-body"); |
| 108 |
const edit_modal = $("#mainwp-edit-application-password-modal"); |
| 109 |
const edit_name_input = $("#mainwp-app-password-edit-name-input"); |
| 110 |
const edit_uuid_input = $("#mainwp-app-password-edit-uuid"); |
| 111 |
const edit_user_id_input = $("#mainwp-app-password-edit-user-id"); |
| 112 |
const has_user_col = $('#mainwp-application-password-table thead th.mainwp-col-user').length > 0; |
| 113 |
const current_user_name = $('#rest-application-passwords-settings').data('current-user-name') || ''; |
| 114 |
const message_zone = $("#mainwp-message-zone-app-passwords"); |
| 115 |
|
| 116 |
/** |
| 117 |
* Helper function to escape HTML |
| 118 |
*/ |
| 119 |
const escape_html = (text) => { |
| 120 |
const map = { |
| 121 |
"&": "&", |
| 122 |
"<": "<", |
| 123 |
">": ">", |
| 124 |
'"': """, |
| 125 |
"'": "'", |
| 126 |
}; |
| 127 |
return text.replace(/[&<>"']/g, (m) => map[m]); // NOSONAR ok. |
| 128 |
}; |
| 129 |
|
| 130 |
/** |
| 131 |
* Helper function to clear messages |
| 132 |
*/ |
| 133 |
const clear_messages = () => { |
| 134 |
message_zone.hide().html(""); |
| 135 |
}; |
| 136 |
|
| 137 |
/** |
| 138 |
* Helper function to show messages |
| 139 |
*/ |
| 140 |
const show_message = (message, type) => { |
| 141 |
clear_messages(); |
| 142 |
|
| 143 |
const class_name = type === "error" ? "red" : "green"; |
| 144 |
const html = `<div class="ui ${class_name} message"> |
| 145 |
<i class="close icon"></i> |
| 146 |
${message} |
| 147 |
</div>`; |
| 148 |
|
| 149 |
message_zone.html(html).show(); |
| 150 |
message_zone.find(".close.icon").on("click", () => { |
| 151 |
message_zone.fadeOut(); |
| 152 |
}); |
| 153 |
|
| 154 |
setTimeout(() => { |
| 155 |
message_zone.fadeOut(); |
| 156 |
}, 3000); |
| 157 |
}; |
| 158 |
|
| 159 |
/** |
| 160 |
* Helper function to format date like PHP format_timestamp |
| 161 |
* Format: "January 1, 2026 10:15 am" |
| 162 |
*/ |
| 163 |
const format_timestamp = (timestamp) => { |
| 164 |
const date = new Date(timestamp * 1000); |
| 165 |
|
| 166 |
// Get month name |
| 167 |
const month_names = [ |
| 168 |
"January", |
| 169 |
"February", |
| 170 |
"March", |
| 171 |
"April", |
| 172 |
"May", |
| 173 |
"June", |
| 174 |
"July", |
| 175 |
"August", |
| 176 |
"September", |
| 177 |
"October", |
| 178 |
"November", |
| 179 |
"December", |
| 180 |
]; |
| 181 |
const month = month_names[date.getMonth()]; |
| 182 |
|
| 183 |
// Get day, year |
| 184 |
const day = date.getDate(); |
| 185 |
const year = date.getFullYear(); |
| 186 |
|
| 187 |
// Get hours and minutes |
| 188 |
let hours = date.getHours(); |
| 189 |
const minutes = date.getMinutes().toString().padStart(2, "0"); |
| 190 |
const ampm = hours >= 12 ? "pm" : "am"; |
| 191 |
hours = hours % 12; |
| 192 |
hours = hours ? hours : 12; // NOSONAR - noopener - hours 0 should be 12. |
| 193 |
|
| 194 |
return `${month} ${day}, ${year} ${hours}:${minutes} ${ampm}`; |
| 195 |
}; |
| 196 |
|
| 197 |
/** |
| 198 |
* Helper function to add password row to table |
| 199 |
*/ |
| 200 |
const add_password_row = (item) => { |
| 201 |
const created_str = format_timestamp(item.created); |
| 202 |
const table_el = $('#mainwp-application-password-table'); |
| 203 |
// Get DataTable instance |
| 204 |
const table = window.mainwp_app_passwords_table; // NOSONAR - noopener - global variable. |
| 205 |
|
| 206 |
if (!table) { |
| 207 |
console.error("DataTable not initialized"); |
| 208 |
return; |
| 209 |
} |
| 210 |
|
| 211 |
// Check manage capability from table data attribute |
| 212 |
const can_manage_table = table_el.data('can-manage') == 1; |
| 213 |
const can_edit_table = table_el.data('can-edit') == 1; |
| 214 |
|
| 215 |
// Create row HTML with proper data-order attributes |
| 216 |
const row_html = `<tr data-uuid="${item.uuid}" data-user-id="${item.user_id || ''}"> |
| 217 |
<td class="check-column"> |
| 218 |
<div class="ui checkbox"> |
| 219 |
<input type="checkbox" value="${item.uuid}" name="" ${can_manage_table ? '' : 'disabled'} /> |
| 220 |
</div> |
| 221 |
</td> |
| 222 |
<td>${escape_html(item.name)}</td> |
| 223 |
${has_user_col ? `<td>${escape_html(current_user_name)}</td>` : ''} |
| 224 |
<td data-order="${item.created}">${created_str}</td> |
| 225 |
<td data-order="0">—</td> |
| 226 |
<td>—</td> |
| 227 |
<td class="right aligned"> |
| 228 |
${can_edit_table ? `<button type="button" class="ui mini basic button mainwp-edit-application-password" data-uuid="${item.uuid}" data-user-id="${item.user_id || ''}" data-name="${escape_html(item.name)}">${MainWP.I18n.t("Edit")}</button>` : ''} |
| 229 |
${can_manage_table ? `<button type="button" class="ui mini grey basic button mainwp-revoke-application-password" data-uuid="${item.uuid}">${MainWP.I18n.t("Revoke")}</button>` : ''} |
| 230 |
</td> |
| 231 |
</tr>`; |
| 232 |
|
| 233 |
// Add row using DataTables API with DOM node |
| 234 |
const row_node = table.row.add($(row_html)[0]).draw(false).node(); |
| 235 |
|
| 236 |
// Initialize Semantic UI checkbox |
| 237 |
$(row_node).find(".ui.checkbox").checkbox(); |
| 238 |
}; |
| 239 |
|
| 240 |
/** |
| 241 |
* Open edit modal |
| 242 |
*/ |
| 243 |
app_pass_tbody.on('click', '.mainwp-edit-application-password', (e) => { |
| 244 |
e.preventDefault(); |
| 245 |
const btn = $(e.currentTarget); |
| 246 |
const uuid = btn.data('uuid'); |
| 247 |
const user_id = btn.data('user-id'); |
| 248 |
const name = btn.data('name'); |
| 249 |
|
| 250 |
edit_uuid_input.val(uuid); |
| 251 |
edit_user_id_input.val(user_id); |
| 252 |
edit_name_input.val(name); |
| 253 |
|
| 254 |
edit_modal.modal('show'); |
| 255 |
}); |
| 256 |
|
| 257 |
/** |
| 258 |
* Submit edit application password |
| 259 |
*/ |
| 260 |
$('#mainwp-edit-app-password-submit').on('click', (e) => { |
| 261 |
e.preventDefault(); |
| 262 |
const uuid = edit_uuid_input.val(); |
| 263 |
const user_id = edit_user_id_input.val(); |
| 264 |
const name = (edit_name_input.val() || '').trim(); |
| 265 |
if (!name) { |
| 266 |
edit_name_input.trigger('focus'); |
| 267 |
show_message(MainWP.I18n.t('Please enter an application name.'), 'error'); |
| 268 |
return false; |
| 269 |
} |
| 270 |
|
| 271 |
const data = mainwp_secure_data({ |
| 272 |
action: 'mainwp_application_password_update', |
| 273 |
uuid: uuid, |
| 274 |
user_id: user_id, |
| 275 |
name: name, |
| 276 |
}); |
| 277 |
|
| 278 |
$.post(ajaxurl, data, (resp) => { // NOSONAR - noopener - complex. |
| 279 |
if (resp?.success) { |
| 280 |
try { |
| 281 |
const table = window.mainwp_app_passwords_table; // NOSONAR - noopener - global variable. |
| 282 |
const tr = $('#mainwp-application-password-table tbody tr[data-uuid="' + uuid + '"]'); |
| 283 |
if (tr.length) { |
| 284 |
// Update name cell |
| 285 |
const name_cell = tr.find('td').eq(1); |
| 286 |
name_cell.text(name); |
| 287 |
// Update buttons aria/data |
| 288 |
const edit_btn = tr.find('.mainwp-edit-application-password'); |
| 289 |
if (edit_btn.length) { |
| 290 |
edit_btn.attr('data-name', name); |
| 291 |
edit_btn.attr('aria-label', MainWP.I18n.t('Rename "%s"').replace('%s', name)); |
| 292 |
} |
| 293 |
const revoke_btn = tr.find('.mainwp-revoke-application-password'); |
| 294 |
if (revoke_btn.length) { |
| 295 |
revoke_btn.attr('aria-label', MainWP.I18n.t('Revoke "%s"').replace('%s', name)); |
| 296 |
} |
| 297 |
if (table) { |
| 298 |
table.row(tr).invalidate().draw(false); |
| 299 |
} |
| 300 |
} |
| 301 |
show_message(MainWP.I18n.t('Application password updated successfully.'), 'success'); |
| 302 |
edit_modal.modal('hide'); |
| 303 |
} catch { |
| 304 |
mainwp_forceReload(); |
| 305 |
} |
| 306 |
} else { |
| 307 |
const msg = (resp?.data?.message) ?? MainWP.I18n.t('Failed to update Application Password.'); |
| 308 |
show_message(msg, 'error'); |
| 309 |
} |
| 310 |
}, 'json'); |
| 311 |
}); |
| 312 |
|
| 313 |
/** |
| 314 |
* Helper function to revoke multiple passwords |
| 315 |
*/ |
| 316 |
const revoke_multiple_passwords = (items) => { |
| 317 |
const data = mainwp_secure_data({ |
| 318 |
action: "mainwp_application_password_delete_multiple", |
| 319 |
items: items, |
| 320 |
}); |
| 321 |
|
| 322 |
$.post( |
| 323 |
ajaxurl, |
| 324 |
data, |
| 325 |
(response) => { |
| 326 |
if (response.success) { |
| 327 |
const table = window.mainwp_app_passwords_table; // NOSONAR - noopener - global variable. |
| 328 |
|
| 329 |
if (table) { |
| 330 |
// Remove all selected rows using DataTables API |
| 331 |
items.forEach((it) => { |
| 332 |
const row = table.row(`[data-uuid="${it.uuid}"]`); |
| 333 |
if (row.length) { |
| 334 |
row.remove(); |
| 335 |
} |
| 336 |
}); |
| 337 |
|
| 338 |
// Redraw table |
| 339 |
table.draw(false); |
| 340 |
} |
| 341 |
|
| 342 |
show_message( |
| 343 |
MainWP.I18n.t("Selected application passwords have been revoked."), |
| 344 |
"success" |
| 345 |
); |
| 346 |
} else { |
| 347 |
show_message( |
| 348 |
response.data.message || MainWP.I18n.t("An error occurred."), |
| 349 |
"error" |
| 350 |
); |
| 351 |
} |
| 352 |
}, |
| 353 |
"json" |
| 354 |
).fail(() => { |
| 355 |
show_message( |
| 356 |
MainWP.I18n.t( |
| 357 |
"An error occurred while revoking the application passwords." |
| 358 |
), |
| 359 |
"error" |
| 360 |
); |
| 361 |
}); |
| 362 |
}; |
| 363 |
|
| 364 |
/** |
| 365 |
* Open create modal |
| 366 |
*/ |
| 367 |
$("#mainwp-create-application-password-button-top, #mainwp-create-application-password-button").on("click", () => { |
| 368 |
app_pass_name_input.val(""); |
| 369 |
const submit_btn = $("#mainwp-create-app-password-submit"); |
| 370 |
submit_btn.addClass("disabled"); |
| 371 |
|
| 372 |
app_pass_name_input.off("input.create_modal").on("input.create_modal", () => { |
| 373 |
if (app_pass_name_input.val().trim().length > 0) { |
| 374 |
submit_btn.removeClass("disabled"); |
| 375 |
} else { |
| 376 |
submit_btn.addClass("disabled"); |
| 377 |
} |
| 378 |
}); |
| 379 |
|
| 380 |
create_modal |
| 381 |
.modal({ |
| 382 |
onApprove: () => { // NOSONAR - noopener - prevent close. |
| 383 |
const name = app_pass_name_input.val().trim(); |
| 384 |
|
| 385 |
if (name.length === 0) { |
| 386 |
app_pass_name_input.trigger("focus"); |
| 387 |
show_message( |
| 388 |
MainWP.I18n.t("Please enter an application name."), |
| 389 |
"error" |
| 390 |
); |
| 391 |
return false; |
| 392 |
} |
| 393 |
|
| 394 |
create_application_password(name); |
| 395 |
return false; // Prevent modal from closing |
| 396 |
}, |
| 397 |
}) |
| 398 |
.modal("show"); |
| 399 |
}); |
| 400 |
|
| 401 |
/** |
| 402 |
* Create new application password |
| 403 |
*/ |
| 404 |
const create_application_password = (name) => { |
| 405 |
clear_messages(); |
| 406 |
|
| 407 |
const submit_button = $("#mainwp-create-app-password-submit"); |
| 408 |
submit_button.addClass("loading disabled"); |
| 409 |
|
| 410 |
const data = mainwp_secure_data({ |
| 411 |
action: "mainwp_application_password_create", |
| 412 |
name: name, |
| 413 |
}); |
| 414 |
|
| 415 |
$.post( |
| 416 |
ajaxurl, |
| 417 |
data, |
| 418 |
(response) => { |
| 419 |
submit_button.removeClass("loading disabled"); |
| 420 |
|
| 421 |
if (response.success) { |
| 422 |
// Close create modal |
| 423 |
create_modal.modal("hide"); |
| 424 |
|
| 425 |
// Show success modal with password |
| 426 |
$("#app-pass-success-name").text(response.data.item.name); |
| 427 |
$("#app-pass-success-value").val(response.data.password); |
| 428 |
|
| 429 |
success_modal |
| 430 |
.modal({ |
| 431 |
closable: false, |
| 432 |
onHidden: () => { |
| 433 |
location.reload(); |
| 434 |
}, |
| 435 |
}) |
| 436 |
.modal("show"); |
| 437 |
|
| 438 |
show_message( |
| 439 |
MainWP.I18n.t("Application password created successfully!"), |
| 440 |
"success" |
| 441 |
); |
| 442 |
} else { |
| 443 |
create_modal.modal("hide"); |
| 444 |
show_message( |
| 445 |
response.data.message || MainWP.I18n.t("An error occurred."), |
| 446 |
"error" |
| 447 |
); |
| 448 |
} |
| 449 |
}, |
| 450 |
"json" |
| 451 |
).fail(() => { |
| 452 |
submit_button.removeClass("loading disabled"); |
| 453 |
create_modal.modal("hide"); |
| 454 |
show_message( |
| 455 |
MainWP.I18n.t( |
| 456 |
"An error occurred while creating the application password." |
| 457 |
), |
| 458 |
"error" |
| 459 |
); |
| 460 |
}); |
| 461 |
}; |
| 462 |
|
| 463 |
/** |
| 464 |
* Copy password to clipboard |
| 465 |
*/ |
| 466 |
$(document).on("click", ".copy-app-password", function () { |
| 467 |
const input = $("#app-pass-success-value"); |
| 468 |
const value = input.val(); |
| 469 |
|
| 470 |
if (navigator.clipboard && globalThis.isSecureContext) { |
| 471 |
navigator.clipboard.writeText(value); |
| 472 |
} |
| 473 |
|
| 474 |
const button = $(this); |
| 475 |
const original_text = button.html(); |
| 476 |
button.html('<i class="check icon"></i> ' + MainWP.I18n.t("Copied!")); |
| 477 |
|
| 478 |
setTimeout(() => { |
| 479 |
button.html(original_text); |
| 480 |
}, 2000); |
| 481 |
}); |
| 482 |
|
| 483 |
/** |
| 484 |
* Revoke single application password |
| 485 |
*/ |
| 486 |
app_pass_tbody.on("click", ".mainwp-revoke-application-password", (e) => { |
| 487 |
e.preventDefault(); |
| 488 |
|
| 489 |
if ( |
| 490 |
!confirm( |
| 491 |
MainWP.I18n.t( |
| 492 |
"Are you sure you want to revoke this password? This action cannot be undone." |
| 493 |
) |
| 494 |
) |
| 495 |
) { |
| 496 |
return; |
| 497 |
} |
| 498 |
|
| 499 |
const button = $(e.currentTarget); |
| 500 |
const tr = button.closest("tr"); |
| 501 |
const uuid = button.data("uuid"); |
| 502 |
const user_id = button.data("user-id") || button.closest('tr').data('user-id') || ''; |
| 503 |
|
| 504 |
clear_messages(); |
| 505 |
button.prop("disabled", true).addClass("disabled loading"); |
| 506 |
|
| 507 |
const data = mainwp_secure_data({ |
| 508 |
action: "mainwp_application_password_delete", |
| 509 |
uuid: uuid, |
| 510 |
user_id: user_id, |
| 511 |
}); |
| 512 |
|
| 513 |
$.post( |
| 514 |
ajaxurl, |
| 515 |
data, |
| 516 |
(response) => { |
| 517 |
button.prop("disabled", false).removeClass("disabled loading"); |
| 518 |
|
| 519 |
if (response.success) { |
| 520 |
const table = window.mainwp_app_passwords_table; // NOSONAR - noopener - global variable. |
| 521 |
|
| 522 |
if (table) { |
| 523 |
// Remove row using DataTables API |
| 524 |
table.row(tr).remove().draw(false); |
| 525 |
} else { |
| 526 |
// Fallback to direct DOM manipulation |
| 527 |
tr.fadeOut(300, function () { |
| 528 |
tr.remove(); |
| 529 |
}); |
| 530 |
} |
| 531 |
|
| 532 |
show_message( |
| 533 |
MainWP.I18n.t("Application password revoked successfully."), |
| 534 |
"success" |
| 535 |
); |
| 536 |
} else { |
| 537 |
show_message( |
| 538 |
response.data.message || MainWP.I18n.t("An error occurred."), |
| 539 |
"error" |
| 540 |
); |
| 541 |
} |
| 542 |
}, |
| 543 |
"json" |
| 544 |
).fail(() => { |
| 545 |
button.prop("disabled", false).removeClass("disabled loading"); |
| 546 |
show_message( |
| 547 |
MainWP.I18n.t( |
| 548 |
"An error occurred while revoking the application password." |
| 549 |
), |
| 550 |
"error" |
| 551 |
); |
| 552 |
}); |
| 553 |
}); |
| 554 |
|
| 555 |
/** |
| 556 |
* Select checkboxes and disable/enable bulk actions |
| 557 |
*/ |
| 558 |
$('.mainwp-application-password-checkbox').on('change', function () { |
| 559 |
const all_checked = $('.mainwp-application-password-checkbox').is(':checked'); |
| 560 |
if (all_checked > 0) { |
| 561 |
$("#mainwp-do-application-passwords-bulk-actions").removeClass('disabled'); |
| 562 |
} else { |
| 563 |
$("#mainwp-do-application-passwords-bulk-actions").addClass('disabled'); |
| 564 |
} |
| 565 |
}); |
| 566 |
|
| 567 |
/** |
| 568 |
* Bulk actions |
| 569 |
*/ |
| 570 |
$("#mainwp-do-application-passwords-bulk-actions").on("click", (e) => { |
| 571 |
const selected = []; |
| 572 |
app_pass_tbody |
| 573 |
.find('.check-column input[type="checkbox"]:checked') |
| 574 |
.each(function () { |
| 575 |
const uuid = $(this).val(); |
| 576 |
const user_id = $(this).data('user-id') || $(this).closest('tr').data('user-id') || ''; |
| 577 |
if (uuid) { |
| 578 |
selected.push({ uuid: uuid, user_id: user_id }); |
| 579 |
} |
| 580 |
}); |
| 581 |
|
| 582 |
if (selected.length === 0) { |
| 583 |
show_message( |
| 584 |
MainWP.I18n.t("Please select at least one application password."), |
| 585 |
"error" |
| 586 |
); |
| 587 |
return false; |
| 588 |
} |
| 589 |
|
| 590 |
if ( |
| 591 |
!confirm( |
| 592 |
MainWP.I18n.t( |
| 593 |
"Are you sure you want to revoke the selected passwords? This action cannot be undone." |
| 594 |
) |
| 595 |
) |
| 596 |
) { |
| 597 |
return false; |
| 598 |
} |
| 599 |
|
| 600 |
revoke_multiple_passwords(selected); |
| 601 |
e.preventDefault(); |
| 602 |
e.stopPropagation(); |
| 603 |
return true; |
| 604 |
}); |
| 605 |
|
| 606 |
/** |
| 607 |
* Close new password notice |
| 608 |
*/ |
| 609 |
app_pass_section.on( |
| 610 |
"click", |
| 611 |
".new-application-password-notice .close.icon", |
| 612 |
function () { |
| 613 |
$(this).closest(".new-application-password-notice").fadeOut(); |
| 614 |
} |
| 615 |
); |
| 616 |
|
| 617 |
/** |
| 618 |
* Enter key on name field |
| 619 |
*/ |
| 620 |
app_pass_name_input.on("keypress", (e) => { |
| 621 |
if (e.which === 13) { |
| 622 |
e.preventDefault(); |
| 623 |
create_button.trigger("click"); |
| 624 |
} |
| 625 |
}); |
| 626 |
}; |
| 627 |
|
| 628 |
/** |
| 629 |
* Initialize REST API Permission Chips |
| 630 |
*/ |
| 631 |
jQuery(document).ready(function($) { // NOSONAR - complex. |
| 632 |
let initPermissionChips = function() { |
| 633 |
$('.mainwp-rest-api-permission-chips').each(function() { |
| 634 |
let container = $(this); |
| 635 |
let hiddenInput = container.find('input[type="hidden"]'); |
| 636 |
let chips = container.find('.mainwp-permission-chip:visible'); |
| 637 |
let initValue = container.data('init-value') || ''; |
| 638 |
|
| 639 |
let updateHiddenInput = function() { |
| 640 |
let selectedPermissions = []; |
| 641 |
container.find('.mainwp-permission-chip:visible').each(function() { // NOSONAR - levels deep. |
| 642 |
if ($(this).hasClass('active')) { |
| 643 |
let perms = $(this).data('permission').toString().split(','); |
| 644 |
perms.forEach(function(p) { |
| 645 |
if (p && !selectedPermissions.includes(p)) { |
| 646 |
selectedPermissions.push(p); |
| 647 |
} |
| 648 |
}); |
| 649 |
} |
| 650 |
}); |
| 651 |
hiddenInput.val(selectedPermissions.join(',')); |
| 652 |
hiddenInput.trigger('change'); |
| 653 |
}; |
| 654 |
|
| 655 |
let initPermissions = new Set( |
| 656 |
initValue |
| 657 |
.split(',') |
| 658 |
.filter(function (p) { return p !== ''; }) |
| 659 |
); |
| 660 |
|
| 661 |
chips.each(function() { |
| 662 |
let chip = $(this); |
| 663 |
let chipPerms = chip.data('permission').toString().split(','); |
| 664 |
let isActive = false; |
| 665 |
|
| 666 |
chipPerms.forEach(function(perm) { |
| 667 |
if (initPermissions.has(perm)) { |
| 668 |
isActive = true; |
| 669 |
} |
| 670 |
}); |
| 671 |
|
| 672 |
if (isActive) { |
| 673 |
chip.addClass('active green'); |
| 674 |
} else { |
| 675 |
chip.addClass('inactive grey'); |
| 676 |
} |
| 677 |
}); |
| 678 |
|
| 679 |
updateHiddenInput(); |
| 680 |
|
| 681 |
chips.off('click.permission-chip').on('click.permission-chip', function(e) { |
| 682 |
e.preventDefault(); |
| 683 |
let chip = $(this); |
| 684 |
|
| 685 |
if (chip.hasClass('active')) { |
| 686 |
chip.removeClass('active green').addClass('inactive grey'); |
| 687 |
} else { |
| 688 |
chip.removeClass('inactive grey').addClass('active green'); |
| 689 |
} |
| 690 |
|
| 691 |
updateHiddenInput(); |
| 692 |
}); |
| 693 |
}); |
| 694 |
}; |
| 695 |
|
| 696 |
initPermissionChips(); |
| 697 |
|
| 698 |
$('#mainwp_rest_api_keys_compatible_v1').on('change', function() { |
| 699 |
let isV1 = $(this).is(':checked'); |
| 700 |
let container = $('.mainwp-rest-api-permission-chips[data-api-version]'); |
| 701 |
|
| 702 |
if (isV1) { |
| 703 |
container.attr('data-api-version', 'v1'); |
| 704 |
container.find('.mainwp-v2-chip').hide(); |
| 705 |
container.find('.mainwp-v1-chip').show(); |
| 706 |
} else { |
| 707 |
container.attr('data-api-version', 'v2'); |
| 708 |
container.find('.mainwp-v1-chip').hide(); |
| 709 |
container.find('.mainwp-v2-chip').show(); |
| 710 |
} |
| 711 |
|
| 712 |
container.find('.mainwp-permission-chip').removeClass('active'); |
| 713 |
initPermissionChips(); |
| 714 |
}); |
| 715 |
|
| 716 |
let updateBulkActionsState = function() { |
| 717 |
let checkedCount = $('.mainwp-rest-api-body-table-manage .check-column INPUT:checkbox:checked').length; |
| 718 |
let dropdown = $('#mainwp-rest-api-bulk-actions-menu'); |
| 719 |
let applyButton = $('#mainwp-do-rest-api-bulk-actions'); |
| 720 |
|
| 721 |
if (checkedCount > 0) { |
| 722 |
dropdown.removeClass('disabled'); |
| 723 |
applyButton.removeClass('disabled'); |
| 724 |
} else { |
| 725 |
dropdown.addClass('disabled'); |
| 726 |
dropdown.dropdown('clear'); |
| 727 |
applyButton.addClass('disabled'); |
| 728 |
} |
| 729 |
}; |
| 730 |
|
| 731 |
updateBulkActionsState(); |
| 732 |
|
| 733 |
$(document).on('change', '.mainwp-rest-api-body-table-manage .check-column INPUT:checkbox', function() { |
| 734 |
updateBulkActionsState(); |
| 735 |
}); |
| 736 |
}); |
| 737 |
|