From e0fb057c840887c89569e5945e3bd0669b44e4a5 Mon Sep 17 00:00:00 2001 From: Deon George Date: Thu, 2 Mar 2023 10:17:15 +1100 Subject: [PATCH] Implemented attribute sorting with configuration to determine sort order --- app/Ldap/Entry.php | 28 ++++++- config/config.php.example | 23 ------ config/ldap.php | 150 +++++++++++++++++++++++--------------- lib/functions.php | 35 --------- 4 files changed, 117 insertions(+), 119 deletions(-) diff --git a/app/Ldap/Entry.php b/app/Ldap/Entry.php index 80acb51..af66537 100644 --- a/app/Ldap/Entry.php +++ b/app/Ldap/Entry.php @@ -20,7 +20,33 @@ class Entry extends Model $result->put($attribute,Factory::create($attribute,$value)); } - return $result->toArray(); + $sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); }); + + // Order the attributes + return $result->sortBy([function($a,$b) use ($sort) { + if (! $sort->count() || $a === $b) + return 0; + + // Check if $a/$b are in the configuration to be sorted first, if so get it's key + $a_key = $sort->search($a->name_lc); + $b_key = $sort->search($b->name_lc); + + // If the keys were not in the sort list, set the key to be the count of elements (ie: so it is last to be sorted) + if ($a_key === FALSE) + $a_key = $sort->count()+1; + + if ($b_key === FALSE) + $b_key = $sort->count()+1; + + // Case where neither $a, nor $b are in ldap.attr_display_order, $a_key = $b_key = one greater than num elements. + // So we sort them alphabetically + if ($a_key === $b_key) + return strcasecmp($a->name,$b->name); + + // Case where at least one attribute or its friendly name is in $attrs_display_order + // return -1 if $a before $b in $attrs_display_order + return ($a_key < $b_key) ? -1 : 1; + } ])->toArray(); } /* ATTRIBUTES */ diff --git a/config/config.php.example b/config/config.php.example index 5c3b126..e7c5c40 100644 --- a/config/config.php.example +++ b/config/config.php.example @@ -248,29 +248,6 @@ $config->custom->appearance['friendly_attrs'] = array( // $config->custom->modify_member['posixfilter'] = '(uid=*)'; // $config->custom->modify_member['posixgroupattr'] = 'memberUid'; -/********************************************* - * Support for attrs display order * - *********************************************/ - -/* Use this array if you want to have your attributes displayed in a specific - order. You can use default attribute names or their fridenly names. - For example, "sn" will be displayed right after "givenName". All the other - attributes that are not specified in this array will be displayed after in - alphabetical order. */ -// $config->custom->appearance['attr_display_order'] = array(); -# $config->custom->appearance['attr_display_order'] = array( -# 'givenName', -# 'sn', -# 'cn', -# 'displayName', -# 'uid', -# 'uidNumber', -# 'gidNumber', -# 'homeDirectory', -# 'mail', -# 'userPassword' -# ); - /********************************************* * Define your LDAP servers in this section * *********************************************/ diff --git a/config/ldap.php b/config/ldap.php index 2a499db..a0aa2f5 100644 --- a/config/ldap.php +++ b/config/ldap.php @@ -2,74 +2,104 @@ return [ - /* - |-------------------------------------------------------------------------- - | Default LDAP Connection Name - |-------------------------------------------------------------------------- - | - | Here you may specify which of the LDAP connections below you wish - | to use as your default connection for all LDAP operations. Of - | course you may add as many connections you'd like below. - | - */ + /* + |-------------------------------------------------------------------------- + | Default LDAP Connection Name + |-------------------------------------------------------------------------- + | + | Here you may specify which of the LDAP connections below you wish + | to use as your default connection for all LDAP operations. Of + | course you may add as many connections you'd like below. + | + */ - 'default' => env('LDAP_CONNECTION', 'default'), + 'default' => env('LDAP_CONNECTION', 'default'), - /* - |-------------------------------------------------------------------------- - | LDAP Connections - |-------------------------------------------------------------------------- - | - | Below you may configure each LDAP connection your application requires - | access to. Be sure to include a valid base DN - otherwise you may - | not receive any results when performing LDAP search operations. - | - */ + /* + |-------------------------------------------------------------------------- + | LDAP Connections + |-------------------------------------------------------------------------- + | + | Below you may configure each LDAP connection your application requires + | access to. Be sure to include a valid base DN - otherwise you may + | not receive any results when performing LDAP search operations. + | + */ - 'connections' => [ + 'connections' => [ - 'default' => [ - 'hosts' => [env('LDAP_HOST', '127.0.0.1')], - 'username' => env('LDAP_USERNAME', 'cn=user,dc=local,dc=com'), - 'password' => env('LDAP_PASSWORD', 'secret'), - 'port' => env('LDAP_PORT', 389), - 'base_dn' => env('LDAP_BASE_DN', 'dc=local,dc=com'), - 'timeout' => env('LDAP_TIMEOUT', 5), - 'use_ssl' => env('LDAP_SSL', false), - 'use_tls' => env('LDAP_TLS', false), - 'name' => env('LDAP_NAME','LDAP Server'), - ], + 'default' => [ + 'hosts' => [env('LDAP_HOST', '127.0.0.1')], + 'username' => env('LDAP_USERNAME', 'cn=user,dc=local,dc=com'), + 'password' => env('LDAP_PASSWORD', 'secret'), + 'port' => env('LDAP_PORT', 389), + 'base_dn' => env('LDAP_BASE_DN', 'dc=local,dc=com'), + 'timeout' => env('LDAP_TIMEOUT', 5), + 'use_ssl' => env('LDAP_SSL', false), + 'use_tls' => env('LDAP_TLS', false), + 'name' => env('LDAP_NAME','LDAP Server'), + ], - ], + ], - /* - |-------------------------------------------------------------------------- - | LDAP Logging - |-------------------------------------------------------------------------- - | - | When LDAP logging is enabled, all LDAP search and authentication - | operations are logged using the default application logging - | driver. This can assist in debugging issues and more. - | - */ + /* + |-------------------------------------------------------------------------- + | LDAP Logging + |-------------------------------------------------------------------------- + | + | When LDAP logging is enabled, all LDAP search and authentication + | operations are logged using the default application logging + | driver. This can assist in debugging issues and more. + | + */ - 'logging' => env('LDAP_LOGGING', true), + 'logging' => env('LDAP_LOGGING', true), - /* - |-------------------------------------------------------------------------- - | LDAP Cache - |-------------------------------------------------------------------------- - | - | LDAP caching enables the ability of caching search results using the - | query builder. This is great for running expensive operations that - | may take many seconds to complete, such as a pagination request. - | - */ + /* + |-------------------------------------------------------------------------- + | LDAP Cache + |-------------------------------------------------------------------------- + | + | LDAP caching enables the ability of caching search results using the + | query builder. This is great for running expensive operations that + | may take many seconds to complete, such as a pagination request. + | + */ - 'cache' => [ - 'enabled' => env('LDAP_CACHE', false), - 'driver' => env('CACHE_DRIVER', 'file'), - 'time' => env('LDAP_CACHE_TIME',5*60), // Seconds - ], + 'cache' => [ + 'enabled' => env('LDAP_CACHE', false), + 'driver' => env('CACHE_DRIVER', 'file'), + 'time' => env('LDAP_CACHE_TIME',5*60), // Seconds + ], + + /* + |-------------------------------------------------------------------------- + | Support for attrs display order + |-------------------------------------------------------------------------- + | + | Use this array if you want to have your attributes displayed in a specific + | order. Case is not important. + | + | For example, "sn" will be displayed right after "givenName". All the other + | attributes that are not specified in this array will be displayed after in + | alphabetical order. + | + */ + + 'attr_display_order' => [], + /* + 'attr_display_order' => [ + 'givenName', + 'sn', + 'cn', + 'displayName', + 'uid', + 'uidNumber', + 'gidNumber', + 'homeDirectory', + 'mail', + 'userPassword' + ], + */ ]; diff --git a/lib/functions.php b/lib/functions.php index 2cafc17..2532b7c 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -2658,41 +2658,6 @@ function pla_reverse_dn($dn) { return (implode(',',array_reverse(pla_explode_dn($dn)))); } -/** - * Attribute sorting - */ -function sortAttrs($a,$b) { - if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) - debug_log('Entered (%%)',1,0,__FILE__,__LINE__,__METHOD__,$fargs); - - if ($a == $b) - return 0; - - $server = $_SESSION[APPCONFIG]->getServer(get_request('server_id','REQUEST')); - $attrs_display_order = arrayLower($_SESSION[APPCONFIG]->getValue('appearance','attr_display_order')); - - # Check if $a is in $attrs_display_order, get its key - $a_key = array_search($a->getName(),$attrs_display_order); - $b_key = array_search($b->getName(),$attrs_display_order); - - if ((! $a_key) && ($a_key !== 0)) - if ((! $a_key = array_search(strtolower($a->getFriendlyName()),$attrs_display_order)) && ($a_key !== 0)) - $a_key = count($attrs_display_order)+1; - - if ((! $b_key) && ($b_key !== 0)) - if ((! $b_key = array_search(strtolower($b->getFriendlyName()),$attrs_display_order)) && ($b_key !== 0)) - $b_key = count($attrs_display_order)+1; - - # Case where neither $a, nor $b are in $attrs_display_order, $a_key = $b_key = one greater than num elements. - # So we sort them alphabetically - if ($a_key === $b_key) - return strcasecmp($a->getFriendlyName(),$b->getFriendlyName()); - - # Case where at least one attribute or its friendly name is in $attrs_display_order - # return -1 if $a before $b in $attrs_display_order - return ($a_key < $b_key) ? -1 : 1; -} - /** * Reads an array and returns the array values back in lower case *