simpler-auth+no-overlay
Some checks failed
Deploy / deploy (push) Has been skipped
CI / lint (push) Failing after 8s
CI / test (push) Failing after 3m57s

This commit is contained in:
2025-09-01 20:36:15 +03:00
parent a44bf3302b
commit 6c3262edbe
20 changed files with 1516 additions and 686 deletions

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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);
```

View File

@@ -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
View 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.*