Code source wiki de Live Security

Modifié par Aurelie Bertrand le 2023/12/12 17:31

Afficher les derniers auteurs
1 {{toc/}}
2
3 ----
4
5 = Définir la fonction Live Security =
6
7 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.
8
9 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.
10
11 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 (% style="color:#e67e22" %)**/* START CONFIG */**(%%) et (% style="color:#e67e22" %)**/* END CONFIG */**(%%)) :
12
13 {{code language="js"}}
14 /* START CONFIG */
15 //version: 2019R2
16 var securedDims = {};
17 securedDims["DIMENSION_NAME_1"] = getUserAttribute("USER_PARAM_1");
18
19 /* Ajouter ici les autres dimensions sur lequel du live security doit s’appliquer */
20 /*
21 securedDims["DIMENSION_NAME_2"] = getUserAttribute("USER_PARAM_2");
22 */
23
24 /* END CONFIG */
25
26 /* MODIFY THE SCRIPT BELOW WITH CAUTION */
27 var sLogPrefix = "[LIVE_SECURITY] [live-sec-thread-" + Math.floor(Math.random()*16777215).toString(16) + "]"; /* 16777215 is FFFFFF in decimal */
28
29 for (var dimId in securedDims)
30 {
31 var dim = selection.dm.objName[dimId];
32 var persoVal = securedDims[dimId];
33
34 //Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + "Applying user filters on: " + dimId + ", persoVal:" + persoVal);
35 if (dim)
36 {
37 if (persoVal == null || persoVal.length == 0)
38 {
39 // user must no see any value
40 var persoValuesTab = ["-noval-"];
41 var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
42 selection.setFilter(filt);
43 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Filters (members) on " + dimId + ": [" + persoValuesTab + "]");
44 }
45 else if (persoVal && persoVal != ".*")
46 {
47 //user is limited to some value(s)
48 var persoValuesTab = persoVal.split("|");
49 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Applying user filters on " + dimId + ": [" + persoValuesTab + "]");
50 var exFilter = selection.filterByDimName[dimId];
51 if (!exFilter)
52 {
53 //there is no exisitng filter on that dimension => create a new one
54 var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
55 selection.setFilter(filt);
56 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters (members) on " + dimId + ": [" + persoValuesTab + "]");
57 }
58 else
59 {
60 //there is already a filter on that dimension => merge (intersect) into a new one
61 var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
62 filt.recalcIds();
63 exFilter.recalcIds();
64 exFilter = mergeFilters(exFilter, filt);
65 origIdsTab = exFilter.origIds;
66 selection.setFilter(exFilter);
67 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters (origIds) on " + dimId + ": [" + exFilter.origIds + "]");
68 }
69 }
70 else // perso value is .*
71 {
72 // do nothing, user can see everything
73 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters on " + dimId + ": All (.*)");
74 }
75 }
76 else
77 {
78 Packages.com.digdash.utils.MessageStack.getInstance().addError(sLogPrefix + " Dimension " + dimId + "not found");
79 }
80 }
81 {{/code}}
82
83 == Attribut Utilisateur ==
84
85 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).
86 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.
87
88
89 [[image:https://lh6.googleusercontent.com/PFz-w1dqknwbuP_W-YeSH0EVWjnR4mbESAsEgTjyNSAKFAwChSJPSkLCVaZOricQLA4g_SGytqGFj0go_OFQUlDRbd8ZSsMC3PrfLq4GV3Kluv_SSy8iO0LEqzqbcdvyYPKHuVfA9fU||height="460" width="905"]]
90
91 = Live Security pour interdire l’affichage d’une mesure =
92
93 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** :
94
95 {{code language="js"}}
96 var show_measure = getUserAttribute('show_measure');
97 var measureId = 'CA'; // id of the measure to hide
98
99 if (show_measure == 'non')
100 {
101 var measIndex = selection.indexOfMeasure(measureId);
102 if (measIndex > 0)
103 selection.removeMeasure(measIndex);
104 }
105 {{/code}}
106
107 = Live Security à appliquer à un graphique précis =
108
109 On peut aussi spécialiser le Live Security en fonction du graphique :
110
111 {{code language="js"}}
112 if (flowId != null && flowId.indexOf("mon_flow_id") > -1)
113 {
114 //Ajouter le code ici pour transformer la sélection de manière spécifique au flux
115 }
116 else
117 {
118 //Ajouter le code ici pour tous les autres flux
119 }
120 {{/code}}
121
122 = Live Security utilisant un autre cube =
123
124 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.
125
126 == Explication du cas ==
127
128 La données « de base » est une table de transactions de flux monétaire.
129 Il existe un champ « SECURITY_CODE » qui sert à savoir au final si un utilisateur connecté à le droit de voir la transaction ou pas.
130 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.
131 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.
132
133 == Solution Live Security ==
134
135 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.
136 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.
137
138 Voici le code du script Live Security pour cet exemple (à adapter selon votre cas, entre **/* START CONFIG */** et **/* END CONFIG */**) :
139
140 {{code cssClass="notranslate" language="javascript"}}
141 /* START CONFIG */
142 var cubeId = "id_cube_authorisations";
143 var userAttr = getUserAttribute("USER_LOGIN_SSO");
144 var dimSecurityCode = "SECURITY_CODE";
145 var dimUser = "LOGIN";
146 /* END CONFIG */
147
148 var sLogPrefix = "[SECURITY] [live-sec-thread-" + Math.floor(Math.random()*16777215).toString(16) + "]";
149 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " start...");
150 DimBean = function(id)
151 {
152 this.id = id;
153 this.members = [];
154 }
155
156 DimBean.prototype.toJSON = function()
157 {
158 return this.id;
159 }
160
161 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " user is " + userAttr);
162 var sel = new DataModelSelection();
163 sel.dm = { "variables":{} };
164 sel.pivot = 0;
165 sel.addBrowse(1, new DimBean(dimSecurityCode), -1, -1, null);
166 sel.addFilter(new FilterSelection(new DimBean(dimUser), -1, -1, [], [userAttr]));
167 var resultJSON = Packages.com.digdash.utils.ResultCubeToJavascript.getResultCubeLiveJSON(sessionId, JSON.stringify(sel), cubeId, null);
168 var cubRes = null;
169 eval("cubRes = " + resultJSON);
170 var resAxis = cubRes.axis[1];
171 var mbr = [];
172 for (var i = 0; i < resAxis.length; ++i)
173 {
174 mbr.push(resAxis[i].i);
175 }
176 if (mbr.length > 0)
177 {
178 var dim = selection.dm.getDimensionById(dimSecurityCode);
179 var filt = new FilterSelection(dim, -1, -1, [], mbr);
180 selection.setFilter(filt);
181 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " Dimension " + dimSecurityCode + " filtered on " + mbr);
182 }
183 else
184 {
185 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " No " + dimSecurityCode + " found for user " + userAttr);
186 }
187 {{/code}}
188
189 = Vérifier l'existence d'une dimension dans un modèle de données =
190
191 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.)
192
193 {{code cssClass="notranslate" language="javascript"}}
194 if (!selection.dm.getDimensionById("LaDimensionObligatoire"))
195 {
196 Packages.com.digdash.utils.MessageStack.getInstance().addError("LaDimensionObligatoire n'est pas dans le modèle de données");
197 //dans cet exemple on choisit de faire échouer le Live Security si la dimension est absente du modèle
198 throw new Error("LaDimensionObligatoire n'est pas dans le modèle de données");
199 }
200
201 //ajouter un filtre sur LaDimensionObligatoire...
202 {{/code}}