Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<#import "template.ftl" as layout>
<#import "password-commons.ftl" as passwordCommons>
<@layout.registrationLayout; section>

<#if section = "header">
${msg("recovery-code-config-header")}
<#elseif section = "form">
<!-- warning -->
<div class="${properties.kcRecoveryCodesWarning!}" aria-label="Warning alert">
<div class="${properties.kcAlertIconClass!}">
<i class="fas fa-fw fa-bell" aria-hidden="true"></i>
</div>
<h4 class="${properties.kcAlertTitleClass!}">
<span class="pf-screen-reader">Warning alert:</span>
${msg("recovery-code-config-warning-title")}
</h4>
<div class="${properties.kcAlertDescriptionClass!}">
<p>${msg("recovery-code-config-warning-message")}</p>
</div>
</div>

<div class="${properties.kcPanelClass!}">
<div class="${properties.kcPanelMainClass!}">
<div class="${properties.kcPanelMainBodyClass!}">
<ol id="kc-recovery-codes-list" class="${properties.kcListClass!}" role="list">
<#list recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesList as code>
<li>${code[0..3]}-${code[4..7]}-${code[8..]}</li>
</#list>
</ol>
</div>
</div>
</div>

<!-- actions -->
<div class="${properties.kcRecoveryCodesActions!}">
<button id="printRecoveryCodes" class="${properties.kcButtonLinkClass}" type="button" onclick="printRecoveryCodes()">
<i class="fas fa-print"></i> ${msg("recovery-codes-print")}
</button>
<button id="downloadRecoveryCodes" class="${properties.kcButtonLinkClass}" type="button" onclick="downloadRecoveryCodes()">
<i class="fas fa-download"></i> ${msg("recovery-codes-download")}
</button>
<button id="copyRecoveryCodes" class="${properties.kcButtonLinkClass}" type="button" onclick="copyRecoveryCodes()">
<i class="fas fa-copy"></i> ${msg("recovery-codes-copy")}
</button>
</div>

<!-- confirmation checkbox -->
<div class="${properties.kcFormOptionsClass!} pf-v5-u-mt-md">
<input class="${properties.kcCheckInputClass!}" type="checkbox" id="kcRecoveryCodesConfirmationCheck" name="kcRecoveryCodesConfirmationCheck"
onchange="document.getElementById('saveRecoveryAuthnCodesBtn').disabled = !this.checked;"
/>
<label for="kcRecoveryCodesConfirmationCheck">${msg("recovery-codes-confirmation-message")}</label>
</div>

<form action="${url.loginAction}" class="${properties.kcFormGroupClass!}" id="kc-recovery-codes-settings-form" method="post">
<input type="hidden" name="generatedRecoveryAuthnCodes" value="${recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesAsString}" />
<input type="hidden" name="generatedAt" value="${recoveryAuthnCodesConfigBean.generatedAt?c}" />
<input type="hidden" id="userLabel" name="userLabel" value="${msg("recovery-codes-label-default")}" />
<@passwordCommons.logoutOtherSessions/>

<#if isAppInitiatedAction??>
<input type="submit"
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}"
id="saveRecoveryAuthnCodesBtn" value="${msg("recovery-codes-action-complete")}"
disabled
/>
<button type="submit"
class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!} pf-m-link"
id="cancelRecoveryAuthnCodesBtn" name="cancel-aia" value="true">${msg("recovery-codes-action-cancel")}
</button>
<#else>
<input type="submit"
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
id="saveRecoveryAuthnCodesBtn" value="${msg("recovery-codes-action-complete")}"
disabled
/>
</#if>
</form>

<script>
/* copy recovery codes */
function copyRecoveryCodes() {
const tmpTextarea = document.createElement("textarea");
document.body.appendChild(parseRecoveryCodeList());
tmpTextarea.select();
document.execCommand("copy");
document.body.removeChild(tmpTextarea);
}

/* download recovery codes */
function formatCurrentDateTime() {
const dt = new Date();
const options = {
month: 'long',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short'
};

return dt.toLocaleString('en-US', options);
}

function parseRecoveryCodeList() {
const recoveryCodes = document.getElementById("kc-recovery-codes-list").getElementsByTagName("li");
const recoveryCodeList = "";

for (let i = 0; i < recoveryCodes.length; i++) {
const recoveryCodeLiElement = recoveryCodes[i].innerText;
<#noparse>
recoveryCodeList += `${i}: ${recoveryCodeLiElement}\r\n`;
</#noparse>
}

return recoveryCodeList;
}

function buildDownloadContent() {
const recoveryCodeList = parseRecoveryCodeList();
const dt = new Date();
const options = {
month: 'long',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short'
};

return fileBodyContent =
"${msg("recovery-codes-download-file-header")}\n\n" +
recoveryCodeList + "\n" +
"${msg("recovery-codes-download-file-description")}\n\n" +
"${msg("recovery-codes-download-file-date")} " + formatCurrentDateTime();
}

function setUpDownloadLinkAndDownload(filename, text) {
const el = document.createElement('a');
el.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
el.setAttribute('download', filename);
el.style.display = 'none';
document.body.appendChild(el);
el.click();
document.body.removeChild(el);
}

function downloadRecoveryCodes() {
setUpDownloadLinkAndDownload('kc-download-recovery-codes.txt', buildDownloadContent());
}

/* print recovery codes */
function buildPrintContent() {
const recoveryCodeListHTML = document.getElementById('kc-recovery-codes-list').parentNode.innerHTML;
const styles =
`@page { size: auto; margin-top: 0; }
body { width: 480px; }
div { font-family: monospace }
p:first-of-type { margin-top: 48px }`;

return printFileContent =
"<html><style>" + styles + "</style><body>" +
"<title>kc-download-recovery-codes</title>" +
"<p>${msg("recovery-codes-download-file-header")}</p>" +
"<div>" + recoveryCodeListHTML + "</div>" +
"<p>${msg("recovery-codes-download-file-description")}</p>" +
"<p>${msg("recovery-codes-download-file-date")} " + formatCurrentDateTime() + "</p>" +
"</body></html>";
}

function printRecoveryCodes() {
const w = window.open();
w.document.write(buildPrintContent());
w.print();
w.close();
}
</script>
</#if>
</@layout.registrationLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,10 @@ div.kc-logo-text span {
border-color: transparent black transparent transparent;
}

#kc-recovery-codes-list {
columns: 2;
}

#certificate_subjectDN {
overflow-wrap: break-word
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<#import "template.ftl" as layout>
<@layout.registrationLayout displayInfo=false; section>
<#if section = "header" || section = "show-username">
<#if section = "header">
${msg("loginChooseAuthenticator")}
</#if>
<#elseif section = "form">

<ul class="${properties.kcSelectAuthListClass!}" role="list">
<#list auth.authenticationSelections as authenticationSelection>
<li class="${properties.kcSelectAuthListItemWrapperClass!}">
<form id="kc-select-credential-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
<input type="hidden" name="authenticationExecution" value="${authenticationSelection.authExecId}">
</form>
<div class="${properties.kcSelectAuthListItemClass!}" onclick="document.forms[${authenticationSelection?index}].submit()">
<div class="pf-v5-c-data-list__item-content">
<div class="${properties.kcSelectAuthListItemIconClass!}">
<i class="${properties['${authenticationSelection.iconCssClass}']!authenticationSelection.iconCssClass} ${properties.kcSelectAuthListItemIconPropertyClass!}"></i>
</div>
<div class="${properties.kcSelectAuthListItemBodyClass!}">
<h2 class="${properties.kcSelectAuthListItemHeadingClass!}">
${msg('${authenticationSelection.displayName}')}
</h2>
</div>
<div class="${properties.kcSelectAuthListItemDescriptionClass!}">
${msg('${authenticationSelection.helpText}')}
</div>
</div>
<div class="${properties.kcSelectAuthListItemFillClass!}">
<i class="${properties.kcSelectAuthListItemArrowIconClass!}" aria-hidden="true"></i>
</div>
</div>
</li>
</#list>
</ul>

</#if>
</@layout.registrationLayout>

Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ kcInputGroup=pf-v5-c-input-group

kcInputErrorMessageClass=pf-v5-c-helper-text__item pf-m-error pf-v5-c-form__label-required kc-feedback-text
kcAlertClass=pf-v5-c-alert pf-m-inline
kcAlertIconClass=pf-v5-c-alert__icon
kcAlertTitleClass=pf-v5-c-alert__title
kcAlertDescriptionClass=pf-v5-c-alert__description
kcFormPasswordVisibilityButtonClass=pf-v5-c-button pf-m-control

kcPanelClass=pf-v5-c-panel pf-m-raised
kcPanelMainClass=pf-v5-c-panel__main
kcPanelMainBodyClass=pf-v5-c-panel__main-body
kcListClass=pf-v5-c-list

kcButtonClass=pf-v5-c-button
kcButtonLinkClass=pf-v5-c-button pf-m-link
kcCommonLogoIdP=pf-v5-c-login__main-footer-links-item
kcFormSocialAccountListClass=pf-v5-c-login__main-footer-links
kcFormSocialAccountListItemClass=pf-v5-c-login__main-footer-links-item
Expand All @@ -28,5 +36,13 @@ kcFormCardClass=card-pf

kcResetFlowIcon=pf-icon fas fa-share-square

kcSelectAuthListItemClass= pf-v5-c-data-list__item pf-m-clickable select-auth-box-parent
kcSelectAuthListClass=pf-v5-c-data-list select-auth-container
kcSelectAuthListItemWrapperClass=pf-v5-c-data-list__item pf-m-clickable
kcSelectAuthListItemClass=pf-v5-c-data-list__item-row select-auth-box-parent
kcSelectAuthListItemHeadingClass=pf-v5-u-font-family-heading select-auth-box-headline
kcSelectAuthListItemBodyClass=pf-v5-c-data-list__cell pf-m-no-fill
kcSelectAuthListItemIconClass=pf-v5-c-data-list__cell pf-m-icon select-auth-box-icon
kcSelectAuthListItemFillClass=pf-v5-c-data-list__item-action
kcSelectAuthListItemDescriptionClass=pf-v5-c-data-list__cell pf-m-no-fill select-auth-box-desc

kcRecoveryCodesWarning=pf-v5-c-alert pf-m-warning pf-m-inline pf-v5-u-mb-md kc-recovery-codes-warning