mirror of
https://github.com/FOSSBilling/FOSSBilling.git
synced 2026-11-09 05:24:58 +09:00
* Cast ticket ID to integer * Added type casting and removed unnecessary $per_page params * Fixed tests * Updated ddev PHP and nginx config * Support ticket validation and upgrade checks * Add order mock and constants in ServiceTest * Require active status for API auth and clear tokens * Validate client/admin sessions against DB * Invalidate sessions on user status deactivation * Check locale availability before toggling * Escape database name properly * Validate and cast rel_id to int in ticketCreateForClient to prevent TypeError Agent-Logs-Url: https://github.com/FOSSBilling/FOSSBilling/sessions/ce700346-2168-43cc-8309-fc6baee7cc82 Co-authored-by: admdly <2807620+admdly@users.noreply.github.com> * Improve rel_id validation error message to include the invalid value Agent-Logs-Url: https://github.com/FOSSBilling/FOSSBilling/sessions/ce700346-2168-43cc-8309-fc6baee7cc82 Co-authored-by: admdly <2807620+admdly@users.noreply.github.com> * Fix Notification AdminTest mock expectation to match actual paginateDoctrineQuery call Agent-Logs-Url: https://github.com/FOSSBilling/FOSSBilling/sessions/2fb587cf-6312-4b98-89e5-10f074646eaa Co-authored-by: admdly <2807620+admdly@users.noreply.github.com> * Validate interface and custom interface inputs * Tighten custom interface hostname validation * Accept `per_page` in paginated API responses * Validate HTTP interfaces and normalize upgrades * Enforce active status and secure config export * Cast rel_type/rel_task/rel_status to string in SupportTicketValidator to prevent TypeError Agent-Logs-Url: https://github.com/FOSSBilling/FOSSBilling/sessions/1ecf2bb3-1139-420f-8421-41ae8f6d1d5f Co-authored-by: admdly <2807620+admdly@users.noreply.github.com> * Use FILTER_VALIDATE_INT instead of is_numeric for rel_id validation in Service.php Agent-Logs-Url: https://github.com/FOSSBilling/FOSSBilling/sessions/7bacd505-ba15-42da-8f52-7621afa1d634 Co-authored-by: admdly <2807620+admdly@users.noreply.github.com> * Validate rel_new_value as a positive integer before using as Product ID in upgrade tickets Agent-Logs-Url: https://github.com/FOSSBilling/FOSSBilling/sessions/842c7e1c-255b-4f09-8235-f34681e0392b Co-authored-by: admdly <2807620+admdly@users.noreply.github.com> * Tighten `sValidHttpInterface` validation * Add page parameter to pager calls --------- Co-authored-by: Adam Daley <admdly@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: admdly <2807620+admdly@users.noreply.github.com>
125 lines
5.1 KiB
PHP
125 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace SystemTests;
|
|
|
|
use APIHelper\Request;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class AdminTest extends TestCase
|
|
{
|
|
private function ipLookupWorking(): bool
|
|
{
|
|
$services = ['https://api64.ipify.org', 'https://ifconfig.io/ip', 'https://ip.hestiacp.com/'];
|
|
foreach ($services as $service) {
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
|
|
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
|
curl_setopt($ch, CURLOPT_URL, $service);
|
|
$ip = curl_exec($ch);
|
|
if (filter_var($ip, FILTER_VALIDATE_IP)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function testClearCache(): void
|
|
{
|
|
// Clear the cache
|
|
$result = Request::makeRequest('admin/system/clear_cache');
|
|
$this->assertTrue($result->wasSuccessful(), $result->generatePHPUnitMessage());
|
|
$this->assertIsBool($result->getResult());
|
|
}
|
|
|
|
public function testErrorReportingToggle(): void
|
|
{
|
|
// Get the starting value
|
|
$before = Request::makeRequest('admin/system/error_reporting_enabled')->getResult();
|
|
$this->assertIsBool($before);
|
|
|
|
// Toggle the option
|
|
$result = Request::makeRequest('admin/system/toggle_error_reporting');
|
|
$this->assertTrue($result->wasSuccessful(), $result->generatePHPUnitMessage());
|
|
$this->assertTrue($result->getResult());
|
|
|
|
// Check that it was correctly switched
|
|
$after = Request::makeRequest('admin/system/error_reporting_enabled')->getResult();
|
|
$this->assertIsBool($after);
|
|
$this->assertNotEquals($after, $before);
|
|
|
|
// Ensure we don't leave error reporting on (it shouldn't report anyways, but this is best practice)
|
|
if ($after) {
|
|
$result = Request::makeRequest('admin/system/toggle_error_reporting');
|
|
$this->assertTrue($result->wasSuccessful(), $result->generatePHPUnitMessage());
|
|
$this->assertTrue($result->getResult());
|
|
}
|
|
}
|
|
|
|
public function testGetAndSetNetworkInterfaces(): void
|
|
{
|
|
// Get the list of network interfaces, validate the response is as expected
|
|
$result = Request::makeRequest('admin/system/get_interface_ips');
|
|
$this->assertTrue($result->wasSuccessful(), $result->generatePHPUnitMessage());
|
|
$this->assertIsArray($result->getResult());
|
|
|
|
// And then validate they are all valid IP addresses
|
|
foreach ($result->getResult() as $ip) {
|
|
$this->assertTrue((bool) filter_var($ip, FILTER_VALIDATE_IP));
|
|
}
|
|
|
|
// Only test each found interface if ipify.org is functioning
|
|
if ($this->ipLookupWorking()) {
|
|
foreach ($result->getResult() as $ip) {
|
|
$testResult = Request::makeRequest('admin/system/set_interface_ip', ['interface' => $ip]);
|
|
$this->assertTrue($testResult->wasSuccessful(), $result->generatePHPUnitMessage());
|
|
|
|
sleep(2);
|
|
|
|
$result = Request::makeRequest('admin/system/env', ['ip' => true]);
|
|
$this->assertTrue($result->wasSuccessful(), $result->generatePHPUnitMessage());
|
|
$this->assertTrue((bool) filter_var($result->getResult(), FILTER_VALIDATE_IP));
|
|
}
|
|
}
|
|
|
|
// Finally, set it back to the default interface
|
|
Request::makeRequest('admin/system/set_interface_ip', ['interface' => '0']);
|
|
}
|
|
|
|
public function testInvalidInterfaceIsRejected(): void
|
|
{
|
|
$result = Request::makeRequest('admin/system/set_interface_ip', ['interface' => '12345']);
|
|
$this->assertFalse($result->wasSuccessful(), 'An invalid interface IP was accepted when it should have been rejected');
|
|
}
|
|
|
|
public function testInvalidCustomInterfaceIsRejected(): void
|
|
{
|
|
$result = Request::makeRequest('admin/system/set_interface_ip', ['custom_interface' => '!@#$%']);
|
|
$this->assertFalse($result->wasSuccessful(), 'An invalid custom interface was accepted when it should have been rejected');
|
|
}
|
|
|
|
public function testMaliciousInterfaceIsRejected(): void
|
|
{
|
|
$result = Request::makeRequest('admin/system/set_interface_ip', ['interface' => "x\"; echo 'pwned'; //"]);
|
|
$this->assertFalse($result->wasSuccessful(), 'A malicious interface value was accepted when it should have been rejected');
|
|
}
|
|
|
|
public function testMaliciousCustomInterfaceIsRejected(): void
|
|
{
|
|
$result = Request::makeRequest('admin/system/set_interface_ip', ['custom_interface' => "x\"; passthru('id'); //"]);
|
|
$this->assertFalse($result->wasSuccessful(), 'A malicious custom interface value was accepted when it should have been rejected');
|
|
}
|
|
|
|
public function testCustomInterfaceAcceptsValidHostname(): void
|
|
{
|
|
$result = Request::makeRequest('admin/system/set_interface_ip', ['custom_interface' => 'eth0']);
|
|
$this->assertTrue($result->wasSuccessful(), $result->generatePHPUnitMessage());
|
|
|
|
// Reset to default
|
|
Request::makeRequest('admin/system/set_interface_ip', ['custom_interface' => '', 'interface' => '0']);
|
|
}
|
|
}
|