dev-nm17-2 #25
2 changed files with 33 additions and 20 deletions
|
@ -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" => {
|
||||||
|
|
|
@ -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 })
|
||||||
|
|
Loading…
Add table
Reference in a new issue