Files
HRM-System/tests/Feature/TenantInvitationSetupTest.php

141 lines
5.0 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\Inquiry;
use App\Models\TenantEntitlement;
use App\Models\TenantSetupToken;
use App\Jobs\ProvisionTenantJob;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Mail;
use App\Models\Tenant;
use Tests\TestCase;
class TenantInvitationSetupTest extends TestCase
{
use RefreshDatabase;
public function test_provisioning_dispatches_one_time_token_and_does_not_use_default_passwords(): void
{
Mail::fake();
$inquiry = Inquiry::create([
'company_name' => 'Secure Org',
'contact_name' => 'Org Admin',
'email' => 'admin@secureorg.com',
'desired_subdomain' => 'secure-org-tenant',
'employee_count' => 25,
'requested_features' => ['payroll'],
'email_verified_at' => now(),
'status' => 'approved',
]);
$job = new ProvisionTenantJob($inquiry);
$job->handle();
$tenant = Tenant::find('secure-org-tenant');
$this->assertNotNull($tenant);
// 1. Verify state transition to active
$this->assertEquals('active', $inquiry->fresh()->status);
// 2. Verify TenantEntitlement created in central DB
$entitlement = TenantEntitlement::where('tenant_id', 'secure-org-tenant')->first();
$this->assertNotNull($entitlement);
$this->assertEquals(25, $entitlement->max_employees);
// 3. Verify TenantSetupToken generated with unexpired hashed token
$setupToken = TenantSetupToken::where('tenant_id', 'secure-org-tenant')->first();
$this->assertNotNull($setupToken);
$this->assertEquals('admin@secureorg.com', $setupToken->email);
$this->assertFalse($setupToken->isExpired());
$this->assertFalse($setupToken->isUsed());
// 4. Verify email invitation was dispatched
Mail::assertSent(\App\Mail\TenantSetupInvitationMail::class, function ($mail) {
return $mail->hasTo('admin@secureorg.com');
});
// 5. Verify admin account inside tenant DB uses default password '12345678'
$tenant->run(function () {
$user = \App\Models\User::where('email', 'admin@secureorg.com')->first();
$this->assertNotNull($user);
$this->assertEquals('active', $user->status);
$this->assertTrue(\Illuminate\Support\Facades\Hash::check('12345678', $user->password));
});
}
public function test_admin_can_set_password_via_token_and_token_expires_after_use(): void
{
$tenantId = 'setup-token-test';
$email = 'tokenadmin@acme.com';
$dbFile = database_path('tenant_' . $tenantId);
if (!file_exists($dbFile)) {
touch($dbFile);
}
Tenant::create([
'id' => $tenantId,
'tenancy_db_name' => 'tenant_' . $tenantId,
'email' => $email,
]);
$rawToken = 'valid_raw_test_token_123456';
$tokenHash = hash('sha256', $rawToken);
$setupToken = TenantSetupToken::create([
'tenant_id' => $tenantId,
'email' => $email,
'token_hash' => $tokenHash,
'expires_at' => now()->addHours(24),
]);
$tenant = Tenant::find($tenantId);
$tenant->run(function () use ($dbFile, $email) {
config(['database.connections.tenant.database' => $dbFile]);
\Illuminate\Support\Facades\DB::purge('tenant');
\Illuminate\Support\Facades\DB::reconnect('tenant');
\Illuminate\Support\Facades\Artisan::call('migrate', [
'--database' => 'tenant',
'--path' => 'database/migrations/tenant',
'--force' => true,
]);
\App\Models\User::updateOrCreate(
['email' => $email],
[
'name' => 'Token Admin',
'password' => \Illuminate\Support\Facades\Hash::make('temp_random_hash'),
'status' => 'inactive',
]
);
});
// Execute setup request
$controller = new \App\Http\Controllers\TenantSetupController();
$request = \Illuminate\Http\Request::create('/setup-admin', 'POST', [
'token' => $rawToken,
'password' => 'NewSecurePassword123!',
'password_confirmation' => 'NewSecurePassword123!',
]);
$response = $tenant->run(function () use ($controller, $request) {
return $controller->completeSetup($request);
});
$this->assertEquals(302, $response->getStatusCode());
// Verify token is marked used
$this->assertTrue($setupToken->fresh()->isUsed());
// Verify admin account is active and password updated inside tenant DB
$tenant->run(function () use ($email) {
$user = \App\Models\User::where('email', $email)->first();
$this->assertEquals('active', $user->status);
$this->assertTrue(\Illuminate\Support\Facades\Hash::check('NewSecurePassword123!', $user->password));
});
}
}