Skip to content

Commit e839ffa

Browse files
committed
Implement Guard for Fn
1 parent 175d869 commit e839ffa

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

src/guard.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ pub trait Guard {
1212
async fn check(&self, ctx: &Context<'_>) -> Result<()>;
1313
}
1414

15+
#[async_trait::async_trait]
16+
impl<T> Guard for T
17+
where
18+
T: Fn(&Context<'_>) -> Result<()> + Send + Sync + 'static,
19+
{
20+
async fn check(&self, ctx: &Context<'_>) -> Result<()> {
21+
self(ctx)
22+
}
23+
}
24+
1525
/// An extension trait for `Guard`.
1626
pub trait GuardExt: Guard + Sized {
1727
/// Perform `and` operator on two rules

tests/guard.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,3 +583,46 @@ pub async fn test_guard_on_complex_object_field() {
583583
}]
584584
);
585585
}
586+
587+
#[tokio::test]
588+
pub async fn test_guard_with_fn() {
589+
fn is_admin(ctx: &Context<'_>) -> Result<()> {
590+
if ctx.data_opt::<Role>() == Some(&Role::Admin) {
591+
Ok(())
592+
} else {
593+
Err("Forbidden".into())
594+
}
595+
}
596+
597+
#[derive(SimpleObject)]
598+
struct Query {
599+
#[graphql(guard = "is_admin")]
600+
value: i32,
601+
}
602+
603+
let schema = Schema::new(Query { value: 10 }, EmptyMutation, EmptySubscription);
604+
605+
let query = "{ value }";
606+
assert_eq!(
607+
schema
608+
.execute(Request::new(query).data(Role::Admin))
609+
.await
610+
.data,
611+
value!({"value": 10})
612+
);
613+
614+
assert_eq!(
615+
schema
616+
.execute(Request::new(query).data(Role::Guest))
617+
.await
618+
.into_result()
619+
.unwrap_err(),
620+
vec![ServerError {
621+
message: "Forbidden".to_string(),
622+
source: None,
623+
locations: vec![Pos { line: 1, column: 3 }],
624+
path: vec![PathSegment::Field("value".to_owned())],
625+
extensions: None,
626+
}]
627+
);
628+
}

0 commit comments

Comments
 (0)