created auth system

This commit is contained in:
sdarbinyan
2026-02-28 17:18:24 +04:00
parent 86d11364f0
commit 6689acbe57
28 changed files with 1254 additions and 674 deletions

View File

@@ -1,168 +1,266 @@
# Backend API Changes Required
# API Changes Required for Backend
## Cart Quantity Support
## Overview
### 1. Add Quantity to Cart Items
Frontend has been updated with two new features:
1. **Region/Location system** — catalog filtering by region
2. **Auth/Login system** — Telegram-based authentication required before payment
**Current GET /cart Response:**
```json
[
{
"itemID": 123,
"name": "Product Name",
"price": 100,
"currency": "RUB",
...other item fields
}
]
```
**NEW Required Response:**
```json
[
{
"itemID": 123,
"name": "Product Name",
"price": 100,
"currency": "RUB",
"quantity": 2, // <-- ADD THIS FIELD
...other item fields
}
]
```
### 2. POST /cart - Add Item to Cart
**Current Request:**
```json
{
"itemID": 123
}
```
**NEW Request (with optional quantity):**
```json
{
"itemID": 123,
"quantity": 1 // Optional, defaults to 1 if not provided
}
```
**Behavior:**
- If item already exists in cart, **increment** the quantity by the provided amount
- If item doesn't exist, add it with the specified quantity
### 3. PATCH /cart - Update Item Quantity (NEW ENDPOINT)
**Request:**
```json
{
"itemID": 123,
"quantity": 5 // New quantity value (not increment, but absolute value)
}
```
**Response:**
```json
{
"message": "Cart updated successfully"
}
```
**Behavior:**
- Set the quantity to the exact value provided
- If quantity is 0 or negative, remove the item from cart
### 4. Payment Endpoints - Include Quantity
**POST /payment/create**
Update the items array to include quantity:
**Current:**
```json
{
"amount": 1000,
"currency": "RUB",
"items": [
{
"itemID": 123,
"price": 500,
"name": "Product Name"
}
]
}
```
**NEW:**
```json
{
"amount": 1000,
"currency": "RUB",
"items": [
{
"itemID": 123,
"price": 500,
"name": "Product Name",
"quantity": 2 // <-- ADD THIS FIELD
}
]
}
```
### 5. Email Purchase Confirmation
**POST /purchase-email**
Update items to include quantity:
**NEW:**
```json
{
"email": "user@example.com",
"telegramUserId": "123456",
"items": [
{
"itemID": 123,
"name": "Product Name",
"price": 500,
"currency": "RUB",
"quantity": 2 // <-- ADD THIS FIELD
}
]
}
```
## Future: Filters & Sorting (To Be Discussed)
### GET /category/{categoryID}
Add query parameters for filtering and sorting:
**Proposed Query Parameters:**
- `sort`: Sort order (e.g., `price_asc`, `price_desc`, `rating_desc`, `name_asc`)
- `minPrice`: Minimum price filter
- `maxPrice`: Maximum price filter
- `minRating`: Minimum rating filter (1-5)
- `count`: Number of items per page (already exists)
- `skip`: Offset for pagination (already exists)
**Example:**
```
GET /category/5?sort=price_asc&minPrice=100&maxPrice=500&minRating=4&count=20&skip=0
```
**Response:** Same as current (array of items)
Base URLs:
- Dexar: `https://api.dexarmarket.ru:445`
- Novo: `https://api.novo.market:444`
---
## Summary
## 1. Region / Location Endpoints
**Required NOW:**
1. Add `quantity` field to cart item responses
2. Support `quantity` parameter in POST /cart
3. Create new PATCH /cart endpoint for updating quantities
4. Include `quantity` in payment and email endpoints
### 1.1 `GET /regions` — List available regions
**Future (After Discussion):**
- Sorting and filtering query parameters for category items endpoint
Returns the list of regions where the marketplace operates.
**Response** `200 OK`
```json
[
{
"id": "moscow",
"city": "Москва",
"country": "Россия",
"countryCode": "RU",
"timezone": "Europe/Moscow"
},
{
"id": "spb",
"city": "Санкт-Петербург",
"country": "Россия",
"countryCode": "RU",
"timezone": "Europe/Moscow"
},
{
"id": "yerevan",
"city": "Ереван",
"country": "Армения",
"countryCode": "AM",
"timezone": "Asia/Yerevan"
}
]
```
**Region object:**
| Field | Type | Required | Description |
|---------------|--------|----------|------------------------------|
| `id` | string | yes | Unique region identifier |
| `city` | string | yes | City name (display) |
| `country` | string | yes | Country name (display) |
| `countryCode` | string | yes | ISO 3166-1 alpha-2 code |
| `timezone` | string | no | IANA timezone string |
> If this endpoint is unavailable, the frontend falls back to 6 hardcoded regions (Moscow, SPB, Yerevan, Minsk, Almaty, Tbilisi).
---
### 1.2 Region Query Parameter on Existing Endpoints
The following **existing** endpoints now accept an optional `?region=` query parameter:
| Endpoint | Example |
|---------------------------------|----------------------------------------------|
| `GET /category` | `GET /category?region=moscow` |
| `GET /category/:id` | `GET /category/5?count=50&skip=0&region=spb` |
| `GET /item/:id` | `GET /item/123?region=yerevan` |
| `GET /searchitems` | `GET /searchitems?search=phone&region=moscow` |
| `GET /randomitems` | `GET /randomitems?count=5&region=almaty` |
**Behavior:**
- If `region` param is **present** → return only items/categories available in that region
- If `region` param is **absent** → return all items globally (current behavior, no change)
- The `region` value matches the `id` field from the `/regions` response
---
## 2. Auth / Login Endpoints
Authentication is **Telegram-based** with **cookie sessions** (HttpOnly, Secure, SameSite=None).
All auth endpoints must support CORS with `credentials: true`.
### 2.1 `GET /auth/session` — Check current session
Called on every page load to check if the user has an active session.
**Request:**
- Cookies: session cookie (set by backend)
- CORS: `withCredentials: true`
**Response `200 OK`** (authenticated):
```json
{
"sessionId": "sess_abc123",
"telegramUserId": 123456789,
"username": "john_doe",
"displayName": "John Doe",
"active": true,
"expiresAt": "2026-03-01T12:00:00Z"
}
```
**Response `200 OK`** (expired session):
```json
{
"sessionId": "sess_abc123",
"telegramUserId": 123456789,
"username": "john_doe",
"displayName": "John Doe",
"active": false,
"expiresAt": "2026-02-27T12:00:00Z"
}
```
**Response `401 Unauthorized`** (no session / invalid cookie):
```json
{
"error": "No active session"
}
```
**AuthSession object:**
| Field | Type | Required | Description |
|------------------|---------|----------|------------------------------------------|
| `sessionId` | string | yes | Unique session ID |
| `telegramUserId` | number | yes | Telegram user ID |
| `username` | string? | no | Telegram @username (can be null) |
| `displayName` | string | yes | User display name (first_name + last_name) |
| `active` | boolean | yes | Whether session is currently valid |
| `expiresAt` | string | yes | ISO 8601 expiration datetime |
---
### 2.2 `GET /auth/telegram/callback` — Telegram bot auth callback
This is the URL the Telegram bot redirects to after the user starts the bot.
**Flow:**
1. Frontend generates link: `https://t.me/{botUsername}?start=auth_{encodedCallbackUrl}`
2. User clicks → opens Telegram → starts the bot
3. Bot sends user data to this callback endpoint
4. Backend creates session, sets `Set-Cookie` header
5. Frontend polls `GET /auth/session` every 3 seconds to detect when session becomes active
**Request** (from Telegram bot / webhook):
```json
{
"id": 123456789,
"first_name": "John",
"last_name": "Doe",
"username": "john_doe",
"photo_url": "https://t.me/i/userpic/...",
"auth_date": 1709100000,
"hash": "abc123def456..."
}
```
**Response:** Should set a session cookie and return:
```json
{
"sessionId": "sess_abc123",
"message": "Authenticated successfully"
}
```
**Cookie requirements:**
| Attribute | Value | Notes |
|------------|----------------|------------------------------------------|
| `HttpOnly` | `true` | Not accessible via JS |
| `Secure` | `true` | HTTPS only |
| `SameSite` | `None` | Required for cross-origin (API ≠ frontend) |
| `Path` | `/` | |
| `Max-Age` | `86400` (24h) | Or as needed |
| `Domain` | API domain | |
> **Important:** Since the API domain differs from the frontend domain, `SameSite=None` + `Secure=true` is required for the cookie to be sent cross-origin.
---
### 2.3 `POST /auth/logout` — End session
**Request:**
- Cookies: session cookie
- CORS: `withCredentials: true`
- Body: `{}` (empty)
**Response `200 OK`:**
```json
{
"message": "Logged out"
}
```
Should clear/invalidate the session cookie.
---
## 3. CORS Configuration
For auth cookies to work cross-origin, the backend CORS config must include:
```
Access-Control-Allow-Origin: https://dexarmarket.ru (NOT *)
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: GET, POST, PATCH, DELETE, OPTIONS
```
> `Access-Control-Allow-Origin` **cannot** be `*` when `Allow-Credentials: true`. Must be the exact frontend origin.
For Novo, also allow `https://novo.market`.
---
## 4. Session Refresh Behavior
The frontend automatically re-checks the session **60 seconds before `expiresAt`**. If the backend supports session extension (sliding expiration), it can re-set the cookie with a fresh `Max-Age` on every `GET /auth/session` call.
---
## 5. Auth Gate — Checkout Flow
The checkout button (`POST /cart` payment) now requires authentication:
- If the user is **not logged in** → frontend shows a Telegram login dialog instead of proceeding
- If the user **is logged in** → checkout proceeds normally
- The session cookie is sent automatically with the payment request
No backend changes needed for the payment endpoint itself — just ensure it reads the session cookie if needed for order association.
---
## Summary of New Endpoints
| Method | Path | Purpose | Auth Required |
|--------|----------------------------|-----------------------------|---------------|
| `GET` | `/regions` | List available regions | No |
| `GET` | `/auth/session` | Check current session | Cookie |
| `GET` | `/auth/telegram/callback` | Telegram bot auth callback | No (from bot) |
| `POST` | `/auth/logout` | End session | Cookie |
## Summary of Modified Endpoints
| Method | Path | Change |
|--------|-------------------|---------------------------------------|
| `GET` | `/category` | Added optional `?region=` param |
| `GET` | `/category/:id` | Added optional `?region=` param |
| `GET` | `/item/:id` | Added optional `?region=` param |
| `GET` | `/searchitems` | Added optional `?region=` param |
| `GET` | `/randomitems` | Added optional `?region=` param |
---
## Telegram Bot Setup
Each brand needs its own bot:
- **Dexar:** `@dexarmarket_bot`
- **Novo:** `@novomarket_bot`
The bot should:
1. Listen for `/start auth_{callbackUrl}` command
2. Extract the callback URL
3. Send the user's Telegram data (id, first_name, username, etc.) to that callback URL
4. The callback URL is `{apiUrl}/auth/telegram/callback`