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:
Serreau Jovann
2026-04-10 11:22:40 +02:00
parent fb62e7f942
commit 581d6a0929
7 changed files with 401 additions and 6 deletions

View 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;
}

View File

@@ -0,0 +1,4 @@
parent=keycloak.v2
import=common/keycloak
locales=fr,en
styles=css/account.css

View 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;">
&copy; E-Cosplay &middot; <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>

View 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>

View File

@@ -0,0 +1,2 @@
parent=keycloak
locales=fr,en