GlobalSearch est un outil open-source permettant d'exposer des tables MySQL/MariaDB sous forme d'interface de recherche unifiée, avec onglets, pagination, index FULLTEXT et restriction par service.
Conçu pour des usages internes (référentiels, annuaires, listes de codes postaux, catalogues…), il s'installe en quelques minutes sur un serveur web PHP ou via Docker.
- Modules de recherche configurables — chaque module pointe vers une table et définit les colonnes interrogeables et affichées
- Recherche FULLTEXT ou LIKE — bascule automatique selon la configuration
- Restriction par service — un module peut n'être visible que pour certains services
- Interface d'administration — création, édition, réorganisation des modules via une UI graphique
- Multi-authentification — SSO SAML, Active Directory / LDAP, comptes locaux, ou aucune auth
- Installation Docker ou serveur web PHP classique
Valeur AUTH_MODE |
Description |
|---|---|
sso |
SSO SAML via proxy token (ex. SimpleSAMLphp, ADFS) |
ad |
Active Directory / LDAP — formulaire login/mot de passe |
db |
Comptes locaux dans la table ah_users (bcrypt) |
none |
Aucune authentification — accès totalement libre |
- PHP ≥ 8.1 avec les extensions :
pdo,pdo_mysql,mbstring,ldap(si modead) - MySQL ≥ 8.0 ou MariaDB ≥ 10.6
- Apache ou Nginx
1. Cloner le dépôt
git clone https://github.com/chevinou/globalsearch.git
cd globalsearch2. Créer la base de données
CREATE DATABASE globalsearch CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'globalsearch'@'localhost' IDENTIFIED BY 'motdepasse';
GRANT ALL PRIVILEGES ON globalsearch.* TO 'globalsearch'@'localhost';
FLUSH PRIVILEGES;Importer le schéma :
mysql -u globalsearch -p globalsearch < globalsearch.sql3. Configurer l'application
cp config.example.php config.php
nano config.php # ou votre éditeur favoriParamètres essentiels à modifier :
define('DB_HOST', 'localhost');
define('DB_PASS', 'motdepasse'); // même mot de passe que ci-dessus
define('APP_URL', 'https://recherche.exemple.fr/');
define('AUTH_MODE', 'sso'); // 'sso' | 'ad' | 'db' | 'none'
define('INITIAL_ADMIN_EMAIL', 'vous@exemple.fr');4. Déployer les fichiers
Copiez le contenu du dépôt dans le répertoire web de votre serveur (ex. /var/www/html/globalsearch/) ou configurez un vhost pointant vers ce dossier.
5. Configuration Apache (vhost recommandé)
<VirtualHost *:443>
ServerName recherche.exemple.fr
DocumentRoot /var/www/html/globalsearch
<Directory /var/www/html/globalsearch>
AllowOverride All
Require all granted
</Directory>
SSLEngine on
SSLCertificateFile /etc/ssl/certs/exemple.crt
SSLCertificateKeyFile /etc/ssl/private/exemple.key
</VirtualHost>6. Configuration Nginx (alternative)
server {
listen 443 ssl;
server_name recherche.exemple.fr;
root /var/www/html/globalsearch;
index index.php;
ssl_certificate /etc/ssl/certs/exemple.crt;
ssl_certificate_key /etc/ssl/private/exemple.key;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\. { deny all; }
}- Docker ≥ 24 et Docker Compose v2
1. Cloner le dépôt
git clone https://github.com/chevinou/globalsearch.git
cd globalsearch2. Créer votre config
cp config.example.php config.php
nano config.phpDans config.php, indiquez :
define('DB_HOST', 'db'); // nom du service Docker
define('DB_PASS', 'changeme'); // identique à MARIADB_PASSWORD dans docker-compose.yml3. Ajuster les mots de passe dans docker-compose.yml
environment:
MARIADB_ROOT_PASSWORD: rootchangeme # ← choisissez un vrai mot de passe
MARIADB_PASSWORD: changeme # ← doit correspondre à DB_PASS4. Lancer
docker compose up -dL'application est accessible sur http://localhost:8080.
5. Arrêter / relancer
docker compose down # arrête sans supprimer les données
docker compose down -v # arrête ET supprime la base de données
docker compose up -d # relance en arrière-plangit pull
docker compose build --no-cache
docker compose up -dCompatible avec SimpleSAMLphp, ADFS, Azure AD, Keycloak et tout provider exposant une API d'échange de token.
define('AUTH_MODE', 'sso');
define('SSO_TOKEN_URL', 'https://sso.exemple.fr/saml/token_exchange.php');
define('SSO_LOGIN_URL', 'https://sso.exemple.fr/saml/index.php');
define('SSO_LOGOUT_URL', 'https://sso.exemple.fr/saml/logoutSSO.php');Le provider SSO doit rediriger vers APP_URL?sso_token=<hex64> après authentification. L'application échange ensuite le token contre les attributs utilisateur.
Adaptez SSO_ATTR_MAP si vos attributs SAML ont des noms différents.
define('AUTH_MODE', 'ad');
define('AD_HOST', 'ldap://dc.exemple.fr'); // ou ldaps:// pour TLS
define('AD_PORT', 389);
define('AD_BASE_DN', 'DC=exemple,DC=fr');
define('AD_BIND_DN', 'CN=svc-search,OU=Services,DC=exemple,DC=fr');
define('AD_BIND_PASS', 'motdepasse_service');
define('AD_FILTER', '(sAMAccountName=%s)'); // %s = login saisiL'extension PHP ldap doit être installée. Pour LDAPS, assurez-vous que le certificat du DC est approuvé par PHP.
define('AUTH_MODE', 'db');Ajoutez la colonne password à la table ah_users :
ALTER TABLE ah_users ADD COLUMN password VARCHAR(255) DEFAULT NULL AFTER prenom;Créez un compte manuellement :
// Génération du hash (à exécuter une fois en PHP CLI)
echo password_hash('votre_mot_de_passe', PASSWORD_BCRYPT);INSERT INTO ah_users (email, nom, prenom, password, role)
VALUES ('admin@exemple.fr', 'Dupont', 'Jean', '$2y$12$...', 'admin');define('AUTH_MODE', 'none');Tout le monde accède à l'application sans se connecter. Tous les utilisateurs sont considérés comme user (pas d'accès admin).
Quel que soit le mode d'auth (sauf none), le premier compte dont l'email correspond à INITIAL_ADMIN_EMAIL reçoit automatiquement le rôle admin lors de sa première connexion.
define('INITIAL_ADMIN_EMAIL', 'admin@exemple.fr');Les administrateurs supplémentaires peuvent être promus directement en base :
UPDATE ah_users SET role = 'admin' WHERE email = 'autre@exemple.fr';- Connectez-vous en tant qu'administrateur
- Cliquez sur ⚙ Administration dans la barre supérieure
- Cliquez sur + Nouveau module
- Remplissez :
- Nom — libellé de l'onglet
- Table — nom exact de la table MySQL à interroger
- Colonnes de recherche — colonnes interrogées par la clause WHERE
- Colonnes affichées — colonnes visibles dans les résultats, avec leur libellé
- FULLTEXT — à activer si la table dispose d'un index FULLTEXT (meilleures performances)
- Restriction service — laissez vide pour tout le monde, ou indiquez les services autorisés séparés par des virgules
La table list_cp est incluse dans le schéma fourni :
| Champ | Valeur |
|---|---|
| Nom | Codes postaux |
| Table | list_cp |
| Colonnes de recherche | Nom_de_la_commune, Code_postal |
| Colonnes affichées | Code_commune_INSEE → "INSEE", Nom_de_la_commune → "Commune", Code_postal → "Code postal" |
| FULLTEXT | ✓ (index déjà présent dans le schéma) |
globalsearch/
├── config.php # ← VOTRE configuration (ne pas committer)
├── config.example.php # Modèle de configuration
├── index.php # Application principale
├── admin.php # Interface d'administration
├── auth.php # Gestion de l'authentification (tous modes)
├── db.php # Connexion PDO singleton
├── logout.php # Déconnexion
├── globalsearch.sql # Schéma de base de données
├── Dockerfile # Image Docker PHP/Apache
├── docker-compose.yml # Stack complète (app + MariaDB)
├── api/
│ ├── search.php # Endpoint AJAX de recherche
│ └── admin.php # Endpoint AJAX d'administration
└── assets/
└── logo.png # Votre logo (référencé dans APP_LOGO)
config.phpest listé dans.gitignore— ne le commitez jamais- Les requêtes SQL utilisent des requêtes préparées PDO exclusivement
- Les noms de tables et colonnes sont validés par regex alphanumérique avant interpolation
- Les sessions utilisent les flags
httponlyetsamesite=Lax - En mode
ad, les mots de passe ne transitent jamais en clair dans la base
Ce projet est distribué sous licence GNU Affero General Public License v3.0 (AGPL-3.0).
Toute modification du code source mise en production (y compris en tant que service réseau) doit être rendue publique sous la même licence.
Voir https://www.gnu.org/licenses/agpl-3.0.html pour le texte complet.