feat: add file_url column to factory_reports and update related queries
chore: upgrade nodemailer to version 9.0.1 and undici to version 7.28.0
feat: enhance factory report editor with file upload functionality for PDFs
fix: increase bcrypt hash rounds for improved password security
fix: restrict file uploads to video, audio, and PDF formats
chore: implement safe URL handling for banner CTA links
chore: seed radar_items with random dates, sources, and tags for consistency
add: new image asset for chart analysis
- Replaced localStorage-based authentication checks with context-based checks using useAuth.
- Updated login handling in PostDetail to navigate to the login page instead of setting localStorage directly.
- Simplified ProfilePage to check for member presence instead of token.
- Removed token dependency from InfoTab, PasswordTab, and ContentTab components.
- Adjusted Radar and RadarPost components to utilize context for authentication state.
Security fixes:
- JWT_SECRET/ADMIN_PASSWORD fail-fast on missing/weak values
- Switch admin auth from localStorage to httpOnly cookie
- Rate limiting on login (10/15min) and contact form (3/10min)
- CORS whitelist via ALLOWED_ORIGINS env var
- Helmet with CSP, frameguard
- Escape HTML in contact email and admin panel innerHTML
- Remove SVG from upload whitelist
- err.message no longer leaked in API responses
- MAIL_TO moved to env var
- JWT expiry 7d → 24h
Navbar:
- Rename: رادار آینده → آیندهپژوهی و رصد هوشمند
- Rename: مرز فناوری → فناوری و نوآوری
- Rename: نبض صنعت → بازار و زنجیره فولاد
- Add: پایداری و فولاد سبز (/sustainability)
- Add: ژئوپلیتیک و اقتصاد جهانی (/geopolitics)
- Remove: رویدادها
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- panel/: standalone Express + SQLite + JWT admin (server.js, db.js, seed.js,
vanilla-JS admin UI under public/). CRUD for articles with cover image
uploads. README documents API, run instructions, and integration steps.
- src/data/reports.ts: appended bootstrapReports() that fetches from
VITE_PANEL_API (defaults to http://localhost:3001) and mutates the in-memory
reports array. Static array kept as fallback when panel is offline.
- src/main.tsx: awaits bootstrapReports() before initial render so all
existing consumers see panel data without per-file changes.