From 077f69778f8cd589cfe75beee1fcb095669734eb Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Sat, 24 Feb 2024 19:03:48 -0300 Subject: [PATCH] Initial Implementation of ResourceGuard Macro --- Cargo.lock | 16 +++++++++++++++- Cargo.toml | 6 +++++- proc-utils/Cargo.toml | 13 +++++++++++++ proc-utils/src/lib.rs | 11 +++++++++++ src/handler/health.rs | 12 +++++------- src/handler/message.rs | 12 +++++------- src/handler/mod.rs | 2 +- src/interceptor/mod.rs | 1 + src/main.rs | 12 ++++-------- src/model/generic_response.rs | 3 +-- src/model/mod.rs | 2 +- src/model/send_message.rs | 11 ++++------- src/route.rs | 9 ++++----- utils/Cargo.toml | 8 ++++++++ utils/src/lib.rs | 24 ++++++++++++++++++++++++ 15 files changed, 102 insertions(+), 40 deletions(-) create mode 100644 proc-utils/Cargo.toml create mode 100644 proc-utils/src/lib.rs create mode 100644 src/interceptor/mod.rs create mode 100644 utils/Cargo.toml create mode 100644 utils/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e678ca9..3978a7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -497,14 +497,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] -name = "message-hideyoshi_com" +name = "message-hideyoshi-com" version = "0.1.0" dependencies = [ "axum", "chrono", + "proc-utils", "serde", "serde_with", "tokio", + "utils", "uuid", ] @@ -627,6 +629,14 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-utils" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "quote" version = "1.0.35" @@ -912,6 +922,10 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utils" +version = "0.1.0" + [[package]] name = "uuid" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 99e694c..852d3d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,15 @@ +workspace = { members = ["proc-utils", "utils"] } [package] -name = "message-hideyoshi_com" +name = "message-hideyoshi-com" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +proc-utils = { path = "proc-utils" } +utils = { path = "utils" } + axum = "0.7.4" tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] } uuid = "1.7.0" diff --git a/proc-utils/Cargo.toml b/proc-utils/Cargo.toml new file mode 100644 index 0000000..e5f2fec --- /dev/null +++ b/proc-utils/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "proc-utils" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +proc-macro = true + +[dependencies] +syn = "2.0.50" +quote = "1.0.35" diff --git a/proc-utils/src/lib.rs b/proc-utils/src/lib.rs new file mode 100644 index 0000000..12827aa --- /dev/null +++ b/proc-utils/src/lib.rs @@ -0,0 +1,11 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, ItemFn}; + +#[proc_macro_attribute] +pub fn guard_resource(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemFn); + println!("{} defined", input.sig.ident); + println!("Args received: {}", _attr.to_string()); + return TokenStream::from(quote!(#input)); +} diff --git a/src/handler/health.rs b/src/handler/health.rs index 1e9b713..1ec367d 100644 --- a/src/handler/health.rs +++ b/src/handler/health.rs @@ -1,10 +1,8 @@ -use axum::{ - http::StatusCode, - response::IntoResponse, - Json, -}; -use crate::model::generic_response::{GenericResponse}; +use crate::model::generic_response::GenericResponse; +use axum::{http::StatusCode, response::IntoResponse, Json}; +use proc_utils::guard_resource; +#[guard_resource(ResourceType::OPEN)] pub async fn health_check() -> impl IntoResponse { const MESSAGE: &str = "Server is running"; let response = GenericResponse { @@ -13,4 +11,4 @@ pub async fn health_check() -> impl IntoResponse { }; (StatusCode::OK, Json(response)) -} \ No newline at end of file +} diff --git a/src/handler/message.rs b/src/handler/message.rs index 70ee34f..9cd6349 100644 --- a/src/handler/message.rs +++ b/src/handler/message.rs @@ -1,10 +1,8 @@ -use axum::{ - http::StatusCode, - response::IntoResponse, - Json, -}; -use crate::model::send_message::{SendMessage}; +use crate::model::send_message::SendMessage; +use axum::{http::StatusCode, response::IntoResponse, Json}; +use proc_utils::guard_resource; +#[guard_resource(ResourceType::OPEN)] pub async fn send_message(Json(payload): Json) -> impl IntoResponse { (StatusCode::OK, Json(payload)) -} \ No newline at end of file +} diff --git a/src/handler/mod.rs b/src/handler/mod.rs index 9320727..f20bb8d 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -1,2 +1,2 @@ pub mod health; -pub mod message; \ No newline at end of file +pub mod message; diff --git a/src/interceptor/mod.rs b/src/interceptor/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/interceptor/mod.rs @@ -0,0 +1 @@ + diff --git a/src/main.rs b/src/main.rs index e2caab7..3d5ebeb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,7 @@ -mod route; -mod model; mod handler; - -use axum::http::{ - header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE}, - HeaderValue, Method -}; +mod interceptor; +mod model; +mod route; #[tokio::main] async fn main() { @@ -14,4 +10,4 @@ async fn main() { println!("🚀 Server started successfully"); let listener = tokio::net::TcpListener::bind("0.0.0.0:8500").await.unwrap(); axum::serve(listener, app).await.unwrap(); -} \ No newline at end of file +} diff --git a/src/model/generic_response.rs b/src/model/generic_response.rs index 84ce3a5..838cac2 100644 --- a/src/model/generic_response.rs +++ b/src/model/generic_response.rs @@ -1,8 +1,7 @@ use serde::Serialize; - #[derive(Serialize)] pub struct GenericResponse { pub status: String, pub message: String, -} \ No newline at end of file +} diff --git a/src/model/mod.rs b/src/model/mod.rs index b4941c6..7b02dcc 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -1,2 +1,2 @@ pub mod generic_response; -pub mod send_message; \ No newline at end of file +pub mod send_message; diff --git a/src/model/send_message.rs b/src/model/send_message.rs index d22438f..6f61331 100644 --- a/src/model/send_message.rs +++ b/src/model/send_message.rs @@ -1,18 +1,15 @@ +use chrono::naive::serde::ts_seconds::deserialize as from_ts; use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; use serde_with::serde_as; -use chrono::naive::serde::ts_seconds::deserialize as from_ts; - - #[derive(Deserialize, Serialize)] pub struct MessageAuthor { name: String, username: String, - email: String + email: String, } - #[serde_as] #[derive(Deserialize, Serialize)] pub struct SendMessage { @@ -23,5 +20,5 @@ pub struct SendMessage { message: String, #[serde(deserialize_with = "from_ts")] - timestamp: NaiveDateTime -} \ No newline at end of file + timestamp: NaiveDateTime, +} diff --git a/src/route.rs b/src/route.rs index b20dad9..10fb3db 100644 --- a/src/route.rs +++ b/src/route.rs @@ -1,13 +1,12 @@ +use crate::handler::health::health_check; +use crate::handler::message::send_message; use axum::{ routing::{get, post}, - Router + Router, }; -use crate::handler::health::{health_check}; -use crate::handler::message::{send_message}; - pub fn create_route() -> Router { Router::new() .route("/health", get(health_check)) .route("/message", post(send_message)) -} \ No newline at end of file +} diff --git a/utils/Cargo.toml b/utils/Cargo.toml new file mode 100644 index 0000000..a0cba9a --- /dev/null +++ b/utils/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/utils/src/lib.rs b/utils/src/lib.rs new file mode 100644 index 0000000..19b834f --- /dev/null +++ b/utils/src/lib.rs @@ -0,0 +1,24 @@ +pub enum ResourceType { + OPEN, + USER, + ADMIN, +} + +impl ResourceType { + fn as_str(&self) -> &str { + match self { + ResourceType::OPEN => "OPEN", + ResourceType::USER => "USER", + ResourceType::ADMIN => "ADMIN", + } + } + + fn from_str(s: &str) -> ResourceType { + match s { + "OPEN" => ResourceType::OPEN, + "USER" => ResourceType::USER, + "ADMIN" => ResourceType::ADMIN, + _ => panic!("Invalid resource type"), + } + } +}