|
|
@@ -0,0 +1,67 @@
|
|
|
+# 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 recoive 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.
|