Files
timebank-cc-public/tests/Feature/Security/Authorization/ExportProfileDataAuthorizationTest.php
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

568 lines
17 KiB
PHP

<?php
namespace Tests\Feature\Security\Authorization;
use App\Models\Account;
use App\Models\Bank;
use App\Models\Organization;
use App\Models\Tag;
use App\Models\Transaction;
use App\Models\TransactionType;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Namu\WireChat\Models\Conversation;
use Namu\WireChat\Models\Message;
use Tests\TestCase;
/**
* Export Profile Data Authorization Tests
*
* Tests that users can only export their own profile data and cannot export
* data from profiles they don't own/manage.
*
* @group security
* @group authorization
* @group export
* @group critical
*/
class ExportProfileDataAuthorizationTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
// Create transaction type for transaction exports
\DB::table('transaction_types')->insert([
'id' => 1,
'name' => 'worked_hours',
'label' => 'Worked Hours',
'icon' => 'clock',
]);
}
/**
* Test user can export their own transactions
*
* @test
*/
public function user_can_export_own_transactions()
{
$user = User::factory()->create();
$recipient = User::factory()->create();
$userAccount = Account::factory()->create([
'accountable_type' => User::class,
'accountable_id' => $user->id,
]);
$recipientAccount = Account::factory()->create([
'accountable_type' => User::class,
'accountable_id' => $recipient->id,
]);
Transaction::factory()->create([
'from_account_id' => $userAccount->id,
'to_account_id' => $recipientAccount->id,
'amount' => 60,
]);
$this->actingAs($user, 'web');
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTransactions', 'json');
$response->assertStatus(200);
}
/**
* Test user cannot export another user's transactions via session manipulation
*
* @test
*/
public function user_cannot_export_another_users_transactions()
{
$user1 = User::factory()->create();
$user2 = User::factory()->create();
$user2Account = Account::factory()->create([
'accountable_type' => User::class,
'accountable_id' => $user2->id,
]);
// Logged in as user1
$this->actingAs($user1, 'web');
// Malicious: manipulate session to target user2
session(['activeProfileType' => User::class, 'activeProfileId' => $user2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTransactions', 'json');
$response->assertStatus(403);
}
/**
* Test organization can export own transactions
*
* @test
*/
public function organization_can_export_own_transactions()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
$orgAccount = Account::factory()->create([
'accountable_type' => Organization::class,
'accountable_id' => $organization->id,
]);
$this->actingAs($organization, 'organization');
session(['activeProfileType' => Organization::class, 'activeProfileId' => $organization->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTransactions', 'json');
$response->assertStatus(200);
}
/**
* Test organization cannot export another organization's transactions
*
* @test
*/
public function organization_cannot_export_another_organizations_transactions()
{
$user = User::factory()->create();
$org1 = Organization::factory()->create();
$org2 = Organization::factory()->create();
$org1->users()->attach($user->id);
// Logged in as both web user and organization
$this->actingAs($user, 'web');
$this->actingAs($org1, 'organization');
// Malicious: manipulate session to target org2
session(['activeProfileType' => Organization::class, 'activeProfileId' => $org2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTransactions', 'json');
$response->assertStatus(403);
}
/**
* Test user can export own profile data
*
* @test
*/
public function user_can_export_own_profile_data()
{
$user = User::factory()->create();
$this->actingAs($user, 'web');
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportProfileData', 'json');
$response->assertStatus(200);
}
/**
* Test user cannot export another user's profile data
*
* @test
*/
public function user_cannot_export_another_users_profile_data()
{
$user1 = User::factory()->create();
$user2 = User::factory()->create();
// Logged in as user1
$this->actingAs($user1, 'web');
// Malicious: manipulate session to target user2
session(['activeProfileType' => User::class, 'activeProfileId' => $user2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportProfileData', 'json');
$response->assertStatus(403);
}
/**
* Test user can export own messages
*
* @test
*/
public function user_can_export_own_messages()
{
$user = User::factory()->create();
$recipient = User::factory()->create();
// Create a conversation using sendMessageTo
$user->sendMessageTo($recipient, 'Test message');
$this->actingAs($user, 'web');
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportMessages', 'json');
$response->assertStatus(200);
}
/**
* Test user cannot export another user's messages
*
* @test
*/
public function user_cannot_export_another_users_messages()
{
$user1 = User::factory()->create();
$user2 = User::factory()->create();
$recipient = User::factory()->create();
// Create messages for user2
$user2->sendMessageTo($recipient, 'User2 private message');
// Logged in as user1
$this->actingAs($user1, 'web');
// Malicious: manipulate session to target user2
session(['activeProfileType' => User::class, 'activeProfileId' => $user2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportMessages', 'json');
$response->assertStatus(403);
}
/**
* Test user can export own tags
*
* @test
*/
public function user_can_export_own_tags()
{
$user = User::factory()->create();
// Create a tag and attach to user
$tag = Tag::factory()->create();
$user->tags()->attach($tag->id);
$this->actingAs($user, 'web');
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTags', 'json');
$response->assertStatus(200);
}
/**
* Test user cannot export another user's tags
*
* @test
*/
public function user_cannot_export_another_users_tags()
{
$user1 = User::factory()->create();
$user2 = User::factory()->create();
// Create tags for user2
$tag = Tag::factory()->create();
$user2->tags()->attach($tag->id);
// Logged in as user1
$this->actingAs($user1, 'web');
// Malicious: manipulate session to target user2
session(['activeProfileType' => User::class, 'activeProfileId' => $user2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTags', 'json');
$response->assertStatus(403);
}
/**
* Test user can export own contacts
*
* @test
*/
public function user_can_export_own_contacts()
{
$user = User::factory()->create();
$contact = User::factory()->create();
// Create a transaction to establish contact
$userAccount = Account::factory()->create([
'accountable_type' => User::class,
'accountable_id' => $user->id,
]);
$contactAccount = Account::factory()->create([
'accountable_type' => User::class,
'accountable_id' => $contact->id,
]);
Transaction::factory()->create([
'from_account_id' => $userAccount->id,
'to_account_id' => $contactAccount->id,
'amount' => 60,
]);
$this->actingAs($user, 'web');
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportContacts', 'json');
$response->assertStatus(200);
}
/**
* Test user cannot export another user's contacts
*
* @test
*/
public function user_cannot_export_another_users_contacts()
{
$user1 = User::factory()->create();
$user2 = User::factory()->create();
// Logged in as user1
$this->actingAs($user1, 'web');
// Malicious: manipulate session to target user2
session(['activeProfileType' => User::class, 'activeProfileId' => $user2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportContacts', 'json');
$response->assertStatus(403);
}
/**
* Test organization can export own messages
*
* @test
*/
public function organization_can_export_own_messages()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
$recipient = User::factory()->create();
// Create a conversation from organization
$organization->sendMessageTo($recipient, 'Org message');
$this->actingAs($user, 'web');
$this->actingAs($organization, 'organization');
session(['activeProfileType' => Organization::class, 'activeProfileId' => $organization->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportMessages', 'json');
$response->assertStatus(200);
}
/**
* Test organization cannot export another organization's messages
*
* @test
*/
public function organization_cannot_export_another_organizations_messages()
{
$user = User::factory()->create();
$org1 = Organization::factory()->create();
$org2 = Organization::factory()->create();
$org1->users()->attach($user->id);
$this->actingAs($user, 'web');
$this->actingAs($org1, 'organization');
// Malicious: manipulate session to target org2
session(['activeProfileType' => Organization::class, 'activeProfileId' => $org2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportMessages', 'json');
$response->assertStatus(403);
}
/**
* Test organization can export own tags
*
* @test
*/
public function organization_can_export_own_tags()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
// Create a tag and attach to organization
$tag = Tag::factory()->create();
$organization->tags()->attach($tag->id);
$this->actingAs($user, 'web');
$this->actingAs($organization, 'organization');
session(['activeProfileType' => Organization::class, 'activeProfileId' => $organization->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTags', 'json');
$response->assertStatus(200);
}
/**
* Test organization cannot export another organization's tags
*
* @test
*/
public function organization_cannot_export_another_organizations_tags()
{
$user = User::factory()->create();
$org1 = Organization::factory()->create();
$org2 = Organization::factory()->create();
$org1->users()->attach($user->id);
$this->actingAs($user, 'web');
$this->actingAs($org1, 'organization');
// Malicious: manipulate session to target org2
session(['activeProfileType' => Organization::class, 'activeProfileId' => $org2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTags', 'json');
$response->assertStatus(403);
}
/**
* Test organization can export own contacts
*
* @test
*/
public function organization_can_export_own_contacts()
{
$user = User::factory()->create();
$organization = Organization::factory()->create();
$organization->users()->attach($user->id);
$this->actingAs($user, 'web');
$this->actingAs($organization, 'organization');
session(['activeProfileType' => Organization::class, 'activeProfileId' => $organization->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportContacts', 'json');
$response->assertStatus(200);
}
/**
* Test organization cannot export another organization's contacts
*
* @test
*/
public function organization_cannot_export_another_organizations_contacts()
{
$user = User::factory()->create();
$org1 = Organization::factory()->create();
$org2 = Organization::factory()->create();
$org1->users()->attach($user->id);
$this->actingAs($user, 'web');
$this->actingAs($org1, 'organization');
// Malicious: manipulate session to target org2
session(['activeProfileType' => Organization::class, 'activeProfileId' => $org2->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportContacts', 'json');
$response->assertStatus(403);
}
/**
* Test cross-guard attack: web user cannot export bank data
*
* @test
*/
public function web_user_cannot_export_bank_data_cross_guard_attack()
{
$user = User::factory()->create();
$bank = Bank::factory()->create();
$bank->managers()->attach($user->id);
// Logged in as user (web guard)
$this->actingAs($user, 'web');
// Malicious: manipulate session to target bank profile
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportProfileData', 'json');
$response->assertStatus(403);
}
/**
* Test bank can export own data when properly authenticated
*
* @test
*/
public function bank_can_export_own_data_when_properly_authenticated()
{
$user = User::factory()->create();
$bank = Bank::factory()->create();
$bank->managers()->attach($user->id);
// Properly logged in as bank
$this->actingAs($bank, 'bank');
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportProfileData', 'json');
$response->assertStatus(200);
}
/**
* Test unauthenticated user cannot export any data
*
* @test
*/
public function unauthenticated_user_cannot_export_data()
{
$user = User::factory()->create();
// Not authenticated
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
$response = Livewire::test(\App\Http\Livewire\Profile\ExportProfileData::class)
->call('exportTransactions', 'json');
// Should return 401 (not authenticated) rather than 403 (authenticated but unauthorized)
$response->assertStatus(401);
}
}