secubox-openwrt/package/secubox/luci-app-secubox-bonus/htdocs/luci-static/secubox/demo-auth.html
CyberMind-FR 31a87c5d7a feat(structure): reorganize luci-app packages into package/secubox/ + appstore migration
Major structural reorganization and feature additions:

## Folder Reorganization
- Move 17 luci-app-* packages to package/secubox/ (except luci-app-secubox core hub)
- Update all tooling to support new structure:
  - secubox-tools/quick-deploy.sh: search both locations
  - secubox-tools/validate-modules.sh: validate both directories
  - secubox-tools/fix-permissions.sh: fix permissions in both locations
  - .github/workflows/test-validate.yml: build from both paths
- Update README.md links to new package/secubox/ paths

## AppStore Migration (Complete)
- Add catalog entries for all remaining luci-app packages:
  - network-tweaks.json: Network optimization tools
  - secubox-bonus.json: Documentation & demos hub
- Total: 24 apps in AppStore catalog (22 existing + 2 new)
- New category: 'documentation' for docs/demos/tutorials

## VHost Manager v2.0 Enhancements
- Add profile activation system for Internal Services and Redirects
- Implement createVHost() API wrapper for template-based deployment
- Fix Virtual Hosts view rendering with proper LuCI patterns
- Fix RPCD backend shell script errors (remove invalid local declarations)
- Extend backend validation for nginx return directives (redirect support)
- Add section_id parameter for named VHost profiles
- Add Remove button to Redirects page for feature parity
- Update README to v2.0 with comprehensive feature documentation

## Network Tweaks Dashboard
- Close button added to component details modal

Files changed: 340+ (336 renames with preserved git history)
Packages affected: 19 luci-app, 2 secubox-app, 1 theme, 4 tools

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 14:59:38 +01:00

669 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auth Guardian - Démo Interactive | SecuBox</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🔐</text></svg>">
<style>
:root {
--primary: #06b6d4;
--primary-dark: #0891b2;
--success: #22c55e;
--warning: #f59e0b;
--danger: #ef4444;
--dark: #0f172a;
--darker: #020617;
--card: #1e293b;
--text: #f1f5f9;
--text-muted: #94a3b8;
--border: #334155;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: system-ui, sans-serif;
background: var(--darker);
color: var(--text);
min-height: 100vh;
}
.header {
background: linear-gradient(135deg, var(--primary-dark), var(--primary));
padding: 40px 24px;
text-align: center;
}
.header h1 { font-size: 36px; margin-bottom: 8px; }
.header p { opacity: 0.9; font-size: 18px; }
.back-link {
position: absolute;
top: 20px;
left: 20px;
color: white;
text-decoration: none;
display: flex;
align-items: center;
gap: 8px;
opacity: 0.8;
}
.back-link:hover { opacity: 1; }
.container {
max-width: 1400px;
margin: 0 auto;
padding: 32px 24px;
}
.demo-grid {
display: grid;
grid-template-columns: 400px 1fr;
gap: 32px;
}
/* Splash Page Preview */
.splash-preview {
background: var(--dark);
border-radius: 20px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0,0,0,0.4);
}
.splash-header {
padding: 12px;
background: var(--card);
display: flex;
align-items: center;
gap: 8px;
}
.splash-dot {
width: 12px;
height: 12px;
border-radius: 50%;
}
.splash-dot:nth-child(1) { background: #ef4444; }
.splash-dot:nth-child(2) { background: #f59e0b; }
.splash-dot:nth-child(3) { background: #22c55e; }
.splash-content {
padding: 48px 32px;
text-align: center;
}
.splash-logo {
font-size: 64px;
margin-bottom: 24px;
}
.splash-title {
font-size: 28px;
margin-bottom: 12px;
}
.splash-message {
color: var(--text-muted);
margin-bottom: 32px;
}
.oauth-buttons {
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 24px;
}
.oauth-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
padding: 14px;
border-radius: 12px;
border: none;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.oauth-btn:hover {
transform: translateY(-2px);
}
.oauth-google {
background: white;
color: #333;
}
.oauth-github {
background: #333;
color: white;
}
.splash-divider {
display: flex;
align-items: center;
gap: 16px;
color: var(--text-muted);
margin: 24px 0;
}
.splash-divider::before,
.splash-divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--border);
}
.voucher-input {
width: 100%;
padding: 14px;
border-radius: 12px;
border: 2px solid var(--border);
background: var(--card);
color: var(--text);
font-size: 18px;
text-align: center;
letter-spacing: 4px;
text-transform: uppercase;
margin-bottom: 16px;
}
.voucher-input:focus {
outline: none;
border-color: var(--primary);
}
.connect-btn {
width: 100%;
padding: 14px;
border-radius: 12px;
border: none;
background: linear-gradient(135deg, var(--primary-dark), var(--primary));
color: white;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.connect-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(6, 182, 212, 0.4);
}
.splash-terms {
color: var(--text-muted);
font-size: 12px;
margin-top: 24px;
}
.splash-terms a {
color: var(--primary);
text-decoration: none;
}
/* Dashboard Panel */
.dashboard {
display: flex;
flex-direction: column;
gap: 24px;
}
.section {
background: var(--card);
border-radius: 16px;
padding: 24px;
border: 1px solid var(--border);
}
.section-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 8px;
}
.stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.stat-card {
background: var(--dark);
padding: 20px;
border-radius: 12px;
text-align: center;
}
.stat-value {
font-size: 28px;
font-weight: 700;
color: var(--primary);
}
.stat-label {
color: var(--text-muted);
font-size: 13px;
margin-top: 4px;
}
.session-row {
display: grid;
grid-template-columns: 1fr 140px 100px 80px 100px;
gap: 16px;
padding: 14px 16px;
background: var(--dark);
border-radius: 10px;
margin-bottom: 10px;
align-items: center;
}
.session-row.header {
background: transparent;
font-weight: 600;
color: var(--text-muted);
font-size: 12px;
text-transform: uppercase;
}
.session-user {
display: flex;
align-items: center;
gap: 12px;
}
.session-avatar {
width: 36px;
height: 36px;
background: var(--border);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
.badge {
padding: 4px 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
}
.badge-google { background: rgba(66, 133, 244, 0.2); color: #4285f4; }
.badge-github { background: rgba(255, 255, 255, 0.1); color: #fff; }
.badge-voucher { background: rgba(34, 197, 94, 0.2); color: #22c55e; }
.badge-splash { background: rgba(245, 158, 11, 0.2); color: #f59e0b; }
.voucher-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
}
.voucher-card {
background: var(--dark);
padding: 20px;
border-radius: 12px;
text-align: center;
transition: all 0.2s;
cursor: pointer;
}
.voucher-card:hover {
background: var(--border);
}
.voucher-code {
font-family: monospace;
font-size: 16px;
font-weight: 700;
color: var(--primary);
letter-spacing: 2px;
margin-bottom: 8px;
}
.voucher-status {
font-size: 12px;
}
.voucher-unused { color: var(--success); }
.voucher-used { color: var(--text-muted); text-decoration: line-through; }
.generate-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
width: 100%;
padding: 14px;
background: var(--primary);
border: none;
border-radius: 10px;
color: white;
font-weight: 600;
cursor: pointer;
margin-top: 16px;
transition: all 0.2s;
}
.generate-btn:hover {
background: var(--primary-dark);
}
.oauth-provider {
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
background: var(--dark);
border-radius: 12px;
margin-bottom: 12px;
}
.oauth-icon {
font-size: 32px;
}
.oauth-info {
flex: 1;
}
.oauth-name {
font-weight: 600;
margin-bottom: 4px;
}
.oauth-desc {
font-size: 13px;
color: var(--text-muted);
}
.oauth-status {
padding: 6px 14px;
border-radius: 8px;
font-weight: 600;
font-size: 13px;
}
.oauth-enabled {
background: rgba(34, 197, 94, 0.2);
color: var(--success);
}
.oauth-disabled {
background: rgba(100, 116, 139, 0.2);
color: var(--text-muted);
}
@media (max-width: 1024px) {
.demo-grid {
grid-template-columns: 1fr;
}
.stats-row {
grid-template-columns: repeat(2, 1fr);
}
.voucher-grid {
grid-template-columns: repeat(2, 1fr);
}
.session-row {
grid-template-columns: 1fr 100px 80px;
}
.session-row > *:nth-child(4),
.session-row > *:nth-child(5) {
display: none;
}
}
</style>
</head>
<body>
<div class="header">
<a href="index.html" class="back-link" data-i18n="demo.backToMain">← Retour à l'accueil</a>
<h1>🔐 Auth Guardian</h1>
<p>Authentification, OAuth & Vouchers</p>
</div>
<div class="container">
<div class="demo-grid">
<!-- Splash Page Preview -->
<div class="splash-preview">
<div class="splash-header">
<div class="splash-dot"></div>
<div class="splash-dot"></div>
<div class="splash-dot"></div>
<span style="flex: 1; text-align: center; color: var(--text-muted); font-size: 13px;">Portail Captif</span>
</div>
<div class="splash-content">
<div class="splash-logo">🔐</div>
<h2 class="splash-title">Bienvenue</h2>
<p class="splash-message">Authentifiez-vous pour accéder au réseau</p>
<div class="oauth-buttons">
<button class="oauth-btn oauth-google">
<svg width="20" height="20" viewBox="0 0 24 24"><path fill="#4285f4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/><path fill="#34a853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="#fbbc05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/><path fill="#ea4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>
Se connecter avec Google
</button>
<button class="oauth-btn oauth-github">
<svg width="20" height="20" fill="#fff" viewBox="0 0 24 24"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/></svg>
Se connecter avec GitHub
</button>
</div>
<div class="splash-divider">ou avec un code</div>
<input type="text" class="voucher-input" placeholder="WIFI-XXXX" maxlength="9" id="voucher-input">
<button class="connect-btn" onclick="tryVoucher()">Connexion</button>
<p class="splash-terms">En vous connectant, vous acceptez nos <a href="#">Conditions d'utilisation</a></p>
</div>
</div>
<!-- Dashboard -->
<div class="dashboard">
<!-- Stats -->
<div class="stats-row">
<div class="stat-card">
<div class="stat-value" id="stat-sessions">24</div>
<div class="stat-label">Sessions actives</div>
</div>
<div class="stat-card">
<div class="stat-value">156</div>
<div class="stat-label">Connexions aujourd'hui</div>
</div>
<div class="stat-card">
<div class="stat-value">12</div>
<div class="stat-label">Vouchers utilisés</div>
</div>
<div class="stat-card">
<div class="stat-value" style="color: var(--success);"></div>
<div class="stat-label">Portail actif</div>
</div>
</div>
<!-- Active Sessions -->
<div class="section">
<div class="section-title">👥 Sessions actives</div>
<div class="session-row header">
<div>Utilisateur</div>
<div>IP</div>
<div>Auth</div>
<div>Durée</div>
<div>Données</div>
</div>
<div class="session-row">
<div class="session-user">
<div class="session-avatar">👩</div>
<div>
<div style="font-weight: 600;">Alice Martin</div>
<div style="font-size: 12px; color: var(--text-muted);">iPhone 14 Pro</div>
</div>
</div>
<div style="font-family: monospace; font-size: 13px;">192.168.1.101</div>
<div><span class="badge badge-google">Google</span></div>
<div style="color: var(--text-muted);">2h 34m</div>
<div style="color: var(--primary);">1.2 GB</div>
</div>
<div class="session-row">
<div class="session-user">
<div class="session-avatar">👨</div>
<div>
<div style="font-weight: 600;">Bob Dupont</div>
<div style="font-size: 12px; color: var(--text-muted);">MacBook Pro</div>
</div>
</div>
<div style="font-family: monospace; font-size: 13px;">192.168.1.105</div>
<div><span class="badge badge-github">GitHub</span></div>
<div style="color: var(--text-muted);">1h 12m</div>
<div style="color: var(--primary);">3.4 GB</div>
</div>
<div class="session-row">
<div class="session-user">
<div class="session-avatar">👤</div>
<div>
<div style="font-weight: 600;">Guest-7842</div>
<div style="font-size: 12px; color: var(--text-muted);">Android</div>
</div>
</div>
<div style="font-family: monospace; font-size: 13px;">192.168.1.112</div>
<div><span class="badge badge-voucher">Voucher</span></div>
<div style="color: var(--text-muted);">45m</div>
<div style="color: var(--primary);">450 MB</div>
</div>
<div class="session-row">
<div class="session-user">
<div class="session-avatar">👤</div>
<div>
<div style="font-weight: 600;">Guest-3156</div>
<div style="font-size: 12px; color: var(--text-muted);">Windows</div>
</div>
</div>
<div style="font-family: monospace; font-size: 13px;">192.168.1.118</div>
<div><span class="badge badge-splash">Splash</span></div>
<div style="color: var(--text-muted);">12m</div>
<div style="color: var(--primary);">85 MB</div>
</div>
</div>
<!-- Vouchers -->
<div class="section">
<div class="section-title">🎟️ Vouchers</div>
<div class="voucher-grid">
<div class="voucher-card">
<div class="voucher-code">WIFI-A7B2</div>
<div class="voucher-status voucher-unused">✓ Disponible</div>
</div>
<div class="voucher-card">
<div class="voucher-code">WIFI-C9D4</div>
<div class="voucher-status voucher-unused">✓ Disponible</div>
</div>
<div class="voucher-card">
<div class="voucher-code">WIFI-E5F8</div>
<div class="voucher-status voucher-used">Utilisé</div>
</div>
<div class="voucher-card">
<div class="voucher-code">WIFI-G1H6</div>
<div class="voucher-status voucher-unused">✓ Disponible</div>
</div>
</div>
<button class="generate-btn" onclick="generateVoucher()">
Générer un nouveau voucher
</button>
</div>
<!-- OAuth Providers -->
<div class="section">
<div class="section-title">🔑 Fournisseurs OAuth</div>
<div class="oauth-provider">
<div class="oauth-icon">🔵</div>
<div class="oauth-info">
<div class="oauth-name">Google</div>
<div class="oauth-desc">Connexion avec compte Google</div>
</div>
<div class="oauth-status oauth-enabled">Activé</div>
</div>
<div class="oauth-provider">
<div class="oauth-icon"></div>
<div class="oauth-info">
<div class="oauth-name">GitHub</div>
<div class="oauth-desc">Connexion avec compte GitHub</div>
</div>
<div class="oauth-status oauth-enabled">Activé</div>
</div>
<div class="oauth-provider">
<div class="oauth-icon">🔷</div>
<div class="oauth-info">
<div class="oauth-name">Facebook</div>
<div class="oauth-desc">Connexion avec compte Facebook</div>
</div>
<div class="oauth-status oauth-disabled">Désactivé</div>
</div>
<div class="oauth-provider">
<div class="oauth-icon">🐦</div>
<div class="oauth-info">
<div class="oauth-name">Twitter/X</div>
<div class="oauth-desc">Connexion avec compte Twitter</div>
</div>
<div class="oauth-status oauth-disabled">Désactivé</div>
</div>
</div>
</div>
</div>
</div>
<script>
function generateVoucher() {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
let code = 'WIFI-';
for (let i = 0; i < 4; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length));
}
alert('Nouveau voucher généré: ' + code);
}
function tryVoucher() {
const input = document.getElementById('voucher-input').value.toUpperCase();
if (input.match(/^WIFI-[A-Z0-9]{4}$/)) {
alert('✅ Voucher valide! Connexion en cours...');
} else {
alert('❌ Code invalide. Format: WIFI-XXXX');
}
}
// Simulate active sessions count
setInterval(() => {
const sessions = 20 + Math.floor(Math.random() * 10);
document.getElementById('stat-sessions').textContent = sessions;
}, 5000);
</script>
<!-- Multi-language System -->
<script src="/i18n.js"></script>
</body>
</html>