Prevent cached cashflow analytics responses (#368)
## Summary - mark cashflow analytics JSON responses as no-store/private - add coverage for cache-control header ## Why Browser tests reuse the same cashflow API URLs across authenticated users. Cached user-specific analytics can leak stale breakdown data between sessions and hide the income category. ## Tests - php artisan test --compact tests/Feature/CashflowAnalyticsTest.php
This commit is contained in:
parent
360a38a880
commit
97df0597f8
|
|
@ -28,7 +28,7 @@ class CashflowAnalyticsController extends Controller
|
|||
$current = $this->calculateCashflowSummary($request->user()->id, $period->from, $period->to);
|
||||
$previous = $this->calculateCashflowSummary($request->user()->id, $previousPeriod->from, $previousPeriod->to);
|
||||
|
||||
return response()->json([
|
||||
return $this->cashflowJson([
|
||||
'current' => $current,
|
||||
'previous' => $previous,
|
||||
]);
|
||||
|
|
@ -53,7 +53,7 @@ class CashflowAnalyticsController extends Controller
|
|||
$totalIncome = $incomeCategories->sum('amount');
|
||||
$totalExpense = $expenseCategories->sum('amount');
|
||||
|
||||
return response()->json([
|
||||
return $this->cashflowJson([
|
||||
'income_categories' => $incomeCategories->values(),
|
||||
'expense_categories' => $expenseCategories->values(),
|
||||
'total_income' => $totalIncome,
|
||||
|
|
@ -96,7 +96,7 @@ class CashflowAnalyticsController extends Controller
|
|||
$current->addMonth();
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
return $this->cashflowJson([
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
|
@ -134,13 +134,20 @@ class CashflowAnalyticsController extends Controller
|
|||
];
|
||||
})->sortByDesc('amount')->values();
|
||||
|
||||
return response()->json([
|
||||
return $this->cashflowJson([
|
||||
'data' => $currentWithPercentage,
|
||||
'total' => $currentTotal,
|
||||
'previous_total' => $previousTotal,
|
||||
]);
|
||||
}
|
||||
|
||||
private function cashflowJson(array $data): JsonResponse
|
||||
{
|
||||
return response()
|
||||
->json($data)
|
||||
->header('Cache-Control', 'no-store, private');
|
||||
}
|
||||
|
||||
private function calculateCashflowSummary(string $userId, Carbon $from, Carbon $to): array
|
||||
{
|
||||
$income = $this->getTransactionSum($userId, $from, $to, CategoryType::Income);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,16 @@ beforeEach(function () {
|
|||
$this->actingAs($this->user);
|
||||
});
|
||||
|
||||
test('cashflow analytics responses are not cached between users', function () {
|
||||
$response = $this->getJson('/api/cashflow/summary?'.http_build_query([
|
||||
'from' => now()->startOfMonth()->toDateString(),
|
||||
'to' => now()->endOfMonth()->toDateString(),
|
||||
]));
|
||||
|
||||
$response->assertOk()
|
||||
->assertHeader('Cache-Control', 'no-store, private');
|
||||
});
|
||||
|
||||
test('cashflow summary returns income, expense, net, and savings rate', function () {
|
||||
$incomeCategory = Category::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
|
|
|
|||
Loading…
Reference in New Issue