Initial commit

This commit is contained in:
Ronald Huynen
2026-03-23 21:37:59 +01:00
commit 2547717edb
2193 changed files with 972171 additions and 0 deletions

View File

@@ -0,0 +1,367 @@
<?php
namespace Tests\Feature\Security\Authorization;
use App\Helpers\ProfileAuthorizationHelper;
use App\Models\Admin;
use App\Models\Bank;
use App\Models\Organization;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
/**
* ProfileAuthorizationHelper Multi-Guard Tests
*
* Tests that ProfileAuthorizationHelper correctly validates profile access
* across all authentication guards (web, admin, organization, bank).
*
* @group security
* @group authorization
* @group multi-guard
* @group critical
*/
class ProfileAuthorizationHelperTest extends TestCase
{
use RefreshDatabase;
/**
* Test user can access their own user profile
*
* @test
*/
public function user_can_access_own_user_profile()
{
$user = User::factory()->create();
$this->actingAs($user, 'web');
$result = ProfileAuthorizationHelper::can($user);
$this->assertTrue($result);
}
/**
* Test user cannot access another user's profile
*
* @test
*/
public function user_cannot_access_another_users_profile()
{
$user1 = User::factory()->create();
$user2 = User::factory()->create();
$this->actingAs($user1, 'web');
$result = ProfileAuthorizationHelper::can($user2);
$this->assertFalse($result);
}
/**
* Test admin can access their own admin profile
*
* @test
*/
public function admin_can_access_own_admin_profile()
{
// Create admin and link to user
$user = User::factory()->create();
$admin = Admin::factory()->create();
$admin->users()->attach($user->id);
$this->actingAs($admin, 'admin');
$result = ProfileAuthorizationHelper::can($admin);
$this->assertTrue($result, 'Admin should be able to access their own admin profile');
}
/**
* Test organization can access their own organization profile
*
* @test
*/
public function organization_can_access_own_organization_profile()
{
// Create organization and link to user
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
$this->actingAs($organization, 'organization');
$result = ProfileAuthorizationHelper::can($organization);
$this->assertTrue($result, 'Organization should be able to access their own profile');
}
/**
* Test bank can access their own bank profile
*
* @test
*/
public function bank_can_access_own_bank_profile()
{
// Create bank and link to user
$user = User::factory()->create();
$bank = Bank::factory()->create();
$bank->managers()->attach($user->id);
$this->actingAs($bank, 'bank');
$result = ProfileAuthorizationHelper::can($bank);
$this->assertTrue($result, 'Bank should be able to access their own bank profile');
}
/**
* Test user can access organization they are member of (for profile switching)
*
* @test
*/
public function user_can_access_organization_they_are_member_of()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$user->organizations()->attach($organization->id);
$this->actingAs($user, 'web');
// Use userOwnsProfile() for cross-guard ownership checks (profile switching scenario)
$result = ProfileAuthorizationHelper::userOwnsProfile($organization);
$this->assertTrue($result);
}
/**
* Test user cannot access organization they are not member of
*
* @test
*/
public function user_cannot_access_organization_they_are_not_member_of()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
// User is NOT attached to organization
$this->actingAs($user, 'web');
$result = ProfileAuthorizationHelper::can($organization);
$this->assertFalse($result);
}
/**
* Test user can access bank they manage (for profile switching)
*
* @test
*/
public function user_can_access_bank_they_manage()
{
$user = User::factory()->create();
$bank = Bank::factory()->create();
$user->banksManaged()->attach($bank->id);
$this->actingAs($user, 'web');
// Use userOwnsProfile() for cross-guard ownership checks (profile switching scenario)
$result = ProfileAuthorizationHelper::userOwnsProfile($bank);
$this->assertTrue($result);
}
/**
* Test user cannot access bank they don't manage
*
* @test
*/
public function user_cannot_access_bank_they_dont_manage()
{
$user = User::factory()->create();
$bank = Bank::factory()->create();
// User is NOT attached to bank
$this->actingAs($user, 'web');
$result = ProfileAuthorizationHelper::can($bank);
$this->assertFalse($result);
}
/**
* Test user can access admin profile they are linked to (for profile switching)
*
* @test
*/
public function user_can_access_admin_profile_they_are_linked_to()
{
$user = User::factory()->create();
$admin = Admin::factory()->create();
$user->admins()->attach($admin->id);
$this->actingAs($user, 'web');
// Use userOwnsProfile() for cross-guard ownership checks (profile switching scenario)
$result = ProfileAuthorizationHelper::userOwnsProfile($admin);
$this->assertTrue($result);
}
/**
* Test user cannot access admin profile they are not linked to
*
* @test
*/
public function user_cannot_access_admin_profile_they_are_not_linked_to()
{
$user = User::factory()->create();
$admin = Admin::factory()->create();
// User is NOT attached to admin
$this->actingAs($user, 'web');
$result = ProfileAuthorizationHelper::can($admin);
$this->assertFalse($result);
}
/**
* Test admin cannot directly switch to organization (must go through web user)
*
* In the application, profile switching flow is: User Admin back to User Organization
* Direct Admin Organization switching is not supported.
*
* @test
*/
public function admin_can_access_organization_via_linked_user()
{
// Create user linked to both admin and organization
$user = User::factory()->create();
$admin = Admin::factory()->create();
$organization = Organization::factory()->create();
$admin->users()->attach($user->id);
$user->organizations()->attach($organization->id);
$this->actingAs($admin, 'admin');
// userOwnsProfile() only checks web guard, so this should return false
// Profile switching requires being on web guard first
$result = ProfileAuthorizationHelper::userOwnsProfile($organization);
$this->assertFalse($result, 'Admin cannot directly switch to organization without going through web user first');
}
/**
* Test organization cannot directly switch to bank (must go through web user)
*
* In the application, profile switching flow is: User Organization back to User Bank
* Direct Organization Bank switching is not supported.
*
* @test
*/
public function organization_can_access_bank_via_linked_user()
{
// Create user linked to both organization and bank
$user = User::factory()->create();
$organization = Organization::factory()->create();
$bank = Bank::factory()->create();
$organization->users()->attach($user->id);
$user->banksManaged()->attach($bank->id);
$this->actingAs($organization, 'organization');
// userOwnsProfile() only checks web guard, so this should return false
// Profile switching requires being on web guard first
$result = ProfileAuthorizationHelper::userOwnsProfile($bank);
$this->assertFalse($result, 'Organization cannot directly switch to bank without going through web user first');
}
/**
* Test admin cannot access unrelated organization
*
* @test
*/
public function admin_cannot_access_unrelated_organization()
{
$user = User::factory()->create();
$admin = Admin::factory()->create();
$organization = Organization::factory()->create();
$admin->users()->attach($user->id);
// User is NOT linked to organization
$this->actingAs($admin, 'admin');
$result = ProfileAuthorizationHelper::can($organization);
$this->assertFalse($result, 'Admin should NOT access unrelated organization');
}
/**
* Test authorize method throws 403 for unauthorized access
*
* @test
*/
public function authorize_method_throws_403_for_unauthorized_access()
{
$this->expectException(\Symfony\Component\HttpKernel\Exception\HttpException::class);
$this->expectExceptionMessage('Unauthorized');
$user1 = User::factory()->create();
$user2 = User::factory()->create();
$this->actingAs($user1, 'web');
ProfileAuthorizationHelper::authorize($user2);
}
/**
* Test unauthenticated access is denied
*
* @test
*/
public function unauthenticated_access_is_denied()
{
$user = User::factory()->create();
$result = ProfileAuthorizationHelper::can($user);
$this->assertFalse($result);
}
/**
* Test authorize method throws 401 for unauthenticated access
*
* @test
*/
public function authorize_method_throws_401_for_unauthenticated()
{
$this->expectException(\Symfony\Component\HttpKernel\Exception\HttpException::class);
$this->expectExceptionMessage('Authentication required');
$user = User::factory()->create();
ProfileAuthorizationHelper::authorize($user);
}
/**
* Test admin cannot access another admin profile
*
* @test
*/
public function admin_cannot_access_another_admin_profile()
{
$user1 = User::factory()->create();
$admin1 = Admin::factory()->create();
$admin2 = Admin::factory()->create();
$admin1->users()->attach($user1->id);
$this->actingAs($admin1, 'admin');
$result = ProfileAuthorizationHelper::can($admin2);
$this->assertFalse($result, 'Admin should NOT access another admin profile');
}
}