# Mercure

On utilise mercure pour envoyer des updates en temps réel depuis le back vers les postes clients.

Voir :

* <https://mercure.rocks/docs>
* <https://symfony.com/doc/5.4/mercure.html>

## Fonctionnement général

Un hub mercure écoute à une url donnée (en local : <https://local.mercure.opentalent.fr>).

Ap2i utilise le bundle mercure pour symfony pour publier des updates à destination d'un ou plusieurs utilisateurs :

Exemple : 

    $update = new Update(
        "access/{$access->getId()}",
        json_encode(['myData' => 'some new data'], JSON_THROW_ON_ERROR),
        true
    );
    $this->mercureHub->publish($update);

Le client web, lui s'est abonné aux mises à jour

    const url = new URL($config.baseUrl_mercure)
    url.searchParams.append('topic', "access/" + store.state.profile.access.id)

    eventSource.value = new EventSourcePolyfill(url.toString(), { withCredentials: true });
    
    eventSource.value.onerror = event => {
        console.error('Error while subscribing to the EventSource : ' + JSON.stringify(event))
    }
    eventSource.value.onopen = event => {
        console.log('Listening for events...')
    }
    eventSource.value.onmessage = event => {
        const data = JSON.parse(event.data)
        console.log('we received an update with data : ' + JSON.stringify(data)) 
    }


## Sécurité

Pour sécuriser les échanges et s'assurer que seul l'utilisateur voulu reçoive l'update, on utilise le [système d'autorisations
prévu par mercure](https://symfony.com/doc/5.4/mercure.html#authorization).

Les updates publiées par ap2i sont marquées comme `private`, via le 3e argument passé au constructeur de l'update :

    $update = new Update($topics, $data, true);

À partir de là, seuls les abonnés en mesure de fournir un JWT valide pourront recevoir les updates.

On construit ce JWT côté back au moment du login, et on le stocke dans un cookie `mercureAuthorization` renvoyé au
client. Le contenu de ce JWT spécifie que le client ne peut s'abonner qu'aux sujets suivants :

* `access/{id}`

Ce JWT est crypté avec l'algo HS256 au moyen d'une clé secrète.

> Pour tester la construction des JWT : <https://jwt.io/>

On ajoute aussi la configuration `{ withCredentials: true }` au EventSource côté client, pour lui indiquer de transmettre
les cookies au hub Mercure.

Enfin, le hub mercure est configuré de manière à interdire les updates anonymes.
