-- On créer la base de donnée si elle n'existe déjà aps CREATE DATABASE IF NOT EXISTS portfolio -- On créer un utilisateur avec un mot de passe fort qui est à changer après execution dus script (voir bitwarden) CREATE USER 'srv_portfolio'@'%' IDENTIFIED BY 'mdp'; -- On met les droits au compte sur la base portfolio à l'utilisateur GRANT ALL ON portfolio.* TO 'srv_portfolio'@'%'; -- On actualise les permissions FLUSH PRIVILEGES; -- Création de la table user : (Généré par Beekeeper Studio : équivalent à dbGate) CREATE TABLE IF NOT EXISTS users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL, password VARCHAR(255) NOT NULL, role ENUM('admin', 'user') NOT NULL DEFAULT 'user', created_at DATETIME NULL DEFAULT NULL, last_login DATETIME NULL DEFAULT NULL, PRIMARY KEY (id), UNIQUE INDEX idx_username (username) ); -- Création de la table projects : (Généré par Beekeeper Studio) CREATE TABLE IF NOT EXISTS projects ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, title VARCHAR(100) NOT NULL, tags VARCHAR(255) NULL, description TEXT NOT NULL, image_url VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ); -- Création de la table projects : (Généré par Beekeeper Studio) CREATE TABLE IF NOT EXISTS experiences ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, title VARCHAR(100) NOT NULL, xptype VARCHAR(100) NOT NULL, tags VARCHAR(255) NULL, description TEXT NOT NULL, duration VARCHAR(100) NOT NULL, image_url VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ); -- Compte de test (PLUS A JOUR METTRE UN HASH) -- INSERT INTO users (username, password, role) -- VALUES ('admin', 'admin', 'admin'); insert into `users` (`created_at`, `id`, `last_login`, `password`, `role`, `username`) values ('2026-06-08 11:10:21', 11, '2026-06-08 13:10:41', '$2y$12$x01fDqrHQEYIyj7MDHa72eRyl2j/n5cNq9sv3.FIiQCaRsB50Q4iK', 'admin', 'admin'); -- Ajout d'une collonne status pour les projets et les expériences pour pouvoir différencier les projets/expériences en cours, terminés ou à venir ALTER TABLE projects ADD COLUMN status VARCHAR(100) NULL AFTER title; ALTER TABLE experiences ADD COLUMN status VARCHAR(100) NULL AFTER title; -- Table de réglages du site (clé / valeur) : utilisée pour la notification de la page d'accueil CREATE TABLE IF NOT EXISTS settings ( name VARCHAR(50) NOT NULL, value TEXT NULL, PRIMARY KEY (name) ); -- Valeurs par défaut de la notification (modifiables ensuite depuis le panel Admin) INSERT INTO settings (name, value) VALUES ('site_notice_title', 'Des bugs peuvent encore se produire.'), ('site_notice_text', 'Si le CSS ou les images s''affichent mal, pensez à vider le cache de votre navigateur (Ctrl + F5 ou Cmd + Shift + R) pour voir les dernières modifications.'), ('site_notice_enabled', '1') ON DUPLICATE KEY UPDATE value = VALUES(value); -- Table des compétences : une ligne = une catégorie (carte sur la page Compétences) -- items : un item par ligne, au format "classes-icone-fontawesome|Texte" (l'icône est optionnelle : "Texte" seul fonctionne aussi) CREATE TABLE IF NOT EXISTS skills ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, title VARCHAR(100) NOT NULL, icon VARCHAR(100) NULL, items TEXT NOT NULL, position INT NOT NULL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ); -- Compétences actuelles (reprises du CV) INSERT INTO skills (title, icon, items, position) VALUES ('Systèmes d''exploitation', 'fa-solid fa-computer', 'fa-brands fa-microsoft|Windows (Serveur/XP/8/10/11)\nfa-brands fa-linux|Linux (Debian/Ubuntu)\nfa-brands fa-apple|macOS', 1), ('Réseaux', 'fa-solid fa-network-wired', 'fa-solid fa-location-dot|Adressage IP\nfa-solid fa-diagram-project|VLAN\nfa-solid fa-shield-halved|Pare-feu (iptables/ufw)\nfa-solid fa-globe|DNS (Bind9)\nfa-solid fa-server|DHCP (ISC DHCP)\nfa-solid fa-arrows-left-right|Proxy (Squid)', 2), ('Scripting', 'fa-solid fa-terminal', 'fa-solid fa-terminal|Bash\nfa-brands fa-python|Python\nfa-brands fa-java|Java\nfa-solid fa-gears|Ansible', 3), ('Applications', 'fa-solid fa-cubes', 'fa-solid fa-address-book|LDAP (Windows AD)\nfa-solid fa-headset|GLPI\nfa-solid fa-compact-disc|FOG\nfa-solid fa-server|Nginx / Apache\nfa-brands fa-docker|Docker\nfa-solid fa-display|Guacamole\nfa-solid fa-database|MySQL / MariaDB', 4), ('Développement web', 'fa-solid fa-code', 'fa-brands fa-html5|HTML\nfa-brands fa-css3-alt|CSS\nfa-brands fa-js|JavaScript\nfa-brands fa-php|PHP', 5), ('Virtualisation & Outils', 'fa-solid fa-layer-group', 'fa-solid fa-server|Proxmox\nfa-solid fa-box|VirtualBox\nfa-brands fa-git-alt|Git (GitHub, Gitea)', 6); -- Table des écoles / formations : affichée sous les expériences professionnelles sur la page Expériences CREATE TABLE IF NOT EXISTS schools ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, title VARCHAR(100) NOT NULL, status VARCHAR(100) NULL, tags VARCHAR(255) NULL, description TEXT NOT NULL, duration VARCHAR(100) NOT NULL, image_url VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ); -- markdown : contenu de la page détaillée (LONGTEXT = ~4 Go, taille pratiquement illimitée) -- link_url : lien externe utilisé à la place du markdown si celui-ci est vide -- Les deux sont facultatifs : si les deux sont vides, la carte n'est pas cliquable ALTER TABLE projects ADD COLUMN markdown LONGTEXT NULL, ADD COLUMN link_url VARCHAR(255) NULL; ALTER TABLE experiences ADD COLUMN markdown LONGTEXT NULL, ADD COLUMN link_url VARCHAR(255) NULL; ALTER TABLE schools ADD COLUMN markdown LONGTEXT NULL, ADD COLUMN link_url VARCHAR(255) NULL; -- ============================================================ -- Juillet 2026 (4) : bandeaux de logos sur la page d'accueil -- ("Outils que je sais manipuler" et "Ils m'ont fait confiance"), -- gérés depuis le panel Admin -- ============================================================ -- Une seule table pour les deux bandeaux, distingués par la colonne category : -- - 'tool' => bandeau "Outils que je sais manipuler" -- - 'partner' => bandeau "Ils m'ont fait confiance" -- link_url est facultatif : si renseigné, le logo devient cliquable (nouvel onglet) CREATE TABLE IF NOT EXISTS logo_banners ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, category ENUM('tool', 'partner') NOT NULL, name VARCHAR(100) NOT NULL, logo_url VARCHAR(255) NOT NULL, link_url VARCHAR(255) NULL, position INT NOT NULL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ); -- Table créée vide volontairement : les logos sont ajoutés depuis le panel Admin -- (section Logos) pour éviter d'afficher des images devinées/potentiellement cassées -- ============================================================ -- Juillet 2026 (3) : PDF en drag & drop pour les projets, -- expériences et écoles, lu depuis un mini lecteur intégré -- ============================================================ -- pdf_data : contenu binaire du PDF (LONGBLOB = ~4 Go, largement suffisant) -- pdf_filename : nom original du fichier (affiché dans le panel admin et le lecteur) -- Priorité d'affichage sur la page de détails : markdown > pdf > lien externe ALTER TABLE projects ADD COLUMN pdf_data LONGBLOB NULL, ADD COLUMN pdf_filename VARCHAR(255) NULL; ALTER TABLE experiences ADD COLUMN pdf_data LONGBLOB NULL, ADD COLUMN pdf_filename VARCHAR(255) NULL; ALTER TABLE schools ADD COLUMN pdf_data LONGBLOB NULL, ADD COLUMN pdf_filename VARCHAR(255) NULL; -- ============================================================ -- Juillet 2026 (5) : icône Devicon en alternative à l'image pour -- le bandeau de logos (surtout utile pour "Outils que je sais -- manipuler" : Devicon est un équivalent gratuit de Font Awesome -- dédié aux logos d'outils/langages/frameworks, cf. devicon.dev) -- ============================================================ -- icon : classes CSS Devicon (ex: "devicon-docker-plain colored"), prioritaire sur logo_url -- si les deux sont renseignés. logo_url devient facultatif : il faut au moins l'un des deux -- (validé côté PHP), pour les outils absents de Devicon (Proxmox, GLPI, FOG...) ALTER TABLE logo_banners ADD COLUMN icon VARCHAR(100) NULL AFTER name, MODIFY COLUMN logo_url VARCHAR(255) NULL; -- ============================================================ -- Juillet 2026 (6) : sortie des PDF des tables projects/experiences/schools -- vers des tables associées dédiées, pour que les pages qui LISTENT ces -- éléments (admin.php, xp.php, projects.php...) n'aient plus à charger les -- PDF (jusqu'à 15 Mo chacun) en mémoire à chaque affichage. C'était la -- cause du ralentissement d'admin.php et de xp.php : ces pages faisaient -- un SELECT * qui remontait aussi tout le contenu binaire des PDF alors -- que seul le nom de fichier est utilisé dans les listes. -- -- ÉTAPE 1/2 (non destructive) : crée les nouvelles tables et copie les PDF -- existants dedans. Les colonnes pdf_data / pdf_filename des tables -- d'origine ne sont PAS touchées à cette étape : aucune perte de donnée -- possible, elles restent en place comme copie de sécurité. -- ============================================================ CREATE TABLE IF NOT EXISTS project_pdfs ( project_id INT UNSIGNED NOT NULL, pdf_filename VARCHAR(255) NOT NULL, pdf_data LONGBLOB NOT NULL, PRIMARY KEY (project_id), CONSTRAINT fk_project_pdfs_project FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS experience_pdfs ( experience_id INT UNSIGNED NOT NULL, pdf_filename VARCHAR(255) NOT NULL, pdf_data LONGBLOB NOT NULL, PRIMARY KEY (experience_id), CONSTRAINT fk_experience_pdfs_experience FOREIGN KEY (experience_id) REFERENCES experiences(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS school_pdfs ( school_id INT UNSIGNED NOT NULL, pdf_filename VARCHAR(255) NOT NULL, pdf_data LONGBLOB NOT NULL, PRIMARY KEY (school_id), CONSTRAINT fk_school_pdfs_school FOREIGN KEY (school_id) REFERENCES schools(id) ON DELETE CASCADE ); -- Copie des PDF déjà en base vers les nouvelles tables (ne copie que les lignes qui ont -- effectivement un PDF ; ré-exécutable sans doublon grâce à la clé primaire = id du parent) INSERT IGNORE INTO project_pdfs (project_id, pdf_filename, pdf_data) SELECT id, pdf_filename, pdf_data FROM projects WHERE pdf_data IS NOT NULL; INSERT IGNORE INTO experience_pdfs (experience_id, pdf_filename, pdf_data) SELECT id, pdf_filename, pdf_data FROM experiences WHERE pdf_data IS NOT NULL; INSERT IGNORE INTO school_pdfs (school_id, pdf_filename, pdf_data) SELECT id, pdf_filename, pdf_data FROM schools WHERE pdf_data IS NOT NULL; -- ============================================================ -- ÉTAPE 2/2 (destructive, À NE PAS EXÉCUTER MAINTENANT) : à lancer plus -- tard, une fois que le site a été vérifié (listes, modification, suppression, -- lecteur PDF) et qu'on est sûr à 100% que tout fonctionne avec les -- nouvelles tables. Supprime les anciennes colonnes devenues inutiles. -- ============================================================ -- ALTER TABLE projects DROP COLUMN pdf_data, DROP COLUMN pdf_filename; -- ALTER TABLE experiences DROP COLUMN pdf_data, DROP COLUMN pdf_filename; -- ALTER TABLE schools DROP COLUMN pdf_data, DROP COLUMN pdf_filename;