Aller au contenu

Blog ·

Un raccourci est une référence, pas un droit

Six cartes à ajouter au tableau de bord et des raccourcis qui ne s’affichent que si le lecteur a encore le droit de voir la cible aujourd’hui.

Par Provibr

Le tableau de bord d’un panneau d’hébergement est l’écran que tout le monde voit en premier et sur lequel presque personne n’a d’avis tant qu’il n’est pas mal réglé pour lui. La demande était modeste : laisser les gens ajouter des cartes, et leur laisser poser des raccourcis vers un serveur ou une intégration sur lesquels ils reviennent sans cesse.

Les demandes modestes sont l’endroit où se cachent les décisions intéressantes, car un raccourci est une préférence enregistrée qui pointe vers un objet réel doté de droits réels. Fausser ce rapport, c’est ainsi qu’un panneau finit par montrer à quelqu’un une machine dont on l’a retiré il y a trois mois.

Six cartes, aucune migration, et rien n’arrive sans demande

Il y a six cartes ajoutables : une liste d’agents, une liste de serveurs, une liste d’intégrations, une liste de tickets, le crédit, et un raccourci. Toutes les six font une demi-largeur, car ce sont des aperçus posés côte à côte et non quelque chose qui réclame la ligne entière.

La disposition est enregistrée en JSON, et cette manche n’a pas ajouté de migration. C’est une décision et non un oubli. Une entrée était un identifiant et un indicateur de masquage ; elle porte désormais aussi un identifiant d’instance et une configuration par carte. Une ancienne ligne se relit proprement dans la nouvelle forme, avec l’identifiant d’instance complété depuis celui de la carte et la configuration vide, et un test vérifie exactement cela : une ancienne disposition se relit comme les mêmes cartes dans le même ordre. Ici, une migration ne ferait que poser un horodatage dans le journal, et un horodatage qui se révèle ensuite trop élevé est un vrai problème pour la manche suivante.

La seconde règle est qu’une carte facultative n’apparaît jamais toute seule. Il existe une boucle qui ajoute les cartes qu’une disposition ne nomme pas, afin qu’une nouvelle carte fixe apparaisse chez tout le monde, et cette boucle ne couvre volontairement que les cartes fixes. Si une carte facultative en faisait partie, « ajouter » ne serait plus une action et tous les tableaux de bord du produit grossiraient à chaque publication d’une carte que personne n’a demandée.

Les cartes absentes sont autant une décision que celles qui sont présentes. La supervision et les sauvegardes existent dans le code derrière des drapeaux de déploiement éteints, une carte pour elles serait donc une carte sans utilisateurs. L’activité récente est restée dehors parce qu’elle existe déjà comme carte fixe.

Deux moitiés d’une seule règle

Dans la disposition enregistrée d’une personne, un raccourci n’est rien de plus qu’une sorte et un identifiant. Tout ce qui arrive à l’écran, le nom, l’état, le lien, est récupéré à chaque chargement de page avec les droits de celui qui regarde à ce moment-là. Cette règle a deux moitiés et les deux sont nécessaires.

La première est le module. Un membre qui perd le module des agents ne voit plus son raccourci vers un agent, même s’il figure toujours dans sa disposition. Cette porte connaît aussi les surfaces : sur le domaine de marque propre d’un client, où la facturation n’existe pas du tout, le raccourci vers le crédit disparaît donc par construction et non par une seconde règle écrite exprès.

La seconde est la requête sur l’objet. L’identifiant d’organisation est dans chaque WHERE, le filtre de suppression douce à côté, et pour un serveur la portée de serveurs de ce membre à côté encore. Un serveur qui n’a jamais été attribué à un membre n’existe pas pour lui, et cela doit valoir aussi pour un raccourci qu’il a créé du temps où il avait le droit de le voir.

La carte de raccourci est aussi la seule carte sans module et la seule qui a le droit d’exister plusieurs fois. C’est juste et non négligent : un raccourci n’est pas un écran à lui, c’est une référence vers un écran qui porte déjà son propre droit. Donnez un module à la sorte de carte et un lecteur disposant de ce module pourrait voir un raccourci vers quelque chose qu’il n’a pas le droit d’ouvrir.

Module retiré et objet disparu sont deux événements différents

Deux choses qui se ressemblent à l’écran reçoivent des traitements opposés.

Ce qui s’est passéCe que voit le lecteur
Le module a été retiréLa carte disparaît sans un mot, et revient avec le module
La cible n’a pas été trouvéeUne carte qui dit qu’elle n’existe plus, avec un bouton pour la retirer

La première est silencieuse parce que le raccourci n’est pas l’histoire. Si le rôle de quelqu’un a changé, le raccourci manquant est un symptôme, et l’annoncer sur le tableau de bord serait du bruit par-dessus un changement qu’il connaît déjà. Il revient d’ailleurs intact dès que le module revient, ce qui n’est possible que parce que rien n’a été supprimé.

La seconde est bruyante parce que la personne n’a rien fait de mal et qu’on lui a retiré quelque chose. Ce n’est volontairement ni un 404 ni un message d’erreur : juste une carte qui nomme la situation et propose de se ranger elle-même.

Afficher avec indulgence, plutôt que nettoyer à la suppression

L’autre solution évidente est de retirer les raccourcis quand leur cible est supprimée. Nous ne l’avons pas fait, et le raisonnement mérite d’être noté parce que la décision inverse a bien été prise ailleurs dans la même base de code : quand un membre quitte un compte, sa disposition enregistrée est réellement oubliée, car cette ligne ne touche aucune cascade et resterait sinon pour toujours dans un compte où il ne revient jamais.

Ici la balance penche de l’autre côté, pour trois raisons.

Disparaître a plus de causes que supprimer. Un membre perd un module, sa portée de serveurs change, il regarde sur un domaine de marque. Aucune routine de nettoyage n’attrape ces trois cas, la voie indulgente doit donc exister de toute façon, et un second mécanisme n’est alors qu’un endroit de plus qui peut diverger.

La disposition est enregistrée par personne. Un serveur supprimé obligerait à réécrire le JSON de chaque membre de l’organisation, dans une transaction sur la voie de suppression. C’est de l’amplification d’écriture sur une voie chaude en échange d’une préférence d’écran.

Et il n’y a rien à protéger. La ligne enregistrée est un UUID d’un objet de sa propre organisation et rien d’autre. Elle ne fuit rien, elle ne grossit pas, et la personne voit tout de suite qu’elle peut partir.

L’essai de bout en bout est brutal à dessein. Après une suppression douce, le serveur ne revient pas, et son nom n’apparaît nulle part dans la sortie. Un membre sans le module des agents n’obtient ni agent ni intégration, et le sélecteur ne les propose pas. Une portée de serveurs vide donne zéro ligne et non tout.

Deux trouvailles que seul un essai réel a produites

Les deux vrais défauts de cette manche étaient invisibles pour les tests unitaires, et les deux ont coûté une dizaine de secondes dès que quelque chose de réel tournait.

Le sélecteur a un champ de recherche, et chercher des intégrations cassait le sélecteur entier avec une erreur de base. La raison est que la colonne du type d’intégration est un type énuméré de Postgres, et qu’il n’existe pas pour un énuméré d’opérateur de motif insensible à la casse : la requête a renvoyé 42883 operator does not exist, et comme cette requête alimentait tout le sélecteur, plus rien du tout ne s’affichait. Convertir la colonne en texte règle le problème. Aucun test unitaire avec un exécuteur simulé ne l’aurait vu, car une simulation n’a pas de types.

Le second est sorti du balayage d’accessibilité. Une tuile de raccourci est un nom, un état et une sorte, et l’ensemble est cliquable. La première version mettait tout cela dans un seul lien, et l’audit a signalé un écart entre le nom accessible et l’étiquette visible, car le texte masqué compte pour le nom accessible. La tuile est désormais un conteneur ordinaire avec un lien qui ne porte que le nom et une zone de clic absolue et vide qui récupère le clic. Cela a amené un second problème, plus petit : la classe de troncature posée sur le lien rognait cette zone à la largeur du texte, si bien que la plus grande partie de la tuile n’était plus cliquable. La troncature a déménagé sur un élément intérieur et la couverture a été mesurée au lieu d’être supposée.

Ce que nous noterions

  1. Enregistrez une référence, résolvez un droit. Dans la préférence, il faut un identifiant. Ce qui arrive à l’écran doit être récupéré à chaque fois avec les droits de celui qui regarde.
  2. Une colonne sans schéma est une migration que vous n’avez pas à écrire. Mais seulement si vous pouvez prouver que l’ancienne forme se relit à l’identique, et cela, c’est un test.
  3. Facultatif veut dire sur demande, définitivement. Une carte qui apparaît toute seule fait d’« ajouter » un mot sans contenu.
  4. Distinguez supprimé d’inatteignable. Ils se ressemblent à l’écran et méritent le traitement inverse : le silence pour l’un, une explication pour l’autre.
  5. Ne pas nettoyer peut être le choix le plus fort. Si le même symptôme a des causes que votre nettoyage ne voit pas, la voie indulgente doit exister de toute façon, et le nettoyage n’est plus qu’une seconde chose à tenir à jour.
  6. Faites tourner la chose. Un énuméré sans opérateur de motif et un lien qui rogne sa propre zone de clic se voient en un instant dans un navigateur, et ne se voient pas du tout dans une suite de tests sans base de données.

Pour être clair sur ce dont il s’agit : les cartes décrites ici sont en production pour tous les comptes. Plusieurs choses ne sont pas prouvées. Le réordonnancement à la souris n’a pas été piloté, les cartes de supervision et de sauvegarde derrière un drapeau n’existent pas et leur chemin de code n’a donc jamais été emprunté, le domaine de marque a été vérifié dans une requête et non dans un navigateur, et une carte fraîchement ajoutée n’apparaît qu’après la manche suivante du serveur.

Issu du travail de plateforme de Provibr. Ce qu’un client de notre client voit et ne voit pas sur un panneau de marque est expliqué dans marque blanche : ce que voit votre client, et pourquoi un écran de synthèse ne réécrit jamais dans les tables qu’il lit est expliqué dans projeter, jamais remplacer.

Commencez avec un hôte et un agent

Créez un compte, installez l’agent avec une seule commande et connectez votre premier hôte Proxmox. La période d’essai dure 14 jours et ne demande aucune coordonnée de paiement.