Go-live, ecosplay realm-as-code, and full theme coverage
Go-live: - Switch keycloak from start-dev to start --import-realm (production mode with auto-build at boot, no Dockerfile needed yet). - Set KC_HOSTNAME=https://auth.e-cosplay.fr and KC_PROXY_HEADERS= xforwarded so Keycloak emits correct issuer URLs and trusts Caddy's X-Forwarded-* headers. - Replace deprecated KEYCLOAK_ADMIN env vars with KC_BOOTSTRAP_ADMIN_*. - Bind the public port to 127.0.0.1 only (Caddy is colocated). - Add a Keycloak healthcheck against /health/ready on the management port (9000) using bash /dev/tcp; init container now waits on service_healthy instead of service_started. Architecture: - New realms/ecosplay-realm.json mounted into /opt/keycloak/data/import and imported on first boot. Defines the dedicated 'ecosplay' realm (separate from master) with French i18n, brute-force protection, strong password policy, SES SMTP, and an OIDC client 'ecosplay-web' pointing at e-cosplay.fr (confidential + PKCE S256). Theme coverage: - themes/ecosplay/account: PatternFly v5 overlay (parent=keycloak.v2) bringing the neo-brutalist colors, thick borders, italic uppercase typography, and offset hard shadows to the user account console. - themes/ecosplay/email: branded HTML wrapper template (table layout with inline styles for email-client safety) plus a matching plain text wrapper. All Keycloak emails now ship with the E-Cosplay identity without needing per-template overrides. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,22 +21,30 @@ services:
|
|||||||
image: quay.io/keycloak/keycloak:26.0
|
image: quay.io/keycloak/keycloak:26.0
|
||||||
container_name: ecosplay-auth-keycloak
|
container_name: ecosplay-auth-keycloak
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: start-dev
|
command: ["start", "--import-realm"]
|
||||||
environment:
|
environment:
|
||||||
KC_DB: postgres
|
KC_DB: postgres
|
||||||
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
|
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
|
||||||
KC_DB_USERNAME: keycloak
|
KC_DB_USERNAME: keycloak
|
||||||
KC_DB_PASSWORD: keycloak
|
KC_DB_PASSWORD: keycloak
|
||||||
KC_HOSTNAME: localhost
|
KC_HOSTNAME: https://auth.e-cosplay.fr
|
||||||
KC_HTTP_ENABLED: "true"
|
KC_HTTP_ENABLED: "true"
|
||||||
|
KC_PROXY_HEADERS: xforwarded
|
||||||
KC_HEALTH_ENABLED: "true"
|
KC_HEALTH_ENABLED: "true"
|
||||||
KC_METRICS_ENABLED: "true"
|
KC_METRICS_ENABLED: "true"
|
||||||
KEYCLOAK_ADMIN: admin
|
KC_BOOTSTRAP_ADMIN_USERNAME: admin
|
||||||
KEYCLOAK_ADMIN_PASSWORD: admin
|
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
|
||||||
ports:
|
ports:
|
||||||
- "9450:8080"
|
- "127.0.0.1:9450:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ./themes/ecosplay:/opt/keycloak/themes/ecosplay:ro
|
- ./themes/ecosplay:/opt/keycloak/themes/ecosplay:ro
|
||||||
|
- ./realms:/opt/keycloak/data/import:ro
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "exec 3<>/dev/tcp/localhost/9000 && printf 'GET /health/ready HTTP/1.0\\r\\nHost: localhost\\r\\n\\r\\n' >&3 && grep -q UP <&3"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 30
|
||||||
|
start_period: 120s
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -48,7 +56,7 @@ services:
|
|||||||
container_name: ecosplay-auth-init
|
container_name: ecosplay-auth-init
|
||||||
depends_on:
|
depends_on:
|
||||||
keycloak:
|
keycloak:
|
||||||
condition: service_started
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
KC_SERVER: http://keycloak:8080
|
KC_SERVER: http://keycloak:8080
|
||||||
KC_ADMIN: admin
|
KC_ADMIN: admin
|
||||||
|
|||||||
85
realms/ecosplay-realm.json
Normal file
85
realms/ecosplay-realm.json
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"realm": "ecosplay",
|
||||||
|
"displayName": "E-Cosplay",
|
||||||
|
"displayNameHtml": "<span style=\"font-weight:900;text-transform:uppercase;font-style:italic;\">E-Cosplay</span>",
|
||||||
|
"enabled": true,
|
||||||
|
|
||||||
|
"loginTheme": "ecosplay",
|
||||||
|
"accountTheme": "ecosplay",
|
||||||
|
"emailTheme": "ecosplay",
|
||||||
|
"adminTheme": "keycloak.v2",
|
||||||
|
|
||||||
|
"internationalizationEnabled": true,
|
||||||
|
"supportedLocales": ["fr"],
|
||||||
|
"defaultLocale": "fr",
|
||||||
|
|
||||||
|
"registrationAllowed": true,
|
||||||
|
"registrationEmailAsUsername": true,
|
||||||
|
"rememberMe": true,
|
||||||
|
"verifyEmail": true,
|
||||||
|
"loginWithEmailAllowed": true,
|
||||||
|
"duplicateEmailsAllowed": false,
|
||||||
|
"resetPasswordAllowed": true,
|
||||||
|
"editUsernameAllowed": false,
|
||||||
|
|
||||||
|
"bruteForceProtected": true,
|
||||||
|
"permanentLockout": false,
|
||||||
|
"maxFailureWaitSeconds": 900,
|
||||||
|
"minimumQuickLoginWaitSeconds": 60,
|
||||||
|
"waitIncrementSeconds": 60,
|
||||||
|
"quickLoginCheckMilliSeconds": 1000,
|
||||||
|
"maxDeltaTimeSeconds": 43200,
|
||||||
|
"failureFactor": 5,
|
||||||
|
|
||||||
|
"passwordPolicy": "length(10) and specialChars(1) and digits(1) and upperCase(1) and lowerCase(1) and notUsername(undefined) and notEmail(undefined)",
|
||||||
|
|
||||||
|
"accessTokenLifespan": 300,
|
||||||
|
"accessTokenLifespanForImplicitFlow": 900,
|
||||||
|
"ssoSessionIdleTimeout": 1800,
|
||||||
|
"ssoSessionMaxLifespan": 36000,
|
||||||
|
"offlineSessionIdleTimeout": 2592000,
|
||||||
|
"actionTokenGeneratedByUserLifespan": 900,
|
||||||
|
|
||||||
|
"smtpServer": {
|
||||||
|
"host": "email-smtp.eu-west-3.amazonaws.com",
|
||||||
|
"port": "587",
|
||||||
|
"from": "auth@e-cosplay.fr",
|
||||||
|
"fromDisplayName": "E-Cosplay",
|
||||||
|
"replyTo": "noreply@e-cosplay.fr",
|
||||||
|
"envelopeFrom": "auth@e-cosplay.fr",
|
||||||
|
"auth": "true",
|
||||||
|
"starttls": "true",
|
||||||
|
"ssl": "false",
|
||||||
|
"user": "AKIAWTT2T22CWBRBBDYN",
|
||||||
|
"password": "BBdgb6KxRQ8mNcpWFJsZCJxbSGNdgLhKFiITMErfBlQP"
|
||||||
|
},
|
||||||
|
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"clientId": "ecosplay-web",
|
||||||
|
"name": "E-Cosplay Web",
|
||||||
|
"description": "Application web principale e-cosplay.fr",
|
||||||
|
"enabled": true,
|
||||||
|
"publicClient": false,
|
||||||
|
"secret": "change-me-in-admin-console",
|
||||||
|
"redirectUris": [
|
||||||
|
"https://www.e-cosplay.fr/*",
|
||||||
|
"https://e-cosplay.fr/*"
|
||||||
|
],
|
||||||
|
"webOrigins": [
|
||||||
|
"https://www.e-cosplay.fr",
|
||||||
|
"https://e-cosplay.fr"
|
||||||
|
],
|
||||||
|
"protocol": "openid-connect",
|
||||||
|
"standardFlowEnabled": true,
|
||||||
|
"implicitFlowEnabled": false,
|
||||||
|
"directAccessGrantsEnabled": false,
|
||||||
|
"serviceAccountsEnabled": false,
|
||||||
|
"frontchannelLogout": true,
|
||||||
|
"attributes": {
|
||||||
|
"post.logout.redirect.uris": "https://www.e-cosplay.fr/*##https://e-cosplay.fr/*",
|
||||||
|
"pkce.code.challenge.method": "S256"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
228
themes/ecosplay/account/resources/css/account.css
Normal file
228
themes/ecosplay/account/resources/css/account.css
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
/* ============================================================
|
||||||
|
E-Cosplay neo-brutalist overlay for the v2 (PatternFly) account console
|
||||||
|
============================================================ */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--pf-v5-global--primary-color--100: #4f46e5;
|
||||||
|
--pf-v5-global--primary-color--200: #4338ca;
|
||||||
|
--pf-v5-global--primary-color--light-100: #6366f1;
|
||||||
|
--pf-v5-global--link--Color: #4f46e5;
|
||||||
|
--pf-v5-global--link--Color--hover: #111827;
|
||||||
|
--pf-v5-global--BackgroundColor--100: #fbfbfb;
|
||||||
|
--pf-v5-global--BackgroundColor--200: #ffffff;
|
||||||
|
--pf-v5-global--BorderColor--100: #111827;
|
||||||
|
--pf-v5-global--FontFamily--text: ui-sans-serif, system-ui, -apple-system,
|
||||||
|
"Segoe UI", Roboto, sans-serif;
|
||||||
|
--pf-v5-global--FontFamily--heading: ui-sans-serif, system-ui, -apple-system,
|
||||||
|
"Segoe UI", Roboto, sans-serif;
|
||||||
|
--pf-v5-global--FontFamily--monospace: ui-monospace, "SFMono-Regular",
|
||||||
|
Menlo, monospace;
|
||||||
|
--pf-v5-global--FontWeight--bold: 900;
|
||||||
|
--pf-v5-global--BorderRadius--sm: 0;
|
||||||
|
--pf-v5-global--BorderRadius--lg: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
.pf-v5-c-page,
|
||||||
|
.pf-v5-c-page__main {
|
||||||
|
background-color: #fbfbfb !important;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header band */
|
||||||
|
.pf-v5-c-masthead {
|
||||||
|
background-color: #111827 !important;
|
||||||
|
border-bottom: 4px solid #4f46e5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-masthead__brand,
|
||||||
|
.pf-v5-c-masthead__main {
|
||||||
|
color: #ffffff !important;
|
||||||
|
font-weight: 900 !important;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
letter-spacing: 0.15em !important;
|
||||||
|
font-style: italic !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cards */
|
||||||
|
.pf-v5-c-card {
|
||||||
|
background-color: #ffffff !important;
|
||||||
|
border: 4px solid #111827 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
box-shadow: 8px 8px 0 rgba(0, 0, 0, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-card__title,
|
||||||
|
.pf-v5-c-card__title-text {
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
font-style: italic !important;
|
||||||
|
font-weight: 900 !important;
|
||||||
|
letter-spacing: -0.02em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Headings */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
.pf-v5-c-title,
|
||||||
|
.pf-v5-c-content h1,
|
||||||
|
.pf-v5-c-content h2,
|
||||||
|
.pf-v5-c-content h3 {
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
font-style: italic !important;
|
||||||
|
font-weight: 900 !important;
|
||||||
|
letter-spacing: -0.025em !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form labels */
|
||||||
|
.pf-v5-c-form__label,
|
||||||
|
.pf-v5-c-form__label-text {
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
font-weight: 900 !important;
|
||||||
|
letter-spacing: 0.1em !important;
|
||||||
|
font-size: 11px !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
font-style: normal !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inputs */
|
||||||
|
.pf-v5-c-form-control,
|
||||||
|
.pf-v5-c-form-control input,
|
||||||
|
input.pf-v5-c-form-control,
|
||||||
|
.pf-v5-c-text-input-group__text-input {
|
||||||
|
border: 4px solid #111827 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
background-color: #ffffff !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
font-weight: 700 !important;
|
||||||
|
font-style: normal !important;
|
||||||
|
padding: 12px 14px !important;
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-form-control:focus,
|
||||||
|
.pf-v5-c-form-control:focus-within {
|
||||||
|
background-color: #fef9c3 !important;
|
||||||
|
box-shadow: 6px 6px 0 #4f46e5 !important;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.pf-v5-c-button {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border: 4px solid #111827 !important;
|
||||||
|
font-weight: 900 !important;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
letter-spacing: 0.12em !important;
|
||||||
|
font-style: italic !important;
|
||||||
|
padding: 14px 24px !important;
|
||||||
|
transition: all 0.15s ease !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-primary {
|
||||||
|
background-color: #4f46e5 !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
box-shadow: 6px 6px 0 rgba(0, 0, 0, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-primary:hover {
|
||||||
|
background-color: #4338ca !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
transform: translate(4px, 4px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-secondary {
|
||||||
|
background-color: #ffffff !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
box-shadow: 6px 6px 0 rgba(0, 0, 0, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-secondary:hover {
|
||||||
|
background-color: #facc15 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
transform: translate(4px, 4px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-danger {
|
||||||
|
background-color: #dc2626 !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
box-shadow: 6px 6px 0 rgba(0, 0, 0, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-link {
|
||||||
|
color: #4f46e5 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
text-decoration: underline !important;
|
||||||
|
text-underline-offset: 4px !important;
|
||||||
|
text-decoration-thickness: 3px !important;
|
||||||
|
padding: 4px 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-link:hover {
|
||||||
|
color: #111827 !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav */
|
||||||
|
.pf-v5-c-nav__link {
|
||||||
|
font-weight: 900 !important;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
letter-spacing: 0.1em !important;
|
||||||
|
font-style: italic !important;
|
||||||
|
border-left: 4px solid transparent !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-nav__link.pf-m-current,
|
||||||
|
.pf-v5-c-nav__link:hover {
|
||||||
|
border-left-color: #4f46e5 !important;
|
||||||
|
background-color: #fef9c3 !important;
|
||||||
|
color: #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alerts */
|
||||||
|
.pf-v5-c-alert {
|
||||||
|
border: 4px solid #111827 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
box-shadow: 6px 6px 0 rgba(0, 0, 0, 1) !important;
|
||||||
|
font-weight: 800 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-alert.pf-m-success {
|
||||||
|
background-color: #bbf7d0 !important;
|
||||||
|
}
|
||||||
|
.pf-v5-c-alert.pf-m-warning {
|
||||||
|
background-color: #fde68a !important;
|
||||||
|
}
|
||||||
|
.pf-v5-c-alert.pf-m-danger {
|
||||||
|
background-color: #fecaca !important;
|
||||||
|
}
|
||||||
|
.pf-v5-c-alert.pf-m-info {
|
||||||
|
background-color: #c7d2fe !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
.pf-v5-c-table {
|
||||||
|
border: 4px solid #111827 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-table thead th {
|
||||||
|
background-color: #111827 !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
font-weight: 900 !important;
|
||||||
|
letter-spacing: 0.1em !important;
|
||||||
|
font-style: italic !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
a {
|
||||||
|
color: #4f46e5 !important;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #111827 !important;
|
||||||
|
text-decoration-thickness: 3px !important;
|
||||||
|
}
|
||||||
4
themes/ecosplay/account/theme.properties
Normal file
4
themes/ecosplay/account/theme.properties
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
parent=keycloak.v2
|
||||||
|
import=common/keycloak
|
||||||
|
locales=fr,en
|
||||||
|
styles=css/account.css
|
||||||
52
themes/ecosplay/email/html/template.ftl
Normal file
52
themes/ecosplay/email/html/template.ftl
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<#macro emailLayout>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>E-Cosplay</title>
|
||||||
|
</head>
|
||||||
|
<body style="margin:0;padding:0;background-color:#fbfbfb;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;color:#111827;">
|
||||||
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color:#fbfbfb;padding:40px 16px;">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" style="max-width:600px;width:100%;">
|
||||||
|
|
||||||
|
<!-- Top bar -->
|
||||||
|
<tr>
|
||||||
|
<td style="background-color:#111827;border:4px solid #111827;padding:18px 24px;color:#ffffff;font-weight:900;text-transform:uppercase;letter-spacing:0.25em;font-size:12px;font-style:italic;">
|
||||||
|
// Authentification // E-Cosplay
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Main card -->
|
||||||
|
<tr>
|
||||||
|
<td style="background-color:#ffffff;border:4px solid #111827;border-top:0;padding:40px 32px;">
|
||||||
|
<p style="margin:0 0 24px 0;color:#4f46e5;font-weight:900;text-transform:uppercase;letter-spacing:0.3em;font-size:11px;font-style:italic;">// Connexion sécurisée</p>
|
||||||
|
<div style="font-size:16px;line-height:1.65;font-weight:600;color:#1f2937;font-style:normal;">
|
||||||
|
<#nested>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Yellow accent bar -->
|
||||||
|
<tr>
|
||||||
|
<td style="background-color:#facc15;border:4px solid #111827;border-top:0;padding:14px 24px;color:#111827;font-weight:900;text-transform:uppercase;letter-spacing:0.18em;font-size:11px;font-style:italic;text-align:center;">
|
||||||
|
Communauté Inclusive // Hauts-de-France
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<tr>
|
||||||
|
<td style="padding:24px 8px 0 8px;text-align:center;color:#6b7280;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.1em;font-style:italic;line-height:1.6;">
|
||||||
|
© E-Cosplay · <a href="https://www.e-cosplay.fr" style="color:#4f46e5;text-decoration:underline;">www.e-cosplay.fr</a><br/>
|
||||||
|
Cet email vous a été envoyé suite à une action sur votre compte. Si vous n'êtes pas à l'origine de cette demande, ignorez ce message.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</#macro>
|
||||||
16
themes/ecosplay/email/text/template.ftl
Normal file
16
themes/ecosplay/email/text/template.ftl
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<#macro emailLayout>
|
||||||
|
=========================================================
|
||||||
|
// E-COSPLAY // CONNEXION SECURISEE
|
||||||
|
=========================================================
|
||||||
|
|
||||||
|
<#nested>
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
E-Cosplay - Communaute Inclusive - Hauts-de-France
|
||||||
|
https://www.e-cosplay.fr
|
||||||
|
|
||||||
|
Cet email vous a ete envoye suite a une action sur votre
|
||||||
|
compte. Si vous n'etes pas a l'origine de cette demande,
|
||||||
|
ignorez ce message.
|
||||||
|
---------------------------------------------------------
|
||||||
|
</#macro>
|
||||||
2
themes/ecosplay/email/theme.properties
Normal file
2
themes/ecosplay/email/theme.properties
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
parent=keycloak
|
||||||
|
locales=fr,en
|
||||||
Reference in New Issue
Block a user