add connexions

This commit is contained in:
2026-06-11 22:39:45 +02:00
parent bf36210670
commit 3d3c4cdde5
8 changed files with 189 additions and 16 deletions
+1
View File
@@ -46,6 +46,7 @@ export default function Dashboard() {
window.open(serviceData.server.login_url, '_blank');
}
else if (serviceData && serviceData.server) {
console.log(serviceData);
// L'URL d'action du formulaire de connexion HestiaCP
const hestiaLoginUrl = "https://panel.gise.be/login/";
const username = serviceData.username;
+10 -5
View File
@@ -1,3 +1,5 @@
import { Link } from 'react-router-dom';
export default function Home() {
return (
<div style={{ textAlign: 'center', marginTop: '10vh' }}>
@@ -22,21 +24,24 @@ export default function Home() {
<br />Propulsé par une architecture bare-metal locale.
</p>
{/* Un petit bouton d'action pour la suite */}
{/* LE BOUTON D'ACTION PRINCIPAL REDIRIGE VERS /REGISTER */}
<div style={{ marginTop: '40px' }}>
<button style={{
<Link to="/register" style={{
display: 'inline-block',
backgroundColor: 'transparent',
color: '#00E5FF',
border: '1px solid #00E5FF',
padding: '12px 24px',
fontSize: '1rem',
fontFamily: 'monospace',
cursor: 'pointer',
textDecoration: 'none',
textTransform: 'uppercase',
letterSpacing: '1px'
letterSpacing: '1px',
fontWeight: 'bold',
transition: 'all 0.3s ease'
}}>
Démarrer le déploiement
</button>
</Link>
</div>
</div>
);
+122
View File
@@ -0,0 +1,122 @@
// src/pages/public/Register.jsx
import { useState } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import { registerUnifiedClient } from '../../services/api';
export default function Register() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleRegister = async (e) => {
e.preventDefault();
setError(null);
// Sécurité Frontend : Validation des mots de passe avant envoi au serveur
if (password !== confirmPassword) {
setError("Les clés d'accès (mots de passe) ne correspondent pas.");
return;
}
// Sécurité Frontend : Regex simple pour valider le format exigé par HestiaCP
const validUsername = /^[a-zA-Z0-9]{3,12}$/.test(username);
if (!validUsername) {
setError("Le nom d'utilisateur doit contenir uniquement des lettres ou chiffres (entre 3 et 12 caractères, sans espace).");
return;
}
setLoading(true);
try {
// Envoi de la requête groupée à notre orchestrateur PHP backend
await registerUnifiedClient(email, username, password, firstName, lastName);
alert("[ PROVISIONNEMENT RÉUSSI ]\nVos comptes FOSSBilling, HestiaCP et Nextcloud ont été initialisés.\nVous pouvez maintenant vous connecter.");
// Redirection automatique vers la page de login après succès
navigate('/login');
} catch (err) {
setError(err.message || "Échec de l'initialisation de l'infrastructure.");
} finally {
setLoading(false);
}
};
// Réutilisation de ton Design System "Bunker"
const inputStyle = {
width: '100%', padding: '10px', marginBottom: '15px',
backgroundColor: '#1A1A1A', color: '#00E5FF',
border: '1px solid #333', fontFamily: 'monospace', outline: 'none',
boxSizing: 'border-box'
};
const buttonStyle = {
width: '100%', padding: '12px', backgroundColor: loading ? '#333' : '#00E5FF',
color: loading ? '#888' : '#000', border: 'none', cursor: loading ? 'not-allowed' : 'pointer',
fontFamily: 'monospace', fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: '1px',
marginTop: '10px'
};
return (
<div style={{ display: 'flex', justifyContent: 'center', marginTop: '5vh', padding: '0 20px' }}>
<div style={{
width: '100%', maxWidth: '500px', backgroundColor: '#242424',
padding: '30px', borderTop: '4px solid #00E5FF', boxShadow: '0 10px 30px rgba(0,0,0,0.5)'
}}>
<h2 style={{ color: '#FFF', textTransform: 'uppercase', marginBottom: '5px', fontSize: '1.5rem' }}>
Créer un accès réseau
</h2>
<p style={{ color: '#888', fontFamily: 'monospace', fontSize: '0.85rem', marginBottom: '25px' }}>
[ INITIALISATION DU PROVISIONNEMENT TRIPLE EN CASCADE ]
</p>
{error && (
<div style={{ backgroundColor: 'rgba(255, 68, 68, 0.1)', color: '#FF4444', padding: '10px', marginBottom: '20px', border: '1px solid #FF4444', fontSize: '0.9rem', fontFamily: 'monospace' }}>
[ ERREUR ] : {error}
</div>
)}
<form onSubmit={handleRegister}>
<div style={{ display: 'flex', gap: '15px' }}>
<div style={{ flex: 1 }}>
<label style={{ display: 'block', color: '#888', marginBottom: '5px', fontSize: '0.8rem' }}>PRÉNOM</label>
<input type="text" value={firstName} onChange={(e) => setFirstName(e.target.value)} style={inputStyle} required placeholder="John" />
</div>
<div style={{ flex: 1 }}>
<label style={{ display: 'block', color: '#888', marginBottom: '5px', fontSize: '0.8rem' }}>NOM</label>
<input type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} style={inputStyle} required placeholder="Doe" />
</div>
</div>
<label style={{ display: 'block', color: '#888', marginBottom: '5px', fontSize: '0.8rem' }}>ADRESSE E-MAIL (IDENTIFIANT FACTURATION)</label>
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} style={inputStyle} required placeholder="john.doe@gise.be" />
<label style={{ display: 'block', color: '#888', marginBottom: '5px', fontSize: '0.8rem' }}>NOM D'UTILISATEUR SÉCURISÉ (ACCÈS HESTIA & CLOUD)</label>
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} style={inputStyle} required placeholder="ex: jdoe42" />
<label style={{ display: 'block', color: '#888', marginBottom: '5px', fontSize: '0.8rem' }}>CLÉ D'ACCÈS (MOT DE PASSE UNIQUE)</label>
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} style={inputStyle} required placeholder="••••••••" />
<label style={{ display: 'block', color: '#888', marginBottom: '5px', fontSize: '0.8rem' }}>CONFIRMER LA CLÉ D'ACCÈS</label>
<input type="password" value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} style={inputStyle} required placeholder="••••••••" />
<button type="submit" style={buttonStyle} disabled={loading}>
{loading ? 'DÉPLOIEMENT EN COURS...' : 'LANCER LE PROVISIONNEMENT'}
</button>
</form>
<div style={{ marginTop: '20px', textAlign: 'center', fontSize: '0.85rem' }}>
<Link to="/login" style={{ color: '#888', textDecoration: 'none' }}>
Déjà enregistré ? <span style={{ color: '#00E5FF' }}>Se connecter au terminal &gt;</span>
</Link>
</div>
</div>
</div>
);
}