dev-nm17-2 #25

Open
nm17 wants to merge 6 commits from dev-nm17-2 into master
2 changed files with 33 additions and 20 deletions
Showing only changes of commit c5eed34237 - Show all commits

View file

@ -6,21 +6,15 @@ mod types;
use ntex::web::types::State; use ntex::web::types::State;
use ntex::util::Bytes; use ntex::util::Bytes;
use ntex::web; use ntex::web;
use nom::AsBytes;
use snafu::ResultExt;
use crate::web_server::app_error::AppError; use crate::web_server::app_error::AppError;
use crate::web_server::NMAppState; use crate::web_server::NMAppState;
use crate::web_server::old_app_api::handlers::{app_init, version}; use crate::web_server::old_app_api::handlers::{app_init, version};
use crate::web_server::old_app_api::types::{AppInitRequest, MandatoryParams}; use crate::web_server::old_app_api::types::{AppInitRequest, MandatoryParams};
use crate::web_server::utils::redis::is_api_key_valid; use crate::web_server::utils::redis::is_api_key_valid;
use crate::web_server::NMAppState; use ntex::web::HttpRequest;
use ntex::http::HeaderMap;
use ntex::util::Bytes;
use ntex::web::types::State;
use ntex::web::{self, HttpRequest};
use snafu::{whatever, ResultExt}; use snafu::{whatever, ResultExt};
use super::app_error::{self, Utf8Snafu}; use super::app_error;
/// Обработчик запросов от приложений. /// Обработчик запросов от приложений.
/// ///
@ -28,9 +22,12 @@ use super::app_error::{self, Utf8Snafu};
/// ///
/// Вызывается напрямую из ntex приложения. /// Вызывается напрямую из ntex приложения.
pub async fn old_api_handler( pub async fn old_api_handler(
request: HttpRequest,
app_state: State<NMAppState>, app_state: State<NMAppState>,
body_bytes: Bytes, body_bytes: Bytes,
) -> Result<impl web::Responder, AppError> { ) -> Result<impl web::Responder, AppError> {
let headers = request.headers();
if body_bytes.len() > 10 * 1024 { if body_bytes.len() > 10 * 1024 {
// 10 KiB // 10 KiB
return Err(AppError::RequestTooLarge); return Err(AppError::RequestTooLarge);
@ -39,10 +36,22 @@ pub async fn old_api_handler(
let mandatory_params: MandatoryParams = let mandatory_params: MandatoryParams =
serde_json::from_slice(&body_bytes).context(app_error::JsonSnafu {})?; // TODO: Simd-JSON serde_json::from_slice(&body_bytes).context(app_error::JsonSnafu {})?; // TODO: Simd-JSON
// Ignore clippy singlematch // Тут все cmd которые могут быть вызваны без api ключа
if mandatory_params.cmd.as_ref() == "version" { return version((), &app_state).await } if mandatory_params.cmd == "version" {
return version((), &app_state).await;
}
is_api_key_valid(&app_state.redis_client, mandatory_params.api_key.as_ref()).await?; let api_key: String;
if let Some(key) = mandatory_params.api_key {
api_key = key;
} else if let Some(key) = headers.get("Narodmon-Api-Key") {
api_key = key.to_str().with_whatever_context(|_| "asd")?.to_string();
} else {
whatever!("No API key found")
}
is_api_key_valid(&app_state.redis_client, api_key).await?;
match mandatory_params.cmd.as_str() { match mandatory_params.cmd.as_str() {
"appInit" => { "appInit" => {

View file

@ -1,18 +1,22 @@
//! Сборник утилит для работы с Redis. //! Сборник утилит для работы с Redis.
use crate::web_server::app_error::{AppError, ServerRedisSnafu}; use crate::{
use fred::prelude::*; uformat,
web_server::app_error::{AppError, ServerRedisSnafu},
};
use fred::clients::Client as RedisClient; use fred::clients::Client as RedisClient;
use fred::prelude::*;
use heapless::String as HeaplessString; use heapless::String as HeaplessString;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use snafu::ResultExt; use snafu::ResultExt;
use ufmt::uwrite; use ufmt::uwrite;
use uuid::Uuid;
lazy_static! { lazy_static! {
/// Разрешённые знаки для API ключа. /// Разрешённые знаки для API ключа.
static ref ALLOWED_API_KEY_CHARACTERS: Regex = Regex::new("[a-zA-Z0-9]{13}").unwrap(); static ref ALLOWED_API_KEY_CHARACTERS: Regex = Regex::new("[a-zA-Z0-9\\-]{13,36}").unwrap();
} }
/// Описание полей в KV DB у `apikey_{}`. /// Описание полей в KV DB у `apikey_{}`.
@ -25,18 +29,18 @@ pub struct ApiKeyDescription {
/// Проверка API ключа на валидность. /// Проверка API ключа на валидность.
pub async fn is_api_key_valid( pub async fn is_api_key_valid(
client: &RedisClient, client: &RedisClient,
api_key: &str, api_key: String,
) -> Result<ApiKeyDescription, AppError> { ) -> Result<ApiKeyDescription, AppError> {
if !ALLOWED_API_KEY_CHARACTERS.is_match(api_key) { if !ALLOWED_API_KEY_CHARACTERS.is_match(&api_key) {
return Err(AppError::ApiKeyInvalid { return Err(AppError::ApiKeyInvalid {
reason: "Invalid characters present in the API key.", reason: "Invalid characters present in the API key.",
}); });
} }
let mut key_buffer = HeaplessString::<{ 7 + 13 }>::new(); let valid: Option<i64> = client
uwrite!(key_buffer, "apikey_{}", api_key).expect("TODO"); // TODO: Error handling .hget(uformat!("apikey_{}", api_key), "owner")
.await
let valid: Option<i64> = client.hget(key_buffer.as_str(), "owner").await.context(ServerRedisSnafu)?; .context(ServerRedisSnafu)?;
valid valid
.map(|uid| ApiKeyDescription { apikey_owner: uid }) .map(|uid| ApiKeyDescription { apikey_owner: uid })