use actix_web::error::ErrorInternalServerError; use redis::{aio::MultiplexedConnection, AsyncCommands}; use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE}; use reqwest::Client as HTTPClient; use serde::Deserialize; use serde_json::json; use std::{collections::HashMap, env, error::Error}; // Структура для десериализации ответа от сервиса аутентификации #[derive(Deserialize)] struct AuthResponse { data: Option, } #[derive(Deserialize)] struct AuthData { validate_jwt_token: Option, } #[derive(Deserialize)] struct ValidateJWTToken { is_valid: bool, claims: Option, } #[derive(Deserialize)] struct Claims { sub: Option, } /// Получает айди пользователя из токена в заголовке pub async fn get_id_by_token(token: &str) -> Result> { let auth_api_base = env::var("AUTH_URL")?; let query_name = "validate_jwt_token"; let operation = "ValidateToken"; let mut headers = HeaderMap::new(); headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); let mut variables = HashMap::>::new(); let mut params = HashMap::::new(); params.insert("token".to_string(), token.to_string()); params.insert("token_type".to_string(), "access_token".to_string()); variables.insert("params".to_string(), params); let gql = json!({ "query": format!("query {}($params: ValidateJWTTokenInput!) {{ {}(params: $params) {{ is_valid claims }} }}", operation, query_name), "operationName": operation, "variables": variables }); let client = HTTPClient::new(); let response = client .post(&auth_api_base) .headers(headers) .json(&gql) .send() .await?; if response.status().is_success() { let auth_response: AuthResponse = response.json().await?; if let Some(auth_data) = auth_response.data { if let Some(validate_jwt_token) = auth_data.validate_jwt_token { if validate_jwt_token.is_valid { if let Some(claims) = validate_jwt_token.claims { if let Some(sub) = claims.sub { return Ok(sub); } } } } } Err(Box::new(std::io::Error::new( std::io::ErrorKind::Other, "Invalid token response", ))) } else { Err(Box::new(std::io::Error::new( std::io::ErrorKind::Other, format!("Request failed with status: {}", response.status()), ))) } } /// Сохраняет имя файла в Redis для пользователя pub async fn user_added_file( redis: &mut MultiplexedConnection, user_id: &str, filename: &str, ) -> Result<(), actix_web::Error> { redis .sadd::<&str, &str, ()>(user_id, filename) .await .map_err(|_| ErrorInternalServerError(format!("Failed to save {} in Redis", filename)))?; // Добавляем имя файла в набор пользователя Ok(()) }