From ced30082a68069c5009a6a7b806b43ca400fc327 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 12:10:28 +0100 Subject: [PATCH 01/15] Added display_name as user field Signed-off-by: snipe --- app/Http/Controllers/Api/UsersController.php | 6 ++++ app/Http/Transformers/UsersTransformer.php | 10 +++--- app/Models/SnipeSCIMConfig.php | 3 +- app/Models/User.php | 10 ++++-- app/Presenters/UserPresenter.php | 9 ++++++ ...08_19_114742_add_display_name_to_users.php | 32 +++++++++++++++++++ resources/lang/en-US/admin/users/table.php | 1 + 7 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 database/migrations/2025_08_19_114742_add_display_name_to_users.php diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index a0d9aeaa30..311b35768f 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -64,6 +64,7 @@ class UsersController extends Controller 'users.jobtitle', 'users.last_login', 'users.last_name', + 'users.display_name', 'users.locale', 'users.location_id', 'users.manager_id', @@ -154,6 +155,10 @@ class UsersController extends Controller $users = $users->where('users.last_name', '=', $request->input('last_name')); } + if ($request->filled('display_name')) { + $users = $users->where('users.display_name', '=', $request->input('display_name')); + } + if ($request->filled('employee_num')) { $users = $users->where('users.employee_num', '=', $request->input('employee_num')); } @@ -284,6 +289,7 @@ class UsersController extends Controller [ 'last_name', 'first_name', + 'display_name', 'email', 'jobtitle', 'username', diff --git a/app/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index fb941007ab..a4c1cdfbc6 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -31,10 +31,11 @@ class UsersTransformer $array = [ 'id' => (int) $user->id, 'avatar' => e($user->present()->gravatar) ?? null, - 'name' => e($user->getFullNameAttribute()), - 'first_name' => e($user->first_name), - 'last_name' => e($user->last_name), - 'username' => e($user->username), + 'name' => e($user->getFullNameAttribute()) ?? null, + 'first_name' => e($user->first_name) ?? null, + 'last_name' => e($user->last_name) ?? null, + 'display_name' => e($user->display_name) ?? null, + 'username' => e($user->username) ?? null, 'remote' => ($user->remote == '1') ? true : false, 'locale' => ($user->locale) ? e($user->locale) : null, 'employee_num' => ($user->employee_num) ? e($user->employee_num) : null, @@ -138,6 +139,7 @@ class UsersTransformer 'first_name' => e($user->first_name), 'last_name' => e($user->last_name), 'username' => e($user->username), + 'display_name' => e($user->display_name), 'created_by' => $user->adminuser ? [ 'id' => (int) $user->adminuser->id, 'name'=> e($user->adminuser->present()->fullName), diff --git a/app/Models/SnipeSCIMConfig.php b/app/Models/SnipeSCIMConfig.php index b7b789bf3d..7387569e10 100644 --- a/app/Models/SnipeSCIMConfig.php +++ b/app/Models/SnipeSCIMConfig.php @@ -34,6 +34,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig 'validations' => [ $user_prefix . 'userName' => 'required', + $user_prefix . 'displayName' => 'nullable|string', $user_prefix . 'name.givenName' => 'required', $user_prefix . 'name.familyName' => 'nullable|string', $user_prefix . 'externalId' => 'nullable|string', @@ -121,7 +122,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig 'honorificSuffix' => null ], - 'displayName' => null, + 'displayName' => AttributeMapping::eloquent("display_name"), 'nickName' => null, 'profileUrl' => null, 'title' => AttributeMapping::eloquent('jobtitle'), diff --git a/app/Models/User.php b/app/Models/User.php index 0c1cbe21fd..bc239063a4 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -64,6 +64,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'first_name', 'jobtitle', 'last_name', + 'display_name', 'ldap_import', 'locale', 'location_id', @@ -103,6 +104,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo protected $rules = [ 'first_name' => 'required|string|min:1|max:191', + 'last_name' => 'nullable|string|max:191', + 'display_name' => 'nullable|string|max:191', 'username' => 'required|string|min:1|unique_undeleted|max:191', 'email' => 'email|nullable|max:191', 'password' => 'required|min:8', @@ -132,15 +135,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'address', 'city', 'country', + 'display_name', 'email', 'employee_num', 'first_name', 'jobtitle', 'last_name', 'locale', + 'mobile', 'notes', 'phone', - 'mobile', 'state', 'username', 'website', @@ -157,7 +161,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'department' => ['name'], 'groups' => ['name'], 'company' => ['name'], - 'manager' => ['first_name', 'last_name', 'username'], + 'manager' => ['first_name', 'last_name', 'username', 'display_name'], ]; @@ -859,6 +863,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo { return $query->where('first_name', 'LIKE', '%' . $search . '%') ->orWhere('last_name', 'LIKE', '%' . $search . '%') + ->orWhere('display_name', 'LIKE', '%' . $search . '%') ->orWhereMultipleColumns( [ 'users.first_name', @@ -1068,6 +1073,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo ->orWhere('users.jobtitle', 'LIKE', '%' . $search . '%') ->orWhere('users.employee_num', 'LIKE', '%' . $search . '%') ->orWhere('users.username', 'LIKE', '%' . $search . '%') + ->orWhere('users.display_name', 'LIKE', '%' . $search . '%') ->orwhereRaw('CONCAT(users.first_name," ",users.last_name) LIKE \''.$search.'%\''); } diff --git a/app/Presenters/UserPresenter.php b/app/Presenters/UserPresenter.php index c60457ea05..dfa6bd7a2e 100644 --- a/app/Presenters/UserPresenter.php +++ b/app/Presenters/UserPresenter.php @@ -79,6 +79,14 @@ class UserPresenter extends Presenter 'visible' => false, 'formatter' => 'usersLinkFormatter', ], + [ + 'field' => 'display_name', + 'searchable' => true, + 'sortable' => true, + 'switchable' => false, + 'title' => trans('admin/users/table.display_name'), + 'visible' => true, + ], [ 'field' => 'jobtitle', 'searchable' => true, @@ -191,6 +199,7 @@ class UserPresenter extends Presenter 'visible' => true, 'formatter' => 'usernameRoleLinkFormatter', ], + [ 'field' => 'employee_num', 'searchable' => true, diff --git a/database/migrations/2025_08_19_114742_add_display_name_to_users.php b/database/migrations/2025_08_19_114742_add_display_name_to_users.php new file mode 100644 index 0000000000..d55e755d3a --- /dev/null +++ b/database/migrations/2025_08_19_114742_add_display_name_to_users.php @@ -0,0 +1,32 @@ +text('display_name')->after('last_name')->nullable()->default(null); + } + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + if (Schema::hasColumn('users', 'display_name')) { + $table->dropColumn('display_name'); + } + }); + } +}; diff --git a/resources/lang/en-US/admin/users/table.php b/resources/lang/en-US/admin/users/table.php index e7a5aa6490..2e2f9c7995 100644 --- a/resources/lang/en-US/admin/users/table.php +++ b/resources/lang/en-US/admin/users/table.php @@ -35,6 +35,7 @@ return array( 'total_assets_cost' => "Total Assets Cost", 'updateuser' => 'Update User', 'username' => 'Username', + 'display_name' => 'Display Name', 'user_deleted_text' => 'This user has been marked as deleted.', 'username_note' => '(This is used for Active Directory binding only, not for login.)', 'cloneuser' => 'Clone User', From 6a8e1566fe867c6f331059215d60d5eca2b4a017 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 12:56:11 +0100 Subject: [PATCH 02/15] Added display_name to a few more places Signed-off-by: snipe --- app/Http/Controllers/Api/UsersController.php | 4 ++ .../Controllers/Users/UsersController.php | 2 + app/Importer/UserImporter.php | 1 + app/Livewire/Importer.php | 8 +++ resources/views/users/edit.blade.php | 17 ++++++ resources/views/users/view.blade.php | 56 +++++++++++-------- 6 files changed, 66 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 311b35768f..133937ed75 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -517,6 +517,10 @@ class UsersController extends Controller $user->username = $request->input('username'); } + if ($request->filled('display_name')) { + $user->display_name = $request->input('display_name'); + } + if ($request->filled('email')) { $user->email = $request->input('email'); } diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 2275e565cb..35ef7d3e68 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -88,6 +88,7 @@ class UsersController extends Controller //Username, email, and password need to be handled specially because the need to respect config values on an edit. $user->email = trim($request->input('email')); $user->username = trim($request->input('username')); + $user->display_name = $request->input('display_name'); if ($request->filled('password')) { $user->password = bcrypt($request->input('password')); } @@ -240,6 +241,7 @@ class UsersController extends Controller $user->first_name = $request->input('first_name'); $user->last_name = $request->input('last_name'); + $user->display_name = $request->input('display_name'); $user->two_factor_optin = $request->input('two_factor_optin') ?: 0; $user->locale = $request->input('locale'); $user->employee_num = $request->input('employee_num'); diff --git a/app/Importer/UserImporter.php b/app/Importer/UserImporter.php index 633551c24d..942f1cf4a2 100644 --- a/app/Importer/UserImporter.php +++ b/app/Importer/UserImporter.php @@ -47,6 +47,7 @@ class UserImporter extends ItemImporter // Pull the records from the CSV to determine their values $this->item['id'] = trim($this->findCsvMatch($row, 'id')); $this->item['username'] = trim($this->findCsvMatch($row, 'username')); + $this->item['display_name'] = trim($this->findCsvMatch($row, 'display_name')); $this->item['first_name'] = trim($this->findCsvMatch($row, 'first_name')); $this->item['last_name'] = trim($this->findCsvMatch($row, 'last_name')); $this->item['email'] = trim($this->findCsvMatch($row, 'email')); diff --git a/app/Livewire/Importer.php b/app/Livewire/Importer.php index 6e6a6f1847..d86b2469c1 100644 --- a/app/Livewire/Importer.php +++ b/app/Livewire/Importer.php @@ -339,6 +339,7 @@ class Importer extends Component 'start_date' => trans('general.start_date'), 'state' => trans('general.state'), 'username' => trans('admin/users/table.username'), + 'display_name' => trans('admin/users/table.display_name'), 'vip' => trans('general.importer.vip'), 'website' => trans('general.website'), 'zip' => trans('general.zip'), @@ -485,6 +486,13 @@ class Importer extends Component 'username', trans('general.importer.checked_out_to_username'), ], + 'display_name' => + [ + 'display name', + 'displayName', + 'display', + trans('admin/users/table.display_name'), + ], 'first_name' => [ 'first name', diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index 3df806ff7a..c38393a246 100755 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -311,6 +311,23 @@
+ + +
+ +
+ + {!! $errors->first('display_name', '') !!} +
+
+ @if ((Gate::allows('canEditAuthFields', $user)) && (\App\Models\Company::canManageUsersCompanies())) @include ('partials.forms.edit.company-select', ['translated_name' => trans('general.select_company'), 'fieldname' => 'company_id']) diff --git a/resources/views/users/view.blade.php b/resources/views/users/view.blade.php index d57a216ee1..ea0017869d 100755 --- a/resources/views/users/view.blade.php +++ b/resources/views/users/view.blade.php @@ -319,34 +319,13 @@ {{ trans('admin/users/table.name') }}
- {{ $user->present()->fullName() }} + {{ $user->first_name }} {{ $user->last_name }}
- - @if (!is_null($user->company)) -
- -
- {{ trans('general.company') }} -
-
- @can('view', 'App\Models\Company') - - {{ $user->company->name }} - - @else - {{ $user->company->name }} - @endcan -
- -
- - @endif -
@@ -366,6 +345,19 @@
+ + @if ($user->display_name) +
+ +
+ {{ trans('admin/users/table.display_name') }} +
+
+ {{ $user->display_name }} +
+
+ @endif + @if (($user->address) || ($user->city) || ($user->state) || ($user->country))
@@ -394,6 +386,26 @@
@endif + + @if (!is_null($user->company)) +
+ +
+ {{ trans('general.company') }} +
+
+ @can('view', 'App\Models\Company') + + {{ $user->company->name }} + + @else + {{ $user->company->name }} + @endcan +
+ +
+ + @endif
From 0c3103e3d2ffcd4b9d7cbec97c67862b076abe72 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 12:56:30 +0100 Subject: [PATCH 03/15] Modify the getter Signed-off-by: snipe --- app/Models/SnipeModel.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/Models/SnipeModel.php b/app/Models/SnipeModel.php index f26946d22a..da2f5f7a01 100644 --- a/app/Models/SnipeModel.php +++ b/app/Models/SnipeModel.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Helpers\Helper; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; class SnipeModel extends Model @@ -155,9 +156,19 @@ class SnipeModel extends Model $this->attributes['status_id'] = $value; } - // - public function getDisplayNameAttribute() + // This gets a little twitchy since *most* things have a property in the table called "name" (but users don't) + // AND we want to be able to use the actual display_name value from the database if it's set (usually via SCIM) + protected function displayNameAttribute(): Attribute { - return $this->name; + // This override should only kick in if the model has a display_name property (users) + if (isset($this->display_name)) { + return Attribute::make( + get: fn (string $value) => $this->display_name, + ); + } + return Attribute::make( + get: fn (string $value) => $this->name, + ); } + } From 90fbf6da463a044c771131783c0aec0c80e6c5a6 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 12:56:44 +0100 Subject: [PATCH 04/15] Modify the presenter to see if they have a display_name set Signed-off-by: snipe --- app/Presenters/UserPresenter.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Presenters/UserPresenter.php b/app/Presenters/UserPresenter.php index dfa6bd7a2e..8eb28091c5 100644 --- a/app/Presenters/UserPresenter.php +++ b/app/Presenters/UserPresenter.php @@ -458,6 +458,9 @@ class UserPresenter extends Presenter */ public function fullName() { + if ($this->display_name) { + return html_entity_decode($this->display_name, ENT_QUOTES | ENT_XML1, 'UTF-8'); + } return html_entity_decode($this->first_name.' '.$this->last_name, ENT_QUOTES | ENT_XML1, 'UTF-8'); } From 270401c6934b975a0e2d2439ed6e8dcb956df971 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 13:12:57 +0100 Subject: [PATCH 05/15] Added display name to user create modal Signed-off-by: snipe --- resources/views/modals/user.blade.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/resources/views/modals/user.blade.php b/resources/views/modals/user.blade.php index 04d0c82357..e9b83fc5ae 100644 --- a/resources/views/modals/user.blade.php +++ b/resources/views/modals/user.blade.php @@ -79,6 +79,18 @@
+
+
+
+ +
+
+ + +
+
+
+
From 8b83584b67e3cfa7deb5413f94960405a622c690 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 18:31:58 +0100 Subject: [PATCH 06/15] Added mapping fields to LDAP Signed-off-by: snipe --- app/Console/Commands/LdapSync.php | 18 + app/Http/Controllers/SettingsController.php | 5 + ...4823_add_display_name_to_ldap_settings.php | 82 + .../lang/en-US/admin/settings/general.php | 9 +- resources/views/settings/ldap.blade.php | 1654 +++++++++-------- 5 files changed, 988 insertions(+), 780 deletions(-) create mode 100644 database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php diff --git a/app/Console/Commands/LdapSync.php b/app/Console/Commands/LdapSync.php index 88015b14a1..10cb402ab6 100644 --- a/app/Console/Commands/LdapSync.php +++ b/app/Console/Commands/LdapSync.php @@ -63,11 +63,17 @@ class LdapSync extends Command "emp_num" => Setting::getSettings()->ldap_emp_num, "email" => Setting::getSettings()->ldap_email, "phone" => Setting::getSettings()->ldap_phone_field, + "mobile" => Setting::getSettings()->ldap_mobile, "jobtitle" => Setting::getSettings()->ldap_jobtitle, + "address" => Setting::getSettings()->ldap_address, + "city" => Setting::getSettings()->ldap_city, + "state" => Setting::getSettings()->ldap_state, + "zip" => Setting::getSettings()->ldap_zip, "country" => Setting::getSettings()->ldap_country, "location" => Setting::getSettings()->ldap_location, "dept" => Setting::getSettings()->ldap_dept, "manager" => Setting::getSettings()->ldap_manager, + "display_name" => Setting::getSettings()->ldap_display_name, ]; $ldap_default_group = Setting::getSettings()->ldap_default_group; @@ -237,6 +243,7 @@ class LdapSync extends Command for ($i = 0; $i < $results['count']; $i++) { $item = []; $item['username'] = $results[$i][$ldap_map["username"]][0] ?? ''; + $item['display_name'] = $results[$i][$ldap_map["ldap_display_name"]][0] ?? ''; $item['employee_number'] = $results[$i][$ldap_map["emp_num"]][0] ?? ''; $item['lastname'] = $results[$i][$ldap_map["last_name"]][0] ?? ''; $item['firstname'] = $results[$i][$ldap_map["first_name"]][0] ?? ''; @@ -244,8 +251,13 @@ class LdapSync extends Command $item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? ''; $item['location_id'] = $results[$i]['location_id'] ?? ''; $item['telephone'] = $results[$i][$ldap_map["phone"]][0] ?? ''; + $item['mobile'] = $results[$i][$ldap_map["mobile"]][0] ?? ''; $item['jobtitle'] = $results[$i][$ldap_map["jobtitle"]][0] ?? ''; + $item['address'] = $results[$i][$ldap_map["ldap_address"]][0] ?? ''; + $item['city'] = $results[$i][$ldap_map["ldap_city"]][0] ?? ''; + $item['state'] = $results[$i][$ldap_map["ldap_state"]][0] ?? ''; $item['country'] = $results[$i][$ldap_map["country"]][0] ?? ''; + $item['zip'] = $results[$i][$ldap_map["ldap_zip"]][0] ?? ''; $item['department'] = $results[$i][$ldap_map["dept"]][0] ?? ''; $item['manager'] = $results[$i][$ldap_map["manager"]][0] ?? ''; $item['location'] = $results[$i][$ldap_map["location"]][0] ?? ''; @@ -278,6 +290,9 @@ class LdapSync extends Command if($ldap_map["username"] != null){ $user->username = $item['username']; } + if($ldap_map["display_name"] != null){ + $user->username = $item['display_name']; + } if($ldap_map["last_name"] != null){ $user->last_name = $item['lastname']; } @@ -293,6 +308,9 @@ class LdapSync extends Command if($ldap_map["phone"] != null){ $user->phone = $item['telephone']; } + if($ldap_map["mobile"] != null){ + $user->mobile = $item['mobile']; + } if($ldap_map["jobtitle"] != null){ $user->jobtitle = $item['jobtitle']; } diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 56b36470d4..2b12eb772a 100644 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -889,7 +889,12 @@ class SettingsController extends Controller $setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0'); $setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url'); $setting->ldap_phone_field = $request->input('ldap_phone'); + $setting->ldap_mobile = $request->input('ldap_mobile'); $setting->ldap_jobtitle = $request->input('ldap_jobtitle'); + $setting->ldap_address = $request->input('ldap_address'); + $setting->ldap_city = $request->input('ldap_city'); + $setting->ldap_state = $request->input('ldap_state'); + $setting->ldap_zip = $request->input('ldap_zip'); $setting->ldap_country = $request->input('ldap_country'); $setting->ldap_location = $request->input('ldap_location'); $setting->ldap_dept = $request->input('ldap_dept'); diff --git a/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php b/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php new file mode 100644 index 0000000000..f1a80adfb6 --- /dev/null +++ b/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php @@ -0,0 +1,82 @@ +text('ldap_display_name')->after('ldap_fname_field')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_zip')) { + $table->text('ldap_zip')->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_state')) { + $table->text('ldap_state')->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_city')) { + $table->text('ldap_city')->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_address')) { + $table->text('ldap_address')->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_mobile')) { + $table->text('ldap_mobile')->after('ldap_phone_field')->nullable()->default(null); + } + + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('settings', function (Blueprint $table) { + if (Schema::hasColumn('settings', 'ldap_display_name')) { + $table->dropColumn('ldap_display_name'); + } + }); + + Schema::table('settings', function (Blueprint $table) { + if (Schema::hasColumn('settings', 'ldap_zip')) { + $table->dropColumn('ldap_zip'); + } + }); + Schema::table('settings', function (Blueprint $table) { + if (Schema::hasColumn('settings', 'ldap_address')) { + $table->dropColumn('ldap_address'); + } + }); + Schema::table('settings', function (Blueprint $table) { + if (Schema::hasColumn('settings', 'ldap_city')) { + $table->dropColumn('ldap_city'); + } + }); + Schema::table('settings', function (Blueprint $table) { + if (Schema::hasColumn('settings', 'ldap_state')) { + $table->dropColumn('ldap_state'); + } + }); + Schema::table('settings', function (Blueprint $table) { + if (Schema::hasColumn('settings', 'ldap_mobile')) { + $table->dropColumn('ldap_mobile'); + } + }); + + + } +}; diff --git a/resources/lang/en-US/admin/settings/general.php b/resources/lang/en-US/admin/settings/general.php index 4e8143a517..8889b98aab 100644 --- a/resources/lang/en-US/admin/settings/general.php +++ b/resources/lang/en-US/admin/settings/general.php @@ -107,7 +107,7 @@ return [ 'ldap_tls_help' => 'This should be checked only if you are running STARTTLS on your LDAP server. ', 'ldap_uname' => 'LDAP Bind Username', 'ldap_dept' => 'LDAP Department', - 'ldap_phone' => 'LDAP Telephone Number', + 'ldap_phone' => 'LDAP Phone Number', 'ldap_jobtitle' => 'LDAP Job Title', 'ldap_country' => 'LDAP Country', 'ldap_pword' => 'LDAP Bind Password', @@ -116,6 +116,7 @@ return [ 'ldap_pw_sync' => 'Cache LDAP Passwords', 'ldap_pw_sync_help' => 'Uncheck this box if you do not wish to keep LDAP passwords cached as local hashed passwords. Disabling this means that your users may not be able to login if your LDAP server is unreachable for some reason.', 'ldap_username_field' => 'Username Field', + 'ldap_display_name' => 'Display Name Field', 'ldap_lname_field' => 'Last Name', 'ldap_fname_field' => 'LDAP First Name', 'ldap_auth_filter_query' => 'LDAP Authentication query', @@ -126,6 +127,11 @@ return [ 'ldap_invert_active_flag_help' => 'If enabled: when the value returned by LDAP Active Flag is 0 or false the user account will be active.', 'ldap_emp_num' => 'LDAP Employee Number', 'ldap_email' => 'LDAP Email', + 'ldap_mobile' => 'LDAP Mobile Field', + 'ldap_address' => 'LDAP Address Field', + 'ldap_city' => 'LDAP City Field', + 'ldap_state' => 'LDAP State/Province Field', + 'ldap_zip' => 'LDAP Postal Code Field', 'ldap_test' => 'Test LDAP', 'ldap_test_sync' => 'Test LDAP Synchronization', 'license' => 'Software License', @@ -463,6 +469,7 @@ return [ 'legends' => [ 'scoping' => 'Scoping', + 'mapping' => 'LDAP Field Mapping', 'formats' => 'Default Formats', 'profiles' => 'User Profiles', 'eula' => 'EULA & Acceptance Preferences', diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 27e6a20dea..b16696461e 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -65,797 +65,893 @@
-
- - -
-
- -
-
- - - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - - -
-
- -
-
- - @error('is_ad') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - -

{{ trans('admin/settings/general.ldap_pw_sync_help') }}

- @error('ldap_pw_sync') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif - -
-
- - -
-
- -
-
- -

{{ trans('admin/settings/general.ad_domain_help') }}

- @error('ad_domain') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_client_tls_key') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- -

{{ trans('admin/settings/general.ldap_client_tls_cert_help') }}

- @error('ldap_client_tls_cert') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_server') - - - {{ $message }} - - @enderror - -

{{ trans('admin/settings/general.ldap_server_help') }}

- - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_tls') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_server_cert_ignore') - - - {{ $message }} - - @enderror - -

- {{ trans('admin/settings/general.ldap_server_cert_help') }} -

- @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_uname') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_pword') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_basedn') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_filter') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_username_field') - - - {!! $message !!} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_lname_field') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_fname_field') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - - @error('ldap_auth_filter_query') - - - {!! $message !!} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - - -
-
- -
- -
- - @if ($groups->count()) - @if ((Config::get('app.lock_passwords') || (!Auth::user()->isSuperUser()))) -
    - @foreach ($groups as $id => $group) - {!! '
  • '.e($group).'
  • ' !!} - @endforeach -
- - {{ trans('admin/users/general.group_memberships_helpblock') }} - @else -
- - - - {{ trans('admin/settings/general.ldap_default_group_info') }} - -
- @endif - @else -

{!! trans('admin/settings/general.no_groups') !!}

- @endif - -
-
- - -
-
- -
-
- -

{!! trans('admin/settings/general.ldap_activated_flag_help') !!}

- - @error('ldap_active_flag') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_invert_active_flag') - - - {{ $message }} - - @enderror - -

- {!! trans('admin/settings/general.ldap_invert_active_flag_help') !!} -

- - @if (config('app.lock_passwords')===true) -

- - {!! trans('general.feature_disabled') !!} -

- @endif -
- -
- - -
-
- -
-
- - @error('ldap_emp_num') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- -
-
- -
-
- - - @error('ldap_dept') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- -
-
- -
-
- - @error('ldap_manager') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_email') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_phone') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_jobtitle') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- - -
-
- -
-
- - @error('ldap_country') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- -
-
- -
-
- -

{!! trans('admin/settings/general.ldap_location_help') !!}

- @error('ldap_location') - - - {{ $message }} - - @enderror - - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
- @if ($setting->ldap_enabled) - - -
-
- -
- -
-
- -
-
-

{{ trans('admin/settings/general.ldap_login_sync_help') }}

- @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
- -
- - -
-
- -
-
-
-
- -
-
- -
+
+ +
+ + {{ trans('admin/settings/general.legends.general') }} + + +
- {{ trans('admin/settings/general.ldap_test') }} + +
+
+ + + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + + +
+
+ +
+
+ + @error('is_ad') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + +

{{ trans('admin/settings/general.ldap_pw_sync_help') }}

+ @error('ldap_pw_sync') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif + +
+
+ + +
+
+ +
+
+ +

{{ trans('admin/settings/general.ad_domain_help') }}

+ @error('ad_domain') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_client_tls_key') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ +

{{ trans('admin/settings/general.ldap_client_tls_cert_help') }}

+ @error('ldap_client_tls_cert') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_server') + + + {{ $message }} + + @enderror + +

{{ trans('admin/settings/general.ldap_server_help') }}

+ + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_tls') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_server_cert_ignore') + + + {{ $message }} + + @enderror + +

+ {{ trans('admin/settings/general.ldap_server_cert_help') }} +

+ @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_uname') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_pword') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_basedn') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_filter') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+
+ +
+ + {{ trans('admin/settings/general.legends.mapping') }} + + +
+
+ +
+
+ + @error('ldap_username_field') + + + {!! $message !!} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_lname_field') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_fname_field') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + + @error('ldap_auth_filter_query') + + + {!! $message !!} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + + +
+
+
+
-
-
-
- - - -
-
-

{{ trans('admin/settings/general.ldap_login_test_help') }}

+ @if ($groups->count()) + @if ((Config::get('app.lock_passwords') || (!Auth::user()->isSuperUser()))) +
    + @foreach ($groups as $id => $group) + {!! '
  • '.e($group).'
  • ' !!} + @endforeach +
+ + {{ trans('admin/users/general.group_memberships_helpblock') }} + @else +
+ + + + {{ trans('admin/settings/general.ldap_default_group_info') }} + +
+ @endif + @else +

{!! trans('admin/settings/general.no_groups') !!}

+ @endif + +
-
+ +
+
+ +
+
+ +

{!! trans('admin/settings/general.ldap_activated_flag_help') !!}

+ + @error('ldap_active_flag') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_invert_active_flag') + + + {{ $message }} + + @enderror + +

+ {!! trans('admin/settings/general.ldap_invert_active_flag_help') !!} +

+ + @if (config('app.lock_passwords')===true) +

+ + {!! trans('general.feature_disabled') !!} +

+ @endif +
+ +
+ + +
+
+ +
+
+ + @error('ldap_emp_num') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ +
+
+ +
+
+ + + @error('ldap_dept') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ +
+
+ +
+
+ + @error('ldap_manager') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_email') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_phone') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_mobile') + + + {{ $message }} + + @enderror +
+
+ + +
+
+ +
+
+ + @error('ldap_jobtitle') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ + +
+
+ +
+
+ + @error('ldap_address') + + + {{ $message }} + + @enderror +
+
+ + +
+
+ +
+
+ + @error('ldap_city') + + + {{ $message }} + + @enderror +
+
+ + +
+
+ +
+
+ + @error('ldap_state') + + + {{ $message }} + + @enderror +
+
+ + +
+
+ +
+
+ + @error('ldap_zip') + + + {{ $message }} + + @enderror +
+
- @endif + +
+
+ +
+
+ + @error('ldap_country') + + + {{ $message }} + + @enderror - -
-
- -
-
- -

{{ trans('admin/settings/general.custom_forgot_pass_url_help') }}

- @error('custom_forgot_pass_url') - - - {{ $message }} - - @enderror + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
- @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
-
+ +
+
+ +
+
+ +

{!! trans('admin/settings/general.ldap_location_help') !!}

+ @error('ldap_location') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ +
+ + {{ trans('admin/settings/general.legends.misc') }} + + @if ($setting->ldap_enabled) + + +
+
+ +
+ +
+
+ +
+
+

{{ trans('admin/settings/general.ldap_login_sync_help') }}

+ @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+ +
+ + +
+
+ +
+ +
+ + + +
+
+

{{ trans('admin/settings/general.ldap_login_test_help') }}

+
+ +
+ + + @endif + + +
+
+ +
+
+ +

{{ trans('admin/settings/general.custom_forgot_pass_url_help') }}

+ @error('custom_forgot_pass_url') + + + {{ $message }} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+ +
+ + +
+
+ +
+
+ + + @error('ldap_auth_filter_query') + + + {!! $message !!} + + @enderror + + @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+
+
+ + {{ trans('admin/settings/general.legends.test') }} + + @if ($setting->ldap_enabled) + + +
+
+ +
+ +
+
+ +
+
+

{{ trans('admin/settings/general.ldap_login_sync_help') }}

+ @if (config('app.lock_passwords')===true) +

+ + {{ trans('general.feature_disabled') }} +

+ @endif +
+ +
+ + +
+
+ +
+ +
+ + + +
+
+

{{ trans('admin/settings/general.ldap_login_test_help') }}

+
+ +
+ + + @endif + +
+
{{ trans('admin/settings/general.legends.mapping') }} @@ -420,12 +510,6 @@ @enderror - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif
@@ -443,12 +527,6 @@ @enderror - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif
@@ -466,39 +544,27 @@ @enderror - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif - -
+ +
- +
- - - @error('ldap_auth_filter_query') - - - {!! $message !!} - + + @error('ldap_display_name') + + + {{ $message }} + @enderror - @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif
+
@@ -863,70 +929,11 @@
+
{{ trans('admin/settings/general.legends.misc') }} - @if ($setting->ldap_enabled) - - -
-
- -
- -
-
- -
-
-

{{ trans('admin/settings/general.ldap_login_sync_help') }}

- @if (config('app.lock_passwords')===true) -

- - {{ trans('general.feature_disabled') }} -

- @endif -
- -
- - -
-
- -
- -
- - - -
-
-

{{ trans('admin/settings/general.ldap_login_test_help') }}

-
- -
- - - @endif -
From 0823c23a6ee87f540972cf36b4d19e128cc1c698 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 18:51:56 +0100 Subject: [PATCH 08/15] Fixed placeholder text Signed-off-by: snipe --- resources/views/settings/ldap.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 5c58a650e4..ecd69556ae 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -784,7 +784,7 @@
- + @error('ldap_mobile') From 2d6270c697d6f1ad7f9931ffd9c8d52e50e20d39 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 19:19:29 +0100 Subject: [PATCH 09/15] Updated validation, switch to string() as db field type Signed-off-by: snipe --- app/Models/User.php | 6 +++--- ...8_19_174823_add_display_name_to_ldap_settings.php | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index bc239063a4..5374b5e284 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -116,9 +116,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'start_date' => 'nullable|date_format:Y-m-d', 'end_date' => 'nullable|date_format:Y-m-d|after_or_equal:start_date', 'autoassign_licenses' => 'boolean', - 'address' => 'max:191|nullable', - 'city' => 'max:191|nullable', - 'state' => 'min:2|max:191|nullable', + 'address' => 'nullable|string|max:191', + 'city' => 'nullable|string|max:191', + 'state' => 'nullable|string|max:191', 'country' => 'min:2|max:191|nullable', 'zip' => 'max:10|nullable', 'vip' => 'boolean', diff --git a/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php b/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php index f1a80adfb6..fb980af6dd 100644 --- a/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php +++ b/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php @@ -14,27 +14,27 @@ return new class extends Migration Schema::table('settings', function (Blueprint $table) { if (!Schema::hasColumn('settings', 'ldap_display_name')) { - $table->text('ldap_display_name')->after('ldap_fname_field')->nullable()->default(null); + $table->string('ldap_display_name', 191)->after('ldap_fname_field')->nullable()->default(null); } if (!Schema::hasColumn('settings', 'ldap_zip')) { - $table->text('ldap_zip')->after('ldap_manager')->nullable()->default(null); + $table->string('ldap_zip', 191)->after('ldap_manager')->nullable()->default(null); } if (!Schema::hasColumn('settings', 'ldap_state')) { - $table->text('ldap_state')->after('ldap_manager')->nullable()->default(null); + $table->string('ldap_state', 191)->after('ldap_manager')->nullable()->default(null); } if (!Schema::hasColumn('settings', 'ldap_city')) { - $table->text('ldap_city')->after('ldap_manager')->nullable()->default(null); + $table->string('ldap_city', 191)->after('ldap_manager')->nullable()->default(null); } if (!Schema::hasColumn('settings', 'ldap_address')) { - $table->text('ldap_address')->after('ldap_manager')->nullable()->default(null); + $table->string('ldap_address', 191)->after('ldap_manager')->nullable()->default(null); } if (!Schema::hasColumn('settings', 'ldap_mobile')) { - $table->text('ldap_mobile')->after('ldap_phone_field')->nullable()->default(null); + $table->string('ldap_mobile', 191)->after('ldap_phone_field')->nullable()->default(null); } }); From 1b42abcc9826e7c869c8fc67a0678cbd0c319048 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 19:54:32 +0100 Subject: [PATCH 10/15] Fixed mapping Signed-off-by: snipe --- app/Console/Commands/LdapSync.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Commands/LdapSync.php b/app/Console/Commands/LdapSync.php index 10cb402ab6..b8ea2eb986 100644 --- a/app/Console/Commands/LdapSync.php +++ b/app/Console/Commands/LdapSync.php @@ -291,7 +291,7 @@ class LdapSync extends Command $user->username = $item['username']; } if($ldap_map["display_name"] != null){ - $user->username = $item['display_name']; + $user->display_name = $item['display_name']; } if($ldap_map["last_name"] != null){ $user->last_name = $item['lastname']; From c2ecd20b7d55cfecb91e6589ec6daaa4ce31afdd Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 20:47:48 +0100 Subject: [PATCH 11/15] Updated field text Signed-off-by: snipe --- .../lang/en-US/admin/settings/general.php | 26 +++--- resources/views/settings/ldap.blade.php | 85 ++++++++++--------- 2 files changed, 56 insertions(+), 55 deletions(-) diff --git a/resources/lang/en-US/admin/settings/general.php b/resources/lang/en-US/admin/settings/general.php index 32b35d79f2..842fe5e338 100644 --- a/resources/lang/en-US/admin/settings/general.php +++ b/resources/lang/en-US/admin/settings/general.php @@ -93,11 +93,11 @@ return [ 'ldap_integration' => 'LDAP Integration', 'ldap_settings' => 'LDAP Settings', 'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.', - 'ldap_location' => 'LDAP Location', -'ldap_location_help' => 'The Ldap Location field should be used if an OU is not being used in the Base Bind DN. Leave this blank if an OU search is being used.', + 'ldap_location' => 'LDAP Location Field', +'ldap_location_help' => 'The LDAP Location field should be used if an OU is not being used in the Base Bind DN. Leave this blank if an OU search is being used.', 'ldap_login_test_help' => 'Enter a valid LDAP username and password from the base DN you specified above to test whether your LDAP login is configured correctly. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.', 'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.', - 'ldap_manager' => 'LDAP Manager', + 'ldap_manager' => 'LDAP Manager Field', 'ldap_server' => 'LDAP Server', 'ldap_server_help' => 'This should start with ldap:// (for unencrypted) or ldaps:// (for TLS or SSL)', 'ldap_server_cert' => 'LDAP SSL certificate validation', @@ -106,27 +106,27 @@ return [ 'ldap_tls' => 'Use TLS', 'ldap_tls_help' => 'This should be checked only if you are running STARTTLS on your LDAP server. ', 'ldap_uname' => 'LDAP Bind Username', - 'ldap_dept' => 'LDAP Department', - 'ldap_phone' => 'LDAP Phone Number', - 'ldap_jobtitle' => 'LDAP Job Title', - 'ldap_country' => 'LDAP Country', + 'ldap_dept' => 'LDAP Department Field', + 'ldap_phone' => 'LDAP Phone Number Field', + 'ldap_jobtitle' => 'LDAP Job Title Field', + 'ldap_country' => 'LDAP Country Field', 'ldap_pword' => 'LDAP Bind Password', 'ldap_basedn' => 'Base Bind DN', 'ldap_filter' => 'LDAP Filter', 'ldap_pw_sync' => 'Cache LDAP Passwords', 'ldap_pw_sync_help' => 'Uncheck this box if you do not wish to keep LDAP passwords cached as local hashed passwords. Disabling this means that your users may not be able to login if your LDAP server is unreachable for some reason.', - 'ldap_username_field' => 'Username Field', - 'ldap_display_name' => 'Display Name Field', - 'ldap_lname_field' => 'Last Name', - 'ldap_fname_field' => 'LDAP First Name', + 'ldap_username_field' => 'LDAP Username Field', + 'ldap_display_name' => 'LDAP Display Name Field', + 'ldap_lname_field' => 'LDAP Last Name Field', + 'ldap_fname_field' => 'LDAP First Name Field', 'ldap_auth_filter_query' => 'LDAP Authentication query', 'ldap_version' => 'LDAP Version', 'ldap_active_flag' => 'LDAP Active Flag', 'ldap_activated_flag_help' => 'This value is used to determine whether a synced user can login to Snipe-IT. It does not affect the ability to check items in or out to them, and should be the attribute name within your AD/LDAP, not the value.

If this field is set to a field name that does not exist in your AD/LDAP, or the value in the AD/LDAP field is set to 0 or false, user login will be disabled. If the value in the AD/LDAP field is set to 1 or true or any other text means the user can log in. When the field is blank in your AD, we respect the userAccountControl attribute, which usually allows non-suspended users to log in.', 'ldap_invert_active_flag' => 'LDAP Invert Active Flag', 'ldap_invert_active_flag_help' => 'If enabled: when the value returned by LDAP Active Flag is 0 or false the user account will be active.', - 'ldap_emp_num' => 'LDAP Employee Number', - 'ldap_email' => 'LDAP Email', + 'ldap_emp_num' => 'LDAP Employee Number Field', + 'ldap_email' => 'LDAP Email Field', 'ldap_mobile' => 'LDAP Mobile Field', 'ldap_address' => 'LDAP Address Field', 'ldap_city' => 'LDAP City Field', diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index ecd69556ae..3673e782fc 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -425,6 +425,47 @@
+ + +
+
+ +
+ +
+ + @if ($groups->count()) + @if ((Config::get('app.lock_passwords') || (!Auth::user()->isSuperUser()))) +
    + @foreach ($groups as $id => $group) + {!! '
  • '.e($group).'
  • ' !!} + @endforeach +
+ + {{ trans('admin/users/general.group_memberships_helpblock') }} + @else +
+ + + + {{ trans('admin/settings/general.ldap_default_group_info') }} + +
+ @endif + @else +

{!! trans('admin/settings/general.no_groups') !!}

+ @endif + +
+
+
@@ -491,6 +532,7 @@ @endif +
@@ -553,7 +595,7 @@
- + @error('ldap_display_name') @@ -565,47 +607,6 @@
- - -
-
- -
- -
- - @if ($groups->count()) - @if ((Config::get('app.lock_passwords') || (!Auth::user()->isSuperUser()))) -
    - @foreach ($groups as $id => $group) - {!! '
  • '.e($group).'
  • ' !!} - @endforeach -
- - {{ trans('admin/users/general.group_memberships_helpblock') }} - @else -
- - - - {{ trans('admin/settings/general.ldap_default_group_info') }} - -
- @endif - @else -

{!! trans('admin/settings/general.no_groups') !!}

- @endif - -
-
-
From 07b25fe376037771001c33b07779a184a3cb46a3 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 20:52:18 +0100 Subject: [PATCH 12/15] Add display name to summary Signed-off-by: snipe --- resources/views/settings/ldap.blade.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 3673e782fc..19051f653b 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -1136,6 +1136,7 @@ var keys = [ '{{ trans('admin/settings/general.employee_number') }}', '{{ trans('mail.username') }}', + '{{ trans('admin/settings/general.ldap_display_name') }}', '{{ trans('general.first_name') }}', '{{ trans('general.last_name') }}', '{{ trans('general.email') }}' @@ -1152,7 +1153,7 @@ { let body = '' for (var i in users) { - body += '' + users[i].employee_number + '' + users[i].username + '' + users[i].firstname + '' + users[i].lastname + '' + users[i].email + '' + body += '' + users[i].employee_number + '' + users[i].username + '' + users[i].display_name + '' + users[i].firstname + '' + users[i].lastname + '' + users[i].email + '' } body += "" return body; From 56e687bed2843aeba52e0708ee65333439c7c689 Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 09:33:00 +0100 Subject: [PATCH 13/15] Retuen the display name in the API call Signed-off-by: snipe --- app/Http/Controllers/Api/SettingsController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/Api/SettingsController.php b/app/Http/Controllers/Api/SettingsController.php index 134d24ef2a..3e48eb23f1 100644 --- a/app/Http/Controllers/Api/SettingsController.php +++ b/app/Http/Controllers/Api/SettingsController.php @@ -51,6 +51,7 @@ class SettingsController extends Controller })->slice(0, 10)->map(function ($item) use ($settings) { return (object) [ 'username' => $item[$settings['ldap_username_field']][0] ?? null, + 'display_name' => $item[$settings['ldap_display_name']][0] ?? null, 'employee_number' => $item[$settings['ldap_emp_num']][0] ?? null, 'lastname' => $item[$settings['ldap_lname_field']][0] ?? null, 'firstname' => $item[$settings['ldap_fname_field']][0] ?? null, From c07ef4d87f57fa56d263d321a0f8de3a3bc698ff Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 21 Aug 2025 09:25:42 +0100 Subject: [PATCH 14/15] A few small tweaks Signed-off-by: snipe --- app/Console/Commands/LdapSync.php | 8 ++++---- app/Http/Controllers/SettingsController.php | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/Console/Commands/LdapSync.php b/app/Console/Commands/LdapSync.php index b8ea2eb986..f79988e2a3 100644 --- a/app/Console/Commands/LdapSync.php +++ b/app/Console/Commands/LdapSync.php @@ -243,7 +243,7 @@ class LdapSync extends Command for ($i = 0; $i < $results['count']; $i++) { $item = []; $item['username'] = $results[$i][$ldap_map["username"]][0] ?? ''; - $item['display_name'] = $results[$i][$ldap_map["ldap_display_name"]][0] ?? ''; + $item['display_name'] = $results[$i][$ldap_map["display_name"]][0] ?? ''; $item['employee_number'] = $results[$i][$ldap_map["emp_num"]][0] ?? ''; $item['lastname'] = $results[$i][$ldap_map["last_name"]][0] ?? ''; $item['firstname'] = $results[$i][$ldap_map["first_name"]][0] ?? ''; @@ -254,10 +254,10 @@ class LdapSync extends Command $item['mobile'] = $results[$i][$ldap_map["mobile"]][0] ?? ''; $item['jobtitle'] = $results[$i][$ldap_map["jobtitle"]][0] ?? ''; $item['address'] = $results[$i][$ldap_map["ldap_address"]][0] ?? ''; - $item['city'] = $results[$i][$ldap_map["ldap_city"]][0] ?? ''; - $item['state'] = $results[$i][$ldap_map["ldap_state"]][0] ?? ''; + $item['city'] = $results[$i][$ldap_map["city"]][0] ?? ''; + $item['state'] = $results[$i][$ldap_map["state"]][0] ?? ''; $item['country'] = $results[$i][$ldap_map["country"]][0] ?? ''; - $item['zip'] = $results[$i][$ldap_map["ldap_zip"]][0] ?? ''; + $item['zip'] = $results[$i][$ldap_map["zip"]][0] ?? ''; $item['department'] = $results[$i][$ldap_map["dept"]][0] ?? ''; $item['manager'] = $results[$i][$ldap_map["manager"]][0] ?? ''; $item['location'] = $results[$i][$ldap_map["location"]][0] ?? ''; diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 2b12eb772a..8c57efa5eb 100644 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -873,6 +873,7 @@ class SettingsController extends Controller $setting->ldap_default_group = $request->input('ldap_default_group'); $setting->ldap_filter = $request->input('ldap_filter'); $setting->ldap_username_field = $request->input('ldap_username_field'); + $setting->ldap_display_name = $request->input('ldap_display_name'); $setting->ldap_lname_field = $request->input('ldap_lname_field'); $setting->ldap_fname_field = $request->input('ldap_fname_field'); $setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query'); From fc091c11742dbe9e41d2fc1ec956284adebddbb8 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 21 Aug 2025 09:29:12 +0100 Subject: [PATCH 15/15] Added comments Signed-off-by: snipe --- app/Console/Commands/LdapSync.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Console/Commands/LdapSync.php b/app/Console/Commands/LdapSync.php index f79988e2a3..7ad4648702 100644 --- a/app/Console/Commands/LdapSync.php +++ b/app/Console/Commands/LdapSync.php @@ -55,6 +55,8 @@ class LdapSync extends Command ini_set('max_execution_time', env('LDAP_TIME_LIM', 600)); //600 seconds = 10 minutes ini_set('memory_limit', env('LDAP_MEM_LIM', '500M')); + + // Map the LDAP attributes to the Snipe-IT user fields. $ldap_map = [ "username" => Setting::getSettings()->ldap_username_field, "last_name" => Setting::getSettings()->ldap_lname_field, @@ -240,6 +242,7 @@ class LdapSync extends Command } + // Assign the mapped LDAP attributes for each user to the Snipe-IT user fields for ($i = 0; $i < $results['count']; $i++) { $item = []; $item['username'] = $results[$i][$ldap_map["username"]][0] ?? '';