Go to file
Mr.Gay100 a188b48679 feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
.claude feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
admin feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
backend feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
deploy feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
frontend feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
tools feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
.env.example feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
.gitignore feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
ADVERSARIAL-ARCHITECTURE-REVIEW.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
API-DOCUMENTATION-FA.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
API-SHARE.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
DEPLOY-ARVAN.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
DEPLOY.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
LIVE-DATA-CATALOG.json feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
LIVE-DATA-CATALOG.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
PRODUCT-CATALOG.csv feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
PRODUCT-CATALOG.json feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
PRODUCT-CATALOG.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
PRODUCT.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
README.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
SECURITY-CHECKLIST.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
SECURITY.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
docker-compose.yml feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00
liara-deploy.md feat: production codebase for Statista (https://statista.steelforesight.ir) 2026-08-26 07:04:12 +00:00

README.md

سامانهٔ جامع آمار و اطلاعات «دیدوان»

داشبورد زندهٔ بازار فلزات، فولاد، ارز، طلا/سکه، کامودیتی و کریپتو — به‌همراه آرشیو گزارش‌های منابع معتبر جهانی. این سند برای توسعه‌دهندهٔ بعدی نوشته شده؛ کل معماری، نحوهٔ کار، راه‌اندازی، امنیت و دام‌ها (gotchas) را پوشش می‌دهد. کامل بخوان.


۱) این سیستم چیست؟

یک اپلیکیشن سه‌بخشی:

بخش تکنولوژی پورت نقش
فرانت‌اند TanStack Start + React 19 + Vite 7 + Tailwind v4 5174 لندینگ، ورود/ثبت‌نام، داشبورد
بک‌اند (API) FastAPI + SQLite + Playwright 8000 اسکرپرها، API دادهٔ بازار، احراز هویت
پنل ادمین FastAPI (HTML درون‌خطی) 8001 بازبینی/تأیید کاربران، مدیریت توکن، سلامت سرویس‌ها، گزارش‌ها

دیتای بازار با اسکرپرهای پس‌زمینه جمع می‌شود و در SQLite ذخیره می‌شود (فقط مقادیرِ تغییرکرده — dedup). فرانت‌اند هر چند ثانیه از API می‌خواند و «زنده» نشان می‌دهد.


۲) ساختار پوشه‌ها

asianmetal-dashboard/
├─ src/                      # فرانت‌اند
│  ├─ routes/                # مسیرهای فایل‌محورِ TanStack
│  │  ├─ index.tsx           # لندینگ (LaserFlow، پنل زنده، گالری‌ها، …)
│  │  ├─ login.tsx           # ورود (کاراکترهای کارتونی + احراز واقعی)
│  │  ├─ register.tsx        # ثبت‌نام (→ pending)
│  │  ├─ dashboard.tsx       # داشبورد + همهٔ تب‌ها/کارت‌ها/چارت‌ها
│  │  └─ __root.tsx          # لایهٔ ریشه (RTL، فونت Vazirmatn، لود styles)
│  ├─ components/            # LaserFlow, CircularGallery, CardSwap, TubelightNavbar, …
│  ├─ components/ui/         # shadcn/ui
│  ├─ lib/                   # labels.ts، metals-data.ts، utils.ts
│  ├─ styles.css             # توکن‌های تم (oklch)، .tile/.glass/.panel، انیمیشن‌ها
│  └─ routeTree.gen.ts       # خودکار توسط TanStack (دستی ویرایش نکن)
│
├─ backend/                  # API + اسکرپرها
│  ├─ main.py                # اپ FastAPI، CORS/هدرها/ریت‌لیمیت، همهٔ اندپوینت‌ها، lifespan
│  ├─ db.py                  # اتصال SQLite + init_db (ساخت/مهاجرت جداول)
│  ├─ auth.py                # هشِ رمز (PBKDF2) + نشست‌های سمت‌سرور
│  ├─ currency_stream.py     # اسکرپِ ارز/طلا/سکهٔ داخلی (Playwright، هر ۶۰ث)
│  ├─ crypto_market.py       # کریپتو از API رایگانِ CoinGecko (هر ۶۰ث)
│  ├─ world_economy.py       # شاخص‌های کلانِ اقتصادهای بزرگ (هفتگی)
│  ├─ steel_stocks.py        # سهام شرکت‌های فولادی (companiesmarketcap، هر ۵ دقیقه)
│  ├─ live_stream.py         # کامودیتی لحظه‌ای (Yahoo Finance) روی WebSocket
│  ├─ reports.py             # اسکنِ آرشیو PDFِ گزارش‌ها (فایل‌سیستم)
│  └─ sync.py                # اسکریپت دستیِ سینکِ قیمت فلزات از API منبعِ بالادست
│
├─ admin/admin_app.py        # پنل ادمین (مستقل)
├─ vite.config.ts            # پورت ۵۱۷۴ + proxy (/api,/ws → :8000) + allowedHosts
├─ .gitignore                # شاملِ .env، __pycache__، *.db
└─ README.md                 # همین فایل

۳) راه‌اندازی محلی

پیش‌نیازها: Node 20+ (یا Bun)، Python 3.11+، و برای اسکرپرها playwright install chromium.

# نصب وابستگی‌های فرانت
npm install

# نصب وابستگی‌های پایتون (نمونه)
pip install fastapi uvicorn playwright requests yfinance pandas websockets
python -m playwright install chromium

اجرای هر سه سرویس (هرکدام در ترمینال جدا)

# ۱) بک‌اند (پورت 8000)
$env:PYTHONUTF8="1"; python -m uvicorn main:app --host 127.0.0.1 --port 8000 --app-dir backend

# ۲) فرانت‌اند (پورت 5174)
npm run dev

# ۳) پنل ادمین (پورت 8001) — ADMIN_PASSWORD الزامی است
$env:ADMIN_USER="admin"; $env:ADMIN_PASSWORD="یک‌رمزِ‌قوی"; python -m uvicorn admin_app:app --host 127.0.0.1 --port 8001 --app-dir admin

سپس: فرانت روی http://localhost:5174 ، پنل ادمین روی http://localhost:8001.


۴) متغیرهای محیطی

متغیر کجا پیش‌فرض توضیح
DB_PATH backend, admin مسیر محلی محل فایل SQLite (هر دو سرویس باید یکی باشند)
ASIANMETAL_TOKEN sync.py توکنِ API بالادست (یا از پنل ادمین در DB) — هیچ‌وقت در کد هاردکد نکن
ADMIN_USER / ADMIN_PASSWORD admin admin / الزامی احراز Basic پنل ادمین؛ بدون ADMIN_PASSWORD بالا نمی‌آید (fail-closed)
ALLOWED_ORIGINS backend localhost:5174,127.0.0.1:5174 originهای مجاز CORS (با کاما)
COOKIE_SECURE backend 0 در پروداکشن (HTTPS) روی 1 بگذار تا کوکیِ نشست Secure شود
REPORTS_DIR reports.py پوشهٔ آرشیو محل PDFهای گزارش (ساختار <منبع> - <دسته>/<file>.pdf)

۵) دیتابیس (SQLite)

init_db() در db.py جداول را می‌سازد و مهاجرتِ امن انجام می‌دهد (ستون‌ها را اگر نبودند ALTER می‌کند):

  • prices — تاریخچهٔ روزانهٔ قیمت فلزات: grp, category, title, date, low, mid, high (یکتا روی title,date). منبعِ تب «فلزات و فولاد».
  • users — کاربران: id, name, email, phone, organization, password_hash, status('pending'|'approved'|'rejected'), created_at.
  • sessions — نشست‌های سمت‌سرور: token, user_id, created_at, expires_at.
  • app_config — جفت‌های key/value (مثلاً asianmetal_token، هارت‌بیت اسکرپرها).
  • جداول اسکرپرها: currency_prices, gold_prices, coin_prices, te_prices, world_economy, steel_stocks — هرکدام آخرین/تاریخچهٔ مقادیر را نگه می‌دارند (dedup روی تغییر).

نکته: قیمت‌های لحظه‌ای (ارز/کریپتو/کامودیتی) عمدتاً در حافظه کش می‌شوند (_latest) و فقط تغییرها در DB ذخیره می‌شوند تا حجم کم بماند.


۶) اسکرپرها (در lifespan بک‌اند خودکار استارت می‌شوند)

ماژول منبع بازه جدول/خروجی
currency_stream نرخ داخلیِ ارز/طلا/سکه (URL در همان فایل) ۶۰ ثانیه currency_prices/gold_prices/coin_prices
crypto_market CoinGecko (API رایگان، بدون کلید) ۶۰ ثانیه حافظه (get_latest)
world_economy شاخص‌های کلانِ اقتصادهای بزرگ هفتگی world_economy
steel_stocks companiesmarketcap.com ۵ دقیقه steel_stocks
live_stream Yahoo Finance لحظه‌ای WebSocket /ws/live
reports فایل‌سیستمِ REPORTS_DIR کشِ ۱۰ دقیقه اسکنِ PDF

دامِ مهم: سایت‌های منبع قیمت‌ها را با JS لِیزی‌لود می‌کنند. اسکرپرهای Playwright بعد از goto یک wait_for_timeout(50009000) دارند؛ حذفش نکن وگرنه مقادیرِ کهنه/خالی خوانده می‌شود. هر اسکرپر هم try/except دارد تا یک خطای گذرا کلِ تسک پس‌زمینه را نکُشد.

sync.py یک اسکریپتِ دستی است (در lifespan نیست) که قیمت فلزات را از API بالادست می‌گیرد؛ توکن را از app_config یا env ASIANMETAL_TOKEN می‌خواند.


۷) اندپوینت‌های API (بک‌اند :8000)

عمومی (دادهٔ بازار): GET /api/tree, /api/history?title=&days=, /api/search?q=, /api/latest, /api/live, /api/currency, /api/gold, /api/coin, /api/world-economy, /api/steel-stocks, /api/crypto, /api/reports, /api/reports/files?folder=, /api/reports/file?folder=&name= (استریمِ inline PDF با گاردِ traversal)، WebSocket /ws/live.

احراز هویت: POST /api/register، POST /api/login، GET /api/me، POST /api/logout.

پنل ادمین :8001 (پشت HTTP Basic): /api/users، POST /api/users/{id}/approve|reject، GET|POST /api/token، /api/health، /api/test-scrape، /api/reports، /api/export?dataset=.


۸) احراز هویت و گردشِ تأیید (مهم)

اصل: هیچ اعتمادی به کلاینت نیست. ورود کاملاً سمت‌سرور تأیید می‌شود؛ نشست در کوکیِ httpOnly است، نه localStorage.

ثبت‌نام (نام، نام‌خانوادگی، سازمان، ایمیل، موبایل، رمز)
      │  POST /api/register  → رمز با PBKDF2 هش می‌شود، رکورد با status='pending'
      ▼
کاربر در وضعیت «در انتظار تأیید»  ──►  ادمین در پنل (تبِ کاربران) تأیید/رد می‌کند
      │                                    (POST /api/users/{id}/approve | reject)
      ▼
ورود  POST /api/login  → اگر approved بود: کوکیِ نشست (httpOnly, SameSite=Lax) ست می‌شود
      │   pending → 403 «در انتظار تأیید» ، rejected → 403 ، رمز غلط → 401
      ▼
داشبورد  → گاردِ سمت‌سرور: fetch('/api/me')؛ اگر 401 شد → ری‌دایرکت به /login
خروج  POST /api/logout → نشست از DB حذف + کوکی پاک می‌شود

نکات پیاده‌سازی:

  • هشِ رمز: auth.hash_password با hashlib.pbkdf2_hmac('sha256', ..., 200000) — بدونِ وابستگیِ خارجی. مقایسه با hmac.compare_digest.
  • توکنِ نشست: secrets.token_urlsafe(32)، انقضای ۷ روزه، در جدول sessions.
  • ریت‌لیمیتِ per-IP (در حافظه) روی register/login (۵ در دقیقه).
  • اعتبارسنجیِ Pydantic: فرمت/طولِ ایمیل و موبایل، حداقل ۸ کاراکترِ رمز.
  • رد کردنِ کاربر، نشست‌های فعالش را هم پاک می‌کند (دسترسی فوراً قطع).

۹) پنل ادمین (:8001)

  • ورود با HTTP Basic؛ ADMIN_PASSWORD الزامی است (بدونش بالا نمی‌آید).
  • تب‌ها: کاربران (لیست + تأیید/رد + سازمان/وضعیت)، توکن منبع داده (ذخیره/تستِ توکن بالادست)، سلامت سرویس‌ها (هارت‌بیتِ هر اسکرپر + تست اسکرپ)، گزارشات (دیتاست‌ها + خروجی CSV).
  • خروجیِ کاربران در UI با esc() فرار داده می‌شود (جلوگیری از XSSِ ذخیره‌شده).

۱۰) فرانت‌اند

  • مسیرها: / (لندینگ)، /login، /register، /dashboard.
  • داشبورد، تب‌ها (VIEW_NAV): بازار داخلی، کامودیتی، فلزات و فولاد (کاتالوگِ کارت + چارت)، اقتصاد جهانی (جدول حرارتی)، سهام فولادی، کریپتو، گزارش‌ها.
  • زبان بصری: تم لایتِ کرم + لهجهٔ کهربایی (فولاد مذاب)؛ توکن‌ها در styles.css (oklch). قیمت‌کارت‌ها سبکِ Spark-canvas (نمودار پس‌زمینه + رقم‌های غلتانِ Odometer + پیلِ درصد).
  • API نسبی است (const API = "") تا از طریق پراکسیِ Vite هم‌مبدأ کار کند → برای share فقط یک تونل لازم است.
  • RTL سراسری، فونت Vazirmatn. اعداد همه با همین فونت (نه مونو).

۱۱) اشتراک‌گذاری (ngrok)

چون vite.config.ts مسیرهای /api و /ws را به :8000 پراکسی می‌کند و فرانت از URLهای نسبی استفاده می‌کند، فقط یک تونل روی ۵۱۷۴ کافی است:

ngrok http 5174
# یا مستقیم باینری: & "$env:APPDATA\npm\node_modules\ngrok\bin\ngrok.exe" http 5174

نکته: شیمِ ngrok.ps1ی npm گاهی پورت را اشتباه پاس می‌دهد؛ اگر تونل به پورت غلط رفت، مستقیم ngrok.exe را صدا بزن. URL را از http://127.0.0.1:4040/api/tunnels هم می‌توانی بخوانی. (پلنِ رایگان: هر بار URL عوض می‌شود و یک صفحهٔ هشدارِ اولیه دارد.)


۱۲) امنیت — وضعیت و کارهای واجب

سخت‌سازی‌های انجام‌شده: CORS محدود، هدرهای امنیتی (nosniff, X-Frame-Options, Referrer-Policy)، اعتبارسنجی + ریت‌لیمیتِ ورودی‌ها، محدودیتِ کوئریِ history/search، گاردِ path-traversal روی استریمِ PDF، کوئری‌های پارامتری، احراز هویتِ سمت‌سرور با کوکیِ httpOnly، و حذفِ توکنِ هاردکد از کد.

واجب قبل از پروداکشن:

  1. توکنِ بالادست (SteelStatista) که قبلاً در git history لو رفته را باطل/تمدید کن؛ مقدارِ جدید فقط در پنل ادمین/env.
  2. ADMIN_PASSWORD قوی بگذار (پیش‌فرضِ ضعیف حذف شده).
  3. در HTTPS واقعی: COOKIE_SECURE=1 و ALLOWED_ORIGINS را به دامنهٔ واقعی محدود کن.
  4. پنل ادمین (:8001) را عمومی نکن (در تونل نگذار؛ فقط لوکال/VPN/SSH).

۱۳) دام‌ها و بدهیِ فنی (برای دفعهٔ بعد)

  • DB_PATH/مسیرها در db.py و admin_app.py پیش‌فرضِ ویندوزیِ مطلق دارند (شاملِ نام کاربری) — بهتره به مسیر نسبی/env منتقل شود.
  • وابستگی‌های package.json با ^ پین نشده‌اند؛ برای بیلدِ تکرارپذیر npm ci + پین.
  • فایل‌های __pycache__/*.pyc قبلاً کامیت شده‌اند؛ untrack کن: git rm -r --cached backend/__pycache__.
  • routeTree.gen.ts خودکار است — دستی ویرایش نکن (با اضافه‌شدن فایل route، خودِ Vite بازتولید می‌کند).
  • اسکرپرها به ساختار HTMLِ منابع وابسته‌اند؛ اگر منبع قالبش را عوض کند، سلکتورها/wait_for_timeout باید تنظیم شوند.