# Proximistore — Store de plugins Proximiweb pour GLPI

Plugin GLPI qui affiche un **catalogue de plugins** (servi par un serveur Proximiweb
sous forme de manifeste JSON) et permet de **télécharger puis extraire** un plugin
directement dans le dossier `plugins/` de GLPI.

> L'installation finale (install + activation) reste manuelle, via l'interface
> **Configuration → Plugins** de GLPI. Le plugin téléchargé n'est jamais activé
> automatiquement.

Compatible **GLPI 10.0.x** et **GLPI 11.x**.

---

## Prérequis

| Prérequis | Détail |
|-----------|--------|
| **GLPI** | ≥ 10.0.0 et < 12.0.0 |
| **PHP – extension cURL** | requise (récupération du catalogue + téléchargement) |
| **PHP – extension Zip** (`ZipArchive`) | requise (extraction des archives) |
| **Dossier `plugins/` inscriptible** | ⚠️ **indispensable pour télécharger des plugins** (voir ci-dessous) |
| **Accès réseau sortant** | le serveur GLPI doit pouvoir joindre l'URL du catalogue et les URL de téléchargement |

### ⚠️ Point crucial : droits d'écriture sur `plugins/`

Le bouton **Installer / Mettre à jour** ne peut fonctionner que si le dossier
`plugins/` de GLPI — **et les éventuels sous-dossiers de plugins déjà présents** —
sont **accessibles en écriture par l'utilisateur du serveur web** (souvent
`www-data`, `apache`, `nginx`…).

Exemple de mise en conformité (adapter l'utilisateur) :

```bash
chown -R www-data:www-data /chemin/vers/glpi/plugins
```

Si un plugin a été installé manuellement en `root`, son sous-dossier appartiendra à
`root` et l'extraction échouera (« Échec de l'extraction dans plugins/. »). Cette
contrainte est la même que pour la marketplace native de GLPI.

---

## Installation

1. Récupérer l'archive du plugin et l'extraire dans le dossier `plugins/` de GLPI.
   **Le dossier doit s'appeler exactement `proximistore`** (tout en minuscules).

   ```
   glpi/plugins/proximistore/
   ```

   > ⚠️ GLPI est sensible à la casse : un dossier `Proximistore` ou `storeGLPI`
   > ne sera **pas** reconnu (la clé du plugin doit correspondre au nom du dossier).

2. Dans GLPI : **Configuration → Plugins** → *Proximistore* → **Installer** puis **Activer**.

3. L'entrée **Proximistore** apparaît dans le menu **Administration**.

L'accès au store nécessite le droit standard **`config`** (READ pour consulter,
UPDATE pour télécharger). Aucun droit dédié n'est créé.

---

## Configuration

L'URL du catalogue est définie **en dur** dans `setup.php` :

```php
define('PLUGIN_PROXIMISTORE_CATALOG_URL', 'https://storeglpi.proximiweb.fr/catalog.json');
```


## Notes de compatibilité GLPI 10 / 11

Ce plugin gère les différences entre les deux versions majeures :

- **Assets statiques (JS/CSS)** : présents à la fois à la racine (`js/`, `css/`
  — servis par GLPI 10) **et** dans `public/` (`public/js/`, `public/css/`
  — servis par GLPI 11). En cas de modification d'un asset, **penser à mettre à
  jour les deux copies**.
- **CSRF des requêtes AJAX (GLPI 11)** : le jeton est envoyé dans l'en-tête
  `X-Glpi-Csrf-Token` (lu par le `CheckCsrfListener` du kernel), avec l'en-tête
  `X-Requested-With: XMLHttpRequest`. Le jeton est aussi placé dans le corps
  (`_glpi_csrf_token`) pour la rétrocompatibilité GLPI 10.
- **User-Agent** : les requêtes cURL envoient un User-Agent explicite pour éviter
  les blocages `429`/`403` de certains hébergeurs (anti-bot / anti-flood).

---

## Dépannage

| Symptôme | Cause probable | Solution |
|----------|----------------|----------|
| Store vide, bloqué sur « Chargement… » | JS non servi (GLPI 11) | vérifier la présence de `public/js/proximistore.js` |
| « Impossible de charger le catalogue » | `catalog.json` injoignable / non‑JSON | vérifier l'URL (HTTP 200 + `application/json`) |
| Plugin non reconnu / « Erreur à nettoyer » | dossier mal nommé (majuscule) | renommer le dossier en `proximistore` |
| « Accès refusé » au clic Installer | jeton CSRF (GLPI 11) | s'assurer que le JS est bien déployé (envoi du header `X-Glpi-Csrf-Token`) |
| « Réponse HTTP inattendue (429) » | anti-bot du serveur de téléchargement | vérifier le rate-limit / User-Agent côté hébergeur du store |
| « Échec de l'extraction dans plugins/. » | droits Unix | `chown` de `plugins/` (et du sous-dossier cible) vers l'utilisateur web |
| « Le dossier plugins/ … n'est pas inscriptible » | `plugins/` non inscriptible | corriger les droits du dossier `plugins/` |

En **préproduction** avec OPcache figé (`opcache.validate_timestamps=0`), penser à
vider l'OPcache (ou recharger PHP-FPM) après chaque déploiement.

---

## Sécurité

- Téléchargement borné en taille (50 Mo) et en temps.
- Extraction protégée contre le **Zip-Slip** : toutes les entrées de l'archive
  doivent vivre sous le dossier `key/`, sans chemin absolu ni `..`.
- Protocoles limités à HTTP/HTTPS (y compris sur redirections).
- Droit `config` (UPDATE) requis pour tout téléchargement.

---

## Licence

GPLv2+
