- بکاند: ستون role برای admin_users (admin/creator) + author_id برای مقالهها - نقشگارد روی کل روتر مدیریتی: creator فقط لیست/ساخت/خواندن/ویرایش پیشنویسهای «خودش» را میبیند؛ بقیهٔ مسیرهای مدیریتی ۴۰۳ - ساخت توسط creator همیشه پیشنویس است و ویرایشش هرگز منتشر نمیشود (حتی تلاش برای publish در payload نادیده گرفته میشود) - حذف/ترتیببندی/پیامها/خبرنامه/سایر بخشها برای creator ممنوع - لاگین نقش را برمیگرداند؛ پنل: AdminBar نویسنده فقط «نوشتن مقاله» + زبان ویرایش + رمز + خروج دارد؛ دکمههای انتشار/حذف مقاله فقط برای admin - ورود creator مستقیم به صفحهٔ نوشتن مقاله هدایت میشود
بکاند گروه ساختمانی آرامش (Aramesh Building Group API)
بکاند سایت گروه ساختمانی آرامش — ساختهشده با FastAPI + PostgreSQL + SQLAlchemy 2 + JWT + MinIO (ذخیره تصاویر) + Traefik (مسیریابی).
امکانات
- API عمومی محتوا: برند، منو، هیرو، داستان، تیتر بخشها، هیرو صفحات، خدمات، پروژهها، مقالات، نظرات مشتریان، سوالات متداول، تیم، تایملاین، آمار، چرا آرامش، قبل/بعد، مدلهای سرمایهگذاری، مراحل کار، دفاتر، گالری، فرم تماس، خبرنامه و فوتر — تمام متنهای سایت در دیتابیس است
- فرم تماس: ثبت پیام مشتریان از سایت (
POST /api/contact) - خبرنامه: عضویت و مدیریت مشترکین (
POST /api/newsletter) - پنل مدیریت: ورود با نام کاربری/رمز عبور و دریافت توکن JWT، سپس CRUD کامل همه محتواها، مدیریت پیامهای تماس و مشترکین
- آپلود تصویر:
POST /api/admin/upload— فایل در MinIO ذخیره و URL نسبی/media/...برمیگردد - Seed خودکار: همه محتوای فعلی سایت با یک دستور در دیتابیس قرار میگیرد (فقط جدولهای خالی پر میشوند — ارتقا بدون از دست رفتن داده)
- مستندات تعاملی Swagger در مسیر
/docs
راهاندازی
۱. پیشنیازها
- Python 3.11 یا جدیدتر
- PostgreSQL در حال اجرا (پورت پیشفرض 5432)
۲. نصب وابستگیها
cd arameshplaza-backend
python -m venv .venv
# ویندوز
.venv\Scripts\activate
# لینوکس / مک
source .venv/bin/activate
pip install -r requirements.txt
۳. تنظیمات
فایل .env.example را به نام .env کپی کنید و مقادیر را تنظیم کنید:
cp .env.example .env # لینوکس / مک
copy .env.example .env # ویندوز
مهمترین تنظیم DATABASE_URL است:
DATABASE_URL=postgresql+psycopg://postgres:YOUR_PASSWORD@localhost:5432/arameshplaza_api
۴. ساخت دیتابیس و Seed
# ساخت دیتابیس (یکبار):
psql -U postgres -c "CREATE DATABASE arameshplaza_api;"
# ساخت جداول + وارد کردن محتوای سایت + ساخت ادمین پیشفرض:
python -m app.seed
# بازنشانی کامل دادهها در صورت نیاز:
python -m app.seed --force
۵. اجرا
uvicorn app.main:app --reload
سپس:
- مستندات API: http://localhost:8000/docs
- بررسی سلامت: http://localhost:8000/api/health
ورود به پنل مدیریت
POST /api/auth/login
{ "username": "admin", "password": "aramesh123" }
پاسخ شامل access_token است. توکن را در هدر همه درخواستهای مدیریتی قرار دهید:
Authorization: Bearer <access_token>
نام کاربری و رمز عبور پیشفرض از تنظیمات
.envخوانده میشود — حتماً در محیط تولید تغییرشان دهید.
تغییر رمز (با توکن):
POST /api/auth/change-password
{ "current_password": "...", "new_password": "..." }
فهرست انتهاپوینتها
عمومی (بدون نیاز به توکن)
| متد | مسیر | توضیح |
|---|---|---|
| GET | /api/health |
وضعیت سرور |
| GET | /api/brand |
اطلاعات برند و تماس |
| GET | /api/services |
خدمات |
| GET | /api/projects |
همه پروژهها |
| GET | /api/projects/{slug} |
جزئیات یک پروژه |
| GET | /api/articles |
مقالههای منتشرشده (پیشنویس نمیآید) |
| GET | /api/articles/{slug} |
جزئیات یک مقاله منتشرشده |
| GET | /api/testimonials |
نظرات مشتریان |
| GET | /api/faqs |
سوالات متداول |
| GET | /api/team |
اعضای تیم |
| GET | /api/timeline |
تایملاین شرکت |
| GET | /api/stats |
آمار |
| GET | /api/why-us |
چرا گروه ساختمانی آرامش |
| GET | /api/before-after |
بخش قبل/بعد |
| GET | /api/site |
همه محتوا در یک درخواست |
| POST | /api/contact |
ثبت پیام تماس |
| POST | /api/newsletter |
عضویت در خبرنامه |
| POST | /api/auth/login |
ورود ادمین و دریافت توکن — بعد از ۵ تلاش ناموفق در ۱۵ دقیقه، 429 |
| GET | /robots.txt |
قوانین خزندهها |
| GET | /sitemap.xml |
نقشه سایت — مقاله/پروژههای منتشرشده |
| GET | /blog/{slug} |
HTML صفحه مقاله با متای سئوی تزریقشده |
| GET | /projects/{slug} |
HTML صفحه پروژه با متای سئوی تزریقشده |
مدیریت (نیاز به توکن Bearer)
برای هر یک از این مسیرها، CRUD کامل در دسترس است:
brand، services، projects، articles، testimonials، faqs، team، timeline، stats، why-us، before-after
| متد | مسیر | توضیح |
|---|---|---|
| GET/POST | /api/admin/{resource} |
لیست / ساخت |
| GET/PUT/DELETE | /api/admin/{resource}/{id} |
دریافت / ویرایش کامل / حذف |
| PATCH | /api/admin/{resource}/{id} |
ویرایش جزئی — فقط فیلدهای ارسالشده بهروزرسانی میشوند |
| POST | /api/admin/{resource}/reorder |
ذخیره ترتیب: {"ids": [3, 1, 2, ...]} |
| GET | /api/admin/messages |
پیامهای تماس (با ?unread_only=true فقط خواندهنشدهها) |
| PATCH | /api/admin/messages/{id} |
تغییر وضعیت خواندهشدن |
| DELETE | /api/admin/messages/{id} |
حذف پیام |
| GET | /api/admin/subscribers |
مشترکین خبرنامه |
| DELETE | /api/admin/subscribers/{id} |
حذف مشترک |
| POST | /api/admin/upload |
آپلود تصویر (multipart، حداکثر ۱۰MB — jpg/png/webp/gif/avif) → {"url": "/media/..."} |
بدنه مقاله — سند TipTap
body مقاله یک سند ساختاریافته TipTap (ProseMirror JSON) است: {"type": "doc", "content": [...]}.
- فقط ساختار اعتبارسنجی میشود (
type: "doc"+contentلیست)؛ امنیت رندر بر عهده رندر استاتیک TipTap در فرانتاند است که فقط تگهای شناختهشده تولید میکند - ردیفهای قدیمی (لیست پاراگراف) با مهاجرت idempotent
migrate_article_bodiesدر startup/seed خودکار به سند تبدیل میشوند - seed هم بدنههای لیستی را قبل از درج تبدیل میکند
| POST/PATCH | /api/admin/seo-meta | عنوان و توضیح متای صفحات — page_key: home / about / services / projects / investment / blog / faq / contact |
منابعی که reorder دارند (ستون position): services، projects، articles، testimonials، faqs، team، timeline، stats، why-us، investment-models، process-steps، offices، gallery، nav. ستون با مهاجرت سبک idempotent هنگام startup/seed به دیتابیسهای موجود اضافه میشود.
تصاویر و MinIO
فایلهای آپلودشده در باکت aramesh-media روی MinIO ذخیره میشوند و با مسیر نسبی /media/<سال>/<ماه>/<فایل> برگردانده میشوند. Traefik مسیر /media را به MinIO میبرد، پس URLها مستقل از بکاند ذخیرهسازی هستند — بعداً برای مهاجرت به R2/S3 فقط تنظیمات را عوض کنید، نه محتوای دیتابیس را.
- کنسول MinIO:
http://localhost:9001(کاربر/رمز ازMINIO_ROOT_USER/MINIO_ROOT_PASSWORDدر compose) - تصاویر عمومی و قابل نمایشاند؛ آپلود فقط با توکن ادمین انجام میشود.
اتصال به فرانتاند
در پروژه React (پوشه ArameshPlaza)، فایل src/config.ts آدرس بکاند را نگه میدارد:
export const API_URL = import.meta.env.VITE_API_URL ?? 'http://localhost:8000'
در محیط تولید مقدار VITE_API_URL را روی آدرس عمومی API تنظیم کنید و مطمئن شوید آدرس سایت در CORS_ORIGINS فایل .env بکاند قرار دارد.
ساختار پروژه
app/
├── main.py # نقطه ورود FastAPI، CORS، ثبت روترها
├── config.py # تنظیمات از .env
├── database.py # اتصال PostgreSQL و نشستها
├── models.py # مدلهای SQLAlchemy
├── schemas.py # اسکیماهای Pydantic (ورودی/خروجی)
├── auth.py # هش رمز عبور و JWT
├── seed.py # اسکریپت seed
├── seed_data.py # دادههای اولیه سایت
└── api/
├── public.py # انتهای عمومی محتوا
├── forms.py # فرم تماس و خبرنامه
└── admin.py # ورود و پنل مدیریت