mirror of
https://gitlab.easter-eggs.com/ee/ldapsaisie.git
synced 2024-11-22 18:09:06 +01:00
Allow a sequence of filters in LSobjects profile configurations
It's now possible for example to define a profile on an LSobject whose attribute would contain the DN of a group the user is member of instead of directly the dn of the user. A possible configuation using this new feature: 'LSprofile' => array( 'admin' => array( 'LSobjects' => array( 'LSsupannGroupAdminByGroup' => array( 'filters' => array( array( 'basedn' => $basedn, 'attr' => 'member', 'attr_value' => '%{dn}', 'LSobject' => 'LSsupannGroup', ), array( 'basedn' => $basedn, 'attr' => 'supannGroupeAdminDN', 'attr_value' => '%{dn}', 'LSobject' => 'LSsupannGroup', ) ), ), ), ), ) Signed-off-by: Benjamin Renard <brenard@easter-eggs.com>
This commit is contained in:
parent
10019fc9fe
commit
9add9c3321
2 changed files with 166 additions and 38 deletions
|
@ -35,6 +35,20 @@
|
||||||
'basedn' => [basedn de recherche],
|
'basedn' => [basedn de recherche],
|
||||||
'params' => [configuration de la 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],
|
'basedn' => [basedn de recherche],
|
||||||
'params' => [configuration de la 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
|
||||||
...
|
...
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>Explications : Dans la configuration d'un <emphasis>LSprofile</emphasis>,
|
<para>Explications : Dans la configuration d'un <emphasis>LSprofile</emphasis>,
|
||||||
la valeur clé <emphasis>LSprofile</emphasis> signifie qu'on est dans un cas de la
|
la valeur clé <emphasis>LSobjects</emphasis> signifie qu'on est dans un cas de la
|
||||||
délégation de droits sur des types d'LSobject. Dans ce tableau associatif, il
|
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
|
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
|
des droits via des recherches simples ou enchaînées. Le fonctionnement simple
|
||||||
associée est un tableau contenant la configuration permettant de dire quels sont
|
consiste à partir de l'objet de l'utilisateur et à générer un filtre de
|
||||||
les LSobjets de ce type concernés par la délégation.</para>
|
recherche sur un type de LSobject. Le fonctionnement enchainée consiste à faire
|
||||||
<para>Cette configuration contient les paramètres d'une recherche dans l'annuaire
|
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
|
||||||
|
<emphasis>ou</emphasis>.</para>
|
||||||
|
|
||||||
|
<para>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
|
||||||
|
<emphasis>LSobject</emphasis>.</para>
|
||||||
|
|
||||||
|
<para>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é <emphasis>filters</emphasis>. La valeur
|
||||||
|
associée à cette clé est celle d'une délégation de type simple où la clé
|
||||||
|
<emphasis>LSobject</emphasis> est devenue obligatoire.</para>
|
||||||
|
|
||||||
|
<para>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
|
en considérant que l'utilisateur connecté aura les droits du LSprofile sur les
|
||||||
objets retournés. Les paramètres de la recherche sont :
|
objets retournés. Les paramètres de la recherche sont :
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>LSobject</term>
|
||||||
|
<listitem>
|
||||||
|
<simpara>C'est le nom du LSobject recherché.
|
||||||
|
<emphasis>(Paramètre facultatif pour une délégation de type simple)</emphasis></simpara>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>attr</term>
|
<term>attr</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -1484,6 +1484,111 @@ class LSsession {
|
||||||
return LStemplate :: fetch($template);
|
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
|
* Charge les droits LS de l'utilisateur
|
||||||
*
|
*
|
||||||
|
@ -1501,38 +1606,8 @@ class LSsession {
|
||||||
if ($topDn == 'LSobjects') {
|
if ($topDn == 'LSobjects') {
|
||||||
if (is_array($rightsInfos)) {
|
if (is_array($rightsInfos)) {
|
||||||
foreach ($rightsInfos as $LSobject => $listInfos) {
|
foreach ($rightsInfos as $LSobject => $listInfos) {
|
||||||
if (self :: loadLSclass('LSsearch')) {
|
LSdebug('loading LSprofile ' . $profile . ' for LSobject ' . $LSobject . ' with params ' . var_export($listInfos, true));
|
||||||
if (isset($listInfos['filter'])) {
|
self :: loadLSprofilesLSobjects($profile, $LSobject, $listInfos);
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in a new issue