diff --git a/client/dist/js/bundle-cms.js b/client/dist/js/bundle-cms.js index 4bbe70bd..a17b24a5 100644 --- a/client/dist/js/bundle-cms.js +++ b/client/dist/js/bundle-cms.js @@ -1 +1 @@ -!function(){var e={189:function(e,t,n){"use strict";var o=i(n(460)),r=i(n(7355)),a=i(n(941));function i(e){return e&&e.__esModule?e:{default:e}}window.document.addEventListener("DOMContentLoaded",(()=>{(0,o.default)(),(0,r.default)(),(0,a.default)()}))},460:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=l(n(6648)),r=l(n(440)),a=l(n(6021)),i=l(n(9521));function l(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{(0,i.default)(),o.default.component.registerMany({MFARegister:r.default,RegisteredMFAMethodListField:a.default})}},7355:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(6648)),r=i(n(6683)),a=i(n(4180));function i(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{(0,a.default)(),o.default.reducer.register("mfaAdministration",r.default)}},941:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=a(n(6648)),r=a(n(3311));function a(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{o.default.transform("apply-sudo-mode-to-mfa",(e=>{e.component("RegisteredMFAMethodListField",r.default)}))}},9521:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(9487)),r=i(n(1284)),a=i(n(6648));function i(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{a.default.component.registerMany({BackupCodeRegister:o.default,BackupCodeVerify:r.default})}},4180:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(6648)),r=i(n(7286)),a=i(n(23));function i(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{o.default.reducer.register("mfaRegister",r.default),o.default.reducer.register("mfaVerify",a.default)}},9487:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=s(n(7086)),a=s(n(9768)),i=n(4855),l=n(1661);function s(e){return e&&e.__esModule?e:{default:e}}function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}class c extends o.Component{constructor(e){super(e),this.state={recentlyCopied:!1},this.printRef=null,this.setPrintRef=e=>{this.printRef=e},this.copyMessageTimeout=null,this.handlePrint=this.handlePrint.bind(this),this.handleCopy=this.handleCopy.bind(this)}getFormattedCodes(){const{codes:e}=this.props;return e.map((e=>(0,l.formatCode)(e)))}handlePrint(e){e.preventDefault(),(new a.default).print(this.printRef,['body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif }'])}handleCopy(e){e.preventDefault();const{copyFeedbackDuration:t}=this.props;this.setState({recentlyCopied:!0}),this.copyMessageTimeout&&clearTimeout(this.copyMessageTimeout),this.copyMessageTimeout=setTimeout((()=>{this.setState({recentlyCopied:!1})}),t)}renderCodes(){return o.default.createElement("pre",{ref:this.setPrintRef,className:"mfa-register-backup-codes__code-grid"},this.getFormattedCodes().map((e=>o.default.createElement("div",{key:e},e))))}renderDescription(){const{ss:{i18n:e}}=window,{method:{supportLink:t,supportText:n}}=this.props;return o.default.createElement("p",null,e._t("MFABackupCodesRegister.DESCRIPTION","Recovery codes enable you to log into your account in the event your primary authentication is not available. Each code can only be used once. Store these codes somewhere safe, as they will not be viewable after leaving this page.")," ",t&&o.default.createElement("a",{href:t,target:"_blank",rel:"noopener noreferrer"},n||e._t("MFARegister.RECOVERY_HELP","Learn more about recovery codes.")))}renderPrintAction(){const{ss:{i18n:e}}=window;return o.default.createElement("button",{type:"button",onClick:this.handlePrint,className:"btn btn-link"},e._t("MFABackupCodesRegister.PRINT","Print codes"))}renderDownloadAction(){const{codes:e,method:t}=this.props,{Blob:n,URL:r,ss:{i18n:a},navigator:i}=window,l=`${t.name}.txt`,s=new n([e.join("\r\n")],{type:"text/plain;charset=UTF-8"}),u=r.createObjectURL(s);return o.default.createElement("a",{download:l,href:u,className:"btn btn-link",onClick:e=>{i.msSaveBlob&&(e.preventDefault(),i.msSaveBlob(s,l))}},a._t("MFABackupCodesRegister.DOWNLOAD","Download"))}renderCopyAction(){const{codes:e}=this.props,{recentlyCopied:t}=this.state,{ss:{i18n:n}}=window,r=t?n._t("MFABackupCodesRegister.COPY_RECENT","Copied!"):n._t("MFABackupCodesRegister.COPY","Copy codes");return o.default.createElement(i.CopyToClipboard,{text:e.join("\n")},o.default.createElement("button",{type:"button",className:"mfa-register-backup-codes__copy-to-clipboard btn btn-link",onClick:this.handleCopy},r))}render(){const{onCompleteRegistration:e}=this.props,{ss:{i18n:t}}=window;return o.default.createElement("div",{className:"mfa-register-backup-codes__container"},this.renderDescription(),this.renderCodes(),o.default.createElement("div",{className:"mfa-register-backup-codes__helper-links"},this.renderPrintAction(),this.renderDownloadAction(),this.renderCopyAction()),o.default.createElement("button",{className:"btn btn-primary",onClick:()=>e()},t._t("MFABackupCodesRegister.FINISH","Finish")))}}c.propTypes={codes:r.default.arrayOf(r.default.string),copyFeedbackDuration:r.default.number},c.defaultProps={copyFeedbackDuration:3e3};t.default=c},1284:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=i(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var l=r?Object.getOwnPropertyDescriptor(e,a):null;l&&(l.get||l.set)?Object.defineProperty(o,a,l):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),a=(o=n(7820))&&o.__esModule?o:{default:o};function i(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(i=function(e){return e?n:t})(e)}class l extends r.Component{constructor(e){super(e),this.state={value:""},this.codeInput=r.default.createRef(),this.handleChange=this.handleChange.bind(this),this.handleCompleteVerification=this.handleCompleteVerification.bind(this)}componentDidMount(){this.codeInput.current&&this.codeInput.current.focus()}handleChange(e){this.setState({value:e.target.value})}handleCompleteVerification(e){e.preventDefault();const{onCompleteVerification:t}=this.props;t({code:this.state.value})}renderControls(){const{moreOptionsControl:e}=this.props,{ss:{i18n:t}}=window;return r.default.createElement("ul",{className:"mfa-action-list mfa-action-list--backup-codes"},r.default.createElement("li",{className:"mfa-action-list__item"},r.default.createElement("button",{className:"btn btn-primary",disabled:0===this.state.value.length,onClick:this.handleCompleteVerification},t._t("MFABackupCodesVerify.NEXT","Next"))),e&&r.default.createElement("li",{className:"mfa-action-list__item"},e))}renderDescription(){const{ss:{i18n:e}}=window,{method:t}=this.props;return r.default.createElement("p",null,e._t("MFABackupCodesVerify.DESCRIPTION","Use one of the recovery codes you received")," ",t&&t.supportLink&&r.default.createElement("a",{href:t.supportLink,target:"_blank",rel:"noopener noreferrer"},e._t("MFARegister.RECOVERY_HELP","How to use recovery codes.")))}renderInput(){const{error:e}=this.props,{ss:{i18n:t}}=window,n=t._t("MFABackupCodesVerify.LABEL","Enter recovery code"),o=(0,a.default)("mfa-verify-backup-codes__input-container",{"has-error":!!e});return r.default.createElement("div",{className:o},r.default.createElement("label",{htmlFor:"backup-code",className:"control-label"},n),r.default.createElement("input",{className:"mfa-verify-backup-codes__input text form-control",type:"text",placeholder:n,id:"backup-code",ref:this.codeInput,onChange:this.handleChange}),e&&r.default.createElement("div",{className:"help-block"},e))}render(){const{graphic:e,name:t}=this.props;return r.default.createElement("form",{className:"mfa-verify-backup-codes__container"},r.default.createElement("div",{className:"mfa-verify-backup-codes__content"},this.renderDescription(),this.renderInput()),r.default.createElement("div",{className:"mfa-verify-backup-codes__image-holder"},r.default.createElement("img",{className:"mfa-verify-backup-codes__image",src:e,alt:t})),this.renderControls())}}t.default=l},2469:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=h(n(7086)),r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=f(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),a=h(n(4510)),i=h(n(42)),l=h(n(3141)),s=h(n(5292)),u=h(n(1820)),c=h(n(3947)),d=(h(n(5666)),h(n(7462)));function f(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(f=function(e){return e?n:t})(e)}function h(e){return e&&e.__esModule?e:{default:e}}class p extends r.Component{constructor(e){super(e),this.state={complete:!1,failed:!1,submitting:!1},this.handleSendReset=this.handleSendReset.bind(this)}async handleSendReset(){const{ss:{i18n:e}}=window,t=e._t("MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION",d.default["MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION"]),n=e._t("MultiFactorAuthentication.CONFIRMATION_TITLE",d.default["MultiFactorAuthentication.CONFIRMATION_TITLE"]),o=e._t("MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION_BUTTON",d.default["MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION_BUTTON"]);if(!await(0,l.default)({title:n,message:t,confirmText:o}))return;this.setState({submitting:!0});const r=JSON.stringify({csrf_token:a.default.get("SecurityID")});(0,i.default)(this.props.resetEndpoint,"POST",r).then((e=>e.json())).then((e=>{const t=!!e.error;this.setState({complete:!0,failed:t,submitting:!1})})).catch((()=>{this.setState({complete:!0,failed:!0,submitting:!1})}))}renderAction(){const{ss:{i18n:e}}=window,{resetEndpoint:t}=this.props,{complete:n,submitting:o}=this.state;return n||o?null:r.default.createElement("p",{className:"account-reset-action"},r.default.createElement("button",{className:"btn btn-outline-secondary",disabled:!t,onClick:this.handleSendReset,type:"button"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_ACTION",d.default["MultiFactorAuthentication.ACCOUNT_RESET_ACTION"])))}renderSending(){const{ss:{i18n:e}}=window,{LoadingIndicatorComponent:t}=this.props;return r.default.createElement("p",{className:"account-reset-action account-reset-action--sending"},r.default.createElement("span",{className:"account-reset-action__icon"},r.default.createElement(t,{size:"32px"})),r.default.createElement("span",{className:"account-reset-action__message"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_SENDING",d.default["MultiFactorAuthentication.ACCOUNT_RESET_SENDING"])))}renderFailure(){const{ss:{i18n:e}}=window;return r.default.createElement("p",{className:"account-reset-action account-reset-action--failure"},r.default.createElement("span",{className:"account-reset-action__icon"},r.default.createElement(u.default,{size:"32px"})),r.default.createElement("span",{className:"account-reset-action__message"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_SENDING",d.default["MultiFactorAuthentication.ACCOUNT_RESET_SENDING_FAILURE"])))}renderSuccess(){const{ss:{i18n:e}}=window;return r.default.createElement("p",{className:"account-reset-action account-reset-action--success"},r.default.createElement("span",{className:"account-reset-action__icon"},r.default.createElement(c.default,{size:"32px"})),r.default.createElement("span",{className:"account-reset-action__message"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_SENDING_SUCCESS",d.default["MultiFactorAuthentication.ACCOUNT_RESET_SENDING_SUCCESS"])))}renderStatusMessage(){const{complete:e,failed:t,submitting:n}=this.state;return n?this.renderSending():e?t?this.renderFailure():this.renderSuccess():null}render(){const{ss:{i18n:e}}=window;return r.default.createElement("div",{className:"account-reset"},r.default.createElement("h5",{className:"account-reset__title"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_TITLE",d.default["MultiFactorAuthentication.ACCOUNT_RESET_TITLE"])),r.default.createElement("p",{className:"account-reset__description"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_DESCRIPTION",d.default["MultiFactorAuthentication.ACCOUNT_RESET_DESCRIPTION"])),this.renderAction(),this.renderStatusMessage())}}p.propTypes={resetEndpoint:o.default.string,LoadingIndicatorComponent:o.default.oneOfType([o.default.object,o.default.func])},p.defaultProps={LoadingIndicatorComponent:s.default};t.default=p},1509:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=p(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=h(n(3141)),a=h(n(7086)),i=h(n(7820)),l=h(n(8488)),s=h(n(5695)),u=h(n(2468)),c=h(n(9831)),d=h(n(8628)),f=h(n(7462));function h(e){return e&&e.__esModule?e:{default:e}}function p(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(p=function(e){return e?n:t})(e)}class m extends o.PureComponent{getStatusMessage(){const{isBackupMethod:e,isDefaultMethod:t}=this.props,{ss:{i18n:n}}=window;return t?n._t("MultiFactorAuthentication.DEFAULT_REGISTERED",f.default["MultiFactorAuthentication.DEFAULT_REGISTERED"]):e?n._t("MultiFactorAuthentication.BACKUP_REGISTERED",f.default["MultiFactorAuthentication.BACKUP_REGISTERED"]):n._t("MultiFactorAuthentication.REGISTERED",f.default["MultiFactorAuthentication.REGISTERED"])}renderRemove(){const{canRemove:e,method:t,RemoveComponent:n}=this.props;return e?o.default.createElement(n,{method:t}):null}renderReset(){const{canReset:e,isBackupMethod:t,method:n}=this.props;if(!e)return null;const a={method:n};if(t){const{ss:{i18n:e}}=window,t=e._t("MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION",f.default["MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION"]),n=e._t("MultiFactorAuthentication.CONFIRMATION_TITLE",f.default["MultiFactorAuthentication.CONFIRMATION_TITLE"]),o=e._t("MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION_BUTTON",f.default["MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION_BUTTON"]);a.onReset=async e=>{await(0,r.default)({title:n,message:t,confirmText:o})&&e()}}return o.default.createElement(c.default,a)}renderSetAsDefault(){const{isDefaultMethod:e,isBackupMethod:t,method:n,SetDefaultComponent:r}=this.props;return e||t?null:o.default.createElement(r,{method:n})}renderControls(){const{canRemove:e,canReset:t}=this.props;return e||t?o.default.createElement("div",null,this.renderRemove(),this.renderReset(),this.renderSetAsDefault()):null}renderNameAndStatus(){const{method:e,createdDate:t}=this.props,{ss:{i18n:n}}=window,o=this.getStatusMessage();return l.default.locale(n.detectLocale()),n.inject(o,{method:e.name,date:(0,l.default)(t).format("L")})}render(){const{tag:e,className:t}=this.props,n=(0,i.default)(t,"registered-method-list-item");return o.default.createElement(e,{className:n},this.renderNameAndStatus(),this.renderControls())}}m.propTypes={method:s.default.isRequired,isDefaultMethod:a.default.bool,isBackupMethod:a.default.bool,canRemove:a.default.bool,canReset:a.default.bool,onRemove:a.default.func,onReset:a.default.func,createdDate:a.default.string,className:a.default.string,tag:a.default.string,RemoveComponent:a.default.oneOfType([a.default.object,a.default.func]),SetDefaultComponent:a.default.oneOfType([a.default.object,a.default.func])},m.defaultProps={isDefaultMethod:!1,isBackupMethod:!1,canRemove:!1,canReset:!1,tag:"li",RemoveComponent:u.default,SetDefaultComponent:d.default};t.default=m},2468:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=h(n(7363)),r=h(n(7086)),a=n(1624),i=h(n(3141)),l=h(n(4510)),s=h(n(42)),u=n(8631),c=n(9861),d=h(n(5695)),f=h(n(7462));function h(e){return e&&e.__esModule?e:{default:e}}const p=(e,t)=>{let{method:n,onRemove:r,defaultMethod:a,registeredMethods:u,onDeregisterMethod:c,onAddAvailableMethod:d,onSetDefaultMethod:h}=e,{backupMethod:p,endpoints:{remove:m}}=t;const{ss:{i18n:E}}=window,M=async()=>{const e=E._t("MultiFactorAuthentication.DELETE_CONFIRMATION",f.default["MultiFactorAuthentication.DELETE_CONFIRMATION"]),t=E._t("MultiFactorAuthentication.CONFIRMATION_TITLE",f.default["MultiFactorAuthentication.CONFIRMATION_TITLE"]),o=E._t("MultiFactorAuthentication.DELETE_CONFIRMATION_BUTTON",f.default["MultiFactorAuthentication.DELETE_CONFIRMATION_BUTTON"]);if(!await(0,i.default)({title:t,message:e,confirmText:o}))return;const r=l.default.get("SecurityID"),M=`${m.replace("{urlSegment}",n.urlSegment)}?SecurityID=${r}`;(0,s.default)(M,"DELETE").then((e=>e.json().then((t=>{if(200===e.status)return c(n),d(t.availableMethod),n.urlSegment===a&&h(null),void(!t.hasBackupMethod&&p&&u.find((e=>e.urlSegment===p.urlSegment))&&c(p));const o=t.errors&&` Errors: \n - ${t.errors.join("\n -")}`||"";throw Error(`Could not delete method. Error code ${e.status}.${o}`)}))))};return o.default.createElement("button",{className:"registered-method-list-item__control",type:"button",onClick:r?r(M):M},E._t("MultiFactorAuthentication.REMOVE_METHOD",f.default["MultiFactorAuthentication.REMOVE_METHOD"]))};p.propTypes={method:d.default.isRequired,onRemove:r.default.func,defaultMethod:r.default.string.isRequired,registeredMethods:r.default.arrayOf(d.default).isRequired,onDeregisterMethod:r.default.func.isRequired,onAddAvailableMethod:r.default.func.isRequired,onSetDefaultMethod:r.default.func.isRequired},p.contextTypes={backupMethod:d.default,endpoints:r.default.shape({register:r.default.string,remove:r.default.string})};t.default=(0,a.connect)((e=>{let{mfaAdministration:{defaultMethod:t,registeredMethods:n}}=e;return{defaultMethod:t,registeredMethods:n}}),(e=>({onDeregisterMethod:t=>{e((0,c.deregisterMethod)(t))},onAddAvailableMethod:t=>{e((0,u.addAvailableMethod)(t))},onSetDefaultMethod:t=>e((0,c.setDefaultMethod)(t))})))(p)},9831:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=h(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=f(n(7086)),a=n(1624),i=n(440),l=n(8631),s=f(n(5695)),u=f(n(2949)),c=f(n(7442)),d=f(n(7462));function f(e){return e&&e.__esModule?e:{default:e}}function h(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(h=function(e){return e?n:t})(e)}class p extends o.Component{constructor(e){super(e),this.state={modalOpen:!1},this.handleReset=this.handleReset.bind(this),this.handleToggleModal=this.handleToggleModal.bind(this)}handleToggleModal(){this.setState((e=>({modalOpen:!e.modalOpen})))}handleReset(){const{onResetMethod:e,method:t}=this.props,{allAvailableMethods:n}=this.context,o=n.find((e=>e.urlSegment===t.urlSegment));if(!o)throw Error(`Cannot register the method given: ${t.name} (${t.urlSegment}).`);e(o),this.handleToggleModal()}render(){const{onReset:e}=this.props,{backupMethod:t,endpoints:n,resources:r}=this.context,a=e?()=>e(this.handleReset):this.handleReset;return o.default.createElement("button",{className:"registered-method-list-item__control",type:"button",onClick:a},window.ss.i18n._t("MultiFactorAuthentication.RESET_METHOD",d.default["MultiFactorAuthentication.RESET_METHOD"]),o.default.createElement(c.default,{backupMethod:t,isOpen:this.state.modalOpen,toggle:this.handleToggleModal,resources:r,endpoints:n,disallowedScreens:[i.SCREEN_CHOOSE_METHOD,i.SCREEN_INTRODUCTION]}))}}p.propTypes={method:s.default.isRequired,onReset:r.default.func},p.contextTypes={allAvailableMethods:r.default.arrayOf(u.default),backupMethod:s.default,endpoints:r.default.shape({register:r.default.string}),resources:r.default.object};t.default=(0,a.connect)(null,(e=>({onResetMethod:t=>{e((0,l.chooseMethod)(t)),e((0,l.showScreen)(i.SCREEN_REGISTER_METHOD))}})))(p)},8628:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=f(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=d(n(7086)),a=d(n(5695)),i=d(n(4510)),l=n(1624),s=d(n(42)),u=n(9861),c=d(n(7462));function d(e){return e&&e.__esModule?e:{default:e}}function f(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(f=function(e){return e?n:t})(e)}class h extends o.Component{constructor(e){super(e),this.handleSetDefault=this.handleSetDefault.bind(this)}handleSetDefault(){const{method:e,onSetDefaultMethod:t}=this.props,{endpoints:{setDefault:n}}=this.context,o=i.default.get("SecurityID"),r=`${n.replace("{urlSegment}",e.urlSegment)}?SecurityID=${o}`;(0,s.default)(r,"PUT").then((n=>n.json().then((o=>{if(200===n.status)return void t(e.urlSegment);const r=o.errors&&` Errors: \n - ${o.errors.join("\n -")}`||"";throw Error(`Could not set default method. Error code ${n.status}.${r}`)}))))}render(){const{ss:{i18n:e}}=window;return o.default.createElement("button",{className:"registered-method-list-item__control",type:"button",onClick:this.handleSetDefault},e._t("MultiFactorAuthentication.SET_AS_DEFAULT",c.default["MultiFactorAuthentication.SET_AS_DEFAULT"]))}}t.Component=h,h.propTypes={method:a.default.isRequired},h.contextTypes={endpoints:r.default.shape({setDefault:r.default.string})};t.default=(0,l.connect)(null,(e=>({onSetDefaultMethod:t=>e((0,u.setDefaultMethod)(t))})))(h)},6021:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=_(n(7086)),r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=M(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),a=n(8127),i=n(1624),l=_(n(7820)),s=_(n(5695)),u=_(n(2949)),c=n(8631),d=n(9861),f=n(440),h=_(n(1509)),p=_(n(2469)),m=_(n(7442)),E=_(n(7462));function M(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(M=function(e){return e?n:t})(e)}function _(e){return e&&e.__esModule?e:{default:e}}class g extends r.Component{constructor(e){super(e),this.state={modalOpen:!1},this.handleToggleModal=this.handleToggleModal.bind(this)}getChildContext(){const{allAvailableMethods:e,backupMethod:t,endpoints:n,resources:o}=this.props;return{allAvailableMethods:e,backupMethod:t,endpoints:n,resources:o}}componentDidMount(){const{onSetDefaultMethod:e,initialDefaultMethod:t,onSetRegisteredMethods:n,initialRegisteredMethods:o,onUpdateAvailableMethods:r,initialAvailableMethods:a}=this.props;n(o),r(a),e(t)}getBaseMethods(){const{backupMethod:e}=this.props;let{registeredMethods:t}=this.props;return t?(e&&(t=t.filter((t=>t.urlSegment!==e.urlSegment))),t):[]}handleToggleModal(){this.setState((e=>({modalOpen:!e.modalOpen})))}renderNoMethodsMessage(){if(this.getBaseMethods().length)return null;const{readOnly:e}=this.props,{ss:{i18n:t}}=window,n=e?"MultiFactorAuthentication.NO_METHODS_REGISTERED_READONLY":"MultiFactorAuthentication.NO_METHODS_REGISTERED";return r.default.createElement("div",{className:"registered-mfa-method-list-field__no-methods"},t._t(n,E.default[n]))}renderBackupMethod(){const{backupMethod:e,backupCreatedDate:t,registeredMethods:n,readOnly:o,MethodListItemComponent:a}=this.props;if(!e)return null;const i=n.find((t=>t.urlSegment===e.urlSegment));return i?r.default.createElement(a,{method:i,createdDate:t,canReset:!o,isBackupMethod:!0,tag:"div",className:"registered-method-list-item--backup"}):null}renderBaseMethods(){const{isMFARequired:e}=this.props,t=this.getBaseMethods();if(!t.length)return[];const{defaultMethod:n,readOnly:o,MethodListItemComponent:a}=this.props;return t.map((i=>{const l={method:i,key:i.urlSegment,isDefaultMethod:n&&i.urlSegment===n,canRemove:!(o||e&&1===t.length),canReset:!o};return r.default.createElement(a,l)}))}renderModal(){const{backupMethod:e,endpoints:t,resources:n,RegisterModalComponent:o}=this.props;return r.default.createElement(o,{backupMethod:e,isOpen:this.state.modalOpen,toggle:this.handleToggleModal,resources:n,endpoints:t,disallowedScreens:[f.SCREEN_INTRODUCTION]})}renderAddButton(){const{availableMethods:e,registeredMethods:t,readOnly:n,onResetRegister:o}=this.props;if(n||!e||0===e.length)return null;const{ss:{i18n:i}}=window,l=t.length?i._t("MultiFactorAuthentication.ADD_ANOTHER_METHOD",E.default["MultiFactorAuthentication.ADD_ANOTHER_METHOD"]):i._t("MultiFactorAuthentication.ADD_FIRST_METHOD",E.default["MultiFactorAuthentication.ADD_FIRST_METHOD"]);return r.default.createElement(a.Button,{className:"registered-mfa-method-list-field__button",outline:!0,type:"button",onClick:()=>{this.handleToggleModal(),o()}},l)}render(){const{readOnly:e,resetEndpoint:t}=this.props,n=(0,l.default)({"registered-mfa-method-list-field":!0,"registered-mfa-method-list-field--read-only":e});return r.default.createElement("div",{className:n},r.default.createElement("ul",{className:"method-list"},this.renderBaseMethods()),this.renderNoMethodsMessage(),this.renderAddButton(),this.renderBackupMethod(),e&&r.default.createElement("hr",null),e&&r.default.createElement(p.default,{resetEndpoint:t}),this.renderModal())}}t.Component=g,g.propTypes={backupMethod:s.default,defaultMethod:o.default.string,readOnly:o.default.bool,isMFARequired:o.default.bool,initialDefaultMethod:o.default.string,initialRegisteredMethods:o.default.arrayOf(s.default),initialAvailableMethods:o.default.arrayOf(u.default),allAvailableMethods:o.default.arrayOf(u.default),resetEndpoint:o.default.string,endpoints:o.default.shape({register:o.default.string,remove:o.default.string}),resources:o.default.object,availableMethods:o.default.arrayOf(u.default),registeredMethods:o.default.arrayOf(s.default),registrationScreen:o.default.number,MethodListItemComponent:o.default.oneOfType([o.default.object,o.default.func]),RegisterModalComponent:o.default.oneOfType([o.default.object,o.default.func])},g.defaultProps={initialAvailableMethods:[],MethodListItemComponent:h.default,RegisterModalComponent:m.default},g.childContextTypes={allAvailableMethods:o.default.arrayOf(u.default),backupMethod:s.default,endpoints:o.default.shape({register:o.default.string,remove:o.default.string,setDefault:o.default.string}),resources:o.default.object};t.default=(0,i.connect)((e=>{const{availableMethods:t,screen:n}=e.mfaRegister,{defaultMethod:o,registeredMethods:r}=e.mfaAdministration;return{availableMethods:t,defaultMethod:o,registeredMethods:r||[],registrationScreen:n}}),(e=>({onResetRegister:()=>{e((0,c.chooseMethod)(null)),e((0,c.showScreen)(f.SCREEN_CHOOSE_METHOD))},onUpdateAvailableMethods:t=>{e((0,c.setAvailableMethods)(t))},onSetDefaultMethod:t=>{e((0,d.setDefaultMethod)(t))},onSetRegisteredMethods:t=>{e((0,d.setRegisteredMethods)(t))}})))(g)},1820:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7363))&&o.__esModule?o:{default:o};t.default=e=>{let{color:t="currentColor",size:n="3em"}=e;return r.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",height:n,width:n},r.default.createElement("g",{fill:t},r.default.createElement("path",{d:"M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z"})))}},3947:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7363))&&o.__esModule?o:{default:o};t.default=e=>{let{color:t="currentColor",size:n="3em"}=e;return r.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",height:n,width:n},r.default.createElement("g",{fill:t},r.default.createElement("path",{d:"M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"})))}},5292:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=a(n(7363)),r=a(n(7820));function a(e){return e&&e.__esModule?e:{default:e}}t.default=e=>{let{block:t=!1,size:n="6em"}=e;return o.default.createElement("div",{style:{height:n,width:n},className:(0,r.default)({"mfa-loading-indicator":!0,"mfa-loading-indicator--block":t})})}},440:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.SCREEN_REGISTER_METHOD=t.SCREEN_INTRODUCTION=t.SCREEN_COMPLETE=t.SCREEN_CHOOSE_METHOD=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=M(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=E(n(7086)),a=E(n(42)),i=n(6648),l=E(n(2949)),s=E(n(5695)),u=E(n(5292)),c=E(n(6910)),d=E(n(3954)),f=E(n(1824)),h=n(1624),p=n(8631),m=E(n(1196));function E(e){return e&&e.__esModule?e:{default:e}}function M(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(M=function(e){return e?n:t})(e)}function _(){return _=Object.assign?Object.assign.bind():function(e){for(var t=1;te.json().then((e=>{const{SecurityID:t,...n}=e;this.setState({registerProps:n,token:t})}))))}handleBack(){const{availableMethods:e,onShowIntroduction:t,onShowChooseMethod:n}=this.props;return 1===e.length&&t?t():(this.setState({registerProps:null}),n())}handleCompleteRegistration(e){const{endpoints:{register:t},selectedMethod:n,onRemoveAvailableMethod:o,onRegister:r}=this.props,{token:i}=this.state,l=i?`?SecurityID=${i}`:"";(0,a.default)(`${t.replace("{urlSegment}",n.urlSegment)}${l}`,"POST",JSON.stringify(e)).then((e=>201===e.status?(this.setState({registerProps:null}),"function"==typeof r&&r(n),o(n),this.setupBackupMethod(),null):e.json())).then((e=>{if(e&&e.errors){const t=e.errors.join(", ");this.setState((e=>({registerProps:{...e.registerProps,error:t}})))}}))}shouldSetupBackupMethod(){const{backupMethod:e,registeredMethods:t}=this.props;return!!e&&!t.find((t=>t.urlSegment===e.urlSegment))}handleSkip(){const{skip:e}=this.props.endpoints;e&&(window.location=this.props.endpoints.skip)}renderIntroduction(){const{canSkip:e,resources:t,endpoints:{skip:n},showSubTitle:r,IntroductionComponent:a}=this.props;return o.default.createElement(a,{canSkip:n&&e,onSkip:this.handleSkip,resources:t,showTitle:r})}renderMethod(){const{selectedMethod:e,showSubTitle:t,TitleComponent:n}=this.props,{registerProps:r}=this.state;if(!e)return null;if(!r)return o.default.createElement(u.default,{block:!0});const a=(0,i.loadComponent)(e.component);return o.default.createElement("div",null,t&&o.default.createElement(n,null),o.default.createElement(a,_({},r,{method:e,onBack:this.handleBack,onCompleteRegistration:this.handleCompleteRegistration})))}renderOptions(){const{availableMethods:e,showSubTitle:t,SelectMethodComponent:n}=this.props;return o.default.createElement(n,{methods:e,showTitle:t})}render(){const{screen:e,onCompleteRegistration:t,showTitle:n,showSubTitle:r,completeMessage:a,CompleteComponent:i}=this.props,{ss:{i18n:l}}=window;if(e===v)return o.default.createElement(i,{showTitle:r,onComplete:t,message:a});let s;switch(e){case b:s=this.renderOptions();break;case y:s=this.renderMethod();break;default:s=this.renderIntroduction()}return o.default.createElement("div",null,n&&o.default.createElement("h1",{className:"mfa-app-title"},l._t("MFARegister.TITLE","Multi-factor authentication")),s)}}t.Component=O,O.propTypes={availableMethods:r.default.arrayOf(l.default),backupMethod:l.default,canSkip:r.default.bool,endpoints:r.default.shape({register:r.default.string.isRequired,skip:r.default.string}),onRegister:r.default.func,onCompleteRegistration:r.default.func.isRequired,registeredMethods:r.default.arrayOf(s.default),resources:r.default.object,showTitle:r.default.bool,showSubTitle:r.default.bool,IntroductionComponent:r.default.oneOfType([r.default.object,r.default.func]),SelectMethodComponent:r.default.oneOfType([r.default.object,r.default.func]),CompleteComponent:r.default.oneOfType([r.default.object,r.default.func]),TitleComponent:r.default.oneOfType([r.default.object,r.default.func])},O.defaultProps={resources:{},showTitle:!0,showSubTitle:!0,showIntroduction:!0,IntroductionComponent:c.default,SelectMethodComponent:f.default,CompleteComponent:d.default,TitleComponent:m.default};t.default=(0,h.connect)((e=>{const t=e.mfaRegister||e;return{screen:t.screen,selectedMethod:t.method,availableMethods:t.availableMethods}}),(e=>({onShowIntroduction:()=>e((0,p.showScreen)(g)),onShowComplete:()=>e((0,p.showScreen)(v)),onSelectMethod:t=>e((0,p.chooseMethod)(t)),onShowChooseMethod:()=>{e((0,p.chooseMethod)(null)),e((0,p.showScreen)(b))},onRemoveAvailableMethod:t=>e((0,p.removeAvailableMethod)(t))})))(O)},3954:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(7363)),r=i(n(7086)),a=i(n(1196));function i(e){return e&&e.__esModule?e:{default:e}}const l=e=>{let{onComplete:t,showTitle:n,message:r}=e;return o.default.createElement("div",{className:"mfa-register-confirmation"},o.default.createElement("i",{className:"font-icon-check-mark mfa-register-confirmation__icon"}),n&&o.default.createElement(a.default,{className:"mfa-register-confirmation__title"}),o.default.createElement("p",{className:"mfa-register-confirmation__description"},r||window.ss.i18n._t("MFARegister.SETUP_COMPLETE_DESCRIPTION","You will be able to edit these settings later from your profile area.")),o.default.createElement("button",{onClick:t,className:"mfa-register-confirmation__continue btn btn-primary"},window.ss.i18n._t("MFARegister.SETUP_COMPLETE_CONTINUE","Continue")))};l.propTypes={onComplete:r.default.func.isRequired,showTitle:r.default.bool},l.defaultProps={showTitle:!0};t.default=l},6910:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=t.ActionList=void 0;var o=c(n(7363)),r=c(n(7086)),a=n(8631),i=n(1624),l=n(440),s=c(n(1196)),u=c(n(7462));function c(e){return e&&e.__esModule?e:{default:e}}const d=e=>{let{canSkip:t,onContinue:n,onSkip:r}=e;const{ss:{i18n:a}}=window;return o.default.createElement("ul",{className:"mfa-action-list"},o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-primary",onClick:n},a._t("MultiFactorAuthentication.GET_STARTED",u.default["MultiFactorAuthentication.GET_STARTED"]))),t&&o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-secondary",onClick:r},a._t("MultiFactorAuthentication.SETUP_LATER",u.default["MultiFactorAuthentication.SETUP_LATER"]))))};t.ActionList=d;const f=e=>{let{canSkip:t,onContinue:n,onSkip:r,resources:a,showTitle:i,TitleComponent:l}=e;const{ss:{i18n:s}}=window;return o.default.createElement("div",null,i&&o.default.createElement(l,null),o.default.createElement("h4",{className:"mfa-feature-list-title"},s._t("MultiFactorAuthentication.HOW_IT_WORKS",u.default["MultiFactorAuthentication.HOW_IT_WORKS"])),o.default.createElement("ul",{className:"mfa-feature-list"},o.default.createElement("li",{className:"mfa-feature-list-item"},a.extra_factor_image_url&&o.default.createElement("img",{alt:s._t("MultiFactorAuthentication.EXTRA_LAYER_IMAGE_ALT",u.default["MultiFactorAuthentication.EXTRA_LAYER_IMAGE_ALT"]),"aria-hidden":"true",className:"mfa-feature-list-item__icon",src:a.extra_factor_image_url}),o.default.createElement("div",{className:"mfa-feature-list-item__content"},o.default.createElement("h5",{className:"mfa-block-heading mfa-feature-list-item__title"},s._t("MultiFactorAuthentication.EXTRA_LAYER_TITLE",u.default["MultiFactorAuthentication.EXTRA_LAYER_TITLE"])),o.default.createElement("p",{className:"mfa-feature-list-item__description"},s._t("MultiFactorAuthentication.EXTRA_LAYER_DESCRIPTION",u.default["MultiFactorAuthentication.EXTRA_LAYER_DESCRIPTION"])," ",a.user_help_link&&o.default.createElement("a",{href:a.user_help_link},s._t("MultiFactorAuthentication.HOW_MFA_WORKS",u.default["MultiFactorAuthentication.HOW_MFA_WORKS"]))))),o.default.createElement("li",{className:"mfa-feature-list-item"},a.unique_image_url&&o.default.createElement("img",{alt:s._t("MultiFactorAuthentication.UNIQUE_IMAGE_ALT",u.default["MultiFactorAuthentication.UNIQUE_IMAGE_ALT"]),"aria-hidden":"true",className:"mfa-feature-list-item__icon",src:a.unique_image_url}),o.default.createElement("div",{className:"mfa-feature-list-item__content"},o.default.createElement("h5",{className:"mfa-block-heading mfa-feature-list-item__title"},s._t("MultiFactorAuthentication.UNIQUE_TITLE",u.default["MultiFactorAuthentication.UNIQUE_TITLE"])),o.default.createElement("p",{className:"mfa-feature-list-item__description"},s._t("MultiFactorAuthentication.UNIQUE_DESCRIPTION",u.default["MultiFactorAuthentication.UNIQUE_DESCRIPTION"]))))),o.default.createElement(d,{canSkip:t,onContinue:n,onSkip:r}))};t.Component=f,f.propTypes={canSkip:r.default.bool,onContinue:r.default.func.isRequired,onSkip:r.default.func,resources:r.default.shape({user_help_link:r.default.string,extra_factor_image_url:r.default.string,unique_image_url:r.default.string}).isRequired,showTitle:r.default.bool,TitleComponent:r.default.oneOfType([r.default.object,r.default.func])},f.defaultProps={showTitle:!0,TitleComponent:s.default};t.default=(0,i.connect)(null,(e=>({onContinue:()=>{e((0,a.chooseMethod)(null)),e((0,a.showScreen)(l.SCREEN_REGISTER_METHOD))}})))(f)},3324:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=s(n(7086)),a=s(n(7820)),i=s(n(2949)),l=s(n(639));function s(e){return e&&e.__esModule?e:{default:e}}function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}class c extends o.Component{constructor(e){super(e),this.handleClick=this.handleClick.bind(this),this.handleKeyUp=this.handleKeyUp.bind(this)}handleClick(e){const{method:{isAvailable:t},onClick:n}=this.props;t&&n&&n(e)}handleKeyUp(e){13===e.keyCode&&this.handleClick(e)}renderSupportLink(e){const{ss:{i18n:t}}=window,{supportLink:n,supportText:r}=e;return n?o.default.createElement("a",{href:n,target:"_blank",rel:"noopener noreferrer",className:"mfa-method-tile__support-link"},r||t._t("MFARegister.HELP","Find out more.")):null}renderUnavailableMask(){const{ss:{i18n:e}}=window,{isAvailable:t,getUnavailableMessage:n}=this.props;if(t())return null;const r=n();return o.default.createElement("div",{className:"mfa-method-tile__unavailable-mask"},o.default.createElement("h3",{className:"mfa-method-tile__unavailable-title"},e._t("MFAMethodTile.UNAVAILABLE","Unsupported: ")),r&&o.default.createElement("p",{className:"mfa-method-tile__unavailable-text"},r))}render(){const{isActive:e,method:t}=this.props,{ss:{i18n:n}}=window,r=(0,a.default)("mfa-method-tile",{"mfa-method-tile--active":e,"mfa-method-tile--unsupported":!t.isAvailable}),i=(0,a.default)("mfa-method-tile__thumbnail-container",{"mfa-method-tile__thumbnail-container--unsupported":!t.isAvailable}),l=n.inject(n._t("MFARegister.REGISTER_WITH","Register with {method}"),{method:t.name.toLowerCase()});return o.default.createElement("li",{className:r},o.default.createElement("div",{className:"mfa-method-tile__content",onClick:this.handleClick,onKeyUp:this.handleKeyUp,tabIndex:"0",role:"button"},t.thumbnail&&o.default.createElement("div",{className:i},o.default.createElement("img",{src:t.thumbnail,className:"mfa-method-tile__thumbnail",alt:t.name})),o.default.createElement("h3",{className:"mfa-method-tile__title"},l),o.default.createElement("p",{className:"mfa-method-tile__description"},t.description&&`${t.description}. `,this.renderSupportLink(t))),this.renderUnavailableMask())}}t.Component=c,c.propTypes={getUnavailableMessage:r.default.func.isRequired,isActive:r.default.bool,isAvailable:r.default.func.isRequired,method:i.default.isRequired,onClick:r.default.func.isRequired},c.defaultProps={isActive:!1};t.default=(0,l.default)(c)},1824:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=m(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=p(n(7086)),a=p(n(2949)),i=p(n(7820)),l=n(8631),s=n(2827),u=n(1624),c=p(n(639)),d=n(440),f=p(n(3324)),h=p(n(1196));function p(e){return e&&e.__esModule?e:{default:e}}function m(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(m=function(e){return e?n:t})(e)}class E extends o.Component{constructor(e){super(e);let t=null;1===e.methods.length&&e.isAvailable&&e.isAvailable(e.methods[0])&&(t=e.methods[0]),this.state={highlightedMethod:t},this.handleGoToNext=this.handleGoToNext.bind(this),this.handleBack=this.handleBack.bind(this)}componentDidMount(){const{highlightedMethod:e}=this.state;e&&this.handleGoToNext()}handleGoToNext(){const{highlightedMethod:e}=this.state;this.props.onSelectMethod(e)}handleClick(e){this.setState({highlightedMethod:e})}handleBack(){this.props.onClickBack&&this.props.onClickBack()}renderActions(){const{ss:{i18n:e}}=window,{highlightedMethod:t}=this.state;return o.default.createElement("ul",{className:"mfa-action-list"},o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-primary",disabled:null===t,onClick:this.handleGoToNext},e._t("MFARegister.NEXT","Next"))),o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-secondary",onClick:this.handleBack},e._t("MFARegister.BACK","Back"))))}render(){const{methods:e,showTitle:t,TitleComponent:n,MethodTileComponent:r}=this.props,{highlightedMethod:a}=this.state,l=(0,i.default)("mfa-method-tile-group",{"mfa-method-tile-group--three-columns":e.length%3==0});return o.default.createElement("div",null,t&&o.default.createElement(n,null),o.default.createElement("ul",{className:l},e.map((e=>o.default.createElement(r,{isActive:a===e,key:e.urlSegment,method:e,onClick:()=>this.handleClick(e)})))),this.renderActions())}}t.Component=E,E.propTypes={methods:r.default.arrayOf(a.default),onSelectMethod:r.default.func,onClickBack:r.default.func,showTitle:r.default.bool,TitleComponent:r.default.oneOfType([r.default.object,r.default.func]),MethodTileComponent:r.default.oneOfType([r.default.object,r.default.func])},E.defaultProps={showTitle:!0,TitleComponent:h.default,MethodTileComponent:f.default};t.default=(0,s.compose)((0,u.connect)(null,(e=>({onClickBack:()=>e((0,l.showScreen)(d.SCREEN_INTRODUCTION)),onSelectMethod:t=>{e((0,l.chooseMethod)(t)),e((0,l.showScreen)(d.SCREEN_REGISTER_METHOD))}}))),c.default)(E)},1196:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=l(n(7363)),r=n(1624),a=n(440),i=l(n(7462));function l(e){return e&&e.__esModule?e:{default:e}}const s=e=>{let{screen:t,method:n,Tag:r="h2",className:l="mfa-section-title"}=e;const{ss:{i18n:s}}=window;let u;switch(t){case a.SCREEN_INTRODUCTION:u=s._t("MultiFactorAuthentication.TITLE",i.default["MultiFactorAuthentication.TITLE"]);break;case a.SCREEN_CHOOSE_METHOD:u=s._t("MultiFactorAuthentication.SELECT_METHOD",i.default["MultiFactorAuthentication.SELECT_METHOD"]);break;case a.SCREEN_COMPLETE:u=s._t("MultiFactorAuthentication.SETUP_COMPLETE_TITLE",i.default["MultiFactorAuthentication.SETUP_COMPLETE_TITLE"]);break;case a.SCREEN_REGISTER_METHOD:u=n&&s.inject(s._t("MFARegister.REGISTER_WITH","Register with {method}"),{method:n.name.toLowerCase()});break;default:u=!1}if(!u||!u.length)return null;const c=r||"span";return o.default.createElement(c,{className:l},u)};t.Component=s;t.default=(0,r.connect)((e=>{const t=e.mfaRegister||e;return{screen:t.screen,method:t.method}}))(s)},7442:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=m(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=p(n(7086)),a=n(8127),i=n(6648),l=n(2827),s=n(1624),u=p(n(1196)),c=n(9861),d=p(n(5695)),f=n(440),h=p(n(7462));function p(e){return e&&e.__esModule?e:{default:e}}function m(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(m=function(e){return e?n:t})(e)}class E extends o.Component{constructor(e){super(e),this.handleRegister=this.handleRegister.bind(this)}componentDidUpdate(){const{disallowedScreens:e,isOpen:t,registrationScreen:n,toggle:o}=this.props;t&&e.length&&e.includes(n)&&o()}handleRegister(e){const{onAddRegisteredMethod:t,onSetDefaultMethod:n,registeredMethods:o}=this.props;o.length||n(e.urlSegment),t(e)}render(){const{backupMethod:e,endpoints:t,isOpen:n,toggle:r,registeredMethods:i,registrationScreen:l,resources:s,RegisterComponent:c}=this.props;return o.default.createElement(a.Modal,{isOpen:n,toggle:r,className:"registered-mfa-method-list-field-register-modal"},o.default.createElement(a.ModalHeader,{toggle:r},o.default.createElement(u.default,{Tag:null})),o.default.createElement(a.ModalBody,{className:"registered-mfa-method-list-field-register-modal__content"},l!==f.SCREEN_INTRODUCTION&&o.default.createElement(c,{backupMethod:e,registeredMethods:i,onCompleteRegistration:r,onRegister:this.handleRegister,resources:s,endpoints:t,showTitle:!1,showSubTitle:!1,completeMessage:window.ss.i18n._t("MultiFactorAuthentication.ADMIN_SETUP_COMPLETE_CONTINUE",h.default["MultiFactorAuthentication.ADMIN_SETUP_COMPLETE_CONTINUE"])})))}}t.Component=E,E.propTypes={isOpen:r.default.bool,toggle:r.default.func,disallowedScreens:r.default.arrayOf(r.default.number),backupMethod:d.default,resources:r.default.object,endpoints:r.default.shape({register:r.default.string}),registrationScreen:r.default.number,registeredMethods:r.default.arrayOf(d.default),onAddRegisteredMethod:r.default.func,onSetDefaultMethod:r.default.func,RegisterComponent:r.default.oneOfType([r.default.element,r.default.func,r.default.elementType])},E.defaultProps={isOpen:!1,disallowedScreens:[]};t.default=(0,l.compose)((0,i.inject)(["MFARegister"],(e=>({RegisterComponent:e})),(()=>"MFARegisterModal")),(0,s.connect)((e=>({registrationScreen:e.mfaRegister.screen,registeredMethods:e.mfaAdministration.registeredMethods})),(e=>({onAddRegisteredMethod:t=>{e((0,c.registerMethod)(t))},onSetDefaultMethod:t=>e((0,c.setDefaultMethod)(t))}))))(E)},830:function(e,t,n){"use strict";var o,r=(o=n(7363))&&o.__esModule?o:{default:o},a=n(9691),i=n(6648);window.jQuery.entwine("ss",(e=>{e('.js-injector-boot [data-field-type="registered-mfa-method-list-field"]').entwine({ReactRoot:null,onmatch(){const e=(0,i.loadComponent)("RegisteredMFAMethodListField"),{readOnly:t,schema:{backupMethod:n,defaultMethod:o,registeredMethods:l,availableMethods:s,allAvailableMethods:u,resources:c,endpoints:d,backupCreatedDate:f,resetEndpoint:h,isMFARequired:p}}=this.data("schema");let m=this.getReactRoot();m||(m=(0,a.createRoot)(this[0]),this.setReactRoot(m)),m.render(r.default.createElement(e,{backupMethod:n,readOnly:t,initialDefaultMethod:o,initialRegisteredMethods:l,initialAvailableMethods:s,allAvailableMethods:u,resources:c,endpoints:d,backupCreatedDate:f,resetEndpoint:h,isMFARequired:p}))},onunmatch(){const e=this.getReactRoot();e&&(e.unmount(),this.setReactRoot(null))}})}))},6388:function(){"use strict";window.jQuery.entwine("ss",(e=>{e('[name="MFARequired"]').entwine({onchange(){parseInt(this.val(),10)?e(".mfa-settings__grace-period").removeAttr("disabled"):e(".mfa-settings__grace-period").attr("disabled","disabled")},onmatch(){this.onchange()}})}))},1924:function(e,t,n){"use strict";n(830),n(6388)},42:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=function(e){return fetch(e,{body:arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,credentials:"same-origin",headers:arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},method:arguments.length>1&&void 0!==arguments[1]?arguments[1]:"GET"})}},1661:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.formatCode=void 0;t.formatCode=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:" ";if(e.length<6)return e;if(e.length%4==0)return e.split(/(.{4})/g).filter((e=>e)).join(t).trim();if(e.length%3==0)return e.split(/(.{3})/g).filter((e=>e)).join(t).trim();const n=4-e.length%4,o=(e.length-3*n)/4,r=[...[...Array(o).keys()].map((()=>4)),...[...Array(n).keys()].map((()=>3))];let a=0;return r.map((t=>e.substring(a,a+=t))).join(t).trim()}},639:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.hoc=t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=i(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var l=r?Object.getOwnPropertyDescriptor(e,a):null;l&&(l.get||l.set)?Object.defineProperty(o,a,l):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=n(1624),a=n(2827);function i(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(i=function(e){return e?n:t})(e)}function l(){return l=Object.assign?Object.assign.bind():function(e){for(var t=1;t{const t=class extends o.Component{constructor(e){super(e),this.getAvailabilityOverride=this.getAvailabilityOverride.bind(this),this.isAvailable=this.isAvailable.bind(this),this.getUnavailableMessage=this.getUnavailableMessage.bind(this)}getAvailabilityOverride(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;const{availableMethodOverrides:t}=this.props,n=e||this.props.method,{urlSegment:o}=n;return void 0!==t[o]?t[o]:{}}getUnavailableMessage(){const e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:null)||this.props.method;return this.getAvailabilityOverride(e).unavailableMessage||e.unavailableMessage}isAvailable(){const e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:null)||this.props.method,t=this.getAvailabilityOverride(e);let n=e.isAvailable;return void 0!==t.isAvailable&&(n=t.isAvailable),n}render(){return o.default.createElement(e,l({},this.props,{isAvailable:this.isAvailable,getUnavailableMessage:this.getUnavailableMessage}))}},n=(e=>e.displayName||e.name||"Component")(e);return t.displayName=`WithMethodAvailability(${n})`,t};t.hoc=s;const u=(0,a.compose)((0,r.connect)((e=>{const t=[...e.mfaRegister.availableMethods,...e.mfaVerify.allMethods],n={};return Object.values(t).forEach((t=>{const{urlSegment:o}=t,r=`${o}Availability`;void 0!==e[r]&&(n[o]=e[r])})),{availableMethodOverrides:n}})),s);t.default=u},2017:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=["ADD_REGISTERED_METHOD","REMOVE_REGISTERED_METHOD","SET_DEFAULT_METHOD","SET_REGISTERED_METHODS"].reduce(((e,t)=>Object.assign(e,{[t]:`MFA_ADMINISTRATION.${t}`})),{})},9861:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setRegisteredMethods=t.setDefaultMethod=t.registerMethod=t.deregisterMethod=void 0;var o,r=(o=n(2017))&&o.__esModule?o:{default:o};t.registerMethod=e=>({type:r.default.ADD_REGISTERED_METHOD,payload:{method:e}});t.deregisterMethod=e=>({type:r.default.REMOVE_REGISTERED_METHOD,payload:{method:e}});t.setDefaultMethod=e=>({type:r.default.SET_DEFAULT_METHOD,payload:{defaultMethod:e}});t.setRegisteredMethods=e=>({type:r.default.SET_REGISTERED_METHODS,payload:{methods:e}})},6683:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:a,{type:t,payload:n}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const o=e=>t=>t.urlSegment===e.urlSegment,{registeredMethods:i}=e;switch(t){case r.default.ADD_REGISTERED_METHOD:{const{method:t}=n;return Array.isArray(i)?i.find(o(t))?e:(i.push(t),{...e,registeredMethods:i}):{...e,registeredMethods:[t]}}case r.default.REMOVE_REGISTERED_METHOD:{const{method:t}=n,r=i.findIndex(o(t));if(r<0)return e;i.splice(r,1);const a=2===i.length?{defaultMethod:i.find((()=>!0)).urlSegment}:{};return{...e,...a,registeredMethods:[...i]}}case r.default.SET_DEFAULT_METHOD:return{...e,defaultMethod:n.defaultMethod};case r.default.SET_REGISTERED_METHODS:return{...e,registeredMethods:n.methods};default:return e}};var o,r=(o=n(2017))&&o.__esModule?o:{default:o};const a={defaultMethod:null,registeredMethods:[]}},3529:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=["ADD_AVAILABLE_METHOD","REMOVE_AVAILABLE_METHOD","SET_AVAILABLE_METHODS","SET_SCREEN","SET_METHOD"].reduce(((e,t)=>Object.assign(e,{[t]:`MFA_REGISTER.${t}`})),{})},8631:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.showScreen=t.setAvailableMethods=t.removeAvailableMethod=t.chooseMethod=t.addAvailableMethod=void 0;var o,r=(o=n(3529))&&o.__esModule?o:{default:o};t.showScreen=e=>({type:r.default.SET_SCREEN,payload:{screen:e}});t.chooseMethod=e=>({type:r.default.SET_METHOD,payload:{method:e}});t.setAvailableMethods=e=>({type:r.default.SET_AVAILABLE_METHODS,payload:{availableMethods:e}});t.addAvailableMethod=e=>({type:r.default.ADD_AVAILABLE_METHOD,payload:{method:e}});t.removeAvailableMethod=e=>({type:r.default.REMOVE_AVAILABLE_METHOD,payload:{method:e}})},7286:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:i,{type:t,payload:n}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};switch(t){case a.default.SET_SCREEN:{const{screen:t}=n;return null===e.method&&t===r.SCREEN_REGISTER_METHOD?{...e,screen:r.SCREEN_CHOOSE_METHOD}:{...e,screen:t}}case a.default.SET_METHOD:return{...e,method:n.method};case a.default.SET_AVAILABLE_METHODS:return{...e,availableMethods:n.availableMethods};case a.default.ADD_AVAILABLE_METHOD:return{...e,availableMethods:[...e.availableMethods,n.method]};case a.default.REMOVE_AVAILABLE_METHOD:return{...e,availableMethods:e.availableMethods.filter((e=>e.urlSegment!==n.method.urlSegment))};default:return e}};var o,r=n(440),a=(o=n(3529))&&o.__esModule?o:{default:o};const i={screen:r.SCREEN_INTRODUCTION,method:null,availableMethods:[]}},7282:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=["SET_ALL_METHODS"].reduce(((e,t)=>Object.assign(e,{[t]:`MFA_VERIFY.${t}`})),{})},23:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:a,{type:t,payload:n}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(t===r.default.SET_ALL_METHODS)return{...e,allMethods:n.allMethods};return e};var o,r=(o=n(7282))&&o.__esModule?o:{default:o};const a={allMethods:[]}},2949:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7086))&&o.__esModule?o:{default:o};t.default=r.default.shape({urlSegment:r.default.string,name:r.default.string,description:r.default.string,supportLink:r.default.string,supportText:r.default.string,thumbnail:r.default.string,component:r.default.string,isAvailable:r.default.bool,unavailableMessage:r.default.string})},5695:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7086))&&o.__esModule?o:{default:o};t.default=r.default.shape({name:r.default.string,urlSegment:r.default.string,isAvailable:r.default.bool,unavailableMessage:r.default.string,component:r.default.string,supportLink:r.default.string,thumbnail:r.default.string})},640:function(e,t,n){"use strict";var o=n(1742),r={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var n,a,i,l,s,u,c=!1;t||(t={}),n=t.debug||!1;try{if(i=o(),l=document.createRange(),s=document.getSelection(),(u=document.createElement("span")).textContent=e,u.ariaHidden="true",u.style.all="unset",u.style.position="fixed",u.style.top=0,u.style.clip="rect(0, 0, 0, 0)",u.style.whiteSpace="pre",u.style.webkitUserSelect="text",u.style.MozUserSelect="text",u.style.msUserSelect="text",u.style.userSelect="text",u.addEventListener("copy",(function(o){if(o.stopPropagation(),t.format)if(o.preventDefault(),void 0===o.clipboardData){n&&console.warn("unable to use e.clipboardData"),n&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var a=r[t.format]||r.default;window.clipboardData.setData(a,e)}else o.clipboardData.clearData(),o.clipboardData.setData(t.format,e);t.onCopy&&(o.preventDefault(),t.onCopy(o.clipboardData))})),document.body.appendChild(u),l.selectNodeContents(u),s.addRange(l),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");c=!0}catch(o){n&&console.error("unable to copy using execCommand: ",o),n&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),c=!0}catch(o){n&&console.error("unable to copy using clipboardData: ",o),n&&console.error("falling back to prompt"),a=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in t?t.message:"Copy to clipboard: #{key}, Enter"),window.prompt(a,e)}}finally{s&&("function"==typeof s.removeRange?s.removeRange(l):s.removeAllRanges()),u&&document.body.removeChild(u),i()}return c}},9768:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Printd=t.createIFrame=t.createLinkStyle=t.createStyle=void 0;var n=/^(((http[s]?)|file):)?(\/\/)+([0-9a-zA-Z-_.=?&].+)$/,o=/^((\.|\.\.)?\/)([0-9a-zA-Z-_.=?&]+\/)*([0-9a-zA-Z-_.=?&]+)$/,r=function(e){return n.test(e)||o.test(e)};function a(e,t){var n=e.createElement("style");return n.appendChild(e.createTextNode(t)),n}function i(e,t){var n=e.createElement("link");return n.type="text/css",n.rel="stylesheet",n.href=t,n}function l(e){var t=window.document.createElement("iframe");return t.setAttribute("src","about:blank"),t.setAttribute("style","visibility:hidden;width:0;height:0;position:absolute;z-index:-9999;bottom:0;"),t.setAttribute("width","0"),t.setAttribute("height","0"),t.setAttribute("wmode","opaque"),e.appendChild(t),t}t.createStyle=a,t.createLinkStyle=i,t.createIFrame=l;var s={parent:window.document.body,headElements:[],bodyElements:[]},u=function(){function e(e){this.isLoading=!1,this.hasEvents=!1,this.opts=[s,e||{}].reduce((function(e,t){return Object.keys(t).forEach((function(n){return e[n]=t[n]})),e}),{}),this.iframe=l(this.opts.parent)}return e.prototype.getIFrame=function(){return this.iframe},e.prototype.print=function(e,t,n,o){if(!this.isLoading){var l=this.iframe,s=l.contentDocument,u=l.contentWindow;if(s&&u&&(this.iframe.src="about:blank",this.elCopy=e.cloneNode(!0),this.elCopy)){this.isLoading=!0,this.callback=o;var c=u.document;c.open(),c.write(''),this.addEvents();var d=this.opts,f=d.headElements,h=d.bodyElements;Array.isArray(f)&&f.forEach((function(e){return c.head.appendChild(e)})),Array.isArray(h)&&h.forEach((function(e){return c.body.appendChild(e)})),Array.isArray(t)&&t.forEach((function(e){e&&c.head.appendChild(r(e)?i(c,e):a(c,e))})),c.body.appendChild(this.elCopy),Array.isArray(n)&&n.forEach((function(e){if(e){var t=c.createElement("script");r(e)?t.src=e:t.innerText=e,c.body.appendChild(t)}})),c.close()}}},e.prototype.printURL=function(e,t){this.isLoading||(this.addEvents(),this.isLoading=!0,this.callback=t,this.iframe.src=e)},e.prototype.onBeforePrint=function(e){this.onbeforeprint=e},e.prototype.onAfterPrint=function(e){this.onafterprint=e},e.prototype.launchPrint=function(e){this.isLoading||e.print()},e.prototype.addEvents=function(){var e=this;if(!this.hasEvents){this.hasEvents=!0,this.iframe.addEventListener("load",(function(){return e.onLoad()}),!1);var t=this.iframe.contentWindow;t&&(this.onbeforeprint&&t.addEventListener("beforeprint",this.onbeforeprint),this.onafterprint&&t.addEventListener("afterprint",this.onafterprint))}},e.prototype.onLoad=function(){var e=this;if(this.iframe){this.isLoading=!1;var t=this.iframe,n=t.contentDocument,o=t.contentWindow;if(!n||!o)return;"function"==typeof this.callback?this.callback({iframe:this.iframe,element:this.elCopy,launchPrint:function(){return e.launchPrint(o)}}):this.launchPrint(o)}},e}();t.Printd=u,t.default=u},4300:function(e,t,n){"use strict";function o(e){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.CopyToClipboard=void 0;var r=l(n(7363)),a=l(n(640)),i=["text","onCopy","options","children"];function l(e){return e&&e.__esModule?e:{default:e}}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function u(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}function d(e,t){for(var n=0;n=0;--a){var i=this.tryEntries[a],l=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var s=o.call(i,"catchLoc"),u=o.call(i,"finallyLoc");if(s&&u){if(this.prev=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),w(n),E}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var o=n.completion;if("throw"===o.type){var r=o.arg;w(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(e,n,o){return this.delegate={iterator:D(e),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=t),E}},e}(e.exports);try{regeneratorRuntime=t}catch(e){"object"==typeof globalThis?globalThis.regeneratorRuntime=t:Function("r","regeneratorRuntime = r")(t)}},1742:function(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],o=0;o{(0,o.default)(),(0,r.default)(),(0,a.default)()}))},460:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=l(n(6648)),r=l(n(440)),a=l(n(6021)),i=l(n(9521));function l(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{(0,i.default)(),o.default.component.registerMany({MFARegister:r.default,RegisteredMFAMethodListField:a.default})}},7355:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(6648)),r=i(n(6683)),a=i(n(4180));function i(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{(0,a.default)(),o.default.reducer.register("mfaAdministration",r.default)}},941:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=a(n(6648)),r=a(n(3311));function a(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{o.default.transform("apply-sudo-mode-to-mfa",(e=>{e.component("RegisteredMFAMethodListField",r.default)}))}},9521:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(9487)),r=i(n(1284)),a=i(n(6648));function i(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{a.default.component.registerMany({BackupCodeRegister:o.default,BackupCodeVerify:r.default})}},4180:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(6648)),r=i(n(7286)),a=i(n(23));function i(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{o.default.reducer.register("mfaRegister",r.default),o.default.reducer.register("mfaVerify",a.default)}},9487:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=s(n(7086)),a=s(n(9768)),i=n(4855),l=n(1661);function s(e){return e&&e.__esModule?e:{default:e}}function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}class c extends o.Component{constructor(e){super(e),this.state={recentlyCopied:!1},this.printRef=null,this.setPrintRef=e=>{this.printRef=e},this.copyMessageTimeout=null,this.handlePrint=this.handlePrint.bind(this),this.handleCopy=this.handleCopy.bind(this)}getFormattedCodes(){const{codes:e}=this.props;return e.map((e=>(0,l.formatCode)(e)))}handlePrint(e){e.preventDefault(),(new a.default).print(this.printRef,['body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif }'])}handleCopy(e){e.preventDefault();const{copyFeedbackDuration:t}=this.props;this.setState({recentlyCopied:!0}),this.copyMessageTimeout&&clearTimeout(this.copyMessageTimeout),this.copyMessageTimeout=setTimeout((()=>{this.setState({recentlyCopied:!1})}),t)}renderCodes(){return o.default.createElement("pre",{ref:this.setPrintRef,className:"mfa-register-backup-codes__code-grid"},this.getFormattedCodes().map((e=>o.default.createElement("div",{key:e},e))))}renderDescription(){const{ss:{i18n:e}}=window,{method:{supportLink:t,supportText:n}}=this.props;return o.default.createElement("p",null,e._t("MFABackupCodesRegister.DESCRIPTION","Recovery codes enable you to log into your account in the event your primary authentication is not available. Each code can only be used once. Store these codes somewhere safe, as they will not be viewable after leaving this page.")," ",t&&o.default.createElement("a",{href:t,target:"_blank",rel:"noopener noreferrer"},n||e._t("MFARegister.RECOVERY_HELP","Learn more about recovery codes.")))}renderPrintAction(){const{ss:{i18n:e}}=window;return o.default.createElement("button",{type:"button",onClick:this.handlePrint,className:"btn btn-link"},e._t("MFABackupCodesRegister.PRINT","Print codes"))}renderDownloadAction(){const{codes:e,method:t}=this.props,{Blob:n,URL:r,ss:{i18n:a},navigator:i}=window,l=`${t.name}.txt`,s=new n([e.join("\r\n")],{type:"text/plain;charset=UTF-8"}),u=r.createObjectURL(s);return o.default.createElement("a",{download:l,href:u,className:"btn btn-link",onClick:e=>{i.msSaveBlob&&(e.preventDefault(),i.msSaveBlob(s,l))}},a._t("MFABackupCodesRegister.DOWNLOAD","Download"))}renderCopyAction(){const{codes:e}=this.props,{recentlyCopied:t}=this.state,{ss:{i18n:n}}=window,r=t?n._t("MFABackupCodesRegister.COPY_RECENT","Copied!"):n._t("MFABackupCodesRegister.COPY","Copy codes");return o.default.createElement(i.CopyToClipboard,{text:e.join("\n")},o.default.createElement("button",{type:"button",className:"mfa-register-backup-codes__copy-to-clipboard btn btn-link",onClick:this.handleCopy},r))}render(){const{onCompleteRegistration:e}=this.props,{ss:{i18n:t}}=window;return o.default.createElement("div",{className:"mfa-register-backup-codes__container"},this.renderDescription(),this.renderCodes(),o.default.createElement("div",{className:"mfa-register-backup-codes__helper-links"},this.renderPrintAction(),this.renderDownloadAction(),this.renderCopyAction()),o.default.createElement("button",{className:"btn btn-primary",onClick:()=>e()},t._t("MFABackupCodesRegister.FINISH","Finish")))}}c.propTypes={codes:r.default.arrayOf(r.default.string),copyFeedbackDuration:r.default.number},c.defaultProps={copyFeedbackDuration:3e3};t.default=c},1284:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=i(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var l=r?Object.getOwnPropertyDescriptor(e,a):null;l&&(l.get||l.set)?Object.defineProperty(o,a,l):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),a=(o=n(7820))&&o.__esModule?o:{default:o};function i(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(i=function(e){return e?n:t})(e)}class l extends r.Component{constructor(e){super(e),this.state={value:""},this.codeInput=r.default.createRef(),this.handleChange=this.handleChange.bind(this),this.handleCompleteVerification=this.handleCompleteVerification.bind(this)}componentDidMount(){this.codeInput.current&&this.codeInput.current.focus()}handleChange(e){this.setState({value:e.target.value})}handleCompleteVerification(e){e.preventDefault();const{onCompleteVerification:t}=this.props;t({code:this.state.value})}renderControls(){const{moreOptionsControl:e}=this.props,{ss:{i18n:t}}=window;return r.default.createElement("ul",{className:"mfa-action-list mfa-action-list--backup-codes"},r.default.createElement("li",{className:"mfa-action-list__item"},r.default.createElement("button",{className:"btn btn-primary",disabled:0===this.state.value.length,onClick:this.handleCompleteVerification},t._t("MFABackupCodesVerify.NEXT","Next"))),e&&r.default.createElement("li",{className:"mfa-action-list__item"},e))}renderDescription(){const{ss:{i18n:e}}=window,{method:t}=this.props;return r.default.createElement("p",null,e._t("MFABackupCodesVerify.DESCRIPTION","Use one of the recovery codes you received")," ",t&&t.supportLink&&r.default.createElement("a",{href:t.supportLink,target:"_blank",rel:"noopener noreferrer"},e._t("MFARegister.RECOVERY_HELP","How to use recovery codes.")))}renderInput(){const{error:e}=this.props,{ss:{i18n:t}}=window,n=t._t("MFABackupCodesVerify.LABEL","Enter recovery code"),o=(0,a.default)("mfa-verify-backup-codes__input-container",{"has-error":!!e});return r.default.createElement("div",{className:o},r.default.createElement("label",{htmlFor:"backup-code",className:"control-label"},n),r.default.createElement("input",{className:"mfa-verify-backup-codes__input text form-control",type:"text",placeholder:n,id:"backup-code",ref:this.codeInput,onChange:this.handleChange}),e&&r.default.createElement("div",{className:"help-block"},e))}render(){const{graphic:e,name:t}=this.props;return r.default.createElement("form",{className:"mfa-verify-backup-codes__container"},r.default.createElement("div",{className:"mfa-verify-backup-codes__content"},this.renderDescription(),this.renderInput()),r.default.createElement("div",{className:"mfa-verify-backup-codes__image-holder"},r.default.createElement("img",{className:"mfa-verify-backup-codes__image",src:e,alt:t})),this.renderControls())}}t.default=l},2469:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=h(n(7086)),r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=f(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),a=h(n(4510)),i=h(n(42)),l=h(n(3141)),s=h(n(5292)),u=h(n(1820)),c=h(n(3947)),d=(h(n(5666)),h(n(7462)));function f(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(f=function(e){return e?n:t})(e)}function h(e){return e&&e.__esModule?e:{default:e}}class p extends r.Component{constructor(e){super(e),this.state={complete:!1,failed:!1,submitting:!1},this.handleSendReset=this.handleSendReset.bind(this)}async handleSendReset(){const{ss:{i18n:e}}=window,t=e._t("MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION",d.default["MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION"]),n=e._t("MultiFactorAuthentication.CONFIRMATION_TITLE",d.default["MultiFactorAuthentication.CONFIRMATION_TITLE"]),o=e._t("MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION_BUTTON",d.default["MultiFactorAuthentication.ACCOUNT_RESET_CONFIRMATION_BUTTON"]);if(!await(0,l.default)({title:n,message:t,confirmText:o}))return;this.setState({submitting:!0});const r=JSON.stringify({csrf_token:a.default.get("SecurityID")});(0,i.default)(this.props.resetEndpoint,"POST",r).then((e=>e.json())).then((e=>{const t=!!e.error;this.setState({complete:!0,failed:t,submitting:!1})})).catch((()=>{this.setState({complete:!0,failed:!0,submitting:!1})}))}renderAction(){const{ss:{i18n:e}}=window,{resetEndpoint:t}=this.props,{complete:n,submitting:o}=this.state;return n||o?null:r.default.createElement("p",{className:"account-reset-action"},r.default.createElement("button",{className:"btn btn-outline-secondary",disabled:!t,onClick:this.handleSendReset,type:"button"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_ACTION",d.default["MultiFactorAuthentication.ACCOUNT_RESET_ACTION"])))}renderSending(){const{ss:{i18n:e}}=window,{LoadingIndicatorComponent:t}=this.props;return r.default.createElement("p",{className:"account-reset-action account-reset-action--sending"},r.default.createElement("span",{className:"account-reset-action__icon"},r.default.createElement(t,{size:"32px"})),r.default.createElement("span",{className:"account-reset-action__message"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_SENDING",d.default["MultiFactorAuthentication.ACCOUNT_RESET_SENDING"])))}renderFailure(){const{ss:{i18n:e}}=window;return r.default.createElement("p",{className:"account-reset-action account-reset-action--failure"},r.default.createElement("span",{className:"account-reset-action__icon"},r.default.createElement(u.default,{size:"32px"})),r.default.createElement("span",{className:"account-reset-action__message"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_SENDING",d.default["MultiFactorAuthentication.ACCOUNT_RESET_SENDING_FAILURE"])))}renderSuccess(){const{ss:{i18n:e}}=window;return r.default.createElement("p",{className:"account-reset-action account-reset-action--success"},r.default.createElement("span",{className:"account-reset-action__icon"},r.default.createElement(c.default,{size:"32px"})),r.default.createElement("span",{className:"account-reset-action__message"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_SENDING_SUCCESS",d.default["MultiFactorAuthentication.ACCOUNT_RESET_SENDING_SUCCESS"])))}renderStatusMessage(){const{complete:e,failed:t,submitting:n}=this.state;return n?this.renderSending():e?t?this.renderFailure():this.renderSuccess():null}render(){const{ss:{i18n:e}}=window;return r.default.createElement("div",{className:"account-reset"},r.default.createElement("h5",{className:"account-reset__title"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_TITLE",d.default["MultiFactorAuthentication.ACCOUNT_RESET_TITLE"])),r.default.createElement("p",{className:"account-reset__description"},e._t("MultiFactorAuthentication.ACCOUNT_RESET_DESCRIPTION",d.default["MultiFactorAuthentication.ACCOUNT_RESET_DESCRIPTION"])),this.renderAction(),this.renderStatusMessage())}}p.propTypes={resetEndpoint:o.default.string,LoadingIndicatorComponent:o.default.oneOfType([o.default.object,o.default.func])},p.defaultProps={LoadingIndicatorComponent:s.default};t.default=p},1509:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=p(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=h(n(3141)),a=h(n(7086)),i=h(n(7820)),l=h(n(8488)),s=h(n(5695)),u=h(n(2468)),c=h(n(9831)),d=h(n(8628)),f=h(n(7462));function h(e){return e&&e.__esModule?e:{default:e}}function p(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(p=function(e){return e?n:t})(e)}class m extends o.PureComponent{getStatusMessage(){const{isBackupMethod:e,isDefaultMethod:t}=this.props,{ss:{i18n:n}}=window;return t?n._t("MultiFactorAuthentication.DEFAULT_REGISTERED",f.default["MultiFactorAuthentication.DEFAULT_REGISTERED"]):e?n._t("MultiFactorAuthentication.BACKUP_REGISTERED",f.default["MultiFactorAuthentication.BACKUP_REGISTERED"]):n._t("MultiFactorAuthentication.REGISTERED",f.default["MultiFactorAuthentication.REGISTERED"])}renderRemove(){const{canRemove:e,method:t,RemoveComponent:n}=this.props;return e?o.default.createElement(n,{method:t}):null}renderReset(){const{canReset:e,isBackupMethod:t,method:n}=this.props;if(!e)return null;const a={method:n};if(t){const{ss:{i18n:e}}=window,t=e._t("MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION",f.default["MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION"]),n=e._t("MultiFactorAuthentication.CONFIRMATION_TITLE",f.default["MultiFactorAuthentication.CONFIRMATION_TITLE"]),o=e._t("MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION_BUTTON",f.default["MultiFactorAuthentication.RESET_BACKUP_CONFIRMATION_BUTTON"]);a.onReset=async e=>{await(0,r.default)({title:n,message:t,confirmText:o})&&e()}}return o.default.createElement(c.default,a)}renderSetAsDefault(){const{isDefaultMethod:e,isBackupMethod:t,method:n,SetDefaultComponent:r}=this.props;return e||t?null:o.default.createElement(r,{method:n})}renderControls(){const{canRemove:e,canReset:t}=this.props;return e||t?o.default.createElement("div",null,this.renderRemove(),this.renderReset(),this.renderSetAsDefault()):null}renderNameAndStatus(){const{method:e,createdDate:t}=this.props,{ss:{i18n:n}}=window,o=this.getStatusMessage();return l.default.locale(n.detectLocale()),n.inject(o,{method:e.name,date:(0,l.default)(t).format("L")})}render(){const{tag:e,className:t}=this.props,n=(0,i.default)(t,"registered-method-list-item");return o.default.createElement(e,{className:n},this.renderNameAndStatus(),this.renderControls())}}m.propTypes={method:s.default.isRequired,isDefaultMethod:a.default.bool,isBackupMethod:a.default.bool,canRemove:a.default.bool,canReset:a.default.bool,onRemove:a.default.func,onReset:a.default.func,createdDate:a.default.string,className:a.default.string,tag:a.default.string,RemoveComponent:a.default.oneOfType([a.default.object,a.default.func]),SetDefaultComponent:a.default.oneOfType([a.default.object,a.default.func])},m.defaultProps={isDefaultMethod:!1,isBackupMethod:!1,canRemove:!1,canReset:!1,tag:"li",RemoveComponent:u.default,SetDefaultComponent:d.default};t.default=m},2468:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=h(n(7363)),r=h(n(7086)),a=n(1624),i=h(n(3141)),l=h(n(4510)),s=h(n(42)),u=n(8631),c=n(9861),d=h(n(5695)),f=h(n(7462));function h(e){return e&&e.__esModule?e:{default:e}}const p=(e,t)=>{let{method:n,onRemove:r,defaultMethod:a,registeredMethods:u,onDeregisterMethod:c,onAddAvailableMethod:d,onSetDefaultMethod:h}=e,{backupMethod:p,endpoints:{remove:m}}=t;const{ss:{i18n:E}}=window,M=async()=>{const e=E._t("MultiFactorAuthentication.DELETE_CONFIRMATION",f.default["MultiFactorAuthentication.DELETE_CONFIRMATION"]),t=E._t("MultiFactorAuthentication.CONFIRMATION_TITLE",f.default["MultiFactorAuthentication.CONFIRMATION_TITLE"]),o=E._t("MultiFactorAuthentication.DELETE_CONFIRMATION_BUTTON",f.default["MultiFactorAuthentication.DELETE_CONFIRMATION_BUTTON"]);if(!await(0,i.default)({title:t,message:e,confirmText:o}))return;const r=l.default.get("SecurityID"),M=`${m.replace("{urlSegment}",n.urlSegment)}?SecurityID=${r}`;(0,s.default)(M,"DELETE").then((e=>e.json().then((t=>{if(200===e.status)return c(n),d(t.availableMethod),n.urlSegment===a&&h(null),void(!t.hasBackupMethod&&p&&u.find((e=>e.urlSegment===p.urlSegment))&&c(p));const o=t.errors&&` Errors: \n - ${t.errors.join("\n -")}`||"";throw Error(`Could not delete method. Error code ${e.status}.${o}`)}))))};return o.default.createElement("button",{className:"registered-method-list-item__control",type:"button",onClick:r?r(M):M},E._t("MultiFactorAuthentication.REMOVE_METHOD",f.default["MultiFactorAuthentication.REMOVE_METHOD"]))};p.propTypes={method:d.default.isRequired,onRemove:r.default.func,defaultMethod:r.default.string.isRequired,registeredMethods:r.default.arrayOf(d.default).isRequired,onDeregisterMethod:r.default.func.isRequired,onAddAvailableMethod:r.default.func.isRequired,onSetDefaultMethod:r.default.func.isRequired},p.contextTypes={backupMethod:d.default,endpoints:r.default.shape({register:r.default.string,remove:r.default.string})};t.default=(0,a.connect)((e=>{let{mfaAdministration:{defaultMethod:t,registeredMethods:n}}=e;return{defaultMethod:t,registeredMethods:n}}),(e=>({onDeregisterMethod:t=>{e((0,c.deregisterMethod)(t))},onAddAvailableMethod:t=>{e((0,u.addAvailableMethod)(t))},onSetDefaultMethod:t=>e((0,c.setDefaultMethod)(t))})))(p)},9831:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=h(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=f(n(7086)),a=n(1624),i=n(440),l=n(8631),s=f(n(5695)),u=f(n(2949)),c=f(n(7442)),d=f(n(7462));function f(e){return e&&e.__esModule?e:{default:e}}function h(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(h=function(e){return e?n:t})(e)}class p extends o.Component{constructor(e){super(e),this.state={modalOpen:!1},this.handleReset=this.handleReset.bind(this),this.handleToggleModal=this.handleToggleModal.bind(this)}handleToggleModal(){this.setState((e=>({modalOpen:!e.modalOpen})))}handleReset(){const{onResetMethod:e,method:t}=this.props,{allAvailableMethods:n}=this.context,o=n.find((e=>e.urlSegment===t.urlSegment));if(!o)throw Error(`Cannot register the method given: ${t.name} (${t.urlSegment}).`);e(o),this.handleToggleModal()}render(){const{onReset:e}=this.props,{backupMethod:t,endpoints:n,resources:r}=this.context,a=e?()=>e(this.handleReset):this.handleReset;return o.default.createElement("button",{className:"registered-method-list-item__control",type:"button",onClick:a},window.ss.i18n._t("MultiFactorAuthentication.RESET_METHOD",d.default["MultiFactorAuthentication.RESET_METHOD"]),o.default.createElement(c.default,{backupMethod:t,isOpen:this.state.modalOpen,toggle:this.handleToggleModal,resources:r,endpoints:n,disallowedScreens:[i.SCREEN_CHOOSE_METHOD,i.SCREEN_INTRODUCTION]}))}}p.propTypes={method:s.default.isRequired,onReset:r.default.func},p.contextTypes={allAvailableMethods:r.default.arrayOf(u.default),backupMethod:s.default,endpoints:r.default.shape({register:r.default.string}),resources:r.default.object};t.default=(0,a.connect)(null,(e=>({onResetMethod:t=>{e((0,l.chooseMethod)(t)),e((0,l.showScreen)(i.SCREEN_REGISTER_METHOD))}})))(p)},8628:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=f(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=d(n(7086)),a=d(n(5695)),i=d(n(4510)),l=n(1624),s=d(n(42)),u=n(9861),c=d(n(7462));function d(e){return e&&e.__esModule?e:{default:e}}function f(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(f=function(e){return e?n:t})(e)}class h extends o.Component{constructor(e){super(e),this.handleSetDefault=this.handleSetDefault.bind(this)}handleSetDefault(){const{method:e,onSetDefaultMethod:t}=this.props,{endpoints:{setDefault:n}}=this.context,o=i.default.get("SecurityID"),r=`${n.replace("{urlSegment}",e.urlSegment)}?SecurityID=${o}`;(0,s.default)(r,"PUT").then((n=>n.json().then((o=>{if(200===n.status)return void t(e.urlSegment);const r=o.errors&&` Errors: \n - ${o.errors.join("\n -")}`||"";throw Error(`Could not set default method. Error code ${n.status}.${r}`)}))))}render(){const{ss:{i18n:e}}=window;return o.default.createElement("button",{className:"registered-method-list-item__control",type:"button",onClick:this.handleSetDefault},e._t("MultiFactorAuthentication.SET_AS_DEFAULT",c.default["MultiFactorAuthentication.SET_AS_DEFAULT"]))}}t.Component=h,h.propTypes={method:a.default.isRequired},h.contextTypes={endpoints:r.default.shape({setDefault:r.default.string})};t.default=(0,l.connect)(null,(e=>({onSetDefaultMethod:t=>e((0,u.setDefaultMethod)(t))})))(h)},6021:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=_(n(7086)),r=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=M(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),a=n(8127),i=n(1624),l=_(n(7820)),s=_(n(5695)),u=_(n(2949)),c=n(8631),d=n(9861),f=n(440),h=_(n(1509)),p=_(n(2469)),m=_(n(7442)),E=_(n(7462));function M(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(M=function(e){return e?n:t})(e)}function _(e){return e&&e.__esModule?e:{default:e}}class g extends r.Component{constructor(e){super(e),this.state={modalOpen:!1},this.handleToggleModal=this.handleToggleModal.bind(this)}getChildContext(){const{allAvailableMethods:e,backupMethod:t,endpoints:n,resources:o}=this.props;return{allAvailableMethods:e,backupMethod:t,endpoints:n,resources:o}}componentDidMount(){const{onSetDefaultMethod:e,initialDefaultMethod:t,onSetRegisteredMethods:n,initialRegisteredMethods:o,onUpdateAvailableMethods:r,initialAvailableMethods:a}=this.props;n(o),r(a),e(t)}getBaseMethods(){const{backupMethod:e}=this.props;let{registeredMethods:t}=this.props;return t?(e&&(t=t.filter((t=>t.urlSegment!==e.urlSegment))),t):[]}handleToggleModal(){this.setState((e=>({modalOpen:!e.modalOpen})))}renderNoMethodsMessage(){if(this.getBaseMethods().length)return null;const{readOnly:e}=this.props,{ss:{i18n:t}}=window,n=e?"MultiFactorAuthentication.NO_METHODS_REGISTERED_READONLY":"MultiFactorAuthentication.NO_METHODS_REGISTERED";return r.default.createElement("div",{className:"registered-mfa-method-list-field__no-methods"},t._t(n,E.default[n]))}renderBackupMethod(){const{backupMethod:e,backupCreatedDate:t,registeredMethods:n,readOnly:o,MethodListItemComponent:a}=this.props;if(!e)return null;const i=n.find((t=>t.urlSegment===e.urlSegment));return i?r.default.createElement(a,{method:i,createdDate:t,canReset:!o,isBackupMethod:!0,tag:"div",className:"registered-method-list-item--backup"}):null}renderBaseMethods(){const{isMFARequired:e}=this.props,t=this.getBaseMethods();if(!t.length)return[];const{defaultMethod:n,readOnly:o,MethodListItemComponent:a}=this.props;return t.map((i=>{const l={method:i,key:i.urlSegment,isDefaultMethod:n&&i.urlSegment===n,canRemove:!(o||e&&1===t.length),canReset:!o};return r.default.createElement(a,l)}))}renderModal(){const{backupMethod:e,endpoints:t,resources:n,RegisterModalComponent:o}=this.props;return r.default.createElement(o,{backupMethod:e,isOpen:this.state.modalOpen,toggle:this.handleToggleModal,resources:n,endpoints:t,disallowedScreens:[f.SCREEN_INTRODUCTION]})}renderAddButton(){const{availableMethods:e,registeredMethods:t,readOnly:n,onResetRegister:o}=this.props;if(n||!e||0===e.length)return null;const{ss:{i18n:i}}=window,l=t.length?i._t("MultiFactorAuthentication.ADD_ANOTHER_METHOD",E.default["MultiFactorAuthentication.ADD_ANOTHER_METHOD"]):i._t("MultiFactorAuthentication.ADD_FIRST_METHOD",E.default["MultiFactorAuthentication.ADD_FIRST_METHOD"]);return r.default.createElement(a.Button,{className:"registered-mfa-method-list-field__button",outline:!0,type:"button",onClick:()=>{this.handleToggleModal(),o()}},l)}render(){const{readOnly:e,resetEndpoint:t}=this.props,n=(0,l.default)({"registered-mfa-method-list-field":!0,"registered-mfa-method-list-field--read-only":e});return r.default.createElement("div",{className:n},r.default.createElement("ul",{className:"method-list"},this.renderBaseMethods()),this.renderNoMethodsMessage(),this.renderAddButton(),this.renderBackupMethod(),e&&r.default.createElement("hr",null),e&&r.default.createElement(p.default,{resetEndpoint:t}),this.renderModal())}}t.Component=g,g.propTypes={backupMethod:s.default,defaultMethod:o.default.string,readOnly:o.default.bool,isMFARequired:o.default.bool,initialDefaultMethod:o.default.string,initialRegisteredMethods:o.default.arrayOf(s.default),initialAvailableMethods:o.default.arrayOf(u.default),allAvailableMethods:o.default.arrayOf(u.default),resetEndpoint:o.default.string,endpoints:o.default.shape({register:o.default.string,remove:o.default.string}),resources:o.default.object,availableMethods:o.default.arrayOf(u.default),registeredMethods:o.default.arrayOf(s.default),registrationScreen:o.default.number,MethodListItemComponent:o.default.oneOfType([o.default.object,o.default.func]),RegisterModalComponent:o.default.oneOfType([o.default.object,o.default.func])},g.defaultProps={initialAvailableMethods:[],MethodListItemComponent:h.default,RegisterModalComponent:m.default},g.childContextTypes={allAvailableMethods:o.default.arrayOf(u.default),backupMethod:s.default,endpoints:o.default.shape({register:o.default.string,remove:o.default.string,setDefault:o.default.string}),resources:o.default.object};t.default=(0,i.connect)((e=>{const{availableMethods:t,screen:n}=e.mfaRegister,{defaultMethod:o,registeredMethods:r}=e.mfaAdministration;return{availableMethods:t,defaultMethod:o,registeredMethods:r||[],registrationScreen:n}}),(e=>({onResetRegister:()=>{e((0,c.chooseMethod)(null)),e((0,c.showScreen)(f.SCREEN_CHOOSE_METHOD))},onUpdateAvailableMethods:t=>{e((0,c.setAvailableMethods)(t))},onSetDefaultMethod:t=>{e((0,d.setDefaultMethod)(t))},onSetRegisteredMethods:t=>{e((0,d.setRegisteredMethods)(t))}})))(g)},1820:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7363))&&o.__esModule?o:{default:o};t.default=e=>{let{color:t="currentColor",size:n="3em"}=e;return r.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",height:n,width:n},r.default.createElement("g",{fill:t},r.default.createElement("path",{d:"M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z"})))}},3947:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7363))&&o.__esModule?o:{default:o};t.default=e=>{let{color:t="currentColor",size:n="3em"}=e;return r.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",height:n,width:n},r.default.createElement("g",{fill:t},r.default.createElement("path",{d:"M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"})))}},5292:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=a(n(7363)),r=a(n(7820));function a(e){return e&&e.__esModule?e:{default:e}}t.default=e=>{let{block:t=!1,size:n="6em"}=e;return o.default.createElement("div",{style:{height:n,width:n},className:(0,r.default)({"mfa-loading-indicator":!0,"mfa-loading-indicator--block":t})})}},440:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.SCREEN_REGISTER_METHOD=t.SCREEN_INTRODUCTION=t.SCREEN_COMPLETE=t.SCREEN_CHOOSE_METHOD=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=M(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=E(n(7086)),a=E(n(42)),i=n(6648),l=E(n(2949)),s=E(n(5695)),u=E(n(5292)),c=E(n(6910)),d=E(n(3954)),f=E(n(1824)),h=n(1624),p=n(8631),m=E(n(1196));function E(e){return e&&e.__esModule?e:{default:e}}function M(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(M=function(e){return e?n:t})(e)}function _(){return _=Object.assign?Object.assign.bind():function(e){for(var t=1;te.json().then((e=>{const{SecurityID:t,...n}=e;this.setState({registerProps:n,token:t})}))))}handleBack(){const{availableMethods:e,onShowIntroduction:t,onShowChooseMethod:n}=this.props;return 1===e.length&&t?t():(this.setState({registerProps:null}),n())}handleCompleteRegistration(e){const{endpoints:{register:t},selectedMethod:n,onRemoveAvailableMethod:o,onRegister:r}=this.props,{token:i}=this.state,l=i?`?SecurityID=${i}`:"";(0,a.default)(`${t.replace("{urlSegment}",n.urlSegment)}${l}`,"POST",JSON.stringify(e)).then((e=>201===e.status?(this.setState({registerProps:null}),"function"==typeof r&&r(n),o(n),this.setupBackupMethod(),null):e.json())).then((e=>{if(e&&e.errors){const t=e.errors.join(", ");this.setState((e=>({registerProps:{...e.registerProps,error:t}})))}}))}shouldSetupBackupMethod(){const{backupMethod:e,registeredMethods:t}=this.props;return!!e&&!t.find((t=>t.urlSegment===e.urlSegment))}handleSkip(){const{skip:e}=this.props.endpoints;e&&(window.location=this.props.endpoints.skip)}renderIntroduction(){const{canSkip:e,resources:t,endpoints:{skip:n},showSubTitle:r,IntroductionComponent:a}=this.props;return o.default.createElement(a,{canSkip:n&&e,onSkip:this.handleSkip,resources:t,showTitle:r})}renderMethod(){const{selectedMethod:e,showSubTitle:t,TitleComponent:n}=this.props,{registerProps:r}=this.state;if(!e)return null;if(!r)return o.default.createElement(u.default,{block:!0});const a=(0,i.loadComponent)(e.component);return o.default.createElement("div",null,t&&o.default.createElement(n,null),o.default.createElement(a,_({},r,{method:e,onBack:this.handleBack,onCompleteRegistration:this.handleCompleteRegistration})))}renderOptions(){const{availableMethods:e,showSubTitle:t,SelectMethodComponent:n}=this.props;return o.default.createElement(n,{methods:e,showTitle:t})}render(){const{screen:e,onCompleteRegistration:t,showTitle:n,showSubTitle:r,completeMessage:a,CompleteComponent:i}=this.props,{ss:{i18n:l}}=window;if(e===v)return o.default.createElement(i,{showTitle:r,onComplete:t,message:a});let s;switch(e){case b:s=this.renderOptions();break;case y:s=this.renderMethod();break;default:s=this.renderIntroduction()}return o.default.createElement("div",null,n&&o.default.createElement("h1",{className:"mfa-app-title"},l._t("MFARegister.TITLE","Multi-factor authentication")),s)}}t.Component=O,O.propTypes={availableMethods:r.default.arrayOf(l.default),backupMethod:l.default,canSkip:r.default.bool,endpoints:r.default.shape({register:r.default.string.isRequired,skip:r.default.string}),onRegister:r.default.func,onCompleteRegistration:r.default.func.isRequired,registeredMethods:r.default.arrayOf(s.default),resources:r.default.object,showTitle:r.default.bool,showSubTitle:r.default.bool,IntroductionComponent:r.default.oneOfType([r.default.object,r.default.func]),SelectMethodComponent:r.default.oneOfType([r.default.object,r.default.func]),CompleteComponent:r.default.oneOfType([r.default.object,r.default.func]),TitleComponent:r.default.oneOfType([r.default.object,r.default.func])},O.defaultProps={resources:{},showTitle:!0,showSubTitle:!0,showIntroduction:!0,IntroductionComponent:c.default,SelectMethodComponent:f.default,CompleteComponent:d.default,TitleComponent:m.default};t.default=(0,h.connect)((e=>{const t=e.mfaRegister||e;return{screen:t.screen,selectedMethod:t.method,availableMethods:t.availableMethods}}),(e=>({onShowIntroduction:()=>e((0,p.showScreen)(g)),onShowComplete:()=>e((0,p.showScreen)(v)),onSelectMethod:t=>e((0,p.chooseMethod)(t)),onShowChooseMethod:()=>{e((0,p.chooseMethod)(null)),e((0,p.showScreen)(b))},onRemoveAvailableMethod:t=>e((0,p.removeAvailableMethod)(t))})))(O)},3954:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=i(n(7363)),r=i(n(7086)),a=i(n(1196));function i(e){return e&&e.__esModule?e:{default:e}}const l=e=>{let{onComplete:t,showTitle:n,message:r}=e;return o.default.createElement("div",{className:"mfa-register-confirmation"},o.default.createElement("i",{className:"font-icon-check-mark mfa-register-confirmation__icon"}),n&&o.default.createElement(a.default,{className:"mfa-register-confirmation__title"}),o.default.createElement("p",{className:"mfa-register-confirmation__description"},r||window.ss.i18n._t("MFARegister.SETUP_COMPLETE_DESCRIPTION","You will be able to edit these settings later from your profile area.")),o.default.createElement("button",{onClick:t,className:"mfa-register-confirmation__continue btn btn-primary"},window.ss.i18n._t("MFARegister.SETUP_COMPLETE_CONTINUE","Continue")))};l.propTypes={onComplete:r.default.func.isRequired,showTitle:r.default.bool},l.defaultProps={showTitle:!0};t.default=l},6910:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=t.ActionList=void 0;var o=c(n(7363)),r=c(n(7086)),a=n(8631),i=n(1624),l=n(440),s=c(n(1196)),u=c(n(7462));function c(e){return e&&e.__esModule?e:{default:e}}const d=e=>{let{canSkip:t,onContinue:n,onSkip:r}=e;const{ss:{i18n:a}}=window;return o.default.createElement("ul",{className:"mfa-action-list"},o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-primary",onClick:n},a._t("MultiFactorAuthentication.GET_STARTED",u.default["MultiFactorAuthentication.GET_STARTED"]))),t&&o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-secondary",onClick:r},a._t("MultiFactorAuthentication.SETUP_LATER",u.default["MultiFactorAuthentication.SETUP_LATER"]))))};t.ActionList=d;const f=e=>{let{canSkip:t,onContinue:n,onSkip:r,resources:a,showTitle:i,TitleComponent:l}=e;const{ss:{i18n:s}}=window;return o.default.createElement("div",null,i&&o.default.createElement(l,null),o.default.createElement("h4",{className:"mfa-feature-list-title"},s._t("MultiFactorAuthentication.HOW_IT_WORKS",u.default["MultiFactorAuthentication.HOW_IT_WORKS"])),o.default.createElement("ul",{className:"mfa-feature-list"},o.default.createElement("li",{className:"mfa-feature-list-item"},a.extra_factor_image_url&&o.default.createElement("img",{alt:s._t("MultiFactorAuthentication.EXTRA_LAYER_IMAGE_ALT",u.default["MultiFactorAuthentication.EXTRA_LAYER_IMAGE_ALT"]),"aria-hidden":"true",className:"mfa-feature-list-item__icon",src:a.extra_factor_image_url}),o.default.createElement("div",{className:"mfa-feature-list-item__content"},o.default.createElement("h5",{className:"mfa-block-heading mfa-feature-list-item__title"},s._t("MultiFactorAuthentication.EXTRA_LAYER_TITLE",u.default["MultiFactorAuthentication.EXTRA_LAYER_TITLE"])),o.default.createElement("p",{className:"mfa-feature-list-item__description"},s._t("MultiFactorAuthentication.EXTRA_LAYER_DESCRIPTION",u.default["MultiFactorAuthentication.EXTRA_LAYER_DESCRIPTION"])," ",a.user_help_link&&o.default.createElement("a",{href:a.user_help_link},s._t("MultiFactorAuthentication.HOW_MFA_WORKS",u.default["MultiFactorAuthentication.HOW_MFA_WORKS"]))))),o.default.createElement("li",{className:"mfa-feature-list-item"},a.unique_image_url&&o.default.createElement("img",{alt:s._t("MultiFactorAuthentication.UNIQUE_IMAGE_ALT",u.default["MultiFactorAuthentication.UNIQUE_IMAGE_ALT"]),"aria-hidden":"true",className:"mfa-feature-list-item__icon",src:a.unique_image_url}),o.default.createElement("div",{className:"mfa-feature-list-item__content"},o.default.createElement("h5",{className:"mfa-block-heading mfa-feature-list-item__title"},s._t("MultiFactorAuthentication.UNIQUE_TITLE",u.default["MultiFactorAuthentication.UNIQUE_TITLE"])),o.default.createElement("p",{className:"mfa-feature-list-item__description"},s._t("MultiFactorAuthentication.UNIQUE_DESCRIPTION",u.default["MultiFactorAuthentication.UNIQUE_DESCRIPTION"]))))),o.default.createElement(d,{canSkip:t,onContinue:n,onSkip:r}))};t.Component=f,f.propTypes={canSkip:r.default.bool,onContinue:r.default.func.isRequired,onSkip:r.default.func,resources:r.default.shape({user_help_link:r.default.string,extra_factor_image_url:r.default.string,unique_image_url:r.default.string}).isRequired,showTitle:r.default.bool,TitleComponent:r.default.oneOfType([r.default.object,r.default.func])},f.defaultProps={showTitle:!0,TitleComponent:s.default};t.default=(0,i.connect)(null,(e=>({onContinue:()=>{e((0,a.chooseMethod)(null)),e((0,a.showScreen)(l.SCREEN_REGISTER_METHOD))}})))(f)},3324:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=s(n(7086)),a=s(n(7820)),i=s(n(2949)),l=s(n(639));function s(e){return e&&e.__esModule?e:{default:e}}function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}class c extends o.Component{constructor(e){super(e),this.handleClick=this.handleClick.bind(this),this.handleKeyUp=this.handleKeyUp.bind(this)}handleClick(e){const{method:{isAvailable:t},onClick:n}=this.props;t&&n&&n(e)}handleKeyUp(e){13===e.keyCode&&this.handleClick(e)}renderSupportLink(e){const{ss:{i18n:t}}=window,{supportLink:n,supportText:r}=e;return n?o.default.createElement("a",{href:n,target:"_blank",rel:"noopener noreferrer",className:"mfa-method-tile__support-link"},r||t._t("MFARegister.HELP","Find out more.")):null}renderUnavailableMask(){const{ss:{i18n:e}}=window,{isAvailable:t,getUnavailableMessage:n}=this.props;if(t())return null;const r=n();return o.default.createElement("div",{className:"mfa-method-tile__unavailable-mask"},o.default.createElement("h3",{className:"mfa-method-tile__unavailable-title"},e._t("MFAMethodTile.UNAVAILABLE","Unsupported: ")),r&&o.default.createElement("p",{className:"mfa-method-tile__unavailable-text"},r))}render(){const{isActive:e,method:t}=this.props,{ss:{i18n:n}}=window,r=(0,a.default)("mfa-method-tile",{"mfa-method-tile--active":e,"mfa-method-tile--unsupported":!t.isAvailable}),i=(0,a.default)("mfa-method-tile__thumbnail-container",{"mfa-method-tile__thumbnail-container--unsupported":!t.isAvailable}),l=n.inject(n._t("MFARegister.REGISTER_WITH","Register with {method}"),{method:t.name.toLowerCase()});return o.default.createElement("li",{className:r},o.default.createElement("div",{className:"mfa-method-tile__content",onClick:this.handleClick,onKeyUp:this.handleKeyUp,tabIndex:"0",role:"button"},t.thumbnail&&o.default.createElement("div",{className:i},o.default.createElement("img",{src:t.thumbnail,className:"mfa-method-tile__thumbnail",alt:t.name})),o.default.createElement("h3",{className:"mfa-method-tile__title"},l),o.default.createElement("p",{className:"mfa-method-tile__description"},t.description&&`${t.description}. `,this.renderSupportLink(t))),this.renderUnavailableMask())}}t.Component=c,c.propTypes={getUnavailableMessage:r.default.func.isRequired,isActive:r.default.bool,isAvailable:r.default.func.isRequired,method:i.default.isRequired,onClick:r.default.func.isRequired},c.defaultProps={isActive:!1};t.default=(0,l.default)(c)},1824:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=m(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=p(n(7086)),a=p(n(2949)),i=p(n(7820)),l=n(8631),s=n(2827),u=n(1624),c=p(n(639)),d=n(440),f=p(n(3324)),h=p(n(1196));function p(e){return e&&e.__esModule?e:{default:e}}function m(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(m=function(e){return e?n:t})(e)}class E extends o.Component{constructor(e){super(e);let t=null;1===e.methods.length&&e.isAvailable&&e.isAvailable(e.methods[0])&&(t=e.methods[0]),this.state={highlightedMethod:t},this.handleGoToNext=this.handleGoToNext.bind(this),this.handleBack=this.handleBack.bind(this)}componentDidMount(){const{highlightedMethod:e}=this.state;e&&this.handleGoToNext()}handleGoToNext(){const{highlightedMethod:e}=this.state;this.props.onSelectMethod(e)}handleClick(e){this.setState({highlightedMethod:e})}handleBack(){this.props.onClickBack&&this.props.onClickBack()}renderActions(){const{ss:{i18n:e}}=window,{highlightedMethod:t}=this.state;return o.default.createElement("ul",{className:"mfa-action-list"},o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-primary",disabled:null===t,onClick:this.handleGoToNext},e._t("MFARegister.NEXT","Next"))),o.default.createElement("li",{className:"mfa-action-list__item"},o.default.createElement("button",{className:"btn btn-secondary",onClick:this.handleBack},e._t("MFARegister.BACK","Back"))))}render(){const{methods:e,showTitle:t,TitleComponent:n,MethodTileComponent:r}=this.props,{highlightedMethod:a}=this.state,l=(0,i.default)("mfa-method-tile-group",{"mfa-method-tile-group--three-columns":e.length%3==0});return o.default.createElement("div",null,t&&o.default.createElement(n,null),o.default.createElement("ul",{className:l},e.map((e=>o.default.createElement(r,{isActive:a===e,key:e.urlSegment,method:e,onClick:()=>this.handleClick(e)})))),this.renderActions())}}t.Component=E,E.propTypes={methods:r.default.arrayOf(a.default),onSelectMethod:r.default.func,onClickBack:r.default.func,showTitle:r.default.bool,TitleComponent:r.default.oneOfType([r.default.object,r.default.func]),MethodTileComponent:r.default.oneOfType([r.default.object,r.default.func])},E.defaultProps={showTitle:!0,TitleComponent:h.default,MethodTileComponent:f.default};t.default=(0,s.compose)((0,u.connect)(null,(e=>({onClickBack:()=>e((0,l.showScreen)(d.SCREEN_INTRODUCTION)),onSelectMethod:t=>{e((0,l.chooseMethod)(t)),e((0,l.showScreen)(d.SCREEN_REGISTER_METHOD))}}))),c.default)(E)},1196:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=l(n(7363)),r=n(1624),a=n(440),i=l(n(7462));function l(e){return e&&e.__esModule?e:{default:e}}const s=e=>{let{screen:t,method:n,Tag:r="h2",className:l="mfa-section-title"}=e;const{ss:{i18n:s}}=window;let u;switch(t){case a.SCREEN_INTRODUCTION:u=s._t("MultiFactorAuthentication.TITLE",i.default["MultiFactorAuthentication.TITLE"]);break;case a.SCREEN_CHOOSE_METHOD:u=s._t("MultiFactorAuthentication.SELECT_METHOD",i.default["MultiFactorAuthentication.SELECT_METHOD"]);break;case a.SCREEN_COMPLETE:u=s._t("MultiFactorAuthentication.SETUP_COMPLETE_TITLE",i.default["MultiFactorAuthentication.SETUP_COMPLETE_TITLE"]);break;case a.SCREEN_REGISTER_METHOD:u=n&&s.inject(s._t("MFARegister.REGISTER_WITH","Register with {method}"),{method:n.name.toLowerCase()});break;default:u=!1}if(!u||!u.length)return null;const c=r||"span";return o.default.createElement(c,{className:l},u)};t.Component=s;t.default=(0,r.connect)((e=>{const t=e.mfaRegister||e;return{screen:t.screen,method:t.method}}))(s)},7442:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.Component=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=m(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=r?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=p(n(7086)),a=n(8127),i=n(6648),l=n(2827),s=n(1624),u=p(n(1196)),c=n(9861),d=p(n(5695)),f=n(440),h=p(n(7462));function p(e){return e&&e.__esModule?e:{default:e}}function m(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(m=function(e){return e?n:t})(e)}class E extends o.Component{constructor(e){super(e),this.handleRegister=this.handleRegister.bind(this)}componentDidUpdate(){const{disallowedScreens:e,isOpen:t,registrationScreen:n,toggle:o}=this.props;t&&e.length&&e.includes(n)&&o()}handleRegister(e){const{onAddRegisteredMethod:t,onSetDefaultMethod:n,registeredMethods:o}=this.props;o.length||n(e.urlSegment),t(e)}render(){const{backupMethod:e,endpoints:t,isOpen:n,toggle:r,registeredMethods:i,registrationScreen:l,resources:s,RegisterComponent:c}=this.props;return o.default.createElement(a.Modal,{isOpen:n,toggle:r,className:"registered-mfa-method-list-field-register-modal"},o.default.createElement(a.ModalHeader,{toggle:r},o.default.createElement(u.default,{Tag:null})),o.default.createElement(a.ModalBody,{className:"registered-mfa-method-list-field-register-modal__content"},l!==f.SCREEN_INTRODUCTION&&o.default.createElement(c,{backupMethod:e,registeredMethods:i,onCompleteRegistration:r,onRegister:this.handleRegister,resources:s,endpoints:t,showTitle:!1,showSubTitle:!1,completeMessage:window.ss.i18n._t("MultiFactorAuthentication.ADMIN_SETUP_COMPLETE_CONTINUE",h.default["MultiFactorAuthentication.ADMIN_SETUP_COMPLETE_CONTINUE"])})))}}t.Component=E,E.propTypes={isOpen:r.default.bool,toggle:r.default.func,disallowedScreens:r.default.arrayOf(r.default.number),backupMethod:d.default,resources:r.default.object,endpoints:r.default.shape({register:r.default.string}),registrationScreen:r.default.number,registeredMethods:r.default.arrayOf(d.default),onAddRegisteredMethod:r.default.func,onSetDefaultMethod:r.default.func,RegisterComponent:r.default.oneOfType([r.default.element,r.default.func,r.default.elementType])},E.defaultProps={isOpen:!1,disallowedScreens:[]};t.default=(0,l.compose)((0,i.inject)(["MFARegister"],(e=>({RegisterComponent:e})),(()=>"MFARegisterModal")),(0,s.connect)((e=>({registrationScreen:e.mfaRegister.screen,registeredMethods:e.mfaAdministration.registeredMethods})),(e=>({onAddRegisteredMethod:t=>{e((0,c.registerMethod)(t))},onSetDefaultMethod:t=>e((0,c.setDefaultMethod)(t))}))))(E)},830:function(e,t,n){"use strict";var o,r=(o=n(7363))&&o.__esModule?o:{default:o},a=n(9691),i=n(6648);window.jQuery.entwine("ss",(e=>{e('.js-injector-boot [data-field-type="registered-mfa-method-list-field"]').entwine({ReactRoot:null,onmatch(){const e=(0,i.loadComponent)("RegisteredMFAMethodListField"),{readOnly:t,schema:{backupMethod:n,defaultMethod:o,registeredMethods:l,availableMethods:s,allAvailableMethods:u,resources:c,endpoints:d,backupCreatedDate:f,resetEndpoint:h,isMFARequired:p}}=this.data("schema");let m=this.getReactRoot();m||(m=(0,a.createRoot)(this[0]),this.setReactRoot(m)),m.render(r.default.createElement(e,{backupMethod:n,readOnly:t,initialDefaultMethod:o,initialRegisteredMethods:l,initialAvailableMethods:s,allAvailableMethods:u,resources:c,endpoints:d,backupCreatedDate:f,resetEndpoint:h,isMFARequired:p}))},onunmatch(){const e=this.getReactRoot();e&&(e.unmount(),this.setReactRoot(null))}})}))},6388:function(){"use strict";window.jQuery.entwine("ss",(e=>{e('[name="MFARequired"]').entwine({setGraceFieldState(){parseInt(this.val(),10)?e(".mfa-settings__grace-period").removeAttr("disabled"):e(".mfa-settings__grace-period").attr("disabled","disabled")},onchange(){this.setGraceFieldState()},onmatch(){this.setGraceFieldState()}}),e('[name="MFAAppliesTo"]').entwine({setGroupFieldVisibility(){if(!this.is(":checked"))return;const t=e(".js-mfa-group-restrictions");"everyone"===this.val()?t.hide():t.show()},onchange(){this.setGroupFieldVisibility()},onmatch(){this.setGroupFieldVisibility()}})}))},1924:function(e,t,n){"use strict";n(830),n(6388)},42:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=function(e){return fetch(e,{body:arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,credentials:"same-origin",headers:arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},method:arguments.length>1&&void 0!==arguments[1]?arguments[1]:"GET"})}},1661:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.formatCode=void 0;t.formatCode=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:" ";if(e.length<6)return e;if(e.length%4==0)return e.split(/(.{4})/g).filter((e=>e)).join(t).trim();if(e.length%3==0)return e.split(/(.{3})/g).filter((e=>e)).join(t).trim();const n=4-e.length%4,o=(e.length-3*n)/4,r=[...[...Array(o).keys()].map((()=>4)),...[...Array(n).keys()].map((()=>3))];let a=0;return r.map((t=>e.substring(a,a+=t))).join(t).trim()}},639:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.hoc=t.default=void 0;var o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=i(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var l=r?Object.getOwnPropertyDescriptor(e,a):null;l&&(l.get||l.set)?Object.defineProperty(o,a,l):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(7363)),r=n(1624),a=n(2827);function i(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(i=function(e){return e?n:t})(e)}function l(){return l=Object.assign?Object.assign.bind():function(e){for(var t=1;t{const t=class extends o.Component{constructor(e){super(e),this.getAvailabilityOverride=this.getAvailabilityOverride.bind(this),this.isAvailable=this.isAvailable.bind(this),this.getUnavailableMessage=this.getUnavailableMessage.bind(this)}getAvailabilityOverride(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;const{availableMethodOverrides:t}=this.props,n=e||this.props.method,{urlSegment:o}=n;return void 0!==t[o]?t[o]:{}}getUnavailableMessage(){const e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:null)||this.props.method;return this.getAvailabilityOverride(e).unavailableMessage||e.unavailableMessage}isAvailable(){const e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:null)||this.props.method,t=this.getAvailabilityOverride(e);let n=e.isAvailable;return void 0!==t.isAvailable&&(n=t.isAvailable),n}render(){return o.default.createElement(e,l({},this.props,{isAvailable:this.isAvailable,getUnavailableMessage:this.getUnavailableMessage}))}},n=(e=>e.displayName||e.name||"Component")(e);return t.displayName=`WithMethodAvailability(${n})`,t};t.hoc=s;const u=(0,a.compose)((0,r.connect)((e=>{const t=[...e.mfaRegister.availableMethods,...e.mfaVerify.allMethods],n={};return Object.values(t).forEach((t=>{const{urlSegment:o}=t,r=`${o}Availability`;void 0!==e[r]&&(n[o]=e[r])})),{availableMethodOverrides:n}})),s);t.default=u},2017:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=["ADD_REGISTERED_METHOD","REMOVE_REGISTERED_METHOD","SET_DEFAULT_METHOD","SET_REGISTERED_METHODS"].reduce(((e,t)=>Object.assign(e,{[t]:`MFA_ADMINISTRATION.${t}`})),{})},9861:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setRegisteredMethods=t.setDefaultMethod=t.registerMethod=t.deregisterMethod=void 0;var o,r=(o=n(2017))&&o.__esModule?o:{default:o};t.registerMethod=e=>({type:r.default.ADD_REGISTERED_METHOD,payload:{method:e}});t.deregisterMethod=e=>({type:r.default.REMOVE_REGISTERED_METHOD,payload:{method:e}});t.setDefaultMethod=e=>({type:r.default.SET_DEFAULT_METHOD,payload:{defaultMethod:e}});t.setRegisteredMethods=e=>({type:r.default.SET_REGISTERED_METHODS,payload:{methods:e}})},6683:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:a,{type:t,payload:n}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const o=e=>t=>t.urlSegment===e.urlSegment,{registeredMethods:i}=e;switch(t){case r.default.ADD_REGISTERED_METHOD:{const{method:t}=n;return Array.isArray(i)?i.find(o(t))?e:(i.push(t),{...e,registeredMethods:i}):{...e,registeredMethods:[t]}}case r.default.REMOVE_REGISTERED_METHOD:{const{method:t}=n,r=i.findIndex(o(t));if(r<0)return e;i.splice(r,1);const a=2===i.length?{defaultMethod:i.find((()=>!0)).urlSegment}:{};return{...e,...a,registeredMethods:[...i]}}case r.default.SET_DEFAULT_METHOD:return{...e,defaultMethod:n.defaultMethod};case r.default.SET_REGISTERED_METHODS:return{...e,registeredMethods:n.methods};default:return e}};var o,r=(o=n(2017))&&o.__esModule?o:{default:o};const a={defaultMethod:null,registeredMethods:[]}},3529:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=["ADD_AVAILABLE_METHOD","REMOVE_AVAILABLE_METHOD","SET_AVAILABLE_METHODS","SET_SCREEN","SET_METHOD"].reduce(((e,t)=>Object.assign(e,{[t]:`MFA_REGISTER.${t}`})),{})},8631:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.showScreen=t.setAvailableMethods=t.removeAvailableMethod=t.chooseMethod=t.addAvailableMethod=void 0;var o,r=(o=n(3529))&&o.__esModule?o:{default:o};t.showScreen=e=>({type:r.default.SET_SCREEN,payload:{screen:e}});t.chooseMethod=e=>({type:r.default.SET_METHOD,payload:{method:e}});t.setAvailableMethods=e=>({type:r.default.SET_AVAILABLE_METHODS,payload:{availableMethods:e}});t.addAvailableMethod=e=>({type:r.default.ADD_AVAILABLE_METHOD,payload:{method:e}});t.removeAvailableMethod=e=>({type:r.default.REMOVE_AVAILABLE_METHOD,payload:{method:e}})},7286:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:i,{type:t,payload:n}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};switch(t){case a.default.SET_SCREEN:{const{screen:t}=n;return null===e.method&&t===r.SCREEN_REGISTER_METHOD?{...e,screen:r.SCREEN_CHOOSE_METHOD}:{...e,screen:t}}case a.default.SET_METHOD:return{...e,method:n.method};case a.default.SET_AVAILABLE_METHODS:return{...e,availableMethods:n.availableMethods};case a.default.ADD_AVAILABLE_METHOD:return{...e,availableMethods:[...e.availableMethods,n.method]};case a.default.REMOVE_AVAILABLE_METHOD:return{...e,availableMethods:e.availableMethods.filter((e=>e.urlSegment!==n.method.urlSegment))};default:return e}};var o,r=n(440),a=(o=n(3529))&&o.__esModule?o:{default:o};const i={screen:r.SCREEN_INTRODUCTION,method:null,availableMethods:[]}},7282:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default=["SET_ALL_METHODS"].reduce(((e,t)=>Object.assign(e,{[t]:`MFA_VERIFY.${t}`})),{})},23:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:a,{type:t,payload:n}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(t===r.default.SET_ALL_METHODS)return{...e,allMethods:n.allMethods};return e};var o,r=(o=n(7282))&&o.__esModule?o:{default:o};const a={allMethods:[]}},2949:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7086))&&o.__esModule?o:{default:o};t.default=r.default.shape({urlSegment:r.default.string,name:r.default.string,description:r.default.string,supportLink:r.default.string,supportText:r.default.string,thumbnail:r.default.string,component:r.default.string,isAvailable:r.default.bool,unavailableMessage:r.default.string})},5695:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,r=(o=n(7086))&&o.__esModule?o:{default:o};t.default=r.default.shape({name:r.default.string,urlSegment:r.default.string,isAvailable:r.default.bool,unavailableMessage:r.default.string,component:r.default.string,supportLink:r.default.string,thumbnail:r.default.string})},640:function(e,t,n){"use strict";var o=n(1742),r={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var n,a,i,l,s,u,c=!1;t||(t={}),n=t.debug||!1;try{if(i=o(),l=document.createRange(),s=document.getSelection(),(u=document.createElement("span")).textContent=e,u.ariaHidden="true",u.style.all="unset",u.style.position="fixed",u.style.top=0,u.style.clip="rect(0, 0, 0, 0)",u.style.whiteSpace="pre",u.style.webkitUserSelect="text",u.style.MozUserSelect="text",u.style.msUserSelect="text",u.style.userSelect="text",u.addEventListener("copy",(function(o){if(o.stopPropagation(),t.format)if(o.preventDefault(),void 0===o.clipboardData){n&&console.warn("unable to use e.clipboardData"),n&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var a=r[t.format]||r.default;window.clipboardData.setData(a,e)}else o.clipboardData.clearData(),o.clipboardData.setData(t.format,e);t.onCopy&&(o.preventDefault(),t.onCopy(o.clipboardData))})),document.body.appendChild(u),l.selectNodeContents(u),s.addRange(l),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");c=!0}catch(o){n&&console.error("unable to copy using execCommand: ",o),n&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),c=!0}catch(o){n&&console.error("unable to copy using clipboardData: ",o),n&&console.error("falling back to prompt"),a=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in t?t.message:"Copy to clipboard: #{key}, Enter"),window.prompt(a,e)}}finally{s&&("function"==typeof s.removeRange?s.removeRange(l):s.removeAllRanges()),u&&document.body.removeChild(u),i()}return c}},9768:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Printd=t.createIFrame=t.createLinkStyle=t.createStyle=void 0;var n=/^(((http[s]?)|file):)?(\/\/)+([0-9a-zA-Z-_.=?&].+)$/,o=/^((\.|\.\.)?\/)([0-9a-zA-Z-_.=?&]+\/)*([0-9a-zA-Z-_.=?&]+)$/,r=function(e){return n.test(e)||o.test(e)};function a(e,t){var n=e.createElement("style");return n.appendChild(e.createTextNode(t)),n}function i(e,t){var n=e.createElement("link");return n.type="text/css",n.rel="stylesheet",n.href=t,n}function l(e){var t=window.document.createElement("iframe");return t.setAttribute("src","about:blank"),t.setAttribute("style","visibility:hidden;width:0;height:0;position:absolute;z-index:-9999;bottom:0;"),t.setAttribute("width","0"),t.setAttribute("height","0"),t.setAttribute("wmode","opaque"),e.appendChild(t),t}t.createStyle=a,t.createLinkStyle=i,t.createIFrame=l;var s={parent:window.document.body,headElements:[],bodyElements:[]},u=function(){function e(e){this.isLoading=!1,this.hasEvents=!1,this.opts=[s,e||{}].reduce((function(e,t){return Object.keys(t).forEach((function(n){return e[n]=t[n]})),e}),{}),this.iframe=l(this.opts.parent)}return e.prototype.getIFrame=function(){return this.iframe},e.prototype.print=function(e,t,n,o){if(!this.isLoading){var l=this.iframe,s=l.contentDocument,u=l.contentWindow;if(s&&u&&(this.iframe.src="about:blank",this.elCopy=e.cloneNode(!0),this.elCopy)){this.isLoading=!0,this.callback=o;var c=u.document;c.open(),c.write(''),this.addEvents();var d=this.opts,f=d.headElements,h=d.bodyElements;Array.isArray(f)&&f.forEach((function(e){return c.head.appendChild(e)})),Array.isArray(h)&&h.forEach((function(e){return c.body.appendChild(e)})),Array.isArray(t)&&t.forEach((function(e){e&&c.head.appendChild(r(e)?i(c,e):a(c,e))})),c.body.appendChild(this.elCopy),Array.isArray(n)&&n.forEach((function(e){if(e){var t=c.createElement("script");r(e)?t.src=e:t.innerText=e,c.body.appendChild(t)}})),c.close()}}},e.prototype.printURL=function(e,t){this.isLoading||(this.addEvents(),this.isLoading=!0,this.callback=t,this.iframe.src=e)},e.prototype.onBeforePrint=function(e){this.onbeforeprint=e},e.prototype.onAfterPrint=function(e){this.onafterprint=e},e.prototype.launchPrint=function(e){this.isLoading||e.print()},e.prototype.addEvents=function(){var e=this;if(!this.hasEvents){this.hasEvents=!0,this.iframe.addEventListener("load",(function(){return e.onLoad()}),!1);var t=this.iframe.contentWindow;t&&(this.onbeforeprint&&t.addEventListener("beforeprint",this.onbeforeprint),this.onafterprint&&t.addEventListener("afterprint",this.onafterprint))}},e.prototype.onLoad=function(){var e=this;if(this.iframe){this.isLoading=!1;var t=this.iframe,n=t.contentDocument,o=t.contentWindow;if(!n||!o)return;"function"==typeof this.callback?this.callback({iframe:this.iframe,element:this.elCopy,launchPrint:function(){return e.launchPrint(o)}}):this.launchPrint(o)}},e}();t.Printd=u,t.default=u},4300:function(e,t,n){"use strict";function o(e){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.CopyToClipboard=void 0;var r=l(n(7363)),a=l(n(640)),i=["text","onCopy","options","children"];function l(e){return e&&e.__esModule?e:{default:e}}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function u(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}function d(e,t){for(var n=0;n=0;--a){var i=this.tryEntries[a],l=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var s=o.call(i,"catchLoc"),u=o.call(i,"finallyLoc");if(s&&u){if(this.prev=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),w(n),E}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var o=n.completion;if("throw"===o.type){var r=o.arg;w(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(e,n,o){return this.delegate={iterator:D(e),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=t),E}},e}(e.exports);try{regeneratorRuntime=t}catch(e){"object"==typeof globalThis?globalThis.regeneratorRuntime=t:Function("r","regeneratorRuntime = r")(t)}},1742:function(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],o=0;o { $('[name="MFARequired"]').entwine({ /** - * Enable or disable the associated "grace period" date field + * Set grace field enabled state based on whether it's enabled or not */ - onchange() { + setGraceFieldState() { const isRequired = parseInt(this.val(), 10); if (isRequired) { $('.mfa-settings__grace-period').removeAttr('disabled'); @@ -13,10 +13,51 @@ window.jQuery.entwine('ss', ($) => { }, /** - * Ensure the "grace period" hide/show handlers wake up when the page does + * Set correct grace field enabled state when value changes + */ + onchange() { + this.setGraceFieldState(); + }, + + /** + * Set correct grace field enabled state when form loads + */ + onmatch() { + this.setGraceFieldState(); + }, + }); + + $('[name="MFAAppliesTo"]').entwine({ + /** + * Set group field visibility based on which option is selected + */ + setGroupFieldVisibility() { + // Ignore radio buttons that aren't selected. + if (!this.is(':checked')) { + return; + } + + // Toggle display + const groupField = $('.js-mfa-group-restrictions'); + if (this.val() === 'everyone') { + groupField.hide(); + } else { + groupField.show(); + } + }, + + /** + * Set group field visibility when selection changes + */ + onchange() { + this.setGroupFieldVisibility(); + }, + + /** + * Set group field visibility when form loads */ onmatch() { - this.onchange(); + this.setGroupFieldVisibility(); }, }); }); diff --git a/docs/en/userguide/02_Administrator_manual/01_Configuring_MFA_site_settings.md b/docs/en/userguide/02_Administrator_manual/01_Configuring_MFA_site_settings.md index c05fd6a5..79ab3b4b 100644 --- a/docs/en/userguide/02_Administrator_manual/01_Configuring_MFA_site_settings.md +++ b/docs/en/userguide/02_Administrator_manual/01_Configuring_MFA_site_settings.md @@ -12,14 +12,14 @@ and select the **Access** tab. Here, you can select one of two modes of operation for MFA on your site: -## MFA is optional for everyone (default) +## MFA is optional (default) This is the default setting when MFA is installed. Everyone will be prompted to set up multi-factor authentication upon their first login, but they can skip the setup process and continue to log in as they did before. They will be able to set up MFA later via their Profile page in Silverstripe CMS. -## MFA is required for everyone +## MFA is required Everyone without MFA setup will be prompted with a message requiring them to setup MFA when they attempt to log in. If they choose not to proceed with setup, @@ -37,3 +37,16 @@ be prompted with the option to set it up on every login, until MFA is set up. ![A screenshot of the site-wide MFA settings UI with the 'MFA is required for everyone' option selected and a date entered in the 'MFA will be required from' field](../_images/02-01-2-grace-period.png) + +## Limit MFA to specific groups + +While it is generally recommended to apply the above settings to _all_ users globally, +you can choose to limit MFA registration to specific groups by setting "Who do these +MFA settings apply to?" to "Only these groups" and then selecting the relevant groups +from the dropdown field. + +Note that any users who have already registered MFA for their account prior to changing +this setting will still need to use MFA to log in, even if they are not in one of the +groups you have selected. + +![A screenshot of the site-wide MFA settings UI with the 'Only these groups' option selected and a group entered in the 'MFA Groups' field](../_images/02-01-3-only-these-groups.png) diff --git a/docs/en/userguide/_images/02-01-1-mfa-settings-ui.png b/docs/en/userguide/_images/02-01-1-mfa-settings-ui.png index c155002b..0900f745 100644 Binary files a/docs/en/userguide/_images/02-01-1-mfa-settings-ui.png and b/docs/en/userguide/_images/02-01-1-mfa-settings-ui.png differ diff --git a/docs/en/userguide/_images/02-01-2-grace-period.png b/docs/en/userguide/_images/02-01-2-grace-period.png index c8cee604..56c997ba 100644 Binary files a/docs/en/userguide/_images/02-01-2-grace-period.png and b/docs/en/userguide/_images/02-01-2-grace-period.png differ diff --git a/docs/en/userguide/_images/02-01-3-only-these-groups.png b/docs/en/userguide/_images/02-01-3-only-these-groups.png new file mode 100644 index 00000000..1b5e1725 Binary files /dev/null and b/docs/en/userguide/_images/02-01-3-only-these-groups.png differ diff --git a/src/Extension/SiteConfigExtension.php b/src/Extension/SiteConfigExtension.php index 186cd38f..42fb6aa2 100644 --- a/src/Extension/SiteConfigExtension.php +++ b/src/Extension/SiteConfigExtension.php @@ -7,8 +7,12 @@ use SilverStripe\Forms\DateField; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\OptionsetField; +use SilverStripe\Forms\TreeMultiselectField; +use SilverStripe\MFA\Service\EnforcementManager; use SilverStripe\ORM\DataExtension; use SilverStripe\ORM\FieldType\DBField; +use SilverStripe\ORM\ValidationResult; +use SilverStripe\Security\Group; use SilverStripe\View\Requirements; /** @@ -32,6 +36,13 @@ class SiteConfigExtension extends DataExtension private static $db = [ 'MFARequired' => 'Boolean', 'MFAGracePeriodExpires' => 'Date', + 'MFAAppliesTo' => 'Enum(["' + . EnforcementManager::APPLIES_TO_EVERYONE . '","' + . EnforcementManager::APPLIES_TO_GROUPS . '"])', + ]; + + private static $many_many = [ + 'MFAGroupRestrictions' => Group::class ]; private static $defaults = [ @@ -47,8 +58,8 @@ public function updateCMSFields(FieldList $fields) 'MFARequired', '', [ - false => _t(__CLASS__ . '.MFA_OPTIONAL', 'MFA is optional for everyone'), - true => _t(__CLASS__ . '.MFA_REQUIRED', 'MFA is required for everyone'), + false => _t(__CLASS__ . '.MFA_OPTIONAL2', 'MFA is optional'), + true => _t(__CLASS__ . '.MFA_REQUIRED2', 'MFA is required'), ] ); $mfaOptions->addExtraClass('mfa-settings__required'); @@ -63,7 +74,28 @@ public function updateCMSFields(FieldList $fields) )); $mfaGraceEnd->addExtraClass('mfa-settings__grace-period'); - $mfaOptions = CompositeField::create($mfaOptions, $mfaGraceEnd) + $mfaAppliesToWho = OptionsetField::create( + 'MFAAppliesTo', + _t(__CLASS__ . '.MFA_APPLIES_TO_TITLE', 'Who do these MFA settings apply to?'), + [ + EnforcementManager::APPLIES_TO_EVERYONE => _t(__CLASS__ . '.EVERYONE', 'Everyone'), + EnforcementManager::APPLIES_TO_GROUPS => _t( + __CLASS__ . '.ONLY_GROUPS', + 'Only these groups (choose from list)' + ), + ] + ); + + $mfaGroupRestrict = TreeMultiselectField::create( + 'MFAGroupRestrictions', + _t(__CLASS__ . '.MFA_GROUP_RESTRICTIONS', 'MFA Groups'), + Group::class + )->setDescription(_t( + __CLASS__ . '.MFA_GROUP_RESTRICTIONS_DESCRIPTION', + 'MFA will only be enabled for members of these selected groups.' + ))->addExtraClass('js-mfa-group-restrictions'); + + $mfaOptions = CompositeField::create($mfaOptions, $mfaGraceEnd, $mfaAppliesToWho, $mfaGroupRestrict) ->setTitle(DBField::create_field( 'HTMLFragment', _t(__CLASS__ . '.MULTI_FACTOR_AUTHENTICATION', 'Multi-factor authentication (MFA)') @@ -73,6 +105,22 @@ public function updateCMSFields(FieldList $fields) $fields->addFieldToTab('Root.Access', $mfaOptions); } + public function validate(ValidationResult $validationResult) + { + if ( + $this->owner->MFAAppliesTo == EnforcementManager::APPLIES_TO_GROUPS + && !$this->owner->MFAGroupRestrictions()->exists() + ) { + $validationResult->addFieldError( + 'MFAGroupRestrictions', + _t( + __CLASS__ . '.MFA_GROUP_RESTRICTIONS_VALIDATION', + 'At least one group must be selected, or the MFA settings should apply to everyone.' + ) + ); + } + } + /** * Gets an anchor tag for CMS users to click to find out more about MFA in the SilverStripe CMS * diff --git a/src/Service/EnforcementManager.php b/src/Service/EnforcementManager.php index fb94be29..3ac9dcc2 100644 --- a/src/Service/EnforcementManager.php +++ b/src/Service/EnforcementManager.php @@ -23,6 +23,9 @@ class EnforcementManager use Configurable; use Injectable; + public const APPLIES_TO_EVERYONE = 'everyone'; + public const APPLIES_TO_GROUPS = 'groups'; + /** * Indicate how many MFA methods the user must authenticate with before they are considered logged in * @@ -72,7 +75,7 @@ public function canSkipMFA(Member $member): bool return true; } - if ($this->isMFARequired()) { + if ($this->isMFARequired() && $this->isUserInMFAEnabledGroup($member)) { return false; } @@ -112,6 +115,10 @@ public function shouldRedirectToMFA(Member $member): bool return true; } + if (!$this->isUserInMFAEnabledGroup($member) && !$this->hasCompletedRegistration($member)) { + return false; + } + if ($this->isGracePeriodInEffect()) { return true; } @@ -152,7 +159,9 @@ public function hasCompletedRegistration(Member $member): bool * Whether MFA is required for eligible users. This takes into account whether a grace period is set and whether * we're currently inside the window for it. * - * Note that in determining this, we ignore whether or not MFA is enabled for the site in general. + * Note that in determining this, we ignore whether or not MFA is enabled for the site in general. We also ignore + * whether any given member is in the list of groups for which MFA has been enabled - for that, call + * {@see isUserInMFAEnabledGroup()} * * @return bool */ @@ -266,4 +275,25 @@ protected function isEnabled(): bool return true; } + + protected function isUserInMFAEnabledGroup(Member $member): bool + { + /** @var SiteConfig&SiteConfigExtension $siteConfig */ + $siteConfig = SiteConfig::current_site_config(); + + // If we aren't restricting by groups, then we pass this check and move on + // to any other applicable checks. + if ($siteConfig->MFAAppliesTo !== self::APPLIES_TO_GROUPS) { + return true; + } + + $groups = $siteConfig->MFAGroupRestrictions(); + + // If no groups are set in the Site Config MFAGroupRestrictions field, MFA is enabled for all users. + // This should generally not be possible, but can happen if a group is deleted after being set in that field. + if ($groups->count() === 0) { + return true; + } + return $member->inGroups($groups); + } } diff --git a/tests/Behat/Context/LoginContext.php b/tests/Behat/Context/LoginContext.php index f337780f..fd561458 100644 --- a/tests/Behat/Context/LoginContext.php +++ b/tests/Behat/Context/LoginContext.php @@ -44,7 +44,7 @@ public function multiFactorAuthenticationIsOptional() */ public function iSelectFromTheMfaSettings($option) { - $value = $option === 'MFA is required for everyone' ? 1 : 0; + $value = $option === 'MFA is required' ? 1 : 0; $this->getMainContext()->selectOption('MFARequired', $value); } } diff --git a/tests/Behat/features/mfa-enabled.feature b/tests/Behat/features/mfa-enabled.feature index 1e18da60..21315599 100644 --- a/tests/Behat/features/mfa-enabled.feature +++ b/tests/Behat/features/mfa-enabled.feature @@ -8,10 +8,46 @@ Feature: MFA is enabled for the site And I go to "/admin" Then I should see the CMS - Scenario: I can set MFA to be required + Scenario: I can set MFA to be required for all users Given I go to "/admin/settings" And I click the "Access" CMS tab Then I should see "Multi-factor authentication (MFA)" - When I select "MFA is required for everyone" from the MFA settings + When I select "MFA is required" from the MFA settings And I press "Save" - Then I should see "Saved" + Then I should see a "Saved" success toast + + # This scenario must be before any other "select a group" scenario, since the saved settings + # aren't reset between scenarios. + Scenario: I must add at least one group if requiring MFA for groups + Given I go to "/admin/settings" + And I click the "Access" CMS tab + Then I should see "Multi-factor authentication (MFA)" + When I select "MFA is required" from the MFA settings + And I select "Only these groups (choose from list)" from "Who do these MFA settings apply to?" input group + And I press "Save" + Then I should not see a "Saved" success toast + Then I should see "At least one group must be selected, or the MFA settings should apply to everyone." + + Scenario: I can set MFA to be required for a given group + Given I go to "/admin/settings" + And I click the "Access" CMS tab + Then I should see "Multi-factor authentication (MFA)" + When I select "MFA is required" from the MFA settings + Then I should not see "MFA Groups" + When I select "Only these groups (choose from list)" from "Who do these MFA settings apply to?" input group + Then I should see "MFA Groups" + When I select "ADMIN group" in the "#Form_EditForm_MFAGroupRestrictions_Holder" tree dropdown + And I press "Save" + Then I should see a "Saved" success toast + Then I should not see "At least one group must be selected, or the MFA settings should apply to everyone." + + Scenario: I can set MFA to be optional for a given group + Given I go to "/admin/settings" + And I click the "Access" CMS tab + Then I should see "Multi-factor authentication (MFA)" + When I select "MFA is optional" from the MFA settings + And I select "Only these groups (choose from list)" from "Who do these MFA settings apply to?" input group + And I select "ADMIN group" in the "#Form_EditForm_MFAGroupRestrictions_Holder" tree dropdown + And I press "Save" + Then I should see a "Saved" success toast + Then I should not see "At least one group must be selected, or the MFA settings should apply to everyone." diff --git a/tests/php/Authenticator/LoginHandlerTest.php b/tests/php/Authenticator/LoginHandlerTest.php index 9a851080..9b315330 100644 --- a/tests/php/Authenticator/LoginHandlerTest.php +++ b/tests/php/Authenticator/LoginHandlerTest.php @@ -26,6 +26,8 @@ use SilverStripe\MFA\Tests\Stub\Store\TestStore; use SilverStripe\MFA\Tests\Stub\BasicMath\Method; use SilverStripe\ORM\FieldType\DBDatetime; +use SilverStripe\ORM\ValidationException; +use SilverStripe\Security\Group; use SilverStripe\Security\Member; use SilverStripe\Security\Security; use SilverStripe\Security\SecurityToken; @@ -572,6 +574,74 @@ public function testGetBackURL() $this->assertSame('foobar', $handler->getBackURL()); } + public function testMFAGroupRestrictionValidation() + { + $config = SiteConfig::current_site_config(); + $config->MFAAppliesTo = EnforcementManager::APPLIES_TO_GROUPS; + $this->expectException(ValidationException::class); + $config->write(); + } + + public function provideMFAGroupRestriction() + { + return [ + 'member in group, has registered method' => [ + 'memberFixture' => 'simon', + 'hasMFA' => true, + ], + 'member in group, with no registered method' => [ + 'memberFixture' => 'guy', + 'hasMFA' => true, + ], + 'member not in group, has registered method' => [ + 'memberFixture' => 'colin', + 'hasMFA' => true, + ], + 'member not in group, with no registered method' => [ + 'memberFixture' => 'carla', + 'hasMFA' => false, + ], + ]; + } + + /** + * @dataProvider provideMFAGroupRestriction + */ + public function testMFAGroupRestriction(string $memberFixture, bool $hasMFA) + { + $config = SiteConfig::current_site_config(); + + /** @var Group $group */ + $group = $this->objFromFixture(Group::class, 'admingroup'); + $config->MFAGroupRestrictions()->add($group); + $config->MFAAppliesTo = EnforcementManager::APPLIES_TO_GROUPS; + $config->write(); + + /** @var Member&MemberExtension $member */ + $member = $this->objFromFixture(Member::class, $memberFixture); + + $this->autoFollowRedirection = false; + $response = $this->doLogin($member, 'Password123'); + $this->autoFollowRedirection = true; + + // Validate that MFA is only enabled for the relevant group, and for users who already registered an MFA method + $path = $hasMFA ? 'default/mfa' : 'default'; + $this->assertSame(302, $response->getStatusCode()); + $this->assertStringEndsWith( + Controller::join_links(Security::login_url(), $path), + $response->getHeader('location') + ); + + // Validate that the member logged in successfully if MFA was not available. + if (!$hasMFA) { + $response = $this->get('/Security/login'); + $this->assertExactMatchBySelector( + '#MemberLoginForm_LoginForm_error', + "You're logged in as {$member->FirstName}." + ); + } + } + public function methodlessMemberFixtureProvider() { return [['guy', 'carla']]; diff --git a/tests/php/Authenticator/LoginHandlerTest.yml b/tests/php/Authenticator/LoginHandlerTest.yml index 180bcb3c..3f21a526 100644 --- a/tests/php/Authenticator/LoginHandlerTest.yml +++ b/tests/php/Authenticator/LoginHandlerTest.yml @@ -25,28 +25,39 @@ SilverStripe\Security\Group: SilverStripe\Security\Member: guy: + FirstName: Guy Email: guy@example.com Password: Password123 PasswordExpiry: 2030-01-01 Groups: =>SilverStripe\Security\Group.admingroup simon: + FirstName: Simon Email: simon@example.com + Password: Password123 RegisteredMFAMethods: =>SilverStripe\MFA\Model\RegisteredMethod.simon-math Groups: =>SilverStripe\Security\Group.admingroup robbie: + FirstName: Robbie Email: robbie@example.com RegisteredMFAMethods: =>SilverStripe\MFA\Model\RegisteredMethod.robbie-math DefaultRegisteredMethodID: =>SilverStripe\MFA\Model\RegisteredMethod.robbie-math Groups: =>SilverStripe\Security\Group.admingroup colin: + FirstName: Colin Email: colin@example.com + Password: Password123 + PasswordExpiry: 2030-01-01 RegisteredMFAMethods: =>SilverStripe\MFA\Model\RegisteredMethod.colin-math DefaultRegisteredMethodID: =>SilverStripe\MFA\Model\RegisteredMethod.colin-math Groups: =>SilverStripe\Security\Group.contentgroup carla: + FirstName: Carla Email: carla@example.com + Password: Password123 Groups: =>SilverStripe\Security\Group.contentgroup pete: + FirstName: Pete Email: pete@example.com + Password: Password123 PasswordExpiry: 1990-01-01 Groups: =>SilverStripe\Security\Group.contentgroup diff --git a/tests/php/Service/EnforcementManagerTest.php b/tests/php/Service/EnforcementManagerTest.php index 56c7f1d0..530c306a 100644 --- a/tests/php/Service/EnforcementManagerTest.php +++ b/tests/php/Service/EnforcementManagerTest.php @@ -9,6 +9,7 @@ use SilverStripe\MFA\Service\MethodRegistry; use SilverStripe\MFA\Tests\Stub\BasicMath\Method as BasicMathMethod; use SilverStripe\ORM\FieldType\DBDatetime; +use SilverStripe\Security\Group; use SilverStripe\Security\Member; use SilverStripe\SiteConfig\SiteConfig; @@ -30,190 +31,602 @@ protected function setUp(): void EnforcementManager::config()->set('enabled', true); } - public function testUserCanSkipWhenMFAIsDisabled() + public function provideCanSkipMFA() { - $this->setSiteConfig(['MFARequired' => true]); - EnforcementManager::config()->set('enabled', false); - - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sally_smith'); - $this->assertTrue(EnforcementManager::create()->canSkipMFA($member)); + $scenarios = [ + // User with registered MFA option can _never_ skip MFA + 'already registered, optional for all' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sally_smith', + 'expected' => false, + ], + 'already registered, required for all' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sally_smith', + 'expected' => false, + ], + 'already registered, in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sally_smith', + 'expected' => false, + ], + 'already registered, in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sally_smith', + 'expected' => false, + ], + 'already registered, NOT in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'sally_smith', + 'expected' => false, + ], + 'already registered, NOT in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'sally_smith', + 'expected' => false, + ], + // User without registered MFA option can skip unless they're not in a specified group + 'not registered, optional for all' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + 'not registered, required for all' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'john_smith', + 'expected' => false, + ], + 'not registered, in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + 'not registered, in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'john_smith', + 'expected' => false, + ], + 'not registered, NOT in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + 'not registered, NOT in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + // Always skip if user has no CMS access + // Note that this is altered by the "requires_admin_access" config, which is tested separately. + 'no cms access, optional for all' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'no cms access, required for all' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'no cms access, not in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'no cms access, not in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'no cms access, in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'no cms access, in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + ]; + // Add scenarios with past and future expiry dates + // See the setUp method, which sets the current datetime to "2019-01-25 12:00:00" + foreach ($scenarios as $name => $scenario) { + // Past expiry dates + $pastScenario = $scenario; + $pastScenario['mfaGracePeriodExpires'] = '2018-12-25'; + $scenarios[$name . ' with past expiry'] = $pastScenario; + // Future expiry dates + $futureScenario = $scenario; + $futureScenario['mfaGracePeriodExpires'] = '2019-01-30'; + // Members who haven't registered MFA yet can skip if there's a currently-active grace period + if ($futureScenario['memberFixture'] === 'john_smith') { + $futureScenario['expected'] = true; + } + $scenarios[$name . ' with future expiry'] = $futureScenario; + } + return $scenarios; } - public function testUserCanSkipWhenNoMethodsAreAvailable() - { - $this->setSiteConfig(['MFARequired' => true]); - MethodRegistry::config()->set('methods', null); + /** + * @dataProvider provideCanSkipMFA + */ + public function testCanSkipMFA( + bool $mfaRequired, + string $mfaAppliesTo, + ?string $mfaGracePeriodExpires, + array $requiredGroupFixtures, + string $memberFixture, + bool $expected + ) { + $config = SiteConfig::current_site_config(); + foreach ($requiredGroupFixtures as $fixtureName) { + $group = $this->objFromFixture(Group::class, $fixtureName); + $config->MFAGroupRestrictions()->add($group); + } + $siteConfigUpdate = ['MFARequired' => $mfaRequired, 'MFAAppliesTo' => $mfaAppliesTo]; + if ($mfaGracePeriodExpires) { + $siteConfigUpdate['MFAGracePeriodExpires'] = $mfaGracePeriodExpires; + } + $this->setSiteConfig($siteConfigUpdate); /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sally_smith'); - $this->assertTrue(EnforcementManager::create()->canSkipMFA($member)); + $member = $this->objFromFixture(Member::class, $memberFixture); + $this->logInAs($member); + + $this->assertSame($expected, EnforcementManager::create()->canSkipMFA($member)); } - public function testUserWithoutCMSAccessCanSkipWhenCMSAccessIsRequired() + public function provideCanSkipMFAWithoutCMSAccess() { - $this->setSiteConfig(['MFARequired' => true]); - - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sammy_smith'); - $this->assertTrue(EnforcementManager::create()->canSkipMFA($member)); + return [ + 'optional, applies to everyone' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'required, applies to everyone' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'optional, not in group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'required, not in group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'optional, in group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'required, in group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + ]; } - public function testUserWithoutCMSAccessCannotSkipWhenCMSAccessIsNotRequired() - { - $this->setSiteConfig(['MFARequired' => true]); + /** + * @dataProvider provideCanSkipMFAWithoutCMSAccess + */ + public function testCanSkipMFAWithoutCMSAccess( + bool $mfaRequired, + string $mfaAppliesTo, + array $requiredGroupFixtures, + string $memberFixture, + bool $expected + ) { EnforcementManager::config()->set('requires_admin_access', false); - - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sammy_smith'); - $this->assertFalse(EnforcementManager::create()->canSkipMFA($member)); + $this->testCanSkipMFA($mfaRequired, $mfaAppliesTo, null, $requiredGroupFixtures, $memberFixture, $expected); } - public function testCannotSkipWhenMFAIsRequiredWithNoGracePeriod() + public function testCanSkipWhenMFAIsDisabled() { $this->setSiteConfig(['MFARequired' => true]); + EnforcementManager::config()->set('enabled', false); /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'reports_user'); - $this->assertFalse(EnforcementManager::create()->canSkipMFA($member)); - } - - public function testCanSkipWhenMFAIsRequiredWithGracePeriodExpiringInFuture() - { - $this->setSiteConfig(['MFARequired' => true, 'MFAGracePeriodExpires' => '2019-01-30']); - - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'reports_user'); + $member = $this->objFromFixture(Member::class, 'sally_smith'); $this->assertTrue(EnforcementManager::create()->canSkipMFA($member)); } - public function testCannotSkipWhenMFAIsRequiredWithGracePeriodExpiringInPast() + public function testCanSkipWhenNoMethodsAreAvailable() { - $this->setSiteConfig(['MFARequired' => true, 'MFAGracePeriodExpires' => '2018-12-25']); - - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'reports_user'); - $this->assertFalse(EnforcementManager::create()->canSkipMFA($member)); - } + $this->setSiteConfig(['MFARequired' => true]); + MethodRegistry::config()->set('methods', null); - public function testCannotSkipWhenMemberHasRegisteredAuthenticationMethodsSetUp() - { - $this->setSiteConfig(['MFARequired' => false]); - // Sally has "backup codes" as a registered authentication method already /** @var Member $member */ $member = $this->objFromFixture(Member::class, 'sally_smith'); - $this->logInAs($member); - - $this->assertFalse(EnforcementManager::create()->canSkipMFA($member)); - } - - public function testCanSkipWhenMFAIsOptional() - { - $this->setSiteConfig(['MFARequired' => false]); - // Anonymous admin user - $memberId = $this->logInWithPermission(); - /** @var Member $member */ - $member = Member::get()->byID($memberId); - $this->assertTrue(EnforcementManager::create()->canSkipMFA($member)); } - public function testShouldNotRedirectToMFAWhenUserDoesNotHaveCMSAccess() + public function provideShouldRedirectToMFA() { - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sammy_smith'); - $this->logInAs($member); - $this->assertFalse(EnforcementManager::create()->shouldRedirectToMFA($member)); + $scenarios = [ + // User with registered MFA option should _always_ redirect to MFA + 'already registered, optional for all' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sally_smith', + 'expected' => true, + ], + 'already registered, required for all' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sally_smith', + 'expected' => true, + ], + 'already registered, in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sally_smith', + 'expected' => true, + ], + 'already registered, in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sally_smith', + 'expected' => true, + ], + 'already registered, NOT in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'sally_smith', + 'expected' => true, + ], + 'already registered, NOT in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'sally_smith', + 'expected' => true, + ], + // User without registered MFA option should only redirect if rules apply to them + 'not registered, optional for all' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + 'not registered, required for all' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + 'not registered, in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + 'not registered, in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'john_smith', + 'expected' => true, + ], + 'not registered, NOT in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'john_smith', + 'expected' => false, + ], + 'not registered, NOT in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'john_smith', + 'expected' => false, + ], + // User who has skipped MFA registration has slightly different behaviour + 'skipped registration, optional for all' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sully_smith', + 'expected' => false, + ], + 'skipped registration, required for all' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sully_smith', + 'expected' => true, + ], + 'skipped registration, in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'sully_smith', + 'expected' => false, + ], + 'skipped registration, in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['reportsgroup'], + 'memberFixture' => 'sully_smith', + 'expected' => true, + ], + 'skipped registration, NOT in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sully_smith', + 'expected' => false, + ], + 'skipped registration, NOT in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sully_smith', + 'expected' => false, + ], + // Should never redirect to MFA if user has no CMS access + // Note that this is altered by the "requires_admin_access" config, which is tested separately. + 'no cms access, optional for all' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'no cms access, required for all' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'no cms access, not in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'no cms access, not in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'no cms access, in optional group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'no cms access, in required group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'mfaGracePeriodExpires' => null, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + ]; + // Add scenarios with past and future expiry dates + // See the setUp method, which sets the current datetime to "2019-01-25 12:00:00" + // Note that the grace period doesn't affect the expected return value. These scenarios are here + // to ensure that doesn't change unexpectedly. + foreach ($scenarios as $name => $scenario) { + // Past expiry dates + $pastScenario = $scenario; + $pastScenario['mfaGracePeriodExpires'] = '2018-12-25'; + $scenarios[$name . ' with past expiry'] = $pastScenario; + // Future expiry dates + $futureScenario = $scenario; + $futureScenario['mfaGracePeriodExpires'] = '2019-01-30'; + $scenarios[$name . ' with future expiry'] = $futureScenario; + } + return $scenarios; } - public function testShouldRedirectToMFAWhenUserDoesNotHaveCMSAccessButTheCheckIsDisabledWithConfig() - { - EnforcementManager::config()->set('requires_admin_access', false); - - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sammy_smith'); - $this->logInAs($member); - $this->assertTrue(EnforcementManager::create()->shouldRedirectToMFA($member)); - } - - public function testShouldRedirectToMFAWhenUserHasAccessToReportsOnly() - { - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'reports_user'); - $this->logInAs($member); - $this->assertTrue(EnforcementManager::create()->shouldRedirectToMFA($member)); - } - - public function testShouldRedirectToMFAForContentAuthors() - { - $memberID = $this->logInWithPermission('CMS_ACCESS_CMSMain'); - /** @var Member $member */ - $member = Member::get()->byID($memberID); - $this->assertTrue(EnforcementManager::create()->shouldRedirectToMFA($member)); - } - - public function testShouldRedirectToMFAWhenUserHasRegisteredMFAMethod() - { - /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sally_smith'); - $shouldRedirect = EnforcementManager::create()->shouldRedirectToMFA($member); - $this->assertTrue($shouldRedirect); - } + /** + * @dataProvider provideShouldRedirectToMFA + */ + public function testShouldRedirectToMFA( + bool $mfaRequired, + string $mfaAppliesTo, + ?string $mfaGracePeriodExpires, + array $requiredGroupFixtures, + string $memberFixture, + bool $expected + ) { + $config = SiteConfig::current_site_config(); + foreach ($requiredGroupFixtures as $fixtureName) { + $group = $this->objFromFixture(Group::class, $fixtureName); + $config->MFAGroupRestrictions()->add($group); + } + $siteConfigUpdate = ['MFARequired' => $mfaRequired, 'MFAAppliesTo' => $mfaAppliesTo]; + if ($mfaGracePeriodExpires) { + $siteConfigUpdate['MFAGracePeriodExpires'] = $mfaGracePeriodExpires; + } + $this->setSiteConfig($siteConfigUpdate); - public function testShouldRedirectToMFAWhenMFAIsRequired() - { - $this->setSiteConfig(['MFARequired' => true]); /** @var Member $member */ - $member = $this->objFromFixture(Member::class, 'sully_smith'); + $member = $this->objFromFixture(Member::class, $memberFixture); $this->logInAs($member); - $this->assertTrue(EnforcementManager::create()->shouldRedirectToMFA($member)); + $this->assertSame($expected, EnforcementManager::create()->shouldRedirectToMFA($member)); } - public function testShouldRedirectToMFAWhenMFAIsRequiredWithGracePeriodExpiringInFuture() + public function provideShouldRedirectToMFAWithoutCMSAccess() { - $this->setSiteConfig(['MFARequired' => true, 'MFAGracePeriodExpires' => '2019-01-30']); - - /** @var Member&MemberExtension $member */ - $member = $this->objFromFixture(Member::class, 'sully_smith'); - $this->logInAs($member); - - $this->assertTrue(EnforcementManager::create()->shouldRedirectToMFA($member)); - } - - public function testShouldRedirectToMFAWhenMFAIsRequiredWithGracePeriodExpiringInPast() - { - $this->setSiteConfig(['MFARequired' => true, 'MFAGracePeriodExpires' => '2018-12-25']); - - /** @var Member&MemberExtension $member */ - $member = $this->objFromFixture(Member::class, 'sully_smith'); - $this->logInAs($member); - - $this->assertTrue(EnforcementManager::create()->shouldRedirectToMFA($member)); - } - - public function testShouldRedirectToMFAWhenMFAIsOptionalAndHasNotBeenSkipped() - { - $this->setSiteConfig(['MFARequired' => false]); - - /** @var Member|MemberExtension $member */ - $member = $this->objFromFixture(Member::class, 'sally_smith'); - $member->HasSkippedMFARegistration = false; - $member->write(); - $this->logInAs($member); - - $this->assertTrue(EnforcementManager::create()->shouldRedirectToMFA($member)); + return [ + 'optional, applies to everyone' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'required, applies to everyone' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_EVERYONE, + 'requiredGroupFixtures' => [], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'optional, not in group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'required, not in group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['admingroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => false, + ], + 'optional, in group' => [ + 'MFARequired' => false, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + 'required, in group' => [ + 'MFARequired' => true, + 'MFAAppliesTo' => EnforcementManager::APPLIES_TO_GROUPS, + 'requiredGroupFixtures' => ['nocmsgroup'], + 'memberFixture' => 'sammy_smith', + 'expected' => true, + ], + ]; } - public function testShouldNotRedirectToMFAWhenMFAIsOptionalAndHasBeenSkipped() - { - $this->setSiteConfig(['MFARequired' => false]); - - /** @var Member&MemberExtension $member */ - $member = $this->objFromFixture(Member::class, 'sully_smith'); - $this->logInAs($member); - - $this->assertFalse(EnforcementManager::create()->shouldRedirectToMFA($member)); + /** + * @dataProvider provideShouldRedirectToMFAWithoutCMSAccess + */ + public function testShouldRedirectToMFAWithoutCMSAccess( + bool $mfaRequired, + string $mfaAppliesTo, + array $requiredGroupFixtures, + string $memberFixture, + bool $expected + ) { + EnforcementManager::config()->set('requires_admin_access', false); + $this->testShouldRedirectToMFA( + $mfaRequired, + $mfaAppliesTo, + null, + $requiredGroupFixtures, + $memberFixture, + $expected + ); } public function testShouldNotRedirectToMFAWhenConfigIsDisabled() diff --git a/tests/php/Service/EnforcementManagerTest.yml b/tests/php/Service/EnforcementManagerTest.yml index 3c56e75c..aefe3e3e 100644 --- a/tests/php/Service/EnforcementManagerTest.yml +++ b/tests/php/Service/EnforcementManagerTest.yml @@ -17,6 +17,9 @@ SilverStripe\Security\Group: Title: View reports Code: reportsgroup Permissions: =>SilverStripe\Security\Permission.reports + nocmsgroup: + Title: No CMS Access + Code: nocmsgroup SilverStripe\Security\Member: sally_smith: @@ -27,10 +30,16 @@ SilverStripe\Security\Member: - =>SilverStripe\MFA\Model\RegisteredMethod.codes DefaultRegisteredMethodID: =>SilverStripe\MFA\Model\RegisteredMethod.codes Groups: =>SilverStripe\Security\Group.admingroup + john_smith: + FirstName: John + Surname: Smith + Email: john.smith@example.com + Groups: =>SilverStripe\Security\Group.admingroup sammy_smith: FirstName: Sammy Surname: Smith Email: sammy.smith@example.com + Groups: =>SilverStripe\Security\Group.nocmsgroup sully_smith: FirstName: Sully Surname: Smith