From a19298beafd786a797c18cca90c4abb02bcee266 Mon Sep 17 00:00:00 2001 From: Sunli Date: Thu, 30 Jun 2022 10:50:45 +0800 Subject: [PATCH] Implement `Guard` for `Fn` --- src/guard.rs | 10 ++++++++++ tests/guard.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/guard.rs b/src/guard.rs index 8285e4ed..ca7140e7 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -12,6 +12,16 @@ pub trait Guard { async fn check(&self, ctx: &Context<'_>) -> Result<()>; } +#[async_trait::async_trait] +impl Guard for T +where + T: Fn(&Context<'_>) -> Result<()> + Send + Sync + 'static, +{ + async fn check(&self, ctx: &Context<'_>) -> Result<()> { + self(ctx) + } +} + /// An extension trait for `Guard`. pub trait GuardExt: Guard + Sized { /// Perform `and` operator on two rules diff --git a/tests/guard.rs b/tests/guard.rs index 32227608..872b72fa 100644 --- a/tests/guard.rs +++ b/tests/guard.rs @@ -583,3 +583,46 @@ pub async fn test_guard_on_complex_object_field() { }] ); } + +#[tokio::test] +pub async fn test_guard_with_fn() { + fn is_admin(ctx: &Context<'_>) -> Result<()> { + if ctx.data_opt::() == Some(&Role::Admin) { + Ok(()) + } else { + Err("Forbidden".into()) + } + } + + #[derive(SimpleObject)] + struct Query { + #[graphql(guard = "is_admin")] + value: i32, + } + + let schema = Schema::new(Query { value: 10 }, EmptyMutation, EmptySubscription); + + let query = "{ value }"; + assert_eq!( + schema + .execute(Request::new(query).data(Role::Admin)) + .await + .data, + value!({"value": 10}) + ); + + assert_eq!( + schema + .execute(Request::new(query).data(Role::Guest)) + .await + .into_result() + .unwrap_err(), + vec![ServerError { + message: "Forbidden".to_string(), + source: None, + locations: vec![Pos { line: 1, column: 3 }], + path: vec![PathSegment::Field("value".to_owned())], + extensions: None, + }] + ); +}