2023-08-30 11:13:38 -07:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Tests\Feature\Api\Users;
|
|
|
|
|
2024-04-17 02:47:48 -07:00
|
|
|
use App\Models\Company;
|
2024-04-17 15:23:26 -07:00
|
|
|
use App\Models\Group;
|
2023-08-30 11:13:38 -07:00
|
|
|
use App\Models\User;
|
|
|
|
use Tests\TestCase;
|
|
|
|
|
|
|
|
class UpdateUserApiTest extends TestCase
|
|
|
|
{
|
|
|
|
public function testApiUsersCanBeActivatedWithNumber()
|
|
|
|
{
|
|
|
|
$admin = User::factory()->superuser()->create();
|
|
|
|
$user = User::factory()->create(['activated' => 0]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($admin)
|
|
|
|
->patch(route('api.users.update', $user), [
|
|
|
|
'activated' => 1,
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->assertEquals(1, $user->refresh()->activated);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testApiUsersCanBeActivatedWithBooleanTrue()
|
|
|
|
{
|
|
|
|
$admin = User::factory()->superuser()->create();
|
|
|
|
$user = User::factory()->create(['activated' => false]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($admin)
|
|
|
|
->patch(route('api.users.update', $user), [
|
|
|
|
'activated' => true,
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->assertEquals(1, $user->refresh()->activated);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testApiUsersCanBeDeactivatedWithNumber()
|
|
|
|
{
|
|
|
|
$admin = User::factory()->superuser()->create();
|
|
|
|
$user = User::factory()->create(['activated' => true]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($admin)
|
|
|
|
->patch(route('api.users.update', $user), [
|
|
|
|
'activated' => 0,
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->assertEquals(0, $user->refresh()->activated);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testApiUsersCanBeDeactivatedWithBooleanFalse()
|
|
|
|
{
|
|
|
|
$admin = User::factory()->superuser()->create();
|
|
|
|
$user = User::factory()->create(['activated' => true]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($admin)
|
|
|
|
->patch(route('api.users.update', $user), [
|
|
|
|
'activated' => false,
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->assertEquals(0, $user->refresh()->activated);
|
|
|
|
}
|
2024-04-17 02:47:48 -07:00
|
|
|
|
|
|
|
public function testUsersScopedToCompanyDuringUpdateWhenMultipleFullCompanySupportEnabled()
|
|
|
|
{
|
|
|
|
$this->settings->enableMultipleFullCompanySupport();
|
|
|
|
|
|
|
|
$companyA = Company::factory()->create(['name'=>'Company A']);
|
|
|
|
$companyB = Company::factory()->create(['name'=>'Company B']);
|
|
|
|
|
|
|
|
$adminA = User::factory(['company_id' => $companyA->id])->admin()->create();
|
|
|
|
$adminB = User::factory(['company_id' => $companyB->id])->admin()->create();
|
|
|
|
$adminNoCompany = User::factory(['company_id' => null])->admin()->create();
|
|
|
|
|
2024-04-17 12:29:01 -07:00
|
|
|
// Create users that belongs to company A and B and one that is unscoped
|
2024-04-17 12:29:51 -07:00
|
|
|
$scoped_user_in_companyA = User::factory()->create(['company_id' => $companyA->id]);
|
|
|
|
$scoped_user_in_companyB = User::factory()->create(['company_id' => $companyB->id]);
|
|
|
|
$scoped_user_in_no_company = User::factory()->create(['company_id' => null]);
|
2024-04-17 02:47:48 -07:00
|
|
|
|
|
|
|
// Admin for Company A should allow updating user from Company A
|
|
|
|
$this->actingAsForApi($adminA)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_companyA))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(200);
|
|
|
|
|
|
|
|
// Admin for Company A should get denied updating user from Company B
|
|
|
|
$this->actingAsForApi($adminA)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_companyB))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(403);
|
|
|
|
|
|
|
|
// Admin for Company A should get denied updating user without a company
|
|
|
|
$this->actingAsForApi($adminA)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_no_company))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(403);
|
|
|
|
|
|
|
|
// Admin for Company B should allow updating user from Company B
|
|
|
|
$this->actingAsForApi($adminB)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_companyB))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(200);
|
|
|
|
|
|
|
|
// Admin for Company B should get denied updating user from Company A
|
|
|
|
$this->actingAsForApi($adminB)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_companyA))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(403);
|
|
|
|
|
|
|
|
// Admin for Company B should get denied updating user without a company
|
|
|
|
$this->actingAsForApi($adminB)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_no_company))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(403);
|
|
|
|
|
|
|
|
// Admin without a company should allow updating user without a company
|
|
|
|
$this->actingAsForApi($adminNoCompany)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_no_company))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(200);
|
|
|
|
|
|
|
|
// Admin without a company should get denied updating user from Company A
|
|
|
|
$this->actingAsForApi($adminNoCompany)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_companyA))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(403);
|
|
|
|
|
|
|
|
// Admin without a company should get denied updating user from Company B
|
|
|
|
$this->actingAsForApi($adminNoCompany)
|
2024-04-17 12:29:01 -07:00
|
|
|
->patchJson(route('api.users.update', $scoped_user_in_companyB))
|
2024-04-17 02:47:48 -07:00
|
|
|
->assertStatus(403);
|
2024-04-17 15:23:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testUserGroupsAreOnlyUpdatedIfAuthenticatedUserIsSuperUser()
|
|
|
|
{
|
|
|
|
$groupToJoin = Group::factory()->create();
|
|
|
|
|
2024-05-21 01:56:57 -07:00
|
|
|
$userWhoCanEditUsers = User::factory()->editUsers()->create();
|
2024-04-17 15:23:26 -07:00
|
|
|
$superUser = User::factory()->superuser()->create();
|
|
|
|
|
2024-05-22 03:00:31 -07:00
|
|
|
$userToUpdateByUserWhoCanEditUsers = User::factory()->create();
|
|
|
|
$userToUpdateByToUserBySuperuser = User::factory()->create();
|
2024-04-17 15:23:26 -07:00
|
|
|
|
2024-05-21 01:56:57 -07:00
|
|
|
$this->actingAsForApi($userWhoCanEditUsers)
|
2024-05-22 03:00:47 -07:00
|
|
|
->patchJson(route('api.users.update', $userToUpdateByUserWhoCanEditUsers), [
|
2024-04-17 15:23:26 -07:00
|
|
|
'groups' => [$groupToJoin->id],
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($superUser)
|
2024-05-21 01:56:57 -07:00
|
|
|
->patchJson(route('api.users.update', $userToUpdateByToUpdateuserBySuperuser), [
|
2024-04-17 15:23:26 -07:00
|
|
|
'groups' => [$groupToJoin->id],
|
|
|
|
]);
|
|
|
|
|
2024-05-22 03:00:52 -07:00
|
|
|
$this->assertFalse($userToUpdateByUserWhoCanEditUsers->refresh()->groups->contains($groupToJoin),
|
2024-04-17 15:23:26 -07:00
|
|
|
'Non-super-user was able to modify user group'
|
|
|
|
);
|
2024-05-21 01:56:57 -07:00
|
|
|
|
|
|
|
$this->assertTrue($userToUpdateByToUpdateuserBySuperuser->refresh()->groups->contains($groupToJoin));
|
2024-04-17 15:23:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testUserGroupsCanBeClearedBySuperUser()
|
|
|
|
{
|
|
|
|
$normalUser = User::factory()->editUsers()->create();
|
|
|
|
$superUser = User::factory()->superuser()->create();
|
|
|
|
|
|
|
|
$oneUserToUpdate = User::factory()->create();
|
|
|
|
$anotherUserToUpdate = User::factory()->create();
|
|
|
|
|
|
|
|
$joinedGroup = Group::factory()->create();
|
|
|
|
$oneUserToUpdate->groups()->sync([$joinedGroup->id]);
|
|
|
|
$anotherUserToUpdate->groups()->sync([$joinedGroup->id]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($normalUser)
|
|
|
|
->patchJson(route('api.users.update', $oneUserToUpdate), [
|
|
|
|
'groups' => null,
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($superUser)
|
|
|
|
->patchJson(route('api.users.update', $anotherUserToUpdate), [
|
|
|
|
'groups' => null,
|
|
|
|
]);
|
2024-04-17 02:47:48 -07:00
|
|
|
|
2024-04-17 15:23:26 -07:00
|
|
|
$this->assertTrue($oneUserToUpdate->refresh()->groups->contains($joinedGroup));
|
|
|
|
$this->assertFalse($anotherUserToUpdate->refresh()->groups->contains($joinedGroup));
|
2024-04-17 02:47:48 -07:00
|
|
|
}
|
2024-05-21 01:56:57 -07:00
|
|
|
|
|
|
|
public function testNonSuperuserCannotUpdateOwnGroups()
|
|
|
|
{
|
|
|
|
$groupToJoin = Group::factory()->create();
|
|
|
|
|
|
|
|
$user = User::factory()->editUsers()->create();
|
|
|
|
|
|
|
|
$this->actingAsForApi($user)
|
|
|
|
->patchJson(route('api.users.update', $user), [
|
|
|
|
'groups' => [$groupToJoin->id],
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($user->refresh()->groups->contains($groupToJoin),
|
|
|
|
'Non-super-user was able to modify user group'
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testNonSuperuserCannotUpdateGroups()
|
|
|
|
{
|
|
|
|
$user = User::factory()->editUsers()->create();
|
|
|
|
$group = Group::factory()->create();
|
|
|
|
$user->groups()->sync([$group->id]);
|
|
|
|
$newGroupToJoin = Group::factory()->create();
|
|
|
|
|
|
|
|
$this->actingAsForApi($user)
|
|
|
|
->patchJson(route('api.users.update', $user), [
|
|
|
|
'groups' => [$newGroupToJoin->id],
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($user->refresh()->groups->contains($newGroupToJoin),
|
|
|
|
'Non-super-user was able to modify user group membership'
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->assertTrue($user->refresh()->groups->contains($group));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testUsersGroupsAreNotClearedIfNoGroupPassedBySuperUser()
|
|
|
|
{
|
|
|
|
$user = User::factory()->create();
|
|
|
|
$superUser = User::factory()->superuser()->create();
|
|
|
|
|
|
|
|
$group = Group::factory()->create();
|
|
|
|
$user->groups()->sync([$group->id]);
|
|
|
|
|
|
|
|
$this->actingAsForApi($superUser)
|
|
|
|
->patchJson(route('api.users.update', $user), []);
|
|
|
|
|
|
|
|
$this->assertTrue($user->refresh()->groups->contains($group));
|
|
|
|
}
|
|
|
|
|
2023-08-30 11:13:38 -07:00
|
|
|
}
|