mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-10 07:34:06 -08:00
Merge pull request #12690 from snipe/features/more_merge_user_olish
More merge-user polishing
This commit is contained in:
commit
789c4b4df8
24
app/Events/UserMerged.php
Normal file
24
app/Events/UserMerged.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Models\User;
|
||||
|
||||
class UserMerged
|
||||
{
|
||||
use Dispatchable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $from_user, User $to_user, User $admin)
|
||||
{
|
||||
$this->merged_from = $from_user;
|
||||
$this->merged_to = $to_user;
|
||||
$this->admin = $admin;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Events\UserMerged;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Accessory;
|
||||
|
@ -22,7 +23,7 @@ use Illuminate\Support\Facades\Password;
|
|||
class BulkUsersController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that confirms the user's a bulk delete will be applied to.
|
||||
* Returns a view that confirms the user's a bulk action will be applied to.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
|
@ -36,18 +37,32 @@ class BulkUsersController extends Controller
|
|||
|
||||
// Make sure there were users selected
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
|
||||
|
||||
// Get the list of affected users
|
||||
$user_raw_array = request('ids');
|
||||
$users = User::whereIn('id', $user_raw_array)
|
||||
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
||||
|
||||
// bulk edit, display the bulk edit form
|
||||
if ($request->input('bulk_actions') == 'edit') {
|
||||
return view('users/bulk-edit', compact('users'))
|
||||
->with('groups', Group::pluck('name', 'id'));
|
||||
|
||||
// bulk delete, display the bulk delete confirmation form
|
||||
} elseif ($request->input('bulk_actions') == 'delete') {
|
||||
return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList());
|
||||
|
||||
// merge, confirm they have at least 2 users selected and display the merge screen
|
||||
} elseif ($request->input('bulk_actions') == 'merge') {
|
||||
return view('users/confirm-merge')->with('users', $users);
|
||||
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 1)) {
|
||||
return view('users/confirm-merge')->with('users', $users);
|
||||
// Not enough users selected, send them back
|
||||
} else {
|
||||
return redirect()->back()->with('error', trans('general.not_enough_users_selected', ['count' => 2]));
|
||||
}
|
||||
|
||||
// bulk password reset, just do the thing
|
||||
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
|
||||
foreach ($users as $user) {
|
||||
if (($user->activated == '1') && ($user->email != '')) {
|
||||
|
@ -273,55 +288,58 @@ class BulkUsersController extends Controller
|
|||
$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)) {
|
||||
if ((!$request->filled('merge_into_id')) || (count($user_ids_to_merge) < 1)) {
|
||||
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();
|
||||
$admin = User::find(Auth::user()->id);
|
||||
|
||||
// Walk users
|
||||
foreach ($users_to_merge as $user) {
|
||||
foreach ($users_to_merge as $user_to_merge) {
|
||||
|
||||
foreach ($user->assets as $asset) {
|
||||
foreach ($user_to_merge->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) {
|
||||
foreach ($user_to_merge->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]);
|
||||
$user_to_merge->licenses()->updateExistingPivot($license->id, ['assigned_to' => $merge_into_user->id]);
|
||||
}
|
||||
|
||||
foreach ($user->consumables as $consumable) {
|
||||
foreach ($user_to_merge->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]);
|
||||
$user_to_merge->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_to_merge->accessories as $accessory) {
|
||||
$user_to_merge->accessories()->updateExistingPivot($accessory->id, ['assigned_to' => $merge_into_user->id]);
|
||||
}
|
||||
|
||||
foreach ($user->userlog as $log) {
|
||||
$log->target_id = $user->id;
|
||||
foreach ($user_to_merge->userlog as $log) {
|
||||
$log->target_id = $user_to_merge->id;
|
||||
$log->save();
|
||||
}
|
||||
|
||||
User::where('manager_id', '=', $user->id)->update(['manager_id' => $merge_into_user->id]);
|
||||
User::where('manager_id', '=', $user_to_merge->id)->update(['manager_id' => $merge_into_user->id]);
|
||||
|
||||
foreach ($user->managedLocations as $managedLocation) {
|
||||
foreach ($user_to_merge->managedLocations as $managedLocation) {
|
||||
$managedLocation->manager_id = $merge_into_user->id;
|
||||
$managedLocation->save();
|
||||
}
|
||||
|
||||
$user->deleted_at = Carbon::now()->timestamp;
|
||||
$user->save();
|
||||
$user_to_merge->delete();
|
||||
//$user_to_merge->save();
|
||||
|
||||
event(new UserMerged($user_to_merge, $merge_into_user, $admin));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('success', trans('general.merge_success'));
|
||||
return redirect()->route('users.index')->with('success', trans('general.merge_success', ['count' => $users_to_merge->count(), 'into_username' => $merge_into_user->username]));
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@ use App\Events\ItemDeclined;
|
|||
use App\Events\LicenseCheckedIn;
|
||||
use App\Events\LicenseCheckedOut;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Events\UserMerged;
|
||||
|
||||
class LogListener
|
||||
{
|
||||
|
@ -87,6 +89,43 @@ class LogListener
|
|||
$logaction->save();
|
||||
}
|
||||
|
||||
|
||||
public function onUserMerged(UserMerged $event)
|
||||
{
|
||||
|
||||
$to_from_array = [
|
||||
'to_id' => $event->merged_to->id,
|
||||
'to_username' => $event->merged_to->username,
|
||||
'from_id' => $event->merged_from->id,
|
||||
'from_username' => $event->merged_from->username,
|
||||
];
|
||||
|
||||
// Add a record to the users being merged FROM
|
||||
\Log::debug('Users merged: '.$event->merged_from->id .' ('.$event->merged_from->username.') merged into '. $event->merged_to->id. ' ('.$event->merged_to->username.')');
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_id = $event->merged_from->id;
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->target_id = $event->merged_to->id;
|
||||
$logaction->target_type = User::class;
|
||||
$logaction->action_type = 'merged';
|
||||
$logaction->note = trans('general.merged_log_this_user_from', $to_from_array);
|
||||
$logaction->user_id = $event->admin->id;
|
||||
$logaction->save();
|
||||
|
||||
// Add a record to the users being merged TO
|
||||
$logaction = new Actionlog();
|
||||
$logaction->target_id = $event->merged_from->id;
|
||||
$logaction->target_type = User::class;
|
||||
$logaction->item_id = $event->merged_to->id;
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->action_type = 'merged';
|
||||
$logaction->note = trans('general.merged_log_this_user_into', $to_from_array);
|
||||
$logaction->user_id = $event->admin->id;
|
||||
$logaction->save();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the listeners for the subscriber.
|
||||
*
|
||||
|
@ -99,6 +138,7 @@ class LogListener
|
|||
'CheckoutableCheckedOut',
|
||||
'CheckoutAccepted',
|
||||
'CheckoutDeclined',
|
||||
'UserMerged',
|
||||
];
|
||||
|
||||
foreach ($list as $event) {
|
||||
|
@ -108,4 +148,6 @@ class LogListener
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ class ActionlogPresenter extends Presenter
|
|||
return 'far fa-save';
|
||||
} elseif ($this->itemType() == 'component') {
|
||||
return 'far fa-hdd';
|
||||
} elseif ($this->itemType() == 'user') {
|
||||
return 'fa-solid fa-people-arrows';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -409,9 +409,14 @@ return [
|
|||
'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.',
|
||||
'merge_information' => 'This will merge the :count users into a single user. Select the user you wish to merge the others into below, and the associated assets, licences, etc will be moved over to the selected user and the other users will be marked as deleted.',
|
||||
'warning_merge_information' => 'This action CANNOT be undone and should ONLY be used when you need to merge users because of a bad import or sync. Be sure to run a backup first.',
|
||||
'no_users_selected' => 'No users selected',
|
||||
'merge_success' => 'Users merged successfully',
|
||||
'not_enough_users_selected' => 'At least :count users must be selected',
|
||||
'merge_success' => ':count users merged successfully into :into_username!',
|
||||
'merged' => 'merged',
|
||||
'merged_log_this_user_into' => 'Merged this user (ID :to_id - :to_username) into user ID :from_id (:from_username) ',
|
||||
'merged_log_this_user_from' => 'Merged user ID :from_id (:from_username) into this user (ID :to_id - :to_username)',
|
||||
|
||||
|
||||
];
|
|
@ -7,19 +7,25 @@
|
|||
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-md-offset-1">
|
||||
<div class="box box-default">
|
||||
<form class="form-horizontal" role="form" method="post" action="{{ route('users.merge.save') }}">
|
||||
<div class="box-body">
|
||||
|
||||
<div class="col-md-12">
|
||||
<p style="padding:10px">
|
||||
{{ trans('general.merge_information', array('count' => count($users))) }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- 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))) }}
|
||||
{{ trans('general.warning_merge_information') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -39,7 +45,6 @@
|
|||
<table class="display table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="col-md-3">{{ trans('general.name') }}</th>
|
||||
<th class="col-md-3">{{ trans('general.email') }}</th>
|
||||
<th class="col-md-3">{{ trans('general.username') }}</th>
|
||||
|
@ -66,14 +71,8 @@
|
|||
@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() }}
|
||||
</span>
|
||||
{{ (Auth::id()==$user->id ? ' (cannot delete yourself)' : '') }}
|
||||
<input type="radio" name="merge_into_id" id="{{ $user->id }}" value="{{ $user->id }}" class="minimal">
|
||||
<label for="{{ $user->id }}"> {{ $user->present()->fullName() }}</label>
|
||||
</td>
|
||||
<td>
|
||||
{{ $user->email }}
|
||||
|
@ -112,7 +111,7 @@
|
|||
</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"{{ (config('app.lock_passwords') ? ' disabled' : '') }}><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('button.submit') }}</button>
|
||||
<button type="submit" class="btn btn-success"{{ (config('app.lock_passwords') ? ' disabled' : '') }} disabled="disabled"><i class="fas fa-check icon-white" aria-hidden="true"></i> {{ trans('button.submit') }}</button>
|
||||
</div><!-- /.box-footer -->
|
||||
|
||||
@foreach ($users as $user)
|
||||
|
@ -128,4 +127,17 @@
|
|||
|
||||
@section('moar_scripts')
|
||||
|
||||
@if (!(config('app.lock_passwords')))
|
||||
|
||||
<script>
|
||||
|
||||
$('button[type="submit"]').prop("disabled", true);
|
||||
|
||||
$('input').on('ifChecked', function(event) {
|
||||
$(' button[type="submit"]').prop("disabled", false);
|
||||
});
|
||||
|
||||
</script>
|
||||
@endif
|
||||
|
||||
@stop
|
|
@ -958,16 +958,18 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th data-field="icon" style="width: 40px;" class="hidden-xs" data-formatter="iconFormatter">Icon</th>
|
||||
<th class="col-sm-3" data-field="created_at" data-formatter="dateDisplayFormatter" data-sortable="true">{{ trans('general.date') }}</th>
|
||||
<th class="col-sm-2" data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.admin') }}</th>
|
||||
<th class="col-sm-2" data-field="action_type">{{ trans('general.action') }}</th>
|
||||
<th data-field="created_at" data-formatter="dateDisplayFormatter" data-sortable="true">{{ trans('general.date') }}</th>
|
||||
<th data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
|
||||
<th data-field="action_type">{{ trans('general.action') }}</th>
|
||||
<th data-field="target" data-formatter="polymorphicItemFormatter">{{ trans('general.target') }}</th>
|
||||
<th data-field="note">{{ trans('general.notes') }}</th>
|
||||
@if ($snipeSettings->require_accept_signature=='1')
|
||||
<th class="col-md-3" data-field="signature_file" data-visible="false" data-formatter="imageFormatter">{{ trans('general.signature') }}</th>
|
||||
<th data-field="signature_file" data-visible="false" data-formatter="imageFormatter">{{ trans('general.signature') }}</th>
|
||||
@endif
|
||||
<th class="col-sm-3" data-field="item.serial" data-visible="false">{{ trans('admin/hardware/table.serial') }}</th>
|
||||
<th class="col-sm-3" data-field="item" data-formatter="polymorphicItemFormatter">{{ trans('general.item') }}</th>
|
||||
<th class="col-sm-3" data-field="note">{{ trans('general.notes') }}</th>
|
||||
<th class="col-sm-2" data-field="target" data-formatter="polymorphicItemFormatter">{{ trans('general.target') }}</th>
|
||||
<th data-field="item.serial" data-visible="false">{{ trans('admin/hardware/table.serial') }}</th>
|
||||
<th data-field="admin" data-formatter="usersLinkObjFormatter">{{ trans('general.admin') }}</th>
|
||||
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
|
Loading…
Reference in a new issue