diff --git a/.env b/.env index 7b257f9d..217e7fdf 100644 --- a/.env +++ b/.env @@ -11,6 +11,8 @@ KEYCLOAK_CLIENT_SECRET="QJiOGn09eCEfnqAmcPP2l4vMU8grlmVQ" REDIRECT_URIS=http://${HOSTNAME}/docs/oauth2-redirect POST_LOGOUT_REDIRECT_URIS=http://${HOSTNAME}/aiod-auth/realms/aiod/protocol/openid-connect/logout +EGICHECKINALIAS= + #ELASTICSEARCH ES_USER=elastic ES_PASSWORD=changeme @@ -23,4 +25,4 @@ LS_JAVA_OPTS="-Xmx256m -Xms256m" #DATA STORAGE DATA_PATH=./data -BACKUP_PATH=./data/backups \ No newline at end of file +BACKUP_PATH=./data/backups diff --git a/data/keycloak/import/realm-export.json b/data/keycloak/data/import/realm-export.json similarity index 99% rename from data/keycloak/import/realm-export.json rename to data/keycloak/data/import/realm-export.json index cc0972ae..da01070f 100644 --- a/data/keycloak/import/realm-export.json +++ b/data/keycloak/data/import/realm-export.json @@ -1527,6 +1527,7 @@ "strictTransportSecurity": "max-age=31536000; includeSubDomains" }, "smtpServer": {}, + "loginTheme" : "aiod", "eventsEnabled": false, "eventsListeners": [ "jboss-logging" diff --git a/data/keycloak/themes/aiod/login/login.ftl b/data/keycloak/themes/aiod/login/login.ftl new file mode 100755 index 00000000..94020948 --- /dev/null +++ b/data/keycloak/themes/aiod/login/login.ftl @@ -0,0 +1,123 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username','password') displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled??; section> + <#if section = "header"> + ${msg("loginAccountTitle")} + <#elseif section = "form"> +
+
+ <#if social.providers??> +

${msg("identity-provider-login-label")}

+
+ <#else> +
+ + <#if realm.password> +
+ <#if !usernameHidden??> +
+ + + + + <#if messagesPerField.existsError('username','password')> + + ${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc} + + + +
+ + +
+ + +
+ + +
+ + <#if usernameHidden?? && messagesPerField.existsError('username','password')> + + ${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc} + + + +
+ +
+
+ <#if realm.rememberMe && !usernameHidden??> +
+ +
+ +
+
+ <#if realm.resetPasswordAllowed> + ${msg("doForgotPassword")} + +
+ +
+ +
+ value="${auth.selectedCredential}"/> + +
+
+ +
+
+ + <#elseif section = "info" > + <#if realm.password && realm.registrationAllowed && !registrationDisabled??> +
+
+ ${msg("noAccount")} ${msg("doRegister")} +
+
+ + <#elseif section = "socialProviders" > + <#if realm.password && social?? && social.providers?has_content> +
+ +
+ + + + diff --git a/data/keycloak/themes/aiod/login/messages/messages_en.properties b/data/keycloak/themes/aiod/login/messages/messages_en.properties new file mode 100644 index 00000000..cff63e19 --- /dev/null +++ b/data/keycloak/themes/aiod/login/messages/messages_en.properties @@ -0,0 +1 @@ +identity-provider-login-label=Or sign in with your local account diff --git a/data/keycloak/themes/aiod/login/resources/css/styles.css b/data/keycloak/themes/aiod/login/resources/css/styles.css new file mode 100644 index 00000000..b8c45139 --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/css/styles.css @@ -0,0 +1,80 @@ +body { + color: white; +} + +login-pf { + background: none; +} + +.form-group { + font-size: small; +} + +.btn-group-lg { + font-size: small; +} + +.login-pf body { + background: #000613 none; +} + +#kc-header-wrapper { + font-size: 0px; + padding: 124px 10px 20px; + background: url("../img/logo.svg") no-repeat center; + background-size: contain; +} + +.card-pf { + background: transparent; +} + +.kc-form-toggle { + color: white; + text-align: center; +} + +.kc-form-toggle::after { + content: '▶︎'; + display: inline-block; + transform: rotate(0deg); + transition: transform 0.3s ease; +} + +.kc-form-toggle.up::after { + transform: rotate(90deg); +} + +.kc-form-wrapper { + display: none; +} + +h1#kc-page-title { + color: white; +} + +#social-egicheckin { + display: inline-block; + width: auto; + padding: 20px 30px 20px 80px; + border: 2px solid #005faa; + border-radius: 100vw; + background-color: #005faa; + background-image: url(../img/egi-logo-white.svg); + background-position: 30px 43%; + background-size: 36px; + background-repeat: no-repeat; + -webkit-transition: all 200ms ease-in-out; + transition: all 200ms ease-in-out; + font-family: 'DM Sans', sans-serif; + color: #fff; + font-size: 18px; + font-weight: 700; + --pf-c-button--after--BorderColor: transparent; +} + +#social-egicheckin:hover { + background-color: #fff; + background-image: url(../img/egi-logo-color.svg); + color: #005faa; +} \ No newline at end of file diff --git a/data/keycloak/themes/aiod/login/resources/img/egi-logo-color.svg b/data/keycloak/themes/aiod/login/resources/img/egi-logo-color.svg new file mode 100644 index 00000000..1250fe1c --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/img/egi-logo-color.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/keycloak/themes/aiod/login/resources/img/egi-logo-white.svg b/data/keycloak/themes/aiod/login/resources/img/egi-logo-white.svg new file mode 100644 index 00000000..17798c69 --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/img/egi-logo-white.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/keycloak/themes/aiod/login/resources/img/logo.svg b/data/keycloak/themes/aiod/login/resources/img/logo.svg new file mode 100644 index 00000000..c25c6329 --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/img/logo.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/keycloak/themes/aiod/login/resources/js/script.js b/data/keycloak/themes/aiod/login/resources/js/script.js new file mode 100644 index 00000000..06923895 --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/js/script.js @@ -0,0 +1,20 @@ +document.addEventListener('DOMContentLoaded', function() { + const toggleButton = document.getElementById('kc-form-toggle'); + const kcFormWrapper = document.getElementById('kc-form-wrapper'); + + function toggleVisibility() { + kcFormWrapper.style.display = kcFormWrapper.style.display === 'block' ? 'none' : 'block'; + toggleButton.classList.toggle('up'); + } + + // Add event listener for the click event + if (toggleButton) { + toggleButton.addEventListener('click', toggleVisibility); + } + const inputError = document.getElementById('input-error'); + if (inputError) { + // Call the function once when the content loads if the specific ID is present + toggleVisibility(); + } +}); + diff --git a/data/keycloak/themes/aiod/login/template.ftl b/data/keycloak/themes/aiod/login/template.ftl new file mode 100644 index 00000000..84fd3e43 --- /dev/null +++ b/data/keycloak/themes/aiod/login/template.ftl @@ -0,0 +1,173 @@ +<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false> + + lang="${locale.currentLanguageTag}"> + + + + + + + <#if properties.meta?has_content> + <#list properties.meta?split(' ') as meta> + + + + ${msg("loginTitle",(realm.displayName!''))} + + <#if properties.stylesCommon?has_content> + <#list properties.stylesCommon?split(' ') as style> + + + + <#if properties.styles?has_content> + <#list properties.styles?split(' ') as style> + + + + <#if properties.scripts?has_content> + <#list properties.scripts?split(' ') as script> + + + + + + <#if scripts??> + <#list scripts as script> + + + + + + + +
+
+
${kcSanitize(msg("loginTitleHtml",(realm.displayNameHtml!'')))?no_esc}
+
+
+
+ <#if realm.internationalizationEnabled && locale.supported?size gt 1> +
+
+ +
+
+ + <#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())> + <#if displayRequiredFields> +
+
+ * ${msg("requiredFields")} +
+
+

<#nested "header">

+
+
+ <#else> +

<#nested "header">

+ + <#else> + <#if displayRequiredFields> +
+
+ * ${msg("requiredFields")} +
+
+ <#nested "show-username"> +
+ + + + +
+
+
+ <#else> + <#nested "show-username"> +
+ + + + +
+ + +
+
+
+ + <#-- App-initiated actions should not see warning messages about the need to complete the action --> + <#-- during login. --> + <#if displayMessage && message?has_content && (message.type != 'warning' || !isAppInitiatedAction??)> +
+
+ <#if message.type = 'success'> + <#if message.type = 'warning'> + <#if message.type = 'error'> + <#if message.type = 'info'> +
+ ${kcSanitize(message.summary)?no_esc} +
+ + + <#nested "socialProviders"> + + <#nested "form"> + + <#if auth?has_content && auth.showTryAnotherWayLink()> +
+ +
+ + + + + <#if displayInfo> +
+
+ <#nested "info"> +
+
+ +
+
+ +
+
+ + + diff --git a/data/keycloak/themes/aiod/login/theme.properties b/data/keycloak/themes/aiod/login/theme.properties new file mode 100644 index 00000000..b766740f --- /dev/null +++ b/data/keycloak/themes/aiod/login/theme.properties @@ -0,0 +1,6 @@ +parent=keycloak +import=common/keycloak +styles=css/login.css css/styles.css +scripts=js/script.js + +egi_checkin_alias=${env.EGICHECKINALIAS} diff --git a/docker-compose.yaml b/docker-compose.yaml index 3b6e9c43..cbbf1319 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -146,7 +146,8 @@ services: ports: - 8080:8080 volumes: - - ${DATA_PATH}/keycloak:/opt/keycloak/data + - ${DATA_PATH}/keycloak/data:/opt/keycloak/data + - ${DATA_PATH}/keycloak/themes:/opt/keycloak/themes command: > start --hostname-url http://${HOSTNAME}/aiod-auth