Clear cache d'un utilisateur insuffisant pour recharger ses droits suite à mise à jour d'un profil

Bonjour,

On a constaté que SystemTool.resetCache(login, true, false) ne fonctionne plus comme avant. C’est à dire qu’on s’attend à avoir un clear cache pour cet utilisateur seulement mais actuellement il se fait déconnecter sans clear cache. On utilise cette méthode lorsqu’on change un groupe d’un profil pour forcer tout les utilisateurs ayant ce profil à prendre en compte les modifications immédiatement avec une déconnexion et clear cache.

Réponse François :

  1. SystemTool.resetCache(login, invalidate session = true, notify = false)
    Ce code n’a pas changé depuis la V4. Avec ces paramètres, ça fait juste au final 2 choses :
Grant.getSystemAdmin().clearCache(login);
Platform.invalidateSessions(login);

Essaye de le faire directement sans appeler la méthode.

Platform.invalidateSessions(login); ne fonctionne pas.

J’ai réussi à faire une déconnexion avec Platform.invalidateSession(tokenID) (sans le “s” à la fin et avec le tokenID plutot que le login utilisateur)
J’ai toujours le même résultat, je n’ai pas de clear cache serveur pour l’utilisateur.

voici le post ou j’arrivais à mes fin à l’époque : https://community.simplicite.io/t/modification-de-profile-prit-en-compte-quapres-clear-cache-serveur/4011/3?u=khalil

Désolé, je n’avais pas du regarder au bon endroit :

En 5.2 la méthode c’est
Platform.invalidateSessions(login, null, false);

Sinon si tu connais le JSESSIONID

c’est le JSESSIONID et non le user-token qu’il faut utiliser

Si vous utilisez un user-token persistant, c’est normal que la session tomcat se recrée automatiquement sans passer par l’écran de logon.

Sinon merci de préciser ce qui ne se vide pas dans la session utilisateur ?

Oui pardon c’était bien le sessionId que j’avais mis pour tester.
la déconnexion fonctionne avec Platform.invalidateSessions(login, null, false);

Mon problème est donc la je pense : Grant.getSystemAdmin().clearCache(login);

Ce qui ne se vide pas, c’est la nouvelle définition des groupes pour l’utilisateur.

si je fais un clear cache orange “Vider tous les caches du serveur (s)” et que l’utilisateur se déconnecte et reconnecte, ses groupes sont bien à jour.
Je veux donc utiliser SystemTool.resetCache(login, true, false); pour faire par code le clear cache serveur + déconnexion.

Je pense que ça a toujours fait ce que ça devait faire, à savoir vider les objets de sa session, ses caches côtés serveur, ses préférences d’usage en session… Cette méthode n’a pas été modifiée depuis bien longtemps.

On est alors dans un cas plus complexe que de simplement recharger les droits du User (ses responsabilités, préférence, user-filters…) avec un clear-cache. Il faut quelque part vider le cache des groupes si leurs définitions (indépendamment des user/responsabilités) ont changés.

Les groupes contiennent toutes les habilitations aux fonctionnalités, donc il faudrait être plus précis pour ne recharger que “la partie” qui est changée à la volée dans la définition.

Il y a un verbe qui recharge tous les groupes dans SystemTools.resetCacheGroups, mais c’est dangereux de faire ça à chaud (surtout pour le system ADMIN) :

public static void resetCacheGroups(Grant g) {
	// Reload groups and dependencies
	CoreCache cc = CoreCache.getInstance();
	cc.loadGroups();
	cc.loadDomains((String)null);
	cc.loadObjects((String)null);
	cc.loadProcess((String)null);
	cc.loadActions(null);
	cc.reloadShortcuts();
	cc.loadUserFilters();

	// User rights
	if (g!=null) {
		cc.loadDomains(g); // User domains
		cc.loadObjects(g); // User object
		cc.loadProcess(g); // User process
		cc.loadActionIntern(g); // CRUD
		cc.loadActionExtern(g); // User actions
		cc.loadObjectViews(g); // User views
		cc.loadSimpleViews(g);
		cc.loadShortcuts(g);
		cc.loadUserFilters(g);
	}
}

Il faut plutôt y aller chirurgicalement en accédant à la définition du groupe en mémoire :

GroupDB group = CoreCache.getInstance().getGroup(groupName)

et en modifiant que ce qui y a changé.

https://docs.simplicite.io/5/javadoc/com/simplicite/util/GroupDB.html

comme getProfile qui liste les groupes du groupe.

getProfile()

addProfile, removeProfile… pour ajouter un groupe ou le retirer à ce profil (étant lui même un groupe).

Je vais pas être bloqué dans le cas ou j’ai plusieurs nœuds et que mon code s’exécute pas forcement sur le même serveur que l’utilisateur connecté ?

Je confirme j’ai ajouté ce bout de code et ça fonctionne très bien qu’à condition que l’utilisateur soit connecté sur le même serveur que celui qui lance le code.

code :

    @Override
	public String postDelete() {
		
		CoreCache.getInstance().getGroup(getFieldValue("GROUPEPROFIL_PROFIL_FK.grp_name")).removeProfile(CoreCache.getInstance().getGroup(getFieldValue("GROUPEPROFIL_GROUPE_FK.grp_name")));
		return null;
	}
	
	@Override
	public String postCreate() {
	
		CoreCache.getInstance().getGroup(getFieldValue("GROUPEPROFIL_PROFIL_FK.grp_name")).addProfile(CoreCache.getInstance().getGroup(getFieldValue("GROUPEPROFIL_GROUPE_FK.grp_name")));
		return null;
	}

Oui, ce code n’est pas propagé aux autres noeuds.
Seul le clear-cache global est propagé en synchrone ou via cron en cas d’erreur.

Il faut donc trouver un autre moyen

  • soit en créant un service (via objet externe) qui propage l’info à tous les noeuds connues de mettre à jour ce cache, mais le call peut planter il faut aussi un cron qui rattrape… lourd
  • soit plus malin et pour être indépendant de l’infra, utiliser le PlatformHooks, pour qu’au logon ça le fasse avant de charger les groupes/responsabilités du user, en comparant la date de mise à jour du profile avec une date en mémoire. Si la date est antérieure, il faut recharger/modifier la définition du profile en cache (avec des remove et addProfile).

En pseudo code :

Il faut avoir une Map qui donne Nom du profil => Date de dernière mise à jour

Dans PlatformHooks.preLoadResponsibilities

Pour tous les profils "dynamiques"
   si la map ne contient pas le profil
       on le place dans la map avec la date en base
   sinon on regarde si la date updated_dt en base a changé avec celle en map
      si oui, on change la définition du GroupDB, 
           et on remet à jour la date en mémoire pour le faire qu une fois

(et là à priori, plus besoin de postDelete/postCreate, puisque ce code marchera qq soit le serveur lorsque l’utilisateur va se reconnecter)

A y réfléchir, il serait pas mal qu’on puisse gérer ça nativement dans la plateforme.
Modifier un profil métier c’est effectivement un cas à la frontière du design et de l’administration des droits.

Je passe ton besoin en feature request.

Il faudrait qu’au create/delete d’un profile = ajout ou retrait d’un groupe dans un groupe, l’ensemble des noeuds du cluster recharge les profils.

  • Le serveur qui met à jour un profile, positionne une date en base pour prévenir les autres
  • Au prochain logon, si le timestamp a changé, le cache des profiles se recharge tout seul, avant de charger les droits du user

Il faudra bien hériter de Profile pour que les hooks postCreate/Delete soient appelés et fassent le job.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.