From c506f3056266ecdc591ba9c8e5f02048d64b1703 Mon Sep 17 00:00:00 2001 From: Richard Hofman Date: Thu, 12 Jan 2017 20:37:14 +1300 Subject: [PATCH] Add support for location-specific LDAP OUs. (#3176) * Add support for location-specific LDAP OUs. * Shortened variable names as suggested by Codacy review. --- app/Console/Commands/LdapSync.php | 42 ++++++++++++++++++- app/Http/Controllers/LocationsController.php | 3 +- app/Http/Controllers/UsersController.php | 36 +++++++++++++++- app/Models/Ldap.php | 9 ++-- ...0429_create_locations_ldap_query_field.php | 31 ++++++++++++++ resources/lang/en/admin/locations/table.php | 1 + resources/views/locations/edit.blade.php | 14 +++++++ 7 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 database/migrations/2017_01_09_040429_create_locations_ldap_query_field.php diff --git a/app/Console/Commands/LdapSync.php b/app/Console/Commands/LdapSync.php index 0a7f2dcbcf..3b10b6e4c7 100644 --- a/app/Console/Commands/LdapSync.php +++ b/app/Console/Commands/LdapSync.php @@ -69,6 +69,18 @@ class LdapSync extends Command $results = Ldap::findLdapUsers(); + $ldap_ou_locations = Location::whereNotNull('ldap_ou')->get(); + + if (sizeof($ldap_ou_locations) > 0) { + LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.'); + } + + $results = Ldap::findLdapUsers(); + for ($i = 0; $i < $results["count"]; $i++) { + $results[$i]["ldap_location_override"] = false; + $results[$i]["location_id"] = 0; + } + if ($this->option('location')!='') { $location = Location::where('name', '=', $this->option('location'))->first(); LOG::debug('Location name '.$this->option('location').' passed'); @@ -82,9 +94,30 @@ class LdapSync extends Command } if (!isset($location)) { - LOG::debug('That location is invalid, so no location will be assigned.'); + LOG::debug('That location is invalid, so no location will be assigned by default.'); } + // Grab subsets based on location-specific DNs, and overwrite location for these users. + foreach ($ldap_ou_locations as $ldap_loc) { + $location_users = Ldap::findLdapUsers($ldap_loc->ldap_ou); + $usernames = array(); + for ($i = 0; $i < $location_users["count"]; $i++) { + $location_users[$i]["ldap_location_override"] = true; + $location_users[$i]["location_id"] = $ldap_loc->id; + $usernames[] = $location_users[$i][$ldap_result_username][0]; + } + + // Delete located users from the general group. + foreach ($results as $key => $generic_entry) { + if (in_array($generic_entry[$ldap_result_username][0], $location_users)) { + unset($results[$key]); + } + } + + $global_count = $results['count']; + $results = array_merge($location_users, $results); + $results['count'] = $global_count; + } $tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20); $pass = bcrypt($tmp_pass); @@ -99,6 +132,9 @@ class LdapSync extends Command $item["lastname"] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : ""; $item["firstname"] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : ""; $item["email"] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : "" ; + $item["ldap_location_override"] = isset($results[$i]["ldap_location_override"]) ? $results[$i]["ldap_location_override"]:""; + $item["location_id"] = isset($results[$i]["location_id"]) ? $results[$i]["location_id"]:""; + // User exists $item["createorupdate"] = 'updated'; @@ -118,7 +154,9 @@ class LdapSync extends Command $user->employee_num = e($item["employee_number"]); $user->activated = 1; - if ($location) { + if ($item['ldap_location_override'] == true) { + $user->location_id = $item['location_id']; + } else if ($location) { $user->location_id = e($location->id); } diff --git a/app/Http/Controllers/LocationsController.php b/app/Http/Controllers/LocationsController.php index f7eefc398c..e3af226cf1 100755 --- a/app/Http/Controllers/LocationsController.php +++ b/app/Http/Controllers/LocationsController.php @@ -184,8 +184,9 @@ class LocationsController extends Controller $location->state = Input::get('state'); $location->country = Input::get('country'); $location->zip = Input::get('zip'); + $location->ldap_ou = Input::get('ldap_ou'); - // Was the asset created? + // Was the location updated? if ($location->save()) { // Redirect to the saved location page return redirect()->route("locations.index")->with('success', trans('admin/locations/message.update.success')); diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index eb77a82f6c..68c2ecb021 100755 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -1049,8 +1049,38 @@ class UsersController extends Controller $summary = array(); + $ldap_ou_locations = Location::whereNotNull('ldap_ou')->get(); + $results = Ldap::findLdapUsers(); + // Inject location information fields + for ($i = 0; $i < $results["count"]; $i++) { + $results[$i]["ldap_location_override"] = false; + $results[$i]["location_id"] = 0; + } + + // Grab subsets based on location-specific DNs, and overwrite location for these users. + foreach ($ldap_ou_locations as $ldap_loc) { + $location_users = Ldap::findLdapUsers($ldap_loc->ldap_ou); + $usernames = array(); + for ($i = 0; $i < $location_users["count"]; $i++) { + $location_users[$i]["ldap_location_override"] = true; + $location_users[$i]["location_id"] = $ldap_loc->id; + $usernames[] = $location_users[$i][$ldap_result_username][0]; + } + + // Delete located users from the general group. + foreach ($results as $key => $generic_entry) { + if (in_array($generic_entry[$ldap_result_username][0], $location_users)) { + unset($results[$key]); + } + } + + $global_count = $results['count']; + $results = array_merge($location_users, $results); + $results['count'] = $global_count; + } + $tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20); $pass = bcrypt($tmp_pass); @@ -1063,6 +1093,8 @@ class UsersController extends Controller $item["lastname"] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : ""; $item["firstname"] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : ""; $item["email"] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : "" ; + $item["ldap_location_override"] = isset($results[$i]["ldap_location_override"]) ? $results[$i]["ldap_location_override"]:""; + $item["location_id"] = isset($results[$i]["location_id"]) ? $results[$i]["location_id"]:""; // User exists $item["createorupdate"] = 'updated'; @@ -1079,7 +1111,9 @@ class UsersController extends Controller $user->email = e($item["email"]); $user->employee_num = e($item["employee_number"]); $user->activated = 1; - if ($request->input('location_id')!='') { + if ($item['ldap_location_override'] == true) { + $user->location_id = $item['location_id']; + } else if ($request->input('location_id')!='') { $user->location_id = e($request->input('location_id')); } $user->notes = 'Imported from LDAP'; diff --git a/app/Models/Ldap.php b/app/Models/Ldap.php index 0373eeedfa..c629491813 100644 --- a/app/Models/Ldap.php +++ b/app/Models/Ldap.php @@ -232,18 +232,21 @@ class Ldap extends Model * @author [A. Gianotto] [] * @since [v3.0] * @param $ldapatttibutes + * @param $base_dn * @return array|bool */ - static function findLdapUsers() + static function findLdapUsers($base_dn = null) { $ldapconn = Ldap::connectToLdap(); $ldap_bind = Ldap::bindAdminToLdap($ldapconn); - $base_dn = Setting::getSettings()->ldap_basedn; + // Default to global base DN if nothing else is provided. + if (is_null($base_dn)) { + $base_dn = Setting::getSettings()->ldap_basedn; + } $filter = Setting::getSettings()->ldap_filter; // Set up LDAP pagination for very large databases - // @author Richard Hofman $page_size = 500; $cookie = ''; $result_set = array(); diff --git a/database/migrations/2017_01_09_040429_create_locations_ldap_query_field.php b/database/migrations/2017_01_09_040429_create_locations_ldap_query_field.php new file mode 100644 index 0000000000..54d609d719 --- /dev/null +++ b/database/migrations/2017_01_09_040429_create_locations_ldap_query_field.php @@ -0,0 +1,31 @@ +string('ldap_ou')->nullable()->default(null); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('locations', function ($table) { + $table->string('ldap_ou')->nullable()->default(null); + }); + } +} diff --git a/resources/lang/en/admin/locations/table.php b/resources/lang/en/admin/locations/table.php index e171d4dd4e..ffa69307d5 100644 --- a/resources/lang/en/admin/locations/table.php +++ b/resources/lang/en/admin/locations/table.php @@ -17,4 +17,5 @@ return array( 'locations' => 'Locations', 'parent' => 'Parent', 'currency' => 'Location Currency', + 'ldap_ou' => 'LDAP Search OU', ); diff --git a/resources/views/locations/edit.blade.php b/resources/views/locations/edit.blade.php index d48c345b47..2c249f602c 100755 --- a/resources/views/locations/edit.blade.php +++ b/resources/views/locations/edit.blade.php @@ -33,6 +33,20 @@ @include ('partials.forms.edit.address') + + +@if ($snipeSettings->ldap_enabled == 1) +
+ +
+ {{ Form::text('ldap_ou', Input::old('ldap_ou', $item->ldap_ou), array('class' => 'form-control')) }} + {!! $errors->first('ldap_ou', ':message') !!} +
+
+@endif + @stop @if (!$item->id)