postJson('/api/login', [ 'email' => 'missing@example.com', 'password' => 'wrong-password', ])->assertUnauthorized(); } $this->postJson('/api/login', [ 'email' => 'missing@example.com', 'password' => 'wrong-password', ])->assertTooManyRequests(); } public function test_file_upload_rejects_executable_files(): void { Storage::fake('local'); $user = User::factory()->create(['status' => 'active']); $this->grantAdminRole($user); $project = Project::create([ 'title' => 'Security test project', 'project_manager_id' => $user->id, 'created_by' => $user->id, ]); $token = $user->createToken('api-token')->plainTextToken; $this->withToken($token) ->postJson('/api/files', [ 'project_id' => $project->id, 'file' => UploadedFile::fake()->create('payload.php', 4, 'application/x-php'), ]) ->assertUnprocessable(); } public function test_file_resource_does_not_expose_storage_path(): void { $user = User::factory()->create(['status' => 'active']); $this->grantAdminRole($user); $file = File::create([ 'name' => 'safe.pdf', 'original_name' => 'safe.pdf', 'path' => 'files/private-safe.pdf', 'mime_type' => 'application/pdf', 'size' => 123, 'fileable_type' => Project::class, 'fileable_id' => 1, 'user_id' => $user->id, ]); $token = $user->createToken('api-token')->plainTextToken; $this->withToken($token) ->getJson('/api/files') ->assertOk() ->assertJsonMissingPath('data.0.path') ->assertJsonPath('data.0.download_url', url("/api/files/{$file->id}")); } public function test_user_without_permission_cannot_access_user_management(): void { $user = User::factory()->create(['status' => 'active']); $token = $user->createToken('api-token')->plainTextToken; $this->withToken($token) ->getJson('/api/users') ->assertForbidden() ->assertJsonPath('success', false); } }