2024-08-31 03:32:37 +03:00
|
|
|
|
use actix_web::error::ErrorInternalServerError;
|
2025-09-01 22:58:03 +03:00
|
|
|
|
use jsonwebtoken::{Algorithm, DecodingKey, Validation, decode};
|
2025-09-01 20:36:15 +03:00
|
|
|
|
use log::{info, warn};
|
2025-09-01 22:58:03 +03:00
|
|
|
|
use redis::{AsyncCommands, aio::MultiplexedConnection};
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
2025-09-02 14:00:54 +03:00
|
|
|
|
use std::{error::Error, time::Duration};
|
2024-08-31 03:32:37 +03:00
|
|
|
|
|
2025-09-01 20:36:15 +03:00
|
|
|
|
// Структуры для JWT токенов
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
|
struct TokenClaims {
|
|
|
|
|
|
user_id: String,
|
|
|
|
|
|
username: Option<String>,
|
|
|
|
|
|
exp: Option<usize>,
|
|
|
|
|
|
iat: Option<usize>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Структура для данных пользователя из Redis сессии
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Author {
|
|
|
|
|
|
pub user_id: String,
|
|
|
|
|
|
pub username: Option<String>,
|
|
|
|
|
|
pub token_type: Option<String>,
|
|
|
|
|
|
pub created_at: Option<String>,
|
|
|
|
|
|
pub last_activity: Option<String>,
|
|
|
|
|
|
pub auth_data: Option<String>,
|
|
|
|
|
|
pub device_info: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Декодирует JWT токен и извлекает claims с проверкой истечения
|
|
|
|
|
|
fn decode_jwt_token(token: &str) -> Result<TokenClaims, Box<dyn Error>> {
|
|
|
|
|
|
// В реальном приложении здесь должен быть настоящий секретный ключ
|
|
|
|
|
|
let secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "your-secret-key".to_string());
|
|
|
|
|
|
let key = DecodingKey::from_secret(secret.as_ref());
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-01 20:36:15 +03:00
|
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
|
|
validation.validate_exp = true; // Включаем проверку истечения срока действия
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-01 20:36:15 +03:00
|
|
|
|
match decode::<TokenClaims>(token, &key, &validation) {
|
|
|
|
|
|
Ok(token_data) => {
|
|
|
|
|
|
let claims = token_data.claims;
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-01 20:36:15 +03:00
|
|
|
|
// Дополнительная проверка exp если поле присутствует
|
|
|
|
|
|
if let Some(exp) = claims.exp {
|
|
|
|
|
|
let current_time = std::time::SystemTime::now()
|
|
|
|
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
|
|
|
|
.unwrap()
|
|
|
|
|
|
.as_secs() as usize;
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-01 20:36:15 +03:00
|
|
|
|
if exp < current_time {
|
|
|
|
|
|
warn!("JWT token expired: exp={}, current={}", exp, current_time);
|
|
|
|
|
|
return Err(Box::new(std::io::Error::other("Token expired")));
|
|
|
|
|
|
}
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-01 20:36:15 +03:00
|
|
|
|
info!("JWT token valid until: {} (current: {})", exp, current_time);
|
|
|
|
|
|
}
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
|
"Successfully decoded and validated JWT token for user: {}",
|
|
|
|
|
|
claims.user_id
|
|
|
|
|
|
);
|
2025-09-01 20:36:15 +03:00
|
|
|
|
Ok(claims)
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
warn!("Failed to decode JWT token: {}", e);
|
|
|
|
|
|
Err(Box::new(e))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
/// Извлекает токен из HTTP запроса (поддерживает Bearer, X-Session-Token, Cookie)
|
|
|
|
|
|
pub fn extract_token_from_request(req: &actix_web::HttpRequest) -> Option<String> {
|
|
|
|
|
|
// 1. Bearer токен в Authorization header
|
|
|
|
|
|
if let Some(auth_header) = req.headers().get("authorization") {
|
|
|
|
|
|
if let Ok(auth_str) = auth_header.to_str() {
|
|
|
|
|
|
if let Some(stripped) = auth_str.strip_prefix("Bearer ") {
|
|
|
|
|
|
return Some(stripped.trim().to_string());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-01 20:36:15 +03:00
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
// 2. Кастомный заголовок X-Session-Token
|
|
|
|
|
|
if let Some(session_token) = req.headers().get("x-session-token") {
|
|
|
|
|
|
if let Ok(token_str) = session_token.to_str() {
|
|
|
|
|
|
return Some(token_str.trim().to_string());
|
2025-09-01 20:36:15 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-22 01:15:35 +03:00
|
|
|
|
|
|
|
|
|
|
// 3. Cookie session_token (для веб-приложений)
|
|
|
|
|
|
if let Some(cookie_header) = req.headers().get("cookie") {
|
|
|
|
|
|
if let Ok(cookie_str) = cookie_header.to_str() {
|
|
|
|
|
|
for cookie in cookie_str.split(';') {
|
|
|
|
|
|
let cookie = cookie.trim();
|
|
|
|
|
|
if let Some(stripped) = cookie.strip_prefix("session_token=") {
|
|
|
|
|
|
return Some(stripped.to_string());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
None
|
2025-09-01 20:36:15 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
/// Безопасная валидация токена с проверкой Redis сессий
|
|
|
|
|
|
pub async fn secure_token_validation(
|
2025-09-01 20:36:15 +03:00
|
|
|
|
token: &str,
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
mut redis: Option<&mut MultiplexedConnection>,
|
2025-09-02 14:00:54 +03:00
|
|
|
|
timeout: Duration,
|
2025-09-01 20:36:15 +03:00
|
|
|
|
) -> Result<Author, Box<dyn Error>> {
|
2025-09-22 01:15:35 +03:00
|
|
|
|
// Базовая проверка формата токена
|
|
|
|
|
|
if token.is_empty() || token.len() < 10 {
|
|
|
|
|
|
return Err(Box::new(std::io::Error::other("Invalid token format")));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 1. Проверяем JWT структуру и подпись
|
2025-09-01 20:36:15 +03:00
|
|
|
|
let claims = decode_jwt_token(token)?;
|
|
|
|
|
|
let user_id = &claims.user_id;
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
info!("JWT token validated for user: {}", user_id);
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
// 2. Проверяем существование сессии в Redis
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
let session_exists = if let Some(ref mut redis) = redis {
|
2025-09-22 01:15:35 +03:00
|
|
|
|
let session_key = format!("session:{}:{}", user_id, token);
|
|
|
|
|
|
|
|
|
|
|
|
match tokio::time::timeout(timeout, redis.exists(&session_key)).await {
|
|
|
|
|
|
Ok(Ok(exists)) => exists,
|
|
|
|
|
|
Ok(Err(e)) => {
|
|
|
|
|
|
warn!("Redis error checking session: {}", e);
|
|
|
|
|
|
false
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(_) => {
|
|
|
|
|
|
warn!("Redis timeout checking session");
|
|
|
|
|
|
false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
} else {
|
|
|
|
|
|
warn!("⚠️ Redis not available, skipping session validation");
|
|
|
|
|
|
false
|
|
|
|
|
|
};
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
if !session_exists {
|
|
|
|
|
|
info!("Session not found in Redis for user: {}", user_id);
|
|
|
|
|
|
// В соответствии с руководством, можем продолжить с JWT-only данными
|
|
|
|
|
|
// или вернуть ошибку в зависимости от политики безопасности
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. Проверяем TTL сессии если она существует
|
|
|
|
|
|
let ttl = if session_exists && redis.is_some() {
|
|
|
|
|
|
let session_key = format!("session:{}:{}", user_id, token);
|
|
|
|
|
|
if let Some(ref mut redis) = redis {
|
|
|
|
|
|
match tokio::time::timeout(timeout, redis.ttl(&session_key)).await {
|
|
|
|
|
|
Ok(Ok(ttl_value)) => {
|
|
|
|
|
|
if ttl_value <= 0 {
|
|
|
|
|
|
return Err(Box::new(std::io::Error::other("Session expired")));
|
|
|
|
|
|
}
|
|
|
|
|
|
ttl_value
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok(Err(e)) => {
|
|
|
|
|
|
warn!("Redis error getting TTL: {}", e);
|
|
|
|
|
|
-1
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(_) => {
|
|
|
|
|
|
warn!("Redis timeout getting TTL");
|
|
|
|
|
|
-1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
-1
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
-1
|
|
|
|
|
|
};
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
// 4. Обновляем last_activity если сессия активна
|
|
|
|
|
|
if session_exists && redis.is_some() {
|
|
|
|
|
|
let current_time = std::time::SystemTime::now()
|
|
|
|
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
|
|
|
|
.unwrap()
|
|
|
|
|
|
.as_secs();
|
|
|
|
|
|
|
|
|
|
|
|
let session_key = format!("session:{}:{}", user_id, token);
|
|
|
|
|
|
if let Some(redis) = redis {
|
|
|
|
|
|
let _: Result<(), _> = tokio::time::timeout(
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
timeout,
|
2025-09-22 01:15:35 +03:00
|
|
|
|
redis.hset(&session_key, "last_activity", current_time.to_string()),
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
)
|
|
|
|
|
|
.await
|
2025-09-22 01:15:35 +03:00
|
|
|
|
.map_err(|_| warn!("Redis timeout updating last_activity"))
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
.unwrap_or(Ok(()))
|
2025-09-22 01:15:35 +03:00
|
|
|
|
.map_err(|e| warn!("Failed to update last_activity: {}", e));
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
info!("Updated last_activity for session: {}", user_id);
|
2025-09-01 20:36:15 +03:00
|
|
|
|
}
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
// Создаем объект Author с расширенными данными
|
2025-09-01 20:36:15 +03:00
|
|
|
|
let author = Author {
|
|
|
|
|
|
user_id: user_id.clone(),
|
|
|
|
|
|
username: claims.username.clone(),
|
|
|
|
|
|
token_type: Some("jwt".to_string()),
|
|
|
|
|
|
created_at: claims.iat.map(|ts| ts.to_string()),
|
|
|
|
|
|
last_activity: Some(
|
|
|
|
|
|
std::time::SystemTime::now()
|
|
|
|
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
|
|
|
|
.unwrap()
|
|
|
|
|
|
.as_secs()
|
2025-09-01 22:58:03 +03:00
|
|
|
|
.to_string(),
|
2025-09-01 20:36:15 +03:00
|
|
|
|
),
|
2025-09-22 01:15:35 +03:00
|
|
|
|
auth_data: if session_exists {
|
|
|
|
|
|
Some(format!("redis_session_ttl:{}", ttl))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Some("jwt_only".to_string())
|
|
|
|
|
|
},
|
2025-09-01 20:36:15 +03:00
|
|
|
|
device_info: None,
|
|
|
|
|
|
};
|
2025-09-01 22:58:03 +03:00
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
info!(
|
|
|
|
|
|
"Successfully validated token for user: {} (session_exists: {})",
|
|
|
|
|
|
user_id, session_exists
|
|
|
|
|
|
);
|
2025-09-01 20:36:15 +03:00
|
|
|
|
Ok(author)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-22 01:15:35 +03:00
|
|
|
|
/// Универсальная функция аутентификации для всех handlers
|
|
|
|
|
|
/// Извлекает токен из запроса и выполняет полную валидацию
|
|
|
|
|
|
pub async fn authenticate_request(
|
|
|
|
|
|
req: &actix_web::HttpRequest,
|
|
|
|
|
|
redis: Option<&mut MultiplexedConnection>,
|
|
|
|
|
|
timeout: Duration,
|
|
|
|
|
|
) -> Result<Author, actix_web::Error> {
|
|
|
|
|
|
// Извлекаем токен из запроса (поддерживает Bearer, X-Session-Token, Cookie)
|
|
|
|
|
|
let token = extract_token_from_request(req).ok_or_else(|| {
|
|
|
|
|
|
warn!("No authorization token provided");
|
|
|
|
|
|
actix_web::error::ErrorUnauthorized("Authorization token required")
|
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
|
|
// Безопасная валидация токена с проверкой Redis сессий
|
|
|
|
|
|
secure_token_validation(&token, redis, timeout)
|
|
|
|
|
|
.await
|
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
|
warn!("Token validation failed: {}", e);
|
|
|
|
|
|
actix_web::error::ErrorUnauthorized("Invalid or expired token")
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-22 01:23:16 +03:00
|
|
|
|
/// Универсальная функция аутентификации с использованием connection pool
|
|
|
|
|
|
/// Автоматически получает и возвращает соединения из пула
|
|
|
|
|
|
pub async fn authenticate_request_with_pool(
|
|
|
|
|
|
req: &actix_web::HttpRequest,
|
|
|
|
|
|
app_state: &crate::app_state::AppState,
|
|
|
|
|
|
) -> Result<Author, actix_web::Error> {
|
|
|
|
|
|
// Извлекаем токен из запроса
|
|
|
|
|
|
let token = extract_token_from_request(req).ok_or_else(|| {
|
|
|
|
|
|
warn!("No authorization token provided");
|
|
|
|
|
|
actix_web::error::ErrorUnauthorized("Authorization token required")
|
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем соединение из пула
|
|
|
|
|
|
match app_state.get_redis_connection().await {
|
|
|
|
|
|
Ok(mut conn) => {
|
|
|
|
|
|
// Валидируем токен с Redis соединением
|
|
|
|
|
|
let result =
|
|
|
|
|
|
secure_token_validation(&token, Some(&mut conn), app_state.request_timeout).await;
|
|
|
|
|
|
|
|
|
|
|
|
// Возвращаем соединение в пул
|
|
|
|
|
|
app_state.return_redis_connection(conn).await;
|
|
|
|
|
|
|
|
|
|
|
|
result.map_err(|e| {
|
|
|
|
|
|
warn!("Token validation failed: {}", e);
|
|
|
|
|
|
actix_web::error::ErrorUnauthorized("Invalid or expired token")
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(_) => {
|
|
|
|
|
|
// Fallback на JWT-only валидацию если Redis недоступен
|
|
|
|
|
|
warn!("Redis pool unavailable, falling back to JWT-only validation");
|
|
|
|
|
|
secure_token_validation(&token, None, app_state.request_timeout)
|
|
|
|
|
|
.await
|
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
|
warn!("Token validation failed: {}", e);
|
|
|
|
|
|
actix_web::error::ErrorUnauthorized("Invalid or expired token")
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-31 03:32:37 +03:00
|
|
|
|
/// Сохраняет имя файла в Redis для пользователя
|
|
|
|
|
|
pub async fn user_added_file(
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
redis: Option<&mut MultiplexedConnection>,
|
2024-08-31 03:32:37 +03:00
|
|
|
|
user_id: &str,
|
2024-10-22 13:15:37 +03:00
|
|
|
|
filename: &str,
|
2024-08-31 03:32:37 +03:00
|
|
|
|
) -> Result<(), actix_web::Error> {
|
[0.6.1] - 2025-09-02
### 🚀 Изменено - Упрощение архитектуры
- **Генерация миниатюр**: Полностью удалена из Quoter, теперь управляется Vercel Edge API
- **Очистка legacy кода**: Удалены все функции генерации миниатюр и сложность
- **Документация**: Сокращена с 17 файлов до 7, следуя принципам KISS/DRY
- **Смена фокуса**: Quoter теперь сосредоточен на upload + storage, Vercel обрабатывает миниатюры
- **Логирование запросов**: Добавлена аналитика источников для оптимизации CORS whitelist
- **Реализация таймаутов**: Добавлены настраиваемые таймауты для S3, Redis и внешних операций
- **Упрощенная безопасность**: Удален сложный rate limiting, оставлена только необходимая защита upload
- **Vercel интеграция**: Добавлена поддержка Vercel Edge API с CORS и оптимизированными заголовками
- **Redis graceful fallback**: Приложение теперь работает без Redis с предупреждениями вместо паники
- **Умная логика ответов**: Автоматическое определение Vercel запросов и оптимизированные заголовки
- **Консолидация документации**: Объединены 4 Vercel документа в один comprehensive guide
### 📝 Обновлено
- Консолидирована документация в практическую структуру:
- Основной README.md с быстрым стартом
- docs/SETUP.md для конфигурации и развертывания
- Упрощенный features.md с фокусом на основную функциональность
- docs/vercel-frontend-migration.md - единый comprehensive guide для Vercel интеграции
- Добавлен акцент на Vercel по всему коду и документации
- Обновлены URL patterns в документации: quoter.discours.io → files.dscrs.site
### 🗑️ Удалено
- Избыточные файлы документации (api-reference, deployment, development, и т.д.)
- Дублирующийся контент в нескольких документах
- Излишне детальная документация для простого файлового прокси
- 4 отдельных Vercel документа: vercel-thumbnails.md, vercel-integration.md, hybrid-architecture.md, vercel-og-integration.md
💋 **Упрощение**: KISS принцип применен - убрали избыточность, оставили суть.
2025-09-02 14:39:54 +03:00
|
|
|
|
let Some(redis) = redis else {
|
|
|
|
|
|
log::warn!(
|
|
|
|
|
|
"⚠️ Redis not available, skipping file tracking for user {}",
|
|
|
|
|
|
user_id
|
|
|
|
|
|
);
|
|
|
|
|
|
return Ok(());
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-08-31 03:32:37 +03:00
|
|
|
|
redis
|
2024-10-22 13:15:37 +03:00
|
|
|
|
.sadd::<&str, &str, ()>(user_id, filename)
|
2024-08-31 03:32:37 +03:00
|
|
|
|
.await
|
2024-10-22 13:15:37 +03:00
|
|
|
|
.map_err(|_| ErrorInternalServerError(format!("Failed to save {} in Redis", filename)))?; // Добавляем имя файла в набор пользователя
|
2024-08-31 03:32:37 +03:00
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|