diff --git a/CLAUDE.md b/CLAUDE.md index 896b05e1..0e9949bb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -251,7 +251,7 @@ Path params extracted as `_paramName` search params (e.g., `/:id` → `searchPar ## Database & Migrations **Location**: `supabase/migrations/` — 45 files, numbered `20240101000001`–`20240101000045`. -**Next migration**: `20240101000049_*.sql` +**Next migration**: `20240101000052_*.sql` ### Placeholder Migrations @@ -288,6 +288,7 @@ Some migrations are no-op placeholders to preserve the numbering sequence: - **Migration 043 (`enforce_fiscal_period_month_boundaries`)** — Ensures fiscal periods start/end on month boundaries. - **Migration 044 (`full_bas_2026`)** — Full BAS 2026 account catalog, K2-excluded flag, and SRU code backfill. - **Migration 045 (`expand_account_type_untaxed_reserves`)** — Adds `untaxed_reserves` to `chart_of_accounts.account_type` CHECK constraint for BAS 21xx accounts (obeskattade reserver). +- **Migration 051 (`set_search_path_on_functions`)** — Pins `search_path = public` on all 24 custom functions to prevent search_path injection. --- diff --git a/components/dashboard/DashboardContent.tsx b/components/dashboard/DashboardContent.tsx index 9038d168..242d5cd3 100644 --- a/components/dashboard/DashboardContent.tsx +++ b/components/dashboard/DashboardContent.tsx @@ -261,24 +261,6 @@ export default function DashboardContent({ firstName, settings, summary, onboard return 'God kväll' })()}{firstName ? `, ${firstName}` : ''} -
- {(() => { - if (summary.overdueInvoicesCount > 0) - return `${summary.overdueInvoicesCount} förfallna fakturor kräver åtgärd` - const passedDeadlines = summary.deadlines.filter(d => !d.is_completed && new Date(d.due_date) <= new Date()).length - if (passedDeadlines > 0) - return `${passedDeadlines} passerade deadlines` - if (summary.uncategorizedCount > 0) - return `${summary.uncategorizedCount} obokförda transaktioner` - if (summary.receiptQueue && summary.receiptQueue.pending_review_count > 0) - return `${summary.receiptQueue.pending_review_count} kvitton att granska` - if (summary.missingUnderlagCount > 0) - return `${summary.missingUnderlagCount} verifikationer saknar underlag` - if (summary.unpaidInvoicesCount > 0) - return `${summary.unpaidInvoicesCount} obetalda fakturor` - return 'Allt är som det ska' - })()} -
{/* New user checklist */} diff --git a/supabase/migrations/20240101000051_set_search_path_on_functions.sql b/supabase/migrations/20240101000051_set_search_path_on_functions.sql new file mode 100644 index 00000000..7f5ce249 --- /dev/null +++ b/supabase/migrations/20240101000051_set_search_path_on_functions.sql @@ -0,0 +1,28 @@ +-- Security hardening: pin search_path on all custom functions +-- to prevent search_path injection attacks. +-- See: https://supabase.com/docs/guides/database/database-linter?lint=0011_function_search_path_mutable + +ALTER FUNCTION public.audit_log_immutable() SET search_path = public; +ALTER FUNCTION public.block_document_deletion() SET search_path = public; +ALTER FUNCTION public.calculate_retention_expiry() SET search_path = public; +ALTER FUNCTION public.check_journal_entry_balance() SET search_path = public; +ALTER FUNCTION public.create_invoice_with_items(p_invoice jsonb, p_items jsonb) SET search_path = public; +ALTER FUNCTION public.detect_voucher_gaps(p_user_id uuid, p_fiscal_period_id uuid, p_series text) SET search_path = public; +ALTER FUNCTION public.enforce_journal_entry_immutability() SET search_path = public; +ALTER FUNCTION public.enforce_journal_entry_line_immutability() SET search_path = public; +ALTER FUNCTION public.enforce_opening_balance_immutability() SET search_path = public; +ALTER FUNCTION public.enforce_period_lock() SET search_path = public; +ALTER FUNCTION public.enforce_period_lock_documents() SET search_path = public; +ALTER FUNCTION public.enforce_retention_journal_entries() SET search_path = public; +ALTER FUNCTION public.generate_invoice_number(p_user_id uuid) SET search_path = public; +ALTER FUNCTION public.get_next_arrival_number(p_user_id uuid) SET search_path = public; +ALTER FUNCTION public.get_unlinked_1930_lines(p_user_id uuid, p_date_from date, p_date_to date) SET search_path = public; +ALTER FUNCTION public.handle_new_user() SET search_path = public; +ALTER FUNCTION public.next_voucher_number(p_user_id uuid, p_fiscal_period_id uuid, p_series text) SET search_path = public; +ALTER FUNCTION public.seed_asset_categories(p_user_id uuid) SET search_path = public; +ALTER FUNCTION public.seed_chart_of_accounts(p_user_id uuid, p_entity_type text) SET search_path = public; +ALTER FUNCTION public.set_committed_at() SET search_path = public; +ALTER FUNCTION public.update_overdue_supplier_invoices() SET search_path = public; +ALTER FUNCTION public.update_reconciliation_session_counts() SET search_path = public; +ALTER FUNCTION public.update_updated_at_column() SET search_path = public; +ALTER FUNCTION public.write_audit_log() SET search_path = public;