// models.rs — Modèles de données partagés (server + client) // // Ce module définit les structs qui représentent les entités métier du projet IPAM. // Ils sont compilés côté serveur ET côté WASM car Leptos en a besoin des deux côtés : // - Serveur : pour lire/écrire en BDD et rendre le HTML // - Client : pour afficher les données dans les composants Leptos // // Chaque struct dérive `Serialize` et `Deserialize` de serde. // C'est obligatoire pour que Leptos puisse transférer les données entre // le serveur et le navigateur via les "server functions" (#[server]). use serde::{Deserialize, Serialize}; // ─── Réseau ─────────────────────────────────────────────────────────────────── /// Un réseau IP défini par sa plage CIDR. /// /// Exemple : { id: 1, cidr: "192.168.1.0/24" } /// → plage de 192.168.1.0 à 192.168.1.255 (254 hôtes utilisables) /// /// La notation CIDR (Classless Inter-Domain Routing) combine l'adresse réseau /// et le masque en un seul champ : /. /// /24 = 24 bits de masque = 255.255.255.0 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Network { /// Identifiant unique auto-incrémenté par la base de données. /// `i64` est le type entier signé 64 bits — correspond à `BIGINT` en SQL. pub id: i64, /// Plage d'adresses en notation CIDR. /// Ex: "10.0.0.0/8", "172.16.0.0/12", "192.168.1.0/24" pub cidr: String, } // ─── Hôte ───────────────────────────────────────────────────────────────────── /// Un hôte (machine, serveur, équipement réseau) appartenant à un réseau. /// /// Contrainte : l'IP doit appartenir à la plage CIDR du réseau référencé /// par `network_id`. Cette contrainte est vérifiée à la création/modification. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Host { pub id: i64, /// Nom descriptif de l'hôte. Ex: "serveur-web-01", "routeur-principal" pub name: String, /// Adresse IPv4 de l'hôte, stockée en texte. /// Ex: "192.168.1.10" /// On utilise String plutôt que IpAddr pour simplifier la sérialisation /// et le stockage en base de données. pub ip: String, /// Référence vers le réseau auquel appartient cet hôte. /// C'est une "clé étrangère" (Foreign Key) vers la table `networks`. pub network_id: i64, } // ─── Port ───────────────────────────────────────────────────────────────────── /// Un port réseau ouvert sur un hôte, avec sa description probable. /// /// Les numéros de ports standards (0–1023) sont des "well-known ports". /// Un port peut être associé à plusieurs applications (association non-stricte). #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Port { /// Numéro de port TCP/UDP. /// `u16` : entier non signé 16 bits → plage 0 à 65535. /// C'est exactement la plage valide pour les ports réseau. pub number: u16, /// Description du protocole probable sur ce port. /// `Option` : peut être absent (None) si le protocole est inconnu. /// Ex: Some("SSH"), Some("HTTPS"), None pub description: Option, /// Hôte sur lequel ce port est ouvert. pub host_id: i64, } impl Port { /// Retourne la description standard pour les ports les plus courants. /// Utilisé pour pré-remplir la description lors de l'ajout d'un port. /// /// `match` est l'équivalent Rust d'un switch/case, mais exhaustif : /// le compilateur oblige à gérer tous les cas possibles. pub fn protocole_connu(numero: u16) -> Option<&'static str> { // `&'static str` : référence vers une chaîne qui vit toute la durée du programme // (les littéraux de chaînes comme "SSH" sont stockés dans le binaire compilé) match numero { 21 => Some("FTP"), 22 => Some("SSH"), 23 => Some("Telnet"), 25 => Some("SMTP"), 53 => Some("DNS"), 80 => Some("HTTP"), 110 => Some("POP3"), 143 => Some("IMAP"), 443 => Some("HTTPS"), 3306 => Some("MySQL"), 5432 => Some("PostgreSQL"), 6379 => Some("Redis"), 8080 => Some("HTTP alternatif"), _ => None, // `_` est le pattern "tout le reste" (wildcard) } } } // ─── Application ────────────────────────────────────────────────────────────── /// Une application qui utilise un ou plusieurs ports. /// /// L'association entre application et port est non-stricte : /// un même port peut être partagé par plusieurs applications. /// Ex: le port 80 peut être utilisé par Nginx ET par un proxy applicatif. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Application { pub id: i64, /// Nom de l'application. Ex: "Nginx", "PostgreSQL", "Prometheus" pub name: String, } // ─── Association Application ↔ Port ────────────────────────────────────────── /// Lien entre une application et un port (relation many-to-many). /// /// On utilise un struct dédié plutôt qu'un Vec dans Application /// pour correspondre directement à la table de jointure en base de données. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ApplicationPort { pub application_id: i64, pub port_number: u16, }