- 6 docs racine (README, HANDOVER, ARCHITECTURE, DECISIONS, INSTALL, OPERATIONS) - 9 docs thématiques dans docs/ - 10 templates docker-compose dans configs/ - 7 scripts Python/Shell d'import Furious vers Zitadel - 2 matrices RBAC Etat infra au 5 juin 2026 : - 88 users Furious importes dans Zitadel - 8 roles RBAC crees et attribues - Intranet filtre les cartes selon role (Approche A) - 7 outils SSO operationnels
240 lines
8.3 KiB
Plaintext
240 lines
8.3 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Seize Consulting — Intranet</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Inter+Tight:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
|
|
<!--
|
|
============================================================================
|
|
TEMPLATE INTRANET SEIZE CONSULTING
|
|
============================================================================
|
|
Ce fichier est un template. Le vrai fichier en production est sur le serveur
|
|
sur ~/docker/intranet/index.html.
|
|
|
|
Points clés :
|
|
- __USER_EMAIL__ est un placeholder substitué par nginx (sub_filter)
|
|
- Chaque carte service-card a un attribut data-app="<nom>" pour le RBAC
|
|
- Le JavaScript en bas fait le filtrage selon le rôle
|
|
============================================================================
|
|
-->
|
|
|
|
<style>
|
|
:root {
|
|
--c-bg-deep: #071C1C;
|
|
--c-surface: rgba(8, 57, 52, 0.6);
|
|
--c-surface-2: rgba(169, 212, 211, 0.04);
|
|
--c-accent: #008A81;
|
|
--c-accent-bright: #00C9B7;
|
|
--c-mint: #A9D4D3;
|
|
--c-lime: #F3FBBA;
|
|
--c-cream: #FBFBF4;
|
|
--c-text-dim: rgba(251, 251, 244, 0.55);
|
|
--c-text-muted: rgba(251, 251, 244, 0.4);
|
|
--c-border: rgba(169, 212, 211, 0.12);
|
|
--c-border-bright: rgba(169, 212, 211, 0.3);
|
|
--font-display: 'Space Grotesk', sans-serif;
|
|
--font-body: 'Inter Tight', sans-serif;
|
|
--font-mono: 'JetBrains Mono', monospace;
|
|
}
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
html, body {
|
|
background: var(--c-bg-deep);
|
|
color: var(--c-cream);
|
|
font-family: var(--font-body);
|
|
min-height: 100vh;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
/* ⚠️ Les styles complets (orbs, animations, etc.) sont dans le fichier réel.
|
|
Ici on garde le minimum pour ne pas surcharger le template. */
|
|
|
|
.container {
|
|
position: relative; z-index: 10;
|
|
max-width: 1400px; margin: 0 auto; padding: 60px 40px;
|
|
}
|
|
.brand {
|
|
display: flex; align-items: center; gap: 16px; margin-bottom: 60px;
|
|
}
|
|
.brand-logo img { height: 50px; }
|
|
.brand-title {
|
|
font-family: var(--font-display); font-size: 28px; font-weight: 700;
|
|
}
|
|
.intro {
|
|
margin-bottom: 50px;
|
|
}
|
|
.intro h1 {
|
|
font-family: var(--font-display); font-size: 48px; font-weight: 700;
|
|
margin-bottom: 12px;
|
|
}
|
|
.services-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
gap: 24px;
|
|
}
|
|
.service-card {
|
|
background: var(--c-surface);
|
|
border: 1px solid var(--c-border);
|
|
border-radius: 16px; padding: 24px;
|
|
display: flex; flex-direction: column; gap: 12px;
|
|
text-decoration: none; color: inherit;
|
|
transition: all 0.3s ease;
|
|
}
|
|
.service-card:hover {
|
|
border-color: var(--c-border-bright);
|
|
transform: translateY(-4px);
|
|
}
|
|
.card-title {
|
|
font-family: var(--font-display); font-size: 22px; font-weight: 600;
|
|
}
|
|
.card-desc {
|
|
color: var(--c-text-dim); font-size: 14px; line-height: 1.5;
|
|
}
|
|
.card-meta {
|
|
display: flex; gap: 8px; flex-wrap: wrap; font-family: var(--font-mono); font-size: 11px;
|
|
}
|
|
.card-url { color: var(--c-mint); }
|
|
.card-tag {
|
|
background: var(--c-surface-2); padding: 4px 10px; border-radius: 12px;
|
|
color: var(--c-accent-bright);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="container">
|
|
<div class="brand">
|
|
<div class="brand-logo"><img src="/logo.png" alt="Seize"></div>
|
|
<div class="brand-title">Seize Consulting</div>
|
|
</div>
|
|
|
|
<div class="intro">
|
|
<h1>Tableau de bord</h1>
|
|
<p>Accédez à vos outils internes</p>
|
|
</div>
|
|
|
|
<div class="services-grid">
|
|
|
|
<!-- ⚠️ Chaque carte a un attribut data-app="<nom>" pour le RBAC -->
|
|
<!-- Le JavaScript en bas du fichier filtre ces cartes selon le rôle -->
|
|
|
|
<!-- PORTAINER -->
|
|
<a class="service-card" data-app="portainer" href="https://portainer.seizeconsulting.com" target="_blank" rel="noopener">
|
|
<div class="card-title">Portainer</div>
|
|
<div class="card-desc">Console de gestion des conteneurs Docker.</div>
|
|
<div class="card-meta">
|
|
<span class="card-url">portainer.seizeconsulting.com</span>
|
|
<span class="card-tag">Infra</span>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- UPTIME KUMA / STATUS -->
|
|
<a class="service-card" data-app="status" href="https://status.seizeconsulting.com" target="_blank" rel="noopener">
|
|
<div class="card-title">Status</div>
|
|
<div class="card-desc">Surveillance de la disponibilité des services.</div>
|
|
<div class="card-meta">
|
|
<span class="card-url">status.seizeconsulting.com</span>
|
|
<span class="card-tag">Monitoring</span>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- N8N -->
|
|
<a class="service-card" data-app="n8n" href="https://n8n.seizeconsulting.com" target="_blank" rel="noopener">
|
|
<div class="card-title">n8n</div>
|
|
<div class="card-desc">Plateforme d'automatisation de workflows.</div>
|
|
<div class="card-meta">
|
|
<span class="card-url">n8n.seizeconsulting.com</span>
|
|
<span class="card-tag">Automation</span>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- GITEA -->
|
|
<a class="service-card" data-app="gitea" href="https://git.seizeconsulting.com" target="_blank" rel="noopener">
|
|
<div class="card-title">Gitea</div>
|
|
<div class="card-desc">Dépôts Git et gestion collaborative du code.</div>
|
|
<div class="card-meta">
|
|
<span class="card-url">git.seizeconsulting.com</span>
|
|
<span class="card-tag">Code</span>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- CODE SERVER -->
|
|
<a class="service-card" data-app="code" href="https://code.seizeconsulting.com" target="_blank" rel="noopener">
|
|
<div class="card-title">Code Server</div>
|
|
<div class="card-desc">Environnement VS Code dans le navigateur.</div>
|
|
<div class="card-meta">
|
|
<span class="card-url">code.seizeconsulting.com</span>
|
|
<span class="card-tag">IDE</span>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- TRAEFIK -->
|
|
<a class="service-card" data-app="traefik" href="https://traefik.seizeconsulting.com" target="_blank" rel="noopener">
|
|
<div class="card-title">Traefik</div>
|
|
<div class="card-desc">Reverse proxy et routage du trafic.</div>
|
|
<div class="card-meta">
|
|
<span class="card-url">traefik.seizeconsulting.com</span>
|
|
<span class="card-tag">Réseau</span>
|
|
</div>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<footer>
|
|
<div>SEIZE CONSULTING · © 2026</div>
|
|
<div>Hébergé en France · Made with care</div>
|
|
</footer>
|
|
</div>
|
|
|
|
<script>
|
|
/* ============================================================================
|
|
RBAC INTRANET — Filtrage des cartes selon rôle Zitadel
|
|
============================================================================
|
|
- __USER_EMAIL__ est remplacé par nginx (sub_filter) par la valeur du
|
|
header X-Forwarded-Email (envoyé par OAuth2-Proxy après auth Zitadel)
|
|
- On fetch /roles-mapping.json (généré par generate-roles-mapping.py)
|
|
- Pour chaque carte service-card[data-app], on cache si rôle pas autorisé
|
|
============================================================================ */
|
|
(async function() {
|
|
const USER_EMAIL = "__USER_EMAIL__"; // ← Substitué par nginx sub_filter
|
|
|
|
/* Matrice RBAC : qui voit quelle carte */
|
|
const ACCESS_MATRIX = {
|
|
"portainer": ["direction", "manager"],
|
|
"status": ["direction"],
|
|
"n8n": ["direction", "manager", "expert"],
|
|
"gitea": ["direction", "manager", "expert", "consultant_senior", "consultant_junior", "alternant", "stagiaire", "support"],
|
|
"code": ["direction", "manager", "expert", "consultant_senior", "consultant_junior", "alternant", "stagiaire", "support"],
|
|
"traefik": ["direction"]
|
|
};
|
|
|
|
let userRole = null;
|
|
try {
|
|
const response = await fetch("/roles-mapping.json", { cache: "no-store" });
|
|
if (response.ok) {
|
|
const mapping = await response.json();
|
|
userRole = mapping[USER_EMAIL.toLowerCase()] || null;
|
|
}
|
|
} catch (e) {
|
|
console.error("[RBAC] Erreur chargement mapping:", e);
|
|
}
|
|
|
|
console.log("[RBAC] User:", USER_EMAIL, "| Rôle:", userRole);
|
|
|
|
/* Filtrer les cartes selon le rôle */
|
|
document.querySelectorAll(".service-card[data-app]").forEach(card => {
|
|
const app = card.dataset.app;
|
|
const allowedRoles = ACCESS_MATRIX[app] || [];
|
|
if (!userRole || !allowedRoles.includes(userRole)) {
|
|
card.style.display = "none";
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|