feat: Implement CSRF protection and PostgreSQL support

- Added CSRF protection mechanism in the backend with utility functions for token management.
- Introduced a new CSRF route to fetch the active CSRF token for SPA bootstrap flows.
- Updated the auth routes to validate CSRF tokens on sensitive operations.
- Configured PostgreSQL as a database option in the environment settings and Docker Compose.
- Created a new SQLite configuration file for local development.
- Enhanced the API client to automatically attach CSRF tokens to requests.
- Updated various frontend components to utilize the new site origin utility for SEO purposes.
- Modified Nginx configuration to improve redirection and SEO headers.
- Added tests for CSRF token handling in the authentication routes.
This commit is contained in:
Your Name
2026-03-17 23:26:32 +02:00
parent 3f24a7ea3e
commit a2824b2132
24 changed files with 332 additions and 319 deletions

View File

@@ -2,7 +2,7 @@ import { useDeferredValue } from 'react';
import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom';
import SEOHead from '@/components/seo/SEOHead';
import { generateOrganization } from '@/utils/seo';
import { generateOrganization, getSiteOrigin } from '@/utils/seo';
import {
FileText,
FileOutput,
@@ -86,6 +86,7 @@ const otherTools: ToolInfo[] = [
export default function HomePage() {
const { t } = useTranslation();
const siteOrigin = getSiteOrigin(typeof window !== 'undefined' ? window.location.origin : '');
const [searchParams, setSearchParams] = useSearchParams();
const query = searchParams.get('q') || '';
const deferredQuery = useDeferredValue(query.trim().toLowerCase());
@@ -123,15 +124,15 @@ export default function HomePage() {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: t('common.appName'),
url: window.location.origin,
url: siteOrigin,
description: t('home.heroSub'),
potentialAction: {
'@type': 'SearchAction',
target: `${window.location.origin}/?q={search_term_string}`,
target: `${siteOrigin}/?q={search_term_string}`,
'query-input': 'required name=search_term_string',
},
},
generateOrganization(window.location.origin),
generateOrganization(siteOrigin),
]}
/>