Merge pull request #12685 from snipe/features/merge_users

Added user merge
This commit is contained in:
snipe 2023-03-16 18:20:24 -07:00 committed by GitHub
commit f566a71658
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 192 additions and 0 deletions

View file

@ -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] [<snipe@snipe.net>]
* @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'));
}
}

View file

@ -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',
];

View file

@ -12,6 +12,7 @@
<select name="bulk_actions" class="form-control select2" style="width: 200px;" aria-label="bulk_actions">
<option value="edit">{{ trans('general.bulk_edit') }}</option>
<option value="delete">{!! trans('general.bulk_checkin_delete') !!}</option>
<option value="merge">{!! trans('general.merge_users') !!}</option>
<option value="bulkpasswordreset">{{ trans('button.send_password_link') }}</option>
</select>
<button class="btn btn-primary" id="bulkUserEditButton" disabled>{{ trans('button.go') }}</button>

View file

@ -0,0 +1,107 @@
@extends('layouts/default')
{{-- Page title --}}
@section('title')
{!! trans('general.merge_users') !!}
@parent
@stop
{{-- Page content --}}
@section('content')
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="box box-default">
<form class="form-horizontal" role="form" method="post" action="{{ route('users.merge.save') }}">
<div class="box-body">
<!-- CSRF Token -->
{{csrf_field()}}
<div class="row">
<div class="col-md-12">
<div class="callout callout-danger">
<i class="fas fa-exclamation-triangle"></i>
{{ trans('general.warning_merge_information', array('count' => count($users))) }}
</div>
</div>
</div>
@if (config('app.lock_passwords'))
<div class="col-md-12">
<div class="callout callout-warning">
<p>{{ trans('general.feature_disabled') }}</p>
</div>
</div>
@endif
<div class="col-md-12">
<div class="table-responsive">
<table class="display table table-hover">
<thead>
<tr>
<th class="col-md-1"></th>
<th class="col-md-6">{{ trans('general.name') }}</th>
<th class="col-md-5">{{ trans('general.groups') }}</th>
<th class="col-md-5">{{ trans('general.assets') }}</th>
<th class="col-md-5">{{ trans('general.accessories') }}</th>
<th class="col-md-5">{{ trans('general.licenses') }}</th>
<th class="col-md-5">{{ trans('general.consumables') }}</th>
</tr>
</thead>
<tbody>
@foreach ($users as $user)
<tr {!! ($user->isSuperUser() ? ' class="danger"':'') !!}>
<td>
<input type="radio" name="merge_into_id" value="{{ $user->id }}" class="minimal" checked="checked">
</td>
<td>
<span {!! (Auth::user()->id==$user->id ? ' style="text-decoration: line-through"' : '') !!}>
{{ $user->present()->fullName() }} ({{ $user->username }}) (#{{ $user->id }})
</span>
{{ (Auth::id()==$user->id ? ' (cannot delete yourself)' : '') }}
</td>
<td>
@foreach ($user->groups as $group)
<a href=" {{ route('groups.update', $group->id) }}" class="label label-default">
{{ $group->name }}
</a>&nbsp;
@endforeach
</td>
<td>
{{ number_format($user->assets()->count()) }}
</td>
<td>
{{ number_format($user->accessories()->count()) }}
</td>
<td>
{{ number_format($user->licenses()->count()) }}
</td>
<td>
{{ number_format($user->consumables()->count()) }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div> <!--/table-responsive-->
</div><!--/col-md-12-->
</div> <!--/box-body-->
<div class="box-footer text-right">
<a class="btn btn-link pull-left" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
<button type="submit" class="btn btn-success"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('button.submit') }}</button>
</div><!-- /.box-footer -->
@foreach ($users as $user)
<input type="hidden" name="ids_to_merge[]" value="{{ $user->id }}">
@endforeach
</form>
</div>
</div>
</div>
@stop
@section('moar_scripts')
@stop

View file

@ -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',