Initial commit
This commit is contained in:
421
tests/Feature/Security/Authorization/WireChatMultiAuthTest.php
Normal file
421
tests/Feature/Security/Authorization/WireChatMultiAuthTest.php
Normal 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');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user