@everymatrix/player-step-up-auth 1.76.6 → 1.76.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{player-step-up-auth-80ad5fa5.js → player-step-up-auth-d5d44be3.js} +85 -65
- package/dist/cjs/player-step-up-auth.cjs.entry.js +1 -1
- package/dist/cjs/player-step-up-auth.cjs.js +1 -1
- package/dist/collection/components/player-step-up-auth/player-step-up-auth.js +87 -66
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{player-step-up-auth-045726cf.js → player-step-up-auth-e624c40c.js} +85 -65
- package/dist/esm/player-step-up-auth.entry.js +1 -1
- package/dist/esm/player-step-up-auth.js +1 -1
- package/dist/player-step-up-auth/index.esm.js +1 -1
- package/dist/player-step-up-auth/{player-step-up-auth-045726cf.js → player-step-up-auth-e624c40c.js} +1 -1
- package/dist/player-step-up-auth/player-step-up-auth.entry.js +1 -1
- package/dist/player-step-up-auth/player-step-up-auth.esm.js +1 -1
- package/dist/types/Users/adrian.pripon/Documents/Work/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.d.ts +2 -0
- package/dist/types/Users/adrian.pripon/Documents/Work/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.dev.d.ts +2 -0
- package/dist/types/components/player-step-up-auth/player-step-up-auth.d.ts +14 -11
- package/package.json +1 -1
- package/dist/types/builds/emfe-widgets/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.d.ts +0 -2
- package/dist/types/builds/emfe-widgets/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.dev.d.ts +0 -2
- /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/libs/common/src/storybook/storybook-utils.d.ts +0 -0
- /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/storybook/main.d.ts +0 -0
- /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/storybook/preview.d.ts +0 -0
- /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/index.d.ts +0 -0
- /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/stencil-clean-deps-plugin.d.ts +0 -0
- /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/vite-chunk-plugin.d.ts +0 -0
- /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/vite-clean-deps-plugin.d.ts +0 -0
package/dist/cjs/index.cjs.js
CHANGED
package/dist/cjs/loader.cjs.js
CHANGED
|
@@ -8,7 +8,7 @@ const appGlobals = require('./app-globals-3a1e7e63.js');
|
|
|
8
8
|
const defineCustomElements = async (win, options) => {
|
|
9
9
|
if (typeof window === 'undefined') return undefined;
|
|
10
10
|
await appGlobals.globalScripts();
|
|
11
|
-
return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
11
|
+
return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
exports.setNonce = index.setNonce;
|
|
@@ -368,16 +368,17 @@ const PlayerStepUpAuth = class {
|
|
|
368
368
|
this.flow = '';
|
|
369
369
|
this.showResendOtp = false;
|
|
370
370
|
this.isLastWarning = false;
|
|
371
|
+
this.inputDisabled = false;
|
|
371
372
|
this.handleResendOtp = this.handleResendOtp.bind(this);
|
|
372
373
|
this.submitOtp = this.submitOtp.bind(this);
|
|
373
|
-
this.setOtpContainerRef = this.setOtpContainerRef.bind(this);
|
|
374
374
|
this.handleCloseWidget = this.handleCloseWidget.bind(this);
|
|
375
375
|
this.manualClosePopup = this.manualClosePopup.bind(this);
|
|
376
376
|
}
|
|
377
377
|
/**
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
378
|
+
* Fetches OTP configuration from the endpoint.
|
|
379
|
+
* Updates the OTP state, expiration time, and starts the countdown timer.
|
|
380
|
+
* Handles specific errors like max attempts exceeded by closing the widget.
|
|
381
|
+
*/
|
|
381
382
|
async getConfig() {
|
|
382
383
|
if (!this.endpoint)
|
|
383
384
|
return;
|
|
@@ -385,29 +386,41 @@ const PlayerStepUpAuth = class {
|
|
|
385
386
|
const url = new URL(`/api/v1/mfa/challenge/${this.token}/config`, this.endpoint);
|
|
386
387
|
this.isLoading = true;
|
|
387
388
|
const response = await fetch(url.href);
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
this.
|
|
402
|
-
|
|
389
|
+
const result = await response.json(); // Parse JSON regardless of status
|
|
390
|
+
if (response.ok) {
|
|
391
|
+
//--- Success Path (2xx status) ---
|
|
392
|
+
this.config = result;
|
|
393
|
+
this.otp = Array(this.config.inputLength).fill('');
|
|
394
|
+
this.isLoading = false;
|
|
395
|
+
this.showResendOtp = false;
|
|
396
|
+
this.expirationTime = this.config.expirationTime;
|
|
397
|
+
this.serverTime = this.config.serverTime;
|
|
398
|
+
if (this.config.numberOfValidateAttempts !== 0) {
|
|
399
|
+
this.hasErrors = true;
|
|
400
|
+
this.errorMessage = translate('invalidOtp', this.language);
|
|
401
|
+
}
|
|
402
|
+
if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
|
|
403
|
+
this.isLastWarning = true;
|
|
404
|
+
}
|
|
405
|
+
this.calculateTimeLeft();
|
|
406
|
+
this.startCountdown();
|
|
403
407
|
}
|
|
404
|
-
|
|
405
|
-
|
|
408
|
+
else {
|
|
409
|
+
//--- Error Path (non-2xx status) ---
|
|
410
|
+
// Check for result existence before accessing properties for compatibility.
|
|
411
|
+
if (result && result.details === 'gm.twofa.token_max_attempts_exceeded') {
|
|
412
|
+
// Specific "max attempts" error: close the widget.
|
|
413
|
+
this.handleCloseWidget();
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
// Any other configuration error: throw to be handled by the catch block.
|
|
417
|
+
const errorMessage = (result && result.message) || `Failed to load config. Status: ${response.status}`;
|
|
418
|
+
throw new Error(errorMessage);
|
|
419
|
+
}
|
|
406
420
|
}
|
|
407
|
-
this.calculateTimeLeft();
|
|
408
|
-
this.startCountdown();
|
|
409
421
|
}
|
|
410
422
|
catch (error) {
|
|
423
|
+
//--- Catch block for network errors or thrown exceptions ---
|
|
411
424
|
this.isLoading = false;
|
|
412
425
|
this.hasConfigErrors = true;
|
|
413
426
|
this.errorMessage = translate('configError', this.language);
|
|
@@ -440,6 +453,7 @@ const PlayerStepUpAuth = class {
|
|
|
440
453
|
const now = Date.now();
|
|
441
454
|
const timeRemaining = Math.max(0, Math.floor((this.expirationTimestamp - now) / 1000));
|
|
442
455
|
this.timeLeft = timeRemaining;
|
|
456
|
+
this.inputDisabled = timeRemaining <= 0;
|
|
443
457
|
if (timeRemaining <= 0) {
|
|
444
458
|
clearInterval(this.countdownTimer);
|
|
445
459
|
this.countdownTimer = null;
|
|
@@ -460,15 +474,6 @@ const PlayerStepUpAuth = class {
|
|
|
460
474
|
const remainingSeconds = seconds % 60;
|
|
461
475
|
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
462
476
|
}
|
|
463
|
-
/**
|
|
464
|
-
* Sets a reference to the OTP input container.
|
|
465
|
-
*
|
|
466
|
-
* @param el - The OTP input container element.
|
|
467
|
-
*/
|
|
468
|
-
setOtpContainerRef(el) {
|
|
469
|
-
if (el)
|
|
470
|
-
this.otpContainer = el;
|
|
471
|
-
}
|
|
472
477
|
/**
|
|
473
478
|
* Sets a reference to the OTP inputs.
|
|
474
479
|
*
|
|
@@ -479,6 +484,18 @@ const PlayerStepUpAuth = class {
|
|
|
479
484
|
this.otpInputs[index] = el;
|
|
480
485
|
}
|
|
481
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* update otp state
|
|
489
|
+
* by creating new array and assign to state, to make the UI trigger
|
|
490
|
+
*
|
|
491
|
+
* @param index - The index of the input field being updated.
|
|
492
|
+
* @param value - The inputted value.
|
|
493
|
+
*/
|
|
494
|
+
updateOtpState(index, value) {
|
|
495
|
+
const updated = [...this.otp];
|
|
496
|
+
updated[index] = value.toUpperCase();
|
|
497
|
+
this.otp = updated;
|
|
498
|
+
}
|
|
482
499
|
/**
|
|
483
500
|
* Handles pasting an OTP directly into the input fields.
|
|
484
501
|
* Extracts characters from the clipboard and populates the OTP fields.
|
|
@@ -486,24 +503,15 @@ const PlayerStepUpAuth = class {
|
|
|
486
503
|
* @param e - The clipboard event containing pasted data.
|
|
487
504
|
*/
|
|
488
505
|
handleOnPasteOtp(e) {
|
|
489
|
-
var _a;
|
|
506
|
+
var _a, _b, _c;
|
|
490
507
|
e.preventDefault();
|
|
491
|
-
const data = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text').trim();
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
value.forEach((char, index) => {
|
|
499
|
-
inputs[index].value = char;
|
|
500
|
-
});
|
|
501
|
-
// Move focus to the last input or trigger submit
|
|
502
|
-
const lastInput = inputs[value.length - 1];
|
|
503
|
-
lastInput === null || lastInput === void 0 ? void 0 : lastInput.focus();
|
|
504
|
-
if (value.length === this.config.inputLength) {
|
|
505
|
-
this.submitOtp();
|
|
506
|
-
}
|
|
508
|
+
const data = ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) === null || _b === void 0 ? void 0 : _b.trim()) || '';
|
|
509
|
+
const values = data.slice(0, this.config.inputLength).split('');
|
|
510
|
+
this.otp = [...values, ...Array(this.config.inputLength - values.length).fill('')];
|
|
511
|
+
// Move focus to the one after last input or trigger submit
|
|
512
|
+
(_c = this.otpInputs[values.length]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
513
|
+
if (values.length === this.config.inputLength) {
|
|
514
|
+
this.submitOtp();
|
|
507
515
|
}
|
|
508
516
|
}
|
|
509
517
|
/**
|
|
@@ -515,14 +523,14 @@ const PlayerStepUpAuth = class {
|
|
|
515
523
|
*/
|
|
516
524
|
handleOtpInput(e, index) {
|
|
517
525
|
const input = e.target;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
+
const value = input.value;
|
|
527
|
+
if (/^[a-z0-9]$/i.test(value)) {
|
|
528
|
+
this.updateOtpState(index, value);
|
|
529
|
+
// Move focus using stored refs
|
|
530
|
+
const nextInput = this.otpInputs[index + 1];
|
|
531
|
+
nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
|
|
532
|
+
}
|
|
533
|
+
input.value = '';
|
|
526
534
|
}
|
|
527
535
|
/**
|
|
528
536
|
* Handles key press events for OTP inputs.
|
|
@@ -532,9 +540,21 @@ const PlayerStepUpAuth = class {
|
|
|
532
540
|
* @param index - The index of the input field.
|
|
533
541
|
*/
|
|
534
542
|
handleKeyDown(e, index) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
543
|
+
const key = e.key;
|
|
544
|
+
const isCommandOrControlKey = e.ctrlKey || e.metaKey;
|
|
545
|
+
if (/^[a-z0-9]$/i.test(key)) {
|
|
546
|
+
if (isCommandOrControlKey && key.toLowerCase() === 'v')
|
|
547
|
+
return;
|
|
548
|
+
e.preventDefault();
|
|
549
|
+
this.updateOtpState(index, key);
|
|
550
|
+
const nextInput = this.otpInputs[index + 1];
|
|
551
|
+
nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
|
|
552
|
+
}
|
|
553
|
+
else if (key === 'Backspace') {
|
|
554
|
+
e.preventDefault();
|
|
555
|
+
if (this.otp[index] !== '') {
|
|
556
|
+
this.updateOtpState(index, '');
|
|
557
|
+
}
|
|
538
558
|
const prevInput = this.otpInputs[index - 1];
|
|
539
559
|
prevInput === null || prevInput === void 0 ? void 0 : prevInput.focus();
|
|
540
560
|
}
|
|
@@ -601,7 +621,7 @@ const PlayerStepUpAuth = class {
|
|
|
601
621
|
throw new Error(result.message);
|
|
602
622
|
}
|
|
603
623
|
catch (error) {
|
|
604
|
-
if (error.message === 'gm.multifactorauthentication.
|
|
624
|
+
if (error.message === 'gm.multifactorauthentication.internal_server_error') {
|
|
605
625
|
if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
|
|
606
626
|
window.dispatchEvent(new CustomEvent('otpSetTimeout'));
|
|
607
627
|
//Trigger notification
|
|
@@ -656,8 +676,8 @@ const PlayerStepUpAuth = class {
|
|
|
656
676
|
(_a = this.stylingSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
657
677
|
}
|
|
658
678
|
/**
|
|
659
|
-
|
|
660
|
-
|
|
679
|
+
* Lifecycle method: Fetch translations on component load
|
|
680
|
+
*/
|
|
661
681
|
async componentWillLoad() {
|
|
662
682
|
if (this.translationUrl.length > 2) {
|
|
663
683
|
await getTranslations(this.translationUrl);
|
|
@@ -684,9 +704,9 @@ const PlayerStepUpAuth = class {
|
|
|
684
704
|
* Displays the OTP popup, input fields, timer, and action buttons.
|
|
685
705
|
*/
|
|
686
706
|
render() {
|
|
687
|
-
return (index.h("div", { key: '
|
|
707
|
+
return (index.h("div", { key: '481fb2d579925de2fb472f3d715712625fb7aba9', ref: el => this.stylingContainer = el }, this.showPopup && (index.h("div", { key: 'd9d55ab487c8bd11ed72d18e7eed49fdb59bab8b', class: "OtpPopupOverlay" }, index.h("div", { key: 'c42458b9f43f03dd88cb9ec8706826739cb2ee4c', class: "OtpPopupContent" }, this.isLoading ? (index.h("div", { class: "OtpLoaderContainer" }, index.h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (index.h("div", { class: "OtpError" }, index.h("div", { class: "OtpErrorHeader" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, index.h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), index.h("h2", null, translate('errorHeader', this.language))), index.h("p", null, this.errorMessage), index.h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (index.h(index.Fragment, null, index.h("div", { class: "otp-description" }, this.showResendOtp ? (index.h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (index.h(index.Fragment, null, index.h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (index.h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), index.h("div", { class: "OtpFieldWrapper" }, index.h("h2", null, translate('otpHeading', this.language)), index.h("div", { class: "OtpField" }, this.otp.map((char, index$1) => {
|
|
688
708
|
const isHalfway = this.config.inputLength % 2 === 0 && index$1 === (this.config.inputLength / 2) - 1;
|
|
689
|
-
return (index.h("input", { key: index$1, ref: el => this.setOtpInputRef(el, index$1), id: `otp-input-${index$1}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index$1), onKeyDown: (event) => this.handleKeyDown(event, index$1), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.
|
|
709
|
+
return (index.h("input", { key: index$1, ref: el => this.setOtpInputRef(el, index$1), id: `otp-input-${index$1}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index$1), onKeyDown: (event) => this.handleKeyDown(event, index$1), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.inputDisabled, autoComplete: 'off' }));
|
|
690
710
|
})), index.h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), index.h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (index.h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (index.h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), index.h("button", { class: "OtpButton", onClick: this.manualClosePopup }, translate('close', this.language)))))))))));
|
|
691
711
|
}
|
|
692
712
|
get el() { return index.getElement(this); }
|
|
@@ -19,7 +19,7 @@ var patchBrowser = () => {
|
|
|
19
19
|
|
|
20
20
|
patchBrowser().then(async (options) => {
|
|
21
21
|
await appGlobals.globalScripts();
|
|
22
|
-
return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
22
|
+
return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
exports.setNonce = index.setNonce;
|
|
@@ -104,16 +104,17 @@ export class PlayerStepUpAuth {
|
|
|
104
104
|
this.flow = '';
|
|
105
105
|
this.showResendOtp = false;
|
|
106
106
|
this.isLastWarning = false;
|
|
107
|
+
this.inputDisabled = false;
|
|
107
108
|
this.handleResendOtp = this.handleResendOtp.bind(this);
|
|
108
109
|
this.submitOtp = this.submitOtp.bind(this);
|
|
109
|
-
this.setOtpContainerRef = this.setOtpContainerRef.bind(this);
|
|
110
110
|
this.handleCloseWidget = this.handleCloseWidget.bind(this);
|
|
111
111
|
this.manualClosePopup = this.manualClosePopup.bind(this);
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
* Fetches OTP configuration from the endpoint.
|
|
115
|
+
* Updates the OTP state, expiration time, and starts the countdown timer.
|
|
116
|
+
* Handles specific errors like max attempts exceeded by closing the widget.
|
|
117
|
+
*/
|
|
117
118
|
async getConfig() {
|
|
118
119
|
if (!this.endpoint)
|
|
119
120
|
return;
|
|
@@ -121,29 +122,41 @@ export class PlayerStepUpAuth {
|
|
|
121
122
|
const url = new URL(`/api/v1/mfa/challenge/${this.token}/config`, this.endpoint);
|
|
122
123
|
this.isLoading = true;
|
|
123
124
|
const response = await fetch(url.href);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
this.
|
|
138
|
-
|
|
125
|
+
const result = await response.json(); // Parse JSON regardless of status
|
|
126
|
+
if (response.ok) {
|
|
127
|
+
//--- Success Path (2xx status) ---
|
|
128
|
+
this.config = result;
|
|
129
|
+
this.otp = Array(this.config.inputLength).fill('');
|
|
130
|
+
this.isLoading = false;
|
|
131
|
+
this.showResendOtp = false;
|
|
132
|
+
this.expirationTime = this.config.expirationTime;
|
|
133
|
+
this.serverTime = this.config.serverTime;
|
|
134
|
+
if (this.config.numberOfValidateAttempts !== 0) {
|
|
135
|
+
this.hasErrors = true;
|
|
136
|
+
this.errorMessage = translate('invalidOtp', this.language);
|
|
137
|
+
}
|
|
138
|
+
if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
|
|
139
|
+
this.isLastWarning = true;
|
|
140
|
+
}
|
|
141
|
+
this.calculateTimeLeft();
|
|
142
|
+
this.startCountdown();
|
|
139
143
|
}
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
else {
|
|
145
|
+
//--- Error Path (non-2xx status) ---
|
|
146
|
+
// Check for result existence before accessing properties for compatibility.
|
|
147
|
+
if (result && result.details === 'gm.twofa.token_max_attempts_exceeded') {
|
|
148
|
+
// Specific "max attempts" error: close the widget.
|
|
149
|
+
this.handleCloseWidget();
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Any other configuration error: throw to be handled by the catch block.
|
|
153
|
+
const errorMessage = (result && result.message) || `Failed to load config. Status: ${response.status}`;
|
|
154
|
+
throw new Error(errorMessage);
|
|
155
|
+
}
|
|
142
156
|
}
|
|
143
|
-
this.calculateTimeLeft();
|
|
144
|
-
this.startCountdown();
|
|
145
157
|
}
|
|
146
158
|
catch (error) {
|
|
159
|
+
//--- Catch block for network errors or thrown exceptions ---
|
|
147
160
|
this.isLoading = false;
|
|
148
161
|
this.hasConfigErrors = true;
|
|
149
162
|
this.errorMessage = translate('configError', this.language);
|
|
@@ -176,6 +189,7 @@ export class PlayerStepUpAuth {
|
|
|
176
189
|
const now = Date.now();
|
|
177
190
|
const timeRemaining = Math.max(0, Math.floor((this.expirationTimestamp - now) / 1000));
|
|
178
191
|
this.timeLeft = timeRemaining;
|
|
192
|
+
this.inputDisabled = timeRemaining <= 0;
|
|
179
193
|
if (timeRemaining <= 0) {
|
|
180
194
|
clearInterval(this.countdownTimer);
|
|
181
195
|
this.countdownTimer = null;
|
|
@@ -196,15 +210,6 @@ export class PlayerStepUpAuth {
|
|
|
196
210
|
const remainingSeconds = seconds % 60;
|
|
197
211
|
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
198
212
|
}
|
|
199
|
-
/**
|
|
200
|
-
* Sets a reference to the OTP input container.
|
|
201
|
-
*
|
|
202
|
-
* @param el - The OTP input container element.
|
|
203
|
-
*/
|
|
204
|
-
setOtpContainerRef(el) {
|
|
205
|
-
if (el)
|
|
206
|
-
this.otpContainer = el;
|
|
207
|
-
}
|
|
208
213
|
/**
|
|
209
214
|
* Sets a reference to the OTP inputs.
|
|
210
215
|
*
|
|
@@ -215,6 +220,18 @@ export class PlayerStepUpAuth {
|
|
|
215
220
|
this.otpInputs[index] = el;
|
|
216
221
|
}
|
|
217
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* update otp state
|
|
225
|
+
* by creating new array and assign to state, to make the UI trigger
|
|
226
|
+
*
|
|
227
|
+
* @param index - The index of the input field being updated.
|
|
228
|
+
* @param value - The inputted value.
|
|
229
|
+
*/
|
|
230
|
+
updateOtpState(index, value) {
|
|
231
|
+
const updated = [...this.otp];
|
|
232
|
+
updated[index] = value.toUpperCase();
|
|
233
|
+
this.otp = updated;
|
|
234
|
+
}
|
|
218
235
|
/**
|
|
219
236
|
* Handles pasting an OTP directly into the input fields.
|
|
220
237
|
* Extracts characters from the clipboard and populates the OTP fields.
|
|
@@ -222,24 +239,15 @@ export class PlayerStepUpAuth {
|
|
|
222
239
|
* @param e - The clipboard event containing pasted data.
|
|
223
240
|
*/
|
|
224
241
|
handleOnPasteOtp(e) {
|
|
225
|
-
var _a;
|
|
242
|
+
var _a, _b, _c;
|
|
226
243
|
e.preventDefault();
|
|
227
|
-
const data = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text').trim();
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
value.forEach((char, index) => {
|
|
235
|
-
inputs[index].value = char;
|
|
236
|
-
});
|
|
237
|
-
// Move focus to the last input or trigger submit
|
|
238
|
-
const lastInput = inputs[value.length - 1];
|
|
239
|
-
lastInput === null || lastInput === void 0 ? void 0 : lastInput.focus();
|
|
240
|
-
if (value.length === this.config.inputLength) {
|
|
241
|
-
this.submitOtp();
|
|
242
|
-
}
|
|
244
|
+
const data = ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) === null || _b === void 0 ? void 0 : _b.trim()) || '';
|
|
245
|
+
const values = data.slice(0, this.config.inputLength).split('');
|
|
246
|
+
this.otp = [...values, ...Array(this.config.inputLength - values.length).fill('')];
|
|
247
|
+
// Move focus to the one after last input or trigger submit
|
|
248
|
+
(_c = this.otpInputs[values.length]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
249
|
+
if (values.length === this.config.inputLength) {
|
|
250
|
+
this.submitOtp();
|
|
243
251
|
}
|
|
244
252
|
}
|
|
245
253
|
/**
|
|
@@ -251,14 +259,14 @@ export class PlayerStepUpAuth {
|
|
|
251
259
|
*/
|
|
252
260
|
handleOtpInput(e, index) {
|
|
253
261
|
const input = e.target;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
+
const value = input.value;
|
|
263
|
+
if (/^[a-z0-9]$/i.test(value)) {
|
|
264
|
+
this.updateOtpState(index, value);
|
|
265
|
+
// Move focus using stored refs
|
|
266
|
+
const nextInput = this.otpInputs[index + 1];
|
|
267
|
+
nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
|
|
268
|
+
}
|
|
269
|
+
input.value = '';
|
|
262
270
|
}
|
|
263
271
|
/**
|
|
264
272
|
* Handles key press events for OTP inputs.
|
|
@@ -268,9 +276,21 @@ export class PlayerStepUpAuth {
|
|
|
268
276
|
* @param index - The index of the input field.
|
|
269
277
|
*/
|
|
270
278
|
handleKeyDown(e, index) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
279
|
+
const key = e.key;
|
|
280
|
+
const isCommandOrControlKey = e.ctrlKey || e.metaKey;
|
|
281
|
+
if (/^[a-z0-9]$/i.test(key)) {
|
|
282
|
+
if (isCommandOrControlKey && key.toLowerCase() === 'v')
|
|
283
|
+
return;
|
|
284
|
+
e.preventDefault();
|
|
285
|
+
this.updateOtpState(index, key);
|
|
286
|
+
const nextInput = this.otpInputs[index + 1];
|
|
287
|
+
nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
|
|
288
|
+
}
|
|
289
|
+
else if (key === 'Backspace') {
|
|
290
|
+
e.preventDefault();
|
|
291
|
+
if (this.otp[index] !== '') {
|
|
292
|
+
this.updateOtpState(index, '');
|
|
293
|
+
}
|
|
274
294
|
const prevInput = this.otpInputs[index - 1];
|
|
275
295
|
prevInput === null || prevInput === void 0 ? void 0 : prevInput.focus();
|
|
276
296
|
}
|
|
@@ -337,7 +357,7 @@ export class PlayerStepUpAuth {
|
|
|
337
357
|
throw new Error(result.message);
|
|
338
358
|
}
|
|
339
359
|
catch (error) {
|
|
340
|
-
if (error.message === 'gm.multifactorauthentication.
|
|
360
|
+
if (error.message === 'gm.multifactorauthentication.internal_server_error') {
|
|
341
361
|
if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
|
|
342
362
|
window.dispatchEvent(new CustomEvent('otpSetTimeout'));
|
|
343
363
|
//Trigger notification
|
|
@@ -392,8 +412,8 @@ export class PlayerStepUpAuth {
|
|
|
392
412
|
(_a = this.stylingSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
393
413
|
}
|
|
394
414
|
/**
|
|
395
|
-
|
|
396
|
-
|
|
415
|
+
* Lifecycle method: Fetch translations on component load
|
|
416
|
+
*/
|
|
397
417
|
async componentWillLoad() {
|
|
398
418
|
if (this.translationUrl.length > 2) {
|
|
399
419
|
await getTranslations(this.translationUrl);
|
|
@@ -420,9 +440,9 @@ export class PlayerStepUpAuth {
|
|
|
420
440
|
* Displays the OTP popup, input fields, timer, and action buttons.
|
|
421
441
|
*/
|
|
422
442
|
render() {
|
|
423
|
-
return (h("div", { key: '
|
|
443
|
+
return (h("div", { key: '481fb2d579925de2fb472f3d715712625fb7aba9', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: 'd9d55ab487c8bd11ed72d18e7eed49fdb59bab8b', class: "OtpPopupOverlay" }, h("div", { key: 'c42458b9f43f03dd88cb9ec8706826739cb2ee4c', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, this.showResendOtp ? (h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (h(Fragment, null, h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField" }, this.otp.map((char, index) => {
|
|
424
444
|
const isHalfway = this.config.inputLength % 2 === 0 && index === (this.config.inputLength / 2) - 1;
|
|
425
|
-
return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.
|
|
445
|
+
return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.inputDisabled, autoComplete: 'off' }));
|
|
426
446
|
})), h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), h("button", { class: "OtpButton", onClick: this.manualClosePopup }, translate('close', this.language)))))))))));
|
|
427
447
|
}
|
|
428
448
|
static get is() { return "player-step-up-auth"; }
|
|
@@ -577,7 +597,8 @@ export class PlayerStepUpAuth {
|
|
|
577
597
|
"token": {},
|
|
578
598
|
"flow": {},
|
|
579
599
|
"showResendOtp": {},
|
|
580
|
-
"isLastWarning": {}
|
|
600
|
+
"isLastWarning": {},
|
|
601
|
+
"inputDisabled": {}
|
|
581
602
|
};
|
|
582
603
|
}
|
|
583
604
|
static get elementRef() { return "el"; }
|
package/dist/esm/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { P as PlayerStepUpAuth } from './player-step-up-auth-
|
|
1
|
+
export { P as PlayerStepUpAuth } from './player-step-up-auth-e624c40c.js';
|
|
2
2
|
import './index-c6eee6d8.js';
|
package/dist/esm/loader.js
CHANGED
|
@@ -5,7 +5,7 @@ import { g as globalScripts } from './app-globals-0f993ce5.js';
|
|
|
5
5
|
const defineCustomElements = async (win, options) => {
|
|
6
6
|
if (typeof window === 'undefined') return undefined;
|
|
7
7
|
await globalScripts();
|
|
8
|
-
return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
8
|
+
return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export { defineCustomElements };
|
|
@@ -366,16 +366,17 @@ const PlayerStepUpAuth = class {
|
|
|
366
366
|
this.flow = '';
|
|
367
367
|
this.showResendOtp = false;
|
|
368
368
|
this.isLastWarning = false;
|
|
369
|
+
this.inputDisabled = false;
|
|
369
370
|
this.handleResendOtp = this.handleResendOtp.bind(this);
|
|
370
371
|
this.submitOtp = this.submitOtp.bind(this);
|
|
371
|
-
this.setOtpContainerRef = this.setOtpContainerRef.bind(this);
|
|
372
372
|
this.handleCloseWidget = this.handleCloseWidget.bind(this);
|
|
373
373
|
this.manualClosePopup = this.manualClosePopup.bind(this);
|
|
374
374
|
}
|
|
375
375
|
/**
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
* Fetches OTP configuration from the endpoint.
|
|
377
|
+
* Updates the OTP state, expiration time, and starts the countdown timer.
|
|
378
|
+
* Handles specific errors like max attempts exceeded by closing the widget.
|
|
379
|
+
*/
|
|
379
380
|
async getConfig() {
|
|
380
381
|
if (!this.endpoint)
|
|
381
382
|
return;
|
|
@@ -383,29 +384,41 @@ const PlayerStepUpAuth = class {
|
|
|
383
384
|
const url = new URL(`/api/v1/mfa/challenge/${this.token}/config`, this.endpoint);
|
|
384
385
|
this.isLoading = true;
|
|
385
386
|
const response = await fetch(url.href);
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
this.
|
|
400
|
-
|
|
387
|
+
const result = await response.json(); // Parse JSON regardless of status
|
|
388
|
+
if (response.ok) {
|
|
389
|
+
//--- Success Path (2xx status) ---
|
|
390
|
+
this.config = result;
|
|
391
|
+
this.otp = Array(this.config.inputLength).fill('');
|
|
392
|
+
this.isLoading = false;
|
|
393
|
+
this.showResendOtp = false;
|
|
394
|
+
this.expirationTime = this.config.expirationTime;
|
|
395
|
+
this.serverTime = this.config.serverTime;
|
|
396
|
+
if (this.config.numberOfValidateAttempts !== 0) {
|
|
397
|
+
this.hasErrors = true;
|
|
398
|
+
this.errorMessage = translate('invalidOtp', this.language);
|
|
399
|
+
}
|
|
400
|
+
if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
|
|
401
|
+
this.isLastWarning = true;
|
|
402
|
+
}
|
|
403
|
+
this.calculateTimeLeft();
|
|
404
|
+
this.startCountdown();
|
|
401
405
|
}
|
|
402
|
-
|
|
403
|
-
|
|
406
|
+
else {
|
|
407
|
+
//--- Error Path (non-2xx status) ---
|
|
408
|
+
// Check for result existence before accessing properties for compatibility.
|
|
409
|
+
if (result && result.details === 'gm.twofa.token_max_attempts_exceeded') {
|
|
410
|
+
// Specific "max attempts" error: close the widget.
|
|
411
|
+
this.handleCloseWidget();
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
// Any other configuration error: throw to be handled by the catch block.
|
|
415
|
+
const errorMessage = (result && result.message) || `Failed to load config. Status: ${response.status}`;
|
|
416
|
+
throw new Error(errorMessage);
|
|
417
|
+
}
|
|
404
418
|
}
|
|
405
|
-
this.calculateTimeLeft();
|
|
406
|
-
this.startCountdown();
|
|
407
419
|
}
|
|
408
420
|
catch (error) {
|
|
421
|
+
//--- Catch block for network errors or thrown exceptions ---
|
|
409
422
|
this.isLoading = false;
|
|
410
423
|
this.hasConfigErrors = true;
|
|
411
424
|
this.errorMessage = translate('configError', this.language);
|
|
@@ -438,6 +451,7 @@ const PlayerStepUpAuth = class {
|
|
|
438
451
|
const now = Date.now();
|
|
439
452
|
const timeRemaining = Math.max(0, Math.floor((this.expirationTimestamp - now) / 1000));
|
|
440
453
|
this.timeLeft = timeRemaining;
|
|
454
|
+
this.inputDisabled = timeRemaining <= 0;
|
|
441
455
|
if (timeRemaining <= 0) {
|
|
442
456
|
clearInterval(this.countdownTimer);
|
|
443
457
|
this.countdownTimer = null;
|
|
@@ -458,15 +472,6 @@ const PlayerStepUpAuth = class {
|
|
|
458
472
|
const remainingSeconds = seconds % 60;
|
|
459
473
|
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
460
474
|
}
|
|
461
|
-
/**
|
|
462
|
-
* Sets a reference to the OTP input container.
|
|
463
|
-
*
|
|
464
|
-
* @param el - The OTP input container element.
|
|
465
|
-
*/
|
|
466
|
-
setOtpContainerRef(el) {
|
|
467
|
-
if (el)
|
|
468
|
-
this.otpContainer = el;
|
|
469
|
-
}
|
|
470
475
|
/**
|
|
471
476
|
* Sets a reference to the OTP inputs.
|
|
472
477
|
*
|
|
@@ -477,6 +482,18 @@ const PlayerStepUpAuth = class {
|
|
|
477
482
|
this.otpInputs[index] = el;
|
|
478
483
|
}
|
|
479
484
|
}
|
|
485
|
+
/**
|
|
486
|
+
* update otp state
|
|
487
|
+
* by creating new array and assign to state, to make the UI trigger
|
|
488
|
+
*
|
|
489
|
+
* @param index - The index of the input field being updated.
|
|
490
|
+
* @param value - The inputted value.
|
|
491
|
+
*/
|
|
492
|
+
updateOtpState(index, value) {
|
|
493
|
+
const updated = [...this.otp];
|
|
494
|
+
updated[index] = value.toUpperCase();
|
|
495
|
+
this.otp = updated;
|
|
496
|
+
}
|
|
480
497
|
/**
|
|
481
498
|
* Handles pasting an OTP directly into the input fields.
|
|
482
499
|
* Extracts characters from the clipboard and populates the OTP fields.
|
|
@@ -484,24 +501,15 @@ const PlayerStepUpAuth = class {
|
|
|
484
501
|
* @param e - The clipboard event containing pasted data.
|
|
485
502
|
*/
|
|
486
503
|
handleOnPasteOtp(e) {
|
|
487
|
-
var _a;
|
|
504
|
+
var _a, _b, _c;
|
|
488
505
|
e.preventDefault();
|
|
489
|
-
const data = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text').trim();
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
value.forEach((char, index) => {
|
|
497
|
-
inputs[index].value = char;
|
|
498
|
-
});
|
|
499
|
-
// Move focus to the last input or trigger submit
|
|
500
|
-
const lastInput = inputs[value.length - 1];
|
|
501
|
-
lastInput === null || lastInput === void 0 ? void 0 : lastInput.focus();
|
|
502
|
-
if (value.length === this.config.inputLength) {
|
|
503
|
-
this.submitOtp();
|
|
504
|
-
}
|
|
506
|
+
const data = ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) === null || _b === void 0 ? void 0 : _b.trim()) || '';
|
|
507
|
+
const values = data.slice(0, this.config.inputLength).split('');
|
|
508
|
+
this.otp = [...values, ...Array(this.config.inputLength - values.length).fill('')];
|
|
509
|
+
// Move focus to the one after last input or trigger submit
|
|
510
|
+
(_c = this.otpInputs[values.length]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
511
|
+
if (values.length === this.config.inputLength) {
|
|
512
|
+
this.submitOtp();
|
|
505
513
|
}
|
|
506
514
|
}
|
|
507
515
|
/**
|
|
@@ -513,14 +521,14 @@ const PlayerStepUpAuth = class {
|
|
|
513
521
|
*/
|
|
514
522
|
handleOtpInput(e, index) {
|
|
515
523
|
const input = e.target;
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
+
const value = input.value;
|
|
525
|
+
if (/^[a-z0-9]$/i.test(value)) {
|
|
526
|
+
this.updateOtpState(index, value);
|
|
527
|
+
// Move focus using stored refs
|
|
528
|
+
const nextInput = this.otpInputs[index + 1];
|
|
529
|
+
nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
|
|
530
|
+
}
|
|
531
|
+
input.value = '';
|
|
524
532
|
}
|
|
525
533
|
/**
|
|
526
534
|
* Handles key press events for OTP inputs.
|
|
@@ -530,9 +538,21 @@ const PlayerStepUpAuth = class {
|
|
|
530
538
|
* @param index - The index of the input field.
|
|
531
539
|
*/
|
|
532
540
|
handleKeyDown(e, index) {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
541
|
+
const key = e.key;
|
|
542
|
+
const isCommandOrControlKey = e.ctrlKey || e.metaKey;
|
|
543
|
+
if (/^[a-z0-9]$/i.test(key)) {
|
|
544
|
+
if (isCommandOrControlKey && key.toLowerCase() === 'v')
|
|
545
|
+
return;
|
|
546
|
+
e.preventDefault();
|
|
547
|
+
this.updateOtpState(index, key);
|
|
548
|
+
const nextInput = this.otpInputs[index + 1];
|
|
549
|
+
nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
|
|
550
|
+
}
|
|
551
|
+
else if (key === 'Backspace') {
|
|
552
|
+
e.preventDefault();
|
|
553
|
+
if (this.otp[index] !== '') {
|
|
554
|
+
this.updateOtpState(index, '');
|
|
555
|
+
}
|
|
536
556
|
const prevInput = this.otpInputs[index - 1];
|
|
537
557
|
prevInput === null || prevInput === void 0 ? void 0 : prevInput.focus();
|
|
538
558
|
}
|
|
@@ -599,7 +619,7 @@ const PlayerStepUpAuth = class {
|
|
|
599
619
|
throw new Error(result.message);
|
|
600
620
|
}
|
|
601
621
|
catch (error) {
|
|
602
|
-
if (error.message === 'gm.multifactorauthentication.
|
|
622
|
+
if (error.message === 'gm.multifactorauthentication.internal_server_error') {
|
|
603
623
|
if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
|
|
604
624
|
window.dispatchEvent(new CustomEvent('otpSetTimeout'));
|
|
605
625
|
//Trigger notification
|
|
@@ -654,8 +674,8 @@ const PlayerStepUpAuth = class {
|
|
|
654
674
|
(_a = this.stylingSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
655
675
|
}
|
|
656
676
|
/**
|
|
657
|
-
|
|
658
|
-
|
|
677
|
+
* Lifecycle method: Fetch translations on component load
|
|
678
|
+
*/
|
|
659
679
|
async componentWillLoad() {
|
|
660
680
|
if (this.translationUrl.length > 2) {
|
|
661
681
|
await getTranslations(this.translationUrl);
|
|
@@ -682,9 +702,9 @@ const PlayerStepUpAuth = class {
|
|
|
682
702
|
* Displays the OTP popup, input fields, timer, and action buttons.
|
|
683
703
|
*/
|
|
684
704
|
render() {
|
|
685
|
-
return (h("div", { key: '
|
|
705
|
+
return (h("div", { key: '481fb2d579925de2fb472f3d715712625fb7aba9', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: 'd9d55ab487c8bd11ed72d18e7eed49fdb59bab8b', class: "OtpPopupOverlay" }, h("div", { key: 'c42458b9f43f03dd88cb9ec8706826739cb2ee4c', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, this.showResendOtp ? (h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (h(Fragment, null, h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField" }, this.otp.map((char, index) => {
|
|
686
706
|
const isHalfway = this.config.inputLength % 2 === 0 && index === (this.config.inputLength / 2) - 1;
|
|
687
|
-
return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.
|
|
707
|
+
return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.inputDisabled, autoComplete: 'off' }));
|
|
688
708
|
})), h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), h("button", { class: "OtpButton", onClick: this.manualClosePopup }, translate('close', this.language)))))))))));
|
|
689
709
|
}
|
|
690
710
|
get el() { return getElement(this); }
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { P as player_step_up_auth } from './player-step-up-auth-
|
|
1
|
+
export { P as player_step_up_auth } from './player-step-up-auth-e624c40c.js';
|
|
2
2
|
import './index-c6eee6d8.js';
|
|
@@ -16,5 +16,5 @@ var patchBrowser = () => {
|
|
|
16
16
|
|
|
17
17
|
patchBrowser().then(async (options) => {
|
|
18
18
|
await globalScripts();
|
|
19
|
-
return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
19
|
+
return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
|
|
20
20
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{P as PlayerStepUpAuth}from"./player-step-up-auth-
|
|
1
|
+
export{P as PlayerStepUpAuth}from"./player-step-up-auth-e624c40c.js";import"./index-c6eee6d8.js";
|
package/dist/player-step-up-auth/{player-step-up-auth-045726cf.js → player-step-up-auth-e624c40c.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e,h as t,F as i,g as r}from"./index-c6eee6d8.js";function o(e,t){if(e){const i=document.createElement("style");i.innerHTML=t,e.appendChild(i)}}function a(e,t){const i=new URL(t);fetch(i.href).then((e=>e.text())).then((t=>{const i=document.createElement("style");i.innerHTML=t,e&&e.appendChild(i)})).catch((e=>{console.error("There was an error while trying to load client styling from URL",e)}))}const s={en:{popupMessage:"Please enter the security code received on your email address to perform the update.",popupMessageLastWarning:"If the next validation attempt is failed, you will be logged out and blocked temporarily.",minutes:"minutes",errorHeader:"Error",configError:"Unable to load OTP data. Please try again later.",otpHeading:"Enter OTP",resendOtp:"Resent OTP",submit:"Submit",close:"Close",invalidOtp:"The code you've sent is not valid. Please try again.",accountBlocked:"Too many attempts for OTP. Your account has been blocked for one hour.",submissionError:"Something went wrong. Please try again.",otpExpiredMessage:"Validation code has expired, please request a new one to continue."},ro:{popupMessage:"Introduceți codul de securitate primit pe adresa dvs. de e-mail pentru a efectua actualizarea.",popupMessageLastWarning:"Dacă următoarea încercare de validare eșuează, veți fi delogat și blocat temporar.",minutes:"minute",errorHeader:"Eroare",configError:"Nu s-a putut încărca datele OTP. Vă rugăm să încercați din nou mai târziu.",otpHeading:"Introduceți OTP",resendOtp:"Retrimitere OTP",submit:"Trimite",close:"Închide",invalidOtp:"Codul introdus nu este valid. Vă rugăm să încercați din nou.",accountBlocked:"Prea multe încercări de OTP. Contul dvs. a fost blocat timp de o oră.",submissionError:"Ceva a mers prost. Vă rugăm să încercați din nou.",otpExpiredMessage:"Codul de validare a expirat, vă rugăm să solicitați unul nou pentru a continua."},fr:{popupMessage:"Veuillez entrer le code de sécurité reçu sur votre adresse e-mail pour effectuer la mise à jour.",popupMessageLastWarning:"Si la prochaine tentative de validation échoue, vous serez déconnecté et temporairement bloqué.",minutes:"minutes",errorHeader:"Erreur",configError:"Impossible de charger les données OTP. Veuillez réessayer plus tard.",otpHeading:"Entrez OTP",resendOtp:"Renvoyer OTP",submit:"Soumettre",close:"Fermer",invalidOtp:"Le code que vous avez saisi n’est pas valide. Veuillez réessayer.",accountBlocked:"Trop de tentatives OTP. Votre compte a été bloqué pendant une heure.",submissionError:"Quelque chose s'est mal passé. Veuillez réessayer.",otpExpiredMessage:"Le code de validation a expiré, veuillez en demander un nouveau pour continuer."},hu:{popupMessage:"Kérjük, adja meg az e-mail címére küldött biztonsági kódot a frissítés végrehajtásához.",popupMessageLastWarning:"Ha a következő érvényesítési kísérlet sikertelen, ki lesz jelentkeztetve és ideiglenesen letiltva.",minutes:"perc",errorHeader:"Hiba",configError:"Nem sikerült betölteni az OTP adatokat. Kérjük, próbálja újra később.",otpHeading:"OTP megadása",resendOtp:"Újraküldés",submit:"Beküldés",close:"Bezárás",invalidOtp:"A megadott kód érvénytelen. Kérjük, próbálja újra.",accountBlocked:"Túl sok OTP próbálkozás. A fiókja egy órára zárolva lett.",submissionError:"Valami hiba történt. Kérjük, próbálja újra.",otpExpiredMessage:"A megerősítő kód lejárt, kérjük, kérjen egy újat a folytatáshoz."},tr:{popupMessage:"Güncellemeyi gerçekleştirmek için e-posta adresinize gelen güvenlik kodunu girin.",popupMessageLastWarning:"Bir sonraki doğrulama girişimi başarısız olursa, oturumunuz kapatılacak ve geçici olarak engelleneceksiniz.",minutes:"dakika",errorHeader:"Hata",configError:"OTP verisi yüklenemedi. Lütfen daha sonra tekrar deneyin.",otpHeading:"OTP Girin",resendOtp:"OTP'yi Yeniden Gönder",submit:"Gönder",close:"Kapat",invalidOtp:"Gönderdiğiniz kod geçersiz. Lütfen tekrar deneyin.",accountBlocked:"Çok fazla OTP denemesi yapıldı. Hesabınız bir saat boyunca kilitlendi.",submissionError:"Bir şeyler yanlış gitti. Lütfen tekrar deneyin.",otpExpiredMessage:"Doğrulama kodunun süresi doldu, devam etmek için lütfen yeni bir tane isteyin."},el:{popupMessage:"Παρακαλώ εισάγετε τον κωδικό ασφαλείας που λάβατε στο email σας για να ολοκληρώσετε την ενημέρωση.",popupMessageLastWarning:"Αν η επόμενη προσπάθεια επικύρωσης αποτύχει, θα αποσυνδεθείτε και θα αποκλειστείτε προσωρινά.",minutes:"λεπτά",errorHeader:"Σφάλμα",configError:"Δεν ήταν δυνατή η φόρτωση των δεδομένων OTP. Παρακαλούμε προσπαθήστε ξανά αργότερα.",otpHeading:"Εισαγωγή OTP",resendOtp:"Αποστολή ξανά OTP",submit:"Υποβολή",close:"Κλείσιμο",invalidOtp:"Ο κωδικός που εισαγάγατε δεν είναι έγκυρος. Παρακαλώ προσπαθήστε ξανά.",accountBlocked:"Πάρα πολλές προσπάθειες OTP. Ο λογαριασμός σας έχει αποκλειστεί για μία ώρα.",submissionError:"Κάτι πήγε στραβά. Παρακαλώ προσπαθήστε ξανά.",otpExpiredMessage:"Ο κωδικός επαλήθευσης έχει λήξει, παρακαλώ ζητήστε έναν νέο για να συνεχίσετε."},es:{popupMessage:"Por favor, introduzca el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudo cargar los datos del OTP. Por favor, inténtelo de nuevo más tarde.",otpHeading:"Introducir OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresaste no es válido. Por favor, inténtalo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},pt:{popupMessage:"Por favor, insira o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, será desconectado e temporariamente bloqueado.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Insira o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código inserido não é válido. Por favor, tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."},hr:{popupMessage:"Unesite sigurnosni kod primljen na vašu e-mail adresu kako biste izvršili ažuriranje.",popupMessageLastWarning:"Ako sljedeći pokušaj provjere ne uspije, bit ćete odjavljeni i privremeno blokirani.",minutes:"minute",errorHeader:"Greška",configError:"Nije moguće učitati OTP podatke. Pokušajte ponovno kasnije.",otpHeading:"Unesite OTP",resendOtp:"Ponovno pošalji OTP",submit:"Pošalji",close:"Zatvori",invalidOtp:"Uneseni kod nije valjan. Molimo pokušajte ponovo.",accountBlocked:"Previše pokušaja unosa OTP-a. Vaš račun je blokiran na jedan sat.",submissionError:"Nešto je pošlo po zlu. Molimo pokušajte ponovo.",otpExpiredMessage:"Kod za potvrdu je istekao, molimo zatražite novi kako biste nastavili."},de:{popupMessage:"Bitte geben Sie den Sicherheitscode ein, den Sie an Ihre E-Mail-Adresse erhalten haben, um das Update durchzuführen.",popupMessageLastWarning:"Wenn der nächste Validierungsversuch fehlschlägt, werden Sie abgemeldet und vorübergehend gesperrt.",minutes:"Minuten",errorHeader:"Fehler",configError:"OTP-Daten konnten nicht geladen werden. Bitte versuchen Sie es später erneut.",otpHeading:"OTP eingeben",resendOtp:"OTP erneut senden",submit:"Absenden",close:"Schließen",invalidOtp:"Der eingegebene Code ist ungültig. Bitte versuchen Sie es erneut.",accountBlocked:"Zu viele OTP-Versuche. Ihr Konto wurde für eine Stunde gesperrt.",submissionError:"Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.",otpExpiredMessage:"Der Bestätigungscode ist abgelaufen, bitte fordern Sie einen neuen an, um fortzufahren."},"es-mx":{popupMessage:"Por favor, ingrese el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudieron cargar los datos del OTP. Inténtelo de nuevo más tarde.",otpHeading:"Ingrese OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresó no es válido. Inténtelo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},"pt-br":{popupMessage:"Por favor, digite o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, você será desconectado e bloqueado temporariamente.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Digite o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código informado não é válido. Tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."}},n=e=>new Promise((t=>{fetch(e).then((e=>e.json())).then((e=>{Object.keys(e).forEach((t=>{for(let i in e[t])s[t][i]=e[t][i]})),t(!0)}))})),l=(e,t)=>s[void 0!==t?t:"en"][e],d=class{handleNewTranslations(){n(this.translationUrl)}handleClientStylingChange(e,t){e!==t&&o(this.el,this.clientStyling)}handleClientStylingUrlChange(e,t){e!=t&&this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)}async handleStepUpAuthEvent(e){var t;if(null===(t=e.detail)||void 0===t?void 0:t["x-step-up-required"]){if(this.hasConfigErrors=!1,this.hasErrors=!1,this.errorMessage="",this.showPopup=!0,this.token=e.detail["x-step-up-token"],this.flow=e.detail.flow,!this.token||!this.flow)return this.isLoading=!1,this.hasConfigErrors=!0,void(this.errorMessage=l("configError",this.language));await this.getConfig()}}handleCloseWidget(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null),this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.showPopup=!1,this.isLastWarning=!1}constructor(t){e(this,t),this.otpInputs=[],this.countdownTimer=null,this.expirationTimestamp=0,this.mbSource=void 0,this.clientStyling=void 0,this.clientStylingUrl=void 0,this.language="en",this.endpoint=void 0,this.userSession=void 0,this.translationUrl="",this.showPopup=!1,this.otp=void 0,this.isLoading=!0,this.config=null,this.timeLeft=0,this.expirationTime="",this.serverTime="",this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.token="",this.flow="",this.showResendOtp=!1,this.isLastWarning=!1,this.handleResendOtp=this.handleResendOtp.bind(this),this.submitOtp=this.submitOtp.bind(this),this.setOtpContainerRef=this.setOtpContainerRef.bind(this),this.handleCloseWidget=this.handleCloseWidget.bind(this),this.manualClosePopup=this.manualClosePopup.bind(this)}async getConfig(){if(this.endpoint)try{const e=new URL(`/api/v1/mfa/challenge/${this.token}/config`,this.endpoint);this.isLoading=!0;const t=await fetch(e.href);if(!t.ok)throw new Error(`HTTP error! Status: ${t.status}`);this.config=await t.json(),this.otp=new Array(this.config.inputLength).fill(""),this.isLoading=!1,this.showResendOtp=!1,this.expirationTime=this.config.expirationTime,this.serverTime=this.config.serverTime,0!==this.config.numberOfValidateAttempts&&(this.hasErrors=!0,this.errorMessage=l("invalidOtp",this.language)),this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1&&(this.isLastWarning=!0),this.calculateTimeLeft(),this.startCountdown()}catch(e){this.isLoading=!1,this.hasConfigErrors=!0,this.errorMessage=l("configError",this.language),console.error("Error loading 2FA config:",e)}}calculateTimeLeft(){const e=new Date(this.expirationTime),t=new Date(this.serverTime),i=new Date,r=t.getTime()-i.getTime();this.expirationTimestamp=e.getTime()-r;const o=Date.now(),a=Math.max(0,Math.floor((this.expirationTimestamp-o)/1e3));this.timeLeft=a}startCountdown(){this.countdownTimer&&clearInterval(this.countdownTimer),this.countdownTimer=setInterval((()=>{const e=Date.now(),t=Math.max(0,Math.floor((this.expirationTimestamp-e)/1e3));this.timeLeft=t,t<=0&&(clearInterval(this.countdownTimer),this.countdownTimer=null,this.showResendOtp=!0,this.hasErrors=!1,this.isLastWarning=!1)}),1e3)}formatTime(e){const t=e%60;return`${Math.floor(e/60).toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}setOtpContainerRef(e){e&&(this.otpContainer=e)}setOtpInputRef(e,t){e&&(this.otpInputs[t]=e)}handleOnPasteOtp(e){var t;e.preventDefault();const i=null===(t=e.clipboardData)||void 0===t?void 0:t.getData("text").trim();if(!i)return;const r=i.slice(0,this.config.inputLength).split("");this.otp=[...r,...new Array(this.config.inputLength-r.length).fill("")];const o=Array.from(this.otpContainer.children);if(o){r.forEach(((e,t)=>{o[t].value=e}));const e=o[r.length-1];null==e||e.focus(),r.length===this.config.inputLength&&this.submitOtp()}}handleOtpInput(e,t){const i=e.target;let r=i.value.replace(/[^0-9a-zA-Z]/gi,"").toUpperCase();if(i.value=r.charAt(0),!r)return;this.otp[t]=r[0];const o=this.otpInputs[t+1];null==o||o.focus()}handleKeyDown(e,t){if("Backspace"===e.key){this.otp[t]="",this.otpInputs[t].value="";const e=this.otpInputs[t-1];null==e||e.focus()}}handleResendOtp(){const e=new CustomEvent("otpResendRequested");window.dispatchEvent(e)}async submitOtp(){if(this.otp.join("").length!==this.config.inputLength)return this.hasErrors=!0,void(this.errorMessage=l("invalidOtp",this.language));this.isLoading=!0,this.hasErrors=!1,this.errorMessage="";const e=this.otp.join("");"stateless"===this.flow&&this.handleOtpStateless(e),"stateful"===this.flow&&await this.handleOtpStateful(e)}handleOtpStateless(e){window.dispatchEvent(new CustomEvent("otpSubmitted",{detail:{code:e,maxAttempts:this.config.maxValidationAttempts,validatedAttempts:this.config.numberOfValidateAttempts}}))}async handleOtpStateful(e){const t=new URL(`/api/v1/mfa/challenge/${this.token}/validate`,this.endpoint);t.searchParams.append("input",e);try{const e=await fetch(t.href,{method:"POST"});if(200===e.status)return void this.handleSuccess();const i=await e.json();throw new Error(i.message)}catch(e){if("gm.multifactorauthentication.challenge"===e.message)return this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1?(window.dispatchEvent(new CustomEvent("otpSetTimeout")),window.postMessage({type:"WidgetNotification",data:{type:"error",message:l("accountBlocked",this.language)}},window.location.href),void this.handleCloseWidget()):(this.hasErrors=!0,this.errorMessage=l("invalidOtp",this.language),void this.getConfig());console.error("OTP submission failed:",e),this.hasErrors=!0,this.errorMessage=l("submissionError",this.language)}finally{this.isLoading=!1}}handleSuccess(){window.dispatchEvent(new CustomEvent("otpSuccess",{detail:{message:"User successfully authenticated"}})),this.handleCloseWidget()}manualClosePopup(){window.dispatchEvent(new CustomEvent("manualClosePopup")),this.handleCloseWidget()}disconnectedCallback(){var e;this.countdownTimer&&clearInterval(this.countdownTimer),null===(e=this.stylingSubscription)||void 0===e||e.unsubscribe()}async componentWillLoad(){this.translationUrl.length>2&&await n(this.translationUrl)}componentDidLoad(){this.stylingContainer&&(null!=window.emMessageBuss?function(e,t){if(window.emMessageBus){const i=document.createElement("style");window.emMessageBus.subscribe(t,(t=>{i.innerHTML=t,e&&e.appendChild(i)}))}}(this.stylingContainer,`${this.mbSource}.Style`):(this.clientStyling&&o(this.stylingContainer,this.clientStyling),this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)))}render(){return t("div",{key:"9afac9d2e248a06828ce17dcb8dc6902fe4ec8cf",ref:e=>this.stylingContainer=e},this.showPopup&&t("div",{key:"48bab2747dcba4c64cb97a973a5f9961856126b8",class:"OtpPopupOverlay"},t("div",{key:"89c38b7dbeb7a151f3c172d6913ea2e6884f2c40",class:"OtpPopupContent"},this.isLoading?t("div",{class:"OtpLoaderContainer"},t("span",{class:"OtpLoader"})):this.hasConfigErrors?t("div",{class:"OtpError"},t("div",{class:"OtpErrorHeader"},t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"})),t("h2",null,l("errorHeader",this.language))),t("p",null,this.errorMessage),t("button",{class:"OtpButton error",onClick:this.manualClosePopup},l("close",this.language))):t(i,null,t("div",{class:"otp-description"},this.showResendOtp?t("p",{class:"OtpNoticeMessage",role:"alert"},l("otpExpiredMessage",this.language)):t(i,null,t("p",{class:this.isLastWarning?"LastWarningMessage":""},l(this.isLastWarning?"popupMessageLastWarning":"popupMessage",this.language)),this.hasErrors&&t("p",{class:"OtpErrorMessage",role:"alert"},this.errorMessage))),t("div",{class:"OtpFieldWrapper"},t("h2",null,l("otpHeading",this.language)),t("div",{class:"OtpField",ref:this.setOtpContainerRef},this.otp.map(((e,i)=>t("input",{key:i,ref:e=>this.setOtpInputRef(e,i),id:`otp-input-${i}`,type:"text",class:"otp-box "+(this.config.inputLength%2==0&&i===this.config.inputLength/2-1?"space":""),maxLength:1,value:e,onInput:e=>this.handleOtpInput(e,i),onKeyDown:e=>this.handleKeyDown(e,i),onPaste:e=>this.handleOnPasteOtp(e),disabled:this.timeLeft<=0})))),t("div",{class:"otp-timer"},this.formatTime(this.timeLeft)," ",l("minutes",this.language))),t("div",{class:"OtpActionButtons"},this.showResendOtp?t("button",{class:"OtpButton",onClick:this.handleResendOtp},l("resendOtp",this.language)):t("button",{class:"OtpButton",onClick:this.submitOtp,disabled:this.otp.join("").length!==this.config.inputLength},l("submit",this.language)),t("button",{class:"OtpButton",onClick:this.manualClosePopup},l("close",this.language)))))))}get el(){return r(this)}static get watchers(){return{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}}};d.style=".OtpPopupOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--emw--color-overlay, rgba(0, 0, 0, 0.5));display:flex;align-items:center;justify-content:center}.OtpButton{font-family:var(--emw--button-typography);border:var(--emw--button-border, none);border-radius:var(--emw--button-border-radius, 3px);border-color:var(--emw--button-border-color);background-color:var(--emw--button-background-color, var(--emw--color-primary, #007bff));color:var(--emw--button-typography, var(--emw--color-white, #fff));padding:10px 20px;cursor:pointer;font-size:16px}.OtpButton.error{background:var(--emw--color-error, #dd3434)}.OtpPopupContent{position:relative;background:var(--emw--color-white, #fff);padding:20px;border-radius:5px;text-align:center;min-width:25%;min-height:200px;display:flex;flex-direction:column;justify-content:center;gap:20px}.OtpPopupContent .OtpError{display:flex;flex-direction:column;gap:20px;align-items:center}.OtpPopupContent .OtpError .OtpErrorHeader{display:flex;justify-content:center;gap:5px}.OtpPopupContent .OtpError h2{margin:0}.OtpPopupContent .OtpError svg{width:25px;fill:var(--emw--color-error, #dd3434)}.OtpFieldWrapper{display:flex;flex-direction:column;gap:10px}.OtpFieldWrapper h2{margin:0}.OtpField{display:flex;justify-content:center}.OtpField input{width:24px;font-size:32px;padding:10px;text-align:center;border-radius:5px;margin:2px;border:2px solid var(--emw--otp-border-color, #55525c);font-weight:bold;outline:none;transition:all 0.1s}.OtpField input.space{margin-right:1rem !important}.OtpField input:focus{border:2px solid var(--emw--color-primary, #007bff);box-shadow:0 0 2px 2px var(--emw--color-primary, #007bff)}.OtpActionButtons{display:flex;justify-content:space-between}.OtpErrorMessage{color:var(--emw--color-error, #dd3434);font-weight:bold}.OtpLoaderContainer{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.OtpLoader{width:48px;height:48px;border:5px solid var(--emw--color-secondary, #b3d8ff);border-bottom-color:var(--emw--color-primary, #007bff);border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";export{d as P}
|
|
1
|
+
import{r as e,h as t,F as i,g as o}from"./index-c6eee6d8.js";function r(e,t){if(e){const i=document.createElement("style");i.innerHTML=t,e.appendChild(i)}}function a(e,t){const i=new URL(t);fetch(i.href).then((e=>e.text())).then((t=>{const i=document.createElement("style");i.innerHTML=t,e&&e.appendChild(i)})).catch((e=>{console.error("There was an error while trying to load client styling from URL",e)}))}const s={en:{popupMessage:"Please enter the security code received on your email address to perform the update.",popupMessageLastWarning:"If the next validation attempt is failed, you will be logged out and blocked temporarily.",minutes:"minutes",errorHeader:"Error",configError:"Unable to load OTP data. Please try again later.",otpHeading:"Enter OTP",resendOtp:"Resent OTP",submit:"Submit",close:"Close",invalidOtp:"The code you've sent is not valid. Please try again.",accountBlocked:"Too many attempts for OTP. Your account has been blocked for one hour.",submissionError:"Something went wrong. Please try again.",otpExpiredMessage:"Validation code has expired, please request a new one to continue."},ro:{popupMessage:"Introduceți codul de securitate primit pe adresa dvs. de e-mail pentru a efectua actualizarea.",popupMessageLastWarning:"Dacă următoarea încercare de validare eșuează, veți fi delogat și blocat temporar.",minutes:"minute",errorHeader:"Eroare",configError:"Nu s-a putut încărca datele OTP. Vă rugăm să încercați din nou mai târziu.",otpHeading:"Introduceți OTP",resendOtp:"Retrimitere OTP",submit:"Trimite",close:"Închide",invalidOtp:"Codul introdus nu este valid. Vă rugăm să încercați din nou.",accountBlocked:"Prea multe încercări de OTP. Contul dvs. a fost blocat timp de o oră.",submissionError:"Ceva a mers prost. Vă rugăm să încercați din nou.",otpExpiredMessage:"Codul de validare a expirat, vă rugăm să solicitați unul nou pentru a continua."},fr:{popupMessage:"Veuillez entrer le code de sécurité reçu sur votre adresse e-mail pour effectuer la mise à jour.",popupMessageLastWarning:"Si la prochaine tentative de validation échoue, vous serez déconnecté et temporairement bloqué.",minutes:"minutes",errorHeader:"Erreur",configError:"Impossible de charger les données OTP. Veuillez réessayer plus tard.",otpHeading:"Entrez OTP",resendOtp:"Renvoyer OTP",submit:"Soumettre",close:"Fermer",invalidOtp:"Le code que vous avez saisi n’est pas valide. Veuillez réessayer.",accountBlocked:"Trop de tentatives OTP. Votre compte a été bloqué pendant une heure.",submissionError:"Quelque chose s'est mal passé. Veuillez réessayer.",otpExpiredMessage:"Le code de validation a expiré, veuillez en demander un nouveau pour continuer."},hu:{popupMessage:"Kérjük, adja meg az e-mail címére küldött biztonsági kódot a frissítés végrehajtásához.",popupMessageLastWarning:"Ha a következő érvényesítési kísérlet sikertelen, ki lesz jelentkeztetve és ideiglenesen letiltva.",minutes:"perc",errorHeader:"Hiba",configError:"Nem sikerült betölteni az OTP adatokat. Kérjük, próbálja újra később.",otpHeading:"OTP megadása",resendOtp:"Újraküldés",submit:"Beküldés",close:"Bezárás",invalidOtp:"A megadott kód érvénytelen. Kérjük, próbálja újra.",accountBlocked:"Túl sok OTP próbálkozás. A fiókja egy órára zárolva lett.",submissionError:"Valami hiba történt. Kérjük, próbálja újra.",otpExpiredMessage:"A megerősítő kód lejárt, kérjük, kérjen egy újat a folytatáshoz."},tr:{popupMessage:"Güncellemeyi gerçekleştirmek için e-posta adresinize gelen güvenlik kodunu girin.",popupMessageLastWarning:"Bir sonraki doğrulama girişimi başarısız olursa, oturumunuz kapatılacak ve geçici olarak engelleneceksiniz.",minutes:"dakika",errorHeader:"Hata",configError:"OTP verisi yüklenemedi. Lütfen daha sonra tekrar deneyin.",otpHeading:"OTP Girin",resendOtp:"OTP'yi Yeniden Gönder",submit:"Gönder",close:"Kapat",invalidOtp:"Gönderdiğiniz kod geçersiz. Lütfen tekrar deneyin.",accountBlocked:"Çok fazla OTP denemesi yapıldı. Hesabınız bir saat boyunca kilitlendi.",submissionError:"Bir şeyler yanlış gitti. Lütfen tekrar deneyin.",otpExpiredMessage:"Doğrulama kodunun süresi doldu, devam etmek için lütfen yeni bir tane isteyin."},el:{popupMessage:"Παρακαλώ εισάγετε τον κωδικό ασφαλείας που λάβατε στο email σας για να ολοκληρώσετε την ενημέρωση.",popupMessageLastWarning:"Αν η επόμενη προσπάθεια επικύρωσης αποτύχει, θα αποσυνδεθείτε και θα αποκλειστείτε προσωρινά.",minutes:"λεπτά",errorHeader:"Σφάλμα",configError:"Δεν ήταν δυνατή η φόρτωση των δεδομένων OTP. Παρακαλούμε προσπαθήστε ξανά αργότερα.",otpHeading:"Εισαγωγή OTP",resendOtp:"Αποστολή ξανά OTP",submit:"Υποβολή",close:"Κλείσιμο",invalidOtp:"Ο κωδικός που εισαγάγατε δεν είναι έγκυρος. Παρακαλώ προσπαθήστε ξανά.",accountBlocked:"Πάρα πολλές προσπάθειες OTP. Ο λογαριασμός σας έχει αποκλειστεί για μία ώρα.",submissionError:"Κάτι πήγε στραβά. Παρακαλώ προσπαθήστε ξανά.",otpExpiredMessage:"Ο κωδικός επαλήθευσης έχει λήξει, παρακαλώ ζητήστε έναν νέο για να συνεχίσετε."},es:{popupMessage:"Por favor, introduzca el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudo cargar los datos del OTP. Por favor, inténtelo de nuevo más tarde.",otpHeading:"Introducir OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresaste no es válido. Por favor, inténtalo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},pt:{popupMessage:"Por favor, insira o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, será desconectado e temporariamente bloqueado.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Insira o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código inserido não é válido. Por favor, tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."},hr:{popupMessage:"Unesite sigurnosni kod primljen na vašu e-mail adresu kako biste izvršili ažuriranje.",popupMessageLastWarning:"Ako sljedeći pokušaj provjere ne uspije, bit ćete odjavljeni i privremeno blokirani.",minutes:"minute",errorHeader:"Greška",configError:"Nije moguće učitati OTP podatke. Pokušajte ponovno kasnije.",otpHeading:"Unesite OTP",resendOtp:"Ponovno pošalji OTP",submit:"Pošalji",close:"Zatvori",invalidOtp:"Uneseni kod nije valjan. Molimo pokušajte ponovo.",accountBlocked:"Previše pokušaja unosa OTP-a. Vaš račun je blokiran na jedan sat.",submissionError:"Nešto je pošlo po zlu. Molimo pokušajte ponovo.",otpExpiredMessage:"Kod za potvrdu je istekao, molimo zatražite novi kako biste nastavili."},de:{popupMessage:"Bitte geben Sie den Sicherheitscode ein, den Sie an Ihre E-Mail-Adresse erhalten haben, um das Update durchzuführen.",popupMessageLastWarning:"Wenn der nächste Validierungsversuch fehlschlägt, werden Sie abgemeldet und vorübergehend gesperrt.",minutes:"Minuten",errorHeader:"Fehler",configError:"OTP-Daten konnten nicht geladen werden. Bitte versuchen Sie es später erneut.",otpHeading:"OTP eingeben",resendOtp:"OTP erneut senden",submit:"Absenden",close:"Schließen",invalidOtp:"Der eingegebene Code ist ungültig. Bitte versuchen Sie es erneut.",accountBlocked:"Zu viele OTP-Versuche. Ihr Konto wurde für eine Stunde gesperrt.",submissionError:"Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.",otpExpiredMessage:"Der Bestätigungscode ist abgelaufen, bitte fordern Sie einen neuen an, um fortzufahren."},"es-mx":{popupMessage:"Por favor, ingrese el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudieron cargar los datos del OTP. Inténtelo de nuevo más tarde.",otpHeading:"Ingrese OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresó no es válido. Inténtelo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},"pt-br":{popupMessage:"Por favor, digite o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, você será desconectado e bloqueado temporariamente.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Digite o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código informado não é válido. Tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."}},n=e=>new Promise((t=>{fetch(e).then((e=>e.json())).then((e=>{Object.keys(e).forEach((t=>{for(let i in e[t])s[t][i]=e[t][i]})),t(!0)}))})),d=(e,t)=>s[void 0!==t?t:"en"][e],l=class{handleNewTranslations(){n(this.translationUrl)}handleClientStylingChange(e,t){e!==t&&r(this.el,this.clientStyling)}handleClientStylingUrlChange(e,t){e!=t&&this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)}async handleStepUpAuthEvent(e){var t;if(null===(t=e.detail)||void 0===t?void 0:t["x-step-up-required"]){if(this.hasConfigErrors=!1,this.hasErrors=!1,this.errorMessage="",this.showPopup=!0,this.token=e.detail["x-step-up-token"],this.flow=e.detail.flow,!this.token||!this.flow)return this.isLoading=!1,this.hasConfigErrors=!0,void(this.errorMessage=d("configError",this.language));await this.getConfig()}}handleCloseWidget(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null),this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.showPopup=!1,this.isLastWarning=!1}constructor(t){e(this,t),this.otpInputs=[],this.countdownTimer=null,this.expirationTimestamp=0,this.mbSource=void 0,this.clientStyling=void 0,this.clientStylingUrl=void 0,this.language="en",this.endpoint=void 0,this.userSession=void 0,this.translationUrl="",this.showPopup=!1,this.otp=void 0,this.isLoading=!0,this.config=null,this.timeLeft=0,this.expirationTime="",this.serverTime="",this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.token="",this.flow="",this.showResendOtp=!1,this.isLastWarning=!1,this.inputDisabled=!1,this.handleResendOtp=this.handleResendOtp.bind(this),this.submitOtp=this.submitOtp.bind(this),this.handleCloseWidget=this.handleCloseWidget.bind(this),this.manualClosePopup=this.manualClosePopup.bind(this)}async getConfig(){if(this.endpoint)try{const e=new URL(`/api/v1/mfa/challenge/${this.token}/config`,this.endpoint);this.isLoading=!0;const t=await fetch(e.href),i=await t.json();if(t.ok)this.config=i,this.otp=Array(this.config.inputLength).fill(""),this.isLoading=!1,this.showResendOtp=!1,this.expirationTime=this.config.expirationTime,this.serverTime=this.config.serverTime,0!==this.config.numberOfValidateAttempts&&(this.hasErrors=!0,this.errorMessage=d("invalidOtp",this.language)),this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1&&(this.isLastWarning=!0),this.calculateTimeLeft(),this.startCountdown();else{if(!i||"gm.twofa.token_max_attempts_exceeded"!==i.details){const e=i&&i.message||`Failed to load config. Status: ${t.status}`;throw new Error(e)}this.handleCloseWidget()}}catch(e){this.isLoading=!1,this.hasConfigErrors=!0,this.errorMessage=d("configError",this.language),console.error("Error loading 2FA config:",e)}}calculateTimeLeft(){const e=new Date(this.expirationTime),t=new Date(this.serverTime),i=new Date,o=t.getTime()-i.getTime();this.expirationTimestamp=e.getTime()-o;const r=Date.now(),a=Math.max(0,Math.floor((this.expirationTimestamp-r)/1e3));this.timeLeft=a}startCountdown(){this.countdownTimer&&clearInterval(this.countdownTimer),this.countdownTimer=setInterval((()=>{const e=Date.now(),t=Math.max(0,Math.floor((this.expirationTimestamp-e)/1e3));this.timeLeft=t,this.inputDisabled=t<=0,t<=0&&(clearInterval(this.countdownTimer),this.countdownTimer=null,this.showResendOtp=!0,this.hasErrors=!1,this.isLastWarning=!1)}),1e3)}formatTime(e){const t=e%60;return`${Math.floor(e/60).toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}setOtpInputRef(e,t){e&&(this.otpInputs[t]=e)}updateOtpState(e,t){const i=[...this.otp];i[e]=t.toUpperCase(),this.otp=i}handleOnPasteOtp(e){var t,i,o;e.preventDefault();const r=((null===(i=null===(t=e.clipboardData)||void 0===t?void 0:t.getData("text"))||void 0===i?void 0:i.trim())||"").slice(0,this.config.inputLength).split("");this.otp=[...r,...Array(this.config.inputLength-r.length).fill("")],null===(o=this.otpInputs[r.length])||void 0===o||o.focus(),r.length===this.config.inputLength&&this.submitOtp()}handleOtpInput(e,t){const i=e.target,o=i.value;if(/^[a-z0-9]$/i.test(o)){this.updateOtpState(t,o);const e=this.otpInputs[t+1];null==e||e.focus()}i.value=""}handleKeyDown(e,t){const i=e.key,o=e.ctrlKey||e.metaKey;if(/^[a-z0-9]$/i.test(i)){if(o&&"v"===i.toLowerCase())return;e.preventDefault(),this.updateOtpState(t,i);const r=this.otpInputs[t+1];null==r||r.focus()}else if("Backspace"===i){e.preventDefault(),""!==this.otp[t]&&this.updateOtpState(t,"");const i=this.otpInputs[t-1];null==i||i.focus()}}handleResendOtp(){const e=new CustomEvent("otpResendRequested");window.dispatchEvent(e)}async submitOtp(){if(this.otp.join("").length!==this.config.inputLength)return this.hasErrors=!0,void(this.errorMessage=d("invalidOtp",this.language));this.isLoading=!0,this.hasErrors=!1,this.errorMessage="";const e=this.otp.join("");"stateless"===this.flow&&this.handleOtpStateless(e),"stateful"===this.flow&&await this.handleOtpStateful(e)}handleOtpStateless(e){window.dispatchEvent(new CustomEvent("otpSubmitted",{detail:{code:e,maxAttempts:this.config.maxValidationAttempts,validatedAttempts:this.config.numberOfValidateAttempts}}))}async handleOtpStateful(e){const t=new URL(`/api/v1/mfa/challenge/${this.token}/validate`,this.endpoint);t.searchParams.append("input",e);try{const e=await fetch(t.href,{method:"POST"});if(200===e.status)return void this.handleSuccess();const i=await e.json();throw new Error(i.message)}catch(e){if("gm.multifactorauthentication.internal_server_error"===e.message)return this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1?(window.dispatchEvent(new CustomEvent("otpSetTimeout")),window.postMessage({type:"WidgetNotification",data:{type:"error",message:d("accountBlocked",this.language)}},window.location.href),void this.handleCloseWidget()):(this.hasErrors=!0,this.errorMessage=d("invalidOtp",this.language),void this.getConfig());console.error("OTP submission failed:",e),this.hasErrors=!0,this.errorMessage=d("submissionError",this.language)}finally{this.isLoading=!1}}handleSuccess(){window.dispatchEvent(new CustomEvent("otpSuccess",{detail:{message:"User successfully authenticated"}})),this.handleCloseWidget()}manualClosePopup(){window.dispatchEvent(new CustomEvent("manualClosePopup")),this.handleCloseWidget()}disconnectedCallback(){var e;this.countdownTimer&&clearInterval(this.countdownTimer),null===(e=this.stylingSubscription)||void 0===e||e.unsubscribe()}async componentWillLoad(){this.translationUrl.length>2&&await n(this.translationUrl)}componentDidLoad(){this.stylingContainer&&(null!=window.emMessageBuss?function(e,t){if(window.emMessageBus){const i=document.createElement("style");window.emMessageBus.subscribe(t,(t=>{i.innerHTML=t,e&&e.appendChild(i)}))}}(this.stylingContainer,`${this.mbSource}.Style`):(this.clientStyling&&r(this.stylingContainer,this.clientStyling),this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)))}render(){return t("div",{key:"481fb2d579925de2fb472f3d715712625fb7aba9",ref:e=>this.stylingContainer=e},this.showPopup&&t("div",{key:"d9d55ab487c8bd11ed72d18e7eed49fdb59bab8b",class:"OtpPopupOverlay"},t("div",{key:"c42458b9f43f03dd88cb9ec8706826739cb2ee4c",class:"OtpPopupContent"},this.isLoading?t("div",{class:"OtpLoaderContainer"},t("span",{class:"OtpLoader"})):this.hasConfigErrors?t("div",{class:"OtpError"},t("div",{class:"OtpErrorHeader"},t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"})),t("h2",null,d("errorHeader",this.language))),t("p",null,this.errorMessage),t("button",{class:"OtpButton error",onClick:this.manualClosePopup},d("close",this.language))):t(i,null,t("div",{class:"otp-description"},this.showResendOtp?t("p",{class:"OtpNoticeMessage",role:"alert"},d("otpExpiredMessage",this.language)):t(i,null,t("p",{class:this.isLastWarning?"LastWarningMessage":""},d(this.isLastWarning?"popupMessageLastWarning":"popupMessage",this.language)),this.hasErrors&&t("p",{class:"OtpErrorMessage",role:"alert"},this.errorMessage))),t("div",{class:"OtpFieldWrapper"},t("h2",null,d("otpHeading",this.language)),t("div",{class:"OtpField"},this.otp.map(((e,i)=>t("input",{key:i,ref:e=>this.setOtpInputRef(e,i),id:`otp-input-${i}`,type:"text",class:"otp-box "+(this.config.inputLength%2==0&&i===this.config.inputLength/2-1?"space":""),maxLength:1,value:e,onInput:e=>this.handleOtpInput(e,i),onKeyDown:e=>this.handleKeyDown(e,i),onPaste:e=>this.handleOnPasteOtp(e),disabled:this.inputDisabled,autoComplete:"off"})))),t("div",{class:"otp-timer"},this.formatTime(this.timeLeft)," ",d("minutes",this.language))),t("div",{class:"OtpActionButtons"},this.showResendOtp?t("button",{class:"OtpButton",onClick:this.handleResendOtp},d("resendOtp",this.language)):t("button",{class:"OtpButton",onClick:this.submitOtp,disabled:this.otp.join("").length!==this.config.inputLength},d("submit",this.language)),t("button",{class:"OtpButton",onClick:this.manualClosePopup},d("close",this.language)))))))}get el(){return o(this)}static get watchers(){return{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}}};l.style=".OtpPopupOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--emw--color-overlay, rgba(0, 0, 0, 0.5));display:flex;align-items:center;justify-content:center}.OtpButton{font-family:var(--emw--button-typography);border:var(--emw--button-border, none);border-radius:var(--emw--button-border-radius, 3px);border-color:var(--emw--button-border-color);background-color:var(--emw--button-background-color, var(--emw--color-primary, #007bff));color:var(--emw--button-typography, var(--emw--color-white, #fff));padding:10px 20px;cursor:pointer;font-size:16px}.OtpButton.error{background:var(--emw--color-error, #dd3434)}.OtpPopupContent{position:relative;background:var(--emw--color-white, #fff);padding:20px;border-radius:5px;text-align:center;min-width:25%;min-height:200px;display:flex;flex-direction:column;justify-content:center;gap:20px}.OtpPopupContent .OtpError{display:flex;flex-direction:column;gap:20px;align-items:center}.OtpPopupContent .OtpError .OtpErrorHeader{display:flex;justify-content:center;gap:5px}.OtpPopupContent .OtpError h2{margin:0}.OtpPopupContent .OtpError svg{width:25px;fill:var(--emw--color-error, #dd3434)}.OtpFieldWrapper{display:flex;flex-direction:column;gap:10px}.OtpFieldWrapper h2{margin:0}.OtpField{display:flex;justify-content:center}.OtpField input{width:24px;font-size:32px;padding:10px;text-align:center;border-radius:5px;margin:2px;border:2px solid var(--emw--otp-border-color, #55525c);font-weight:bold;outline:none;transition:all 0.1s}.OtpField input.space{margin-right:1rem !important}.OtpField input:focus{border:2px solid var(--emw--color-primary, #007bff);box-shadow:0 0 2px 2px var(--emw--color-primary, #007bff)}.OtpActionButtons{display:flex;justify-content:space-between}.OtpErrorMessage{color:var(--emw--color-error, #dd3434);font-weight:bold}.OtpLoaderContainer{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.OtpLoader{width:48px;height:48px;border:5px solid var(--emw--color-secondary, #b3d8ff);border-bottom-color:var(--emw--color-primary, #007bff);border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";export{l as P}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{P as player_step_up_auth}from"./player-step-up-auth-
|
|
1
|
+
export{P as player_step_up_auth}from"./player-step-up-auth-e624c40c.js";import"./index-c6eee6d8.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{p as e,b as n}from"./index-c6eee6d8.js";export{s as setNonce}from"./index-c6eee6d8.js";import{g as t}from"./app-globals-0f993ce5.js";(()=>{const n=import.meta.url,t={};return""!==n&&(t.resourcesUrl=new URL(".",n).href),e(t)})().then((async e=>(await t(),n([["player-step-up-auth",[[1,"player-step-up-auth",{mbSource:[513,"mb-source"],clientStyling:[513,"client-styling"],clientStylingUrl:[513,"client-styling-url"],language:[513],endpoint:[513],userSession:[513,"user-session"],translationUrl:[513,"translation-url"],showPopup:[32],otp:[32],isLoading:[32],config:[32],timeLeft:[32],expirationTime:[32],serverTime:[32],hasErrors:[32],hasConfigErrors:[32],errorMessage:[32],token:[32],flow:[32],showResendOtp:[32],isLastWarning:[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}]]]],e))));
|
|
1
|
+
import{p as e,b as n}from"./index-c6eee6d8.js";export{s as setNonce}from"./index-c6eee6d8.js";import{g as t}from"./app-globals-0f993ce5.js";(()=>{const n=import.meta.url,t={};return""!==n&&(t.resourcesUrl=new URL(".",n).href),e(t)})().then((async e=>(await t(),n([["player-step-up-auth",[[1,"player-step-up-auth",{mbSource:[513,"mb-source"],clientStyling:[513,"client-styling"],clientStylingUrl:[513,"client-styling-url"],language:[513],endpoint:[513],userSession:[513,"user-session"],translationUrl:[513,"translation-url"],showPopup:[32],otp:[32],isLoading:[32],config:[32],timeLeft:[32],expirationTime:[32],serverTime:[32],hasErrors:[32],hasConfigErrors:[32],errorMessage:[32],token:[32],flow:[32],showResendOtp:[32],isLastWarning:[32],inputDisabled:[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}]]]],e))));
|
|
@@ -42,9 +42,9 @@ export declare class PlayerStepUpAuth {
|
|
|
42
42
|
flow: string;
|
|
43
43
|
showResendOtp: boolean;
|
|
44
44
|
isLastWarning: boolean;
|
|
45
|
+
inputDisabled: boolean;
|
|
45
46
|
private stylingContainer;
|
|
46
47
|
private stylingSubscription;
|
|
47
|
-
private otpContainer;
|
|
48
48
|
private otpInputs;
|
|
49
49
|
private countdownTimer;
|
|
50
50
|
private expirationTimestamp;
|
|
@@ -89,9 +89,10 @@ export declare class PlayerStepUpAuth {
|
|
|
89
89
|
*/
|
|
90
90
|
constructor();
|
|
91
91
|
/**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
* Fetches OTP configuration from the endpoint.
|
|
93
|
+
* Updates the OTP state, expiration time, and starts the countdown timer.
|
|
94
|
+
* Handles specific errors like max attempts exceeded by closing the widget.
|
|
95
|
+
*/
|
|
95
96
|
getConfig(): Promise<void>;
|
|
96
97
|
/**
|
|
97
98
|
* Calculates the remaining time for OTP expiration.
|
|
@@ -111,17 +112,19 @@ export declare class PlayerStepUpAuth {
|
|
|
111
112
|
*/
|
|
112
113
|
formatTime(seconds: number): string;
|
|
113
114
|
/**
|
|
114
|
-
* Sets a reference to the OTP
|
|
115
|
+
* Sets a reference to the OTP inputs.
|
|
115
116
|
*
|
|
116
117
|
* @param el - The OTP input container element.
|
|
117
118
|
*/
|
|
118
|
-
|
|
119
|
+
setOtpInputRef(el: HTMLInputElement | null, index: number): void;
|
|
119
120
|
/**
|
|
120
|
-
*
|
|
121
|
+
* update otp state
|
|
122
|
+
* by creating new array and assign to state, to make the UI trigger
|
|
121
123
|
*
|
|
122
|
-
* @param
|
|
124
|
+
* @param index - The index of the input field being updated.
|
|
125
|
+
* @param value - The inputted value.
|
|
123
126
|
*/
|
|
124
|
-
|
|
127
|
+
updateOtpState(index: number, value: string): void;
|
|
125
128
|
/**
|
|
126
129
|
* Handles pasting an OTP directly into the input fields.
|
|
127
130
|
* Extracts characters from the clipboard and populates the OTP fields.
|
|
@@ -181,8 +184,8 @@ export declare class PlayerStepUpAuth {
|
|
|
181
184
|
*/
|
|
182
185
|
disconnectedCallback(): void;
|
|
183
186
|
/**
|
|
184
|
-
|
|
185
|
-
|
|
187
|
+
* Lifecycle method: Fetch translations on component load
|
|
188
|
+
*/
|
|
186
189
|
componentWillLoad(): Promise<void>;
|
|
187
190
|
/**
|
|
188
191
|
* Lifecycle method: Set up event listeners after the component is rendered
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|