Commit Graph

31 Commits

Author SHA1 Message Date
davide db6b727902 test: add component tests (Button, ProductCard) and test suite README
20 component tests covering Button (variants, disabled state, event handlers) and
ProductCard (rendering, price formatting, sale badge, image fallback). README
documents the full suite: 151 tests across 10 files, how to run, mock patterns,
and what's missing by priority (checkout flow, admin routes, more components).
2026-05-19 14:08:07 +02:00
davide 6a5d5a6119 test: add integration tests for API routes (auth, Stripe webhook)
27 tests covering POST /api/auth/login (9), POST /api/auth/register (9), and
POST /api/webhooks/stripe (11). Routes are tested by importing handlers directly
as functions, no HTTP server needed. Stripe false-positive fixed: thrown error
message now differs from the hardcoded 400 response to verify sanitization.
2026-05-19 14:07:53 +02:00
davide 5428eeccc1 test: add unit tests for lib/ (validate, auth, storage, email, rate-limit)
49 tests for all 10 Zod schemas in validate.ts, 26 tests for auth (hashPassword,
verifyPassword, createSession, getSession, getCurrentUser, deleteSession), 11 for
storage (magic-byte validation, saveImage, deleteImageFile), 9 for email (sendMail
scenarios), and 6 for rate limiting logic.
2026-05-19 14:07:38 +02:00
davide b93f5d5bdf test: add Vitest infrastructure (config, setup, mocks, fixtures)
Adds test harness for the suite:
- vitest.config.ts: happy-dom env, @/* alias, v8 coverage with 70% thresholds
- setup.ts: env vars, global next/headers and next/navigation mocks
- tsconfig.json: IDE alias resolution for test/
- __mocks__/prisma.ts: centralised Prisma mock auto-registered via vi.mock
- fixtures/users.ts, fixtures/orders.ts: typed test data
2026-05-19 14:07:22 +02:00
davide ed7faa3be5 build: add Vitest test dependencies and fix Docker build type error
Added devDependencies: vitest, @vitest/coverage-v8, happy-dom, @testing-library/react,
jest-dom, user-event, and test scripts (test, test:watch, test:coverage).
Removed @types/testing-library__jest-dom (redundant with jest-dom v6+, caused
Docker build to fail with "Cannot find type definition file" error).
2026-05-19 14:07:09 +02:00
davide 93cfe1ad5e docs: update CLAUDE.md with Italian rule, error workflow, and full data model
Added Italian communication requirement, error-first workflow (report then wait),
and missing Prisma models: ProductVariant, PasswordResetToken, Page/PageSection,
SiteSettings, AuditLog. Added app/coverage/ to .gitignore.
2026-05-19 14:05:34 +02:00
davide ea5fca6561 fix: replace hardcoded site name with dynamic settings
- Add public /api/settings endpoint (force-dynamic, no auth) exposing
  site_name, site_description, footer_copyright, footer_links
- Navbar, login, register pages fetch site_name via useEffect
- Homepage hero and footer read site_name and site_description from DB
- Fix admin settings form silently ignoring API errors on save
2026-05-19 11:30:15 +02:00
davide 9797519e5c fix: use named Docker volume for uploads to fix permission errors
Bind-mounting ./data/uploads caused EACCES errors because Docker creates
the host directory as root, while the container runs as nextjs (UID 1001).
A named volume is initialized from the image where chown is already set correctly.
2026-05-19 10:54:45 +02:00
davide 43a3efc94f fix(security): clamp pagination parameters to prevent negative or overflow values
Replace raw parseInt() with Math.max/min bounds: page >= 1, limit 1-100.
Affects public products, admin orders, and admin reviews endpoints.
2026-05-19 10:12:17 +02:00
davide e18bc8fbda fix(security): block deletion of categories and product types in use
Return 409 Conflict if any products reference the entity being deleted,
preventing accidental data corruption from orphaned foreign keys.
2026-05-19 10:12:03 +02:00
davide 5654964d09 fix(security): sanitize error logging and remove Zod schema details from responses
- Stripe webhook: log only error.message instead of full error objects
  to avoid exposing stack traces in aggregated logs
- Admin products POST: return only first Zod error message instead of
  the full error array which reveals internal schema structure
2026-05-19 10:11:47 +02:00
davide 8cf038443f fix(security): remove hardcoded default credentials from config files
- .env.example: replace weak default INITIAL_ADMIN_PASSWORD and
  AUTH_SECRET with instructive placeholders requiring manual generation
- docker-compose.yml: parameterize POSTGRES_USER, POSTGRES_PASSWORD,
  POSTGRES_DB and DATABASE_URL via environment variables with local fallbacks
2026-05-19 10:11:30 +02:00
davide d4b3398de5 fix(security): enforce order status state machine in admin endpoint
Add VALID_TRANSITIONS map and validate each status change before updating
the database. Prevents skipping payment (e.g. PENDING→FULFILLED) or
reopening closed orders.
2026-05-19 10:11:16 +02:00
davide f4eedaffe2 fix(security): replace in-memory rate limiting with persistent DB-backed limiter
- Add LoginAttempt model to Prisma schema with migration
- Create rate-limit.ts utility (10 attempts / 15 min window, DB-backed)
- Apply rate limiting to login endpoint (replaces in-memory Map)
- Apply rate limiting to change-password endpoint (previously unprotected)
- Rate limit state survives server restarts and works across multiple instances
2026-05-19 10:10:57 +02:00
davide 45a50dc906 fix(security): whitelist allowed keys in admin settings endpoint
Reject any key not in the explicit allowlist before writing to the database,
preventing arbitrary configuration injection by a malicious admin.
2026-05-19 10:10:42 +02:00
davide fcfa0707a1 fix(security): replace localStorage user state with server-side session
- Add GET /api/auth/me endpoint returning current user from httpOnly cookie
- Add UserContext + useUser() hook that fetches from /api/auth/me on mount
- Wrap root layout with UserProvider
- Remove all localStorage.setItem/getItem('user') calls from login, register,
  navbar, account pages, change-password, and checkout
- mustChangePassword redirect now reads from refreshed server session
2026-05-19 10:10:24 +02:00
davide 0395a78008 fix(security): add HTTP security headers (CSP, HSTS, X-Frame-Options)
- middleware.ts: set X-Frame-Options, X-Content-Type-Options,
  Referrer-Policy, Permissions-Policy, Content-Security-Policy on all responses
- Caddyfile: add Strict-Transport-Security (HSTS 1y), X-Frame-Options,
  X-Content-Type-Options at reverse proxy level
2026-05-19 10:10:08 +02:00
davide 2a6c3a1222 fix(security): validate file uploads with magic bytes, remove SVG from favicon whitelist
- Add validateImageMagicBytes() to storage.ts reading first 12 bytes
  to verify JPEG/PNG/WebP/ICO signatures regardless of declared MIME type
- Remove image/svg+xml from favicon upload whitelist (SVG can embed scripts)
- Apply magic bytes check in product image and favicon upload endpoints
2026-05-19 10:09:53 +02:00
davide d958a4b9a5 docs: add network ports section to README
Sezione dedicata alle porte con distinzione tra porte pubbliche (80,
443), interne Docker (3000, 5432, 1025) e solo sviluppo (8025).
Include comandi UFW pronti per Ubuntu/Debian.
2026-05-19 09:19:16 +02:00
davide 4a7cd9fbd4 docs: expand admin guide with field-by-field documentation
Aggiunta documentazione campo per campo per tutte le sezioni: Product

Types, Categorie, Admin Users, Impostazioni (generale, footer, favicon).

Corretto Base Price da centesimi a euro dopo la fix del form.
2026-05-19 09:17:38 +02:00
davide 7afb609386 fix: hide slug field in product type form, auto-generate from name
Lo slug viene calcolato automaticamente dal nome senza che l'utente
debba compilarlo — il campo è rimosso dal form ma continua ad essere
inviato nel payload e visibile nella tabella.
2026-05-19 09:17:17 +02:00
davide 46d1596dce fix: update tsconfig target from deprecated ES5 to ES2017 2026-05-19 09:01:51 +02:00
davide 3b800463f5 fix: accept price in currency units instead of cents in product form
Il campo prezzo del form admin ora accetta valori in unità (es. 19.99)
invece di centesimi (1999). La conversione *100 avviene al submit,
il DB e Stripe continuano a ricevere centesimi.
2026-05-19 08:58:46 +02:00
davide 2c6c847d76 feat: replace Docker named volumes with local bind mounts and add backup script
- docker-compose.yml: sostituisce pgdata/uploads/caddy_data/caddy_config con bind mount su ./data/
- app/public/.gitkeep: crea cartella richiesta dal Dockerfile durante il build
- scripts/backup.sh: backup automatico di DB (pg_dump) e uploads con rotazione 30 giorni
- docs/BACKUP.md: guida completa backup, ripristino e setup cron
- .gitignore: aggiorna con data/ e backups/
2026-05-19 08:49:28 +02:00
davide b62c02adc1 feat: add favicon upload and footer customization to admin settings
- Admin settings page now has sections for general settings, footer, and favicon
- Footer component reads footer_copyright and footer_links from DB
- New API route POST /api/admin/upload/favicon saves uploaded image and updates favicon_url in DB
- Textarea support added for footer_links JSON field
2026-05-18 22:50:07 +02:00
davide b33eee8bea docs: add favicon, reorganize docs and add customization guide
- Add icon.png as default favicon (cropped to remove transparent padding)
- Fix layout.tsx to use icon.png as fallback when favicon_url is not set in DB
- Move ADMIN_GUIDE.md to docs/ folder
- Add docs/CUSTOMIZATION.md with guide on how to customize icon, title, footer
2026-05-18 22:49:22 +02:00
davide e82e20b0f1 docs: add localhost vs production comparison and fix Caddyfile example
- Add new section summarising the 4 differences between local dev and
  production: domain/HTTPS, env vars, server requirements, backups
- Update production Caddyfile example to include /uploads/* static
  file handler (required for image serving)
2026-05-18 17:55:12 +02:00
davide aab9d24800 docs: add comprehensive admin panel user guide (Italian)
Covers all admin sections with step-by-step instructions:
login, dashboard, products (detailed field reference including image
upload with aspect ratio guidance), product types, categories,
orders, customers, reviews, admin users, settings, and recommended
onboarding flow.
2026-05-18 17:55:05 +02:00
davide 676b173414 feat: add product image upload to admin panel
- Add storage.ts utility (saveImage, deleteImageFile) for local disk operations
- Add POST /api/admin/products/[id]/images: validates MIME type and 5MB limit, saves file, creates MediaAsset record
- Add DELETE /api/admin/products/[id]/images?imageId=: removes file and DB record
- Add Images section to product edit form (hidden for new products until saved)
- Display images in square aspect-ratio grid matching storefront display
- Support multi-file upload; hover to reveal delete button
2026-05-18 17:54:09 +02:00
davide b3097670c0 infra: add persistent uploads volume and configure Caddy to serve static images
- Add named Docker volume `uploads` mounted at /app/public/uploads in app container
- Share same volume with Caddy at /srv/uploads for direct static file serving
- Add Caddy `handle /uploads/*` block so images bypass Next.js (standalone mode does not serve runtime public files)
- Create uploads directory with correct nextjs:nodejs ownership in Dockerfile
- Add mkdir safeguard in entrypoint.sh
2026-05-18 17:54:00 +02:00
davide a8d4c158b8 Commit iniziale 2026-05-18 15:25:38 +02:00