Move existing themes under a default folder

This commit is contained in:
decentral1se
2021-05-05 11:50:45 +02:00
parent a95dc5d92e
commit 96c1306cd5
425 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,70 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='account' bodyClass='user'; section>
<div class="row">
<div class="col-md-10">
<h2>${msg("editAccountHtmlTitle")}</h2>
</div>
<div class="col-md-2 subtitle">
<span class="subtitle"><span class="required">*</span> ${msg("requiredFields")}</span>
</div>
</div>
<form action="${url.accountUrl}" class="form-horizontal" method="post">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<#if !realm.registrationEmailAsUsername>
<div class="form-group ${messagesPerField.printIfExists('username','has-error')}">
<div class="col-sm-2 col-md-2">
<label for="username" class="control-label">${msg("username")}</label> <#if realm.editUsernameAllowed><span class="required">*</span></#if>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="form-control" id="username" name="username" <#if !realm.editUsernameAllowed>disabled="disabled"</#if> value="${(account.username!'')}"/>
</div>
</div>
</#if>
<div class="form-group ${messagesPerField.printIfExists('email','has-error')}">
<div class="col-sm-2 col-md-2">
<label for="email" class="control-label">${msg("email")}</label> <span class="required">*</span>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="form-control" id="email" name="email" autofocus value="${(account.email!'')}"/>
</div>
</div>
<div class="form-group ${messagesPerField.printIfExists('firstName','has-error')}">
<div class="col-sm-2 col-md-2">
<label for="firstName" class="control-label">${msg("firstName")}</label> <span class="required">*</span>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="form-control" id="firstName" name="firstName" value="${(account.firstName!'')}"/>
</div>
</div>
<div class="form-group ${messagesPerField.printIfExists('lastName','has-error')}">
<div class="col-sm-2 col-md-2">
<label for="lastName" class="control-label">${msg("lastName")}</label> <span class="required">*</span>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="form-control" id="lastName" name="lastName" value="${(account.lastName!'')}"/>
</div>
</div>
<div class="form-group">
<div id="kc-form-buttons" class="col-md-offset-2 col-md-10 submit">
<div class="">
<#if url.referrerURI??><a href="${url.referrerURI}">${kcSanitize(msg("backToApplication")?no_esc)}</a></#if>
<button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="submitAction" value="Save">${msg("doSave")}</button>
<button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" name="submitAction" value="Cancel">${msg("doCancel")}</button>
</div>
</div>
</div>
</form>
</@layout.mainLayout>

View File

@ -0,0 +1,76 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='applications' bodyClass='applications'; section>
<div class="row">
<div class="col-md-10">
<h2>${msg("applicationsHtmlTitle")}</h2>
</div>
</div>
<form action="${url.applicationsUrl}" method="post">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<input type="hidden" id="referrer" name="referrer" value="${stateChecker}">
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>${msg("application")}</td>
<td>${msg("availableRoles")}</td>
<td>${msg("grantedPermissions")}</td>
<td>${msg("additionalGrants")}</td>
<td>${msg("action")}</td>
</tr>
</thead>
<tbody>
<#list applications.applications as application>
<tr>
<td>
<#if application.effectiveUrl?has_content><a href="${application.effectiveUrl}"></#if>
<#if application.client.name?has_content>${advancedMsg(application.client.name)}<#else>${application.client.clientId}</#if>
<#if application.effectiveUrl?has_content></a></#if>
</td>
<td>
<#list application.realmRolesAvailable as role>
<#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)}</#if>
<#if role_has_next>, </#if>
</#list>
<#list application.resourceRolesAvailable?keys as resource>
<#if application.realmRolesAvailable?has_content>, </#if>
<#list application.resourceRolesAvailable[resource] as clientRole>
<#if clientRole.roleDescription??>${advancedMsg(clientRole.roleDescription)}<#else>${advancedMsg(clientRole.roleName)}</#if>
${msg("inResource")} <strong><#if clientRole.clientName??>${advancedMsg(clientRole.clientName)}<#else>${clientRole.clientId}</#if></strong>
<#if clientRole_has_next>, </#if>
</#list>
</#list>
</td>
<td>
<#if application.client.consentRequired>
<#list application.clientScopesGranted as claim>
${advancedMsg(claim)}<#if claim_has_next>, </#if>
</#list>
<#else>
<strong>${msg("fullAccess")}</strong>
</#if>
</td>
<td>
<#list application.additionalGrants as grant>
${advancedMsg(grant)}<#if grant_has_next>, </#if>
</#list>
</td>
<td>
<#if (application.client.consentRequired && application.clientScopesGranted?has_content) || application.additionalGrants?has_content>
<button type='submit' class='${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!}' id='revoke-${application.client.clientId}' name='clientId' value="${application.client.id}">${msg("revoke")}</button>
</#if>
</td>
</tr>
</#list>
</tbody>
</table>
</form>
</@layout.mainLayout>

View File

@ -0,0 +1,42 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='social' bodyClass='social'; section>
<div class="row">
<div class="col-md-10">
<h2>${msg("federatedIdentitiesHtmlTitle")}</h2>
</div>
</div>
<div id="federated-identities">
<#list federatedIdentity.identities as identity>
<div class="row margin-bottom">
<div class="col-sm-2 col-md-2">
<label for="${identity.providerId!}" class="control-label">${identity.displayName!}</label>
</div>
<div class="col-sm-5 col-md-5">
<input disabled="true" class="form-control" value="${identity.userName!}">
</div>
<div class="col-sm-5 col-md-5">
<#if identity.connected>
<#if federatedIdentity.removeLinkPossible>
<form action="${url.socialUrl}" method="post" class="form-inline">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<input type="hidden" id="action" name="action" value="remove">
<input type="hidden" id="providerId" name="providerId" value="${identity.providerId!}">
<button id="remove-link-${identity.providerId!}" class="btn btn-default">${msg("doRemove")}</button>
</form>
</#if>
<#else>
<form action="${url.socialUrl}" method="post" class="form-inline">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<input type="hidden" id="action" name="action" value="add">
<input type="hidden" id="providerId" name="providerId" value="${identity.providerId!}">
<button id="add-link-${identity.providerId!}" class="btn btn-default">${msg("doAdd")}</button>
</form>
</#if>
</div>
</div>
</#list>
</div>
</@layout.mainLayout>

View File

@ -0,0 +1,35 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='log' bodyClass='log'; section>
<div class="row">
<div class="col-md-10">
<h2>${msg("accountLogHtmlTitle")}</h2>
</div>
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>${msg("date")}</td>
<td>${msg("event")}</td>
<td>${msg("ip")}</td>
<td>${msg("client")}</td>
<td>${msg("details")}</td>
</tr>
</thead>
<tbody>
<#list log.events as event>
<tr>
<td>${event.date?datetime}</td>
<td>${event.event}</td>
<td>${event.ipAddress}</td>
<td>${event.client!}</td>
<td><#list event.details as detail>${detail.key} = ${detail.value} <#if detail_has_next>, </#if></#list></td>
</tr>
</#list>
</tbody>
</table>
</@layout.mainLayout>

View File

@ -0,0 +1,376 @@
doSave=Save
doCancel=Cancel
doLogOutAllSessions=Log out all sessions
doRemove=Remove
doAdd=Add
doSignOut=Sign Out
doLogIn=Log In
doLink=Link
noAccessMessage=Access not allowed
editAccountHtmlTitle=Edit Account
personalInfoHtmlTitle=Personal Info
federatedIdentitiesHtmlTitle=Federated Identities
accountLogHtmlTitle=Account Log
changePasswordHtmlTitle=Change Password
deviceActivityHtmlTitle=Device Activity
sessionsHtmlTitle=Sessions
accountManagementTitle=Keycloak Account Management
authenticatorTitle=Authenticator
applicationsHtmlTitle=Applications
linkedAccountsHtmlTitle=Linked Accounts
accountManagementWelcomeMessage=Welcome to Keycloak Account Management
personalInfoIntroMessage=Manage your basic information
accountSecurityTitle=Account Security
accountSecurityIntroMessage=Control your password and account access
applicationsIntroMessage=Track and manage your app permission to access your account
resourceIntroMessage=Share your resources among team members
passwordLastUpdateMessage=Your password was updated at
updatePasswordTitle=Update Password
updatePasswordMessageTitle=Make sure you choose a strong password
updatePasswordMessage=A strong password contains a mix of numbers, letters, and symbols. It is hard to guess, does not resemble a real word, and is only used for this account.
personalSubTitle=Your Personal Info
personalSubMessage=Manage this basic information: your first name, last name and email
authenticatorCode=One-time code
email=Email
firstName=First name
givenName=Given name
fullName=Full name
lastName=Last name
familyName=Family name
password=Password
currentPassword=Current Password
passwordConfirm=Confirmation
passwordNew=New Password
username=Username
address=Address
street=Street
locality=City or Locality
region=State, Province, or Region
postal_code=Zip or Postal code
country=Country
emailVerified=Email verified
website=Web page
phoneNumber=Phone number
phoneNumberVerified=Phone number verified
gender=Gender
birthday=Birthdate
zoneinfo=Time zone
gssDelegationCredential=GSS Delegation Credential
profileScopeConsentText=User profile
emailScopeConsentText=Email address
addressScopeConsentText=Address
phoneScopeConsentText=Phone number
offlineAccessScopeConsentText=Offline Access
samlRoleListScopeConsentText=My Roles
rolesScopeConsentText=User roles
role_admin=Admin
role_realm-admin=Realm Admin
role_create-realm=Create realm
role_view-realm=View realm
role_view-users=View users
role_view-applications=View applications
role_view-clients=View clients
role_view-events=View events
role_view-identity-providers=View identity providers
role_view-consent=View consents
role_manage-realm=Manage realm
role_manage-users=Manage users
role_manage-applications=Manage applications
role_manage-identity-providers=Manage identity providers
role_manage-clients=Manage clients
role_manage-events=Manage events
role_view-profile=View profile
role_manage-account=Manage account
role_manage-account-links=Manage account links
role_manage-consent=Manage consents
role_read-token=Read token
role_offline-access=Offline access
role_uma_authorization=Obtain permissions
client_account=Account
client_account-console=Account Console
client_security-admin-console=Security Admin Console
client_admin-cli=Admin CLI
client_realm-management=Realm Management
client_broker=Broker
requiredFields=Required fields
allFieldsRequired=All fields required
backToApplication=&laquo; Back to application
backTo=Back to {0}
date=Date
event=Event
ip=IP
client=Client
clients=Clients
details=Details
started=Started
lastAccess=Last Access
expires=Expires
applications=Applications
account=Account
federatedIdentity=Federated Identity
authenticator=Authenticator
device-activity=Device Activity
sessions=Sessions
log=Log
application=Application
availableRoles=Available Roles
grantedPermissions=Granted Permissions
grantedPersonalInfo=Granted Personal Info
additionalGrants=Additional Grants
action=Action
inResource=in
fullAccess=Full Access
offlineToken=Offline Token
revoke=Revoke Grant
configureAuthenticators=Configured Authenticators
mobile=Mobile
totpStep1=Install one of the following applications on your mobile:
totpStep2=Open the application and scan the barcode:
totpStep3=Enter the one-time code provided by the application and click Save to finish the setup.
totpStep3DeviceName=Provide a Device Name to help you manage your OTP devices.
totpManualStep2=Open the application and enter the key:
totpManualStep3=Use the following configuration values if the application allows setting them:
totpUnableToScan=Unable to scan?
totpScanBarcode=Scan barcode?
totp.totp=Time-based
totp.hotp=Counter-based
totpType=Type
totpAlgorithm=Algorithm
totpDigits=Digits
totpInterval=Interval
totpCounter=Counter
totpDeviceName=Device Name
irreversibleAction=This action is irreversible
deletingImplies=Deleting your account implies:
errasingData=Erasing all your data
loggingOutImmediately=Logging you out immediately
accountUnusable=Any subsequent use of the application will not be possible with this account
missingUsernameMessage=Please specify username.
missingFirstNameMessage=Please specify first name.
invalidEmailMessage=Invalid email address.
missingLastNameMessage=Please specify last name.
missingEmailMessage=Please specify email.
missingPasswordMessage=Please specify password.
notMatchPasswordMessage=Passwords don''t match.
invalidUserMessage=Invalid user
updateReadOnlyAttributesRejectedMessage=Update of read-only attribute rejected
missingTotpMessage=Please specify authenticator code.
missingTotpDeviceNameMessage=Please specify device name.
invalidPasswordExistingMessage=Invalid existing password.
invalidPasswordConfirmMessage=Password confirmation doesn''t match.
invalidTotpMessage=Invalid authenticator code.
usernameExistsMessage=Username already exists.
emailExistsMessage=Email already exists.
readOnlyUserMessage=You can''t update your account as it is read-only.
readOnlyUsernameMessage=You can''t update your username as it is read-only.
readOnlyPasswordMessage=You can''t update your password as your account is read-only.
successTotpMessage=Mobile authenticator configured.
successTotpRemovedMessage=Mobile authenticator removed.
successGrantRevokedMessage=Grant revoked successfully.
accountUpdatedMessage=Your account has been updated.
accountPasswordUpdatedMessage=Your password has been updated.
missingIdentityProviderMessage=Identity provider not specified.
invalidFederatedIdentityActionMessage=Invalid or missing action.
identityProviderNotFoundMessage=Specified identity provider not found.
federatedIdentityLinkNotActiveMessage=This identity is not active anymore.
federatedIdentityRemovingLastProviderMessage=You can''t remove last federated identity as you don''t have a password.
identityProviderRedirectErrorMessage=Failed to redirect to identity provider.
identityProviderRemovedMessage=Identity provider removed successfully.
identityProviderAlreadyLinkedMessage=Federated identity returned by {0} is already linked to another user.
staleCodeAccountMessage=The page expired. Please try one more time.
consentDenied=Consent denied.
accountDisabledMessage=Account is disabled, contact your administrator.
accountTemporarilyDisabledMessage=Account is temporarily disabled, contact your administrator or try again later.
invalidPasswordMinLengthMessage=Invalid password: minimum length {0}.
invalidPasswordMinLowerCaseCharsMessage=Invalid password: must contain at least {0} lower case characters.
invalidPasswordMinDigitsMessage=Invalid password: must contain at least {0} numerical digits.
invalidPasswordMinUpperCaseCharsMessage=Invalid password: must contain at least {0} upper case characters.
invalidPasswordMinSpecialCharsMessage=Invalid password: must contain at least {0} special characters.
invalidPasswordNotUsernameMessage=Invalid password: must not be equal to the username.
invalidPasswordNotEmailMessage=Invalid password: must not be equal to the email.
invalidPasswordRegexPatternMessage=Invalid password: fails to match regex pattern(s).
invalidPasswordHistoryMessage=Invalid password: must not be equal to any of last {0} passwords.
invalidPasswordBlacklistedMessage=Invalid password: password is blacklisted.
invalidPasswordGenericMessage=Invalid password: new password doesn''t match password policies.
# Authorization
myResources=My Resources
myResourcesSub=My resources
doDeny=Deny
doRevoke=Revoke
doApprove=Approve
doRemoveSharing=Remove Sharing
doRemoveRequest=Remove Request
peopleAccessResource=People with access to this resource
resourceManagedPolicies=Permissions granting access to this resource
resourceNoPermissionsGrantingAccess=No permissions granting access to this resource
anyAction=Any action
description=Description
name=Name
scopes=Scopes
resource=Resource
user=User
peopleSharingThisResource=People sharing this resource
shareWithOthers=Share with others
needMyApproval=Need my approval
requestsWaitingApproval=Your requests waiting approval
icon=Icon
requestor=Requestor
owner=Owner
resourcesSharedWithMe=Resources shared with me
permissionRequestion=Permission Requestion
permission=Permission
shares=share(s)
notBeingShared=This resource is not being shared.
notHaveAnyResource=You don't have any resources
noResourcesSharedWithYou=There are no resources shared with you
havePermissionRequestsWaitingForApproval=You have {0} permission request(s) waiting for approval.
clickHereForDetails=Click here for details.
resourceIsNotBeingShared=The resource is not being shared
locale_ca=Catal\u00e0
locale_cs=\u010Ce\u0161tina
locale_de=Deutsch
locale_en=English
locale_es=Espa\u00f1ol
locale_fr=Fran\u00e7ais
locale_hu=Magyar
locale_it=Italiano
locale_ja=\u65e5\u672c\u8a9e
locale_lt=Lietuvi\u0173
locale_nl=Nederlands
locale_no=Norsk
locale_pl=Polski
locale_pt-BR=Portugu\u00eas (Brasil)
locale_ru=\u0420\u0443\u0441\u0441\u043a\u0438\u0439
locale_sk=Sloven\u010dina
locale_sv=Svenska
locale_tr=T\u00FCrk\u00E7e
locale_zh-CN=\u4e2d\u6587\u7b80\u4f53
# Applications
applicationName=Name
applicationType=Application Type
applicationInUse=In-use app only
clearAllFilter=Clear all filters
activeFilters=Active filters
filterByName=Filter By Name ...
allApps=All applications
internalApps=Internal applications
thirdpartyApps=Third-Party applications
appResults=Results
clientNotFoundMessage=Client not found.
# Linked account
authorizedProvider=Authorized Provider
authorizedProviderMessage=Authorized Providers linked with your account
identityProvider=Identity Provider
identityProviderMessage=To link your account with identity providers you have configured
socialLogin=Social Login
userDefined=User Defined
removeAccess=Remove Access
removeAccessMessage=You will need to grant access again, if you want to use this app account.
#Authenticator
authenticatorStatusMessage=Two-factor authentication is currently
authenticatorFinishSetUpTitle=Your Two-Factor Authentication
authenticatorFinishSetUpMessage=Each time you sign in to your Keycloak account, you will be asked to provide a two-factor authentication code.
authenticatorSubTitle=Set Up Two-Factor Authentication
authenticatorSubMessage=To enhance the security of your account, enable at least one of the available two-factor authentication methods.
authenticatorMobileTitle=Mobile Authenticator
authenticatorMobileMessage=Use mobile Authenticator to get Verification codes as the two-factor authentication.
authenticatorMobileFinishSetUpMessage=The authenticator has been bound to your phone.
authenticatorActionSetup=Set up
authenticatorSMSTitle=SMS Code
authenticatorSMSMessage=Keycloak will send the Verification code to your phone as the two-factor authentication.
authenticatorSMSFinishSetUpMessage=Text messages are sent to
authenticatorDefaultStatus=Default
authenticatorChangePhone=Change Phone Number
authenticatorBackupCodesTitle=Backup Codes
authenticatorBackupCodesMessage=Get your 8-digit backup codes
authenticatorBackupCodesFinishSetUpMessage=12 backup codes were generated at this time. Each one can be used once.
#Authenticator - Mobile Authenticator setup
authenticatorMobileSetupTitle=Mobile Authenticator Setup
smscodeIntroMessage=Enter your phone number and a verification code will be sent to your phone.
mobileSetupStep1=Install an authenticator application on your phone. The applications listed here are supported.
mobileSetupStep2=Open the application and scan the barcode:
mobileSetupStep3=Enter the one-time code provided by the application and click Save to finish the setup.
scanBarCode=Want to scan the barcode?
enterBarCode=Enter the one-time code
doCopy=Copy
doFinish=Finish
#Authenticator - SMS Code setup
authenticatorSMSCodeSetupTitle=SMS Code Setup
chooseYourCountry=Choose your country
enterYourPhoneNumber=Enter your phone number
sendVerficationCode=Send Verification Code
enterYourVerficationCode=Enter your verification code
#Authenticator - backup Code setup
authenticatorBackupCodesSetupTitle=Backup Codes Setup
backupcodesIntroMessage=If you lose access to your phone, you can still log into your account through backup codes. Keep them somewhere safe and accessible.
realmName=Realm
doDownload=Download
doPrint=Print
backupCodesTips-1=Each backup code can be used once.
backupCodesTips-2=These codes were generated on
generateNewBackupCodes=Generate New Backup Codes
backupCodesTips-3=When you generate new backup codes, the current codes will not work anymore.
backtoAuthenticatorPage=Back to Authenticator Page
#Resources
resources=Resources
sharedwithMe=Shared with Me
share=Share
sharedwith=Shared with
accessPermissions=Access Permissions
permissionRequests=Permission Requests
approve=Approve
approveAll=Approve all
people=people
perPage=per page
currentPage=Current Page
sharetheResource=Share the resource
group=Group
selectPermission=Select Permission
addPeople=Add people to share your resource with
addTeam=Add team to share your resource with
myPermissions=My Permissions
waitingforApproval=Waiting for approval
anyPermission=Any Permission
# Openshift messages
openshift.scope.user_info=User information
openshift.scope.user_check-access=User access information
openshift.scope.user_full=Full Access
openshift.scope.list-projects=List projects

View File

@ -0,0 +1,59 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='password' bodyClass='password'; section>
<div class="row">
<div class="col-md-10">
<h2>${msg("changePasswordHtmlTitle")}</h2>
</div>
<div class="col-md-2 subtitle">
<span class="subtitle">${msg("allFieldsRequired")}</span>
</div>
</div>
<form action="${url.passwordUrl}" class="form-horizontal" method="post">
<input type="text" id="username" name="username" value="${(account.username!'')}" autocomplete="username" readonly="readonly" style="display:none;">
<#if password.passwordSet>
<div class="form-group">
<div class="col-sm-2 col-md-2">
<label for="password" class="control-label">${msg("password")}</label>
</div>
<div class="col-sm-10 col-md-10">
<input type="password" class="form-control" id="password" name="password" autofocus autocomplete="current-password">
</div>
</div>
</#if>
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<div class="form-group">
<div class="col-sm-2 col-md-2">
<label for="password-new" class="control-label">${msg("passwordNew")}</label>
</div>
<div class="col-sm-10 col-md-10">
<input type="password" class="form-control" id="password-new" name="password-new" autocomplete="new-password">
</div>
</div>
<div class="form-group">
<div class="col-sm-2 col-md-2">
<label for="password-confirm" class="control-label" class="two-lines">${msg("passwordConfirm")}</label>
</div>
<div class="col-sm-10 col-md-10">
<input type="password" class="form-control" id="password-confirm" name="password-confirm" autocomplete="new-password">
</div>
</div>
<div class="form-group">
<div id="kc-form-buttons" class="col-md-offset-2 col-md-10 submit">
<div class="">
<button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="submitAction" value="Save">${msg("doSave")}</button>
</div>
</div>
</div>
</form>
</@layout.mainLayout>

View File

@ -0,0 +1,277 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='authorization' bodyClass='authorization'; section>
<style>
.search-box,.close-icon,.search-wrapper {
position: relative;
}
.search-wrapper {
width: 500px;
margin: auto;
margin-top: 50px;
}
.search-box {
font-weight: 600;
color: white;
border: 1px solid #006e9c;
outline: 0;
border-radius: 15px;
background-color: #0085cf;
padding: 2px 5px;
}
.search-box:focus {
box-shadow: 0 0 15px 5px #b0e0ee;
border: 2px solid #bebede;
}
.close-icon {
border:1px solid transparent;
background-color: transparent;
display: inline-block;
float: right;
outline: 0;
cursor: pointer;
}
.close-icon:after {
display: block;
width: 15px;
height: 15px;
background-color: #FA9595;
z-index:1;
right: 35px;
top: 0;
bottom: 0;
margin: auto;
padding: 2px;
border-radius: 50%;
text-align: center;
color: white;
font-weight: normal;
font-size: 12px;
box-shadow: 0 0 2px #E50F0F;
cursor: pointer;
}
.search-box:not(:valid) ~ .close-icon {
display: none;
}
</style>
<script>
function removeScopeElm(elm) {
elm.parentNode.removeChild(elm);
}
function removeAllScopes(id) {
var scopesElm = document.getElementsByName('removeScope-' + id);
for (i = 0; i < scopesElm.length; i++) {
var td = scopesElm[i].parentNode.parentNode;
var tr = td.parentNode;
var tbody = tr.parentNode;
tbody.removeChild(tr);
}
}
function getChildren(parent, childId) {
var childNodes = [];
for (i = 0; i < parent.childNodes.length; i++) {
if (parent.childNodes[i].id == childId) {
childNodes.push(parent.childNodes[i]);
}
}
return childNodes;
}
</script>
<div class="row">
<div class="col-md-10">
<h2>
<a href="${url.resourceUrl}">${msg("myResources")}</a> <i class="fa fa-angle-right"></i> <#if authorization.resource.displayName??>${authorization.resource.displayName}<#else>${authorization.resource.name}</#if>
</h2>
</div>
</div>
<#if authorization.resource.iconUri??>
<img src="${authorization.resource.iconUri}">
<br/>
</#if>
<div class="row">
<div class="col-md-10">
<h3>
${msg("peopleAccessResource")}
</h3>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>${msg("user")}</th>
<th>${msg("permission")}</th>
<th>${msg("date")}</th>
<th>${msg("action")}</th>
</tr>
</thead>
<tbody>
<#if authorization.resource.shares?size != 0>
<#list authorization.resource.shares as permission>
<form action="${url.getResourceGrant(authorization.resource.id)}" name="revokeForm-${authorization.resource.id}-${permission.requester.username}" method="post">
<input type="hidden" name="action" value="revoke">
<input type="hidden" name="requester" value="${permission.requester.username}">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<tr>
<td>
<#if permission.requester.email??>${permission.requester.email}<#else>${permission.requester.username}</#if>
</td>
<td>
<#if permission.scopes?size != 0>
<#list permission.scopes as scope>
<#if scope.granted && scope.scope??>
<div class="search-box">
<#if scope.scope.displayName??>
${scope.scope.displayName}
<#else>
${scope.scope.name}
</#if>
<button class="close-icon" type="button" name="removeScope-${authorization.resource.id}-${permission.requester.username}" onclick="removeScopeElm(this.parentNode);document.forms['revokeForm-${authorization.resource.id}-${permission.requester.username}'].submit();"><i class="fa fa-times" aria-hidden="true"></i></button>
<input type="hidden" name="permission_id" value="${scope.id}"/>
</div>
<#else>
${msg("anyPermission")}
</#if>
</#list>
<#else>
Any action
</#if>
</td>
<td>
${permission.createdDate?datetime}
</td>
<td width="20%" align="middle" style="vertical-align: middle">
<a href="#" id="revoke-${authorization.resource.name}-${permission.requester.username}" onclick="removeAllScopes('${authorization.resource.id}-${permission.requester.username}');document.forms['revokeForm-${authorization.resource.id}-${permission.requester.username}'].submit();" type="submit" class="btn btn-primary">${msg("doRevoke")}</a>
</td>
</tr>
</form>
</#list>
<#else>
<tr>
<td colspan="4">${msg("resourceIsNotBeingShared")}</td>
</tr>
</#if>
</tbody>
</table>
</form>
</div>
</div>
<div class="row">
<div class="col-md-10">
<h3>
${msg("resourceManagedPolicies")}
</h3>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>${msg("description")}</th>
<th>${msg("permission")}</th>
<th>${msg("action")}</th>
</tr>
</thead>
<tbody>
<#if authorization.resource.policies?size != 0>
<#list authorization.resource.policies as permission>
<form action="${url.getResourceGrant(authorization.resource.id)}" name="revokePolicyForm-${authorization.resource.id}-${permission.id}" method="post">
<input type="hidden" name="action" value="revokePolicy">
<input type="hidden" name="permission_id" value="${permission.id}"/>
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<tr>
<td>
<#if permission.description??>
${permission.description}
</#if>
</td>
<td>
<#if permission.scopes?size != 0>
<#list permission.scopes as scope>
<div class="search-box">
<#if scope.displayName??>
${scope.displayName}
<#else>
${scope.name}
</#if>
<button class="close-icon" type="button" name="removePolicyScope-${authorization.resource.id}-${permission.id}-${scope.id}" onclick="removeScopeElm(this.parentNode);document.forms['revokePolicyForm-${authorization.resource.id}-${permission.id}'].submit();"><i class="fa fa-times" aria-hidden="true"></i></button>
<input type="hidden" name="permission_id" value="${permission.id}:${scope.id}"/>
</div>
</#list>
<#else>
${msg("anyAction")}
</#if>
</td>
<td width="20%" align="middle" style="vertical-align: middle">
<a href="#" id="revokePolicy-${authorization.resource.name}-${permission.id}" onclick="document.forms['revokePolicyForm-${authorization.resource.id}-${permission.id}']['action'].value = 'revokePolicyAll';document.forms['revokePolicyForm-${authorization.resource.id}-${permission.id}'].submit();" type="submit" class="btn btn-primary">${msg("doRevoke")}</a>
</td>
</tr>
</form>
</#list>
<#else>
<tr>
<td colspan="3">
${msg("resourceNoPermissionsGrantingAccess")}
</td>
</tr>
</#if>
</tbody>
</table>
</form>
</div>
</div>
<div class="row">
<div class="col-md-10">
<h3>
${msg("shareWithOthers")}
</h3>
</div>
</div>
<div class="row">
<div class="col-md-10">
<form action="${url.getResourceShare(authorization.resource.id)}" name="shareForm" method="post">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<div class="col-sm-3 col-md-3">
<label for="password" class="control-label">${msg("username")} or ${msg("email")} </label> <span class="required">*</span>
</div>
<div class="col-sm-8 col-md-8">
<div class="row">
<div class="col-md-12">
<input type="text" class="form-control" id="user_id" name="user_id" autofocus autocomplete="off">
</div>
<div class="col-md-12">
<br/>
<#list authorization.resource.scopes as scope>
<div id="scope" class="search-box">
<#if scope.displayName??>
${scope.displayName}
<#else>
${scope.name}
</#if>
<button class="close-icon" id="share-remove-scope-${authorization.resource.name}-${scope.name}" type="button" onclick="if (getChildren(this.parentNode.parentNode, 'scope').length > 1) {removeScopeElm(this.parentNode)}"><i class="fa fa-times" aria-hidden="true"></i></button>
<input type="hidden" name="scope_id" value="${scope.id}"/>
</div>
</#list>
</div>
<div class="col-md-12">
<br/>
<a href="#" onclick="document.forms['shareForm'].submit()" type="submit" id="share-button" class="btn btn-primary">${msg("share")}</a>
</div>
</div>
</div>
</form>
</div>
</div>
<br/>
</@layout.mainLayout>

View File

@ -0,0 +1,403 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='authorization' bodyClass='authorization'; section>
<style>
.search-box,.close-icon,.search-wrapper {
position: relative;
}
.search-wrapper {
width: 500px;
margin: auto;
margin-top: 50px;
}
.search-box {
font-weight: 600;
color: white;
border: 1px solid #006e9c;
outline: 0;
border-radius: 15px;
background-color: #0085cf;
padding: 2px 5px;
}
.search-box:focus {
box-shadow: 0 0 15px 5px #b0e0ee;
border: 2px solid #bebede;
}
.close-icon {
border:1px solid transparent;
background-color: transparent;
display: inline-block;
float: right;
outline: 0;
cursor: pointer;
}
.close-icon:after {
display: block;
width: 15px;
height: 15px;
background-color: #FA9595;
z-index:1;
right: 35px;
top: 0;
bottom: 0;
margin: auto;
padding: 2px;
border-radius: 50%;
text-align: center;
color: white;
font-weight: normal;
font-size: 12px;
box-shadow: 0 0 2px #E50F0F;
cursor: pointer;
}
.search-box:not(:valid) ~ .close-icon {
display: none;
}
</style>
<script>
function showHideActions(elm) {
if (elm.style.display == 'none') {
elm.style.display = '';
} else {
elm.style.display = 'none';
}
}
function removeScopeElm(elm) {
var td = elm.parentNode;
var tr = td.parentNode;
var tbody = tr.parentNode;
td.removeChild(elm);
var childCount = td.childNodes.length - 1;
for (i = 0; i < td.childNodes.length; i++) {
if (!td.childNodes[i].tagName || td.childNodes[i].tagName.toUpperCase() != 'DIV') {
td.removeChild(td.childNodes[i]);
childCount--;
}
}
if (childCount <= 0) {
tbody.removeChild(tr);
}
}
function removeAllScopes(id) {
var scopesElm = document.getElementsByName('removeScope-' + id);
for (i = 0; i < scopesElm.length; i++) {
var td = scopesElm[i].parentNode.parentNode;
var tr = td.parentNode;
var tbody = tr.parentNode;
tbody.removeChild(tr);
}
}
function selectAllCheckBoxes(formName, elm, name) {
var shares = document.forms[formName].getElementsByTagName('input');
for (i = 0; i < shares.length; i++) {
if (shares[i].name == name) {
shares[i].checked = elm.checked;
}
}
}
</script>
<div class="row">
<div class="col-md-10">
<h2>
${msg("myResources")}
</h2>
</div>
</div>
<#if authorization.resourcesWaitingApproval?size != 0>
<div class="row">
<div class="col-md-12">
<h3>
${msg("needMyApproval")}
</h3>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>${msg("resource")}</th>
<th>${msg("requestor")}</th>
<th>${msg("permissionRequestion")}</th>
<th>${msg("action")}</th>
</tr>
</thead>
<tbody>
<#list authorization.resourcesWaitingApproval as resource>
<#list resource.permissions as permission>
<form action="${url.getResourceGrant(resource.id)}" name="approveForm-${resource.id}-${permission.requester.username}" method="post">
<input type="hidden" name="action" value="grant">
<input type="hidden" name="requester" value="${permission.requester.username}">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<tr>
<td>
<#if resource.displayName??>${resource.displayName}<#else>${resource.name}</#if>
</td>
<td>
<#if permission.requester.email??>${permission.requester.email}<#else>${permission.requester.username}</#if>
</td>
<td>
<#list permission.scopes as scope>
<#if scope.scope??>
<div class="search-box">
<#if scope.scope.displayName??>
${scope.scope.displayName}
<#else>
${scope.scope.name}
</#if>
<button class="close-icon" type="button" id="grant-remove-scope-${resource.name}-${permission.requester.username}-${scope.scope.name}" name="removeScope-${resource.id}-${permission.requester.username}" onclick="removeScopeElm(this.parentNode);document.forms['approveForm-${resource.id}-${permission.requester.username}']['action'].value = 'deny';document.forms['approveForm-${resource.id}-${permission.requester.username}'].submit();"><i class="fa fa-times" aria-hidden="true"></i></button>
<input type="hidden" name="permission_id" value="${scope.id}"/>
</div>
<#else>
${msg("anyPermission")}
</#if>
</#list>
</td>
<td width="20%" align="middle" style="vertical-align: middle">
<a href="#" id="grant-${resource.name}-${permission.requester.username}" onclick="document.forms['approveForm-${resource.id}-${permission.requester.username}']['action'].value = 'grant';document.forms['approveForm-${resource.id}-${permission.requester.username}'].submit();" type="submit" class="btn btn-primary">${msg("doApprove")}</a>
<a href="#" id="deny-${resource.name}-${permission.requester.username}" onclick="removeAllScopes('${resource.id}-${permission.requester.username}');document.forms['approveForm-${resource.id}-${permission.requester.username}']['action'].value = 'deny';document.forms['approveForm-${resource.id}-${permission.requester.username}'].submit();" type="submit" class="btn btn-danger">${msg("doDeny")}</a>
</td>
</tr>
</form>
</#list>
</#list>
</tbody>
</table>
</div>
</div>
</#if>
<div class="row">
<div class="col-md-12">
<h3>
${msg("myResourcesSub")}
</h3>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>${msg("resource")}</th>
<th>${msg("application")}</th>
<th>${msg("peopleSharingThisResource")}</th>
</tr>
</thead>
<tbody>
<#if authorization.resources?size != 0>
<#list authorization.resources as resource>
<tr>
<td>
<a id="detail-${resource.name}" href="${url.getResourceDetailUrl(resource.id)}">
<#if resource.displayName??>${resource.displayName}<#else>${resource.name}</#if>
</a>
</td>
<td>
<#if resource.resourceServer.baseUri??>
<a href="${resource.resourceServer.baseUri}">${resource.resourceServer.name}</a>
<#else>
${resource.resourceServer.name}
</#if>
</td>
<td>
<#if resource.shares?size != 0>
<a href="${url.getResourceDetailUrl(resource.id)}">${resource.shares?size} <i class="fa fa-users"></i></a>
<#else>
${msg("notBeingShared")}
</#if>
</td>
</tr>
</#list>
<#else>
<tr>
<td colspan="4">${msg("notHaveAnyResource")}</td>
</tr>
</#if>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>
${msg("resourcesSharedWithMe")}
</h3>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form action="${url.resourceUrl}" name="shareForm" method="post">
<input type="hidden" name="action" value="cancel"/>
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th width="5%"><input type="checkbox" onclick="selectAllCheckBoxes('shareForm', this, 'resource_id');" <#if authorization.sharedResources?size == 0>disabled="true"</#if></td>
<th>${msg("resource")}</th>
<th>${msg("owner")}</th>
<th>${msg("application")}</th>
<th>${msg("permission")}</th>
<th>${msg("date")}</th>
</tr>
</thead>
<tbody>
<#if authorization.sharedResources?size != 0>
<#list authorization.sharedResources as resource>
<tr>
<td>
<input type="checkbox" name="resource_id" value="${resource.id}"/>
</td>
<td>
<#if resource.displayName??>${resource.displayName}<#else>${resource.name}</#if>
</td>
<td>
${resource.ownerName}
</td>
<td>
<#if resource.resourceServer.baseUri??>
<a href="${resource.resourceServer.baseUri}">${resource.resourceServer.name}</a>
<#else>
${resource.resourceServer.name}
</#if>
</td>
<td>
<#if resource.permissions?size != 0>
<ul>
<#list resource.permissions as permission>
<#list permission.scopes as scope>
<#if scope.granted && scope.scope??>
<li>
<#if scope.scope.displayName??>
${scope.scope.displayName}
<#else>
${scope.scope.name}
</#if>
</li>
<#else>
${msg("anyPermission")}
</#if>
</#list>
</#list>
</ul>
<#else>
Any action
</#if>
</td>
<td>
${resource.permissions[0].grantedDate?datetime}
</td>
</tr>
</#list>
<#else>
<tr>
<td colspan="6">${msg("noResourcesSharedWithYou")}</td>
</tr>
</#if>
</tbody>
</table>
</form>
</div>
<#if authorization.sharedResources?size != 0>
<div class="col-md-12">
<a href="#" onclick="document.forms['shareForm'].submit();" type="submit" class="btn btn-danger">${msg("doRemoveSharing")}</a>
</div>
</#if>
</div>
<#if authorization.resourcesWaitingOthersApproval?size != 0>
<br/>
<div class="row">
<div class="col-md-12">
<h3>
${msg("requestsWaitingApproval")}
</h3>
</div>
</div>
<div class="row">
<div class="col-md-12">
<i class="pficon pficon-info"></i> ${msg("havePermissionRequestsWaitingForApproval",authorization.resourcesWaitingOthersApproval?size)}
<a href="#" onclick="document.getElementById('waitingApproval').style.display=''">${msg("clickHereForDetails")}</a>
<div class="row">
<div class="col-md-12"></div>
</div>
<div class="row">
<div class="col-md-12"></div>
</div>
<div class="row">
<div class="col-md-12"></div>
</div>
<div class="row" id="waitingApproval" style="display:none">
<div class="col-md-12">
<form action="${url.resourceUrl}" name="waitingApprovalForm" method="post">
<input type="hidden" name="action" value="cancelRequest"/>
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th width="5%"><input type="checkbox" onclick="selectAllCheckBoxes('waitingApprovalForm', this, 'resource_id');" <#if authorization.resourcesWaitingOthersApproval?size == 0>disabled="true"</#if></th>
<th>${msg("resource")}</th>
<th>${msg("owner")}</th>
<th>${msg("action")}</th>
<th>${msg("date")}</th>
</tr>
</thead>
<tbody>
<#list authorization.resourcesWaitingOthersApproval as resource>
<tr>
<td>
<input type="checkbox" name="resource_id" value="${resource.id}"/>
</td>
<td>
<#if resource.displayName??>${resource.displayName}<#else>${resource.name}</#if>
</td>
<td>
${resource.ownerName}
</td>
<td>
<ul>
<#list resource.permissions as permission>
<#list permission.scopes as scope>
<li>
<#if scope.scope??>
<#if scope.scope.displayName??>
${scope.scope.displayName}
<#else>
${scope.scope.name}
</#if>
<#else>
${msg("anyPermission")}
</#if>
</li>
</#list>
</#list>
</ul>
</td>
<td>
${resource.permissions[0].createdDate?datetime}
</td>
</tr>
</#list>
</tbody>
</table>
</form>
</div>
<div class="col-md-12">
<a href="#" onclick="document.forms['waitingApprovalForm'].submit();" type="submit" class="btn btn-danger">${msg("doRemoveRequest")}</a>
</div>
</div>
</div>
</div>
</#if>
</@layout.mainLayout>

View File

@ -0,0 +1,44 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='sessions' bodyClass='sessions'; section>
<div class="row">
<div class="col-md-10">
<h2>${msg("sessionsHtmlTitle")}</h2>
</div>
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>${msg("ip")}</td>
<td>${msg("started")}</td>
<td>${msg("lastAccess")}</td>
<td>${msg("expires")}</td>
<td>${msg("clients")}</td>
</tr>
</thead>
<tbody>
<#list sessions.sessions as session>
<tr>
<td>${session.ipAddress}</td>
<td>${session.started?datetime}</td>
<td>${session.lastAccess?datetime}</td>
<td>${session.expires?datetime}</td>
<td>
<#list session.clients as client>
${client}<br/>
</#list>
</td>
</tr>
</#list>
</tbody>
</table>
<form action="${url.sessionsUrl}" method="post">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<button id="logout-all-sessions" class="btn btn-default">${msg("doLogOutAllSessions")}</button>
</form>
</@layout.mainLayout>

View File

@ -0,0 +1,88 @@
<#macro mainLayout active bodyClass>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow">
<title>${msg("accountManagementTitle")}</title>
<link rel="icon" href="${url.resourcesPath}/img/favicon.ico">
<#if properties.stylesCommon?has_content>
<#list properties.stylesCommon?split(' ') as style>
<link href="${url.resourcesCommonPath}/${style}" rel="stylesheet" />
</#list>
</#if>
<#if properties.styles?has_content>
<#list properties.styles?split(' ') as style>
<link href="${url.resourcesPath}/${style}" rel="stylesheet" />
</#list>
</#if>
<#if properties.scripts?has_content>
<#list properties.scripts?split(' ') as script>
<script type="text/javascript" src="${url.resourcesPath}/${script}"></script>
</#list>
</#if>
</head>
<body class="admin-console user ${bodyClass}">
<header class="navbar navbar-default navbar-pf navbar-main header">
<nav class="navbar" role="navigation">
<div class="navbar-header">
<div class="container">
<h1 class="navbar-title">Keycloak</h1>
</div>
</div>
<div class="navbar-collapse navbar-collapse-1">
<div class="container">
<ul class="nav navbar-nav navbar-utility">
<#if realm.internationalizationEnabled>
<li>
<div class="kc-dropdown" id="kc-locale-dropdown">
<a href="#" id="kc-current-locale-link">${locale.current}</a>
<ul>
<#list locale.supported as l>
<li class="kc-dropdown-item"><a href="${l.url}">${l.label}</a></li>
</#list>
</ul>
</div>
<li>
</#if>
<#if referrer?has_content && referrer.url?has_content><li><a href="${referrer.url}" id="referrer">${msg("backTo",referrer.name)}</a></li></#if>
<li><a href="${url.logoutUrl}">${msg("doSignOut")}</a></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<div class="bs-sidebar col-sm-3">
<ul>
<li class="<#if active=='account'>active</#if>"><a href="${url.accountUrl}">${msg("account")}</a></li>
<#if features.passwordUpdateSupported><li class="<#if active=='password'>active</#if>"><a href="${url.passwordUrl}">${msg("password")}</a></li></#if>
<li class="<#if active=='totp'>active</#if>"><a href="${url.totpUrl}">${msg("authenticator")}</a></li>
<#if features.identityFederation><li class="<#if active=='social'>active</#if>"><a href="${url.socialUrl}">${msg("federatedIdentity")}</a></li></#if>
<li class="<#if active=='sessions'>active</#if>"><a href="${url.sessionsUrl}">${msg("sessions")}</a></li>
<li class="<#if active=='applications'>active</#if>"><a href="${url.applicationsUrl}">${msg("applications")}</a></li>
<#if features.log><li class="<#if active=='log'>active</#if>"><a href="${url.logUrl}">${msg("log")}</a></li></#if>
<#if realm.userManagedAccessAllowed && features.authorization><li class="<#if active=='authorization'>active</#if>"><a href="${url.resourceUrl}">${msg("myResources")}</a></li></#if>
</ul>
</div>
<div class="col-sm-9 content-area">
<#if message?has_content>
<div class="alert alert-${message.type}">
<#if message.type=='success' ><span class="pficon pficon-ok"></span></#if>
<#if message.type=='error' ><span class="pficon pficon-error-circle-o"></span></#if>
<span class="kc-feedback-text">${kcSanitize(message.summary)?no_esc}</span>
</div>
</#if>
<#nested "content">
</div>
</div>
</body>
</html>
</#macro>

View File

@ -0,0 +1,141 @@
<#import "template.ftl" as layout>
<@layout.mainLayout active='totp' bodyClass='totp'; section>
<div class="row">
<div class="col-md-10">
<h2>${msg("authenticatorTitle")}</h2>
</div>
<#if totp.otpCredentials?size == 0>
<div class="col-md-2 subtitle">
<span class="subtitle"><span class="required">*</span> ${msg("requiredFields")}</span>
</div>
</#if>
</div>
<#if totp.enabled>
<table class="table table-bordered table-striped">
<thead>
<#if totp.otpCredentials?size gt 1>
<tr>
<th colspan="4">${msg("configureAuthenticators")}</th>
</tr>
<#else>
<tr>
<th colspan="3">${msg("configureAuthenticators")}</th>
</tr>
</#if>
</thead>
<tbody>
<#list totp.otpCredentials as credential>
<tr>
<td class="provider">${msg("mobile")}</td>
<#if totp.otpCredentials?size gt 1>
<td class="provider">${credential.id}</td>
</#if>
<td class="provider">${credential.userLabel!}</td>
<td class="action">
<form action="${url.totpUrl}" method="post" class="form-inline">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<input type="hidden" id="submitAction" name="submitAction" value="Delete">
<input type="hidden" id="credentialId" name="credentialId" value="${credential.id}">
<button id="remove-mobile" class="btn btn-default">
<i class="pficon pficon-delete"></i>
</button>
</form>
</td>
</tr>
</#list>
</tbody>
</table>
<#else>
<hr/>
<ol>
<li>
<p>${msg("totpStep1")}</p>
<ul>
<#list totp.policy.supportedApplications as app>
<li>${app}</li>
</#list>
</ul>
</li>
<#if mode?? && mode = "manual">
<li>
<p>${msg("totpManualStep2")}</p>
<p><span id="kc-totp-secret-key">${totp.totpSecretEncoded}</span></p>
<p><a href="${totp.qrUrl}" id="mode-barcode">${msg("totpScanBarcode")}</a></p>
</li>
<li>
<p>${msg("totpManualStep3")}</p>
<ul>
<li id="kc-totp-type">${msg("totpType")}: ${msg("totp." + totp.policy.type)}</li>
<li id="kc-totp-algorithm">${msg("totpAlgorithm")}: ${totp.policy.getAlgorithmKey()}</li>
<li id="kc-totp-digits">${msg("totpDigits")}: ${totp.policy.digits}</li>
<#if totp.policy.type = "totp">
<li id="kc-totp-period">${msg("totpInterval")}: ${totp.policy.period}</li>
<#elseif totp.policy.type = "hotp">
<li id="kc-totp-counter">${msg("totpCounter")}: ${totp.policy.initialCounter}</li>
</#if>
</ul>
</li>
<#else>
<li>
<p>${msg("totpStep2")}</p>
<p><img src="data:image/png;base64, ${totp.totpSecretQrCode}" alt="Figure: Barcode"></p>
<p><a href="${totp.manualUrl}" id="mode-manual">${msg("totpUnableToScan")}</a></p>
</li>
</#if>
<li>
<p>${msg("totpStep3")}</p>
<p>${msg("totpStep3DeviceName")}</p>
</li>
</ol>
<hr/>
<form action="${url.totpUrl}" class="form-horizontal" method="post">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<div class="form-group">
<div class="col-sm-2 col-md-2">
<label for="totp" class="control-label">${msg("authenticatorCode")}</label> <span class="required">*</span>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="form-control" id="totp" name="totp" autocomplete="off" autofocus>
<input type="hidden" id="totpSecret" name="totpSecret" value="${totp.totpSecret}"/>
</div>
</div>
<div class="form-group" ${messagesPerField.printIfExists('userLabel',properties.kcFormGroupErrorClass!)}">
<div class="col-sm-2 col-md-2">
<label for="userLabel" class="control-label">${msg("totpDeviceName")}</label> <#if totp.otpCredentials?size gte 1><span class="required">*</span></#if>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="form-control" id="userLabel" name="userLabel" autocomplete="off">
</div>
</div>
<div class="form-group">
<div id="kc-form-buttons" class="col-md-offset-2 col-md-10 submit">
<div class="">
<button type="submit"
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}"
id="saveTOTPBtn" name="submitAction" value="Save">${msg("doSave")}
</button>
<button type="submit"
class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}"
id="cancelTOTPBtn" name="submitAction" value="Cancel">${msg("doCancel")}
</button>
</div>
</div>
</div>
</form>
</#if>
</@layout.mainLayout>