feat(old_app_api): proper api key handling
This commit is contained in:
parent
1f827114eb
commit
c5eed34237
2 changed files with 33 additions and 20 deletions
|
@ -6,21 +6,15 @@ mod types;
|
|||
use ntex::web::types::State;
|
||||
use ntex::util::Bytes;
|
||||
use ntex::web;
|
||||
use nom::AsBytes;
|
||||
use snafu::ResultExt;
|
||||
use crate::web_server::app_error::AppError;
|
||||
use crate::web_server::NMAppState;
|
||||
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::utils::redis::is_api_key_valid;
|
||||
use crate::web_server::NMAppState;
|
||||
use ntex::http::HeaderMap;
|
||||
use ntex::util::Bytes;
|
||||
use ntex::web::types::State;
|
||||
use ntex::web::{self, HttpRequest};
|
||||
use ntex::web::HttpRequest;
|
||||
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 приложения.
|
||||
pub async fn old_api_handler(
|
||||
request: HttpRequest,
|
||||
app_state: State<NMAppState>,
|
||||
body_bytes: Bytes,
|
||||
) -> Result<impl web::Responder, AppError> {
|
||||
let headers = request.headers();
|
||||
|
||||
if body_bytes.len() > 10 * 1024 {
|
||||
// 10 KiB
|
||||
return Err(AppError::RequestTooLarge);
|
||||
|
@ -39,10 +36,22 @@ pub async fn old_api_handler(
|
|||
let mandatory_params: MandatoryParams =
|
||||
serde_json::from_slice(&body_bytes).context(app_error::JsonSnafu {})?; // TODO: Simd-JSON
|
||||
|
||||
// Ignore clippy singlematch
|
||||
if mandatory_params.cmd.as_ref() == "version" { return version((), &app_state).await }
|
||||
// Тут все cmd которые могут быть вызваны без api ключа
|
||||
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() {
|
||||
"appInit" => {
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
//! Сборник утилит для работы с Redis.
|
||||
|
||||
use crate::web_server::app_error::{AppError, ServerRedisSnafu};
|
||||
use fred::prelude::*;
|
||||
use crate::{
|
||||
uformat,
|
||||
web_server::app_error::{AppError, ServerRedisSnafu},
|
||||
};
|
||||
use fred::clients::Client as RedisClient;
|
||||
use fred::prelude::*;
|
||||
use heapless::String as HeaplessString;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snafu::ResultExt;
|
||||
use ufmt::uwrite;
|
||||
use uuid::Uuid;
|
||||
|
||||
lazy_static! {
|
||||
/// Разрешённые знаки для 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_{}`.
|
||||
|
@ -25,18 +29,18 @@ pub struct ApiKeyDescription {
|
|||
/// Проверка API ключа на валидность.
|
||||
pub async fn is_api_key_valid(
|
||||
client: &RedisClient,
|
||||
api_key: &str,
|
||||
api_key: String,
|
||||
) -> 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 {
|
||||
reason: "Invalid characters present in the API key.",
|
||||
});
|
||||
}
|
||||
|
||||
let mut key_buffer = HeaplessString::<{ 7 + 13 }>::new();
|
||||
uwrite!(key_buffer, "apikey_{}", api_key).expect("TODO"); // TODO: Error handling
|
||||
|
||||
let valid: Option<i64> = client.hget(key_buffer.as_str(), "owner").await.context(ServerRedisSnafu)?;
|
||||
let valid: Option<i64> = client
|
||||
.hget(uformat!("apikey_{}", api_key), "owner")
|
||||
.await
|
||||
.context(ServerRedisSnafu)?;
|
||||
|
||||
valid
|
||||
.map(|uid| ApiKeyDescription { apikey_owner: uid })
|
||||
|
|
Loading…
Add table
Reference in a new issue