From 853e809ff8cc3345667f398d4c5a936481df1893 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 16 Mar 2023 18:18:26 -0700 Subject: [PATCH 1/5] Added route Signed-off-by: snipe --- routes/web/users.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/routes/web/users.php b/routes/web/users.php index 0183d48dc..95de20063 100644 --- a/routes/web/users.php +++ b/routes/web/users.php @@ -120,6 +120,14 @@ Route::group(['prefix' => 'users', 'middleware' => ['auth']], function () { ] )->name('users/bulkedit'); + Route::post( + 'merge', + [ + Users\BulkUsersController::class, + 'merge' + ] + )->name('users.merge.save'); + Route::post( 'bulksave', From 0dfb51f6421ab1552662d11267c56126b908a8d9 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 16 Mar 2023 18:18:32 -0700 Subject: [PATCH 2/5] User merge blade Signed-off-by: snipe --- resources/views/users/confirm-merge.blade.php | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 resources/views/users/confirm-merge.blade.php diff --git a/resources/views/users/confirm-merge.blade.php b/resources/views/users/confirm-merge.blade.php new file mode 100644 index 000000000..f01846d32 --- /dev/null +++ b/resources/views/users/confirm-merge.blade.php @@ -0,0 +1,107 @@ +@extends('layouts/default') +{{-- Page title --}} +@section('title') + {!! trans('general.merge_users') !!} + @parent +@stop + +{{-- Page content --}} +@section('content') + +
+
+
+
+
+ + {{csrf_field()}} +
+
+
+ + {{ trans('general.warning_merge_information', array('count' => count($users))) }} +
+
+
+ + @if (config('app.lock_passwords')) +
+
+

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

+
+
+ @endif + +
+
+ + + + + + + + + + + + + + @foreach ($users as $user) + isSuperUser() ? ' class="danger"':'') !!}> + + + + + + + + + + @endforeach + + +
{{ trans('general.name') }}{{ trans('general.groups') }}{{ trans('general.assets') }}{{ trans('general.accessories') }}{{ trans('general.licenses') }}{{ trans('general.consumables') }}
+ + + id==$user->id ? ' style="text-decoration: line-through"' : '') !!}> + {{ $user->present()->fullName() }} ({{ $user->username }}) (#{{ $user->id }}) + + {{ (Auth::id()==$user->id ? ' (cannot delete yourself)' : '') }} + + @foreach ($user->groups as $group) + + {{ $group->name }} +   + @endforeach + + {{ number_format($user->assets()->count()) }} + + {{ number_format($user->accessories()->count()) }} + + {{ number_format($user->licenses()->count()) }} + + {{ number_format($user->consumables()->count()) }} +
+
+
+
+ + + @foreach ($users as $user) + + @endforeach + +
+
+
+
+ +@stop + +@section('moar_scripts') + +@stop \ No newline at end of file From 07fbbf5f7f04b95734f020e1b97b2a293ca54c11 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 16 Mar 2023 18:18:54 -0700 Subject: [PATCH 3/5] Added merge to user menu Signed-off-by: snipe --- resources/views/partials/users-bulk-actions.blade.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/views/partials/users-bulk-actions.blade.php b/resources/views/partials/users-bulk-actions.blade.php index 016f54921..381f18391 100644 --- a/resources/views/partials/users-bulk-actions.blade.php +++ b/resources/views/partials/users-bulk-actions.blade.php @@ -12,6 +12,7 @@ From d3d26cb988db0e448945f37bf3ec9c6697a6d3c7 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 16 Mar 2023 18:19:03 -0700 Subject: [PATCH 4/5] Added translations Signed-off-by: snipe --- resources/lang/en/general.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/lang/en/general.php b/resources/lang/en/general.php index 8ac322e8b..153e5d1da 100644 --- a/resources/lang/en/general.php +++ b/resources/lang/en/general.php @@ -408,6 +408,10 @@ return [ 'false' => 'False', 'integration_option' => 'Integration Option', 'log_does_not_exist' => 'No matching log record exists.', + 'merge_users' => 'Merge Users', + 'warning_merge_information' => 'This will merge the selected :count users into a single user. Select the user you wish to merge the others into into below. THIS ACTION CANNOT BE UNDONE and should ONLY be used when you need to merge users because of a bad import or sync.', + 'no_users_selected' => 'No users selected', + 'merge_success' => 'Users merged successfully', ]; \ No newline at end of file From 0dd11575c5aaaffae0050a10582a7c896667a031 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 16 Mar 2023 18:19:16 -0700 Subject: [PATCH 5/5] Added merge controller Signed-off-by: snipe --- .../Controllers/Users/BulkUsersController.php | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/app/Http/Controllers/Users/BulkUsersController.php b/app/Http/Controllers/Users/BulkUsersController.php index 3550b4370..3334d3c0b 100644 --- a/app/Http/Controllers/Users/BulkUsersController.php +++ b/app/Http/Controllers/Users/BulkUsersController.php @@ -13,6 +13,7 @@ use App\Models\LicenseSeat; use App\Models\ConsumableAssignment; use App\Models\Consumable; use App\Models\User; +use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; @@ -45,6 +46,8 @@ class BulkUsersController extends Controller ->with('groups', Group::pluck('name', 'id')); } elseif ($request->input('bulk_actions') == 'delete') { return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList()); + } elseif ($request->input('bulk_actions') == 'merge') { + return view('users/confirm-merge')->with('users', $users); } elseif ($request->input('bulk_actions') == 'bulkpasswordreset') { foreach ($users as $user) { if (($user->activated == '1') && ($user->email != '')) { @@ -249,4 +252,73 @@ class BulkUsersController extends Controller $logAction->logaction('checkin from'); } } + + /** + * Save bulk-edited users + * + * @author [A. Gianotto] [] + * @since [v1.0] + * @param Request $request + * @return \Illuminate\Http\RedirectResponse + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function merge(Request $request) + { + $this->authorize('update', User::class); + + $user_ids_to_merge = $request->input('ids_to_merge'); + $user_ids_to_merge = array_diff($user_ids_to_merge, array($request->input('merge_into_id'))); + + if ((!$request->filled('merge_into_id')) || (count($user_ids_to_merge) < 0)) { + return redirect()->back()->with('error', trans('general.no_users_selected')); + } + + // Get the users + $merge_into_user = User::find($request->input('merge_into_id')); + $users_to_merge = User::whereIn('id', $user_ids_to_merge)->with('assets', 'licenses', 'consumables','accessories')->get(); + + // Walk users + foreach ($users_to_merge as $user) { + + foreach ($user->assets as $asset) { + \Log::debug('Updating asset: '.$asset->asset_tag . ' to '.$merge_into_user->id); + $asset->assigned_to = $request->input('merge_into_id'); + $asset->save(); + } + + foreach ($user->licenses as $license) { + \Log::debug('Updating license pivot: '.$license->id . ' to '.$merge_into_user->id); + $user->licenses()->updateExistingPivot($license->id, ['assigned_to' => $merge_into_user->id]); + } + + foreach ($user->consumables as $consumable) { + \Log::debug('Updating consumable pivot: '.$consumable->id . ' to '.$merge_into_user->id); + $user->consumables()->updateExistingPivot($consumable->id, ['assigned_to' => $merge_into_user->id]); + } + + foreach ($user->accessories as $accessory) { + $user->accessories()->updateExistingPivot($accessory->id, ['assigned_to' => $merge_into_user->id]); + } + + foreach ($user->userlog as $log) { + $log->target_id = $user->id; + $log->save(); + } + + User::where('manager_id', '=', $user->id)->update(['manager_id' => $merge_into_user->id]); + + foreach ($user->managedLocations as $managedLocation) { + $managedLocation->manager_id = $merge_into_user->id; + $managedLocation->save(); + } + + $user->deleted_at = Carbon::now()->timestamp; + $user->save(); + + } + + return redirect()->route('users.index')->with('success', trans('general.merge_success')); + + + } }