simpler-auth+no-overlay
This commit is contained in:
@@ -52,27 +52,56 @@ filename.ext
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- `401 Unauthorized` - неверный токен
|
||||
- `413 Payload Too Large` - превышена квота
|
||||
- `400 Bad Request` - нет файлов или все файлы пустые
|
||||
- `401 Unauthorized` - неверный или отсутствующий токен
|
||||
- `413 Payload Too Large` - превышена квота пользователя или лимит размера файла
|
||||
- `415 Unsupported Media Type` - неподдерживаемый тип файла
|
||||
- `500 Internal Server Error` - ошибка загрузки в S3 или обновления квоты
|
||||
|
||||
### 3. Получение файлов
|
||||
### 3. Получение информации о текущем пользователе
|
||||
|
||||
#### GET /
|
||||
Получает информацию о залогиненном пользователе с данными о квоте.
|
||||
|
||||
**Заголовки:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Ответ:**
|
||||
```json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"username": "john_doe",
|
||||
"token_type": "session",
|
||||
"created_at": "1642248600",
|
||||
"last_activity": "1642335000",
|
||||
"auth_data": "{\"roles\": [\"user\"]}",
|
||||
"device_info": "{\"platform\": \"web\"}",
|
||||
"quota": {
|
||||
"current_quota": 1073741824,
|
||||
"max_quota": 5368709120,
|
||||
"usage_percentage": 20.0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Ошибки:**
|
||||
- `401 Unauthorized` - неверный или отсутствующий токен
|
||||
|
||||
### 4. Получение файлов
|
||||
|
||||
#### GET /{filename}
|
||||
Получает файл по имени.
|
||||
|
||||
**Параметры запроса:**
|
||||
- `s=<shout_id>` - добавляет оверлей с данными shout (только для изображений)
|
||||
|
||||
**Примеры:**
|
||||
```
|
||||
GET /image.jpg
|
||||
GET /image.jpg?s=123
|
||||
GET /image_300.jpg
|
||||
GET /image_300.jpg/webp
|
||||
```
|
||||
|
||||
### 4. Управление квотами
|
||||
### 5. Управление квотами
|
||||
|
||||
#### GET /quota
|
||||
Получает информацию о квоте пользователя.
|
||||
@@ -139,10 +168,10 @@ GET /quota?user_id=user123
|
||||
| Код | Описание |
|
||||
|-----|----------|
|
||||
| 200 | Успешный запрос |
|
||||
| 400 | Неверные параметры запроса |
|
||||
| 400 | Неверные параметры запроса или нет файлов |
|
||||
| 401 | Неавторизованный доступ |
|
||||
| 404 | Файл не найден |
|
||||
| 413 | Превышена квота |
|
||||
| 413 | Превышена квота пользователя или лимит размера файла (500 МБ) |
|
||||
| 415 | Неподдерживаемый тип файла |
|
||||
| 500 | Внутренняя ошибка сервера |
|
||||
|
||||
@@ -155,6 +184,12 @@ curl -X POST http://localhost:8080/ \
|
||||
-F "file=@image.jpg"
|
||||
```
|
||||
|
||||
### Получение информации о пользователе
|
||||
```bash
|
||||
curl -H "Authorization: Bearer your-token" \
|
||||
http://localhost:8080/
|
||||
```
|
||||
|
||||
### Получение миниатюры
|
||||
```bash
|
||||
curl http://localhost:8080/image_300.jpg
|
||||
|
||||
@@ -76,7 +76,7 @@ sequenceDiagram
|
||||
|
||||
Client->>Quoter: POST / (file + token)
|
||||
Quoter->>Core API: Validate token
|
||||
Core API-->>Quoter: User ID
|
||||
Core API-->>Quoter: Author ID
|
||||
Quoter->>Redis: Check quota
|
||||
Redis-->>Quoter: Current quota
|
||||
Quoter->>S3: Upload file
|
||||
|
||||
@@ -196,7 +196,7 @@ After=network.target redis.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=quoter
|
||||
Author=quoter
|
||||
Group=quoter
|
||||
WorkingDirectory=/opt/quoter
|
||||
Environment=REDIS_URL=redis://localhost:6379
|
||||
|
||||
@@ -215,7 +215,7 @@ use log::{debug, info, warn, error};
|
||||
// В коде
|
||||
debug!("Processing file: {}", filename);
|
||||
info!("File uploaded successfully");
|
||||
warn!("User quota is getting low: {} bytes", quota);
|
||||
warn!("Author quota is getting low: {} bytes", quota);
|
||||
error!("Failed to upload file: {}", e);
|
||||
```
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ lazy_static! {
|
||||
|
||||
pub static ref QUOTA_USAGE: Histogram = Histogram::new(
|
||||
"quoter_quota_usage_bytes",
|
||||
"User quota usage in bytes"
|
||||
"Author quota usage in bytes"
|
||||
).unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
298
docs/upload-api-detailed.md
Normal file
298
docs/upload-api-detailed.md
Normal file
@@ -0,0 +1,298 @@
|
||||
# 📤 API загрузки файлов с квотами - Точная документация
|
||||
|
||||
## Обзор
|
||||
|
||||
Quoter предоставляет API для загрузки файлов с системой квот и автоматической обработкой различных типов медиа.
|
||||
|
||||
## Базовый URL
|
||||
```
|
||||
http://localhost:8080
|
||||
```
|
||||
|
||||
## Аутентификация
|
||||
Все эндпоинты загрузки требуют JWT токен в заголовке:
|
||||
```
|
||||
Authorization: Bearer <jwt-token>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📤 Загрузка файлов (УЛУЧШЕННАЯ ВЕРСИЯ)
|
||||
|
||||
### POST /
|
||||
|
||||
Загружает файл(ы) в S3-совместимое хранилище (Storj) с улучшенной проверкой квот и валидацией.
|
||||
|
||||
#### Заголовки запроса
|
||||
```http
|
||||
Authorization: Bearer <jwt-token>
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
#### Параметры
|
||||
- **file** (required) - файл(ы) для загрузки в multipart/form-data
|
||||
|
||||
#### Поддерживаемые форматы
|
||||
Автоматическое определение MIME-типа из содержимого файла:
|
||||
- **Изображения**: JPEG, PNG, GIF, WebP, HEIC
|
||||
- **Видео**: MP4, WebM, AVI
|
||||
- **Аудио**: MP3, WAV, OGG
|
||||
- **Документы**: PDF
|
||||
|
||||
#### 🔄 Улучшенная логика обработки
|
||||
|
||||
1. **Проверка авторизации** - извлечение и валидация JWT токена
|
||||
2. **Получение текущей квоты** пользователя из Redis
|
||||
3. **Предварительная проверка квоты** - пользователь не достиг лимита
|
||||
4. **Streaming чтение файла** с проверками на каждом chunk:
|
||||
- Проверка лимита одного файла (500 МБ)
|
||||
- Проверка общей квоты пользователя
|
||||
5. **Пропуск пустых файлов**
|
||||
6. **Определение MIME-типа** из содержимого (не из расширения!)
|
||||
7. **Генерация UUID имени** файла с правильным расширением
|
||||
8. **Загрузка в Storj S3**
|
||||
9. **Обновление квоты** пользователя
|
||||
10. **Сохранение метаданных** в Redis (с обработкой ошибок)
|
||||
|
||||
#### Ограничения
|
||||
|
||||
- **Максимальная квота на пользователя**: 5 ГБ (5,368,709,120 байт)
|
||||
- **Максимальный размер одного файла**: 500 МБ (524,288,000 байт)
|
||||
- **Проверка квоты происходит во время чтения** (streaming)
|
||||
- **Поддержка множественных файлов** в одном запросе
|
||||
|
||||
#### Успешные ответы
|
||||
|
||||
**Один файл:**
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/plain
|
||||
|
||||
```
|
||||
|
||||
**Несколько файлов:**
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
#### Коды ошибок (ИСПРАВЛЕННЫЕ)
|
||||
|
||||
| Код | Условие | Описание |
|
||||
|-----|---------|----------|
|
||||
| **400 Bad Request** | Нет файлов | `"No files provided or all files were empty"` |
|
||||
| **401 Unauthorized** | Отсутствует токен | `"Authorization token required"` |
|
||||
| **401 Unauthorized** | Неверный токен | `"Invalid authorization token"` |
|
||||
| **413 Payload Too Large** | 🎯 Превышена квота | `"Author quota limit exceeded"` |
|
||||
| **413 Payload Too Large** | 🎯 Большой файл | `"Single file size limit exceeded"` |
|
||||
| **413 Payload Too Large** | 🎯 Превышение при загрузке | `"Author quota limit would be exceeded"` |
|
||||
| **415 Unsupported Media Type** | Неподдерживаемый MIME | `"Unsupported file format"` |
|
||||
| **415 Unsupported Media Type** | Нет расширения для MIME | `"Unsupported content type"` |
|
||||
| **500 Internal Server Error** | Ошибка S3 | `"File upload failed"` |
|
||||
| **500 Internal Server Error** | Ошибка квоты | `"Failed to update user quota"` |
|
||||
|
||||
#### ✅ Исправленные проблемы
|
||||
|
||||
1. **Правильный код ошибки для квоты**: 413 Payload Too Large
|
||||
2. **Efficient memory usage**: streaming с проверками на каждом chunk
|
||||
3. **Предварительная проверка квоты** перед началом загрузки
|
||||
4. **Лимит размера одного файла**: 500 МБ
|
||||
5. **Улучшенная обработка ошибок** с детальными сообщениями
|
||||
6. **Поддержка множественных файлов** в одном запросе
|
||||
7. **Детальное логирование** с процентом использования квоты
|
||||
|
||||
---
|
||||
|
||||
#### 🔄 Как это работает
|
||||
|
||||
1. **JWT декодирование** - извлекается `user_id` из токена
|
||||
2. **Redis lookup** - опциональный поиск сессии по ключу `session:{user_id}:{token}`
|
||||
3. **Quota lookup** - получение квоты по ключу `quota:{user_id}` из Redis
|
||||
4. **Activity update** - обновление `last_activity` timestamp (если сессия найдена)
|
||||
5. **Response building** - объединение данных пользователя и квоты
|
||||
|
||||
#### Заголовки запроса
|
||||
```http
|
||||
Authorization: Bearer <jwt-token>
|
||||
```
|
||||
|
||||
#### Успешный ответ
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
#### Поля ответа
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|------|-----|----------|
|
||||
| `user_id` | string | Уникальный ID пользователя |
|
||||
| `username` | string \| null | Имя пользователя |
|
||||
| `token_type` | string \| null | Тип токена (обычно "session") |
|
||||
| `created_at` | string \| null | Unix timestamp создания сессии |
|
||||
| `last_activity` | string \| null | Unix timestamp последней активности |
|
||||
| `auth_data` | string \| null | JSON-строка с данными авторизации |
|
||||
| `device_info` | string \| null | JSON-строка с информацией об устройстве |
|
||||
| `quota.current_quota` | number | Текущее использование квоты в байтах |
|
||||
| `quota.max_quota` | number | Максимальная квота в байтах |
|
||||
| `quota.usage_percentage` | number | Процент использования квоты |
|
||||
|
||||
#### Коды ошибок
|
||||
|
||||
| Код | Условие | Описание |
|
||||
|-----|---------|----------|
|
||||
| **401 Unauthorized** | Отсутствует токен | `"Authorization token required"` |
|
||||
| **401 Unauthorized** | Неверный JWT | `"Invalid or expired session token"` |
|
||||
| **401 Unauthorized** | Сессия не найдена | `"Session not found or expired"` |
|
||||
|
||||
#### Примеры использования
|
||||
|
||||
```bash
|
||||
# Получение информации о текущем пользователе
|
||||
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \
|
||||
http://localhost:8080/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Управление квотами
|
||||
|
||||
### GET /quota
|
||||
|
||||
Получает информацию о квоте пользователя.
|
||||
|
||||
#### Параметры запроса
|
||||
```
|
||||
GET /quota?user_id=<user_id>
|
||||
```
|
||||
|
||||
#### Ответ
|
||||
```json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"current_quota": 1073741824,
|
||||
"max_quota": 5368709120
|
||||
}
|
||||
```
|
||||
|
||||
### POST /quota/increase
|
||||
|
||||
Увеличивает квоту пользователя (admin-only).
|
||||
|
||||
#### Тело запроса
|
||||
```json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"additional_bytes": 1073741824
|
||||
}
|
||||
```
|
||||
|
||||
#### Валидация
|
||||
- `additional_bytes` должно быть > 0
|
||||
- Требуется админский токен
|
||||
|
||||
### POST /quota/set
|
||||
|
||||
Устанавливает абсолютное значение квоты (admin-only).
|
||||
|
||||
#### Тело запроса
|
||||
```json
|
||||
{
|
||||
"user_id": "user123",
|
||||
"new_quota_bytes": 2147483648
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Получение файлов
|
||||
|
||||
### GET /{filename}
|
||||
|
||||
Возвращает файл по имени с возможными трансформациями.
|
||||
|
||||
#### Параметры URL
|
||||
- `filename` - имя файла или имя_размер.расширение для миниатюр
|
||||
|
||||
#### Query параметры
|
||||
- `s=<shout_id>` - добавляет оверлей с данными shout (только изображения)
|
||||
|
||||
#### Примеры
|
||||
```bash
|
||||
GET /uuid-file.jpg # Оригинальный файл
|
||||
GET /uuid-file_300.jpg # Миниатюра 300px
|
||||
GET /uuid-file_300.jpg/webp # Миниатюра в WebP
|
||||
GET /uuid-file.jpg?s=123 # С оверлеем shout
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Примеры использования
|
||||
|
||||
### Загрузка файла
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/ \
|
||||
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \
|
||||
-F "file=@photo.jpg"
|
||||
```
|
||||
|
||||
**Ответ при успехе:**
|
||||
```
|
||||
c4ca4238-a0b9-23f1-8429-81dc9bdb9a1f.jpg
|
||||
```
|
||||
|
||||
**Ответ при превышении квоты:**
|
||||
```
|
||||
HTTP/1.1 401 Unauthorized
|
||||
Quota exceeded
|
||||
```
|
||||
|
||||
### Проверка квоты
|
||||
```bash
|
||||
curl "http://localhost:8080/quota?user_id=user123" \
|
||||
-H "Authorization: Bearer admin-token"
|
||||
```
|
||||
|
||||
### Увеличение квоты (admin)
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/quota/increase \
|
||||
-H "Authorization: Bearer admin-token" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"user_id": "user123", "additional_bytes": 1073741824}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Рекомендации по улучшению
|
||||
|
||||
1. **Исправить код ошибки квоты**: 401 → 413
|
||||
2. **Добавить предварительную проверку размера** из Content-Length
|
||||
3. **Streaming загрузка** вместо полного чтения в память
|
||||
4. **Лимит размера одного файла**
|
||||
5. **Детальная валидация MIME-типов**
|
||||
6. **Метрики использования квот**
|
||||
|
||||
---
|
||||
|
||||
*Документация актуальна для версии кода на момент создания. Для изменений см. CHANGELOG.md.*
|
||||
-H "Authorization: Bearer admin-token" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"user_id": "user123", "additional_bytes": 1073741824}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Рекомендации по улучшению
|
||||
|
||||
1. **Исправить код ошибки квоты**: 401 → 413
|
||||
2. **Добавить предварительную проверку размера** из Content-Length
|
||||
3. **Streaming загрузка** вместо полного чтения в память
|
||||
4. **Лимит размера одного файла**
|
||||
5. **Детальная валидация MIME-типов**
|
||||
6. **Метрики использования квот**
|
||||
|
||||
---
|
||||
|
||||
*Документация актуальна для версии кода на момент создания. Для изменений см. CHANGELOG.md.*
|
||||
Reference in New Issue
Block a user