103 lines
3.6 KiB
PHP
103 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace Tests\App\Config;
|
|
|
|
use CodeIgniter\Test\CIUnitTestCase;
|
|
|
|
class FinancialRouteIntegrityTest extends CIUnitTestCase
|
|
{
|
|
private string $routesFile;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->routesFile = ROOTPATH . 'app/Config/Routes.php';
|
|
}
|
|
|
|
public function testFinancialBrowserWriteRoutesArePostOnlyAndFiltered(): void
|
|
{
|
|
$routes = file($this->routesFile, FILE_IGNORE_NEW_LINES) ?: [];
|
|
$financialWrites = array_values(array_filter($routes, static function (string $line): bool {
|
|
return str_contains($line, '$routes->post(')
|
|
&& preg_match('/(refunds|expenses|reimbursements|discount|charges|payment|invoice|purchase|inventory)/i', $line);
|
|
}));
|
|
|
|
$this->assertNotEmpty($financialWrites);
|
|
foreach ($financialWrites as $line) {
|
|
$this->assertStringContainsString("'filter'", $line, $line);
|
|
$this->assertStringContainsString('auth:', $line, $line);
|
|
}
|
|
}
|
|
|
|
public function testFinancialStateChangingRoutesDoNotUseGet(): void
|
|
{
|
|
$routes = file($this->routesFile, FILE_IGNORE_NEW_LINES) ?: [];
|
|
foreach ($routes as $line) {
|
|
if (!str_contains($line, '$routes->get(')) {
|
|
continue;
|
|
}
|
|
if (! preg_match('/\$routes->get\(\s*[\'"]([^\'"]+)/', $line, $matches)) {
|
|
continue;
|
|
}
|
|
|
|
$routePath = $matches[1];
|
|
if (!preg_match('/(refunds|expenses|reimbursements|discount|charges|payment|invoice|purchase|inventory)/i', $routePath)) {
|
|
continue;
|
|
}
|
|
$this->assertDoesNotMatchRegularExpression('/(update|store|approve|reverse|void|delete|apply|recalculate)/i', $routePath, $line);
|
|
}
|
|
}
|
|
|
|
public function testFinancialWritesDoNotUseGetPostMatchRoutes(): void
|
|
{
|
|
$routes = file($this->routesFile, FILE_IGNORE_NEW_LINES) ?: [];
|
|
$checked = 0;
|
|
foreach ($routes as $line) {
|
|
if (!str_contains($line, '$routes->match(') || !str_contains($line, "'get'") || !str_contains($line, "'post'")) {
|
|
continue;
|
|
}
|
|
if (!preg_match('/(refunds|expenses|reimbursements|discount|charges|payment|invoice|purchase|inventory)/i', $line)) {
|
|
continue;
|
|
}
|
|
|
|
$checked++;
|
|
$this->fail('Financial routes must split read GET and write POST handlers: ' . $line);
|
|
}
|
|
|
|
$this->assertSame(0, $checked);
|
|
}
|
|
|
|
public function testGenericApiDoesNotExposeFinancialMutations(): void
|
|
{
|
|
$text = file_get_contents($this->routesFile) ?: '';
|
|
$forbidden = [
|
|
"post('payments'",
|
|
"put('payments/",
|
|
"post('payment-transactions'",
|
|
"get('payment-transactions'",
|
|
"post('payment-notifications/send'",
|
|
"post('expenses'",
|
|
"put('expenses/",
|
|
"post('reimbursements'",
|
|
"put('reimbursements/",
|
|
"post('refunds'",
|
|
"put('refunds/",
|
|
"post('discounts/apply'",
|
|
"post('extra-charges'",
|
|
"put('extra-charges/",
|
|
"post('purchase-orders'",
|
|
"put('purchase-orders/",
|
|
"post('inventory'",
|
|
"put('inventory/",
|
|
"delete('inventory/",
|
|
];
|
|
|
|
$apiV1Start = strpos($text, "\$routes->group('api/v1'");
|
|
$this->assertIsInt($apiV1Start);
|
|
$apiV1Text = substr($text, $apiV1Start);
|
|
foreach ($forbidden as $needle) {
|
|
$this->assertStringNotContainsString($needle, $apiV1Text, $needle);
|
|
}
|
|
}
|
|
}
|