2FAuth/tests/Api/v1/Controllers/GroupControllerTest.php

468 lines
14 KiB
PHP
Raw Normal View History

2021-11-14 01:52:46 +01:00
<?php
namespace Tests\Api\v1\Controllers;
2023-08-01 11:28:27 +02:00
use App\Api\v1\Controllers\GroupController;
use App\Api\v1\Resources\GroupResource;
use App\Listeners\DissociateTwofaccountFromGroup;
2023-08-01 11:28:27 +02:00
use App\Listeners\ResetUsersPreference;
2021-12-02 13:15:53 +01:00
use App\Models\Group;
use App\Models\TwoFAccount;
2022-11-22 15:15:52 +01:00
use App\Models\User;
2023-08-01 11:28:27 +02:00
use App\Policies\GroupPolicy;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
2022-11-22 15:15:52 +01:00
use Tests\FeatureTestCase;
2021-11-22 01:09:54 +01:00
2023-08-01 11:28:27 +02:00
#[CoversClass(GroupController::class)]
#[CoversClass(GroupResource::class)]
#[CoversClass(ResetUsersPreference::class)]
#[CoversClass(GroupPolicy::class)]
#[CoversClass(Group::class)]
#[CoversClass(DissociateTwofaccountFromGroup::class)]
2021-11-14 01:52:46 +01:00
class GroupControllerTest extends FeatureTestCase
{
/**
* @var \App\Models\User|\Illuminate\Contracts\Auth\Authenticatable
2022-11-22 15:15:52 +01:00
*/
2023-03-10 22:59:46 +01:00
protected $user;
protected $anotherUser;
/**
* @var App\Models\Group
*/
2023-03-10 22:59:46 +01:00
protected $userGroupA;
protected $userGroupB;
protected $anotherUserGroupA;
protected $anotherUserGroupB;
/**
* @var App\Models\TwoFAccount
*/
2023-03-10 22:59:46 +01:00
protected $twofaccountA;
protected $twofaccountB;
protected $twofaccountC;
protected $twofaccountD;
private const NEW_GROUP_NAME = 'MyNewGroup';
2021-11-14 01:52:46 +01:00
2022-12-13 12:07:29 +01:00
public function setUp() : void
2021-11-14 01:52:46 +01:00
{
parent::setUp();
2023-03-10 22:59:46 +01:00
$this->user = User::factory()->create();
$this->userGroupA = Group::factory()->for($this->user)->create();
$this->userGroupB = Group::factory()->for($this->user)->create();
$this->twofaccountA = TwoFAccount::factory()->for($this->user)->create([
'group_id' => $this->userGroupA->id,
]);
$this->twofaccountB = TwoFAccount::factory()->for($this->user)->create([
'group_id' => $this->userGroupA->id,
]);
2023-03-10 22:59:46 +01:00
$this->anotherUser = User::factory()->create();
$this->anotherUserGroupA = Group::factory()->for($this->anotherUser)->create();
$this->anotherUserGroupB = Group::factory()->for($this->anotherUser)->create();
$this->twofaccountC = TwoFAccount::factory()->for($this->anotherUser)->create([
'group_id' => $this->anotherUserGroupA->id,
]);
$this->twofaccountD = TwoFAccount::factory()->for($this->anotherUser)->create([
'group_id' => $this->anotherUserGroupB->id,
]);
2021-11-14 01:52:46 +01:00
}
#[Test]
public function test_index_returns_user_groups_only_with_pseudo_group()
2021-11-14 01:52:46 +01:00
{
$this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('GET', '/api/v1/groups')
->assertOk()
->assertExactJson([
'0' => [
'id' => 0,
'name' => 'All',
'twofaccounts_count' => 2,
],
'1' => [
'id' => $this->userGroupA->id,
'name' => $this->userGroupA->name,
'twofaccounts_count' => 2,
],
'2' => [
'id' => $this->userGroupB->id,
'name' => $this->userGroupB->name,
'twofaccounts_count' => 0,
2022-11-22 15:15:52 +01:00
],
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
public function test_orphan_groups_are_reassign_to_the_only_user()
{
config(['auth.defaults.guard' => 'reverse-proxy-guard']);
$this->anotherUser->delete();
$this->userGroupA->user_id = null;
$this->userGroupA->save();
$this->assertCount(1, User::all());
$this->assertNull($this->userGroupA->user_id);
$this->actingAs($this->user, 'reverse-proxy-guard')
->json('GET', '/api/v1/groups')
->assertOk();
$this->userGroupA->refresh();
$this->assertNotNull($this->userGroupA->user_id);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_store_returns_created_group_resource()
{
$this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('POST', '/api/v1/groups', [
'name' => self::NEW_GROUP_NAME,
2021-11-14 01:52:46 +01:00
])
->assertCreated()
2022-04-01 13:35:59 +02:00
->assertJsonFragment([
'name' => self::NEW_GROUP_NAME,
2021-11-14 01:52:46 +01:00
'twofaccounts_count' => 0,
]);
$this->assertDatabaseHas('groups', [
'name' => self::NEW_GROUP_NAME,
'user_id' => $this->user->id,
]);
2021-11-14 01:52:46 +01:00
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_store_invalid_data_returns_validation_error()
{
$this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('POST', '/api/v1/groups', [
'name' => null,
])
->assertStatus(422);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_show_returns_group_resource()
{
$group = Group::factory()->for($this->user)->create([
2021-11-14 01:52:46 +01:00
'name' => 'My group',
]);
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('GET', '/api/v1/groups/' . $group->id)
->assertOk()
2022-04-01 13:35:59 +02:00
->assertJsonFragment([
2022-11-22 15:15:52 +01:00
'name' => 'My group',
2021-11-14 01:52:46 +01:00
'twofaccounts_count' => 0,
]);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_show_missing_group_returns_not_found()
{
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('GET', '/api/v1/groups/1000')
->assertNotFound()
->assertJsonStructure([
2022-11-22 15:15:52 +01:00
'message',
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
public function test_show_group_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
->json('GET', '/api/v1/groups/' . $this->userGroupA->id)
->assertForbidden()
->assertJsonStructure([
'message',
]);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_update_returns_updated_group_resource()
{
$group = Group::factory()->for($this->user)->create();
2021-11-14 01:52:46 +01:00
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('PUT', '/api/v1/groups/' . $group->id, [
'name' => 'name updated',
])
2021-11-14 01:52:46 +01:00
->assertOk()
2022-04-01 13:35:59 +02:00
->assertJsonFragment([
2022-11-22 15:15:52 +01:00
'name' => 'name updated',
2021-11-14 01:52:46 +01:00
'twofaccounts_count' => 0,
]);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_update_missing_group_returns_not_found()
{
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('PUT', '/api/v1/groups/1000', [
'name' => 'testUpdate',
])
2021-11-14 01:52:46 +01:00
->assertNotFound()
->assertJsonStructure([
2022-11-22 15:15:52 +01:00
'message',
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_update_with_invalid_data_returns_validation_error()
{
$group = Group::factory()->for($this->user)->create();
2021-11-14 01:52:46 +01:00
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('PUT', '/api/v1/groups/' . $group->id, [
'name' => null,
])
2021-11-14 01:52:46 +01:00
->assertStatus(422);
}
#[Test]
public function test_update_group_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
->json('PUT', '/api/v1/groups/' . $this->userGroupA->id, [
'name' => 'name updated',
])
->assertForbidden()
->assertJsonStructure([
'message',
]);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_assign_accounts_returns_updated_group_resource()
{
$group = Group::factory()->for($this->user)->create();
$accounts = TwoFAccount::factory()->count(2)->for($this->user)->create();
2021-11-14 01:52:46 +01:00
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('POST', '/api/v1/groups/' . $group->id . '/assign', [
2022-04-01 13:35:59 +02:00
'ids' => [$accounts[0]->id, $accounts[1]->id],
])
2021-11-14 01:52:46 +01:00
->assertOk()
->assertExactJson([
2022-11-22 15:15:52 +01:00
'id' => $group->id,
'name' => $group->name,
2021-11-14 01:52:46 +01:00
'twofaccounts_count' => 2,
]);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_assign_accounts_to_missing_group_returns_not_found()
{
$accounts = TwoFAccount::factory()->count(2)->for($this->user)->create();
2021-11-14 01:52:46 +01:00
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('POST', '/api/v1/groups/1000/assign', [
2022-04-01 13:35:59 +02:00
'ids' => [$accounts[0]->id, $accounts[1]->id],
])
2021-11-14 01:52:46 +01:00
->assertNotFound()
->assertJsonStructure([
2022-11-22 15:15:52 +01:00
'message',
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
2021-11-14 01:52:46 +01:00
public function test_assign_invalid_accounts_returns_validation_error()
{
$group = Group::factory()->for($this->user)->create();
$accounts = TwoFAccount::factory()->count(2)->for($this->user)->create();
2021-11-14 01:52:46 +01:00
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('POST', '/api/v1/groups/' . $group->id . '/assign', [
'ids' => 1,
])
2021-11-14 01:52:46 +01:00
->assertStatus(422);
}
#[Test]
public function test_assign_to_group_of_another_user_is_forbidden()
2021-11-14 01:52:46 +01:00
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
->json('POST', '/api/v1/groups/' . $this->userGroupA->id . '/assign', [
'ids' => [$this->twofaccountC->id, $this->twofaccountD->id],
])
->assertForbidden()
->assertJsonStructure([
'message',
]);
}
2021-11-14 01:52:46 +01:00
#[Test]
public function test_assign_accounts_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
->json('POST', '/api/v1/groups/' . $this->userGroupA->id . '/assign', [
'ids' => [$this->twofaccountC->id, $this->twofaccountD->id],
])
->assertForbidden()
->assertJsonStructure([
'message',
2021-11-14 01:52:46 +01:00
]);
}
2021-11-14 01:52:46 +01:00
#[Test]
public function test_accounts_returns_twofaccounts_collection()
{
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
->json('GET', '/api/v1/groups/' . $this->userGroupA->id . '/twofaccounts')
2021-11-14 01:52:46 +01:00
->assertOk()
->assertJsonCount(2)
->assertJsonStructure([
'*' => [
'group_id',
'service',
'account',
'icon',
'otp_type',
'digits',
'algorithm',
'period',
2022-11-22 15:15:52 +01:00
'counter',
],
])
->assertJsonFragment([
'account' => $this->twofaccountA->account,
])
->assertJsonFragment([
'account' => $this->twofaccountB->account,
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
public function test_accounts_returns_twofaccounts_collection_with_secret()
2021-11-14 01:52:46 +01:00
{
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
->json('GET', '/api/v1/groups/' . $this->userGroupA->id . '/twofaccounts?withSecret=1')
2021-11-14 01:52:46 +01:00
->assertOk()
->assertJsonCount(2)
->assertJsonStructure([
'*' => [
'group_id',
'service',
'account',
'icon',
'secret',
'otp_type',
'digits',
'algorithm',
'period',
2022-11-22 15:15:52 +01:00
'counter',
],
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
public function test_accounts_of_missing_group_returns_not_found()
2021-11-14 01:52:46 +01:00
{
2022-03-31 08:38:35 +02:00
$response = $this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('GET', '/api/v1/groups/1000/twofaccounts')
->assertNotFound()
->assertJsonStructure([
2022-11-22 15:15:52 +01:00
'message',
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
public function test_accounts_of_another_user_group_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
->json('GET', '/api/v1/groups/' . $this->userGroupA->id . '/twofaccounts')
->assertForbidden()
->assertJsonStructure([
'message',
]);
}
2021-11-14 01:52:46 +01:00
/**
* test Group deletion via API
*/
#[Test]
2021-11-14 01:52:46 +01:00
public function test_destroy_group_returns_success()
{
$group = Group::factory()->for($this->user)->create();
2021-11-14 01:52:46 +01:00
$this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('DELETE', '/api/v1/groups/' . $group->id)
->assertNoContent();
}
/**
* test Group deletion via API
*/
#[Test]
2021-11-14 01:52:46 +01:00
public function test_destroy_missing_group_returns_not_found()
{
$this->actingAs($this->user, 'api-guard')
2021-11-14 01:52:46 +01:00
->json('DELETE', '/api/v1/groups/1000')
->assertNotFound()
->assertJsonStructure([
2022-11-22 15:15:52 +01:00
'message',
2021-11-14 01:52:46 +01:00
]);
}
#[Test]
public function test_destroy_group_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
2023-12-20 16:55:58 +01:00
->json('DELETE', '/api/v1/groups/' . $this->userGroupA->id)
->assertForbidden()
->assertJsonStructure([
'message',
]);
}
2023-03-18 17:33:43 +01:00
#[Test]
2023-03-18 17:33:43 +01:00
public function test_destroy_group_resets_user_preferences()
{
// Set the default group to a specific one
$this->user['preferences->defaultGroup'] = $this->userGroupA->id;
// Set the active group
$this->user['preferences->activeGroup'] = $this->userGroupA->id;
$this->user->save();
$this->assertEquals($this->userGroupA->id, $this->user->preferences['defaultGroup']);
$this->assertEquals($this->userGroupA->id, $this->user->preferences['activeGroup']);
$this->actingAs($this->user, 'api-guard')
->json('DELETE', '/api/v1/groups/' . $this->userGroupA->id);
$this->user->refresh();
$this->assertEquals(0, $this->user->preferences['defaultGroup']);
$this->assertEquals(0, $this->user->preferences['activeGroup']);
}
#[Test]
public function test_twofaccount_is_released_on_group_destroy()
{
$this->actingAs($this->user, 'api-guard')
->json('DELETE', '/api/v1/groups/' . $this->userGroupA->id)
->assertNoContent();
$this->twofaccountA->refresh();
$this->twofaccountB->refresh();
$this->assertNull($this->twofaccountA->group_id);
$this->assertNull($this->twofaccountB->group_id);
}
2021-11-14 01:52:46 +01:00
}