mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-28 23:19:42 -08:00
Merge remote-tracking branch 'origin/develop'
This commit is contained in:
commit
fc7809192d
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Events\UserMerged;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
@ -51,7 +52,7 @@ class MergeUsersByUsername extends Command
|
|||
|
||||
$bad_users = User::where('username', '=', trim($parts[0]))
|
||||
->whereNull('deleted_at')
|
||||
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')
|
||||
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')
|
||||
->get();
|
||||
|
||||
|
||||
|
@ -105,10 +106,26 @@ class MergeUsersByUsername extends Command
|
|||
$managedLocation->save();
|
||||
}
|
||||
|
||||
foreach ($bad_user->uploads as $upload) {
|
||||
$this->info('Updating upload log record '.$upload->id.' to user '.$user->id);
|
||||
$upload->item_id = $user->id;
|
||||
$upload->save();
|
||||
}
|
||||
|
||||
foreach ($bad_user->acceptances as $acceptance) {
|
||||
$this->info('Updating acceptance log record '.$acceptance->id.' to user '.$user->id);
|
||||
$acceptance->item_id = $user->id;
|
||||
$acceptance->save();
|
||||
}
|
||||
|
||||
// Mark the user as deleted
|
||||
$this->info('Marking the user as deleted');
|
||||
$bad_user->deleted_at = Carbon::now()->timestamp;
|
||||
$bad_user->save();
|
||||
|
||||
event(new UserMerged($bad_user, $user, null));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class UserMerged
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $from_user, User $to_user, User $admin)
|
||||
public function __construct(User $from_user, User $to_user, ?User $admin)
|
||||
{
|
||||
$this->merged_from = $from_user;
|
||||
$this->merged_to = $to_user;
|
||||
|
|
|
@ -247,10 +247,6 @@ class UsersController extends Controller
|
|||
'jobtitle',
|
||||
'username',
|
||||
'employee_num',
|
||||
'assets',
|
||||
'accessories',
|
||||
'consumables',
|
||||
'licenses',
|
||||
'groups',
|
||||
'activated',
|
||||
'created_at',
|
||||
|
|
|
@ -906,6 +906,25 @@ class AssetsController extends Controller
|
|||
$asset->location_id = $request->input('location_id');
|
||||
}
|
||||
|
||||
if (($asset->model->fieldset)) {
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
$asset->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
||||
} else {
|
||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
|
||||
|
|
|
@ -42,7 +42,7 @@ class BulkUsersController extends Controller
|
|||
// Get the list of affected users
|
||||
$user_raw_array = request('ids');
|
||||
$users = User::whereIn('id', $user_raw_array)
|
||||
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
||||
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')->get();
|
||||
|
||||
// bulk edit, display the bulk edit form
|
||||
if ($request->input('bulk_actions') == 'edit') {
|
||||
|
@ -317,7 +317,7 @@ class BulkUsersController extends Controller
|
|||
|
||||
// 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();
|
||||
$users_to_merge = User::whereIn('id', $user_ids_to_merge)->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')->get();
|
||||
$admin = User::find(Auth::user()->id);
|
||||
|
||||
// Walk users
|
||||
|
@ -344,10 +344,20 @@ class BulkUsersController extends Controller
|
|||
}
|
||||
|
||||
foreach ($user_to_merge->userlog as $log) {
|
||||
$log->target_id = $user_to_merge->id;
|
||||
$log->target_id = $merge_into_user->id;
|
||||
$log->save();
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->uploads as $upload) {
|
||||
$upload->item_id = $merge_into_user->id;
|
||||
$upload->save();
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->acceptances as $acceptance) {
|
||||
$acceptance->item_id = $merge_into_user->id;
|
||||
$acceptance->save();
|
||||
}
|
||||
|
||||
User::where('manager_id', '=', $user_to_merge->id)->update(['manager_id' => $merge_into_user->id]);
|
||||
|
||||
foreach ($user_to_merge->managedLocations as $managedLocation) {
|
||||
|
@ -356,7 +366,6 @@ class BulkUsersController extends Controller
|
|||
}
|
||||
|
||||
$user_to_merge->delete();
|
||||
//$user_to_merge->save();
|
||||
|
||||
event(new UserMerged($user_to_merge, $merge_into_user, $admin));
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ class LogListener
|
|||
$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->user_id = $event->admin->id ?? null;
|
||||
$logaction->save();
|
||||
|
||||
// Add a record to the users being merged TO
|
||||
|
@ -122,7 +122,7 @@ class LogListener
|
|||
$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->user_id = $event->admin->id ?? null;
|
||||
$logaction->save();
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,6 @@ class PersonalAccessTokens extends Component
|
|||
{
|
||||
//this needs safety (though the scope of auth::user might kind of do it...)
|
||||
//seems like it does, test more
|
||||
Auth::user()->tokens()->find($tokenId)->delete();
|
||||
Auth::user()->tokens()->find($tokenId)?->delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -481,8 +481,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
/**
|
||||
* Establishes the user -> uploads relationship
|
||||
*
|
||||
* @todo I don't think we use this?
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
|
@ -496,6 +494,21 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
|||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the user -> acceptances relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v7.0.7]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function acceptances()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Actionlog::class, 'target_id')
|
||||
->where('target_type', self::class)
|
||||
->where('action_type', '=', 'accepted')
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the user -> requested assets relationship
|
||||
*
|
||||
|
|
|
@ -105,4 +105,64 @@ class ActionlogFactory extends Factory
|
|||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function filesUploaded()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'uploaded',
|
||||
'item_type' => User::class,
|
||||
'filename' => $this->faker->unixTime('now'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function acceptedSignature()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
$asset = Asset::factory()->create();
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'accepted',
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'target_type' => User::class,
|
||||
'accept_signature' => $this->faker->unixTime('now'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function acceptedEula()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
$asset = Asset::factory()->create();
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'accepted',
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'target_type' => User::class,
|
||||
'filename' => $this->faker->unixTime('now'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function userUpdated()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'update',
|
||||
'target_type' => User::class,
|
||||
'item_type' => User::class,
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Models\Company;
|
|||
use App\Models\Consumable;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use App\Models\Supplier;
|
||||
|
||||
|
@ -116,4 +117,16 @@ class ConsumableFactory extends Factory
|
|||
$consumable->category->update(['require_acceptance' => 1]);
|
||||
});
|
||||
}
|
||||
|
||||
public function checkedOutToUser(User $user = null)
|
||||
{
|
||||
return $this->afterCreating(function (Consumable $consumable) use ($user) {
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => User::factory()->create()->id,
|
||||
'assigned_to' => $user->id ?? User::factory()->create()->id,
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,6 +549,8 @@ return [
|
|||
'license_seats' => ':count License Seat|:count License Seats',
|
||||
'consumables' => ':count Consumable|:count Consumables',
|
||||
'components' => ':count Component|:count Components',
|
||||
]
|
||||
],
|
||||
'more_info' => 'More Info',
|
||||
'quickscan_bulk_help' => 'Checking this box will edit the asset record to reflect this new location. Leaving it unchecked will simply note the location in the audit log. Note that if this asset is checked out, it will not change the location of the person, asset or location it is checked out to.',
|
||||
|
||||
];
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<input type="checkbox" value="1" name="update_location" {{ old('update_location') == '1' ? ' checked="checked"' : '' }}> {{ trans('admin/hardware/form.asset_location') }}
|
||||
</label>
|
||||
|
||||
<a href="#" class="text-dark-gray" tabindex="0" role="button" data-toggle="popover" data-trigger="focus" title="<i class='far fa-life-ring'></i> More Info" data-html="true" data-content="Checking this box will edit the asset record to reflect this new location. Leaving it unchecked will simply note the location in the audit log.<br><br>Note that if this asset is checked out, it will not change the location of the person, asset or location it is checked out to."><i class="far fa-life-ring"></i></a>
|
||||
<a href="#" class="text-dark-gray" tabindex="0" role="button" data-toggle="popover" data-trigger="focus" title="<i class='far fa-life-ring'></i>"{{ trans('general.more_info') }} data-html="true" data-content="{{ trans('general.quickscan_bulk_help') }}"><i class="far fa-life-ring"></i></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -48,7 +48,8 @@
|
|||
</td>
|
||||
<!-- Delete Button -->
|
||||
<td style="vertical-align: middle;" class="text-right">
|
||||
<a class="action-link btn btn-danger btn-sm" wire:click="deleteToken('{{ $token->id }}')">
|
||||
<a class="action-link btn btn-danger btn-sm" wire:click="deleteToken('{{ $token->id }}')"
|
||||
wire:loading.attr="disabled">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<a style="padding-left: 10px; font-size: 18px;" class="text-dark-gray" data-trigger="focus" tabindex="0" role="button" data-toggle="popover" title="More Info" data-placement="right" data-html="true" data-content="{{ (isset($helpText)) ? $helpText : 'Help Info Missing' }}">
|
||||
<a style="padding-left: 10px; font-size: 18px;" class="text-dark-gray" data-trigger="focus" tabindex="0" role="button" data-toggle="popover" title="{{ trans('general.more_info') }}" data-placement="right" data-html="true" data-content="{{ (isset($helpText)) ? $helpText : 'Help Info Missing' }}">
|
||||
<i class="far fa-life-ring" aria-hidden="true"><span class="sr-only">{{ trans('general.moreinfo') }}</span></i>
|
||||
</a>
|
||||
|
|
|
@ -66,6 +66,10 @@
|
|||
<i class="fas fa-tint fa-fw" aria-hidden="true" style="font-size: 17px;"></i>
|
||||
<span class="sr-only">{{ trans('general.consumables') }}</span>
|
||||
</th>
|
||||
<th class="col-md-1 text-right">
|
||||
<i class="fas fa-paperclip fa-fw" aria-hidden="true" style="font-size: 17px;"></i>
|
||||
<span class="sr-only">{{ trans('general.files') }}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -93,16 +97,19 @@
|
|||
@endforeach
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ number_format($user->assets()->count()) }}
|
||||
{{ number_format($user->assets->count()) }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ number_format($user->accessories()->count()) }}
|
||||
{{ number_format($user->accessories->count()) }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ number_format($user->licenses()->count()) }}
|
||||
{{ number_format($user->licenses->count()) }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ number_format($user->consumables()->count()) }}
|
||||
{{ number_format($user->consumables->count()) }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ number_format($user->uploads->count()) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
|
135
tests/Feature/Console/MergeUsersTest.php
Normal file
135
tests/Feature/Console/MergeUsersTest.php
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Console;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use App\Models\Actionlog;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
||||
class MergeUsersTest extends TestCase
|
||||
{
|
||||
public function testAssetsAreTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create(['username' => 'user1']);
|
||||
$user_to_merge_into = User::factory()->create(['username' => 'user1@example.com']);
|
||||
|
||||
Asset::factory()->count(3)->assignedToUser($user1)->create();
|
||||
Asset::factory()->count(3)->assignedToUser($user_to_merge_into)->create();
|
||||
|
||||
$this->artisan('snipeit:merge-users')->assertExitCode(0);
|
||||
|
||||
$this->assertEquals(6, $user_to_merge_into->refresh()->assets->count());
|
||||
$this->assertEquals(0, $user1->refresh()->assets->count());
|
||||
|
||||
}
|
||||
|
||||
public function testLicensesAreTransferredOnUserMerge(): void
|
||||
{
|
||||
$user1 = User::factory()->create(['username' => 'user1']);
|
||||
$user_to_merge_into = User::factory()->create(['username' => 'user1@example.com']);
|
||||
|
||||
LicenseSeat::factory()->count(3)->create(['assigned_to' => $user1->id]);
|
||||
LicenseSeat::factory()->count(3)->create(['assigned_to' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->licenses->count());
|
||||
|
||||
$this->artisan('snipeit:merge-users')->assertExitCode(0);
|
||||
|
||||
$this->assertEquals(6, $user_to_merge_into->refresh()->licenses->count());
|
||||
$this->assertEquals(0, $user1->refresh()->licenses->count());
|
||||
|
||||
}
|
||||
|
||||
public function testAccessoriesTransferredOnUserMerge(): void
|
||||
{
|
||||
$user1 = User::factory()->create(['username' => 'user1']);
|
||||
$user_to_merge_into = User::factory()->create(['username' => 'user1@example.com']);
|
||||
|
||||
Accessory::factory()->count(3)->checkedOutToUser($user1)->create();
|
||||
Accessory::factory()->count(3)->checkedOutToUser($user_to_merge_into)->create();
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->accessories->count());
|
||||
|
||||
$this->artisan('snipeit:merge-users')->assertExitCode(0);
|
||||
|
||||
$this->assertEquals(6, $user_to_merge_into->refresh()->accessories->count());
|
||||
$this->assertEquals(0, $user1->refresh()->accessories->count());
|
||||
|
||||
}
|
||||
|
||||
public function testConsumablesTransferredOnUserMerge(): void
|
||||
{
|
||||
$user1 = User::factory()->create(['username' => 'user1']);
|
||||
$user_to_merge_into = User::factory()->create(['username' => 'user1@example.com']);
|
||||
|
||||
Consumable::factory()->count(3)->checkedOutToUser($user1)->create();
|
||||
Consumable::factory()->count(3)->checkedOutToUser($user_to_merge_into)->create();
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->consumables->count());
|
||||
|
||||
$this->artisan('snipeit:merge-users')->assertExitCode(0);
|
||||
|
||||
$this->assertEquals(6, $user_to_merge_into->refresh()->consumables->count());
|
||||
$this->assertEquals(0, $user1->refresh()->consumables->count());
|
||||
|
||||
}
|
||||
|
||||
public function testFilesAreTransferredOnUserMerge(): void
|
||||
{
|
||||
$user1 = User::factory()->create(['username' => 'user1']);
|
||||
$user_to_merge_into = User::factory()->create(['username' => 'user1@example.com']);
|
||||
|
||||
Actionlog::factory()->count(3)->filesUploaded()->create(['item_id' => $user1->id]);
|
||||
Actionlog::factory()->count(3)->filesUploaded()->create(['item_id' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->uploads->count());
|
||||
|
||||
$this->artisan('snipeit:merge-users')->assertExitCode(0);
|
||||
|
||||
$this->assertEquals(6, $user_to_merge_into->refresh()->uploads->count());
|
||||
$this->assertEquals(0, $user1->refresh()->uploads->count());
|
||||
|
||||
}
|
||||
|
||||
public function testAcceptancesAreTransferredOnUserMerge(): void
|
||||
{
|
||||
$user1 = User::factory()->create(['username' => 'user1']);
|
||||
$user_to_merge_into = User::factory()->create(['username' => 'user1@example.com']);
|
||||
|
||||
Actionlog::factory()->count(3)->acceptedSignature()->create(['target_id' => $user1->id]);
|
||||
Actionlog::factory()->count(3)->acceptedSignature()->create(['target_id' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->acceptances->count());
|
||||
|
||||
$this->artisan('snipeit:merge-users')->assertExitCode(0);
|
||||
|
||||
$this->assertEquals(6, $user_to_merge_into->refresh()->acceptances->count());
|
||||
$this->assertEquals(0, $user1->refresh()->acceptances->count());
|
||||
|
||||
}
|
||||
|
||||
public function testUserUpdateHistoryIsTransferredOnUserMerge(): void
|
||||
{
|
||||
$user1 = User::factory()->create(['username' => 'user1']);
|
||||
$user_to_merge_into = User::factory()->create(['username' => 'user1@example.com']);
|
||||
|
||||
Actionlog::factory()->count(3)->userUpdated()->create(['target_id' => $user1->id, 'item_id' => $user1->id]);
|
||||
Actionlog::factory()->count(3)->userUpdated()->create(['target_id' => $user_to_merge_into->id, 'item_id' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->userlog->count());
|
||||
|
||||
$this->artisan('snipeit:merge-users')->assertExitCode(0);
|
||||
|
||||
// This needs to be more than the otherwise expected because the merge action itself is logged for the two merging users
|
||||
$this->assertEquals(7, $user_to_merge_into->refresh()->userlog->count());
|
||||
$this->assertEquals(1, $user1->refresh()->userlog->count());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -144,4 +144,17 @@ class UserSearchTest extends TestCase
|
|||
'User index contains unexpected user from another company'
|
||||
);
|
||||
}
|
||||
|
||||
public function testUsersIndexWhenInvalidSortFieldIsPassed()
|
||||
{
|
||||
$this->markIncompleteIfSqlite('This test is not compatible with SQLite');
|
||||
|
||||
$this->actingAsForApi(User::factory()->viewUsers()->create())
|
||||
->getJson(route('api.users.index', [
|
||||
'sort' => 'assets',
|
||||
]))
|
||||
->assertOk()
|
||||
->assertStatus(200)
|
||||
->json();
|
||||
}
|
||||
}
|
||||
|
|
213
tests/Feature/Users/Ui/MergeUsersTest.php
Normal file
213
tests/Feature/Users/Ui/MergeUsersTest.php
Normal file
|
@ -0,0 +1,213 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Users\Ui;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use App\Models\Actionlog;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
||||
class MergeUsersTest extends TestCase
|
||||
{
|
||||
public function testAssetsAreTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
$user2 = User::factory()->create();
|
||||
$user_to_merge_into = User::factory()->create();
|
||||
|
||||
Asset::factory()->count(3)->assignedToUser($user1)->create();
|
||||
Asset::factory()->count(3)->assignedToUser($user2)->create();
|
||||
Asset::factory()->count(3)->assignedToUser($user_to_merge_into)->create();
|
||||
|
||||
$response = $this->actingAs(User::factory()->editUsers()->viewUsers()->create())
|
||||
->post(route('users.merge.save', $user1->id),
|
||||
[
|
||||
'ids_to_merge' => [$user1->id, $user2->id],
|
||||
'merge_into_id' => $user_to_merge_into->id
|
||||
])
|
||||
->assertStatus(302)
|
||||
->assertRedirect(route('users.index'));
|
||||
|
||||
$this->followRedirects($response)->assertSee('Success');
|
||||
$this->assertEquals(9, $user_to_merge_into->refresh()->assets->count());
|
||||
$this->assertEquals(0, $user1->refresh()->assets->count());
|
||||
$this->assertEquals(0, $user2->refresh()->assets->count());
|
||||
|
||||
}
|
||||
|
||||
public function testLicensesAreTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
$user2 = User::factory()->create();
|
||||
$user_to_merge_into = User::factory()->create();
|
||||
|
||||
LicenseSeat::factory()->count(3)->create(['assigned_to' => $user1->id]);
|
||||
LicenseSeat::factory()->count(3)->create(['assigned_to' => $user2->id]);
|
||||
LicenseSeat::factory()->count(3)->create(['assigned_to' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->licenses->count());
|
||||
|
||||
$response = $this->actingAs(User::factory()->editUsers()->viewUsers()->create())
|
||||
->post(route('users.merge.save', $user1->id),
|
||||
[
|
||||
'ids_to_merge' => [$user1->id, $user2->id],
|
||||
'merge_into_id' => $user_to_merge_into->id
|
||||
])
|
||||
->assertStatus(302)
|
||||
->assertRedirect(route('users.index'));
|
||||
|
||||
$this->followRedirects($response)->assertSee('Success');
|
||||
$this->assertEquals(9, $user_to_merge_into->refresh()->licenses->count());
|
||||
$this->assertEquals(0, $user1->refresh()->licenses->count());
|
||||
$this->assertEquals(0, $user2->refresh()->licenses->count());
|
||||
|
||||
}
|
||||
|
||||
public function testAccessoriesTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
$user2 = User::factory()->create();
|
||||
$user_to_merge_into = User::factory()->create();
|
||||
|
||||
Accessory::factory()->count(3)->checkedOutToUser($user1)->create();
|
||||
Accessory::factory()->count(3)->checkedOutToUser($user2)->create();
|
||||
Accessory::factory()->count(3)->checkedOutToUser($user_to_merge_into)->create();
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->accessories->count());
|
||||
|
||||
$response = $this->actingAs(User::factory()->editUsers()->viewUsers()->create())
|
||||
->post(route('users.merge.save', $user1->id),
|
||||
[
|
||||
'ids_to_merge' => [$user1->id, $user2->id],
|
||||
'merge_into_id' => $user_to_merge_into->id
|
||||
])
|
||||
->assertStatus(302)
|
||||
->assertRedirect(route('users.index'));
|
||||
|
||||
$this->followRedirects($response)->assertSee('Success');
|
||||
$this->assertEquals(9, $user_to_merge_into->refresh()->accessories->count());
|
||||
$this->assertEquals(0, $user1->refresh()->accessories->count());
|
||||
$this->assertEquals(0, $user2->refresh()->accessories->count());
|
||||
|
||||
}
|
||||
|
||||
public function testConsumablesTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
$user2 = User::factory()->create();
|
||||
$user_to_merge_into = User::factory()->create();
|
||||
|
||||
Consumable::factory()->count(3)->checkedOutToUser($user1)->create();
|
||||
Consumable::factory()->count(3)->checkedOutToUser($user2)->create();
|
||||
Consumable::factory()->count(3)->checkedOutToUser($user_to_merge_into)->create();
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->consumables->count());
|
||||
|
||||
$response = $this->actingAs(User::factory()->editUsers()->viewUsers()->create())
|
||||
->post(route('users.merge.save', $user1->id),
|
||||
[
|
||||
'ids_to_merge' => [$user1->id, $user2->id],
|
||||
'merge_into_id' => $user_to_merge_into->id
|
||||
])
|
||||
->assertStatus(302)
|
||||
->assertRedirect(route('users.index'));
|
||||
|
||||
$this->followRedirects($response)->assertSee('Success');
|
||||
$this->assertEquals(9, $user_to_merge_into->refresh()->consumables->count());
|
||||
$this->assertEquals(0, $user1->refresh()->consumables->count());
|
||||
$this->assertEquals(0, $user2->refresh()->consumables->count());
|
||||
|
||||
}
|
||||
|
||||
public function testFilesAreTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
$user2 = User::factory()->create();
|
||||
$user_to_merge_into = User::factory()->create();
|
||||
|
||||
Actionlog::factory()->count(3)->filesUploaded()->create(['item_id' => $user1->id]);
|
||||
Actionlog::factory()->count(3)->filesUploaded()->create(['item_id' => $user2->id]);
|
||||
Actionlog::factory()->count(3)->filesUploaded()->create(['item_id' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->uploads->count());
|
||||
|
||||
$response = $this->actingAs(User::factory()->editUsers()->viewUsers()->create())
|
||||
->post(route('users.merge.save', $user1->id),
|
||||
[
|
||||
'ids_to_merge' => [$user1->id, $user2->id],
|
||||
'merge_into_id' => $user_to_merge_into->id
|
||||
])
|
||||
->assertStatus(302)
|
||||
->assertRedirect(route('users.index'));
|
||||
|
||||
$this->followRedirects($response)->assertSee('Success');
|
||||
$this->assertEquals(9, $user_to_merge_into->refresh()->uploads->count());
|
||||
$this->assertEquals(0, $user1->refresh()->uploads->count());
|
||||
$this->assertEquals(0, $user2->refresh()->uploads->count());
|
||||
|
||||
}
|
||||
|
||||
public function testAcceptancesAreTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
$user2 = User::factory()->create();
|
||||
$user_to_merge_into = User::factory()->create();
|
||||
|
||||
Actionlog::factory()->count(3)->acceptedSignature()->create(['target_id' => $user1->id]);
|
||||
Actionlog::factory()->count(3)->acceptedSignature()->create(['target_id' => $user2->id]);
|
||||
Actionlog::factory()->count(3)->acceptedSignature()->create(['target_id' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->acceptances->count());
|
||||
|
||||
$response = $this->actingAs(User::factory()->editUsers()->viewUsers()->create())
|
||||
->post(route('users.merge.save', $user1->id),
|
||||
[
|
||||
'ids_to_merge' => [$user1->id, $user2->id],
|
||||
'merge_into_id' => $user_to_merge_into->id
|
||||
])
|
||||
->assertStatus(302)
|
||||
->assertRedirect(route('users.index'));
|
||||
|
||||
$this->followRedirects($response)->assertSee('Success');
|
||||
$this->assertEquals(9, $user_to_merge_into->refresh()->acceptances->count());
|
||||
$this->assertEquals(0, $user1->refresh()->acceptances->count());
|
||||
$this->assertEquals(0, $user2->refresh()->acceptances->count());
|
||||
|
||||
}
|
||||
|
||||
public function testUserUpdateHistoryIsTransferredOnUserMerge()
|
||||
{
|
||||
$user1 = User::factory()->create();
|
||||
$user2 = User::factory()->create();
|
||||
$user_to_merge_into = User::factory()->create();
|
||||
|
||||
Actionlog::factory()->count(3)->userUpdated()->create(['target_id' => $user1->id, 'item_id' => $user1->id]);
|
||||
Actionlog::factory()->count(3)->userUpdated()->create(['target_id' => $user2->id, 'item_id' => $user2->id]);
|
||||
Actionlog::factory()->count(3)->userUpdated()->create(['target_id' => $user_to_merge_into->id, 'item_id' => $user_to_merge_into->id]);
|
||||
|
||||
$this->assertEquals(3, $user_to_merge_into->refresh()->userlog->count());
|
||||
|
||||
$response = $this->actingAs(User::factory()->editUsers()->viewUsers()->create())
|
||||
->post(route('users.merge.save', $user1->id),
|
||||
[
|
||||
'ids_to_merge' => [$user1->id, $user2->id],
|
||||
'merge_into_id' => $user_to_merge_into->id
|
||||
])
|
||||
->assertStatus(302)
|
||||
->assertRedirect(route('users.index'));
|
||||
|
||||
$this->followRedirects($response)->assertSee('Success');
|
||||
|
||||
// This needs to be 2 more than the otherwise expected because the merge action itself is logged for the two merging users
|
||||
$this->assertEquals(11, $user_to_merge_into->refresh()->userlog->count());
|
||||
$this->assertEquals(2, $user1->refresh()->userlog->count());
|
||||
$this->assertEquals(2, $user2->refresh()->userlog->count());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -10,4 +10,11 @@ trait CanSkipTests
|
|||
$this->markTestIncomplete($message);
|
||||
}
|
||||
}
|
||||
|
||||
public function markIncompleteIfSqlite($message = 'Test skipped due to database driver being sqlite.')
|
||||
{
|
||||
if (config('database.default') === 'sqlite') {
|
||||
$this->markTestIncomplete($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue