[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 (function () { 2 'use strict'; 3 4 /** 5 * @package Joomla.Plugin 6 * @subpackage System.webauthn 7 * 8 * @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org> 9 * @license GNU General Public License version 2 or later; see LICENSE.txt 10 */ 11 window.Joomla = window.Joomla || {}; 12 13 (function (Joomla, document) { 14 /** 15 * Converts a simple object containing query string parameters to a single, escaped query string. 16 * This method is a necessary evil since Joomla.request can only accept data as a string. 17 * 18 * @param object {object} A plain object containing the query parameters to pass 19 * @param prefix {string} Prefix for array-type parameters 20 * 21 * @returns {string} 22 */ 23 var interpolateParameters = function interpolateParameters(object, prefix) { 24 if (prefix === void 0) { 25 prefix = ''; 26 } 27 28 var encodedString = ''; 29 Object.keys(object).forEach(function (prop) { 30 if (typeof object[prop] !== 'object') { 31 if (encodedString.length > 0) { 32 encodedString += '&'; 33 } 34 35 if (prefix === '') { 36 encodedString += encodeURIComponent(prop) + "=" + encodeURIComponent(object[prop]); 37 } else { 38 encodedString += encodeURIComponent(prefix) + "[" + encodeURIComponent(prop) + "]=" + encodeURIComponent(object[prop]); 39 } 40 41 return; 42 } // Objects need special handling 43 44 45 encodedString += "" + interpolateParameters(object[prop], prop); 46 }); 47 return encodedString; 48 }; 49 /** 50 * A simple error handler 51 * 52 * @param {String} message 53 */ 54 55 56 var handleCreationError = function handleCreationError(message) { 57 Joomla.renderMessages({ 58 error: [message] 59 }); 60 }; 61 /** 62 * Ask the user to link an authenticator using the provided public key (created server-side). 63 * Posts the credentials to the URL defined in post_url using AJAX. 64 * That URL must re-render the management interface. 65 * These contents will replace the element identified by the interface_selector CSS selector. 66 */ 67 // eslint-disable-next-line no-unused-vars 68 69 70 Joomla.plgSystemWebauthnInitCreateCredentials = function () { 71 // Make sure the browser supports Webauthn 72 if (!('credentials' in navigator)) { 73 Joomla.renderMessages({ 74 error: [Joomla.Text._('PLG_SYSTEM_WEBAUTHN_ERR_NO_BROWSER_SUPPORT')] 75 }); 76 return; 77 } // Get the public key creation options through AJAX. 78 79 80 var paths = Joomla.getOptions('system.paths'); 81 var postURL = "" + (paths ? paths.base + "/index.php" : window.location.pathname); 82 var postBackData = { 83 option: 'com_ajax', 84 group: 'system', 85 plugin: 'webauthn', 86 format: 'json', 87 akaction: 'initcreate', 88 encoding: 'json' 89 }; 90 postBackData[Joomla.getOptions('csrf.token')] = 1; 91 Joomla.request({ 92 url: postURL, 93 method: 'POST', 94 data: interpolateParameters(postBackData), 95 onSuccess: function onSuccess(response) { 96 try { 97 var publicKey = JSON.parse(response); 98 Joomla.plgSystemWebauthnCreateCredentials(publicKey); 99 } catch (exception) { 100 handleCreationError(Joomla.Text._('PLG_SYSTEM_WEBAUTHN_ERR_XHR_INITCREATE')); 101 } 102 }, 103 onError: function onError(xhr) { 104 handleCreationError(xhr.status + " " + xhr.statusText); 105 } 106 }); 107 }; 108 109 Joomla.plgSystemWebauthnCreateCredentials = function (publicKey) { 110 var paths = Joomla.getOptions('system.paths'); 111 var postURL = "" + (paths ? paths.base + "/index.php" : window.location.pathname); 112 113 var arrayToBase64String = function arrayToBase64String(a) { 114 return btoa(String.fromCharCode.apply(String, a)); 115 }; 116 117 var base64url2base64 = function base64url2base64(input) { 118 var output = input.replace(/-/g, '+').replace(/_/g, '/'); 119 var pad = output.length % 4; 120 121 if (pad) { 122 if (pad === 1) { 123 throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); 124 } 125 126 output += new Array(5 - pad).join('='); 127 } 128 129 return output; 130 }; // Convert the public key information to a format usable by the browser's credentials manager 131 132 133 publicKey.challenge = Uint8Array.from(window.atob(base64url2base64(publicKey.challenge)), function (c) { 134 return c.charCodeAt(0); 135 }); 136 publicKey.user.id = Uint8Array.from(window.atob(publicKey.user.id), function (c) { 137 return c.charCodeAt(0); 138 }); 139 140 if (publicKey.excludeCredentials) { 141 publicKey.excludeCredentials = publicKey.excludeCredentials.map(function (data) { 142 data.id = Uint8Array.from(window.atob(base64url2base64(data.id)), function (c) { 143 return c.charCodeAt(0); 144 }); 145 return data; 146 }); 147 } // Ask the browser to prompt the user for their authenticator 148 149 150 navigator.credentials.create({ 151 publicKey: publicKey 152 }).then(function (data) { 153 var publicKeyCredential = { 154 id: data.id, 155 type: data.type, 156 rawId: arrayToBase64String(new Uint8Array(data.rawId)), 157 response: { 158 clientDataJSON: arrayToBase64String(new Uint8Array(data.response.clientDataJSON)), 159 attestationObject: arrayToBase64String(new Uint8Array(data.response.attestationObject)) 160 } 161 }; // Send the response to your server 162 163 var postBackData = { 164 option: 'com_ajax', 165 group: 'system', 166 plugin: 'webauthn', 167 format: 'raw', 168 akaction: 'create', 169 encoding: 'raw', 170 data: btoa(JSON.stringify(publicKeyCredential)) 171 }; 172 postBackData[Joomla.getOptions('csrf.token')] = 1; 173 Joomla.request({ 174 url: postURL, 175 method: 'POST', 176 data: interpolateParameters(postBackData), 177 onSuccess: function onSuccess(responseHTML) { 178 var elements = document.querySelectorAll('#plg_system_webauthn-management-interface'); 179 180 if (!elements) { 181 return; 182 } 183 184 var elContainer = elements[0]; 185 elContainer.outerHTML = responseHTML; 186 Joomla.plgSystemWebauthnInitialize(); 187 Joomla.plgSystemWebauthnReactivateTooltips(); 188 }, 189 onError: function onError(xhr) { 190 handleCreationError(xhr.status + " " + xhr.statusText); 191 } 192 }); 193 }).catch(function (error) { 194 // An error occurred: timeout, request to provide the authenticator refused, hardware / 195 // software error... 196 handleCreationError(error); 197 }); 198 }; 199 /** 200 * Edit label button 201 * 202 * @param {Element} that The button being clicked 203 * @param {String} storeID CSS ID for the element storing the configuration in its data 204 * properties 205 */ 206 // eslint-disable-next-line no-unused-vars 207 208 209 Joomla.plgSystemWebauthnEditLabel = function (that) { 210 var paths = Joomla.getOptions('system.paths'); 211 var postURL = "" + (paths ? paths.base + "/index.php" : window.location.pathname); // Find the UI elements 212 213 var elTR = that.parentElement.parentElement; 214 var credentialId = elTR.dataset.credential_id; 215 var elTDs = elTR.querySelectorAll('.webauthnManagementCell'); 216 var elLabelTD = elTDs[0]; 217 var elButtonsTD = elTDs[1]; 218 var elButtons = elButtonsTD.querySelectorAll('button'); 219 var elEdit = elButtons[0]; 220 var elDelete = elButtons[1]; // Show the editor 221 222 var oldLabel = elLabelTD.innerText; 223 var elContainer = document.createElement('div'); 224 elContainer.className = 'webauthnManagementEditorRow d-flex gap-2'; 225 var elInput = document.createElement('input'); 226 elInput.type = 'text'; 227 elInput.name = 'label'; 228 elInput.defaultValue = oldLabel; 229 elInput.className = 'form-control'; 230 var elSave = document.createElement('button'); 231 elSave.className = 'btn btn-success btn-sm'; 232 elSave.innerText = Joomla.Text._('PLG_SYSTEM_WEBAUTHN_MANAGE_BTN_SAVE_LABEL'); 233 elSave.addEventListener('click', function () { 234 var elNewLabel = elInput.value; 235 236 if (elNewLabel !== '') { 237 var postBackData = { 238 option: 'com_ajax', 239 group: 'system', 240 plugin: 'webauthn', 241 format: 'json', 242 encoding: 'json', 243 akaction: 'savelabel', 244 credential_id: credentialId, 245 new_label: elNewLabel 246 }; 247 postBackData[Joomla.getOptions('csrf.token')] = 1; 248 Joomla.request({ 249 url: postURL, 250 method: 'POST', 251 data: interpolateParameters(postBackData), 252 onSuccess: function onSuccess(rawResponse) { 253 var result = false; 254 255 try { 256 result = JSON.parse(rawResponse); 257 } catch (exception) { 258 result = rawResponse === 'true'; 259 } 260 261 if (result !== true) { 262 handleCreationError(Joomla.Text._('PLG_SYSTEM_WEBAUTHN_ERR_LABEL_NOT_SAVED')); 263 } 264 }, 265 onError: function onError(xhr) { 266 handleCreationError(Joomla.Text._('PLG_SYSTEM_WEBAUTHN_ERR_LABEL_NOT_SAVED') + " -- " + xhr.status + " " + xhr.statusText); 267 } 268 }); 269 } 270 271 elLabelTD.innerText = elNewLabel; 272 elEdit.disabled = false; 273 elDelete.disabled = false; 274 return false; 275 }, false); 276 var elCancel = document.createElement('button'); 277 elCancel.className = 'btn btn-danger btn-sm'; 278 elCancel.innerText = Joomla.Text._('PLG_SYSTEM_WEBAUTHN_MANAGE_BTN_CANCEL_LABEL'); 279 elCancel.addEventListener('click', function () { 280 elLabelTD.innerText = oldLabel; 281 elEdit.disabled = false; 282 elDelete.disabled = false; 283 return false; 284 }, false); 285 elLabelTD.innerHTML = ''; 286 elContainer.appendChild(elInput); 287 elContainer.appendChild(elSave); 288 elContainer.appendChild(elCancel); 289 elLabelTD.appendChild(elContainer); 290 elEdit.disabled = true; 291 elDelete.disabled = true; 292 return false; 293 }; 294 /** 295 * Delete button 296 * 297 * @param {Element} that The button being clicked 298 */ 299 // eslint-disable-next-line no-unused-vars 300 301 302 Joomla.plgSystemWebauthnDelete = function (that) { 303 if (!window.confirm(Joomla.Text._('JGLOBAL_CONFIRM_DELETE'))) { 304 return false; 305 } 306 307 var paths = Joomla.getOptions('system.paths'); 308 var postURL = "" + (paths ? paths.base + "/index.php" : window.location.pathname); // Find the UI elements 309 310 var elTR = that.parentElement.parentElement; 311 var credentialId = elTR.dataset.credential_id; 312 var elTDs = elTR.querySelectorAll('.webauthnManagementCell'); 313 var elButtonsTD = elTDs[1]; 314 var elButtons = elButtonsTD.querySelectorAll('button'); 315 var elEdit = elButtons[0]; 316 var elDelete = elButtons[1]; 317 elEdit.disabled = true; 318 elDelete.disabled = true; // Delete the record 319 320 var postBackData = { 321 option: 'com_ajax', 322 group: 'system', 323 plugin: 'webauthn', 324 format: 'json', 325 encoding: 'json', 326 akaction: 'delete', 327 credential_id: credentialId 328 }; 329 postBackData[Joomla.getOptions('csrf.token')] = 1; 330 Joomla.request({ 331 url: postURL, 332 method: 'POST', 333 data: interpolateParameters(postBackData), 334 onSuccess: function onSuccess(rawResponse) { 335 var result = false; 336 337 try { 338 result = JSON.parse(rawResponse); 339 } catch (e) { 340 result = rawResponse === 'true'; 341 } 342 343 if (result !== true) { 344 handleCreationError(Joomla.Text._('PLG_SYSTEM_WEBAUTHN_ERR_NOT_DELETED')); 345 return; 346 } 347 348 elTR.parentElement.removeChild(elTR); 349 }, 350 onError: function onError(xhr) { 351 elEdit.disabled = false; 352 elDelete.disabled = false; 353 handleCreationError(Joomla.Text._('PLG_SYSTEM_WEBAUTHN_ERR_NOT_DELETED') + " -- " + xhr.status + " " + xhr.statusText); 354 } 355 }); 356 return false; 357 }; 358 359 Joomla.plgSystemWebauthnReactivateTooltips = function () { 360 var tooltips = Joomla.getOptions('bootstrap.tooltip'); 361 362 if (typeof tooltips === 'object' && tooltips !== null) { 363 Object.keys(tooltips).forEach(function (tooltip) { 364 var opt = tooltips[tooltip]; 365 var options = { 366 animation: opt.animation ? opt.animation : true, 367 container: opt.container ? opt.container : false, 368 delay: opt.delay ? opt.delay : 0, 369 html: opt.html ? opt.html : false, 370 selector: opt.selector ? opt.selector : false, 371 trigger: opt.trigger ? opt.trigger : 'hover focus', 372 fallbackPlacement: opt.fallbackPlacement ? opt.fallbackPlacement : null, 373 boundary: opt.boundary ? opt.boundary : 'clippingParents', 374 title: opt.title ? opt.title : '', 375 customClass: opt.customClass ? opt.customClass : '', 376 sanitize: opt.sanitize ? opt.sanitize : true, 377 sanitizeFn: opt.sanitizeFn ? opt.sanitizeFn : null, 378 popperConfig: opt.popperConfig ? opt.popperConfig : null 379 }; 380 381 if (opt.placement) { 382 options.placement = opt.placement; 383 } 384 385 if (opt.template) { 386 options.template = opt.template; 387 } 388 389 if (opt.allowList) { 390 options.allowList = opt.allowList; 391 } 392 393 var elements = Array.from(document.querySelectorAll(tooltip)); 394 395 if (elements.length) { 396 elements.map(function (el) { 397 return new window.bootstrap.Tooltip(el, options); 398 }); 399 } 400 }); 401 } 402 }; 403 /** 404 * Add New Authenticator button click handler 405 * 406 * @param {MouseEvent} event The mouse click event 407 * 408 * @returns {boolean} Returns false to prevent the default browser button behavior 409 */ 410 411 412 Joomla.plgSystemWebauthnAddOnClick = function (event) { 413 event.preventDefault(); 414 Joomla.plgSystemWebauthnInitCreateCredentials(); 415 return false; 416 }; 417 /** 418 * Edit Name button click handler 419 * 420 * @param {MouseEvent} event The mouse click event 421 * 422 * @returns {boolean} Returns false to prevent the default browser button behavior 423 */ 424 425 426 Joomla.plgSystemWebauthnEditOnClick = function (event) { 427 event.preventDefault(); 428 Joomla.plgSystemWebauthnEditLabel(event.currentTarget); 429 return false; 430 }; 431 /** 432 * Remove button click handler 433 * 434 * @param {MouseEvent} event The mouse click event 435 * 436 * @returns {boolean} Returns false to prevent the default browser button behavior 437 */ 438 439 440 Joomla.plgSystemWebauthnDeleteOnClick = function (event) { 441 event.preventDefault(); 442 Joomla.plgSystemWebauthnDelete(event.currentTarget); 443 return false; 444 }; 445 /** 446 * Initialization on page load. 447 */ 448 449 450 Joomla.plgSystemWebauthnInitialize = function () { 451 var addButton = document.getElementById('plg_system_webauthn-manage-add'); 452 453 if (addButton) { 454 addButton.addEventListener('click', Joomla.plgSystemWebauthnAddOnClick); 455 } 456 457 var editLabelButtons = [].slice.call(document.querySelectorAll('.plg_system_webauthn-manage-edit')); 458 459 if (editLabelButtons.length) { 460 editLabelButtons.forEach(function (button) { 461 button.addEventListener('click', Joomla.plgSystemWebauthnEditOnClick); 462 }); 463 } 464 465 var deleteButtons = [].slice.call(document.querySelectorAll('.plg_system_webauthn-manage-delete')); 466 467 if (deleteButtons.length) { 468 deleteButtons.forEach(function (button) { 469 button.addEventListener('click', Joomla.plgSystemWebauthnDeleteOnClick); 470 }); 471 } 472 }; // Initialization. Runs on DOM content loaded since this script is always loaded deferred. 473 474 475 Joomla.plgSystemWebauthnInitialize(); 476 })(Joomla, document); 477 478 })();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |