Skip to content

Commit

Permalink
fix(webserver): Parsing user_id in a valid format
Browse files Browse the repository at this point in the history
  • Loading branch information
pedronauck committed Jan 24, 2025
1 parent 51b96a5 commit 4918803
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 99 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 9 additions & 81 deletions crates/fuel-streams-types/src/primitives/block_height.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
use std::{ops::Deref, str::FromStr};
use crate::{declare_integer_wrapper, fuel_core::FuelCoreBlockHeight};

use serde::{Deserialize, Serialize};

use crate::fuel_core::FuelCoreBlockHeight;

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Hash, Copy)]
pub struct BlockHeight(u64);

impl Default for BlockHeight {
fn default() -> Self {
0.into()
}
#[derive(thiserror::Error, Debug)]
pub enum BlockHeightError {
#[error("Failed to parse to block_height: {0}")]
InvalidFormat(String),
}

declare_integer_wrapper!(BlockHeight, u64, BlockHeightError);

impl From<&FuelCoreBlockHeight> for BlockHeight {
fn from(value: &FuelCoreBlockHeight) -> Self {
value.to_owned().into()
Expand All @@ -26,73 +21,6 @@ impl From<FuelCoreBlockHeight> for BlockHeight {
}
}

impl std::fmt::Display for BlockHeight {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}

impl FromStr for BlockHeight {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let height = s.parse::<u64>().map_err(|_| "Invalid block height")?;
Ok(BlockHeight(height))
}
}

impl Deref for BlockHeight {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl AsRef<u64> for BlockHeight {
fn as_ref(&self) -> &u64 {
&self.0
}
}

macro_rules! impl_block_height_conversion {
($($t:ty),*) => {
$(
impl From<$t> for BlockHeight {
fn from(value: $t) -> Self {
BlockHeight(value as u64)
}
}

impl From<BlockHeight> for $t {
fn from(value: BlockHeight) -> Self {
value.0 as $t
}
}

)*
};
}

impl BlockHeight {
// Helper method to parse the internal string to u64
fn as_number(&self) -> u64 {
self.0
}
}

impl PartialOrd for BlockHeight {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for BlockHeight {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_number().cmp(&other.as_number())
}
}

impl_block_height_conversion!(u32, i32, u64, i64);

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -145,11 +73,11 @@ mod tests {
#[test]
fn test_block_height_from_str() {
// Test valid conversion
let height = BlockHeight::from_str("100").unwrap();
let height = BlockHeight::try_from("100").unwrap();
assert_eq!(height.0, 100);

// Test invalid conversion
assert!(BlockHeight::from_str("invalid").is_err());
assert!(BlockHeight::try_from("invalid").is_err());
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions crates/fuel-streams-types/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod identifier;
pub mod script_execution;
pub mod tx_pointer;
pub mod utxo_id;
pub mod wrapper_int;

pub use block_height::*;
pub use bytes::*;
Expand Down
105 changes: 105 additions & 0 deletions crates/fuel-streams-types/src/primitives/wrapper_int.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#[macro_export]
macro_rules! impl_conversions {
($name:ident, $inner_type:ty, $($t:ty),*) => {
$(
impl From<$t> for $name {
fn from(value: $t) -> Self {
$name(value as $inner_type)
}
}

impl From<$name> for $t {
fn from(value: $name) -> Self {
value.0 as $t
}
}
)*
};
}

#[macro_export]
macro_rules! declare_integer_wrapper {
($name:ident, $inner_type:ty, $error:ty) => {
#[derive(
Debug,
Clone,
Eq,
PartialEq,
serde::Serialize,
serde::Deserialize,
Hash,
Copy,
)]
pub struct $name($inner_type);

impl Default for $name {
fn default() -> Self {
0.into()
}
}

impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}

impl std::ops::Deref for $name {
type Target = $inner_type;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl AsRef<$inner_type> for $name {
fn as_ref(&self) -> &$inner_type {
&self.0
}
}

impl $name {
fn as_number(&self) -> $inner_type {
self.0
}
}

impl PartialOrd for $name {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for $name {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_number().cmp(&other.as_number())
}
}

impl TryFrom<&str> for $name {
type Error = $error;
fn try_from(s: &str) -> Result<Self, Self::Error> {
let value = s
.parse::<$inner_type>()
.map_err(|_| <$error>::InvalidFormat(s.to_string()))?;
Ok($name(value))
}
}

impl TryFrom<String> for $name {
type Error = $error;
fn try_from(s: String) -> Result<Self, Self::Error> {
s.as_str().try_into()
}
}

// TODO: remove this and let just TryFrom<&str>
impl std::str::FromStr for $name {
type Err = $error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}

$crate::impl_conversions!($name, $inner_type, u32, i32, u64, i64);
};
}
1 change: 1 addition & 0 deletions crates/fuel-web-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ elasticsearch = "8.15.0-alpha.1"
fuel-data-parser = { workspace = true }
fuel-message-broker = { workspace = true }
fuel-streams-store = { workspace = true }
fuel-streams-types = { workspace = true }
futures = { workspace = true }
futures-util = { workspace = true }
num_cpus = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use actix_web::{HttpMessage, HttpRequest};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

use super::ApiKeyError;
use super::{ApiKeyError, ApiKeyUserId};

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum ApiKeyLimit {
Expand Down Expand Up @@ -39,11 +39,9 @@ pub enum ApiKeyStatus {
Deleted,
}

pub type ApiKeyId = u64;

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct ApiKey {
user_id: ApiKeyId,
user_id: ApiKeyUserId,
user_name: String,
api_key: String,
pub limits: ApiKeyLimits,
Expand All @@ -54,7 +52,11 @@ pub struct ApiKey {
}

impl ApiKey {
pub fn new(user_id: ApiKeyId, user_name: String, api_key: String) -> Self {
pub fn new(
user_id: ApiKeyUserId,
user_name: String,
api_key: String,
) -> Self {
Self {
user_id,
user_name,
Expand Down Expand Up @@ -97,7 +99,7 @@ impl ApiKey {
}
}

pub fn id(&self) -> ApiKeyId {
pub fn id(&self) -> ApiKeyUserId {
self.user_id
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::server::middlewares::api_key::{

#[derive(sqlx::FromRow, Debug, Clone, Serialize, Deserialize)]
pub struct DbUserApiKey {
pub user_id: i64,
pub user_id: i32,
pub user_name: String,
pub api_key: String,
}
Expand Down Expand Up @@ -53,7 +53,7 @@ impl ApiKeysManager {
.into_iter()
.map(|record| {
ApiKey::new(
record.user_id as u64,
record.user_id.into(),
record.user_name,
record.api_key,
)
Expand All @@ -73,8 +73,9 @@ impl ApiKeysManager {
.fetch_optional(&self.db.pool)
.await
.map_err(ApiKeyManagerError::DatabaseError)?;
Ok(record
.map(|r| ApiKey::new(r.user_id as u64, r.user_name, r.api_key)))
Ok(record.map(|record| {
ApiKey::new(record.user_id.into(), record.user_name, record.api_key)
}))
}

pub async fn validate_api_key(
Expand Down
2 changes: 2 additions & 0 deletions crates/fuel-web-utils/src/server/middlewares/api_key/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ mod errors;
mod manager;
pub mod middleware;
mod storage;
mod user_id;

pub use api_key_impl::*;
pub use errors::*;
pub use manager::*;
pub use storage::*;
pub use user_id::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use fuel_streams_types::declare_integer_wrapper;

#[derive(thiserror::Error, Debug)]
pub enum ApiKeyUserIdError {
#[error("Failed to parse to user_id: {0}")]
InvalidFormat(String),
}

declare_integer_wrapper!(ApiKeyUserId, u32, ApiKeyUserIdError);
Loading

0 comments on commit 4918803

Please sign in to comment.