Live Security
- Définir la fonction Live Security
- Live Security pour interdire l’affichage d’une mesure
- Live Security à appliquer à un graphique précis
- Live Security utilisant un autre cube
- Vérifier l'existence d'une dimension dans un modèle de données
Définir la fonction Live Security
La fonction de live security, aussi appelée fonction de transformation de la sélection peut être configurée durant l'édition d'un modèle de données, au niveau de l'étape de configuration avancée du modèle de données, dans l'onglet Avancé. Vous pouvez choisir une fonction de transformation de sélection existante, ou en créer une nouvelle, manuellement, pour des fonctions utilisant du code javascript, ou via un assistant.
L'utilisation de l'assistant permet d'associer des dimensions à des paramètre de l'utilisateur qui fera en sorte que toute sélection sur un cube forcera les dimensions configurées à être filtrées en fonction des valeurs des paramètres utilisateurs.
L'approche manuelle, par utilisation d'un script javascript permet d'aller plus loin. L'exemple suivant est la création d'une fonction avancée de transformation de sélection qui peut être changer pour ajouter des dimensions sécurisées (modifier entre /* START CONFIG */ et /* END CONFIG */) :
//version: 2019R2
var securedDims = {};
securedDims["DIMENSION_NAME_1"] = getUserAttribute("USER_PARAM_1");
/* Ajouter ici les autres dimensions sur lequel du live security doit s’appliquer */
/*
securedDims["DIMENSION_NAME_2"] = getUserAttribute("USER_PARAM_2");
*/
/* END CONFIG */
/* MODIFY THE SCRIPT BELOW WITH CAUTION */
var sLogPrefix = "[LIVE_SECURITY] [live-sec-thread-" + Math.floor(Math.random()*16777215).toString(16) + "]"; /* 16777215 is FFFFFF in decimal */
for (var dimId in securedDims)
{
var dim = selection.dm.objName[dimId];
var persoVal = securedDims[dimId];
//Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + "Applying user filters on: " + dimId + ", persoVal:" + persoVal);
if (dim)
{
if (persoVal == null || persoVal.length == 0)
{
// user must no see any value
var persoValuesTab = ["-noval-"];
var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
selection.setFilter(filt);
Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Filters (members) on " + dimId + ": [" + persoValuesTab + "]");
}
else if (persoVal && persoVal != ".*")
{
//user is limited to some value(s)
var persoValuesTab = persoVal.split("|");
Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Applying user filters on " + dimId + ": [" + persoValuesTab + "]");
var exFilter = selection.filterByDimName[dimId];
if (!exFilter)
{
//there is no exisitng filter on that dimension => create a new one
var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
selection.setFilter(filt);
Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters (members) on " + dimId + ": [" + persoValuesTab + "]");
}
else
{
//there is already a filter on that dimension => merge (intersect) into a new one
var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
filt.recalcIds();
exFilter.recalcIds();
exFilter = mergeFilters(exFilter, filt);
origIdsTab = exFilter.origIds;
selection.setFilter(exFilter);
Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters (origIds) on " + dimId + ": [" + exFilter.origIds + "]");
}
}
else // perso value is .*
{
// do nothing, user can see everything
Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters on " + dimId + ": All (.*)");
}
}
else
{
Packages.com.digdash.utils.MessageStack.getInstance().addError(sLogPrefix + " Dimension " + dimId + "not found");
}
}
Attribut Utilisateur
Prendre le soin de créer le paramètre utilisateur USER_PARAM_1 et de l’avoir renseigné pour les utilisateurs concernés (Saisie “.*” pour les autres).
Dans l’exemple ci-dessous, admin aura le droit de voir les lignes de la dimension DIMENSION_NAME_1 ou les valeurs A, B ou C apparaissent.
Live Security pour interdire l’affichage d’une mesure
Une utilisation avancée du Live Security permet de cacher des mesures en fonction du profil de l'utilisateur. Dans l'exemple suivant, les utilisateurs ont un paramètre show_measure qui peut avoir une valeur oui ou non :
var measureId = 'CA'; // id of the measure to hide
if (show_measure == 'non')
{
var measIndex = selection.indexOfMeasure(measureId);
if (measIndex != -1)
selection.removeMeasure(measIndex);
}
Live Security à appliquer à un graphique précis
On peut aussi spécialiser le Live Security en fonction du graphique :
{
//Ajouter le code ici pour transformer la sélection de manière spécifique au flux
}
else
{
//Ajouter le code ici pour tous les autres flux
}
Live Security utilisant un autre cube
L'exemple le plus avancé est d'aller chercher les valeurs de filtrage dans un autre cube plutôt que dans les paramètres utilisateurs stockés dans le LDAP.
Explication du cas
La données « de base » est une table de transactions de flux monétaire.
Il existe un champ « SECURITY_CODE » qui sert à savoir au final si un utilisateur connecté à le droit de voir la transaction ou pas.
Il existe une autre table dite de confidentialité où l’on trouve les utilisateurs LOGIN, appartenant à des groupes GROUP_ID (relation n-n). Et les « SECURITY_CODE » rattachés à plusieurs groupes.
On ne peut pas déclarer ces SECURITY_CODE dans une variable utilisateur du LDAP car il y beaucoup de valeurs possibles et cette information doit rester en base car très changeante.
Solution Live Security
La solution est donc de ne pas faire la jointure mais de simplement ajouter une fonction Live Security au cube transactions qui va en temps réel aller « chercher » les « SECURITY_CODE » par rapport à l’utilisateur connecté dans le cube confidentialité et les imposer comme filtre.
De cette manière, la volumétrie du cube final n’augmente pas, on est sur des aplatissements très rapide et on à besoin que de 8GB de RAM sur le serveur alors qu’il en fallait au moins 32GB à Tableau pour des chargements lents.
Voici le code du script Live Security pour cet exemple (à adapter selon votre cas, entre /* START CONFIG */ et /* END CONFIG */) :
var cubeId = "id_cube_authorisations";
var userAttr = getUserAttribute("USER_LOGIN_SSO");
var dimSecurityCode = "SECURITY_CODE";
var dimUser = "LOGIN";
/* END CONFIG */
var sLogPrefix = "[SECURITY] [live-sec-thread-" + Math.floor(Math.random()*16777215).toString(16) + "]";
Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " start...");
DimBean = function(id)
{
this.id = id;
this.members = [];
}
DimBean.prototype.toJSON = function()
{
return this.id;
}
Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " user is " + userAttr);
var sel = new DataModelSelection();
sel.dm = { "variables":{} };
sel.pivot = 0;
sel.addBrowse(1, new DimBean(dimSecurityCode), -1, -1, null);
sel.addFilter(new FilterSelection(new DimBean(dimUser), -1, -1, [], [userAttr]));
var resultJSON = Packages.com.digdash.utils.ResultCubeToJavascript.getResultCubeLiveJSON(sessionId, JSON.stringify(sel), cubeId, null);
var cubRes = null;
eval("cubRes = " + resultJSON);
var resAxis = cubRes.axis[1];
var mbr = [];
for (var i = 0; i < resAxis.length; ++i)
{
mbr.push(resAxis[i].i);
}
if (mbr.length > 0)
{
var dim = selection.dm.getDimensionById(dimSecurityCode);
var filt = new FilterSelection(dim, -1, -1, [], mbr);
selection.setFilter(filt);
Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " Dimension " + dimSecurityCode + " filtered on " + mbr);
}
else
{
Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " No " + dimSecurityCode + " found for user " + userAttr);
}
Vérifier l'existence d'une dimension dans un modèle de données
Dans certains cas il peut être intéressant de vérifier qu'une dimension est présente dans le modèle de données, par exemple si le script de Live Security doit être réutilisé dans un modèle dépendant (union, transformateur de colonnes, etc.)
{
Packages.com.digdash.utils.MessageStack.getInstance().addError("LaDimensionObligatoire n'est pas dans le modèle de données");
//dans cet exemple on choisit de faire échouer le Live Security si la dimension est absente du modèle
throw new Error("LaDimensionObligatoire n'est pas dans le modèle de données");
}
//ajouter un filtre sur LaDimensionObligatoire...