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,421 @@
<?php
namespace Tests\Feature\Security\Authorization;
use App\Models\Admin;
use App\Models\Bank;
use App\Models\Organization;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Namu\WireChat\Models\Conversation;
use Tests\TestCase;
/**
* WireChat Multi-Auth Tests
*
* Tests that WireChat components work correctly with multi-guard authentication
* for User, Organization, Bank, and Admin profiles.
*
* @group security
* @group authorization
* @group multi-guard
* @group wirechat
*/
class WireChatMultiAuthTest extends TestCase
{
use RefreshDatabase;
/**
* Test user can access conversation they belong to
*
* @test
*/
public function user_can_access_conversation_they_belong_to()
{
$user = User::factory()->create();
$recipient = User::factory()->create();
$this->actingAs($user, 'web');
// Create conversation using sendMessageTo (same logic as Pay.php line 417)
$message = $user->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(200);
}
/**
* Test user cannot access conversation they don't belong to
*
* @test
*/
public function user_cannot_access_conversation_they_dont_belong_to()
{
$user = User::factory()->create();
$otherUser = User::factory()->create();
$anotherUser = User::factory()->create();
$this->actingAs($user, 'web');
// Set active profile in session (required by getActiveProfile())
session([
'activeProfileType' => get_class($user),
'activeProfileId' => $user->id,
'active_guard' => 'web',
]);
// Create conversation between otherUser and anotherUser (not involving $user)
$message = $otherUser->sendMessageTo($anotherUser, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(403);
}
/**
* Test organization can access conversation they belong to
*
* @test
*/
public function organization_can_access_conversation_they_belong_to()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
$recipient = User::factory()->create();
$this->actingAs($organization, 'organization');
// Create conversation with organization as sender
$message = $organization->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(200);
}
/**
* Test admin can access conversation they belong to
*
* @test
*/
public function admin_can_access_conversation_they_belong_to()
{
$user = User::factory()->create();
$admin = Admin::factory()->create();
$admin->users()->attach($user->id);
$recipient = User::factory()->create();
$this->actingAs($admin, 'admin');
// Create conversation with admin as sender
$message = $admin->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(200);
}
/**
* Test bank can access conversation they belong to
*
* @test
*/
public function bank_can_access_conversation_they_belong_to()
{
$user = User::factory()->create();
$bank = Bank::factory()->create();
$bank->managers()->attach($user->id);
$recipient = User::factory()->create();
$this->actingAs($bank, 'bank');
// Create conversation with bank as sender
$message = $bank->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(200);
}
/**
* Test organization cannot access conversation they don't belong to
*
* @test
*/
public function organization_cannot_access_conversation_they_dont_belong_to()
{
$user = User::factory()->create();
$org1 = Organization::factory()->create();
$org2 = Organization::factory()->create();
$recipient = User::factory()->create();
$org1->users()->attach($user->id);
$org2->users()->attach($recipient->id);
$this->actingAs($org1, 'organization');
// Set active profile in session (required by getActiveProfile())
session([
'activeProfileType' => get_class($org1),
'activeProfileId' => $org1->id,
'active_guard' => 'organization',
]);
// Create conversation with org2 (not org1)
$message = $org2->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(403);
}
/**
* Test unauthenticated user cannot access conversations
*
* @test
*/
public function unauthenticated_user_cannot_access_conversations()
{
$user1 = User::factory()->create();
$user2 = User::factory()->create();
// Create conversation between two users
$message = $user1->sendMessageTo($user2, 'Test message');
$conversation = $message->conversation;
// No authentication - accessing as guest
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(403);
}
/**
* Test multi-participant conversation access (User and Organization)
*
* @test
*/
public function multi_participant_conversation_allows_both_participants()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
// Create conversation between user and organization
$message = $user->sendMessageTo($organization, 'Test message');
$conversation = $message->conversation;
// Test 1: User can access
$this->actingAs($user, 'web');
$response1 = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response1->assertStatus(200);
// Test 2: Organization can access
$this->actingAs($organization, 'organization');
$response2 = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response2->assertStatus(200);
}
/**
* Test disappearing messages can be enabled by organization
*
* @test
*/
public function organization_can_enable_disappearing_messages()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
$recipient = User::factory()->create();
$this->actingAs($organization, 'organization');
// Create conversation with organization as sender
$message = $organization->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
// Check that component loaded successfully
$response->assertStatus(200);
$response->assertSet('conversationId', $conversation->id);
$response->assertSet('platformEnabled', true);
}
/**
* Test admin can access disappearing message settings
*
* @test
*/
public function admin_can_access_disappearing_message_settings()
{
$user = User::factory()->create();
$admin = Admin::factory()->create();
$admin->users()->attach($user->id);
$recipient = User::factory()->create();
$this->actingAs($admin, 'admin');
// Create conversation with admin as sender
$message = $admin->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(200);
$response->assertViewHas('conversation');
}
/**
* Test bank can access disappearing message settings
*
* @test
*/
public function bank_can_access_disappearing_message_settings()
{
$user = User::factory()->create();
$bank = Bank::factory()->create();
$bank->managers()->attach($user->id);
$recipient = User::factory()->create();
$this->actingAs($bank, 'bank');
// Create conversation with bank as sender
$message = $bank->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
$response = Livewire::test(
\App\Http\Livewire\WireChat\DisappearingMessagesSettings::class,
['conversationId' => $conversation->id]
);
$response->assertStatus(200);
$response->assertSet('conversation', function ($conversation) {
return $conversation instanceof Conversation;
});
}
/**
* Test conversation access via route middleware (belongsToConversation)
*
* @test
*/
public function route_middleware_blocks_unauthorized_conversation_access()
{
$user = User::factory()->create();
$otherUser = User::factory()->create();
$anotherUser = User::factory()->create();
$this->actingAs($user, 'web');
// Set active profile in session (required by getActiveProfile())
session([
'activeProfileType' => get_class($user),
'activeProfileId' => $user->id,
'active_guard' => 'web',
]);
// Create conversation between otherUser and anotherUser (not involving $user)
$message = $otherUser->sendMessageTo($anotherUser, 'Test message');
$conversation = $message->conversation;
// Try to access via route (should be blocked)
$response = $this->get(route('chat', ['conversation' => $conversation->id]));
// Middleware may return 403 or redirect (302) when unauthorized
// Both are acceptable - what matters is user cannot access the conversation
$this->assertTrue(
in_array($response->status(), [302, 403]),
"Expected 302 redirect or 403 forbidden, but got {$response->status()}"
);
// If redirected, should not be to the chat page
if ($response->status() === 302) {
$this->assertNotEquals(
route('chat', ['conversation' => $conversation->id]),
$response->headers->get('Location'),
'User should not be redirected to the unauthorized conversation'
);
}
}
/**
* Test route middleware allows authorized conversation access
*
* @test
*/
public function route_middleware_allows_authorized_conversation_access()
{
$user = User::factory()->create();
$recipient = User::factory()->create();
$this->actingAs($user, 'web');
// Set active profile in session (required by getActiveProfile())
session([
'activeProfileType' => get_class($user),
'activeProfileId' => $user->id,
'active_guard' => 'web',
]);
// Create conversation with current user as sender
$message = $user->sendMessageTo($recipient, 'Test message');
$conversation = $message->conversation;
// Access via route (should be allowed by middleware)
$response = $this->get(route('chat', ['conversation' => $conversation->id]));
// Should either return 200 (success) or 302 redirect to valid location
// The Livewire component tests already verify authorization at component level
// Route level we just need to ensure it's not blocked entirely
$this->assertTrue(
in_array($response->status(), [200, 302]),
"Expected 200 success or 302 redirect, but got {$response->status()}"
);
// If successful (200), verify we're not getting an error page
if ($response->status() === 200) {
$response->assertDontSee('403');
$response->assertDontSee('Forbidden');
}
}
}