diff --git a/doc/conf/LSprofile.docbook b/doc/conf/LSprofile.docbook index 152f9077..97683ee9 100644 --- a/doc/conf/LSprofile.docbook +++ b/doc/conf/LSprofile.docbook @@ -35,6 +35,20 @@ 'basedn' => [basedn de recherche], 'params' => [configuration de la recherche] ), + [nom quelconque] => array ( + 'filters' => array( + array( + 'LSobject' => [nom du LSobject], + 'attr' => [nom de l'attribut clé], + 'attr_value' => [format de la valeur de l'attribut clé], + // ou + 'filter' => [format du filtre de recherche], + + 'basedn' => [basedn de recherche], + 'params' => [configuration de la recherche] + ), + ), + ), ... ) ), @@ -151,6 +165,20 @@ objets pour lesquels l'utilisateur appartiendra au 'basedn' => [basedn de recherche], 'params' => [configuration de la recherche] ), + array ( + 'filters' => array( + array( + 'LSobject' => [nom du LSobject], + 'attr' => [nom de l'attribut clé], + 'attr_value' => [format de la valeur de l'attribut clé], + // ou + 'filter' => [format du filtre de recherche], + + 'basedn' => [basedn de recherche], + 'params' => [configuration de la recherche] + ), + ), + ), ... ) ), @@ -159,18 +187,43 @@ objets pour lesquels l'utilisateur appartiendra au ... Explications : Dans la configuration d'un LSprofile, -la valeur clé LSprofile signifie qu'on est dans un cas de la -délégation de droits sur des types d'LSobject. Dans ce tableau associatif, il +la valeur clé LSobjects signifie qu'on est dans un cas de la +délégation de droits sur des types d'LSobject. Dans ce tableau associatif, il est possible de définir un ou plusieurs types de LSobject pour lesquels on délègue -des droits. Dans ce tableau la valeur clé est le nom du LSobject et la valeur -associée est un tableau contenant la configuration permettant de dire quels sont -les LSobjets de ce type concernés par la délégation. -Cette configuration contient les paramètres d'une recherche dans l'annuaire +des droits via des recherches simples ou enchaînées. Le fonctionnement simple +consiste à partir de l'objet de l'utilisateur et à générer un filtre de +recherche sur un type de LSobject. Le fonctionnement enchainée consiste à faire +un première recherche à partir de l'objet de l'utilisateur puis à recommencer à +partir des objets trouvés en construisant une liste de filtres de recherche +pour chaque objet qui seront combinés via l'opérateur booléen +ou. + +Pour configurer une délégation de type simple on mettra le nom du +LSobject dans la clé du tableau et dans la valeur un tableau définissant la +recherche. Il est possible de ne pas utiliser la clé du tableau comme nom du +LSobject grâce à la clé de configuration +LSobject. + +Pour configurer une délégation de type enchaîné on pourra utiliser +n'importe quelle valeur unique pour la clé du tableau et pour la valeur un +tableau contenant une unique clé filters. La valeur +associée à cette clé est celle d'une délégation de type simple où la clé +LSobject est devenue obligatoire. + +Cette configuration contient les paramètres d'une ou plusieurs recherches dans l'annuaire en considérant que l'utilisateur connecté aura les droits du LSprofile sur les objets retournés. Les paramètres de la recherche sont : + + LSobject + + C'est le nom du LSobject recherché. + (Paramètre facultatif pour une délégation de type simple) + + + attr diff --git a/public_html/includes/class/class.LSsession.php b/public_html/includes/class/class.LSsession.php index adab3f10..4703a2d8 100644 --- a/public_html/includes/class/class.LSsession.php +++ b/public_html/includes/class/class.LSsession.php @@ -1484,6 +1484,111 @@ class LSsession { return LStemplate :: fetch($template); } + /** + * Prend un tableau de LSobject et le réduit en utilisant un filtre de + * recherche sur un autre type de LSobject. + * + * Si une erreur est présente dans le tableau de définition du filtre, un + * tableau vide est renvoyé. + * + * @param[in] string $LSobject le type LSobject par défaut + * @param[in] array $set tableau de LSobject + * @param[in] array $filter_def définition du filtre de recherche pour la réduction + * @param[in] string $basend basedn pour la recherche, null par défaut + * + * @retval array le nouveau tableau de LSobject + */ + private static function reduceLdapSet($LSobject, $set, $filter_def, $basedn=null) { + if (empty($set)) { + return array(); + } + + if (! isset($filter_def['filter']) && + (! isset($filter_def['attr']) || + ! isset($filter_def['attr_value']))) { + LSdebug("Filtre de profil LSobject invalide " . var_export($filter_def, true)); + return array(); + } + + LSdebug('LSsession :: reducing set of'); + foreach ($set as $object) { + LSdebug('LSsession :: -> ' . $object -> getDn()); + } + + $LSobject = isset($filter_def['LSObject']) ? $filter_def['LSobject'] : $LSobject; + LSdebug('LSobject :: ' . $LSobject); + $filters = array(); + foreach ($set as $object) { + if (isset($filter_def['filter'])) { + $filters[] = $object -> getFData($filter_def['filter']); + } + else { + $value = $object -> getFData($filter_def['attr_value']); + $filters[] = Net_LDAP2_Filter::create($filter_def['attr'], 'equals', $value); + } + } + $filter = LSldap::combineFilters('or', $filters); + $params = array( + 'basedn' => isset($filter_def['basedn']) ? $filter_def['basedn'] : $basedn, + 'filter' => $filter, + ); + if (isset($filter_def['params']) && is_array($filter_def['params'])) { + $params = array_merge($filter_def['params'],$params); + } + $LSsearch = new LSsearch($LSobject,'LSsession :: loadLSprofiles',$params,true); + $LSsearch -> run(false); + + $set = $LSsearch -> listObjects(); + LSdebug('LSsession :: reduced set to'); + foreach ($set as $object) { + LSdebug('LSsession :: -> ' . $object -> getDn()); + } + return $set; + } + + /** + * Charge les droits LS de l'utilisateur : uniquement du type LSobjects + * + * @param[in] string $ + * + * @retval void + */ + private static function loadLSprofilesLSobjects($profile, $LSobject, $listInfos) { + if (! self :: loadLSclass('LSsearch')) { + LSdebug('Impossible de charger la classe LSsearch'); + return; + } + # we are gonna grow a set of objects progressively, we start from the user + $set = array(self :: getLSuserObject()); + $basedn = isset($listInfos['basedn']) ? $listInfos['basedn'] : null; + $LSobject = isset($listInfos['LSobject']) ? $listInfos['LSobject'] : $LSobject; + + if (isset($listInfos['filters']) && is_array($listInfos['filters'])) { + foreach ($listInfos['filters'] as $filter_def) { + $set = self :: reduceLdapSet($LSobject, $set, $filter_def, $basedn); + } + } + if (isset($listInfos['filter']) || (isset($listInfos['attr']) && isset($listInfos['attr_value']))) { + # support legacy profile definition + $set = self :: reduceLdapSet($LSobject, $set, $listInfos, $basedn); + } + + $DNs = []; + foreach ($set as $object) { + $DNs[] = $object -> getDn(); + } + if (!is_array(self :: $LSprofiles[$profile])) { + self :: $LSprofiles[$profile]=$DNs; + } + else { + foreach($DNs as $dn) { + if (!in_array($dn,self :: $LSprofiles[$profile])) { + self :: $LSprofiles[$profile][] = $dn; + } + } + } + } + /** * Charge les droits LS de l'utilisateur * @@ -1501,38 +1606,8 @@ class LSsession { if ($topDn == 'LSobjects') { if (is_array($rightsInfos)) { foreach ($rightsInfos as $LSobject => $listInfos) { - if (self :: loadLSclass('LSsearch')) { - if (isset($listInfos['filter'])) { - $filter = self :: getLSuserObject() -> getFData($listInfos['filter']); - } - else { - $filter = '('.$listInfos['attr'].'='.self :: getLSuserObject() -> getFData($listInfos['attr_value']).')'; - } - - $params = array ( - 'basedn' => (isset($listInfos['basedn'])?$listInfos['basedn']:null), - 'filter' => $filter - ); - - if (isset($listInfos['params']) && is_array($listInfos['params'])) { - $params = array_merge($listInfos['params'],$params); - } - - $LSsearch = new LSsearch($LSobject,'LSsession :: loadLSprofiles',$params,true); - $LSsearch -> run(false); - - $DNs = $LSsearch -> listObjectsDn(); - if (!is_array(self :: $LSprofiles[$profile])) { - self :: $LSprofiles[$profile]=$DNs; - } - else { - foreach($DNs as $dn) { - if (!in_array($dn,self :: $LSprofiles[$profile])) { - self :: $LSprofiles[$profile][] = $dn; - } - } - } - } + LSdebug('loading LSprofile ' . $profile . ' for LSobject ' . $LSobject . ' with params ' . var_export($listInfos, true)); + self :: loadLSprofilesLSobjects($profile, $LSobject, $listInfos); } } else {