Modifié par Aurelie Bertrand le 2025/11/04 16:11

Afficher les derniers auteurs
1 {{ddtoc/}}
2
3 ----
4
5 La fonction Live Security contrôle l’accès aux données des tableaux de bord selon le profil de l’utilisateur. Elle filtre en temps réel les dimensions, mesures ou membres visibles, selon des règles définies par l’administrateur.
6
7 La configuration peut se faire :
8
9 * Via l’assistant graphique : associe des dimensions à des paramètres utilisateurs (LDAP ou plateforme).
10 * Via un script JavaScript : permet des logiques avancées comme filtrage conditionnel, masquage de mesures ou récupération de droits depuis un autre cube.
11
12 Nous allons voir ici des exemples d'utilisation avancée du Live Security.
13
14 = Définir la fonction Live Security =
15
16 (% class="box" %)
17 (((
18 💡 Consultez le paragraphe [[Sécurisation via Live Security>>doc:Digdash.user_guide.tutorials.live_security.WebHome||anchor="live_security"]] pour plus de détails sur le fonctionnement et la mise en place de Live Security.
19 )))
20
21 La fonction 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.
22
23 L'utilisation de l'assistant permet d'associer des dimensions à des paramètres utilisateur. Ainsi, toute sélection sur un cube forcera les dimensions configurées à être filtrées en fonction des valeurs des paramètres utilisateurs.
24
25 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 modifiée pour ajouter des dimensions sécurisées (modifier entre (% style="color:#e67e22" %)**/* START CONFIG */**(%%) et (% style="color:#e67e22" %)**/* END CONFIG */**(%%)) :
26
27 {{code language="js"}}
28 /* START CONFIG */
29 var securedDims = {};
30 securedDims["DIMENSION_NAME_1"] = getUserAttribute("USER_PARAM_1");
31
32 /* Ajouter ici les autres dimensions sur lequel du live security doit s’appliquer */
33 /*
34 securedDims["DIMENSION_NAME_2"] = getUserAttribute("USER_PARAM_2");
35 */
36
37 /* END CONFIG */
38
39 /* MODIFY THE SCRIPT BELOW WITH CAUTION */
40 var sLogPrefix = "[LIVE_SECURITY] [live-sec-thread-" + Math.floor(Math.random()*16777215).toString(16) + "]"; /* 16777215 is FFFFFF in decimal */
41
42 for (var dimId in securedDims)
43 {
44 var dim = selection.dm.objName[dimId];
45 var persoVal = securedDims[dimId];
46
47 //Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + "Applying user filters on: " + dimId + ", persoVal:" + persoVal);
48 if (dim)
49 {
50 if (persoVal == null || persoVal.length == 0)
51 {
52 // user must no see any value
53 var persoValuesTab = ["-noval-"];
54 var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
55 selection.setFilter(filt);
56 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Filters (members) on " + dimId + ": [" + persoValuesTab + "]");
57 }
58 else if (persoVal && persoVal != ".*")
59 {
60 //user is limited to some value(s)
61 var persoValuesTab = persoVal.split("|");
62 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Applying user filters on " + dimId + ": [" + persoValuesTab + "]");
63 var exFilter = selection.filterByDimName[dimId];
64 if (!exFilter)
65 {
66 //there is no exisitng filter on that dimension => create a new one
67 var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
68 selection.setFilter(filt);
69 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters (members) on " + dimId + ": [" + persoValuesTab + "]");
70 }
71 else
72 {
73 //there is already a filter on that dimension => merge (intersect) into a new one
74 var filt = new FilterSelection(dim, -1, -1, [], persoValuesTab);
75 filt.recalcIds();
76 exFilter.recalcIds();
77 exFilter = mergeFilters(exFilter, filt);
78 origIdsTab = exFilter.origIds;
79 selection.setFilter(exFilter);
80 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters (origIds) on " + dimId + ": [" + exFilter.origIds + "]");
81 }
82 }
83 else // perso value is .*
84 {
85 // do nothing, user can see everything
86 Packages.com.digdash.utils.MessageStack.getInstance().addDebug(sLogPrefix + " Resolved filters on " + dimId + ": All (.*)");
87 }
88 }
89 else
90 {
91 Packages.com.digdash.utils.MessageStack.getInstance().addError(sLogPrefix + " Dimension " + dimId + "not found");
92 }
93 }
94 {{/code}}
95
96
97
98 == Paramètre utilisateur ==
99
100 Il est nécessaire de créer le paramètre utilisateur associé à chaque dimension à sécuriser (par exemple, **USER_PARAM_1)** et de le renseigner pour les utilisateurs concernés.
101 Dans l’exemple ci-dessous, l'utilisateur aura le droit de voir les lignes de la dimension **DIMENSION_NAME_1** comportant les valeurs **A, B ou C**.
102
103 Consultez le paragraphe [[Ajouter un paramètre utilisateur>>doc:Digdash.deployment.configuration.administration.User_management.User_management.WebHome||anchor="Parametres_utilisateurs"]] pour plus de détails.
104
105 [[image:User_parameter_FR.png]]
106
107 = Live Security pour interdire l’affichage d’une mesure =
108
109 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** :
110
111 {{code language="js"}}
112 var show_measure = getUserAttribute('show_measure');
113 var measureId = 'CA'; // id of the measure to hide
114
115 if (show_measure == 'non')
116 {
117 var measIndex = selection.indexOfMeasure(measureId);
118 if (measIndex != -1)
119 selection.removeMeasure(measIndex);
120 }
121 {{/code}}
122
123 = Live Security à appliquer à un graphique précis =
124
125 On peut aussi spécialiser le Live Security en fonction du graphique :
126
127 {{code language="js"}}
128 if (flowId != null && flowId.indexOf("mon_flow_id") > -1)
129 {
130 //Ajouter le code ici pour transformer la sélection de manière spécifique au flux
131 }
132 else
133 {
134 //Ajouter le code ici pour tous les autres flux
135 }
136 {{/code}}
137
138 = Live Security utilisant un autre cube =
139
140 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.
141
142 == Explication du cas ==
143
144 La données « de base » est une table de transactions de flux monétaire.
145 Il existe un champ « SECURITY_CODE » qui sert à savoir au final si un utilisateur connecté à le droit de voir la transaction ou pas.
146 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.
147 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.
148
149 == Solution Live Security ==
150
151 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.
152 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.
153
154 Voici le code du script Live Security pour cet exemple (à adapter selon votre cas, entre **/* START CONFIG */** et **/* END CONFIG */**) :
155
156 {{code cssClass="notranslate" language="javascript"}}
157 /* START CONFIG */
158 var cubeId = "id_cube_authorisations";
159 var userAttr = getUserAttribute("USER_LOGIN_SSO");
160 var dimSecurityCode = "SECURITY_CODE";
161 var dimUser = "LOGIN";
162 /* END CONFIG */
163
164 var sLogPrefix = "[SECURITY] [live-sec-thread-" + Math.floor(Math.random()*16777215).toString(16) + "]";
165 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " start...");
166 DimBean = function(id)
167 {
168 this.id = id;
169 this.members = [];
170 }
171
172 DimBean.prototype.toJSON = function()
173 {
174 return this.id;
175 }
176
177 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " user is " + userAttr);
178 var sel = new DataModelSelection();
179 sel.dm = { "variables":{} };
180 sel.pivot = 0;
181 sel.addBrowse(1, new DimBean(dimSecurityCode), -1, -1, null);
182 sel.addFilter(new FilterSelection(new DimBean(dimUser), -1, -1, [], [userAttr]));
183 var resultJSON = Packages.com.digdash.utils.ResultCubeToJavascript.getResultCubeLiveJSON(sessionId, JSON.stringify(sel), cubeId, null);
184 var cubRes = null;
185 eval("cubRes = " + resultJSON);
186 var resAxis = cubRes.axis[1];
187 var mbr = [];
188 for (var i = 0; i < resAxis.length; ++i)
189 {
190 mbr.push(resAxis[i].i);
191 }
192 if (mbr.length > 0)
193 {
194 var dim = selection.dm.getDimensionById(dimSecurityCode);
195 var filt = new FilterSelection(dim, -1, -1, [], mbr);
196 selection.setFilter(filt);
197 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " Dimension " + dimSecurityCode + " filtered on " + mbr);
198 }
199 else
200 {
201 Packages.com.digdash.utils.MessageStack.getInstance().addText(sLogPrefix + " No " + dimSecurityCode + " found for user " + userAttr);
202 }
203 {{/code}}
204
205 = Vérifier l'existence d'une dimension dans un modèle de données =
206
207 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.)
208
209 {{code cssClass="notranslate" language="javascript"}}
210 if (!selection.dm.getDimensionById("LaDimensionObligatoire"))
211 {
212 Packages.com.digdash.utils.MessageStack.getInstance().addError("LaDimensionObligatoire n'est pas dans le modèle de données");
213 //dans cet exemple on choisit de faire échouer le Live Security si la dimension est absente du modèle
214 throw new Error("LaDimensionObligatoire n'est pas dans le modèle de données");
215 }
216
217 //ajouter un filtre sur LaDimensionObligatoire...
218 {{/code}}
219
220 = Pour en savoir plus... =
221
222 * [[Sécuriser un modèle de données>>doc:Digdash.user_guide.tutorials.live_security.WebHome]]