From b264bbf69fc3126cc88598797b176c88bb87de52 Mon Sep 17 00:00:00 2001 From: Nicky West Date: Mon, 28 Jul 2025 15:55:37 -0700 Subject: [PATCH 01/51] feat(api): Add API endpoints for managing asset history notes - Add POST endpoint to create a history note attached to an asset - Add GET endpoint to retrieve history notes for an asset - Add ActionLog factory state for manual notes - Implement controller methods with authorization checks - Add feature tests for note creation, retrieval, and access control - Register new API routes for these endpoints Supports automation by enabling programmatic asset history note management. --- app/Http/Controllers/Api/NotesController.php | 119 +++++++++++++++++++ database/factories/ActionlogFactory.php | 22 ++++ routes/api.php | 22 ++++ tests/Feature/Assets/Api/AssetNotesTest.php | 88 ++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 app/Http/Controllers/Api/NotesController.php create mode 100644 tests/Feature/Assets/Api/AssetNotesTest.php diff --git a/app/Http/Controllers/Api/NotesController.php b/app/Http/Controllers/Api/NotesController.php new file mode 100644 index 0000000000..023c399ad5 --- /dev/null +++ b/app/Http/Controllers/Api/NotesController.php @@ -0,0 +1,119 @@ +authorize('update', Asset::class); + + if ($request->input('note', '') == '') { + return response()->json(Helper::formatStandardApiResponse('error', null, trans('validation.required', ['attribute' => 'note'])), 422); + } + + try { + $asset = Asset::findOrFail($asset_id); + } catch (ModelNotFoundException $e) { + return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 404); + } catch (\Exception $e) { + Log::debug('Error fetching asset: ' . $e->getMessage()); + + // Return generic server error response since something unexpected happened + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/settings/message.webhook.500')), 500); + } + + $this->authorize('update', $asset); + + // Create the note + $logaction = new ActionLog(); + $logaction->item_type = get_class($asset); + $logaction->created_by = Auth::id(); + $logaction->item_id = $asset->id; + $logaction->note = $request->input('note', ''); + + if($logaction->logaction('note added')) { + // Return a success response + return response()->json(Helper::formatStandardApiResponse('success', ['note' => $logaction->note, 'item_id' => $asset->id], trans('general.note_added'))); + } + + // Return an error response if something went wrong + return response()->json(Helper::formatStandardApiResponse('error', null, 'Something went wrong'), 500); + } + + /** + * Retrieve a list of manual notes (action logs) for a given asset. + * + * Checks authorization to view assets, attempts to find the asset by ID, + * and fetches related action log entries of type 'note added', including + * user information for each note. Returns a JSON response with the notes or errors. + * + * @param \Illuminate\Http\Request $request The incoming HTTP request. + * @param int|string $asset_id The ID of the asset whose notes to retrieve. + * @return \Illuminate\Http\JsonResponse + */ + public function getList(Request $request, $asset_id): JsonResponse + { + $this->authorize('view', Asset::class); + + try { + $asset = Asset::findOrFail($asset_id); + } catch (ModelNotFoundException $e) { + return response()->json(Helper::formatStandardApiResponse('error', null, $e->getMessage()), 404); + } catch (\Exception $e) { + // Return generic server error response since something unexpected happened + return response()->json(Helper::formatStandardApiResponse('error', null, $e->getMessage()), 500); + } + + $this->authorize('view', $asset); + + // Get the manual notes for the asset + $notes = ActionLog::with('user:id,username') + ->where('item_type', Asset::class) + ->where('item_id', $asset->id) + ->where('action_type', 'note added') + ->orderBy('created_at', 'desc') + ->get(['id', 'created_at', 'note', 'created_by', 'item_id', 'item_type', 'action_type', 'target_id', 'target_type']); + + $notesArray = $notes->map(function ($note) { + return [ + 'id' => $note->id, + 'created_at' => $note->created_at, + 'note' => $note->note, + 'created_by' => $note->created_by, + 'username' => $note->user?->username, // adding the username + 'item_id' => $note->item_id, + 'item_type' => $note->item_type, + 'action_type' => $note->action_type, + ]; + }); + + // Return a success response + return response()->json(Helper::formatStandardApiResponse('success', ['notes' => $notesArray, 'asset_id' => $asset->id])); + } +} diff --git a/database/factories/ActionlogFactory.php b/database/factories/ActionlogFactory.php index ad07f7082b..9c41f2c2d5 100644 --- a/database/factories/ActionlogFactory.php +++ b/database/factories/ActionlogFactory.php @@ -84,6 +84,28 @@ class ActionlogFactory extends Factory }); } + /** + * This sets up an ActionLog representing a manually added note tied to an Asset, + * with an optional User as the creator. If no User is provided, one is generated. + * + * @param User|null $user Optional user to associate as the creator of the note. + * @return \Illuminate\Database\Eloquent\Factories\Factory + */ + public function assetNote(?User $user = null) + { + return $this + ->state(function (array $attributes) use ($user) { + return [ + 'action_type' => 'note added', + 'item_type' => Asset::class, + 'target_type' => 'asset', + 'note' => 'Factory-generated manual note', + 'created_by' => $user?->id ?? User::factory(), + ]; + }) + ->for($user ?? User::factory(), 'user'); + } + public function licenseCheckoutToUser() { return $this->state(function () { diff --git a/routes/api.php b/routes/api.php index eeb644d13a..5609508526 100644 --- a/routes/api.php +++ b/routes/api.php @@ -841,6 +841,28 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu ); // end asset models API routes + /** + * Asset notes API routes + */ + Route::group(['prefix' => 'notes'], function () { + + Route::post( + '{asset_id}/store', + [ + Api\NotesController::class, + 'store' + ] + )->name('api.notes.store'); + + Route::get( + '{asset_id}/getList', + [ + Api\NotesController::class, + 'getList' + ] + )->name('api.notes.getList'); + } + ); // end asset notes API routes /** * Settings API routes diff --git a/tests/Feature/Assets/Api/AssetNotesTest.php b/tests/Feature/Assets/Api/AssetNotesTest.php new file mode 100644 index 0000000000..906c5debf7 --- /dev/null +++ b/tests/Feature/Assets/Api/AssetNotesTest.php @@ -0,0 +1,88 @@ +actingAsForApi(User::factory()->editAssets()->create()) + ->postJson(route('api.notes.store', 123456789)) + ->assertStatusMessageIs('error'); + } + + public function testRequiresPermissionToAddNoteToAssetAsset() + { + $asset = Asset::factory()->create(); + + $this->actingAsForApi(User::factory()->create()) + ->postJson(route('api.notes.store', $asset->id), [ + 'note' => 'test' + ]) + ->assertForbidden(); + } + + public function testAssetNoteIsSaved() + { + $asset = Asset::factory()->create(); + + $this->actingAsForApi(User::factory()->editAssets()->create()) + ->postJson(route('api.notes.store', ['asset_id' => $asset->id]), [ + 'note' => 'This is a test note.' + ]) + ->assertStatusMessageIs('success') + ->assertJson([ + 'messages' => trans('general.note_added'), + 'payload' => [ + 'note' => 'This is a test note.', + 'item_id' => e($asset->id), + ], + ]) + ->assertStatus(200); + + $note = ActionLog::where('item_id', $asset->id) + ->where('action_type', 'note added') + ->first(); + + $this->assertNotNull($note, 'The note was not saved in the database.'); + $this->assertEquals('This is a test note.', $note->note, 'The note content does not match.'); + } + + public function testAssetNotesAreRetrievable() + { + $asset = Asset::factory()->create(); + + $user = User::factory()->viewAssets()->create(); + + $assetNote = Actionlog::factory() + ->assetNote($user) + ->create([ + 'item_id' => $asset->id, + 'note' => 'This is a test note.', + ]); + + $this->actingAsForApi($user) + ->getJson(route('api.notes.getList', ['asset_id' => $asset->id])) + ->assertOk() + ->assertJson([ + 'messages' => null, + 'payload' => [ + 'notes' => [ + [ + 'note' => 'This is a test note.', + 'created_by' => $assetNote->created_by, + 'username' => $user->username, + 'item_id' => $assetNote->item_id, + 'item_type' => Asset::class, + 'action_type' => 'note added', + ] + ] + ], + ]); + } +} From 822f9a6f283930791576d465077b916733f82e62 Mon Sep 17 00:00:00 2001 From: Nicky West Date: Mon, 28 Jul 2025 16:37:08 -0700 Subject: [PATCH 02/51] Fixed deviations from code standards --- app/Http/Controllers/Api/NotesController.php | 14 +++++++------- database/factories/ActionlogFactory.php | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/Api/NotesController.php b/app/Http/Controllers/Api/NotesController.php index 023c399ad5..9f5f5415a6 100644 --- a/app/Http/Controllers/Api/NotesController.php +++ b/app/Http/Controllers/Api/NotesController.php @@ -26,10 +26,10 @@ class NotesController extends Controller * Returns JSON responses indicating success or failure with appropriate HTTP status codes. * * @param \Illuminate\Http\Request $request The incoming HTTP request containing the 'note'. - * @param int|string $asset_id The ID of the asset to attach the note to. + * @param int|string $assetId The ID of the asset to attach the note to. * @return \Illuminate\Http\JsonResponse */ - public function store(Request $request, $asset_id): JsonResponse + public function store(Request $request, $assetId): JsonResponse { $this->authorize('update', Asset::class); @@ -38,7 +38,7 @@ class NotesController extends Controller } try { - $asset = Asset::findOrFail($asset_id); + $asset = Asset::findOrFail($assetId); } catch (ModelNotFoundException $e) { return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 404); } catch (\Exception $e) { @@ -57,7 +57,7 @@ class NotesController extends Controller $logaction->item_id = $asset->id; $logaction->note = $request->input('note', ''); - if($logaction->logaction('note added')) { + if ($logaction->logaction('note added')) { // Return a success response return response()->json(Helper::formatStandardApiResponse('success', ['note' => $logaction->note, 'item_id' => $asset->id], trans('general.note_added'))); } @@ -74,15 +74,15 @@ class NotesController extends Controller * user information for each note. Returns a JSON response with the notes or errors. * * @param \Illuminate\Http\Request $request The incoming HTTP request. - * @param int|string $asset_id The ID of the asset whose notes to retrieve. + * @param int|string $assetId The ID of the asset whose notes to retrieve. * @return \Illuminate\Http\JsonResponse */ - public function getList(Request $request, $asset_id): JsonResponse + public function getList(Request $request, $assetId): JsonResponse { $this->authorize('view', Asset::class); try { - $asset = Asset::findOrFail($asset_id); + $asset = Asset::findOrFail($assetId); } catch (ModelNotFoundException $e) { return response()->json(Helper::formatStandardApiResponse('error', null, $e->getMessage()), 404); } catch (\Exception $e) { diff --git a/database/factories/ActionlogFactory.php b/database/factories/ActionlogFactory.php index 9c41f2c2d5..4773b39532 100644 --- a/database/factories/ActionlogFactory.php +++ b/database/factories/ActionlogFactory.php @@ -91,10 +91,10 @@ class ActionlogFactory extends Factory * @param User|null $user Optional user to associate as the creator of the note. * @return \Illuminate\Database\Eloquent\Factories\Factory */ - public function assetNote(?User $user = null) + public function assetNote(?User $user=null) { return $this - ->state(function (array $attributes) use ($user) { + ->state(function () use ($user) { return [ 'action_type' => 'note added', 'item_type' => Asset::class, From 16fdb16a5699cf1bb3e149874d26450f3e082633 Mon Sep 17 00:00:00 2001 From: Nicky West Date: Mon, 28 Jul 2025 16:55:11 -0700 Subject: [PATCH 03/51] Changed over to route model binding and simplified logic & gates --- app/Http/Controllers/Api/NotesController.php | 34 +++----------------- routes/api.php | 4 +-- tests/Feature/Assets/Api/AssetNotesTest.php | 8 ++--- 3 files changed, 11 insertions(+), 35 deletions(-) diff --git a/app/Http/Controllers/Api/NotesController.php b/app/Http/Controllers/Api/NotesController.php index 9f5f5415a6..965eec96dd 100644 --- a/app/Http/Controllers/Api/NotesController.php +++ b/app/Http/Controllers/Api/NotesController.php @@ -26,30 +26,17 @@ class NotesController extends Controller * Returns JSON responses indicating success or failure with appropriate HTTP status codes. * * @param \Illuminate\Http\Request $request The incoming HTTP request containing the 'note'. - * @param int|string $assetId The ID of the asset to attach the note to. + * @param Asset $asset The ID of the asset to attach the note to. * @return \Illuminate\Http\JsonResponse */ - public function store(Request $request, $assetId): JsonResponse + public function store(Request $request, Asset $asset): JsonResponse { - $this->authorize('update', Asset::class); + $this->authorize('update', $asset); if ($request->input('note', '') == '') { return response()->json(Helper::formatStandardApiResponse('error', null, trans('validation.required', ['attribute' => 'note'])), 422); } - try { - $asset = Asset::findOrFail($assetId); - } catch (ModelNotFoundException $e) { - return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 404); - } catch (\Exception $e) { - Log::debug('Error fetching asset: ' . $e->getMessage()); - - // Return generic server error response since something unexpected happened - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/settings/message.webhook.500')), 500); - } - - $this->authorize('update', $asset); - // Create the note $logaction = new ActionLog(); $logaction->item_type = get_class($asset); @@ -74,22 +61,11 @@ class NotesController extends Controller * user information for each note. Returns a JSON response with the notes or errors. * * @param \Illuminate\Http\Request $request The incoming HTTP request. - * @param int|string $assetId The ID of the asset whose notes to retrieve. + * @param Asset $asset The ID of the asset whose notes to retrieve. * @return \Illuminate\Http\JsonResponse */ - public function getList(Request $request, $assetId): JsonResponse + public function getList(Asset $asset): JsonResponse { - $this->authorize('view', Asset::class); - - try { - $asset = Asset::findOrFail($assetId); - } catch (ModelNotFoundException $e) { - return response()->json(Helper::formatStandardApiResponse('error', null, $e->getMessage()), 404); - } catch (\Exception $e) { - // Return generic server error response since something unexpected happened - return response()->json(Helper::formatStandardApiResponse('error', null, $e->getMessage()), 500); - } - $this->authorize('view', $asset); // Get the manual notes for the asset diff --git a/routes/api.php b/routes/api.php index 5609508526..001061fc9f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -847,7 +847,7 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu Route::group(['prefix' => 'notes'], function () { Route::post( - '{asset_id}/store', + '{asset}/store', [ Api\NotesController::class, 'store' @@ -855,7 +855,7 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu )->name('api.notes.store'); Route::get( - '{asset_id}/getList', + '{asset}/getList', [ Api\NotesController::class, 'getList' diff --git a/tests/Feature/Assets/Api/AssetNotesTest.php b/tests/Feature/Assets/Api/AssetNotesTest.php index 906c5debf7..5096546af7 100644 --- a/tests/Feature/Assets/Api/AssetNotesTest.php +++ b/tests/Feature/Assets/Api/AssetNotesTest.php @@ -12,7 +12,7 @@ class AssetNotesTest extends TestCase public function testThatANonExistentAssetIdReturnsError() { $this->actingAsForApi(User::factory()->editAssets()->create()) - ->postJson(route('api.notes.store', 123456789)) + ->postJson(route('api.notes.store', ['asset' => 123456789])) ->assertStatusMessageIs('error'); } @@ -21,7 +21,7 @@ class AssetNotesTest extends TestCase $asset = Asset::factory()->create(); $this->actingAsForApi(User::factory()->create()) - ->postJson(route('api.notes.store', $asset->id), [ + ->postJson(route('api.notes.store', $asset), [ 'note' => 'test' ]) ->assertForbidden(); @@ -32,7 +32,7 @@ class AssetNotesTest extends TestCase $asset = Asset::factory()->create(); $this->actingAsForApi(User::factory()->editAssets()->create()) - ->postJson(route('api.notes.store', ['asset_id' => $asset->id]), [ + ->postJson(route('api.notes.store', $asset), [ 'note' => 'This is a test note.' ]) ->assertStatusMessageIs('success') @@ -67,7 +67,7 @@ class AssetNotesTest extends TestCase ]); $this->actingAsForApi($user) - ->getJson(route('api.notes.getList', ['asset_id' => $asset->id])) + ->getJson(route('api.notes.getList', $asset)) ->assertOk() ->assertJson([ 'messages' => null, From c94a8c42f4f699ba910f84e9b89cccfcc59ead3d Mon Sep 17 00:00:00 2001 From: Nicky West Date: Mon, 28 Jul 2025 16:57:46 -0700 Subject: [PATCH 04/51] Changed NotesController::getList() to NotesController::index() & reordered methods for consistency --- app/Http/Controllers/Api/NotesController.php | 80 ++++++++++---------- routes/api.php | 6 +- tests/Feature/Assets/Api/AssetNotesTest.php | 2 +- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/app/Http/Controllers/Api/NotesController.php b/app/Http/Controllers/Api/NotesController.php index 965eec96dd..c1a16fd4d6 100644 --- a/app/Http/Controllers/Api/NotesController.php +++ b/app/Http/Controllers/Api/NotesController.php @@ -18,6 +18,46 @@ use Illuminate\Support\Facades\Log; */ class NotesController extends Controller { + /** + * Retrieve a list of manual notes (action logs) for a given asset. + * + * Checks authorization to view assets, attempts to find the asset by ID, + * and fetches related action log entries of type 'note added', including + * user information for each note. Returns a JSON response with the notes or errors. + * + * @param \Illuminate\Http\Request $request The incoming HTTP request. + * @param Asset $asset The ID of the asset whose notes to retrieve. + * @return \Illuminate\Http\JsonResponse + */ + public function index(Asset $asset): JsonResponse + { + $this->authorize('view', $asset); + + // Get the manual notes for the asset + $notes = ActionLog::with('user:id,username') + ->where('item_type', Asset::class) + ->where('item_id', $asset->id) + ->where('action_type', 'note added') + ->orderBy('created_at', 'desc') + ->get(['id', 'created_at', 'note', 'created_by', 'item_id', 'item_type', 'action_type', 'target_id', 'target_type']); + + $notesArray = $notes->map(function ($note) { + return [ + 'id' => $note->id, + 'created_at' => $note->created_at, + 'note' => $note->note, + 'created_by' => $note->created_by, + 'username' => $note->user?->username, // adding the username + 'item_id' => $note->item_id, + 'item_type' => $note->item_type, + 'action_type' => $note->action_type, + ]; + }); + + // Return a success response + return response()->json(Helper::formatStandardApiResponse('success', ['notes' => $notesArray, 'asset_id' => $asset->id])); + } + /** * Store a manual note on a specified asset and log the action. * @@ -52,44 +92,4 @@ class NotesController extends Controller // Return an error response if something went wrong return response()->json(Helper::formatStandardApiResponse('error', null, 'Something went wrong'), 500); } - - /** - * Retrieve a list of manual notes (action logs) for a given asset. - * - * Checks authorization to view assets, attempts to find the asset by ID, - * and fetches related action log entries of type 'note added', including - * user information for each note. Returns a JSON response with the notes or errors. - * - * @param \Illuminate\Http\Request $request The incoming HTTP request. - * @param Asset $asset The ID of the asset whose notes to retrieve. - * @return \Illuminate\Http\JsonResponse - */ - public function getList(Asset $asset): JsonResponse - { - $this->authorize('view', $asset); - - // Get the manual notes for the asset - $notes = ActionLog::with('user:id,username') - ->where('item_type', Asset::class) - ->where('item_id', $asset->id) - ->where('action_type', 'note added') - ->orderBy('created_at', 'desc') - ->get(['id', 'created_at', 'note', 'created_by', 'item_id', 'item_type', 'action_type', 'target_id', 'target_type']); - - $notesArray = $notes->map(function ($note) { - return [ - 'id' => $note->id, - 'created_at' => $note->created_at, - 'note' => $note->note, - 'created_by' => $note->created_by, - 'username' => $note->user?->username, // adding the username - 'item_id' => $note->item_id, - 'item_type' => $note->item_type, - 'action_type' => $note->action_type, - ]; - }); - - // Return a success response - return response()->json(Helper::formatStandardApiResponse('success', ['notes' => $notesArray, 'asset_id' => $asset->id])); - } } diff --git a/routes/api.php b/routes/api.php index 001061fc9f..b139f3e81d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -855,12 +855,12 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu )->name('api.notes.store'); Route::get( - '{asset}/getList', + '{asset}/index', [ Api\NotesController::class, - 'getList' + 'index' ] - )->name('api.notes.getList'); + )->name('api.notes.index'); } ); // end asset notes API routes diff --git a/tests/Feature/Assets/Api/AssetNotesTest.php b/tests/Feature/Assets/Api/AssetNotesTest.php index 5096546af7..b3076c2852 100644 --- a/tests/Feature/Assets/Api/AssetNotesTest.php +++ b/tests/Feature/Assets/Api/AssetNotesTest.php @@ -67,7 +67,7 @@ class AssetNotesTest extends TestCase ]); $this->actingAsForApi($user) - ->getJson(route('api.notes.getList', $asset)) + ->getJson(route('api.notes.index', $asset)) ->assertOk() ->assertJson([ 'messages' => null, From ba85af11aaf560cb8751675e1842e167d569de58 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 12 Aug 2025 14:59:20 -0700 Subject: [PATCH 05/51] adds serial to expiring assets report email --- .../notifications/markdown/report-expiring-assets.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/notifications/markdown/report-expiring-assets.blade.php b/resources/views/notifications/markdown/report-expiring-assets.blade.php index 7c91fff974..2e8e87923b 100644 --- a/resources/views/notifications/markdown/report-expiring-assets.blade.php +++ b/resources/views/notifications/markdown/report-expiring-assets.blade.php @@ -3,14 +3,14 @@ @component('mail::table') - + @foreach ($assets as $asset) @php $expires = Helper::getFormattedDateObject($asset->present()->warranty_expires, 'date'); $diff = round(abs(strtotime($asset->present()->warranty_expires) - strtotime(date('Y-m-d')))/86400); $icon = ($diff <= ($threshold / 2)) ? '🚨' : (($diff <= $threshold) ? '⚠️' : ' '); @endphp - + @endforeach
 {{ trans('mail.name') }}{{ trans('mail.Days') }}{{ trans('mail.expires') }}{{ trans('mail.supplier') }}{{ trans('mail.assigned_to') }}
 {{ trans('mail.name') }}{{ trans('mail.serial') }}{{ trans('mail.Days') }}{{ trans('mail.expires') }}{{ trans('mail.supplier') }}{{ trans('mail.assigned_to') }}
{{ $icon }} {{ $asset->present()->name }} {{ $diff }} {{ trans('mail.Days') }} {{ !is_null($expires) ? $expires['formatted'] : '' }} {{ ($asset->supplier ? e($asset->supplier->name) : '') }} {{ ($asset->assignedTo ? e($asset->assignedTo->present()->name()) : '') }}
{{ $icon }} {{ $asset->present()->name }} {{$asset->serial}} {{ $diff }} {{ trans('mail.Days') }} {{ !is_null($expires) ? $expires['formatted'] : '' }} {{ ($asset->supplier ? e($asset->supplier->name) : '') }} {{ ($asset->assignedTo ? e($asset->assignedTo->present()->name()) : '') }}
@endcomponent From ced30082a68069c5009a6a7b806b43ca400fc327 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 12:10:28 +0100 Subject: [PATCH 06/51] 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 07/51] 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 08/51] 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 09/51] 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 10/51] 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 ed402e012257d6ba029169872f1da5d1041dbb32 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 19 Aug 2025 10:10:20 -0700 Subject: [PATCH 11/51] adds serial underneath name --- .../notifications/markdown/report-expiring-assets.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/notifications/markdown/report-expiring-assets.blade.php b/resources/views/notifications/markdown/report-expiring-assets.blade.php index 2e8e87923b..2ad33b57c4 100644 --- a/resources/views/notifications/markdown/report-expiring-assets.blade.php +++ b/resources/views/notifications/markdown/report-expiring-assets.blade.php @@ -3,14 +3,14 @@ @component('mail::table') - + @foreach ($assets as $asset) @php $expires = Helper::getFormattedDateObject($asset->present()->warranty_expires, 'date'); $diff = round(abs(strtotime($asset->present()->warranty_expires) - strtotime(date('Y-m-d')))/86400); $icon = ($diff <= ($threshold / 2)) ? '🚨' : (($diff <= $threshold) ? '⚠️' : ' '); @endphp - + @endforeach
 {{ trans('mail.name') }}{{ trans('mail.serial') }}{{ trans('mail.Days') }}{{ trans('mail.expires') }}{{ trans('mail.supplier') }}{{ trans('mail.assigned_to') }}
 {{ trans('mail.name') }}{{ trans('mail.serial') }}{{ trans('mail.Days') }}{{ trans('mail.expires') }}{{ trans('mail.supplier') }}{{ trans('mail.assigned_to') }}
{{ $icon }} {{ $asset->present()->name }} {{$asset->serial}} {{ $diff }} {{ trans('mail.Days') }} {{ !is_null($expires) ? $expires['formatted'] : '' }} {{ ($asset->supplier ? e($asset->supplier->name) : '') }} {{ ($asset->assignedTo ? e($asset->assignedTo->present()->name()) : '') }}
{{ $icon }} {{ $asset->present()->name }}
{{trans('mail.serial').': '.$asset->serial}}
{{ $diff }} {{ trans('mail.Days') }} {{ !is_null($expires) ? $expires['formatted'] : '' }} {{ ($asset->supplier ? e($asset->supplier->name) : '') }} {{ ($asset->assignedTo ? e($asset->assignedTo->present()->name()) : '') }}
@endcomponent From 765051ce8890e33a3af4b9a148c5d8709c224170 Mon Sep 17 00:00:00 2001 From: Johannes Pollitt Date: Tue, 19 Aug 2025 19:21:48 +0200 Subject: [PATCH 12/51] Added LabelWriter for 11354 format labels. Printable for example with the Dymo LabelWriter 450. --- .../Labels/Tapes/Dymo/LabelWriter_11354.php | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 app/Models/Labels/Tapes/Dymo/LabelWriter_11354.php diff --git a/app/Models/Labels/Tapes/Dymo/LabelWriter_11354.php b/app/Models/Labels/Tapes/Dymo/LabelWriter_11354.php new file mode 100644 index 0000000000..08f2fb6d27 --- /dev/null +++ b/app/Models/Labels/Tapes/Dymo/LabelWriter_11354.php @@ -0,0 +1,116 @@ +getPrintableArea(); + + $currentX = $pa->x1; + $currentY = $pa->y1; + $usableWidth = $pa->w; + $usableHeight = $pa->h; + + // Wide 1D barcode on top + if ($record->has('barcode1d')) { + static::write1DBarcode( + $pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type, + $currentX, $currentY, $usableWidth, self::BARCODE1D_HEIGHT + ); + $currentY += self::BARCODE1D_HEIGHT + self::BARCODE_MARGIN; + $usableHeight -= self::BARCODE1D_HEIGHT + self::BARCODE_MARGIN; + } + + // 2D Barcode in left column + if ($record->has('barcode2d')) { + $barcodeSize = $usableHeight - self::TAG_SIZE; + + static::writeText( + $pdf, $record->get('tag'), + $currentX, $pa->y2 - self::TAG_SIZE, + 'freesans', 'b', self::TAG_SIZE, 'C', + $barcodeSize, self::TAG_SIZE, true, 0 + ); + static::write2DBarcode( + $pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type, + $currentX, $currentY, + $barcodeSize, $barcodeSize + ); + $currentX += $barcodeSize + self::BARCODE_MARGIN; + $usableWidth -= $barcodeSize + self::BARCODE_MARGIN; + } + + // Right column + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $currentX, $currentY, + 'freesans', 'b', self::TITLE_SIZE, 'L', + $usableWidth, self::TITLE_SIZE, true, 0 + ); + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, (($field['label']) ? $field['label'].' ' : '') . $field['value'], + $currentX, $currentY, + 'freesans', '', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.3 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + } + +} \ No newline at end of file From 9eb686fe084531d11a832b17573234453cf717a4 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 19 Aug 2025 10:23:15 -0700 Subject: [PATCH 13/51] changes translation to administrator --- .../views/notifications/markdown/asset-acceptance.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/notifications/markdown/asset-acceptance.blade.php b/resources/views/notifications/markdown/asset-acceptance.blade.php index 85bc110ffa..2ed288b4fc 100644 --- a/resources/views/notifications/markdown/asset-acceptance.blade.php +++ b/resources/views/notifications/markdown/asset-acceptance.blade.php @@ -38,7 +38,7 @@ | **{{ trans('mail.serial') }}** | {{ $item_serial }} | @endif @if (isset($admin)) -| **{{ trans('general.checked_out').' '.trans('general.by')}}** | {{ $admin }} | +| **{{ trans('general.administrator') }}** | {{ $admin }} | @endif @endcomponent From 8b83584b67e3cfa7deb5413f94960405a622c690 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 19 Aug 2025 18:31:58 +0100 Subject: [PATCH 14/51] 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 16/51] 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 17/51] 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 18/51] 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 19/51] 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 20/51] 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 21/51] 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 bf591320af84ffff436cec38861f9506497520c3 Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 09:58:30 +0100 Subject: [PATCH 22/51] Fixed #17665 - delete custom report modal Signed-off-by: snipe --- resources/views/reports/custom.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/reports/custom.blade.php b/resources/views/reports/custom.blade.php index 835a8d9013..01eb13ad8f 100644 --- a/resources/views/reports/custom.blade.php +++ b/resources/views/reports/custom.blade.php @@ -672,7 +672,7 @@ Date: Wed, 20 Aug 2025 10:34:05 +0100 Subject: [PATCH 23/51] Fixed tooltip Signed-off-by: snipe --- resources/views/partials/bootstrap-table.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 0eca09d946..1aca076efa 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -1340,7 +1340,7 @@ window.location.href = '{{ route('maintenances.create', ['asset_id' => (isset($asset)) ? $asset->id :'' ]) }}'; }, attributes: { - title: '{{ trans('general.create') }}', + title: '{{ trans('button.add_maintenance') }}', } }, @endcan From 9c06ff389994fdc9a96e4f3ff5a044384ed33dba Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 11:00:18 +0100 Subject: [PATCH 24/51] Check for numeric Signed-off-by: snipe --- app/Models/SnipeModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/SnipeModel.php b/app/Models/SnipeModel.php index f26946d22a..f300a22bd7 100644 --- a/app/Models/SnipeModel.php +++ b/app/Models/SnipeModel.php @@ -21,7 +21,7 @@ class SnipeModel extends Model */ public function setPurchaseCostAttribute($value) { - if (is_float($value)) { + if (is_numeric($value)) { //value is *already* a floating-point number. Just assign it directly $this->attributes['purchase_cost'] = $value; return; From bc645d26212ed162bcafabc4cdbd4575aaa2c275 Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 11:24:16 +0100 Subject: [PATCH 25/51] Use email formatter in licensed_to_email display Signed-off-by: snipe --- app/Presenters/LicensePresenter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Presenters/LicensePresenter.php b/app/Presenters/LicensePresenter.php index 773f5f5547..b0518ef264 100644 --- a/app/Presenters/LicensePresenter.php +++ b/app/Presenters/LicensePresenter.php @@ -53,6 +53,7 @@ class LicensePresenter extends Presenter 'searchable' => true, 'sortable' => true, 'title' => trans('admin/licenses/form.to_email'), + 'formatter' => 'emailFormatter', ], [ 'field' => 'license_name', 'searchable' => true, From 855922c21ac999f06b34c71fcf8af6b2db286ba3 Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 11:32:16 +0100 Subject: [PATCH 26/51] Account for null in tetss (vs 0) Signed-off-by: snipe --- tests/Unit/SnipeModelTest.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Unit/SnipeModelTest.php b/tests/Unit/SnipeModelTest.php index 2bc81da61b..d36b6e4289 100644 --- a/tests/Unit/SnipeModelTest.php +++ b/tests/Unit/SnipeModelTest.php @@ -18,12 +18,14 @@ class SnipeModelTest extends TestCase public function testSetsPurchaseCostsAppropriately() { $c = new SnipeModel; + $c->purchase_cost = ''; + $this->assertTrue($c->purchase_cost == null); $c->purchase_cost = '0.00'; - $this->assertTrue($c->purchase_cost === null); + $this->assertTrue($c->purchase_cost == 0.00); $c->purchase_cost = '9.54'; - $this->assertTrue($c->purchase_cost === 9.54); + $this->assertTrue($c->purchase_cost == 9.54); $c->purchase_cost = '9.50'; - $this->assertTrue($c->purchase_cost === 9.5); + $this->assertTrue($c->purchase_cost == 9.5); } public function testNullsBlankLocationIdsButNotOthers() From 312be981326d2523fd77c3aaa7f7bcb38e079c61 Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 12:43:23 +0100 Subject: [PATCH 27/51] Add @FlorestanII as a contributor --- .all-contributorsrc | 9 +++++++++ CONTRIBUTORS.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index b91e5afeb0..bcb1ea5479 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -4198,6 +4198,15 @@ "contributions": [ "code" ] + }, + { + "login": "FlorestanII", + "name": "Johannes Pollitt", + "avatar_url": "https://avatars.githubusercontent.com/u/15015119?v=4", + "profile": "https://github.com/FlorestanII", + "contributions": [ + "code" + ] } ] } diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ed141050d5..8e8a13e708 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -68,7 +68,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken | [
Juan Font](https://github.com/juanfont)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juanfont "Code") | [
Juho Taipale](https://github.com/juhotaipale)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juhotaipale "Code") | [
Korvin Szanto](https://github.com/KorvinSzanto)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=KorvinSzanto "Code") | [
Lewis Foster](https://lewisfoster.foo/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=sniff122 "Code") | [
Logan Swartzendruber](https://github.com/loganswartz)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=loganswartz "Code") | [
Lorenzo P.](https://github.com/lopezio)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lopezio "Code") | [
Lukas Jung](https://github.com/m4us1ne)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=m4us1ne "Code") | | [
Ellie](https://leafedfox.xyz/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=LeafedFox "Code") | [
GA Stamper](https://github.com/gastamper)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gastamper "Code") | [
Guillaume Lefranc](https://github.com/gl-pup)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gl-pup "Code") | [
Hajo MΓΆller](https://github.com/dasjoe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=dasjoe "Code") | [
Istvan Basa](https://github.com/pottom)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=pottom "Code") | [
JJ Asghar](https://jjasghar.github.io/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jjasghar "Code") | [
James E. Msenga](https://github.com/JemCdo)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JemCdo "Code") | | [
Jan Felix Wiebe](https://github.com/jfwiebe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jfwiebe "Code") | [
Jo Drexl](https://www.nfon.com/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=drexljo "Code") | [
Austin Sasko](https://github.com/austinsasko)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=austinsasko "Code") | [
Jasson](http://jassoncordones.github.io)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JassonCordones "Code") | [
Okean](https://github.com/Tinyblargon)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=Tinyblargon "Code") | [
Alejandro Medrano](https://www.lst.tfo.upm.es/alejandro-medrano/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=amedranogil "Code") | [
Lukas Kraic](https://github.com/lukaskraic)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lukaskraic "Code") | -| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | +| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [
Johannes Pollitt](https://github.com/FlorestanII)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! From 618106c10325cfff0039ca9572ad6918b7007ad3 Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 14:11:20 +0100 Subject: [PATCH 28/51] Fixed #17674 - added odp, ods, odt to accepted files Signed-off-by: snipe --- app/Helpers/Helper.php | 11 +++++++++++ app/Helpers/StorageHelper.php | 13 ++++++++++++- app/Http/Transformers/UploadedFilesTransformer.php | 2 +- config/filesystems.php | 8 +++++++- resources/lang/en-US/general.php | 1 + resources/views/partials/bootstrap-table.blade.php | 8 ++++++-- 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 7980e22fe1..9db9e4cb2a 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1197,19 +1197,30 @@ class Helper 'webp' => 'far fa-image', 'avif' => 'far fa-image', 'svg' => 'fas fa-vector-square', + // word 'doc' => 'far fa-file-word', 'docx' => 'far fa-file-word', + // Excel 'xls' => 'far fa-file-excel', 'xlsx' => 'far fa-file-excel', + 'ods' => 'far fa-file-excel', + + // Presentation + 'ppt' => 'far fa-file-powerpoint', + 'odp' => 'far fa-file-powerpoint', + // archive 'zip' => 'fas fa-file-archive', 'rar' => 'fas fa-file-archive', + //Text + 'odt' => 'far fa-file-alt', 'txt' => 'far fa-file-alt', 'rtf' => 'far fa-file-alt', 'xml' => 'fas fa-code', + // Misc 'pdf' => 'far fa-file-pdf', 'lic' => 'far fa-save', diff --git a/app/Helpers/StorageHelper.php b/app/Helpers/StorageHelper.php index 1b55b69a3f..4d100fb72a 100644 --- a/app/Helpers/StorageHelper.php +++ b/app/Helpers/StorageHelper.php @@ -29,7 +29,7 @@ class StorageHelper public static function getMediaType($file_with_path) { - // The file exists and is allowed to be displayed inline + // Get the file extension and determine the media type if (Storage::exists($file_with_path)) { $fileinfo = pathinfo($file_with_path); $extension = strtolower($fileinfo['extension']); @@ -51,6 +51,15 @@ class StorageHelper case 'webm': case 'mov': return 'video'; + case 'doc': + case 'docx': + return 'document'; + case 'txt': + return 'text'; + case 'xls': + case 'xlsx': + case 'ods': + return 'spreadsheet'; default: return $extension; // Default for unknown types } @@ -87,9 +96,11 @@ class StorageHelper 'webp', ]; + \Log::error(pathinfo($file_with_path, PATHINFO_EXTENSION)); // The file exists and is allowed to be displayed inline if (Storage::exists($file_with_path) && (in_array(pathinfo($file_with_path, PATHINFO_EXTENSION), $allowed_inline))) { + \Log::error('File is allowed inline: ' . $file_with_path); return true; } return false; diff --git a/app/Http/Transformers/UploadedFilesTransformer.php b/app/Http/Transformers/UploadedFilesTransformer.php index ae6c981eda..e32aabc8e5 100644 --- a/app/Http/Transformers/UploadedFilesTransformer.php +++ b/app/Http/Transformers/UploadedFilesTransformer.php @@ -45,7 +45,7 @@ class UploadedFilesTransformer ] : null, 'created_at' => Helper::getFormattedDateObject($file->created_at, 'datetime'), 'deleted_at' => Helper::getFormattedDateObject($file->deleted_at, 'datetime'), - 'inlineable' => StorageHelper::allowSafeInline($file->uploads_file_path()), + 'inlineable' => StorageHelper::allowSafeInline($file->uploads_file_path()) ?? false, 'exists_on_disk' => (Storage::exists($file->uploads_file_path()) ? true : false), ]; diff --git a/config/filesystems.php b/config/filesystems.php index 2aae01c055..6098438ed2 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -123,6 +123,9 @@ $config['allowed_upload_extensions_array'] = [ 'mov', 'mp3', 'mp4', + 'odp', + 'ods', + 'odt', 'ogg', 'pdf', 'png', @@ -140,12 +143,15 @@ $config['allowed_upload_extensions_array'] = [ ]; - +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types $config['allowed_upload_mimetypes_array'] = [ 'application/json', 'application/msword', 'application/pdf', 'application/vnd.ms-excel', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.text', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/x-rar-compressed', diff --git a/resources/lang/en-US/general.php b/resources/lang/en-US/general.php index b06d6899fd..e4bc2ad232 100644 --- a/resources/lang/en-US/general.php +++ b/resources/lang/en-US/general.php @@ -337,6 +337,7 @@ return [ 'zip' => 'Zip', 'noimage' => 'No image uploaded or image not found.', 'file_does_not_exist' => 'The requested file does not exist on the server.', + 'file_not_inlineable' => 'The requested file cannot be opened inline in your browser. You can download it instead.', 'open_new_window' => 'Open this file in a new window', 'file_upload_success' => 'File upload success!', 'no_files_uploaded' => 'File upload success!', diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 1aca076efa..8fc3bfbfbe 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -966,10 +966,14 @@ var download_button = '
'; var download_button_disabled = ''; var inline_button = ''; - var inline_button_disabled = ''; + var inline_button_disabled = ''; if (exists_on_disk === true) { - return '' + download_button + ' ' + inline_button + ''; + if (inlinable === true) { + return '' + download_button + ' ' + inline_button + ''; + } else { + return '' + download_button + ' ' + inline_button_disabled + ''; + } } else { return '' + download_button_disabled + ' ' + inline_button_disabled + ''; } From da5b1afd19749388c6a91f946c93638b9608f99d Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 14:11:42 +0100 Subject: [PATCH 29/51] Removed logging Signed-off-by: snipe --- app/Helpers/StorageHelper.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Helpers/StorageHelper.php b/app/Helpers/StorageHelper.php index 4d100fb72a..cbd801d302 100644 --- a/app/Helpers/StorageHelper.php +++ b/app/Helpers/StorageHelper.php @@ -96,11 +96,9 @@ class StorageHelper 'webp', ]; - \Log::error(pathinfo($file_with_path, PATHINFO_EXTENSION)); // The file exists and is allowed to be displayed inline if (Storage::exists($file_with_path) && (in_array(pathinfo($file_with_path, PATHINFO_EXTENSION), $allowed_inline))) { - \Log::error('File is allowed inline: ' . $file_with_path); return true; } return false; From 11eee833bb8259443390c32c0df6783ff9a0180d Mon Sep 17 00:00:00 2001 From: snipe Date: Wed, 20 Aug 2025 15:56:10 +0100 Subject: [PATCH 30/51] Fixed #17667 - Switch to hyphens for windows Signed-off-by: snipe --- app/Http/Controllers/Api/ImportController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ImportController.php b/app/Http/Controllers/Api/ImportController.php index c18df26683..79bffd1206 100644 --- a/app/Http/Controllers/Api/ImportController.php +++ b/app/Http/Controllers/Api/ImportController.php @@ -195,7 +195,7 @@ class ImportController extends Controller // Run a backup immediately before processing if ($request->get('run-backup')) { Log::debug('Backup manually requested via importer'); - Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]); + Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H-i-s')]); } else { Log::debug('NO BACKUP requested via importer'); } From c07ef4d87f57fa56d263d321a0f8de3a3bc698ff Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 21 Aug 2025 09:25:42 +0100 Subject: [PATCH 31/51] 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 32/51] 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] ?? ''; From d8dd274c084a6f30cb4aaee10f6564dbb9d71188 Mon Sep 17 00:00:00 2001 From: qay Date: Thu, 21 Aug 2025 12:26:13 +0200 Subject: [PATCH 33/51] Fix components presenting wrong URLs --- app/Presenters/ComponentPresenter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Presenters/ComponentPresenter.php b/app/Presenters/ComponentPresenter.php index 32e63ac713..254e7f4110 100644 --- a/app/Presenters/ComponentPresenter.php +++ b/app/Presenters/ComponentPresenter.php @@ -191,7 +191,7 @@ class ComponentPresenter extends Presenter */ public function nameUrl() { - return (string) link_to_route('consumables.show', e($this->name), $this->id); + return (string) link_to_route('components.show', e($this->name), $this->id); } /** @@ -200,6 +200,6 @@ class ComponentPresenter extends Presenter */ public function viewUrl() { - return route('accessories.show', $this->id); + return route('components.show', $this->id); } } From 952b6f33bb3c1700f8facaea4861dd7fdff4f13d Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 21 Aug 2025 11:31:47 +0100 Subject: [PATCH 34/51] Add @strobelm as a contributor --- .all-contributorsrc | 9 +++++++++ CONTRIBUTORS.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index bcb1ea5479..3634e71d69 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -4207,6 +4207,15 @@ "contributions": [ "code" ] + }, + { + "login": "strobelm", + "name": "Michael Strobel", + "avatar_url": "https://avatars.githubusercontent.com/u/14185442?v=4", + "profile": "https://strobelm.de", + "contributions": [ + "code" + ] } ] } diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 8e8a13e708..7bd1223187 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -68,7 +68,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken | [
Juan Font](https://github.com/juanfont)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juanfont "Code") | [
Juho Taipale](https://github.com/juhotaipale)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juhotaipale "Code") | [
Korvin Szanto](https://github.com/KorvinSzanto)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=KorvinSzanto "Code") | [
Lewis Foster](https://lewisfoster.foo/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=sniff122 "Code") | [
Logan Swartzendruber](https://github.com/loganswartz)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=loganswartz "Code") | [
Lorenzo P.](https://github.com/lopezio)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lopezio "Code") | [
Lukas Jung](https://github.com/m4us1ne)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=m4us1ne "Code") | | [
Ellie](https://leafedfox.xyz/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=LeafedFox "Code") | [
GA Stamper](https://github.com/gastamper)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gastamper "Code") | [
Guillaume Lefranc](https://github.com/gl-pup)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gl-pup "Code") | [
Hajo MΓΆller](https://github.com/dasjoe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=dasjoe "Code") | [
Istvan Basa](https://github.com/pottom)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=pottom "Code") | [
JJ Asghar](https://jjasghar.github.io/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jjasghar "Code") | [
James E. Msenga](https://github.com/JemCdo)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JemCdo "Code") | | [
Jan Felix Wiebe](https://github.com/jfwiebe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jfwiebe "Code") | [
Jo Drexl](https://www.nfon.com/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=drexljo "Code") | [
Austin Sasko](https://github.com/austinsasko)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=austinsasko "Code") | [
Jasson](http://jassoncordones.github.io)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JassonCordones "Code") | [
Okean](https://github.com/Tinyblargon)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=Tinyblargon "Code") | [
Alejandro Medrano](https://www.lst.tfo.upm.es/alejandro-medrano/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=amedranogil "Code") | [
Lukas Kraic](https://github.com/lukaskraic)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lukaskraic "Code") | -| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [
Johannes Pollitt](https://github.com/FlorestanII)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | +| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [
Johannes Pollitt](https://github.com/FlorestanII)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [
Michael Strobel](https://strobelm.de)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! From b84d9282ca44e029dd4728dd6f2fd2695e5bc863 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 21 Aug 2025 13:05:01 +0100 Subject: [PATCH 35/51] Use normal locale for warranty Signed-off-by: snipe --- resources/views/hardware/view.blade.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/views/hardware/view.blade.php b/resources/views/hardware/view.blade.php index 550c4b1fbf..82eb7d00cb 100755 --- a/resources/views/hardware/view.blade.php +++ b/resources/views/hardware/view.blade.php @@ -809,7 +809,7 @@
{{ Helper::getFormattedDateObject($asset->purchase_date, 'date', false) }} - - {{ Carbon::parse($asset->purchase_date)->diff(Carbon::now())->format('%y years, %m months and %d days')}} + {{ Carbon::parse($asset->purchase_date)->diffForHumans(['parts' => 3]) }}
@@ -940,7 +940,7 @@ @if ($asset->purchase_date) {{ Helper::getFormattedDateObject($asset->present()->warranty_expires(), 'date', false) }} - - {{ Carbon::parse($asset->present()->warranty_expires())->diffForHumans(['parts' => 2]) }} + {{ Carbon::parse($asset->present()->warranty_expires())->diffForHumans(['parts' => 3]) }} @else {{ trans('general.na_no_purchase_date') }} @endif @@ -971,7 +971,7 @@ @if ($asset->purchase_date) {{ Helper::getFormattedDateObject($asset->depreciated_date()->format('Y-m-d'), 'date', false) }} - - {{ Carbon::parse($asset->depreciated_date())->diffForHumans(['parts' => 2]) }} + {{ Carbon::parse($asset->depreciated_date())->diffForHumans(['parts' => 3]) }} @else {{ trans('general.na_no_purchase_date') }} @endif @@ -1008,7 +1008,7 @@ @if ($asset->asset_eol_date) {{ Helper::getFormattedDateObject($asset->asset_eol_date, 'date', false) }} - - {{ Carbon::parse($asset->asset_eol_date)->diffForHumans(['parts' => 2]) }} + {{ Carbon::parse($asset->asset_eol_date)->locale(app()->getLocale())->diffForHumans(['parts' => 3]) }} @else {{ trans('general.na_no_purchase_date') }} @endif From 822339fe420ce09f5d0d5c4bc48f5a6b0729ec5a Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 21 Aug 2025 13:13:11 +0100 Subject: [PATCH 36/51] Moved warning Signed-off-by: snipe --- resources/views/hardware/view.blade.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/views/hardware/view.blade.php b/resources/views/hardware/view.blade.php index 82eb7d00cb..33085bdcc3 100755 --- a/resources/views/hardware/view.blade.php +++ b/resources/views/hardware/view.blade.php @@ -930,9 +930,7 @@
{{ trans('admin/hardware/form.warranty_expires') }} - @if ($asset->purchase_date) - {!! $asset->present()->warranty_expires() < date("Y-m-d") ? '' : '' !!} - @endif +
@@ -941,6 +939,10 @@ {{ Helper::getFormattedDateObject($asset->present()->warranty_expires(), 'date', false) }} - {{ Carbon::parse($asset->present()->warranty_expires())->diffForHumans(['parts' => 3]) }} + + @if ($asset->purchase_date) + {!! $asset->present()->warranty_expires() < date("Y-m-d") ? '' : '' !!} + @endif @else {{ trans('general.na_no_purchase_date') }} @endif @@ -1017,7 +1019,7 @@ data-placement="top" data-title="Explicit EOL" title="Explicit EOL"> - + @endif
From 6db0003e3f0a8ffcd82b3fc0fb73fda821fcdeb0 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Thu, 21 Aug 2025 13:44:14 +0100 Subject: [PATCH 37/51] Adds a 'created_at' index to the models table --- ..._190617_add_created_at_index_to_models.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 database/migrations/2025_08_20_190617_add_created_at_index_to_models.php diff --git a/database/migrations/2025_08_20_190617_add_created_at_index_to_models.php b/database/migrations/2025_08_20_190617_add_created_at_index_to_models.php new file mode 100644 index 0000000000..5a73a94f3b --- /dev/null +++ b/database/migrations/2025_08_20_190617_add_created_at_index_to_models.php @@ -0,0 +1,28 @@ +index(['created_at']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('models', function (Blueprint $table) { + $table->dropIndex(['created_at']); + }); + } +}; From 6503f9c667c1428c68461f8c58e1b6e8bdbb6100 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 21 Aug 2025 20:23:47 +0100 Subject: [PATCH 38/51] Revert "Merge pull request #17650 from grokability/add-displayName-to-users" This reverts commit 4770e469b4e383301e72c931d3589d2adba3b40b, reversing changes made to 29a18c7c8bc108ede2d9b56f4de0cf57daa5c769. Signed-off-by: snipe --- app/Console/Commands/LdapSync.php | 21 - .../Controllers/Api/SettingsController.php | 1 - app/Http/Controllers/Api/UsersController.php | 10 - app/Http/Controllers/SettingsController.php | 6 - .../Controllers/Users/UsersController.php | 2 - app/Http/Transformers/UsersTransformer.php | 10 +- app/Importer/UserImporter.php | 1 - app/Livewire/Importer.php | 8 - app/Models/SnipeModel.php | 17 +- app/Models/SnipeSCIMConfig.php | 3 +- app/Models/User.php | 16 +- app/Presenters/UserPresenter.php | 12 - ...08_19_114742_add_display_name_to_users.php | 32 - ...4823_add_display_name_to_ldap_settings.php | 82 - .../lang/en-US/admin/settings/general.php | 57 +- resources/lang/en-US/admin/users/table.php | 1 - resources/views/modals/user.blade.php | 12 - resources/views/settings/ldap.blade.php | 1637 ++++++++--------- resources/views/users/edit.blade.php | 17 - resources/views/users/view.blade.php | 56 +- 20 files changed, 825 insertions(+), 1176 deletions(-) delete mode 100644 database/migrations/2025_08_19_114742_add_display_name_to_users.php delete 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 7ad4648702..88015b14a1 100644 --- a/app/Console/Commands/LdapSync.php +++ b/app/Console/Commands/LdapSync.php @@ -55,8 +55,6 @@ 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, @@ -65,17 +63,11 @@ 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; @@ -242,11 +234,9 @@ 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] ?? ''; - $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,13 +244,8 @@ 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["city"]][0] ?? ''; - $item['state'] = $results[$i][$ldap_map["state"]][0] ?? ''; $item['country'] = $results[$i][$ldap_map["country"]][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] ?? ''; @@ -293,9 +278,6 @@ class LdapSync extends Command if($ldap_map["username"] != null){ $user->username = $item['username']; } - if($ldap_map["display_name"] != null){ - $user->display_name = $item['display_name']; - } if($ldap_map["last_name"] != null){ $user->last_name = $item['lastname']; } @@ -311,9 +293,6 @@ 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/Api/SettingsController.php b/app/Http/Controllers/Api/SettingsController.php index 3e48eb23f1..134d24ef2a 100644 --- a/app/Http/Controllers/Api/SettingsController.php +++ b/app/Http/Controllers/Api/SettingsController.php @@ -51,7 +51,6 @@ 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, diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 133937ed75..a0d9aeaa30 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -64,7 +64,6 @@ class UsersController extends Controller 'users.jobtitle', 'users.last_login', 'users.last_name', - 'users.display_name', 'users.locale', 'users.location_id', 'users.manager_id', @@ -155,10 +154,6 @@ 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')); } @@ -289,7 +284,6 @@ class UsersController extends Controller [ 'last_name', 'first_name', - 'display_name', 'email', 'jobtitle', 'username', @@ -517,10 +511,6 @@ 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/SettingsController.php b/app/Http/Controllers/SettingsController.php index 8c57efa5eb..56b36470d4 100644 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -873,7 +873,6 @@ 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'); @@ -890,12 +889,7 @@ 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/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 35ef7d3e68..2275e565cb 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -88,7 +88,6 @@ 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')); } @@ -241,7 +240,6 @@ 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/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index a4c1cdfbc6..fb941007ab 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -31,11 +31,10 @@ class UsersTransformer $array = [ 'id' => (int) $user->id, 'avatar' => e($user->present()->gravatar) ?? null, - '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, + 'name' => e($user->getFullNameAttribute()), + 'first_name' => e($user->first_name), + 'last_name' => e($user->last_name), + 'username' => e($user->username), 'remote' => ($user->remote == '1') ? true : false, 'locale' => ($user->locale) ? e($user->locale) : null, 'employee_num' => ($user->employee_num) ? e($user->employee_num) : null, @@ -139,7 +138,6 @@ 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/Importer/UserImporter.php b/app/Importer/UserImporter.php index 942f1cf4a2..633551c24d 100644 --- a/app/Importer/UserImporter.php +++ b/app/Importer/UserImporter.php @@ -47,7 +47,6 @@ 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 d86b2469c1..6e6a6f1847 100644 --- a/app/Livewire/Importer.php +++ b/app/Livewire/Importer.php @@ -339,7 +339,6 @@ 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'), @@ -486,13 +485,6 @@ 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/app/Models/SnipeModel.php b/app/Models/SnipeModel.php index 4cc5aa957d..f300a22bd7 100644 --- a/app/Models/SnipeModel.php +++ b/app/Models/SnipeModel.php @@ -3,7 +3,6 @@ namespace App\Models; use App\Helpers\Helper; -use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; class SnipeModel extends Model @@ -156,19 +155,9 @@ class SnipeModel extends Model $this->attributes['status_id'] = $value; } - // 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 + // + public function getDisplayNameAttribute() { - // 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, - ); + return $this->name; } - } diff --git a/app/Models/SnipeSCIMConfig.php b/app/Models/SnipeSCIMConfig.php index 5fce6ef292..c0d82dff43 100644 --- a/app/Models/SnipeSCIMConfig.php +++ b/app/Models/SnipeSCIMConfig.php @@ -34,7 +34,6 @@ 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', @@ -122,7 +121,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig 'honorificSuffix' => null ], - 'displayName' => AttributeMapping::eloquent("display_name"), + 'displayName' => null, 'nickName' => null, 'profileUrl' => null, 'title' => AttributeMapping::eloquent('jobtitle'), diff --git a/app/Models/User.php b/app/Models/User.php index 5374b5e284..0c1cbe21fd 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -64,7 +64,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'first_name', 'jobtitle', 'last_name', - 'display_name', 'ldap_import', 'locale', 'location_id', @@ -104,8 +103,6 @@ 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', @@ -116,9 +113,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' => 'nullable|string|max:191', - 'city' => 'nullable|string|max:191', - 'state' => 'nullable|string|max:191', + 'address' => 'max:191|nullable', + 'city' => 'max:191|nullable', + 'state' => 'min:2|max:191|nullable', 'country' => 'min:2|max:191|nullable', 'zip' => 'max:10|nullable', 'vip' => 'boolean', @@ -135,16 +132,15 @@ 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', @@ -161,7 +157,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'department' => ['name'], 'groups' => ['name'], 'company' => ['name'], - 'manager' => ['first_name', 'last_name', 'username', 'display_name'], + 'manager' => ['first_name', 'last_name', 'username'], ]; @@ -863,7 +859,6 @@ 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', @@ -1073,7 +1068,6 @@ 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 8eb28091c5..c60457ea05 100644 --- a/app/Presenters/UserPresenter.php +++ b/app/Presenters/UserPresenter.php @@ -79,14 +79,6 @@ 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, @@ -199,7 +191,6 @@ class UserPresenter extends Presenter 'visible' => true, 'formatter' => 'usernameRoleLinkFormatter', ], - [ 'field' => 'employee_num', 'searchable' => true, @@ -458,9 +449,6 @@ 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'); } 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 deleted file mode 100644 index d55e755d3a..0000000000 --- a/database/migrations/2025_08_19_114742_add_display_name_to_users.php +++ /dev/null @@ -1,32 +0,0 @@ -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/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 deleted file mode 100644 index fb980af6dd..0000000000 --- a/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php +++ /dev/null @@ -1,82 +0,0 @@ -string('ldap_display_name', 191)->after('ldap_fname_field')->nullable()->default(null); - } - - if (!Schema::hasColumn('settings', 'ldap_zip')) { - $table->string('ldap_zip', 191)->after('ldap_manager')->nullable()->default(null); - } - - if (!Schema::hasColumn('settings', 'ldap_state')) { - $table->string('ldap_state', 191)->after('ldap_manager')->nullable()->default(null); - } - - if (!Schema::hasColumn('settings', 'ldap_city')) { - $table->string('ldap_city', 191)->after('ldap_manager')->nullable()->default(null); - } - - if (!Schema::hasColumn('settings', 'ldap_address')) { - $table->string('ldap_address', 191)->after('ldap_manager')->nullable()->default(null); - } - - if (!Schema::hasColumn('settings', 'ldap_mobile')) { - $table->string('ldap_mobile', 191)->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 842fe5e338..4e8143a517 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 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_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_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 Field', + 'ldap_manager' => 'LDAP Manager', '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,32 +106,26 @@ 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 Field', - 'ldap_phone' => 'LDAP Phone Number Field', - 'ldap_jobtitle' => 'LDAP Job Title Field', - 'ldap_country' => 'LDAP Country Field', + 'ldap_dept' => 'LDAP Department', + 'ldap_phone' => 'LDAP Telephone Number', + 'ldap_jobtitle' => 'LDAP Job Title', + 'ldap_country' => 'LDAP Country', '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' => '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_username_field' => 'Username Field', + 'ldap_lname_field' => 'Last Name', + 'ldap_fname_field' => 'LDAP First Name', '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 Field', - 'ldap_email' => 'LDAP Email Field', - '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_emp_num' => 'LDAP Employee Number', + 'ldap_email' => 'LDAP Email', 'ldap_test' => 'Test LDAP', 'ldap_test_sync' => 'Test LDAP Synchronization', 'license' => 'Software License', @@ -468,24 +462,21 @@ return [ 'legends' => [ - 'checkin' => 'Checkin Preferences', - 'colors' => 'Colors & Skins', - 'dashboard' => 'Login & Dashboard Preferences', - 'email' => 'Email Preferences', - 'eula' => 'EULA & Acceptance Preferences', - 'footer' => 'Footer Preferences', + 'scoping' => 'Scoping', 'formats' => 'Default Formats', + 'profiles' => 'User Profiles', + 'eula' => 'EULA & Acceptance Preferences', + 'misc_display' => 'Miscellaneous Display Options', + 'email' => 'Email Preferences', + 'checkin' => 'Checkin Preferences', + 'dashboard' => 'Login & Dashboard Preferences', + 'misc' => 'Miscellaneous', + 'logos' => 'Logos & Display', + 'colors' => 'Colors & Skins', + 'footer' => 'Footer Preferences', + 'security' => 'Security Preferences', 'general' => 'General', 'intervals' => 'Intervals & Thresholds', - 'logos' => 'Logos & Display', - 'mapping' => 'LDAP Field Mapping', - 'test' => 'Test LDAP Connection', - 'misc' => 'Miscellaneous', - 'misc_display' => 'Miscellaneous Display Options', - 'profiles' => 'User Profiles', - 'server' => 'Server Settings', - 'scoping' => 'Scoping', - 'security' => 'Security Preferences', ], diff --git a/resources/lang/en-US/admin/users/table.php b/resources/lang/en-US/admin/users/table.php index 2e2f9c7995..e7a5aa6490 100644 --- a/resources/lang/en-US/admin/users/table.php +++ b/resources/lang/en-US/admin/users/table.php @@ -35,7 +35,6 @@ 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', diff --git a/resources/views/modals/user.blade.php b/resources/views/modals/user.blade.php index e9b83fc5ae..04d0c82357 100644 --- a/resources/views/modals/user.blade.php +++ b/resources/views/modals/user.blade.php @@ -79,18 +79,6 @@ -
-
-
- -
-
- - -
-
-
-
diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 19051f653b..27e6a20dea 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -65,357 +65,728 @@
-
+
-
- - {{ trans('admin/settings/general.legends.server') }} - - -
-
- -
-
+ +
+
+ +
+
- + - @if (config('app.lock_passwords')===true) -

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

- @endif -
-
+ @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_auth_filter_query') + +
+
+ +
+
+ + @error('is_ad') - - {!! $message !!} - - @enderror + + {{ $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)

@@ -423,543 +794,68 @@

@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_login_test_help') }}

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

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

+ @error('custom_forgot_pass_url') + + + {{ $message }} + + @enderror -
- -
- - {{ 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 -
- -
- - -
-
- -
-
-
-
- -
-
- -
- + @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') }} - - -
-
- -
-
- - @error('ldap_username_field') - - - {!! $message !!} - - @enderror - -
-
- - -
-
- -
-
- - @error('ldap_lname_field') - - - {{ $message }} - - @enderror - -
-
- - -
-
- -
-
- - @error('ldap_fname_field') - - - {{ $message }} - - @enderror - -
-
- - -
-
- -
-
- - @error('ldap_display_name') - - - {{ $message }} - - @enderror - -
-
- - - -
-
- -
-
- -

{!! 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 -
-
- - - -
-
- -
-
- - @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 -
-
-
- -
- - {{ trans('admin/settings/general.legends.misc') }} - - -
-
- -
-
- -

{{ 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 -
-
- -
- {{ $user->first_name }} {{ $user->last_name }} + {{ $user->present()->fullName() }}
+ + @if (!is_null($user->company)) +
+ +
+ {{ trans('general.company') }} +
+
+ @can('view', 'App\Models\Company') + + {{ $user->company->name }} + + @else + {{ $user->company->name }} + @endcan +
+ +
+ + @endif +
@@ -345,19 +366,6 @@
- - @if ($user->display_name) -
- -
- {{ trans('admin/users/table.display_name') }} -
-
- {{ $user->display_name }} -
-
- @endif - @if (($user->address) || ($user->city) || ($user->state) || ($user->country))
@@ -386,26 +394,6 @@
@endif - - @if (!is_null($user->company)) -
- -
- {{ trans('general.company') }} -
-
- @can('view', 'App\Models\Company') - - {{ $user->company->name }} - - @else - {{ $user->company->name }} - @endcan -
- -
- - @endif
From b6d397bcca4e8a05176b782de769d7160058bfc4 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 25 Aug 2025 14:57:34 +0100 Subject: [PATCH 39/51] Updated `->present()->fullName()` to `->display_name` Signed-off-by: snipe --- .../Commands/SendAcceptanceReminder.php | 2 +- app/Http/Controllers/Api/AssetsController.php | 2 +- .../Controllers/Api/ConsumablesController.php | 4 +-- app/Http/Controllers/Api/UsersController.php | 10 +++--- .../Controllers/Assets/AssetsController.php | 4 +-- .../Licenses/LicensesController.php | 2 +- app/Http/Controllers/ReportsController.php | 6 ++-- .../Controllers/Users/UsersController.php | 4 +-- app/Http/Controllers/ViewAssetsController.php | 2 +- .../Transformers/AccessoriesTransformer.php | 2 +- .../Transformers/ActionlogsTransformer.php | 8 ++--- .../Transformers/AssetModelsTransformer.php | 2 +- app/Http/Transformers/AssetsTransformer.php | 4 +-- .../Transformers/CategoriesTransformer.php | 2 +- .../Transformers/CompaniesTransformer.php | 2 +- .../Transformers/ComponentsTransformer.php | 2 +- .../Transformers/ConsumablesTransformer.php | 2 +- .../Transformers/DepartmentsTransformer.php | 2 +- .../Transformers/DepreciationsTransformer.php | 2 +- app/Http/Transformers/GroupsTransformer.php | 2 +- app/Http/Transformers/LicensesTransformer.php | 2 +- .../Transformers/MaintenancesTransformer.php | 4 +-- .../Transformers/ManufacturersTransformer.php | 2 +- .../PredefinedKitsTransformer.php | 2 +- app/Http/Transformers/ProfileTransformer.php | 2 +- .../Transformers/StatuslabelsTransformer.php | 2 +- app/Http/Transformers/UsersTransformer.php | 6 ++-- app/Mail/CheckoutAssetMail.php | 4 +-- app/Mail/CheckoutLicenseMail.php | 4 +-- app/Models/Labels/FieldOption.php | 4 +-- app/Notifications/AuditNotification.php | 6 ++-- .../CheckinAccessoryNotification.php | 8 ++--- .../CheckinAssetNotification.php | 6 ++-- .../CheckinComponentNotification.php | 16 +++++----- .../CheckinLicenseSeatNotification.php | 16 +++++----- .../CheckoutAccessoryNotification.php | 8 ++--- .../CheckoutAssetNotification.php | 8 ++--- .../CheckoutComponentNotification.php | 14 ++++---- .../CheckoutConsumableNotification.php | 14 ++++---- .../CheckoutLicenseSeatNotification.php | 12 +++---- app/Notifications/RequestAssetCancelation.php | 2 +- .../RequestAssetNotification.php | 2 +- app/Presenters/Presenter.php | 31 +++++++++++++++--- app/Presenters/UserPresenter.php | 32 +++++++++---------- app/Providers/BreadcrumbsServiceProvider.php | 6 ++-- database/factories/UserFactory.php | 3 +- resources/views/account/profile.blade.php | 2 +- resources/views/account/view-assets.blade.php | 12 +++---- .../views/blade/full-user-name.blade.php | 22 ++++++------- resources/views/hardware/requested.blade.php | 2 +- resources/views/hardware/view.blade.php | 4 +-- resources/views/layouts/default.blade.php | 2 +- resources/views/locations/print.blade.php | 8 ++--- .../mail/markdown/checkin-accessory.blade.php | 4 +-- .../mail/markdown/checkin-asset.blade.php | 4 +-- .../mail/markdown/checkin-component.blade.php | 4 +-- .../mail/markdown/checkin-license.blade.php | 4 +-- .../checkout-acceptance-response.blade.php | 4 +-- .../markdown/checkout-accessory.blade.php | 4 +-- .../mail/markdown/checkout-asset.blade.php | 2 +- .../markdown/checkout-component.blade.php | 4 +-- .../markdown/checkout-consumable.blade.php | 4 +-- .../mail/markdown/checkout-license.blade.php | 2 +- resources/views/models/view.blade.php | 2 +- .../markdown/asset-requested.blade.php | 2 +- .../views/users/confirm-bulk-delete.blade.php | 2 +- resources/views/users/confirm-merge.blade.php | 2 +- resources/views/users/edit.blade.php | 4 +-- resources/views/users/print.blade.php | 6 ++-- resources/views/users/view.blade.php | 14 ++++---- .../Console/SendAcceptanceReminderTest.php | 2 +- .../Unit/BladeComponents/UserFullNameTest.php | 12 ++++--- 72 files changed, 217 insertions(+), 199 deletions(-) diff --git a/app/Console/Commands/SendAcceptanceReminder.php b/app/Console/Commands/SendAcceptanceReminder.php index c1cf4ffda2..67efecbb34 100644 --- a/app/Console/Commands/SendAcceptanceReminder.php +++ b/app/Console/Commands/SendAcceptanceReminder.php @@ -77,7 +77,7 @@ class SendAcceptanceReminder extends Command if(!$email){ $no_email_list[] = [ 'id' => $acceptance->assignedTo?->id, - 'name' => $acceptance->assignedTo?->present()->fullName(), + 'name' => $acceptance->assignedTo?->display_name, ]; } else { $count++; diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index f0fadb84c4..0c2260cfd3 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -609,7 +609,7 @@ class AssetsController extends Controller $asset->use_text = $asset->present()->fullName; if (($asset->checkedOutToUser()) && ($asset->assigned)) { - $asset->use_text .= ' β†’ ' . $asset->assigned->getFullNameAttribute(); + $asset->use_text .= ' β†’ ' . $asset->assigned->display_name; } diff --git a/app/Http/Controllers/Api/ConsumablesController.php b/app/Http/Controllers/Api/ConsumablesController.php index 35fb08470a..e163f080aa 100644 --- a/app/Http/Controllers/Api/ConsumablesController.php +++ b/app/Http/Controllers/Api/ConsumablesController.php @@ -230,13 +230,13 @@ class ConsumablesController extends Controller 'avatar' => ($consumable_assignment->user) ? e($consumable_assignment->user->present()->gravatar) : '', 'user' => ($consumable_assignment->user) ? [ 'id' => (int) $consumable_assignment->user->id, - 'name'=> e($consumable_assignment->user->present()->fullName()), + 'name'=> e($consumable_assignment->user->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'), 'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null, 'created_by' => ($consumable_assignment->adminuser) ? [ 'id' => (int) $consumable_assignment->adminuser->id, - 'name'=> e($consumable_assignment->adminuser->present()->fullName()), + 'name'=> e($consumable_assignment->adminuser->display_name), ] : null, ]; } diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 133937ed75..ac9c6add7b 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -361,6 +361,7 @@ class UsersController extends Controller 'users.employee_num', 'users.first_name', 'users.last_name', + 'users.display_name', 'users.gravatar', 'users.avatar', 'users.email', @@ -371,20 +372,17 @@ class UsersController extends Controller $users = $users->where(function ($query) use ($request) { $query->SimpleNameSearch($request->get('search')) ->orWhere('username', 'LIKE', '%'.$request->get('search').'%') + ->orWhere('display_name', 'LIKE', '%'.$request->get('search').'%') ->orWhere('email', 'LIKE', '%'.$request->get('search').'%') ->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%'); }); } - $users = $users->orderBy('last_name', 'asc')->orderBy('first_name', 'asc'); + $users = $users->orderBy('display_name', 'asc')->orderBy('last_name', 'asc')->orderBy('first_name', 'asc'); $users = $users->paginate(50); foreach ($users as $user) { - $name_str = ''; - if ($user->last_name != '') { - $name_str .= $user->last_name.', '; - } - $name_str .= $user->first_name; + $name_str = $user->display_name; if ($user->username != '') { $name_str .= ' ('.$user->username.')'; diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index 67b6bfb4e0..afc16a73ca 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -797,7 +797,7 @@ class AssetsController extends Controller 'item_id' => $asset->id, 'item_type' => Asset::class, 'created_by' => auth()->id(), - 'note' => 'Checkout imported by '.auth()->user()->present()->fullName().' from history importer', + 'note' => 'Checkout imported by '.auth()->user()->display_name.' from history importer', 'target_id' => $item[$asset_tag][$batch_counter]['user_id'], 'target_type' => User::class, 'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'], @@ -825,7 +825,7 @@ class AssetsController extends Controller 'item_id' => $item[$asset_tag][$batch_counter]['asset_id'], 'item_type' => Asset::class, 'created_by' => auth()->id(), - 'note' => 'Checkin imported by '.auth()->user()->present()->fullName().' from history importer', + 'note' => 'Checkin imported by '.auth()->user()->display_name.' from history importer', 'target_id' => null, 'created_at' => $checkin_date, 'action_type' => 'checkin', diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php index d67f2a0be1..98a65f5ad4 100755 --- a/app/Http/Controllers/Licenses/LicensesController.php +++ b/app/Http/Controllers/Licenses/LicensesController.php @@ -364,7 +364,7 @@ class LicensesController extends Controller $license->order_number, $license->free_seat_count, $license->seats, - ($license->adminuser ? $license->adminuser->present()->fullName() : trans('admin/reports/general.deleted_user')), + ($license->adminuser ? $license->adminuser->display_name : trans('admin/reports/general.deleted_user')), $license->depreciation ? $license->depreciation->name: '', $license->updated_at, $license->deleted_at, diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index 954b7cb64c..6883e8cea3 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -275,7 +275,7 @@ class ReportsController extends Controller if ($actionlog->target) { if ($actionlog->targetType() == 'user') { - $target_name = $actionlog->target->getFullNameAttribute(); + $target_name = $actionlog->target->display_name; } else { $target_name = $actionlog->target->getDisplayNameAttribute(); } @@ -289,7 +289,7 @@ class ReportsController extends Controller $row = [ $actionlog->created_at, - ($actionlog->adminuser) ? e($actionlog->adminuser->getFullNameAttribute()) : '', + ($actionlog->adminuser) ? e($actionlog->adminuser->display_name) : '', $actionlog->present()->actionType(), e($actionlog->itemType()), ($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name, @@ -856,7 +856,7 @@ class ReportsController extends Controller } if ($request->filled('assigned_to')) { - $row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : ''); + $row[] = ($asset->checkedOutToUser() && $asset->assigned) ?? $asset->assigned->display_name; $row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType(); } diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 35ef7d3e68..ec87d3ec99 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -564,10 +564,10 @@ class UsersController extends Controller $user->employee_num, $user->first_name, $user->last_name, - $user->present()->fullName(), + $user->display_name, $user->username, $user->email, - ($user->manager) ? $user->manager->present()->fullName() : '', + ($user->manager) ? $user->manager->display_name : '', ($user->userloc) ? $user->userloc->name : '', ($user->department) ? $user->department->name : '', $user->assets->count(), diff --git a/app/Http/Controllers/ViewAssetsController.php b/app/Http/Controllers/ViewAssetsController.php index c4e72971b4..2b767650ad 100755 --- a/app/Http/Controllers/ViewAssetsController.php +++ b/app/Http/Controllers/ViewAssetsController.php @@ -185,7 +185,7 @@ class ViewAssetsController extends Controller $logaction->target_type = User::class; $data['item_quantity'] = $request->has('request-quantity') ? e($request->input('request-quantity')) : 1; - $data['requested_by'] = $user->present()->fullName(); + $data['requested_by'] = $user->display_name; $data['item'] = $item; $data['item_type'] = $itemType; $data['target'] = auth()->user(); diff --git a/app/Http/Transformers/AccessoriesTransformer.php b/app/Http/Transformers/AccessoriesTransformer.php index b502490884..491871e122 100644 --- a/app/Http/Transformers/AccessoriesTransformer.php +++ b/app/Http/Transformers/AccessoriesTransformer.php @@ -44,7 +44,7 @@ class AccessoriesTransformer 'checkouts_count' => $accessory->checkouts_count, 'created_by' => ($accessory->adminuser) ? [ 'id' => (int) $accessory->adminuser->id, - 'name'=> e($accessory->adminuser->present()->fullName()), + 'name'=> e($accessory->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'), diff --git a/app/Http/Transformers/ActionlogsTransformer.php b/app/Http/Transformers/ActionlogsTransformer.php index 64086ca46e..5f0007310c 100644 --- a/app/Http/Transformers/ActionlogsTransformer.php +++ b/app/Http/Transformers/ActionlogsTransformer.php @@ -150,7 +150,7 @@ class ActionlogsTransformer 'item' => ($actionlog->item) ? [ 'id' => (int) $actionlog->item->id, - 'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()), + 'name' => e($actionlog->item->display_name) ?? null, 'type' => e($actionlog->itemType()), 'serial' =>e($actionlog->item->serial) ? e($actionlog->item->serial) : null ] : null, @@ -165,19 +165,19 @@ class ActionlogsTransformer 'action_type' => $actionlog->present()->actionType(), 'admin' => ($actionlog->adminuser) ? [ 'id' => (int) $actionlog->adminuser->id, - 'name' => e($actionlog->adminuser->getFullNameAttribute()), + 'name' => e($actionlog->adminuser->display_name), 'first_name'=> e($actionlog->adminuser->first_name), 'last_name'=> e($actionlog->adminuser->last_name) ] : null, 'created_by' => ($actionlog->adminuser) ? [ 'id' => (int) $actionlog->adminuser->id, - 'name' => e($actionlog->adminuser->getFullNameAttribute()), + 'name' => e($actionlog->adminuser->display_name), 'first_name'=> e($actionlog->adminuser->first_name), 'last_name'=> e($actionlog->adminuser->last_name) ] : null, 'target' => ($actionlog->target) ? [ 'id' => (int) $actionlog->target->id, - 'name' => ($actionlog->targetType()=='user') ? e($actionlog->target->getFullNameAttribute()) : e($actionlog->target->getDisplayNameAttribute()), + 'name' => ($actionlog->target->display_name) ?? null, 'type' => e($actionlog->targetType()), ] : null, diff --git a/app/Http/Transformers/AssetModelsTransformer.php b/app/Http/Transformers/AssetModelsTransformer.php index 2d47ca47db..81814c5ee1 100644 --- a/app/Http/Transformers/AssetModelsTransformer.php +++ b/app/Http/Transformers/AssetModelsTransformer.php @@ -68,7 +68,7 @@ class AssetModelsTransformer 'notes' => Helper::parseEscapedMarkedownInline($assetmodel->notes), 'created_by' => ($assetmodel->adminuser) ? [ 'id' => (int) $assetmodel->adminuser->id, - 'name'=> e($assetmodel->adminuser->present()->fullName()), + 'name'=> e($assetmodel->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($assetmodel->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($assetmodel->updated_at, 'datetime'), diff --git a/app/Http/Transformers/AssetsTransformer.php b/app/Http/Transformers/AssetsTransformer.php index 976aff94f1..af33a42694 100644 --- a/app/Http/Transformers/AssetsTransformer.php +++ b/app/Http/Transformers/AssetsTransformer.php @@ -84,7 +84,7 @@ class AssetsTransformer 'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null, 'created_by' => ($asset->adminuser) ? [ 'id' => (int) $asset->adminuser->id, - 'name'=> e($asset->adminuser->present()->fullName()), + 'name'=> e($asset->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($asset->updated_at, 'datetime'), @@ -280,7 +280,7 @@ class AssetsTransformer 'id' => (int) $asset->id, 'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null, 'type' => 'asset', - 'name' => e($asset->present()->fullName()), + 'name' => e($asset->display_name), 'model' => ($asset->model) ? e($asset->model->name) : null, 'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null, 'asset_tag' => e($asset->asset_tag), diff --git a/app/Http/Transformers/CategoriesTransformer.php b/app/Http/Transformers/CategoriesTransformer.php index 0d1834649d..348c5d4552 100644 --- a/app/Http/Transformers/CategoriesTransformer.php +++ b/app/Http/Transformers/CategoriesTransformer.php @@ -64,7 +64,7 @@ class CategoriesTransformer 'licenses_count' => (int) $category->licenses_count, 'created_by' => ($category->adminuser) ? [ 'id' => (int) $category->adminuser->id, - 'name'=> e($category->adminuser->present()->fullName()), + 'name'=> e($category->adminuser->display_name), ] : null, 'notes' => Helper::parseEscapedMarkedownInline($category->notes), 'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'), diff --git a/app/Http/Transformers/CompaniesTransformer.php b/app/Http/Transformers/CompaniesTransformer.php index 8ca5344de6..13f9a05e27 100644 --- a/app/Http/Transformers/CompaniesTransformer.php +++ b/app/Http/Transformers/CompaniesTransformer.php @@ -38,7 +38,7 @@ class CompaniesTransformer 'users_count' => (int) $company->users_count, 'created_by' => ($company->adminuser) ? [ 'id' => (int) $company->adminuser->id, - 'name'=> e($company->adminuser->present()->fullName()), + 'name'=> e($company->adminuser->display_name), ] : null, 'notes' => Helper::parseEscapedMarkedownInline($company->notes), 'created_at' => Helper::getFormattedDateObject($company->created_at, 'datetime'), diff --git a/app/Http/Transformers/ComponentsTransformer.php b/app/Http/Transformers/ComponentsTransformer.php index 90d10ba9a5..969a137f5c 100644 --- a/app/Http/Transformers/ComponentsTransformer.php +++ b/app/Http/Transformers/ComponentsTransformer.php @@ -51,7 +51,7 @@ class ComponentsTransformer 'notes' => ($component->notes) ? Helper::parseEscapedMarkedownInline($component->notes) : null, 'created_by' => ($component->adminuser) ? [ 'id' => (int) $component->adminuser->id, - 'name'=> e($component->adminuser->present()->fullName()), + 'name'=> e($component->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'), diff --git a/app/Http/Transformers/ConsumablesTransformer.php b/app/Http/Transformers/ConsumablesTransformer.php index 8a40606c87..4c7dbf9cc5 100644 --- a/app/Http/Transformers/ConsumablesTransformer.php +++ b/app/Http/Transformers/ConsumablesTransformer.php @@ -42,7 +42,7 @@ class ConsumablesTransformer 'notes' => ($consumable->notes) ? Helper::parseEscapedMarkedownInline($consumable->notes) : null, 'created_by' => ($consumable->adminuser) ? [ 'id' => (int) $consumable->adminuser->id, - 'name'=> e($consumable->adminuser->present()->fullName()), + 'name'=> e($consumable->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'), diff --git a/app/Http/Transformers/DepartmentsTransformer.php b/app/Http/Transformers/DepartmentsTransformer.php index 3d1e4c6f90..e072585a12 100644 --- a/app/Http/Transformers/DepartmentsTransformer.php +++ b/app/Http/Transformers/DepartmentsTransformer.php @@ -35,7 +35,7 @@ class DepartmentsTransformer ] : null, 'manager' => ($department->manager) ? [ 'id' => (int) $department->manager->id, - 'name' => e($department->manager->getFullNameAttribute()), + 'name' => e($department->manager->display_name), 'first_name'=> e($department->manager->first_name), 'last_name'=> e($department->manager->last_name), ] : null, diff --git a/app/Http/Transformers/DepreciationsTransformer.php b/app/Http/Transformers/DepreciationsTransformer.php index af153539e2..3b0d68392c 100644 --- a/app/Http/Transformers/DepreciationsTransformer.php +++ b/app/Http/Transformers/DepreciationsTransformer.php @@ -33,7 +33,7 @@ class DepreciationsTransformer 'licenses_count' => ($depreciation->licenses_count > 0) ? (int) $depreciation->licenses_count : 0, 'created_by' => ($depreciation->adminuser) ? [ 'id' => (int) $depreciation->adminuser->id, - 'name'=> e($depreciation->adminuser->present()->fullName()), + 'name'=> e($depreciation->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime') diff --git a/app/Http/Transformers/GroupsTransformer.php b/app/Http/Transformers/GroupsTransformer.php index 9495aeeecc..7593926155 100644 --- a/app/Http/Transformers/GroupsTransformer.php +++ b/app/Http/Transformers/GroupsTransformer.php @@ -29,7 +29,7 @@ class GroupsTransformer 'notes' => Helper::parseEscapedMarkedownInline($group->notes), 'created_by' => ($group->adminuser) ? [ 'id' => (int) $group->adminuser->id, - 'name'=> e($group->adminuser->present()->fullName()), + 'name'=> e($group->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'), diff --git a/app/Http/Transformers/LicensesTransformer.php b/app/Http/Transformers/LicensesTransformer.php index af2e902087..678c491257 100644 --- a/app/Http/Transformers/LicensesTransformer.php +++ b/app/Http/Transformers/LicensesTransformer.php @@ -48,7 +48,7 @@ class LicensesTransformer 'category' => ($license->category) ? ['id' => (int) $license->category->id, 'name'=> e($license->category->name)] : null, 'created_by' => ($license->adminuser) ? [ 'id' => (int) $license->adminuser->id, - 'name'=> e($license->adminuser->present()->fullName()), + 'name'=> e($license->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'), diff --git a/app/Http/Transformers/MaintenancesTransformer.php b/app/Http/Transformers/MaintenancesTransformer.php index c2fc8a0e14..c20c254869 100644 --- a/app/Http/Transformers/MaintenancesTransformer.php +++ b/app/Http/Transformers/MaintenancesTransformer.php @@ -73,11 +73,11 @@ class MaintenancesTransformer 'completion_date' => Helper::getFormattedDateObject($assetmaintenance->completion_date, 'date'), 'user_id' => ($assetmaintenance->adminuser) ? [ 'id' => $assetmaintenance->adminuser->id, - 'name'=> e($assetmaintenance->adminuser->present()->fullName()) + 'name'=> e($assetmaintenance->adminuser->display_name) ] : null, // legacy to not change the shape of the API 'created_by' => ($assetmaintenance->adminuser) ? [ 'id' => (int) $assetmaintenance->adminuser->id, - 'name'=> e($assetmaintenance->adminuser->present()->fullName()), + 'name'=> e($assetmaintenance->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'), diff --git a/app/Http/Transformers/ManufacturersTransformer.php b/app/Http/Transformers/ManufacturersTransformer.php index cf17eb7764..0d1373414c 100644 --- a/app/Http/Transformers/ManufacturersTransformer.php +++ b/app/Http/Transformers/ManufacturersTransformer.php @@ -40,7 +40,7 @@ class ManufacturersTransformer 'notes' => Helper::parseEscapedMarkedownInline($manufacturer->notes), 'created_by' => ($manufacturer->adminuser) ? [ 'id' => (int) $manufacturer->adminuser->id, - 'name'=> e($manufacturer->adminuser->present()->fullName()), + 'name'=> e($manufacturer->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($manufacturer->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($manufacturer->updated_at, 'datetime'), diff --git a/app/Http/Transformers/PredefinedKitsTransformer.php b/app/Http/Transformers/PredefinedKitsTransformer.php index 61c9e476a9..3660ff269e 100644 --- a/app/Http/Transformers/PredefinedKitsTransformer.php +++ b/app/Http/Transformers/PredefinedKitsTransformer.php @@ -34,7 +34,7 @@ class PredefinedKitsTransformer 'name' => e($kit->name), 'created_by' => ($kit->adminuser) ? [ 'id' => (int) $kit->adminuser->id, - 'name'=> e($kit->adminuser->present()->fullName()), + 'name'=> e($kit->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($kit->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($kit->updated_at, 'datetime'), diff --git a/app/Http/Transformers/ProfileTransformer.php b/app/Http/Transformers/ProfileTransformer.php index 9b1104515c..a0c07e699f 100644 --- a/app/Http/Transformers/ProfileTransformer.php +++ b/app/Http/Transformers/ProfileTransformer.php @@ -26,7 +26,7 @@ class ProfileTransformer 'id' => (int) $file->id, 'icon' => Helper::filetype_icon($file->filename), 'item' => ($file->item) ? [ - 'name' => ($file->itemType()=='user') ? e($file->item->getFullNameAttribute()) : e($file->item->getDisplayNameAttribute()), + 'name' => ($file->itemType()=='user') ? e($file->item->display_name) : e($file->item->getDisplayNameAttribute()), 'type' => e($file->itemType()), ] : null, 'filename' => e($file->filename), diff --git a/app/Http/Transformers/StatuslabelsTransformer.php b/app/Http/Transformers/StatuslabelsTransformer.php index 751edb7016..6409795994 100644 --- a/app/Http/Transformers/StatuslabelsTransformer.php +++ b/app/Http/Transformers/StatuslabelsTransformer.php @@ -32,7 +32,7 @@ class StatuslabelsTransformer 'notes' => e($statuslabel->notes), 'created_by' => ($statuslabel->adminuser) ? [ 'id' => (int) $statuslabel->adminuser->id, - 'name'=> e($statuslabel->adminuser->present()->fullName()), + 'name'=> e($statuslabel->adminuser->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'), diff --git a/app/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index a4c1cdfbc6..bef81320a5 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -34,14 +34,14 @@ class UsersTransformer '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, + 'display_name' => e($user->getRawOriginal('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, 'manager' => ($user->manager) ? [ 'id' => (int) $user->manager->id, - 'name'=> e($user->manager->first_name).' '.e($user->manager->last_name), + 'name'=> e($user->manager->display_name), ] : null, 'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null, 'vip' => ($user->vip == '1') ? true : false, @@ -83,7 +83,7 @@ class UsersTransformer 'company' => ($user->company) ? ['id' => (int) $user->company->id, 'name'=> e($user->company->name)] : null, 'created_by' => ($user->createdBy) ? [ 'id' => (int) $user->createdBy->id, - 'name'=> e($user->createdBy->present()->fullName), + 'name'=> e($user->createdBy->display_name), ] : null, 'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'), diff --git a/app/Mail/CheckoutAssetMail.php b/app/Mail/CheckoutAssetMail.php index fae935ceb7..72a96ee271 100644 --- a/app/Mail/CheckoutAssetMail.php +++ b/app/Mail/CheckoutAssetMail.php @@ -38,10 +38,10 @@ class CheckoutAssetMail extends Mailable // Location is a target option, but there are no emails currently associated with locations. if($this->target instanceof User){ - $this->target = $this->target->present()?->fullName(); + $this->target = $this->target->display_name; } else if($this->target instanceof Asset){ - $this->target = $this->target->assignedto?->present()?->fullName(); + $this->target = $this->target->assignedto?->display_name; } $this->last_checkout = ''; diff --git a/app/Mail/CheckoutLicenseMail.php b/app/Mail/CheckoutLicenseMail.php index e0701413e7..f3688bae5a 100644 --- a/app/Mail/CheckoutLicenseMail.php +++ b/app/Mail/CheckoutLicenseMail.php @@ -31,10 +31,10 @@ class CheckoutLicenseMail extends Mailable $this->target = $checkedOutTo; if($this->target instanceof User){ - $this->target = $this->target->present()?->fullName(); + $this->target = $this->target->display_name; } elseif($this->target instanceof Asset){ - $this->target = $this->target->assignedto?->present()?->fullName(); + $this->target = $this->target->display_name; } } diff --git a/app/Models/Labels/FieldOption.php b/app/Models/Labels/FieldOption.php index 916707b21d..cf65af57ba 100644 --- a/app/Models/Labels/FieldOption.php +++ b/app/Models/Labels/FieldOption.php @@ -30,10 +30,10 @@ class FieldOption if ($asset->relationLoaded('assignedTo')) { // If the "assignedTo" relationship was eager loaded then the way to get the // relationship changes from $asset->assignedTo to $asset->assigned. - return $asset->assigned ? $asset->assigned->present()->fullName() : null; + return $asset->assigned ? $asset->assigned->display_name : null; } - return $asset->assignedTo ? $asset->assignedTo->present()->fullName() : null; + return $asset->assignedTo ? $asset->assignedTo->display_name : null; } // Handle Laravel's stupid Carbon datetime casting diff --git a/app/Notifications/AuditNotification.php b/app/Notifications/AuditNotification.php index a7056e8cbd..6a09986030 100644 --- a/app/Notifications/AuditNotification.php +++ b/app/Notifications/AuditNotification.php @@ -64,7 +64,7 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage; $item = $this->params['item']; $admin_user = $this->params['admin']; $fields = [ - 'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->present()->fullName().'>', + 'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->display_name.'>', ]; array_key_exists('note', $this->params) && $fields['Notes'] = $this->params['note']; array_key_exists('location', $this->params) && $fields['Location'] = $this->params['location']; @@ -89,9 +89,9 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage; ->title(class_basename(get_class($params['item'])) . ' Audited') ->addStartGroupToSection('activityText') ->fact(trans('mail.asset'), $item) - ->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->present()->fullName()); + ->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->display_name); } - $message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->present()->fullName(); + $message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->display_name; $details = [ trans('mail.asset') => htmlspecialchars_decode($item->present()->name), trans('mail.notes') => $note ?: '', diff --git a/app/Notifications/CheckinAccessoryNotification.php b/app/Notifications/CheckinAccessoryNotification.php index 5354775d7e..b1ce3be29e 100644 --- a/app/Notifications/CheckinAccessoryNotification.php +++ b/app/Notifications/CheckinAccessoryNotification.php @@ -73,8 +73,8 @@ class CheckinAccessoryNotification extends Notification $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ - trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -109,7 +109,7 @@ class CheckinAccessoryNotification extends Notification ->addStartGroupToSection('activityText') ->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle') ->fact(trans('mail.checked_into'), $item->location->name ? $item->location->name : '') - ->fact(trans('mail.Accessory_Checkin_Notification')." by ", $admin->present()->fullName()) + ->fact(trans('mail.Accessory_Checkin_Notification')." by ", $admin->display_name) ->fact(trans('admin/consumables/general.remaining'), $item->numRemaining()) ->fact(trans('mail.notes'), $note ?: ''); } @@ -118,7 +118,7 @@ class CheckinAccessoryNotification extends Notification $details = [ trans('mail.accessory_name') => htmlspecialchars_decode($item->present()->name), trans('mail.checked_into') => $item->location->name ? $item->location->name : '', - trans('mail.Accessory_Checkin_Notification'). ' by' => $admin->present()->fullName(), + trans('mail.Accessory_Checkin_Notification'). ' by' => $admin->display_name, trans('admin/consumables/general.remaining')=> $item->numRemaining(), trans('mail.notes') => $note ?: '', ]; diff --git a/app/Notifications/CheckinAssetNotification.php b/app/Notifications/CheckinAssetNotification.php index 5de3ff1be8..2ff65134a9 100644 --- a/app/Notifications/CheckinAssetNotification.php +++ b/app/Notifications/CheckinAssetNotification.php @@ -78,7 +78,7 @@ class CheckinAssetNotification extends Notification $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ - trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', trans('general.status') => $item->assetstatus?->name, trans('general.location') => ($item->location) ? $item->location->name : '', ]; @@ -116,7 +116,7 @@ class CheckinAssetNotification extends Notification ->addStartGroupToSection('activityText') ->fact(htmlspecialchars_decode($item->present()->name), '', 'activityText') ->fact(trans('mail.checked_into'), ($item->location) ? $item->location->name : '') - ->fact(trans('mail.Asset_Checkin_Notification') . " by ", $admin->present()->fullName()) + ->fact(trans('mail.Asset_Checkin_Notification') . " by ", $admin->display_name) ->fact(trans('admin/hardware/form.status'), $item->assetstatus?->name) ->fact(trans('mail.notes'), $note ?: ''); } @@ -126,7 +126,7 @@ class CheckinAssetNotification extends Notification $details = [ trans('mail.asset') => htmlspecialchars_decode($item->present()->name), trans('mail.checked_into') => ($item->location) ? $item->location->name : '', - trans('mail.Asset_Checkin_Notification')." by " => $admin->present()->fullName(), + trans('mail.Asset_Checkin_Notification')." by " => $admin->display_name, trans('admin/hardware/form.status') => $item->assetstatus?->name, trans('mail.notes') => $note ?: '', ]; diff --git a/app/Notifications/CheckinComponentNotification.php b/app/Notifications/CheckinComponentNotification.php index 4057c26812..1532d507c7 100644 --- a/app/Notifications/CheckinComponentNotification.php +++ b/app/Notifications/CheckinComponentNotification.php @@ -76,8 +76,8 @@ class CheckinComponentNotification extends Notification if ($admin) { $fields = [ - trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -90,7 +90,7 @@ class CheckinComponentNotification extends Notification } else { $fields = [ - 'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', + 'To' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', 'By' => 'CLI tool', ]; } @@ -119,16 +119,16 @@ class CheckinComponentNotification extends Notification ->title(trans('mail.Component_checkin_notification')) ->addStartGroupToSection('activityText') ->fact(htmlspecialchars_decode($item->present()->name), '', 'header') - ->fact(trans('mail.Component_checkin_notification')." by ", $admin->present()->fullName() ?: 'CLI tool') - ->fact(trans('mail.checkedin_from'), $target->present()->fullName()) + ->fact(trans('mail.Component_checkin_notification')." by ", $admin->display_name ?: 'CLI tool') + ->fact(trans('mail.checkedin_from'), $target->display_name) ->fact(trans('admin/consumables/general.remaining'), $item->numRemaining()) ->fact(trans('mail.notes'), $note ?: ''); } $message = trans('mail.Component_checkin_notification'); $details = [ - trans('mail.checkedin_from')=> $target->present()->fullName(), - trans('mail.Component_checkin_notification')." by " => $admin->present()->fullName() ?: 'CLI tool', + trans('mail.checkedin_from')=> $target->display_name, + trans('mail.Component_checkin_notification')." by " => $admin->display_name ?: 'CLI tool', trans('admin/consumables/general.remaining') => $item->numRemaining(), trans('mail.notes') => $note ?: '', ]; @@ -153,7 +153,7 @@ class CheckinComponentNotification extends Notification Section::create( KeyValue::create( trans('mail.checkedin_from') ?: '', - $target->present()->fullName() ?: '', + $target->display_name ?: '', trans('admin/consumables/general.remaining').': '.$item->numRemaining(), ) ->onClick(route('components.show', $item->id)) diff --git a/app/Notifications/CheckinLicenseSeatNotification.php b/app/Notifications/CheckinLicenseSeatNotification.php index 07c3308dbc..f0110db8ba 100644 --- a/app/Notifications/CheckinLicenseSeatNotification.php +++ b/app/Notifications/CheckinLicenseSeatNotification.php @@ -77,8 +77,8 @@ class CheckinLicenseSeatNotification extends Notification if ($admin) { $fields = [ - trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -91,7 +91,7 @@ class CheckinLicenseSeatNotification extends Notification } else { $fields = [ - 'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', + 'To' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', 'By' => 'CLI tool', ]; } @@ -120,17 +120,17 @@ class CheckinLicenseSeatNotification extends Notification ->title(trans('mail.License_Checkin_Notification')) ->addStartGroupToSection('activityText') ->fact(htmlspecialchars_decode($item->present()->name), '', 'header') - ->fact(trans('mail.License_Checkin_Notification')." by ", $admin->present()->fullName() ?: 'CLI tool') - ->fact(trans('mail.checkedin_from'), $target->present()->fullName()) + ->fact(trans('mail.License_Checkin_Notification')." by ", $admin->display_name ?: 'CLI tool') + ->fact(trans('mail.checkedin_from'), $target->display_name) ->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count()) ->fact(trans('mail.notes'), $note ?: ''); } $message = trans('mail.License_Checkin_Notification'); $details = [ - trans('mail.checkedin_from')=> $target->present()->fullName(), + trans('mail.checkedin_from')=> $target->display_name, trans('mail.license_for') => htmlspecialchars_decode($item->present()->name), - trans('mail.License_Checkin_Notification')." by " => $admin->present()->fullName() ?: 'CLI tool', + trans('mail.License_Checkin_Notification')." by " => $admin->display_name ?: 'CLI tool', trans('admin/consumables/general.remaining') => $item->availCount()->count(), trans('mail.notes') => $note ?: '', ]; @@ -155,7 +155,7 @@ class CheckinLicenseSeatNotification extends Notification Section::create( KeyValue::create( trans('mail.checkedin_from') ?: '', - $target->present()->fullName() ?: '', + $target->display_name ?: '', trans('admin/consumables/general.remaining').': '.$item->availCount()->count(), ) ->onClick(route('licenses.show', $item->id)) diff --git a/app/Notifications/CheckoutAccessoryNotification.php b/app/Notifications/CheckoutAccessoryNotification.php index 016bfc526c..22dc78b2b3 100644 --- a/app/Notifications/CheckoutAccessoryNotification.php +++ b/app/Notifications/CheckoutAccessoryNotification.php @@ -100,8 +100,8 @@ class CheckoutAccessoryNotification extends Notification $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ - trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -140,7 +140,7 @@ class CheckoutAccessoryNotification extends Notification ->fact(trans('mail.assigned_to'), $target->present()->name) ->fact(trans('general.qty'), $this->checkout_qty) ->fact(trans('mail.checkedout_from'), $item->location->name ? $item->location->name : '') - ->fact(trans('mail.Accessory_Checkout_Notification') . " by ", $admin->present()->fullName()) + ->fact(trans('mail.Accessory_Checkout_Notification') . " by ", $admin->display_name) ->fact(trans('admin/consumables/general.remaining'), $item->numRemaining()) ->fact(trans('mail.notes'), $note ?: ''); } @@ -151,7 +151,7 @@ class CheckoutAccessoryNotification extends Notification trans('mail.accessory_name') => htmlspecialchars_decode($item->present()->name), trans('general.qty') => $this->checkout_qty, trans('mail.checkedout_from') => $item->location->name ? $item->location->name : '', - trans('mail.Accessory_Checkout_Notification'). ' by' => $admin->present()->fullName(), + trans('mail.Accessory_Checkout_Notification'). ' by' => $admin->display_name, trans('admin/consumables/general.remaining')=> $item->numRemaining(), trans('mail.notes') => $note ?: '', ]; diff --git a/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php index 8cdfbdd046..70ab74c60e 100644 --- a/app/Notifications/CheckoutAssetNotification.php +++ b/app/Notifications/CheckoutAssetNotification.php @@ -93,8 +93,8 @@ class CheckoutAssetNotification extends Notification $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ - trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -135,7 +135,7 @@ class CheckoutAssetNotification extends Notification ->addStartGroupToSection('activityText') ->fact(trans('mail.assigned_to'), $target->present()->name) ->fact(htmlspecialchars_decode($item->present()->name), '', 'activityText') - ->fact(trans('mail.Asset_Checkout_Notification') . " by ", $admin->present()->fullName()) + ->fact(trans('mail.Asset_Checkout_Notification') . " by ", $admin->display_name) ->fact(trans('mail.notes'), $note ?: ''); } @@ -143,7 +143,7 @@ class CheckoutAssetNotification extends Notification $details = [ trans('mail.assigned_to') => $target->present()->name, trans('mail.asset') => htmlspecialchars_decode($item->present()->name), - trans('mail.Asset_Checkout_Notification'). ' by' => $admin->present()->fullName(), + trans('mail.Asset_Checkout_Notification'). ' by' => $admin->display_name, trans('mail.notes') => $note ?: '', ]; return array($message, $details); diff --git a/app/Notifications/CheckoutComponentNotification.php b/app/Notifications/CheckoutComponentNotification.php index fab303fb52..11f77e9d47 100644 --- a/app/Notifications/CheckoutComponentNotification.php +++ b/app/Notifications/CheckoutComponentNotification.php @@ -80,8 +80,8 @@ class CheckoutComponentNotification extends Notification $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ - trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -117,17 +117,17 @@ class CheckoutComponentNotification extends Notification ->title(trans('mail.Component_checkout_notification')) ->addStartGroupToSection('activityText') ->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle') - ->fact(trans('mail.Component_checkout_notification')." by ", $admin->present()->fullName()) - ->fact(trans('mail.assigned_to'), $target->present()->fullName()) + ->fact(trans('mail.Component_checkout_notification')." by ", $admin->display_name) + ->fact(trans('mail.assigned_to'), $target->display_name) ->fact(trans('admin/consumables/general.remaining'), $item->numRemaining()) ->fact(trans('mail.notes'), $note ?: ''); } $message = trans('mail.Component_checkout_notification'); $details = [ - trans('mail.assigned_to') => $target->present()->fullName(), + trans('mail.assigned_to') => $target->display_name, trans('mail.item') => htmlspecialchars_decode($item->present()->name), - trans('mail.Component_checkout_notification').' by' => $admin->present()->fullName(), + trans('mail.Component_checkout_notification').' by' => $admin->display_name, trans('admin/consumables/general.remaining') => $item->numRemaining(), trans('mail.notes') => $note ?: '', ]; @@ -152,7 +152,7 @@ class CheckoutComponentNotification extends Notification Section::create( KeyValue::create( trans('mail.assigned_to') ?: '', - $target->present()->fullName() ?: '', + $target->display_name ?: '', trans('admin/consumables/general.remaining').': '.$item->numRemaining(), ) ->onClick(route('api.assets.show', $target->id)) diff --git a/app/Notifications/CheckoutConsumableNotification.php b/app/Notifications/CheckoutConsumableNotification.php index e8db8b8bd1..0274bbeecf 100644 --- a/app/Notifications/CheckoutConsumableNotification.php +++ b/app/Notifications/CheckoutConsumableNotification.php @@ -80,8 +80,8 @@ class CheckoutConsumableNotification extends Notification $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ - trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -117,17 +117,17 @@ class CheckoutConsumableNotification extends Notification ->title(trans('mail.Consumable_checkout_notification')) ->addStartGroupToSection('activityText') ->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle') - ->fact(trans('mail.Consumable_checkout_notification')." by ", $admin->present()->fullName()) - ->fact(trans('mail.assigned_to'), $target->present()->fullName()) + ->fact(trans('mail.Consumable_checkout_notification')." by ", $admin->display_name) + ->fact(trans('mail.assigned_to'), $target->display_name) ->fact(trans('admin/consumables/general.remaining'), $item->numRemaining()) ->fact(trans('mail.notes'), $note ?: ''); } $message = trans('mail.Consumable_checkout_notification'); $details = [ - trans('mail.assigned_to') => $target->present()->fullName(), + trans('mail.assigned_to') => $target->display_name, trans('mail.item') => htmlspecialchars_decode($item->present()->name), - trans('mail.Consumable_checkout_notification').' by' => $admin->present()->fullName(), + trans('mail.Consumable_checkout_notification').' by' => $admin->display_name, trans('admin/consumables/general.remaining') => $item->numRemaining(), trans('mail.notes') => $note ?: '', ]; @@ -152,7 +152,7 @@ class CheckoutConsumableNotification extends Notification Section::create( KeyValue::create( trans('mail.assigned_to') ?: '', - $target->present()->fullName() ?: '', + $target->display_name ?: '', trans('admin/consumables/general.remaining').': '.$item->numRemaining(), ) ->onClick(route('users.show', $target->id)) diff --git a/app/Notifications/CheckoutLicenseSeatNotification.php b/app/Notifications/CheckoutLicenseSeatNotification.php index fa00421885..4fc2ab7def 100644 --- a/app/Notifications/CheckoutLicenseSeatNotification.php +++ b/app/Notifications/CheckoutLicenseSeatNotification.php @@ -78,8 +78,8 @@ class CheckoutLicenseSeatNotification extends Notification $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ - trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', - trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', + trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', + trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>', ]; if ($item->location) { @@ -115,17 +115,17 @@ class CheckoutLicenseSeatNotification extends Notification ->title(trans('mail.License_Checkout_Notification')) ->addStartGroupToSection('activityText') ->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle') - ->fact(trans('mail.License_Checkout_Notification')." by ", $admin->present()->fullName()) - ->fact(trans('mail.assigned_to'), $target->present()->fullName()) + ->fact(trans('mail.License_Checkout_Notification')." by ", $admin->display_name) + ->fact(trans('mail.assigned_to'), $target->display_name) ->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count()) ->fact(trans('mail.notes'), $note ?: ''); } $message = trans('mail.License_Checkout_Notification'); $details = [ - trans('mail.assigned_to') => $target->present()->fullName(), + trans('mail.assigned_to') => $target->display_name, trans('mail.license_for') => htmlspecialchars_decode($item->present()->name), - trans('mail.License_Checkout_Notification').' by' => $admin->present()->fullName(), + trans('mail.License_Checkout_Notification').' by' => $admin->display_name, trans('admin/consumables/general.remaining') => $item->availCount()->count(), trans('mail.notes') => $note ?: '', ]; diff --git a/app/Notifications/RequestAssetCancelation.php b/app/Notifications/RequestAssetCancelation.php index 6c06ede3ca..0211b17e4e 100644 --- a/app/Notifications/RequestAssetCancelation.php +++ b/app/Notifications/RequestAssetCancelation.php @@ -79,7 +79,7 @@ class RequestAssetCancelation extends Notification $fields = [ 'QTY' => $qty, - 'Canceled By' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', + 'Canceled By' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', ]; if (($this->expected_checkin) && ($this->expected_checkin != '')) { diff --git a/app/Notifications/RequestAssetNotification.php b/app/Notifications/RequestAssetNotification.php index d2001f2e13..e3c99c56f6 100644 --- a/app/Notifications/RequestAssetNotification.php +++ b/app/Notifications/RequestAssetNotification.php @@ -78,7 +78,7 @@ class RequestAssetNotification extends Notification $fields = [ 'QTY' => $qty, - 'Requested By' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>', + 'Requested By' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>', ]; return (new SlackMessage) diff --git a/app/Presenters/Presenter.php b/app/Presenters/Presenter.php index 85fe2338ae..13bae66ecd 100644 --- a/app/Presenters/Presenter.php +++ b/app/Presenters/Presenter.php @@ -3,6 +3,7 @@ namespace App\Presenters; use App\Models\SnipeModel; +use Illuminate\Database\Eloquent\Casts\Attribute; abstract class Presenter { @@ -69,10 +70,30 @@ abstract class Presenter return ''; } - public function name() - { - return $this->model->name; - } +// public function name() +// { +// return $this->model->name; +// } +// +// public function display_name() +// { +// return $this->model->display_name; +// } + + +// protected function displayName(): Attribute +// { +// // This override should only kick in if the model has a display_name prope +// if ($this->getRawOriginal('display_name')) { +// return Attribute:: make ( +// get: fn(mixed $value) => 'Poop:'.$this->display_name +// ); +// } +// +// return Attribute:: make( +// get: fn(mixed $value) => 'Fart: '.$this->name, +// ); +// } public function __get($property) { @@ -80,7 +101,7 @@ abstract class Presenter return $this->{$property}(); } - return e($this->model->{$property}); + return $this->model->{$property}; } public function __call($method, $args) diff --git a/app/Presenters/UserPresenter.php b/app/Presenters/UserPresenter.php index 8eb28091c5..296fafe568 100644 --- a/app/Presenters/UserPresenter.php +++ b/app/Presenters/UserPresenter.php @@ -456,23 +456,23 @@ class UserPresenter extends Presenter * * @return string */ - 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'); - } +// public function fullName() +// { +// if ($this->display_name) { +// return 'kjdfh'.html_entity_decode($this->display_name, ENT_QUOTES | ENT_XML1, 'UTF-8'); +// } +// return 'roieuoe'.html_entity_decode($this->first_name.' '.$this->last_name, ENT_QUOTES | ENT_XML1, 'UTF-8'); +// } - /** - * Standard accessor. - * @TODO Remove presenter::fullName() entirely? - * @return string - */ - public function name() - { - return $this->fullName(); - } +// /** +// * Standard accessor. +// * @TODO Remove presenter::fullName() entirely? +// * @return string +// */ +// public function name() +// { +// return $this->fullName(); +// } diff --git a/app/Providers/BreadcrumbsServiceProvider.php b/app/Providers/BreadcrumbsServiceProvider.php index e7b41a8fca..a5092b3ded 100644 --- a/app/Providers/BreadcrumbsServiceProvider.php +++ b/app/Providers/BreadcrumbsServiceProvider.php @@ -74,12 +74,12 @@ class BreadcrumbsServiceProvider extends ServiceProvider Breadcrumbs::for('hardware.show', fn (Trail $trail, Asset $asset) => $trail->parent('hardware.index', route('hardware.index')) - ->push($asset->present()->fullName(), route('hardware.show', $asset)) + ->push($asset->display_name, route('hardware.show', $asset)) ); Breadcrumbs::for('hardware.edit', fn (Trail $trail, Asset $asset) => $trail->parent('hardware.index', route('hardware.index')) - ->push($asset->present()->fullName(), route('hardware.show', $asset)) + ->push($asset->display_name, route('hardware.show', $asset)) ->push(trans('admin/hardware/general.edit')) ); @@ -579,7 +579,7 @@ class BreadcrumbsServiceProvider extends ServiceProvider Breadcrumbs::for('users.show', fn (Trail $trail, User $user) => $trail->parent('users.index', route('users.index')) - ->push($user->getFullNameAttribute() ?? 'Missing Username!', route('users.show', $user)) + ->push($user->display_name ?? 'Missing Username!', route('users.show', $user)) ); Breadcrumbs::for('users.edit', fn (Trail $trail, User $user) => diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index b9326fd83a..989fad08f2 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -28,8 +28,9 @@ class UserFactory extends Factory 'email' => $this->faker->safeEmail(), 'employee_num' => $this->faker->numberBetween(3500, 35050), 'first_name' => $this->faker->firstName(), - 'jobtitle' => $this->faker->jobTitle(), 'last_name' => $this->faker->lastName(), + 'display_name' => null, + 'jobtitle' => $this->faker->jobTitle(), 'locale' => 'en-US', 'notes' => 'Created by DB seeder', 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password diff --git a/resources/views/account/profile.blade.php b/resources/views/account/profile.blade.php index abf463ad94..b4aea49918 100755 --- a/resources/views/account/profile.blade.php +++ b/resources/views/account/profile.blade.php @@ -139,7 +139,7 @@ {!! $errors->first('gravatar', '') !!}

- {{ $user->present()->fullName() }} avatar image + {{ $user->display_name }} avatar image {!! trans('general.gravatar_url') !!}

diff --git a/resources/views/account/view-assets.blade.php b/resources/views/account/view-assets.blade.php index 8fa949869e..f71ac7d5df 100755 --- a/resources/views/account/view-assets.blade.php +++ b/resources/views/account/view-assets.blade.php @@ -2,7 +2,7 @@ {{-- Page title --}} @section('title') -{{ trans('general.hello_name', array('name' => $user->present()->getFullNameAttribute())) }} +{{ trans('general.hello_name', array('name' => $user->display_name)) }} @parent @stop @@ -37,7 +37,7 @@ {{ $user->present()->fullName() }} + {{ $user->email }} diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index c38393a246..a4dc6b40cb 100755 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -3,7 +3,7 @@ @section('title') @if ($user->id) {{ trans('admin/users/table.updateuser') }} - {{ $user->present()->fullName() }} + {{ $user->display_name }} @else {{ trans('admin/users/table.createuser') }} @endif @@ -322,7 +322,7 @@ maxlength="191" name="display_name" id="display_name" - value="{{ old('display_name', $user->display_name) }}" + value="{{ old('display_name', $user->getRawOriginal('display_name')) }}" /> {!! $errors->first('display_name', '') !!} diff --git a/resources/views/users/print.blade.php b/resources/views/users/print.blade.php index abd6c53912..935959a400 100644 --- a/resources/views/users/print.blade.php +++ b/resources/views/users/print.blade.php @@ -3,7 +3,7 @@ @if ((isset($users) && count($users) === 1)) - {{ trans('general.assigned_to', ['name' => $users[0]->present()->fullName()]) }} - {{ date('Y-m-d H:i', time()) }} + {{ trans('general.assigned_to', ['name' => $users[0]->display_name]) }} - {{ date('Y-m-d H:i', time()) }} @else {{ trans('admin/users/general.print_assigned') }} - {{ date('Y-m-d H:i', time()) }} @endisset @@ -96,10 +96,10 @@
{{-- used for page breaks when printing --}}

@if ($show_user->company) - {{ trans('admin/companies/table.name') }}: {{ $show_user->company->name }} + {{ trans('admin/companies/table.name') }}: {{ $show_user->company->name }}
@endif - {{ trans('general.assigned_to', ['name' => $show_user->present()->fullName()]) }} + {{ trans('general.assigned_to', ['name' => $show_user->display_name]) }} {{ ($show_user->employee_num!='') ? ' (#'.$show_user->employee_num.') ' : '' }} {{ ($show_user->jobtitle!='' ? ' - '.$show_user->jobtitle : '') }}

diff --git a/resources/views/users/view.blade.php b/resources/views/users/view.blade.php index ea0017869d..6ce7118791 100755 --- a/resources/views/users/view.blade.php +++ b/resources/views/users/view.blade.php @@ -2,7 +2,7 @@ {{-- Page title --}} @section('title') -{{ trans('admin/users/general.view_user', ['name' => $user->present()->fullName()]) }} +{{ trans('admin/users/general.view_user', ['name' => $user->display_name]) }} @parent @stop @@ -179,7 +179,7 @@
- {{ $user->present()->fullName() }} + {{ $user->display_name }}
@can('update', $user) @@ -266,7 +266,7 @@ @if ($user->deleted_at=='')
@if ($user->isDeletable()) - + {{ trans('button.delete')}} @@ -353,7 +353,7 @@ {{ trans('admin/users/table.display_name') }}
- {{ $user->display_name }} + {{ $user->getRawOriginal('display_name') }}
@endif @@ -490,7 +490,7 @@ @@ -613,7 +613,7 @@ @if ($user->createdBy) - @if ($user->createdBy->deleted_at=='') - {{ $user->createdBy->present()->fullName }} + {{ $user->createdBy->display_name }} @else {{ $user->createdBy->present()->fullName }} @endif @@ -838,7 +838,7 @@ class="table table-striped snipe-table" data-url="{{ route('api.assets.index',['assigned_to' => e($user->id), 'assigned_type' => 'App\Models\User']) }}" data-export-options='{ - "fileName": "export-{{ str_slug($user->present()->fullName()) }}-assets-{{ date('Y-m-d') }}", + "fileName": "export-{{ str_slug($user->username) }}-assets-{{ date('Y-m-d') }}", "ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"] }'> diff --git a/tests/Feature/Console/SendAcceptanceReminderTest.php b/tests/Feature/Console/SendAcceptanceReminderTest.php index ee28e09355..6d0a51dd5d 100644 --- a/tests/Feature/Console/SendAcceptanceReminderTest.php +++ b/tests/Feature/Console/SendAcceptanceReminderTest.php @@ -45,7 +45,7 @@ class SendAcceptanceReminderTest extends TestCase ]); $headers = ['ID', 'Name']; $rows = [ - [$userA->id, $userA->present()->fullName()], + [$userA->id, $userA->display_name], ]; $this->artisan('snipeit:acceptance-reminder') ->expectsOutput("The following users do not have an email address:") diff --git a/tests/Unit/BladeComponents/UserFullNameTest.php b/tests/Unit/BladeComponents/UserFullNameTest.php index bbd74c7fa1..feb88ff71d 100644 --- a/tests/Unit/BladeComponents/UserFullNameTest.php +++ b/tests/Unit/BladeComponents/UserFullNameTest.php @@ -17,7 +17,7 @@ class UserFullNameTest extends TestCase function () { return [ 'actor' => User::factory()->viewUsers()->create(), - 'user' => User::factory()->create(['first_name' => 'Jim', 'last_name' => 'Bagg']), + 'user' => User::factory()->create(['first_name' => 'Jim', 'last_name' => 'Bagg', 'display_name' => null]), 'assertions' => function ($rendered) { Assert::assertStringContainsString(' User::factory()->viewUsers()->create(), - 'user' => User::factory()->deleted()->create(['first_name' => 'Jim', 'last_name' => 'Bagg']), + 'user' => User::factory()->deleted()->create(['first_name' => 'Jim', 'last_name' => 'Bagg', 'display_name' => 'Jim Baggins']), 'assertions' => function ($rendered) { Assert::assertStringContainsString(' User::factory()->create(), - 'user' => User::factory()->create(['first_name' => 'Jim', 'last_name' => 'Bagg']), + 'user' => User::factory()->create(['first_name' => 'Jim', 'last_name' => 'Bagg', 'display_name' => 'Jim Bagg']), 'assertions' => function ($rendered) { Assert::assertStringContainsString('Jim Bagg', $rendered); Assert::assertStringNotContainsString(' User::factory()->create(), - 'user' => User::factory()->deleted()->create(['first_name' => 'Jim', 'last_name' => 'Bagg']), + 'user' => User::factory()->deleted()->create(['first_name' => 'Jim', 'last_name' => 'Bagg', 'display_name' => 'Jim Bagg']), 'assertions' => function ($rendered) { Assert::assertStringContainsString('Jim Bagg', $rendered); }, @@ -82,6 +82,10 @@ class UserFullNameTest extends TestCase { ['actor' => $actor, 'user' => $user, 'assertions' => $assertions] = $provided(); + // $user->displayName(); + + // \Log::error($user->toArray()); + $this->actingAs($actor); $renderedTemplateString = View::make('blade.full-user-name', ['user' => $user])->render(); From e60f2b2332c63b399824f859ff65324ee3e51542 Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 25 Aug 2025 15:00:10 +0100 Subject: [PATCH 40/51] Tightened up accessor code for better inheritence Signed-off-by: snipe --- app/Models/SnipeModel.php | 16 +++++----------- app/Models/User.php | 14 +++++++++++++- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/app/Models/SnipeModel.php b/app/Models/SnipeModel.php index da2f5f7a01..ac8e9009aa 100644 --- a/app/Models/SnipeModel.php +++ b/app/Models/SnipeModel.php @@ -156,19 +156,13 @@ class SnipeModel extends Model $this->attributes['status_id'] = $value; } - // 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 + protected function displayName(): Attribute { - // 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, + + return Attribute:: make( + get: fn(mixed $value) => $this->name, ); } + } diff --git a/app/Models/User.php b/app/Models/User.php index 5374b5e284..148a393dc8 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -200,8 +200,20 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo }); } + /** + * This overrides the SnipeModel displayName accessor to return the full name if display_name is not set + * @see SnipeModel::displayName() + * @return Attribute + */ - public function isAvatarExternal() + protected function displayName(): Attribute + { + return Attribute:: make( + get: fn(mixed $value) => $value ?? $this->getFullNameAttribute(), + ); + } + + public function isAvatarExternal() : bool { // Check if it's a google avatar or some external avatar if (Str::startsWith($this->avatar, ['http://', 'https://'])) { From 40108b196c06a17977497ad7af7c553f8797988b Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 25 Aug 2025 15:28:39 +0100 Subject: [PATCH 41/51] Trying to fix import tests :( Signed-off-by: snipe --- .../Feature/Importing/Api/ImportUsersTest.php | 22 +++++++++++++++---- .../Importing/UsersImportFileBuilder.php | 18 ++++++++------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/tests/Feature/Importing/Api/ImportUsersTest.php b/tests/Feature/Importing/Api/ImportUsersTest.php index 1f5ae7a604..fb4f61634e 100644 --- a/tests/Feature/Importing/Api/ImportUsersTest.php +++ b/tests/Feature/Importing/Api/ImportUsersTest.php @@ -77,6 +77,7 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ $this->assertEquals($row['email'], $newUser->email); $this->assertEquals($row['firstName'], $newUser->first_name); $this->assertEquals($row['lastName'], $newUser->last_name); + $this->assertEquals($row['displayName'], $newUser->display_name); $this->assertEquals($row['employeeNumber'], $newUser->employee_num); $this->assertEquals($row['companyName'], $newUser->company->name); $this->assertEquals($row['location'], $newUser->location->name); @@ -229,12 +230,22 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ $updatedUser = User::query()->with(['company', 'location'])->find($user->id); $updatedAttributes = [ - 'first_name', 'email', 'last_name', 'employee_num', 'company', - 'location_id', 'company_id', 'updated_at', 'phone', 'jobtitle' + 'first_name', + 'display_name', + 'email', + 'last_name', + 'employee_num', + 'company', + 'location_id', + 'company_id', + 'updated_at', + 'phone', + 'jobtitle', ]; $this->assertEquals($row['email'], $updatedUser->email); $this->assertEquals($row['firstName'], $updatedUser->first_name); + $this->assertEquals($row['displayName'], $updatedUser->display_name); $this->assertEquals($row['lastName'], $updatedUser->last_name); $this->assertEquals($row['employeeNumber'], $updatedUser->employee_num); $this->assertEquals($row['companyName'], $updatedUser->company->name); @@ -255,14 +266,15 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ $faker = ImportFileBuilder::new()->definition(); $row = [ 'companyName' => $faker['username'], - 'email' => $faker['position'], + 'email' => $faker['email'], 'employeeNumber' => $faker['phoneNumber'], 'firstName' => $faker['location'], 'lastName' => $faker['lastName'], 'location' => $faker['firstName'], 'phoneNumber' => $faker['employeeNumber'], - 'position' => $faker['email'], + 'position' => $faker['position'], 'username' => $faker['companyName'], + 'display_name' => $faker['displayName'], ]; $importFileBuilder = new ImportFileBuilder([$row]); @@ -278,6 +290,7 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ 'Employee Number' => 'phone_number', 'First Name' => 'location', 'Last Name' => 'last_name', + 'Display Name' => 'display_name', 'Location' => 'first_name', 'Phone Number' => 'employee_num', 'Job Title' => 'email', @@ -293,6 +306,7 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ $this->assertEquals($row['position'], $newUser->email); $this->assertEquals($row['location'], $newUser->first_name); $this->assertEquals($row['lastName'], $newUser->last_name); + $this->assertEquals($row['displayName'], $newUser->display_name); $this->assertEquals($row['email'], $newUser->jobtitle); $this->assertEquals($row['phoneNumber'], $newUser->employee_num); $this->assertEquals($row['username'], $newUser->company->name); diff --git a/tests/Support/Importing/UsersImportFileBuilder.php b/tests/Support/Importing/UsersImportFileBuilder.php index 0a00c995c2..99992438af 100644 --- a/tests/Support/Importing/UsersImportFileBuilder.php +++ b/tests/Support/Importing/UsersImportFileBuilder.php @@ -36,6 +36,7 @@ class UsersImportFileBuilder extends FileBuilder 'employeeNumber' => 'Employee Number', 'firstName' => 'First Name', 'lastName' => 'Last Name', + 'displayName' => 'Display Name', 'location' => 'Location', 'phoneNumber' => 'Phone Number', 'position' => 'Job Title', @@ -51,15 +52,16 @@ class UsersImportFileBuilder extends FileBuilder $faker = fake(); return [ - 'companyName' => $faker->company, - 'email' => Str::random(32) . "@{$faker->freeEmailDomain}", - 'employeeNumber' => $faker->uuid, + 'companyName' => $faker->company, + 'email' => Str::random(32) . "@{$faker->freeEmailDomain}", + 'employeeNumber' => $faker->uuid, 'firstName' => $faker->firstName, - 'lastName' => $faker->lastName, - 'location' => "{$faker->city}, {$faker->country}", - 'phoneNumber' => $faker->phoneNumber, - 'position' => $faker->jobTitle, - 'username' => Str::random(), + 'lastName' => $faker->lastName, + 'displayName' => 'Display: '.$faker->name, + 'location' => "{$faker->city}, {$faker->country}", + 'phoneNumber' => $faker->phoneNumber, + 'position' => $faker->jobTitle, + 'username' => Str::random(), ]; } } From 5a16b594621ca64b7952fede38fe4d3a79448bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Aqaba=20=C5=A0tarman?= Date: Mon, 25 Aug 2025 16:47:52 +0200 Subject: [PATCH 42/51] Adds support for label sheets Avery L4736 & L6009 --- app/Models/Labels/Sheets/Avery/L6009.php | 112 +++++++++++++++++++ app/Models/Labels/Sheets/Avery/L6009_A.php | 121 +++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 app/Models/Labels/Sheets/Avery/L6009.php create mode 100644 app/Models/Labels/Sheets/Avery/L6009_A.php diff --git a/app/Models/Labels/Sheets/Avery/L6009.php b/app/Models/Labels/Sheets/Avery/L6009.php new file mode 100644 index 0000000000..c5e5cd9b40 --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/L6009.php @@ -0,0 +1,112 @@ +getUnit(), 0); + $this->pageWidth = $paperSize->width; + $this->pageHeight = $paperSize->height; + + $this->pageMarginLeft = Helper::convertUnit(self::COLUMN1_X, 'pt', $this->getUnit()); + $this->pageMarginTop = Helper::convertUnit(self::ROW1_Y, 'pt', $this->getUnit()); + + $columnSpacingPt = self::COLUMN2_X - self::COLUMN1_X - self::LABEL_W; + $columnSpacingPt = self::COLUMN2_X - self::LABEL_W + 7.15; + $this->columnSpacing = Helper::convertUnit($columnSpacingPt, 'pt', $this->getUnit()); + $rowSpacingPt = self::ROW2_Y - self::ROW1_Y - self::LABEL_H; + $rowSpacingPt = self::ROW2_Y - self::LABEL_H; + $this->rowSpacing = Helper::convertUnit($rowSpacingPt, 'pt', $this->getUnit()); + + $this->labelWidth = Helper::convertUnit(self::LABEL_W, 'pt', $this->getUnit()); + $this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit()); + } + + public function getPageWidth() + { + return $this->pageWidth; + } + public function getPageHeight() + { + return $this->pageHeight; + } + + public function getPageMarginTop() + { + return $this->pageMarginTop; + } + public function getPageMarginBottom() + { + return $this->pageMarginTop; + } + public function getPageMarginLeft() + { + return $this->pageMarginLeft; + } + public function getPageMarginRight() + { + return $this->pageMarginLeft; + } + + public function getColumns() + { + return 4; + } + public function getRows() + { + return 12; + } + + public function getLabelColumnSpacing() + { + return $this->columnSpacing; + } + public function getLabelRowSpacing() + { + return $this->rowSpacing; + } + + public function getLabelWidth() + { + return $this->labelWidth; + } + public function getLabelHeight() + { + return $this->labelHeight; + } + + public function getLabelBorder() + { + return 0; + } +} + +?> diff --git a/app/Models/Labels/Sheets/Avery/L6009_A.php b/app/Models/Labels/Sheets/Avery/L6009_A.php new file mode 100644 index 0000000000..09f3aa8358 --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/L6009_A.php @@ -0,0 +1,121 @@ +getLabelPrintableArea(); + + $currentX = $pa->x1; + $currentY = $pa->y1; + $usableWidth = $pa->w; + $usableHeight = $pa->h; + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $pa->x1, $pa->y1, + 'freesans', '', self::TITLE_SIZE, 'C', + $pa->w, self::TITLE_SIZE, true, 0 + ); + + } + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + $usableHeight -= self::TITLE_SIZE + self::TITLE_MARGIN; + $barcodeSize = $usableHeight; + if ($record->has('barcode2d')) { + static::write2DBarcode( + $pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type, + $currentX, $currentY, + $barcodeSize, $barcodeSize + ); + $currentX += $barcodeSize + self::BARCODE_MARGIN; + $usableWidth -= $barcodeSize + self::BARCODE_MARGIN; + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, $field['label'], + $currentX, $currentY, + 'freesans', '', self::LABEL_SIZE, 'L', + $usableWidth, self::LABEL_SIZE, true, 0 + ); + $currentY += self::LABEL_SIZE + self::LABEL_MARGIN; + + static::writeText( + $pdf, $field['value'], + $currentX, $currentY, + 'freemono', 'B', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.01 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + + } +} + + +?> From 07dbc6842c7b67b4d07998d973201ad497307e6c Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 25 Aug 2025 15:56:28 +0100 Subject: [PATCH 43/51] Are you KIDDING ME, Github?? This reverts commit c8e79aa5ca412edee8dc0f646fac5f78aa3c9808, reversing changes made to e60f2b2332c63b399824f859ff65324ee3e51542. Signed-off-by: snipe --- app/Console/Commands/LdapSync.php | 21 + .../Controllers/Api/SettingsController.php | 1 + app/Http/Controllers/Api/UsersController.php | 10 + app/Http/Controllers/SettingsController.php | 6 + .../Controllers/Users/UsersController.php | 2 + app/Http/Transformers/UsersTransformer.php | 2 +- app/Importer/UserImporter.php | 1 + app/Livewire/Importer.php | 8 + app/Models/SnipeModel.php | 1 + app/Models/SnipeSCIMConfig.php | 24 +- app/Models/User.php | 16 +- app/Presenters/ComponentPresenter.php | 4 +- app/Presenters/UserPresenter.php | 33 + ...08_19_114742_add_display_name_to_users.php | 32 + ...4823_add_display_name_to_ldap_settings.php | 82 + .../lang/en-US/admin/settings/general.php | 53 +- resources/lang/en-US/admin/users/table.php | 1 + resources/views/modals/user.blade.php | 12 + resources/views/settings/ldap.blade.php | 1583 +++++++++-------- resources/views/users/view.blade.php | 44 +- 20 files changed, 1128 insertions(+), 808 deletions(-) create mode 100644 database/migrations/2025_08_19_114742_add_display_name_to_users.php 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..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, @@ -63,11 +65,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; @@ -234,9 +242,11 @@ 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] ?? ''; + $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] ?? ''; @@ -244,8 +254,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["city"]][0] ?? ''; + $item['state'] = $results[$i][$ldap_map["state"]][0] ?? ''; $item['country'] = $results[$i][$ldap_map["country"]][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] ?? ''; @@ -278,6 +293,9 @@ class LdapSync extends Command if($ldap_map["username"] != null){ $user->username = $item['username']; } + if($ldap_map["display_name"] != null){ + $user->display_name = $item['display_name']; + } if($ldap_map["last_name"] != null){ $user->last_name = $item['lastname']; } @@ -293,6 +311,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/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, diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index 86620caeff..ac9c6add7b 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', @@ -509,6 +515,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/SettingsController.php b/app/Http/Controllers/SettingsController.php index 56b36470d4..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'); @@ -889,7 +890,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/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 1c8a829441..ec87d3ec99 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/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index 3683046970..bef81320a5 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -31,7 +31,6 @@ class UsersTransformer $array = [ 'id' => (int) $user->id, 'avatar' => e($user->present()->gravatar) ?? null, - 'name' => e($user->getFullNameAttribute()) ?? null, 'first_name' => e($user->first_name) ?? null, 'last_name' => e($user->last_name) ?? null, @@ -140,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/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/app/Models/SnipeModel.php b/app/Models/SnipeModel.php index fcf9eeebd1..f5a5a51cc0 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 diff --git a/app/Models/SnipeSCIMConfig.php b/app/Models/SnipeSCIMConfig.php index c0d82dff43..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'), @@ -153,21 +154,12 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig "primary" => AttributeMapping::constant(true)->ignoreWrite() ]], - // Mobile and work phone numbers - 'phoneNumbers' => [ - [ - "value" => AttributeMapping::eloquent("phone"), - "display" => null, - "type" => AttributeMapping::constant("work")->ignoreWrite(), - "primary" => AttributeMapping::constant(true)->ignoreWrite(), - ], - [ - "value" => AttributeMapping::eloquent("mobile"), - "display" => null, - "type" => AttributeMapping::constant("mobile")->ignoreWrite(), - "primary" => AttributeMapping::constant(false)->ignoreWrite() - ] - ], + 'phoneNumbers' => [[ + "value" => AttributeMapping::eloquent("phone"), + "display" => null, + "type" => AttributeMapping::constant("work")->ignoreWrite(), + "primary" => AttributeMapping::constant(true)->ignoreWrite() + ]], 'ims' => [[ "value" => null, diff --git a/app/Models/User.php b/app/Models/User.php index 4c3541a5d8..148a393dc8 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', @@ -113,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', @@ -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'], ]; @@ -871,6 +875,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', @@ -1080,6 +1085,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/ComponentPresenter.php b/app/Presenters/ComponentPresenter.php index 254e7f4110..32e63ac713 100644 --- a/app/Presenters/ComponentPresenter.php +++ b/app/Presenters/ComponentPresenter.php @@ -191,7 +191,7 @@ class ComponentPresenter extends Presenter */ public function nameUrl() { - return (string) link_to_route('components.show', e($this->name), $this->id); + return (string) link_to_route('consumables.show', e($this->name), $this->id); } /** @@ -200,6 +200,6 @@ class ComponentPresenter extends Presenter */ public function viewUrl() { - return route('components.show', $this->id); + return route('accessories.show', $this->id); } } diff --git a/app/Presenters/UserPresenter.php b/app/Presenters/UserPresenter.php index 63c52ceaa7..296fafe568 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, @@ -441,6 +450,30 @@ class UserPresenter extends Presenter return ''; } + /** + * Returns the user full name, it simply concatenates + * the user first and last name. + * + * @return string + */ +// public function fullName() +// { +// if ($this->display_name) { +// return 'kjdfh'.html_entity_decode($this->display_name, ENT_QUOTES | ENT_XML1, 'UTF-8'); +// } +// return 'roieuoe'.html_entity_decode($this->first_name.' '.$this->last_name, ENT_QUOTES | ENT_XML1, 'UTF-8'); +// } + +// /** +// * Standard accessor. +// * @TODO Remove presenter::fullName() entirely? +// * @return string +// */ +// public function name() +// { +// return $this->fullName(); +// } + /** 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/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..fb980af6dd --- /dev/null +++ b/database/migrations/2025_08_19_174823_add_display_name_to_ldap_settings.php @@ -0,0 +1,82 @@ +string('ldap_display_name', 191)->after('ldap_fname_field')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_zip')) { + $table->string('ldap_zip', 191)->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_state')) { + $table->string('ldap_state', 191)->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_city')) { + $table->string('ldap_city', 191)->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_address')) { + $table->string('ldap_address', 191)->after('ldap_manager')->nullable()->default(null); + } + + if (!Schema::hasColumn('settings', 'ldap_mobile')) { + $table->string('ldap_mobile', 191)->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..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,26 +106,32 @@ 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 Telephone 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_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', + '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', @@ -462,21 +468,24 @@ return [ 'legends' => [ - 'scoping' => 'Scoping', - 'formats' => 'Default Formats', - 'profiles' => 'User Profiles', - 'eula' => 'EULA & Acceptance Preferences', - 'misc_display' => 'Miscellaneous Display Options', - 'email' => 'Email Preferences', 'checkin' => 'Checkin Preferences', - 'dashboard' => 'Login & Dashboard Preferences', - 'misc' => 'Miscellaneous', - 'logos' => 'Logos & Display', 'colors' => 'Colors & Skins', + 'dashboard' => 'Login & Dashboard Preferences', + 'email' => 'Email Preferences', + 'eula' => 'EULA & Acceptance Preferences', 'footer' => 'Footer Preferences', - 'security' => 'Security Preferences', + 'formats' => 'Default Formats', 'general' => 'General', 'intervals' => 'Intervals & Thresholds', + 'logos' => 'Logos & Display', + 'mapping' => 'LDAP Field Mapping', + 'test' => 'Test LDAP Connection', + 'misc' => 'Miscellaneous', + 'misc_display' => 'Miscellaneous Display Options', + 'profiles' => 'User Profiles', + 'server' => 'Server Settings', + 'scoping' => 'Scoping', + 'security' => 'Security Preferences', ], 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', 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 @@ +
+
+
+ +
+
+ + +
+
+
+
diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 27e6a20dea..19051f653b 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -65,728 +65,357 @@
-
+
- -
-
- -
-
+
+ + {{ trans('admin/settings/general.legends.server') }} + + +
+
+ +
+
- + - @if (config('app.lock_passwords')===true) -

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

- @endif -
-
+ @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') }} + +
+
+ +
+
+ + @error('is_ad') + + + {{ $message }} -
- @endif - @else -

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

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

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

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

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

+ +
+
+ +
+
+ - @error('ldap_active_flag') - - - {{ $message }} - - @enderror +

{{ 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 -
-
+ @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') !!} -

+ +
+
+ +
+
+ +

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

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

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

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

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

+ @endif +
+
-
+ +
+
+ +
+
+ + @error('ldap_client_tls_key') + + + {{ $message }} + + @enderror - -
-
- -
-
- - @error('ldap_emp_num') - - - {{ $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_client_tls_cert_help') }}

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

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

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

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

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

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

- @endif -
-
+

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

- @endif -
-
+ +
+
+ +
+
+ + @error('ldap_uname') + + + {{ $message }} + + @enderror - -
-
- -
-
- - @error('ldap_country') - - - {{ $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 + +
+
+ +
+
+ + @error('ldap_pword') + + + {{ $message }} + + @enderror - @if (config('app.lock_passwords')===true) -

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

- @endif -
-
- @if ($setting->ldap_enabled) + @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.ldap_login_sync_help') }}

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

@@ -794,68 +423,543 @@

@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.legends.test') }} + + @if ($setting->ldap_enabled) + + +
- {{ trans('admin/settings/general.ldap_test') }} + +
+ +
+
+ +
+
+

{{ 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') }}

-
+ +
+
+ +
+
+ +
+
+ + + +
+
+

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

+
- -
-
- -
-
- -

{{ 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 -
-
+
+ @endif + + + +
+ + {{ trans('admin/settings/general.legends.mapping') }} + + +
+
+ +
+
+ + @error('ldap_username_field') + + + {!! $message !!} + + @enderror + +
+
+ + +
+
+ +
+
+ + @error('ldap_lname_field') + + + {{ $message }} + + @enderror + +
+
+ + +
+
+ +
+
+ + @error('ldap_fname_field') + + + {{ $message }} + + @enderror + +
+
+ + +
+
+ +
+
+ + @error('ldap_display_name') + + + {{ $message }} + + @enderror + +
+
+ + + +
+
+ +
+
+ +

{!! 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 +
+
+ + + +
+
+ +
+
+ + @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 +
+
+
+ +
+ + {{ trans('admin/settings/general.legends.misc') }} + + +
+
+ +
+
+ +

{{ 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 +
+
+ +
- {{ $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,7 +345,6 @@
- @if ($user->display_name)
@@ -408,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 be0f3910bb44453f9d104c1ae8791565adc1b6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Aqaba=20=C5=A0tarman?= Date: Mon, 25 Aug 2025 16:57:32 +0200 Subject: [PATCH 44/51] Fixed: Old computation --- app/Models/Labels/Sheets/Avery/L6009.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Models/Labels/Sheets/Avery/L6009.php b/app/Models/Labels/Sheets/Avery/L6009.php index c5e5cd9b40..11d6cfffca 100644 --- a/app/Models/Labels/Sheets/Avery/L6009.php +++ b/app/Models/Labels/Sheets/Avery/L6009.php @@ -40,10 +40,8 @@ abstract class L6009 extends RectangleSheet $this->pageMarginTop = Helper::convertUnit(self::ROW1_Y, 'pt', $this->getUnit()); $columnSpacingPt = self::COLUMN2_X - self::COLUMN1_X - self::LABEL_W; - $columnSpacingPt = self::COLUMN2_X - self::LABEL_W + 7.15; $this->columnSpacing = Helper::convertUnit($columnSpacingPt, 'pt', $this->getUnit()); $rowSpacingPt = self::ROW2_Y - self::ROW1_Y - self::LABEL_H; - $rowSpacingPt = self::ROW2_Y - self::LABEL_H; $this->rowSpacing = Helper::convertUnit($rowSpacingPt, 'pt', $this->getUnit()); $this->labelWidth = Helper::convertUnit(self::LABEL_W, 'pt', $this->getUnit()); From 3524e23e38115e442eb5f08f8700b79008abaa5c Mon Sep 17 00:00:00 2001 From: snipe Date: Mon, 25 Aug 2025 17:17:45 +0100 Subject: [PATCH 45/51] Fixed tests Signed-off-by: snipe --- app/Http/Transformers/UsersTransformer.php | 2 +- app/Importer/Importer.php | 3 + .../lang/en-US/admin/settings/general.php | 1 + resources/views/settings/ldap.blade.php | 3 +- sample_csvs/users-sample.csv | 202 +++++++++--------- .../Feature/Importing/Api/ImportUsersTest.php | 19 +- .../Importing/UsersImportFileBuilder.php | 24 +-- 7 files changed, 133 insertions(+), 121 deletions(-) diff --git a/app/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index bef81320a5..85f6bdd271 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -60,7 +60,7 @@ class UsersTransformer ] : null, 'department_manager' => ($user->department?->manager) ? [ 'id' => (int) $user->department->manager->id, - 'name'=> e($user->department->manager->full_name), + 'name'=> e($user->department->manager->display_name), ] : null, 'location' => ($user->userloc) ? [ 'id' => (int) $user->userloc->id, diff --git a/app/Importer/Importer.php b/app/Importer/Importer.php index 3c0ea4e264..f21c108e8f 100644 --- a/app/Importer/Importer.php +++ b/app/Importer/Importer.php @@ -72,6 +72,7 @@ abstract class Importer 'termination_date' => 'termination date', 'warranty_months' => 'warranty', 'full_name' => 'full name', + 'display_name' => 'display name', 'email' => 'email', 'username' => 'username', 'address' => 'address', @@ -299,6 +300,7 @@ abstract class Importer 'full_name' => $this->findCsvMatch($row, 'full_name'), 'first_name' => $this->findCsvMatch($row, 'first_name'), 'last_name' => $this->findCsvMatch($row, 'last_name'), + 'display_name' => $this->findCsvMatch($row, 'display_name'), 'email' => $this->findCsvMatch($row, 'email'), 'manager_id'=> '', 'department_id' => '', @@ -369,6 +371,7 @@ abstract class Importer $user->first_name = $user_array['first_name']; $user->last_name = $user_array['last_name']; $user->username = $user_array['username']; + $user->username = $user_array['display_name']; $user->email = $user_array['email']; $user->manager_id = $user_array['manager_id'] ?? null; $user->department_id = $user_array['department_id'] ?? null; diff --git a/resources/lang/en-US/admin/settings/general.php b/resources/lang/en-US/admin/settings/general.php index 842fe5e338..32417af741 100644 --- a/resources/lang/en-US/admin/settings/general.php +++ b/resources/lang/en-US/admin/settings/general.php @@ -117,6 +117,7 @@ return [ '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' => 'LDAP Username Field', 'ldap_display_name' => 'LDAP Display Name Field', + 'ldap_display_name_help' => 'If you have a separate displayName field in your LDAP/AD, map it here and it will be used for displaying users within Snipe-IT.', 'ldap_lname_field' => 'LDAP Last Name Field', 'ldap_fname_field' => 'LDAP First Name Field', 'ldap_auth_filter_query' => 'LDAP Authentication query', diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 19051f653b..32b3f77649 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -595,7 +595,8 @@
- + +

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

@error('ldap_display_name') diff --git a/sample_csvs/users-sample.csv b/sample_csvs/users-sample.csv index 8ee2359cbc..9ac76f8825 100644 --- a/sample_csvs/users-sample.csv +++ b/sample_csvs/users-sample.csv @@ -1,101 +1,101 @@ -ο»ΏFirst Name,Last Name,Email,Username,Activated,Location,Address,City,State,Country,Postal Code,Website,Phone,Job Title,Notes,Employee Number,Company,Manager,Remote,VIP,Start Date,End Date,Gravatar -Reagen,Tenant,rtenant0@istockphoto.com,rtenant0,true,"Braun, Ullrich and O'Hara",0406 Emmet Drive,,,,,https://netvibes.com,895-137-2034,Nurse Practicioner,ac tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum,"",,Reagen Tenant,true,true,2022-03-18,2022-12-04,rtenant0@soup.io -Kenneth,Lefeuvre,klefeuvre1@woothemes.com,klefeuvre1,false,Mueller LLC,404 Dennis Alley,,,,,,,Senior Quality Engineer,lacus at turpis donec posuere metus vitae ipsum,"",,,true,,,, -Kiel,Eland,keland2@tinyurl.com,keland2,false,"Mayer, Jacobi and Gibson",3058 Declaration Park,,,,,,,Web Developer I,eu est congue elementum in hac habitasse platea dictumst morbi vestibulum velit id,"",,,true,,,, -Susana,Kinneally,skinneally3@purevolume.com,skinneally3,false,Block Inc,1 Chive Alley,,,,,,,Software Consultant,phasellus in felis donec semper sapien a libero nam dui proin leo odio porttitor id consequat,"",,,true,,,, -Wallis,Hadcock,whadcock4@abc.net.au,whadcock4,false,Roob-Bartoletti,496 Hazelcrest Terrace,,,,,,,Information Systems Manager,nam congue risus semper porta volutpat quam pede lobortis ligula sit amet eleifend,"","Hand, Rohan and Oberbrunner",,false,,,, -Audry,Piell,apiell5@china.com.cn,apiell5,false,Schoen-Hilpert,3136 Talmadge Circle,,,,,,,Chemical Engineer,congue risus semper porta volutpat quam pede lobortis ligula sit amet eleifend pede libero quis orci nullam,"",,,false,,,, -Veronike,Poytress,vpoytress6@scribd.com,vpoytress6,false,"D'Amore, Schoen and Rogahn",3 Northwestern Hill,,,,,http://acquirethisname.com,198-980-1723,Compensation Analyst,non mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet,"",,Veronike Poytress,true,true,2022-05-10,2022-08-14,vpoytress6@ed.gov -Sibel,Serris,sserris7@mayoclinic.com,sserris7,true,Swaniawski and Sons,090 Summit Road,,,,,,,,,,,,false,,,, -Aldis,Smardon,asmardon8@ifeng.com,asmardon8,false,Huels-Reinger,2 Brown Trail,,,,,,,,,,,,true,,,, -Juan,,,jlowseley9,true,Nicolas and Sons,0 Village Pass,,,,,,,Cost Accountant,phasellus id sapien in sapien,"",,,true,,,, -Thaine,Coger,tcogera@naver.com,tcogera,false,Zieme-Davis,31 Little Fleur Park,,,,,,,,,,,,true,,,, -Adrien,Ciotti,aciottib@ucoz.ru,aciottib,true,"Ward, Wolff and King",61 Graedel Hill,,,,,,,,,,,,false,,,, -Harmony,Vanetti,hvanettic@wordpress.com,hvanettic,true,"Kulas, Heller and Cormier",35 Hintze Drive,,,,,,,,,,Wyman-Jenkins,,true,,,, -Pansie,Morston,pmorstond@ebay.com,pmorstond,false,Mosciski-Graham,73222 Walton Street,,,,,,,,,,,,false,,,, -Court,Halse,chalsee@walmart.com,chalsee,true,"O'Reilly, Hilll and Stokes",61514 Pepper Wood Trail,,,,,,,,,,,,false,,,, -Gerardo,Scrowby,gscrowbyf@multiply.com,gscrowbyf,false,Cruickshank-Kling,18314 Schlimgen Point,,,,,,,,,,,,false,,,, -Imojean,Veare,iveareg@chronoengine.com,iveareg,false,Schultz-Lakin,9 Blaine Street,,,,,https://soup.io,502-710-6094,Environmental Tech,consequat lectus in est risus auctor sed,"",,Imojean Veare,false,true,2022-01-24,2022-08-06,iveareg@answers.com -Samuel,Bickley,sbickleyh@gravatar.com,sbickleyh,true,Langworth-Friesen,5891 Bunker Hill Crossing,,,,,,,,,,Corkery and Sons,,false,,,, -Niall,Ethington,nethingtoni@google.fr,nethingtoni,true,"Ledner, Klocko and Sipes",511 Springs Parkway,,,,,,,,,,,,false,,,, -Elfreda,Ilyukhov,eilyukhovj@mashable.com,eilyukhovj,false,Spinka-Ortiz,475 Bluestem Point,,,,,,,Clinical Specialist,felis ut at dolor quis odio consequat varius integer ac,"",,,true,,,, -Serena,Josling,sjoslingk@oracle.com,sjoslingk,false,Wuckert-Schuster,10512 Fuller Avenue,,,,,,,,,,"Cruickshank, Ziemann and Kreiger",,false,,,, -Sheelah,Dockwray,sdockwrayl@narod.ru,sdockwrayl,true,Orn-Koss,4241 Scofield Circle,,,,,,,Nurse,vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede,"",Hermann-Anderson,,true,,,, -Lanette,Remnant,lremnantm@vinaora.com,lremnantm,false,Abshire LLC,8 Buena Vista Junction,,,,,,,General Manager,mauris ullamcorper purus sit amet,"",Bahringer-Lockman,,false,,,, -Jordan,Pritty,jprittyn@reverbnation.com,jprittyn,false,Stroman LLC,36 Becker Plaza,,,,,,,,,,Durgan-Bosco,,true,,,, -Lorrin,Boni,lbonio@msn.com,lbonio,true,Bogisich-Nolan,7 Messerschmidt Point,,,,,,,,,,,,false,,,, -Marie-ann,Waind,mwaindp@ucoz.ru,mwaindp,true,"Hartmann, Weissnat and Cassin",68082 Schmedeman Court,,,,,,,Nurse,duis faucibus accumsan odio curabitur convallis duis consequat,"",,,true,,,, -Marti,Daens,mdaensq@huffingtonpost.com,mdaensq,false,Robel-Roob,7 Knutson Pass,,,,,http://gov.uk,381-382-8857,Electrical Engineer,sapien a libero nam dui proin leo,"",,Marti Daens,false,true,2021-12-19,2022-12-08,mdaensq@themeforest.net -Scotti,Gillison,sgillisonr@intel.com,sgillisonr,true,Howe-Collins,44 Elka Terrace,,,,,,,Financial Advisor,viverra eget congue eget semper rutrum nulla nunc purus,"",,,true,,,, -Bobbe,Alven,balvens@csmonitor.com,balvens,true,Weimann-Bernhard,71 Manley Park,,,,,,,,,,Champlin-Turcotte,,false,,,, -Ferdy,Kincade,fkincadet@wsj.com,fkincadet,true,Bode Inc,3023 Novick Alley,,,,,,,Statistician IV,amet nulla quisque arcu libero,"",,,true,,,, -Rachael,Briers,rbriersu@vimeo.com,rbriersu,false,Koch and Sons,71 Shoshone Court,,,,,,,,,,,,true,,,, -Ado,Bartholin,abartholinv@ft.com,abartholinv,false,"Buckridge, Klein and Johnston",11 Jenna Avenue,,,,,,,,,,,,false,,,, -Tessy,,,tsailerw,false,Parker-Beer,0964 Vidon Way,,,,,,,Structural Engineer,aliquet ultrices erat tortor sollicitudin,"",,,true,,,, -Chloe,Gebbie,cgebbiex@cam.ac.uk,cgebbiex,false,Smith Inc,8 5th Alley,,,,,,,,,,,,true,,,, -Emlyn,Cusick,ecusicky@homestead.com,ecusicky,true,Dickens LLC,43 Canary Point,,,,,,,Health Coach II,eu tincidunt in leo maecenas pulvinar lobortis est phasellus sit amet erat nulla tempus vivamus in,"",,,true,,,, -Kenneth,McGuire,kmcguirez@scribd.com,kmcguirez,true,"Torphy, Bednar and Davis",2 Stone Corner Park,,,,,,,Nurse Practicioner,tortor duis mattis egestas metus aenean fermentum donec ut mauris eget massa,"",,,false,,,, -Berri,Forson,bforson10@pcworld.com,bforson10,true,"D'Amore, Larkin and O'Keefe",266 Alpine Road,,,,,,,Tax Accountant,in purus eu magna vulputate luctus cum sociis natoque penatibus et,"",,,true,,,, -Bree,Jiru,bjiru11@gravatar.com,bjiru11,true,Altenwerth LLC,58 4th Alley,,,,,,,,,,Farrell and Sons,,true,,,, -Kathie,Dignan,kdignan12@bbb.org,kdignan12,true,"Pagac, Effertz and Padberg",973 Banding Point,,,,,,,,,,"Marquardt, Cummings and Bosco",,true,,,, -Filbert,Van Der Straaten,fvanderstraaten13@sourceforge.net,fvanderstraaten13,false,"Cronin, Mante and Klein",0 Stuart Junction,,,,,,,Research Assistant I,ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in leo maecenas,"",Bauch-Kling,,true,,,, -Miguel,Farbrace,mfarbrace14@barnesandnoble.com,mfarbrace14,false,O'Keefe Inc,1 Mallory Avenue,,,,,,,Assistant Manager,a libero nam dui proin leo odio porttitor id consequat in consequat ut nulla sed accumsan felis,"",Schmeler-Krajcik,,false,,,, -Em,,,ekittley15,false,Schuppe-Barrows,9946 Canary Pass,,,,,,,Nuclear Power Engineer,odio curabitur convallis duis consequat dui nec nisi,"","Abshire, Goyette and Spinka",,true,,,, -Bill,Morales,bmorales16@addtoany.com,bmorales16,true,Leannon Inc,0 Hudson Circle,,,,,,,,,,,,true,,,, -Spenser,Branca,sbranca17@tripod.com,sbranca17,false,Halvorson Inc,7904 Green Road,,,,,,,,,,,,false,,,, -Dawna,Ainslee,dainslee18@nifty.com,dainslee18,true,"Strosin, Collier and O'Connell",17 Granby Center,,,,,,,,,,,,false,,,, -Lind,Fontanet,lfontanet19@lycos.com,lfontanet19,false,Bins-Kunde,84 Kenwood Junction,,,,,,,,,,"Romaguera, Adams and Schoen",,false,,,, -Ashli,Gheorghie,agheorghie1a@blogtalkradio.com,agheorghie1a,false,Hauck Inc,8 Warrior Drive,,,,,,,,,,Wisozk Inc,,false,,,, -Janice,Freddi,jfreddi1b@behance.net,jfreddi1b,true,"Stoltenberg, Aufderhar and Schaden",0 Esch Alley,,,,,,,,,,,,false,,,, -Reinwald,Ivakhin,rivakhin1c@ask.com,rivakhin1c,false,Jacobson-Mosciski,24 New Castle Alley,,,,,,,,,,Welch and Sons,,true,,,, -Lindsey,Trevance,ltrevance1d@prnewswire.com,ltrevance1d,true,Hansen-Luettgen,17443 Lindbergh Plaza,,,,,,,Web Designer II,interdum eu tincidunt in leo maecenas pulvinar lobortis est phasellus,"",,,false,,,, -Cordi,Frostdyke,cfrostdyke1e@weather.com,cfrostdyke1e,false,Kohler Inc,53066 Merchant Plaza,,,,,,,,,,,,false,,,, -Jayme,Piatto,jpiatto1f@slate.com,jpiatto1f,true,Johnson and Sons,5598 Fuller Avenue,,,,,,,Graphic Designer,accumsan felis ut at dolor quis odio consequat varius integer,"",,,true,,,, -Henriette,Glanvill,hglanvill1g@ifeng.com,hglanvill1g,true,"Mills, Kautzer and Stiedemann",6461 Stang Center,,,,,,,,,,Gibson and Sons,,true,,,, -Izak,Legen,ilegen1h@berkeley.edu,ilegen1h,true,"Schiller, Runolfsson and Gottlieb",86874 Hovde Avenue,,,,,,,,,,,,false,,,, -Silas,Vallentin,svallentin1i@zdnet.com,svallentin1i,false,Wolff Inc,15041 Graceland Park,,,,,,,,,,,,true,,,, -Ansel,Augustus,aaugustus1j@oaic.gov.au,aaugustus1j,true,"Rippin, Frami and Parker",843 Nova Alley,,,,,,,Assistant Media Planner,ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae donec,"",Morissette and Sons,,false,,,, -Annemarie,Reburn,areburn1k@networksolutions.com,areburn1k,true,Dach Group,05 Crowley Avenue,,,,,,,Administrative Assistant IV,vivamus tortor duis mattis egestas metus aenean fermentum donec,"","Murazik, Wyman and Yost",,false,,,, -Fee,Bissell,fbissell1l@comsenz.com,fbissell1l,true,Braun Group,678 Nelson Hill,,,,,,,Health Coach IV,sed augue aliquam erat volutpat in congue etiam justo etiam pretium iaculis justo in,"","Lindgren, Quitzon and Heathcote",,true,,,, -Zenia,Kordt,zkordt1m@com.com,zkordt1m,true,"Harvey, Fay and Yundt",6337 Mayer Trail,,,,,,,Associate Professor,congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna,"",,,true,,,, -Winthrop,Eales,weales1n@stanford.edu,weales1n,true,Johns-Kshlerin,79780 Helena Lane,,,,,,,Accountant I,platea dictumst etiam faucibus cursus urna ut,"",,,false,,,, -Davis,,,dnatalie1o,false,Tillman-Marquardt,3893 Express Junction,,,,,https://answers.com,266-409-9118,Teacher,suspendisse accumsan tortor quis turpis sed ante vivamus tortor,"",Casper-Grimes,Davis Natalie,false,false,2022-04-08,2022-09-24,dnatalie1o@altervista.org -Massimiliano,Fardo,mfardo1p@imgur.com,mfardo1p,true,Kozey Group,72 Hauk Terrace,,,,,,,Account Coordinator,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida sem praesent id,"",Bednar Inc,,false,,,, -Dacey,Larrie,dlarrie1q@digg.com,dlarrie1q,false,Jerde-Ullrich,70371 Del Mar Center,,,,,,,,,,,,true,,,, -Pattie,Melvin,pmelvin1r@discovery.com,pmelvin1r,false,"McDermott, Mayert and Kemmer",845 Anderson Point,,,,,,,Safety Technician II,sit amet erat nulla tempus vivamus in felis eu sapien cursus vestibulum proin,"",,,true,,,, -Franny,Laughlin,flaughlin1s@blogspot.com,flaughlin1s,false,Renner-Terry,94 Northfield Pass,,,,,,,,,,"Parisian, Hudson and Bahringer",,false,,,, -Mariel,Roelvink,mroelvink1t@timesonline.co.uk,mroelvink1t,true,Russel-Blanda,434 Crest Line Road,,,,,http://amazon.de,429-401-0847,Quality Engineer,vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus auctor sed tristique in tempus,"",,Mariel Roelvink,true,false,2022-02-21,2022-09-01,mroelvink1t@feedburner.com -Josee,Ghirardi,jghirardi1u@arizona.edu,jghirardi1u,true,Koss-Schmitt,96 Kingsford Avenue,,,,,,,,,,,,true,,,, -Felix,Pheasant,fpheasant1v@soundcloud.com,fpheasant1v,true,Rogahn Group,43 Northridge Place,,,,,,,,,,Hoppe-O'Reilly,,false,,,, -Stearne,Gwatkins,sgwatkins1w@jugem.jp,sgwatkins1w,false,"Koch, Ferry and Marks",6 Victoria Circle,,,,,,,,,,,,false,,,, -Nathaniel,Parkinson,nparkinson1x@springer.com,nparkinson1x,true,Harber Group,4589 Clarendon Way,,,,,,,Software Consultant,non mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,"",Koepp LLC,,true,,,, -Blondelle,Crawley,bcrawley1y@ezinearticles.com,bcrawley1y,true,"Hirthe, Bashirian and Feeney",17149 Ridge Oak Park,,,,,,,Help Desk Technician,sit amet cursus id turpis integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu,"",,,true,,,, -Pammi,Yair,pyair1z@virginia.edu,pyair1z,true,"Pfeffer, Schmeler and Dibbert",541 Beilfuss Alley,,,,,,,,,,,,true,,,, -Tremain,Lattimer,tlattimer20@go.com,tlattimer20,true,"Kuvalis, Kris and Howell",19 Red Cloud Parkway,,,,,,,,,,Gutkowski LLC,,true,,,, -Moreen,Fermin,mfermin21@w3.org,mfermin21,false,"Romaguera, Spinka and Bayer",50 Eagle Crest Circle,,,,,,,,,,,,true,,,, -Jena,Taborre,jtaborre22@pinterest.com,jtaborre22,true,Raynor Group,97 Helena Center,,,,,,,Dental Hygienist,vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris,"",,,false,,,, -Odille,Stede,ostede23@biglobe.ne.jp,ostede23,true,"Boyle, Schowalter and Mayer",88993 Sunbrook Street,,,,,http://live.com,464-815-6024,,,,,Odille Stede,true,false,2021-12-12,2022-06-27,ostede23@lycos.com -Kori,Fulk,kfulk24@tiny.cc,kfulk24,true,Konopelski and Sons,43 Mockingbird Avenue,,,,,,,,,,"Nikolaus, Cassin and Streich",,true,,,, -Pollyanna,Cardon,pcardon25@infoseek.co.jp,pcardon25,false,Hickle Group,52088 Almo Junction,,,,,,,,,,"Cronin, Cummerata and Tromp",,false,,,, -Austin,McGeneay,amcgeneay26@tmall.com,amcgeneay26,true,Yundt-Howell,021 4th Park,,,,,,,Social Worker,est phasellus sit amet erat nulla tempus vivamus in felis eu sapien cursus vestibulum proin eu mi nulla,"",,,true,,,, -Imogen,Hamill,ihamill27@w3.org,ihamill27,false,Herman-Schulist,802 Sunbrook Place,,,,,http://vistaprint.com,344-665-1217,Registered Nurse,curabitur convallis duis consequat dui nec nisi volutpat,"",,Imogen Hamill,false,false,2021-12-03,2023-04-16,ihamill27@over-blog.com -Hershel,Bielfeld,hbielfeld28@soup.io,hbielfeld28,true,Kreiger and Sons,6944 Buell Trail,,,,,,,Actuary,curae donec pharetra magna vestibulum aliquet ultrices erat,"",Schmitt-Abbott,,true,,,, -Korry,,,ksteckings29,true,Bogan Inc,800 Ilene Parkway,,,,,,,,,,,,true,,,, -Cookie,Warret,cwarret2a@sakura.ne.jp,cwarret2a,false,Murphy-Yost,9 Vera Terrace,,,,,,,Mechanical Systems Engineer,semper rutrum nulla nunc purus phasellus in felis donec semper sapien a libero nam dui proin leo odio,"","Lueilwitz, Beahan and Raynor",,false,,,, -Wynne,Gonnely,wgonnely2b@facebook.com,wgonnely2b,true,"Frami, Erdman and Mayert",051 Kenwood Junction,,,,,,,,,,,,true,,,, -Ethelred,Bogey,ebogey2c@infoseek.co.jp,ebogey2c,true,Christiansen and Sons,7414 2nd Pass,,,,,,,Media Manager II,donec odio justo sollicitudin ut suscipit a feugiat et eros vestibulum ac est lacinia,"",,,false,,,, -Alvera,Tunuy,atunuy2d@bizjournals.com,atunuy2d,false,"Vandervort, Veum and Walker",152 Division Park,,,,,,,,,,"Bartell, Hartmann and Jerde",,false,,,, -Martino,Rosenbusch,mrosenbusch2e@seesaa.net,mrosenbusch2e,true,Parisian-Romaguera,130 Westridge Alley,,,,,http://bravesites.com,626-888-4072,,,,"Keebler, Walter and Senger",Martino Rosenbusch,false,false,2022-01-20,2022-09-11,mrosenbusch2e@about.me -Susi,Trapp,strapp2f@ft.com,strapp2f,false,"Rogahn, Volkman and McDermott",72958 Vahlen Avenue,,,,,,,,,,Nitzsche-Langosh,,true,,,, -Gordon,Alflatt,galflatt2g@marriott.com,galflatt2g,false,Effertz-Howell,0681 International Plaza,,,,,,,Research Associate,duis aliquam convallis nunc proin,"","Farrell, Hoeger and O'Keefe",,true,,,, -Derrick,Braidon,dbraidon2h@blogs.com,dbraidon2h,false,Prosacco-Walker,8760 Del Sol Circle,,,,,,,,,,Koss-Bogisich,,true,,,, -Minnnie,Bonar,mbonar2i@biglobe.ne.jp,mbonar2i,true,Daniel LLC,5424 Karstens Alley,,,,,,,Web Designer III,faucibus orci luctus et ultrices posuere cubilia curae mauris,"",,,true,,,, -Casper,Sinnatt,csinnatt2j@hc360.com,csinnatt2j,true,Barrows-Mertz,79 Melvin Center,,,,,,,,,,,,false,,,, -Chloe,Fist,cfist2k@auda.org.au,cfist2k,false,"Kling, Streich and Kertzmann",47064 Glacier Hill Court,,,,,,,,,,Altenwerth-Leuschke,,true,,,, -Elysha,Gosenell,egosenell2l@ft.com,egosenell2l,true,Hirthe LLC,70 Old Gate Alley,,,,,,,Nuclear Power Engineer,amet cursus id turpis integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus,"",Macejkovic and Sons,,false,,,, -Gerianna,Feirn,gfeirn2m@bing.com,gfeirn2m,true,"Collier, Kirlin and Armstrong",881 Summer Ridge Circle,,,,,,,,,,,,false,,,, -Lucas,Mulvany,lmulvany2n@deliciousdays.com,lmulvany2n,false,Bahringer Group,639 La Follette Circle,,,,,,,,,,,,true,,,, -Lenore,Menendez,lmenendez2o@cdbaby.com,lmenendez2o,true,"Nader, Harvey and Casper",02 Springs Avenue,,,,,https://a8.net,926-526-1742,Community Outreach Specialist,ut odio cras mi pede malesuada in imperdiet et commodo vulputate justo in blandit ultrices enim lorem ipsum dolor,"",,Lenore Menendez,true,false,2022-01-11,2022-07-29,lmenendez2o@ifeng.com -Collete,Brandes,cbrandes2p@accuweather.com,cbrandes2p,true,Koepp-Parisian,5 Haas Way,,,,,,,,,,,,false,,,, -Osborne,Gummory,ogummory2q@1und1.de,ogummory2q,false,Mertz and Sons,91749 Haas Alley,,,,,,,,,,,,true,,,, -Emiline,Grossman,egrossman2r@dmoz.org,egrossman2r,true,Parisian and Sons,3872 Eagle Crest Court,,,,,https://uiuc.edu,338-830-8647,Food Chemist,dolor vel est donec odio justo sollicitudin ut suscipit a feugiat et eros vestibulum ac est lacinia nisi venenatis,"",Williamson-Casper,Emiline Grossman,true,true,2021-11-10,2022-10-01,egrossman2r@spiegel.de +ο»ΏFirst Name,Last Name,Email,Username,Display Name,Activated,Location,Address,City,State,Country,Postal Code,Website,Phone,Job Title,Notes,Employee Number,Company,Manager,Remote,VIP,Start Date,End Date,Gravatar +Reagen,Tenant,rtenant0@istockphoto.com,rtenant0,Heywood,TRUE,"Braun, Ullrich and O'Hara",0406 Emmet Drive,,,,,https://netvibes.com,895-137-2034,Nurse Practicioner,ac tellus semper interdum mauris ullamcorper purus sit amet nulla quisque arcu libero rutrum,,,Reagen Tenant,TRUE,TRUE,2022-03-18,2022-12-04,rtenant0@soup.io +Kenneth,Lefeuvre,klefeuvre1@woothemes.com,klefeuvre1,,FALSE,Mueller LLC,404 Dennis Alley,,,,,,,Senior Quality Engineer,lacus at turpis donec posuere metus vitae ipsum,,,,TRUE,,,, +Kiel,Eland,keland2@tinyurl.com,keland2,,FALSE,"Mayer, Jacobi and Gibson",3058 Declaration Park,,,,,,,Web Developer I,eu est congue elementum in hac habitasse platea dictumst morbi vestibulum velit id,,,,TRUE,,,, +Susana,Kinneally,skinneally3@purevolume.com,skinneally3,George,FALSE,Block Inc,1 Chive Alley,,,,,,,Software Consultant,phasellus in felis donec semper sapien a libero nam dui proin leo odio porttitor id consequat,,,,TRUE,,,, +Wallis,Hadcock,whadcock4@abc.net.au,whadcock4,,FALSE,Roob-Bartoletti,496 Hazelcrest Terrace,,,,,,,Information Systems Manager,nam congue risus semper porta volutpat quam pede lobortis ligula sit amet eleifend,,"Hand, Rohan and Oberbrunner",,FALSE,,,, +Audry,Piell,apiell5@china.com.cn,apiell5,,FALSE,Schoen-Hilpert,3136 Talmadge Circle,,,,,,,Chemical Engineer,congue risus semper porta volutpat quam pede lobortis ligula sit amet eleifend pede libero quis orci nullam,,,,FALSE,,,, +Veronike,Poytress,vpoytress6@scribd.com,vpoytress6,Paul,FALSE,"D'Amore, Schoen and Rogahn",3 Northwestern Hill,,,,,http://acquirethisname.com,198-980-1723,Compensation Analyst,non mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet,,,Veronike Poytress,TRUE,TRUE,2022-05-10,2022-08-14,vpoytress6@ed.gov +Sibel,Serris,sserris7@mayoclinic.com,sserris7,,TRUE,Swaniawski and Sons,090 Summit Road,,,,,,,,,,,,FALSE,,,, +Aldis,Smardon,asmardon8@ifeng.com,asmardon8,,FALSE,Huels-Reinger,2 Brown Trail,,,,,,,,,,,,TRUE,,,, +Juan,,,jlowseley9,Awesomesauce,TRUE,Nicolas and Sons,0 Village Pass,,,,,,,Cost Accountant,phasellus id sapien in sapien,,,,TRUE,,,, +Thaine,Coger,tcogera@naver.com,tcogera,,FALSE,Zieme-Davis,31 Little Fleur Park,,,,,,,,,,,,TRUE,,,, +Adrien,Ciotti,aciottib@ucoz.ru,aciottib,,TRUE,"Ward, Wolff and King",61 Graedel Hill,,,,,,,,,,,,FALSE,,,, +Harmony,Vanetti,hvanettic@wordpress.com,hvanettic,,TRUE,"Kulas, Heller and Cormier",35 Hintze Drive,,,,,,,,,,Wyman-Jenkins,,TRUE,,,, +Pansie,Morston,pmorstond@ebay.com,pmorstond,,FALSE,Mosciski-Graham,73222 Walton Street,,,,,,,,,,,,FALSE,,,, +Court,Halse,chalsee@walmart.com,chalsee,Test,TRUE,"O'Reilly, Hilll and Stokes",61514 Pepper Wood Trail,,,,,,,,,,,,FALSE,,,, +Gerardo,Scrowby,gscrowbyf@multiply.com,gscrowbyf,,FALSE,Cruickshank-Kling,18314 Schlimgen Point,,,,,,,,,,,,FALSE,,,, +Imojean,Veare,iveareg@chronoengine.com,iveareg,Testtest,FALSE,Schultz-Lakin,9 Blaine Street,,,,,https://soup.io,502-710-6094,Environmental Tech,consequat lectus in est risus auctor sed,,,Imojean Veare,FALSE,TRUE,2022-01-24,2022-08-06,iveareg@answers.com +Samuel,Bickley,sbickleyh@gravatar.com,sbickleyh,,TRUE,Langworth-Friesen,5891 Bunker Hill Crossing,,,,,,,,,,Corkery and Sons,,FALSE,,,, +Niall,Ethington,nethingtoni@google.fr,nethingtoni,,TRUE,"Ledner, Klocko and Sipes",511 Springs Parkway,,,,,,,,,,,,FALSE,,,, +Elfreda,Ilyukhov,eilyukhovj@mashable.com,eilyukhovj,,FALSE,Spinka-Ortiz,475 Bluestem Point,,,,,,,Clinical Specialist,felis ut at dolor quis odio consequat varius integer ac,,,,TRUE,,,, +Serena,Josling,sjoslingk@oracle.com,sjoslingk,,FALSE,Wuckert-Schuster,10512 Fuller Avenue,,,,,,,,,,"Cruickshank, Ziemann and Kreiger",,FALSE,,,, +Sheelah,Dockwray,sdockwrayl@narod.ru,sdockwrayl,,TRUE,Orn-Koss,4241 Scofield Circle,,,,,,,Nurse,vestibulum sed magna at nunc commodo placerat praesent blandit nam nulla integer pede,,Hermann-Anderson,,TRUE,,,, +Lanette,Remnant,lremnantm@vinaora.com,lremnantm,,FALSE,Abshire LLC,8 Buena Vista Junction,,,,,,,General Manager,mauris ullamcorper purus sit amet,,Bahringer-Lockman,,FALSE,,,, +Jordan,Pritty,jprittyn@reverbnation.com,jprittyn,,FALSE,Stroman LLC,36 Becker Plaza,,,,,,,,,,Durgan-Bosco,,TRUE,,,, +Lorrin,Boni,lbonio@msn.com,lbonio,,TRUE,Bogisich-Nolan,7 Messerschmidt Point,,,,,,,,,,,,FALSE,,,, +Marie-ann,Waind,mwaindp@ucoz.ru,mwaindp,,TRUE,"Hartmann, Weissnat and Cassin",68082 Schmedeman Court,,,,,,,Nurse,duis faucibus accumsan odio curabitur convallis duis consequat,,,,TRUE,,,, +Marti,Daens,mdaensq@huffingtonpost.com,mdaensq,,FALSE,Robel-Roob,7 Knutson Pass,,,,,http://gov.uk,381-382-8857,Electrical Engineer,sapien a libero nam dui proin leo,,,Marti Daens,FALSE,TRUE,2021-12-19,2022-12-08,mdaensq@themeforest.net +Scotti,Gillison,sgillisonr@intel.com,sgillisonr,,TRUE,Howe-Collins,44 Elka Terrace,,,,,,,Financial Advisor,viverra eget congue eget semper rutrum nulla nunc purus,,,,TRUE,,,, +Bobbe,Alven,balvens@csmonitor.com,balvens,,TRUE,Weimann-Bernhard,71 Manley Park,,,,,,,,,,Champlin-Turcotte,,FALSE,,,, +Ferdy,Kincade,fkincadet@wsj.com,fkincadet,,TRUE,Bode Inc,3023 Novick Alley,,,,,,,Statistician IV,amet nulla quisque arcu libero,,,,TRUE,,,, +Rachael,Briers,rbriersu@vimeo.com,rbriersu,,FALSE,Koch and Sons,71 Shoshone Court,,,,,,,,,,,,TRUE,,,, +Ado,Bartholin,abartholinv@ft.com,abartholinv,,FALSE,"Buckridge, Klein and Johnston",11 Jenna Avenue,,,,,,,,,,,,FALSE,,,, +Tessy,,,tsailerw,,FALSE,Parker-Beer,0964 Vidon Way,,,,,,,Structural Engineer,aliquet ultrices erat tortor sollicitudin,,,,TRUE,,,, +Chloe,Gebbie,cgebbiex@cam.ac.uk,cgebbiex,,FALSE,Smith Inc,8 5th Alley,,,,,,,,,,,,TRUE,,,, +Emlyn,Cusick,ecusicky@homestead.com,ecusicky,,TRUE,Dickens LLC,43 Canary Point,,,,,,,Health Coach II,eu tincidunt in leo maecenas pulvinar lobortis est phasellus sit amet erat nulla tempus vivamus in,,,,TRUE,,,, +Kenneth,McGuire,kmcguirez@scribd.com,kmcguirez,,TRUE,"Torphy, Bednar and Davis",2 Stone Corner Park,,,,,,,Nurse Practicioner,tortor duis mattis egestas metus aenean fermentum donec ut mauris eget massa,,,,FALSE,,,, +Berri,Forson,bforson10@pcworld.com,bforson10,,TRUE,"D'Amore, Larkin and O'Keefe",266 Alpine Road,,,,,,,Tax Accountant,in purus eu magna vulputate luctus cum sociis natoque penatibus et,,,,TRUE,,,, +Bree,Jiru,bjiru11@gravatar.com,bjiru11,,TRUE,Altenwerth LLC,58 4th Alley,,,,,,,,,,Farrell and Sons,,TRUE,,,, +Kathie,Dignan,kdignan12@bbb.org,kdignan12,,TRUE,"Pagac, Effertz and Padberg",973 Banding Point,,,,,,,,,,"Marquardt, Cummings and Bosco",,TRUE,,,, +Filbert,Van Der Straaten,fvanderstraaten13@sourceforge.net,fvanderstraaten13,,FALSE,"Cronin, Mante and Klein",0 Stuart Junction,,,,,,,Research Assistant I,ut massa volutpat convallis morbi odio odio elementum eu interdum eu tincidunt in leo maecenas,,Bauch-Kling,,TRUE,,,, +Miguel,Farbrace,mfarbrace14@barnesandnoble.com,mfarbrace14,,FALSE,O'Keefe Inc,1 Mallory Avenue,,,,,,,Assistant Manager,a libero nam dui proin leo odio porttitor id consequat in consequat ut nulla sed accumsan felis,,Schmeler-Krajcik,,FALSE,,,, +Em,,,ekittley15,,FALSE,Schuppe-Barrows,9946 Canary Pass,,,,,,,Nuclear Power Engineer,odio curabitur convallis duis consequat dui nec nisi,,"Abshire, Goyette and Spinka",,TRUE,,,, +Bill,Morales,bmorales16@addtoany.com,bmorales16,,TRUE,Leannon Inc,0 Hudson Circle,,,,,,,,,,,,TRUE,,,, +Spenser,Branca,sbranca17@tripod.com,sbranca17,,FALSE,Halvorson Inc,7904 Green Road,,,,,,,,,,,,FALSE,,,, +Dawna,Ainslee,dainslee18@nifty.com,dainslee18,,TRUE,"Strosin, Collier and O'Connell",17 Granby Center,,,,,,,,,,,,FALSE,,,, +Lind,Fontanet,lfontanet19@lycos.com,lfontanet19,,FALSE,Bins-Kunde,84 Kenwood Junction,,,,,,,,,,"Romaguera, Adams and Schoen",,FALSE,,,, +Ashli,Gheorghie,agheorghie1a@blogtalkradio.com,agheorghie1a,,FALSE,Hauck Inc,8 Warrior Drive,,,,,,,,,,Wisozk Inc,,FALSE,,,, +Janice,Freddi,jfreddi1b@behance.net,jfreddi1b,,TRUE,"Stoltenberg, Aufderhar and Schaden",0 Esch Alley,,,,,,,,,,,,FALSE,,,, +Reinwald,Ivakhin,rivakhin1c@ask.com,rivakhin1c,,FALSE,Jacobson-Mosciski,24 New Castle Alley,,,,,,,,,,Welch and Sons,,TRUE,,,, +Lindsey,Trevance,ltrevance1d@prnewswire.com,ltrevance1d,,TRUE,Hansen-Luettgen,17443 Lindbergh Plaza,,,,,,,Web Designer II,interdum eu tincidunt in leo maecenas pulvinar lobortis est phasellus,,,,FALSE,,,, +Cordi,Frostdyke,cfrostdyke1e@weather.com,cfrostdyke1e,,FALSE,Kohler Inc,53066 Merchant Plaza,,,,,,,,,,,,FALSE,,,, +Jayme,Piatto,jpiatto1f@slate.com,jpiatto1f,,TRUE,Johnson and Sons,5598 Fuller Avenue,,,,,,,Graphic Designer,accumsan felis ut at dolor quis odio consequat varius integer,,,,TRUE,,,, +Henriette,Glanvill,hglanvill1g@ifeng.com,hglanvill1g,,TRUE,"Mills, Kautzer and Stiedemann",6461 Stang Center,,,,,,,,,,Gibson and Sons,,TRUE,,,, +Izak,Legen,ilegen1h@berkeley.edu,ilegen1h,,TRUE,"Schiller, Runolfsson and Gottlieb",86874 Hovde Avenue,,,,,,,,,,,,FALSE,,,, +Silas,Vallentin,svallentin1i@zdnet.com,svallentin1i,,FALSE,Wolff Inc,15041 Graceland Park,,,,,,,,,,,,TRUE,,,, +Ansel,Augustus,aaugustus1j@oaic.gov.au,aaugustus1j,,TRUE,"Rippin, Frami and Parker",843 Nova Alley,,,,,,,Assistant Media Planner,ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae donec,,Morissette and Sons,,FALSE,,,, +Annemarie,Reburn,areburn1k@networksolutions.com,areburn1k,,TRUE,Dach Group,05 Crowley Avenue,,,,,,,Administrative Assistant IV,vivamus tortor duis mattis egestas metus aenean fermentum donec,,"Murazik, Wyman and Yost",,FALSE,,,, +Fee,Bissell,fbissell1l@comsenz.com,fbissell1l,,TRUE,Braun Group,678 Nelson Hill,,,,,,,Health Coach IV,sed augue aliquam erat volutpat in congue etiam justo etiam pretium iaculis justo in,,"Lindgren, Quitzon and Heathcote",,TRUE,,,, +Zenia,Kordt,zkordt1m@com.com,zkordt1m,,TRUE,"Harvey, Fay and Yundt",6337 Mayer Trail,,,,,,,Associate Professor,congue etiam justo etiam pretium iaculis justo in hac habitasse platea dictumst etiam faucibus cursus urna,,,,TRUE,,,, +Winthrop,Eales,weales1n@stanford.edu,weales1n,,TRUE,Johns-Kshlerin,79780 Helena Lane,,,,,,,Accountant I,platea dictumst etiam faucibus cursus urna ut,,,,FALSE,,,, +Davis,,,dnatalie1o,,FALSE,Tillman-Marquardt,3893 Express Junction,,,,,https://answers.com,266-409-9118,Teacher,suspendisse accumsan tortor quis turpis sed ante vivamus tortor,,Casper-Grimes,Davis Natalie,FALSE,FALSE,2022-04-08,2022-09-24,dnatalie1o@altervista.org +Massimiliano,Fardo,mfardo1p@imgur.com,mfardo1p,,TRUE,Kozey Group,72 Hauk Terrace,,,,,,,Account Coordinator,parturient montes nascetur ridiculus mus etiam vel augue vestibulum rutrum rutrum neque aenean auctor gravida sem praesent id,,Bednar Inc,,FALSE,,,, +Dacey,Larrie,dlarrie1q@digg.com,dlarrie1q,,FALSE,Jerde-Ullrich,70371 Del Mar Center,,,,,,,,,,,,TRUE,,,, +Pattie,Melvin,pmelvin1r@discovery.com,pmelvin1r,,FALSE,"McDermott, Mayert and Kemmer",845 Anderson Point,,,,,,,Safety Technician II,sit amet erat nulla tempus vivamus in felis eu sapien cursus vestibulum proin,,,,TRUE,,,, +Franny,Laughlin,flaughlin1s@blogspot.com,flaughlin1s,,FALSE,Renner-Terry,94 Northfield Pass,,,,,,,,,,"Parisian, Hudson and Bahringer",,FALSE,,,, +Mariel,Roelvink,mroelvink1t@timesonline.co.uk,mroelvink1t,,TRUE,Russel-Blanda,434 Crest Line Road,,,,,http://amazon.de,429-401-0847,Quality Engineer,vel pede morbi porttitor lorem id ligula suspendisse ornare consequat lectus in est risus auctor sed tristique in tempus,,,Mariel Roelvink,TRUE,FALSE,2022-02-21,2022-09-01,mroelvink1t@feedburner.com +Josee,Ghirardi,jghirardi1u@arizona.edu,jghirardi1u,,TRUE,Koss-Schmitt,96 Kingsford Avenue,,,,,,,,,,,,TRUE,,,, +Felix,Pheasant,fpheasant1v@soundcloud.com,fpheasant1v,,TRUE,Rogahn Group,43 Northridge Place,,,,,,,,,,Hoppe-O'Reilly,,FALSE,,,, +Stearne,Gwatkins,sgwatkins1w@jugem.jp,sgwatkins1w,,FALSE,"Koch, Ferry and Marks",6 Victoria Circle,,,,,,,,,,,,FALSE,,,, +Nathaniel,Parkinson,nparkinson1x@springer.com,nparkinson1x,,TRUE,Harber Group,4589 Clarendon Way,,,,,,,Software Consultant,non mattis pulvinar nulla pede ullamcorper augue a suscipit nulla elit ac nulla sed vel enim sit amet nunc viverra,,Koepp LLC,,TRUE,,,, +Blondelle,Crawley,bcrawley1y@ezinearticles.com,bcrawley1y,,TRUE,"Hirthe, Bashirian and Feeney",17149 Ridge Oak Park,,,,,,,Help Desk Technician,sit amet cursus id turpis integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus nisi eu,,,,TRUE,,,, +Pammi,Yair,pyair1z@virginia.edu,pyair1z,,TRUE,"Pfeffer, Schmeler and Dibbert",541 Beilfuss Alley,,,,,,,,,,,,TRUE,,,, +Tremain,Lattimer,tlattimer20@go.com,tlattimer20,,TRUE,"Kuvalis, Kris and Howell",19 Red Cloud Parkway,,,,,,,,,,Gutkowski LLC,,TRUE,,,, +Moreen,Fermin,mfermin21@w3.org,mfermin21,,FALSE,"Romaguera, Spinka and Bayer",50 Eagle Crest Circle,,,,,,,,,,,,TRUE,,,, +Jena,Taborre,jtaborre22@pinterest.com,jtaborre22,,TRUE,Raynor Group,97 Helena Center,,,,,,,Dental Hygienist,vel enim sit amet nunc viverra dapibus nulla suscipit ligula in lacus curabitur at ipsum ac tellus semper interdum mauris,,,,FALSE,,,, +Odille,Stede,ostede23@biglobe.ne.jp,ostede23,,TRUE,"Boyle, Schowalter and Mayer",88993 Sunbrook Street,,,,,http://live.com,464-815-6024,,,,,Odille Stede,TRUE,FALSE,2021-12-12,2022-06-27,ostede23@lycos.com +Kori,Fulk,kfulk24@tiny.cc,kfulk24,,TRUE,Konopelski and Sons,43 Mockingbird Avenue,,,,,,,,,,"Nikolaus, Cassin and Streich",,TRUE,,,, +Pollyanna,Cardon,pcardon25@infoseek.co.jp,pcardon25,,FALSE,Hickle Group,52088 Almo Junction,,,,,,,,,,"Cronin, Cummerata and Tromp",,FALSE,,,, +Austin,McGeneay,amcgeneay26@tmall.com,amcgeneay26,,TRUE,Yundt-Howell,021 4th Park,,,,,,,Social Worker,est phasellus sit amet erat nulla tempus vivamus in felis eu sapien cursus vestibulum proin eu mi nulla,,,,TRUE,,,, +Imogen,Hamill,ihamill27@w3.org,ihamill27,,FALSE,Herman-Schulist,802 Sunbrook Place,,,,,http://vistaprint.com,344-665-1217,Registered Nurse,curabitur convallis duis consequat dui nec nisi volutpat,,,Imogen Hamill,FALSE,FALSE,2021-12-03,2023-04-16,ihamill27@over-blog.com +Hershel,Bielfeld,hbielfeld28@soup.io,hbielfeld28,,TRUE,Kreiger and Sons,6944 Buell Trail,,,,,,,Actuary,curae donec pharetra magna vestibulum aliquet ultrices erat,,Schmitt-Abbott,,TRUE,,,, +Korry,,,ksteckings29,,TRUE,Bogan Inc,800 Ilene Parkway,,,,,,,,,,,,TRUE,,,, +Cookie,Warret,cwarret2a@sakura.ne.jp,cwarret2a,,FALSE,Murphy-Yost,9 Vera Terrace,,,,,,,Mechanical Systems Engineer,semper rutrum nulla nunc purus phasellus in felis donec semper sapien a libero nam dui proin leo odio,,"Lueilwitz, Beahan and Raynor",,FALSE,,,, +Wynne,Gonnely,wgonnely2b@facebook.com,wgonnely2b,,TRUE,"Frami, Erdman and Mayert",051 Kenwood Junction,,,,,,,,,,,,TRUE,,,, +Ethelred,Bogey,ebogey2c@infoseek.co.jp,ebogey2c,,TRUE,Christiansen and Sons,7414 2nd Pass,,,,,,,Media Manager II,donec odio justo sollicitudin ut suscipit a feugiat et eros vestibulum ac est lacinia,,,,FALSE,,,, +Alvera,Tunuy,atunuy2d@bizjournals.com,atunuy2d,,FALSE,"Vandervort, Veum and Walker",152 Division Park,,,,,,,,,,"Bartell, Hartmann and Jerde",,FALSE,,,, +Martino,Rosenbusch,mrosenbusch2e@seesaa.net,mrosenbusch2e,,TRUE,Parisian-Romaguera,130 Westridge Alley,,,,,http://bravesites.com,626-888-4072,,,,"Keebler, Walter and Senger",Martino Rosenbusch,FALSE,FALSE,2022-01-20,2022-09-11,mrosenbusch2e@about.me +Susi,Trapp,strapp2f@ft.com,strapp2f,,FALSE,"Rogahn, Volkman and McDermott",72958 Vahlen Avenue,,,,,,,,,,Nitzsche-Langosh,,TRUE,,,, +Gordon,Alflatt,galflatt2g@marriott.com,galflatt2g,,FALSE,Effertz-Howell,0681 International Plaza,,,,,,,Research Associate,duis aliquam convallis nunc proin,,"Farrell, Hoeger and O'Keefe",,TRUE,,,, +Derrick,Braidon,dbraidon2h@blogs.com,dbraidon2h,,FALSE,Prosacco-Walker,8760 Del Sol Circle,,,,,,,,,,Koss-Bogisich,,TRUE,,,, +Minnnie,Bonar,mbonar2i@biglobe.ne.jp,mbonar2i,,TRUE,Daniel LLC,5424 Karstens Alley,,,,,,,Web Designer III,faucibus orci luctus et ultrices posuere cubilia curae mauris,,,,TRUE,,,, +Casper,Sinnatt,csinnatt2j@hc360.com,csinnatt2j,,TRUE,Barrows-Mertz,79 Melvin Center,,,,,,,,,,,,FALSE,,,, +Chloe,Fist,cfist2k@auda.org.au,cfist2k,,FALSE,"Kling, Streich and Kertzmann",47064 Glacier Hill Court,,,,,,,,,,Altenwerth-Leuschke,,TRUE,,,, +Elysha,Gosenell,egosenell2l@ft.com,egosenell2l,,TRUE,Hirthe LLC,70 Old Gate Alley,,,,,,,Nuclear Power Engineer,amet cursus id turpis integer aliquet massa id lobortis convallis tortor risus dapibus augue vel accumsan tellus,,Macejkovic and Sons,,FALSE,,,, +Gerianna,Feirn,gfeirn2m@bing.com,gfeirn2m,,TRUE,"Collier, Kirlin and Armstrong",881 Summer Ridge Circle,,,,,,,,,,,,FALSE,,,, +Lucas,Mulvany,lmulvany2n@deliciousdays.com,lmulvany2n,,FALSE,Bahringer Group,639 La Follette Circle,,,,,,,,,,,,TRUE,,,, +Lenore,Menendez,lmenendez2o@cdbaby.com,lmenendez2o,,TRUE,"Nader, Harvey and Casper",02 Springs Avenue,,,,,https://a8.net,926-526-1742,Community Outreach Specialist,ut odio cras mi pede malesuada in imperdiet et commodo vulputate justo in blandit ultrices enim lorem ipsum dolor,,,Lenore Menendez,TRUE,FALSE,2022-01-11,2022-07-29,lmenendez2o@ifeng.com +Collete,Brandes,cbrandes2p@accuweather.com,cbrandes2p,,TRUE,Koepp-Parisian,5 Haas Way,,,,,,,,,,,,FALSE,,,, +Osborne,Gummory,ogummory2q@1und1.de,ogummory2q,,FALSE,Mertz and Sons,91749 Haas Alley,,,,,,,,,,,,TRUE,,,, +Emiline,Grossman,egrossman2r@dmoz.org,egrossman2r,,TRUE,Parisian and Sons,3872 Eagle Crest Court,,,,,https://uiuc.edu,338-830-8647,Food Chemist,dolor vel est donec odio justo sollicitudin ut suscipit a feugiat et eros vestibulum ac est lacinia nisi venenatis,,Williamson-Casper,Emiline Grossman,TRUE,TRUE,2021-11-10,2022-10-01,egrossman2r@spiegel.de \ No newline at end of file diff --git a/tests/Feature/Importing/Api/ImportUsersTest.php b/tests/Feature/Importing/Api/ImportUsersTest.php index fb4f61634e..42e1777ffb 100644 --- a/tests/Feature/Importing/Api/ImportUsersTest.php +++ b/tests/Feature/Importing/Api/ImportUsersTest.php @@ -260,21 +260,26 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ ); } + + /** + * Some of these should mismatch on purpose to ensure the mapping is working + * @return void + */ #[Test] public function customColumnMapping(): void { $faker = ImportFileBuilder::new()->definition(); $row = [ 'companyName' => $faker['username'], - 'email' => $faker['email'], + 'email' => $faker['position'], 'employeeNumber' => $faker['phoneNumber'], 'firstName' => $faker['location'], 'lastName' => $faker['lastName'], 'location' => $faker['firstName'], 'phoneNumber' => $faker['employeeNumber'], - 'position' => $faker['position'], + 'position' => $faker['email'], 'username' => $faker['companyName'], - 'display_name' => $faker['displayName'], + 'dumbName' => $faker['displayName'], ]; $importFileBuilder = new ImportFileBuilder([$row]); @@ -290,13 +295,15 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ 'Employee Number' => 'phone_number', 'First Name' => 'location', 'Last Name' => 'last_name', - 'Display Name' => 'display_name', 'Location' => 'first_name', 'Phone Number' => 'employee_num', 'Job Title' => 'email', 'Username' => 'company', + 'dumbName' => 'display_name', ] - ])->assertOk(); + ])->assertOk() + ->json(); + $newUser = User::query() ->with(['company', 'location']) @@ -306,7 +313,7 @@ class ImportUsersTest extends ImportDataTestCase implements TestsPermissionsRequ $this->assertEquals($row['position'], $newUser->email); $this->assertEquals($row['location'], $newUser->first_name); $this->assertEquals($row['lastName'], $newUser->last_name); - $this->assertEquals($row['displayName'], $newUser->display_name); + $this->assertEquals($row['dumbName'], $newUser->display_name); $this->assertEquals($row['email'], $newUser->jobtitle); $this->assertEquals($row['phoneNumber'], $newUser->employee_num); $this->assertEquals($row['username'], $newUser->company->name); diff --git a/tests/Support/Importing/UsersImportFileBuilder.php b/tests/Support/Importing/UsersImportFileBuilder.php index 99992438af..0490cf230a 100644 --- a/tests/Support/Importing/UsersImportFileBuilder.php +++ b/tests/Support/Importing/UsersImportFileBuilder.php @@ -31,16 +31,16 @@ class UsersImportFileBuilder extends FileBuilder protected function getDictionary(): array { return [ - 'companyName' => 'Company', - 'email' => 'email', - 'employeeNumber' => 'Employee Number', + 'companyName' => 'Company', + 'email' => 'email', + 'employeeNumber' => 'Employee Number', 'firstName' => 'First Name', - 'lastName' => 'Last Name', - 'displayName' => 'Display Name', - 'location' => 'Location', - 'phoneNumber' => 'Phone Number', - 'position' => 'Job Title', - 'username' => 'Username', + 'lastName' => 'Last Name', + 'displayName' => 'Display Name', + 'location' => 'Location', + 'phoneNumber' => 'Phone Number', + 'position' => 'Job Title', + 'username' => 'Username', ]; } @@ -53,15 +53,15 @@ class UsersImportFileBuilder extends FileBuilder return [ 'companyName' => $faker->company, - 'email' => Str::random(32) . "@{$faker->freeEmailDomain}", + 'email' => $faker->safeEmail(), 'employeeNumber' => $faker->uuid, 'firstName' => $faker->firstName, 'lastName' => $faker->lastName, - 'displayName' => 'Display: '.$faker->name, + 'displayName' => $faker->firstName, 'location' => "{$faker->city}, {$faker->country}", 'phoneNumber' => $faker->phoneNumber, 'position' => $faker->jobTitle, - 'username' => Str::random(), + 'username' => $faker->userName(), ]; } } From 73ac00bc519dda7e6dd6be1d69ea8d5e4c9d9dcf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 16:25:39 +0000 Subject: [PATCH 46/51] Bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/SA-codeql.yml | 2 +- .github/workflows/codacy-analysis.yml | 2 +- .github/workflows/crowdin-upload.yml | 2 +- .github/workflows/docker-alpine.yml | 2 +- .github/workflows/docker-ubuntu.yml | 2 +- .github/workflows/dockerhub-description.yml | 2 +- .github/workflows/tests-mysql.yml | 2 +- .github/workflows/tests-postgres.yml | 2 +- .github/workflows/tests-sqlite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/SA-codeql.yml b/.github/workflows/SA-codeql.yml index 29f3e1b1f1..007d07d37a 100644 --- a/.github/workflows/SA-codeql.yml +++ b/.github/workflows/SA-codeql.yml @@ -26,7 +26,7 @@ jobs: language: [ 'javascript' ] steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/codacy-analysis.yml b/.github/workflows/codacy-analysis.yml index 32de700bdc..fee3bab64c 100644 --- a/.github/workflows/codacy-analysis.yml +++ b/.github/workflows/codacy-analysis.yml @@ -32,7 +32,7 @@ jobs: steps: # Checkout the repository to the GitHub Actions runner - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis - name: Run Codacy Analysis CLI diff --git a/.github/workflows/crowdin-upload.yml b/.github/workflows/crowdin-upload.yml index 7b9331c97d..b2e798d562 100644 --- a/.github/workflows/crowdin-upload.yml +++ b/.github/workflows/crowdin-upload.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Crowdin push uses: crowdin/github-action@v2 diff --git a/.github/workflows/docker-alpine.yml b/.github/workflows/docker-alpine.yml index 86e0c022e2..a65d48d2e2 100644 --- a/.github/workflows/docker-alpine.yml +++ b/.github/workflows/docker-alpine.yml @@ -42,7 +42,7 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v4 + uses: actions/checkout@v5 # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx diff --git a/.github/workflows/docker-ubuntu.yml b/.github/workflows/docker-ubuntu.yml index a78ba7413c..c345105b7e 100644 --- a/.github/workflows/docker-ubuntu.yml +++ b/.github/workflows/docker-ubuntu.yml @@ -42,7 +42,7 @@ jobs: steps: # https://github.com/actions/checkout - name: Checkout codebase - uses: actions/checkout@v4 + uses: actions/checkout@v5 # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx diff --git a/.github/workflows/dockerhub-description.yml b/.github/workflows/dockerhub-description.yml index f9064dec95..8b5782339b 100644 --- a/.github/workflows/dockerhub-description.yml +++ b/.github/workflows/dockerhub-description.yml @@ -11,7 +11,7 @@ jobs: dockerHubDescription: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Docker Hub Description uses: grokability/dockerhub-description@7ea9d275c7cdbe2b676a093a0308c50665e3b8b4 diff --git a/.github/workflows/tests-mysql.yml b/.github/workflows/tests-mysql.yml index 16190900b0..237220b337 100644 --- a/.github/workflows/tests-mysql.yml +++ b/.github/workflows/tests-mysql.yml @@ -37,7 +37,7 @@ jobs: php-version: "${{ matrix.php-version }}" coverage: none - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Get Composer Cache Directory id: composer-cache diff --git a/.github/workflows/tests-postgres.yml b/.github/workflows/tests-postgres.yml index d111fc87a5..97379ec2bc 100644 --- a/.github/workflows/tests-postgres.yml +++ b/.github/workflows/tests-postgres.yml @@ -34,7 +34,7 @@ jobs: php-version: "${{ matrix.php-version }}" coverage: none - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Get Composer Cache Directory id: composer-cache diff --git a/.github/workflows/tests-sqlite.yml b/.github/workflows/tests-sqlite.yml index cd06805e01..fdf4ea2ce9 100644 --- a/.github/workflows/tests-sqlite.yml +++ b/.github/workflows/tests-sqlite.yml @@ -25,7 +25,7 @@ jobs: php-version: "${{ matrix.php-version }}" coverage: none - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Get Composer Cache Directory id: composer-cache From dd742a2e4ae39d741c24ac79f6d8cd9e4cdc10aa Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Mon, 25 Aug 2025 15:10:41 -0700 Subject: [PATCH 47/51] add a check for audit notification variables in MS Teams and a translation --- app/Notifications/AuditNotification.php | 12 ++++++------ resources/lang/en-US/general.php | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/Notifications/AuditNotification.php b/app/Notifications/AuditNotification.php index a7056e8cbd..47dfde30ee 100644 --- a/app/Notifications/AuditNotification.php +++ b/app/Notifications/AuditNotification.php @@ -57,7 +57,7 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage; $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; return (new SlackMessage) ->success() - ->content(class_basename(get_class($this->params['item'])).' Audited') + ->content(class_basename(get_class($this->params['item'])).' '.trans('general.audited')) ->from(($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot') ->to($channel) ->attachment(function ($attachment) { @@ -76,17 +76,17 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage; public static function toMicrosoftTeams($params) { - $item = $params['item']; - $admin_user = $params['admin']; - $note = $params['note']; - $location = $params['location']; + $item = $params['item'] ?? null; + $admin_user = $params['admin'] ?? null; + $note = $params['note'] ?? ''; + $location = $params['location'] ?? ''; $setting = Setting::getSettings(); if(!Str::contains($setting->webhook_endpoint, 'workflows')) { return MicrosoftTeamsMessage::create() ->to($setting->webhook_endpoint) ->type('success') - ->title(class_basename(get_class($params['item'])) . ' Audited') + ->title(class_basename(get_class($params['item'])) .' '.trans('general.audited')) ->addStartGroupToSection('activityText') ->fact(trans('mail.asset'), $item) ->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->present()->fullName()); diff --git a/resources/lang/en-US/general.php b/resources/lang/en-US/general.php index e4bc2ad232..1d501ee616 100644 --- a/resources/lang/en-US/general.php +++ b/resources/lang/en-US/general.php @@ -36,6 +36,7 @@ return [ 'accept_assets_menu' => 'Accept Assets', 'accept_item' => 'Accept Item', 'audit' => 'Audit', + 'audited' => 'Audited', 'audits' => 'Audits', 'audit_report' => 'Audit Log', 'assets' => 'Assets', From ecf24511cdbd5d036edf677ff47f75d7249ea8b4 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 26 Aug 2025 12:09:55 +0100 Subject: [PATCH 48/51] Fixed tests for real this time tho Signed-off-by: snipe --- app/Importer/Importer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Importer/Importer.php b/app/Importer/Importer.php index f21c108e8f..a5142f4380 100644 --- a/app/Importer/Importer.php +++ b/app/Importer/Importer.php @@ -371,7 +371,7 @@ abstract class Importer $user->first_name = $user_array['first_name']; $user->last_name = $user_array['last_name']; $user->username = $user_array['username']; - $user->username = $user_array['display_name']; + $user->display_name = $user_array['display_name'] ?? null; $user->email = $user_array['email']; $user->manager_id = $user_array['manager_id'] ?? null; $user->department_id = $user_array['department_id'] ?? null; From 855a176ca95c4d20a5cd5fc13c498525314b24b5 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 26 Aug 2025 12:41:17 +0100 Subject: [PATCH 49/51] Add @nickwest as a contributor --- .all-contributorsrc | 9 +++++++++ CONTRIBUTORS.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 3634e71d69..43422ef9ea 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -4216,6 +4216,15 @@ "contributions": [ "code" ] + }, + { + "login": "nickwest", + "name": "Nicky West", + "avatar_url": "https://avatars.githubusercontent.com/u/634790?v=4", + "profile": "http://nickwest.me", + "contributions": [ + "code" + ] } ] } diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7bd1223187..ff9f742460 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -68,7 +68,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken | [
Juan Font](https://github.com/juanfont)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juanfont "Code") | [
Juho Taipale](https://github.com/juhotaipale)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juhotaipale "Code") | [
Korvin Szanto](https://github.com/KorvinSzanto)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=KorvinSzanto "Code") | [
Lewis Foster](https://lewisfoster.foo/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=sniff122 "Code") | [
Logan Swartzendruber](https://github.com/loganswartz)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=loganswartz "Code") | [
Lorenzo P.](https://github.com/lopezio)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lopezio "Code") | [
Lukas Jung](https://github.com/m4us1ne)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=m4us1ne "Code") | | [
Ellie](https://leafedfox.xyz/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=LeafedFox "Code") | [
GA Stamper](https://github.com/gastamper)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gastamper "Code") | [
Guillaume Lefranc](https://github.com/gl-pup)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gl-pup "Code") | [
Hajo MΓΆller](https://github.com/dasjoe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=dasjoe "Code") | [
Istvan Basa](https://github.com/pottom)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=pottom "Code") | [
JJ Asghar](https://jjasghar.github.io/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jjasghar "Code") | [
James E. Msenga](https://github.com/JemCdo)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JemCdo "Code") | | [
Jan Felix Wiebe](https://github.com/jfwiebe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jfwiebe "Code") | [
Jo Drexl](https://www.nfon.com/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=drexljo "Code") | [
Austin Sasko](https://github.com/austinsasko)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=austinsasko "Code") | [
Jasson](http://jassoncordones.github.io)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JassonCordones "Code") | [
Okean](https://github.com/Tinyblargon)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=Tinyblargon "Code") | [
Alejandro Medrano](https://www.lst.tfo.upm.es/alejandro-medrano/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=amedranogil "Code") | [
Lukas Kraic](https://github.com/lukaskraic)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lukaskraic "Code") | -| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [
Johannes Pollitt](https://github.com/FlorestanII)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [
Michael Strobel](https://strobelm.de)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | +| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [
Johannes Pollitt](https://github.com/FlorestanII)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [
Michael Strobel](https://strobelm.de)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | [
Nicky West](http://nickwest.me)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=nickwest "Code") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! From 39955ac76042dc4e698545582afbe0fc847b97b1 Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 26 Aug 2025 12:42:20 +0100 Subject: [PATCH 50/51] Add @akaspeh1 as a contributor --- .all-contributorsrc | 9 +++++++++ CONTRIBUTORS.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 43422ef9ea..088a20081e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -4225,6 +4225,15 @@ "contributions": [ "code" ] + }, + { + "login": "akaspeh1", + "name": "akaspeh1", + "avatar_url": "https://avatars.githubusercontent.com/u/1347327?v=4", + "profile": "https://github.com/akaspeh1", + "contributions": [ + "code" + ] } ] } diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ff9f742460..c2011a5423 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -68,7 +68,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken | [
Juan Font](https://github.com/juanfont)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juanfont "Code") | [
Juho Taipale](https://github.com/juhotaipale)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=juhotaipale "Code") | [
Korvin Szanto](https://github.com/KorvinSzanto)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=KorvinSzanto "Code") | [
Lewis Foster](https://lewisfoster.foo/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=sniff122 "Code") | [
Logan Swartzendruber](https://github.com/loganswartz)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=loganswartz "Code") | [
Lorenzo P.](https://github.com/lopezio)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lopezio "Code") | [
Lukas Jung](https://github.com/m4us1ne)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=m4us1ne "Code") | | [
Ellie](https://leafedfox.xyz/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=LeafedFox "Code") | [
GA Stamper](https://github.com/gastamper)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gastamper "Code") | [
Guillaume Lefranc](https://github.com/gl-pup)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=gl-pup "Code") | [
Hajo MΓΆller](https://github.com/dasjoe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=dasjoe "Code") | [
Istvan Basa](https://github.com/pottom)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=pottom "Code") | [
JJ Asghar](https://jjasghar.github.io/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jjasghar "Code") | [
James E. Msenga](https://github.com/JemCdo)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JemCdo "Code") | | [
Jan Felix Wiebe](https://github.com/jfwiebe)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=jfwiebe "Code") | [
Jo Drexl](https://www.nfon.com/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=drexljo "Code") | [
Austin Sasko](https://github.com/austinsasko)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=austinsasko "Code") | [
Jasson](http://jassoncordones.github.io)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=JassonCordones "Code") | [
Okean](https://github.com/Tinyblargon)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=Tinyblargon "Code") | [
Alejandro Medrano](https://www.lst.tfo.upm.es/alejandro-medrano/)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=amedranogil "Code") | [
Lukas Kraic](https://github.com/lukaskraic)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=lukaskraic "Code") | -| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [
Johannes Pollitt](https://github.com/FlorestanII)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [
Michael Strobel](https://strobelm.de)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | [
Nicky West](http://nickwest.me)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=nickwest "Code") | +| [
Π“Π΅Ρ€Ρ…Π°Ρ€Π΄ PICCORO Lenz McKAY ](https://github-readme-stats.vercel.app/api?username=mckaygerhard)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [
Johannes Pollitt](https://github.com/FlorestanII)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [
Michael Strobel](https://strobelm.de)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | [
Nicky West](http://nickwest.me)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=nickwest "Code") | [
akaspeh1](https://github.com/akaspeh1)
[πŸ’»](https://github.com/snipe/snipe-it/commits?author=akaspeh1 "Code") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! From 17650c5735894b79fe1fe3481ea6aa01260528ca Mon Sep 17 00:00:00 2001 From: snipe Date: Tue, 26 Aug 2025 14:03:11 +0100 Subject: [PATCH 51/51] Changed field title 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 32b3f77649..b104236485 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -1137,7 +1137,7 @@ var keys = [ '{{ trans('admin/settings/general.employee_number') }}', '{{ trans('mail.username') }}', - '{{ trans('admin/settings/general.ldap_display_name') }}', + '{{ trans('admin/users/table.display_name') }}', '{{ trans('general.first_name') }}', '{{ trans('general.last_name') }}', '{{ trans('general.email') }}'