Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
238 lines
9.8 KiB
Markdown
238 lines
9.8 KiB
Markdown
# Phase 7 — User Accounts, Profiles, Media & Polish
|
|
|
|
## Status: Complete ✅
|
|
|
|
All work targets the `SERVER/` directory (live production copy).
|
|
|
|
Phase 7 has been expanded from profile polish into production CMS readiness: real delivery providers, scheduled publishing, media inventory, admin exports, and native systemd deployment. Docker is no longer the production deployment target.
|
|
|
|
---
|
|
|
|
## 7.1 — User Profiles & Usernames ✅
|
|
|
|
**Goal:** Every registered user gets a public profile page at `/profile/@username`.
|
|
|
|
### Schema changes
|
|
- `User.username` — unique, URL-safe slug (e.g. `coaxys`). Distinct from `User.name` (display name).
|
|
- `User.bio` — short biography (max 280 chars).
|
|
- `User.avatarUrl` — already added in Phase 6.5 (OAuth). Upload endpoint added here.
|
|
|
|
### Backend routes
|
|
- `GET /api/profile/:username` — public profile (name, bio, avatar, role, joined date, article count)
|
|
- `PUT /api/auth/profile` — update own profile (name, bio, username, avatarUrl)
|
|
- `POST /api/auth/avatar` — upload profile picture (JPEG/PNG → optional WebP conversion)
|
|
|
|
### Frontend
|
|
- New file: `teknav-profile.jsx` — `UserProfilePage` component
|
|
- Route: `/profile/@username` (e.g. `/profile/@coaxys`)
|
|
- Theme: warm terracotta / burnt orange / deep sand — NOT teal
|
|
- Shows avatar, display name, @username, bio, role badge, join date, article list (if writer/editor)
|
|
- `teknav-app.jsx` — route dispatch updated
|
|
- `teknav-auth.jsx` — profile settings section added to login page flow (accessible after login)
|
|
|
|
---
|
|
|
|
## 7.2 — Security & Auth Flows ✅
|
|
|
|
### Forgot password
|
|
- `POST /api/auth/forgot-password` — generates a reset token (Redis, 1h TTL) and sends the reset email through SMTP when configured
|
|
- `POST /api/auth/reset-password` — validates token + hashes new password
|
|
- Frontend: "فراموشی رمز عبور" button on login page → modal flow
|
|
|
|
### OTP (Phone)
|
|
- `POST /api/auth/otp/send` — generates and sends a 6-digit OTP through Kavenegar when `SMS_PROVIDER=kavenegar` and `SMS_API_KEY` are set
|
|
- `POST /api/auth/otp/verify` — verifies OTP, stores the phone number, and marks `phoneVerifiedAt`
|
|
- If SMS is not configured, the API returns a real `503` state instead of pretending delivery happened
|
|
|
|
### Email verification
|
|
- `POST /api/auth/email/verify/request` — creates a one-hour Redis token and sends a verification link through SMTP
|
|
- `POST /api/auth/email/verify/confirm` — validates the token for the current session and sets `emailVerifiedAt`
|
|
- Profile settings expose email/phone verification controls without mock success states
|
|
|
|
---
|
|
|
|
## 7.3 — Media: Images in Articles ✅
|
|
|
|
### Backend
|
|
- `POST /api/admin/uploads` already exists (Phase 5). Extended with:
|
|
- `?webp=1` query param → server-side WebP conversion using `sharp` (installed as optional dep)
|
|
- `sharp` is optional: if not installed, uploads proceed without conversion (no crash)
|
|
|
|
### Frontend — Article Editor (HTML mode)
|
|
- **HTML editor** added to `ArticleEditor` in admin panel (for writer/editor/admin roles)
|
|
- Toolbar: Bold, Italic, Heading, Link, Unordered List, Ordered List, Blockquote, Code, HR
|
|
- Image insert: inline upload → returns `/uploads/yyyy/mm/uuid.ext` URL inserted into HTML
|
|
- WebP conversion toggle in upload panel (off by default)
|
|
- Existing 3D diagram panel preserved alongside HTML editor (two tabs: "محتوا" / "نمودار")
|
|
- `MediaAsset` records are now created for admin uploads and profile avatars, including filename, URL, MIME type, size, dimensions, uploader, and created date
|
|
- `GET /api/admin/media` powers a real admin/editor media library
|
|
- `DELETE /api/admin/media/:id` removes unused media and blocks deletion while referenced by content or avatars
|
|
|
|
---
|
|
|
|
## 7.4 — Remove All Mock/Placeholder Data ✅
|
|
|
|
Files cleaned:
|
|
- `teknav-home.jsx` — StatsBar: "نویسنده فعال: ۸" → 3 (matches real seed authors)
|
|
- `teknav-admin.jsx`
|
|
- `writerStats` — hardcoded 3/1/1 articles → computed from real API data
|
|
- `editorStats` — `Math.min(published, 8)` → real `published` count
|
|
- Dashboard "آخرین فعالیتها" — now loaded only from API; no TeknavStore.getActivity() fallback faked data
|
|
- `ArticlesManagement` — TeknavStore fallback removed; shows empty state if API unavailable
|
|
- `teknav-data.js` — `activityLog` kept for legacy reference only (not shown in UI)
|
|
|
|
---
|
|
|
|
## 7.5 — UI Polish ✅
|
|
|
|
### Footer
|
|
- Copyright year: `۱۴۰۳` → `۱۴۰۵`
|
|
|
|
### Mobile responsiveness
|
|
- Header: hamburger menu already works; improved padding/font sizes
|
|
- Article cards: single column on < 480px
|
|
- Admin panel: sidebar collapses to bottom nav on mobile
|
|
- Login/signup form: better vertical spacing on small screens
|
|
- Profile page: single-column stack on mobile
|
|
|
|
### Profile page design language
|
|
- Warm terracotta (`#C46A4D`) / burnt orange (`#A8512E`) accents
|
|
- Deep sand card backgrounds (`#F4EFE6`)
|
|
- Unique green (`#2F8F6B`) for highlights (same as diagram accent)
|
|
- Avatar with warm circular border
|
|
- No teal in profile UI
|
|
|
|
---
|
|
|
|
## 7.6 — Email + OTP Infrastructure ✅
|
|
|
|
### Backend delivery
|
|
- `backend/src/lib/email.ts` sends through SMTP when `SMTP_HOST` is configured; otherwise it logs operator-visible output for non-production use
|
|
- `backend/src/lib/otp.ts` stores Redis OTPs and sends real SMS through Kavenegar
|
|
- Delivery failures are surfaced to the frontend and never shown as fake success
|
|
|
|
### Env vars (add to `/etc/teknav/backend.env`)
|
|
```
|
|
# Email
|
|
SMTP_HOST=
|
|
SMTP_PORT=587
|
|
SMTP_USER=
|
|
SMTP_PASS=
|
|
SMTP_FROM=no-reply@teknav.ir
|
|
|
|
# SMS / OTP
|
|
SMS_PROVIDER=kavenegar
|
|
SMS_API_KEY=
|
|
SMS_SENDER=
|
|
```
|
|
|
|
---
|
|
|
|
## 7.8 — Scheduling, Exports & Operations ✅
|
|
|
|
### Article scheduling
|
|
- `Article.scheduledAt` and status `زمانبندیشده` are supported in the editor
|
|
- `POST /api/admin/articles/:id/schedule` lets editor/admin roles schedule publication
|
|
- `backend/scripts/publish-due.mjs` publishes due articles and clears public cache keys
|
|
- `deploy/systemd/teknav-publish-due.timer` runs the publisher every 5 minutes
|
|
|
|
### Reporting
|
|
- `GET /api/admin/dashboard` includes real totals for users, authors, categories, tags, media, top articles, status counts, DB views, and Redis-buffered views
|
|
- `GET /api/admin/activity/export.csv` exports activity logs for admin users
|
|
|
|
### Native deployment
|
|
- systemd units live in `deploy/systemd/`
|
|
- log rotation lives in `deploy/logrotate/teknav`
|
|
- database backups run through `scripts/systemd-backup.sh` and `teknav-backup.timer`
|
|
- `DEPLOY.md` is now the canonical non-Docker production runbook for `www.teknav.ir`
|
|
|
|
### Staff credentials
|
|
- `ACCOUNTS.md` contains operator-facing initial credentials and is ignored by git
|
|
- nginx blocks `/ACCOUNTS.md`
|
|
- `backend/prisma/credentials.json` seeds the login records
|
|
- Three writer-admin accounts were added for آرسام صباغ, رادمان قلیچی, and سیداحمدرضا محجوب
|
|
- Every seeded user now receives a username; login accepts email or `@username`
|
|
- Signup collects display name, username, and password; profile settings allow users of any role to edit display name, username, bio, verification data, and password
|
|
|
|
---
|
|
|
|
## 7.7 — WebP Image Optimization ✅
|
|
|
|
- `sharp` installed as optional dependency in `backend/package.json`
|
|
- Upload route (`POST /api/admin/uploads`) gains `?webp=1` query param
|
|
- If `sharp` is available and `webp=1`: converts JPEG/PNG → WebP (quality 82), saves as `.webp`
|
|
- Admin upload panel shows "تبدیل به WebP" checkbox (off by default)
|
|
- Profile avatar upload automatically converts to WebP if sharp is available
|
|
|
|
---
|
|
|
|
## Phase 7 Checklist
|
|
|
|
### Backend
|
|
- [x] `User.username` + `User.bio` in schema
|
|
- [x] `GET /api/profile/:username`
|
|
- [x] `PUT /api/auth/profile`
|
|
- [x] `POST /api/auth/avatar`
|
|
- [x] `POST /api/auth/forgot-password`
|
|
- [x] `POST /api/auth/reset-password`
|
|
- [x] `POST /api/auth/otp/send`
|
|
- [x] `POST /api/auth/otp/verify`
|
|
- [x] `POST /api/auth/email/verify/request`
|
|
- [x] `POST /api/auth/email/verify/confirm`
|
|
- [x] WebP upload option (`?webp=1`)
|
|
- [x] `MediaAsset` model + media library APIs
|
|
- [x] Article scheduling API + due publisher script
|
|
- [x] Activity CSV export
|
|
- [x] `backend/src/lib/email.ts` SMTP sender
|
|
- [x] `backend/src/lib/otp.ts`
|
|
- [x] `.env.prod.example` updated with SMTP + SMS vars
|
|
- [x] Writer-admin seed accounts added to `backend/prisma/credentials.json`
|
|
- [x] Login by email or `@username`
|
|
- [x] Profile password update API
|
|
|
|
### Frontend
|
|
- [x] `teknav-profile.jsx` — public profile page
|
|
- [x] `/profile/@username` route in `teknav-app.jsx`
|
|
- [x] Forgot password button + modal in `LoginPage`
|
|
- [x] Profile picture upload in settings
|
|
- [x] HTML editor in `ArticleEditor`
|
|
- [x] Image insertion in articles
|
|
- [x] WebP toggle in upload panels
|
|
- [x] Media library panel with real API data only
|
|
- [x] Scheduled publish controls in article editor
|
|
- [x] Activity CSV export link
|
|
- [x] Email/phone verification controls in profile settings
|
|
- [x] Username field on signup
|
|
- [x] Password editing in profile settings
|
|
- [x] Footer year → 1405
|
|
- [x] StatsBar "نویسنده فعال" → 3
|
|
- [x] Mock data removed from admin panel
|
|
- [x] Mobile responsiveness improvements
|
|
|
|
### Docs
|
|
- [x] `MEMORY.md` updated
|
|
- [x] `ARCH.md` updated
|
|
- [x] `SECURITY.md` updated
|
|
- [x] `DEPLOY.md` updated for native systemd deployment and SMTP/SMS vars
|
|
- [x] `PHASE7.md` written
|
|
- [x] `ACCOUNTS.md` added, gitignored, and nginx-blocked
|
|
|
|
---
|
|
|
|
## Dependencies Added
|
|
|
|
| Package | Location | Purpose |
|
|
|---|---|---|
|
|
| `sharp` | `backend` (optional) | WebP image conversion |
|
|
| `nodemailer` | `backend` | SMTP email delivery |
|
|
|
|
Install on server: `cd backend && npm install sharp` (or it's included if added to `package.json`)
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- Phone OTP requires Kavenegar credentials on the Linux server.
|
|
- Forgot-password and email verification require SMTP credentials on the Linux server.
|
|
- `sharp` is optional: if not installed, uploads work normally as JPEG/PNG. WebP toggle in the UI gracefully falls back.
|