diff --git a/examples/helloworld/Cargo.toml b/examples/helloworld/Cargo.toml new file mode 100644 index 0000000..75bea16 --- /dev/null +++ b/examples/helloworld/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "helloworld" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +axum = "0.7.1" +axum_jwt_ware = { version = "0.1.4", path = "../.." } +chrono = "0.4.31" +tokio = "1.34.0" + + diff --git a/examples/helloworld/src/main.rs b/examples/helloworld/src/main.rs new file mode 100644 index 0000000..f210c94 --- /dev/null +++ b/examples/helloworld/src/main.rs @@ -0,0 +1,13 @@ +mod route; +use route::create_router; +mod service; +pub use axum_jwt_ware; + + +#[tokio::main] +async fn main() { + let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); + axum::serve(listener, create_router().into_make_service()) + .await + .unwrap(); +} \ No newline at end of file diff --git a/examples/helloworld/src/route.rs b/examples/helloworld/src/route.rs new file mode 100644 index 0000000..3967a7b --- /dev/null +++ b/examples/helloworld/src/route.rs @@ -0,0 +1,60 @@ +use crate::service::{hello, MyUserData}; +use axum::{ + middleware, + routing::{get, post}, + Json, Router, +}; +use axum_jwt_ware::{self, refresh_token, Claims, DecodingContext, EncodingContext, RefreshBody}; +use chrono::{Duration, Utc}; + +pub fn create_router() -> Router { + let user_data = MyUserData; + let jwt_secret = "secret"; + let refresh_secret = "refresh_secret"; + + let app = Router::new() + .route( + "/hello", + get(hello).layer(middleware::from_fn(move |req, next| { + let key = axum_jwt_ware::DecodingKey::from_secret(jwt_secret.as_ref()); + let validation = axum_jwt_ware::Validation::default(); + async move { axum_jwt_ware::verify_user(req, &key, validation, next).await } + })), + ) + .route( + "/login", + post(move |body: Json| { + let expiry_timestamp = Utc::now() + Duration::hours(48); + + axum_jwt_ware::login( + body, + user_data.clone(), + jwt_secret, + refresh_secret, + expiry_timestamp.timestamp(), + ) + }), + ) + .route( + "/refresh", + post(move |body: Json| { + let encoding_context = EncodingContext { + header: axum_jwt_ware::Header::default(), + validation: axum_jwt_ware::Validation::default(), + key: axum_jwt_ware::EncodingKey::from_secret("refresh_secret".as_ref()), + }; + let decoding_context = DecodingContext { + header: axum_jwt_ware::Header::default(), + validation: axum_jwt_ware::Validation::default(), + key: axum_jwt_ware::DecodingKey::from_secret("refresh_secret".as_ref()), + }; + let claims = Claims { + sub: "jkfajfafghjjfn".to_string(), + username: "ezesunday".to_string(), + exp: (Utc::now() + Duration::hours(48)).timestamp(), + }; + refresh_token(body, encoding_context, decoding_context, claims) + }), + ); + app +} diff --git a/examples/helloworld/src/service.rs b/examples/helloworld/src/service.rs new file mode 100644 index 0000000..b8ea71c --- /dev/null +++ b/examples/helloworld/src/service.rs @@ -0,0 +1,25 @@ +use axum::{Extension, Json}; +use crate::axum_jwt_ware::{UserData, CurrentUser, Claims}; + +#[derive(Clone, Copy)] +pub struct MyUserData; + +impl UserData for MyUserData { + fn get_user_by_email(&self, _email: &str) -> Option { + // Implement the logic to fetch user by email from your database + // This is just a placeholder; replace it with the actual implementation + Some(CurrentUser { + password: "password".to_string(), + name: "Eze Sunday".to_string(), + email: "mailstoeze@gmail.com".to_string(), + username: "ezesunday".to_string(), + id: "jkfajfafghjjfn".to_string(), + }) + } +} + +pub async fn hello( + Extension(claims): Extension, +) -> Json { + Json(claims) +}