From 4d982943295bd40d8f71715c19d235943028b264 Mon Sep 17 00:00:00 2001 From: Eason <30045503+Eason0729@users.noreply.github.com> Date: Tue, 23 Jul 2024 05:51:06 +0000 Subject: [PATCH] fix(backend): use custom Deserialize impl for postcard to handle `#[serde(skip)]` --- backend/src/controller/crypto.rs | 3 +++ backend/src/controller/token.rs | 19 ++++++++----------- backend/src/entity/util/paginator.rs | 24 ++++++++++++++++++++---- backend/src/util/rate_limit.rs | 8 ++++++-- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/backend/src/controller/crypto.rs b/backend/src/controller/crypto.rs index 0b5b187..c5293d4 100644 --- a/backend/src/controller/crypto.rs +++ b/backend/src/controller/crypto.rs @@ -5,6 +5,7 @@ use serde::{de::DeserializeOwned, Serialize}; use crate::config::CONFIG; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; use blake2::{Blake2b512, Digest}; +use tracing::instrument; type Result = std::result::Result; @@ -60,6 +61,7 @@ impl CryptoController { /// Serialize and calculate checksum and return /// /// Note that it shouldn't be an security measurement + #[instrument(skip_all, level = "debug", ret(level = "debug"))] pub fn encode(&self, obj: M) -> Result { let mut raw = postcard::to_allocvec(&obj)?; @@ -75,6 +77,7 @@ impl CryptoController { /// check signature and return the object /// /// Error if signature invaild + #[instrument(skip_all, level = "debug", err(level = "debug"))] pub fn decode(&self, raw: String) -> Result { let mut raw = URL_SAFE_NO_PAD.decode(raw)?; diff --git a/backend/src/controller/token.rs b/backend/src/controller/token.rs index 3da365d..bf41f61 100644 --- a/backend/src/controller/token.rs +++ b/backend/src/controller/token.rs @@ -129,18 +129,16 @@ impl TokenController { base64::Engine::decode(&base64::engine::general_purpose::STANDARD_NO_PAD, token)?; let rand: Rand = rand.try_into().map_err(|_| Error::InvalidTokenLength)?; - let cache_result = { - match self.cache.get(&rand) { - Some(cc) => { - if cc.expiry < now { - self.cache.remove(&rand); - None - } else { - Some(cc.clone()) - } + let cache_result = match self.cache.get(&rand) { + Some(cc) => { + if cc.expiry < now { + self.cache.remove(&rand); + None + } else { + Some(cc.clone()) } - None => None, } + None => None, }; let token = match cache_result { @@ -149,7 +147,6 @@ impl TokenController { token } None => { - // FIXME: this is cold branch! let token: CachedToken = (token::Entity::find() .filter(token::Column::Rand.eq(rand.to_vec())) .one(self.db.deref()) diff --git a/backend/src/entity/util/paginator.rs b/backend/src/entity/util/paginator.rs index 22739d4..a7d98a1 100644 --- a/backend/src/entity/util/paginator.rs +++ b/backend/src/entity/util/paginator.rs @@ -12,7 +12,7 @@ use super::helper::*; use crate::util::auth::Auth; use sea_orm::*; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize}; use tonic::async_trait; use tracing::*; @@ -360,17 +360,33 @@ impl, R: Reflect> PaginateRaw for ColumnPaginator { - #[serde(skip_deserializing, skip_serializing)] + #[serde(skip)] Uninit(::Data, bool), #[serde(bound(deserialize = "P: for<'a> Deserialize<'a>"))] Init(P), - #[serde(skip_deserializing, skip_serializing)] + #[serde(skip)] #[default] None, } +impl<'de, P: PaginateRaw> Deserialize<'de> for UninitPaginator

{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let p: Option

= Deserialize::deserialize(deserializer)?; + + match p { + Some(p) => Ok(UninitPaginator::Init(p)), + None => Err(serde::de::Error::custom( + "Unexpected data format for UninitPaginator", + )), + } + } +} + impl UninitPaginator

{ pub fn new(data: ::Data, start_from_end: bool) -> Self { Self::Uninit(data, start_from_end) diff --git a/backend/src/util/rate_limit.rs b/backend/src/util/rate_limit.rs index 796d53e..8a371bd 100644 --- a/backend/src/util/rate_limit.rs +++ b/backend/src/util/rate_limit.rs @@ -1,19 +1,20 @@ use std::num::NonZeroU32; +use super::auth::Auth; use crate::{ controller::rate_limit::{Bucket, TrafficType}, server::Server, }; use grpc::backend::{Id, *}; use tracing::*; - -use super::auth::Auth; +use tracing_futures::Instrument; impl Server { /// parse authentication without rate limiting /// /// It's useful for endpoints that require resolving identity /// before rate limiting, such as logout + #[instrument(skip_all, level = "info")] pub async fn parse_auth( &self, req: &tonic::Request, @@ -25,6 +26,7 @@ impl Server { .check(req, |req| async { if let Some(x) = req.metadata().get("token") { let token = x.to_str().unwrap(); + tracing::debug!(token = token); match self.token.verify(token).in_current_span().await { Ok(user) => { @@ -42,6 +44,7 @@ impl Server { TrafficType::Guest } }) + .in_current_span() .await?; tracing::info!(auth = %auth); Ok((auth, bucket)) @@ -89,6 +92,7 @@ impl Server { let (auth, bucket) = self.parse_auth(&req).in_current_span().await?; bucket.cost(NonZeroU32::new(3).unwrap())?; let req = req.into_inner(); + tracing::debug!(bucket = %bucket); if let Some(cost) = NonZeroU32::new(req.get_cost()) { bucket.cost(cost)?;