Implement `Guard` for `Fn`

This commit is contained in:
Sunli 2022-06-30 10:50:45 +08:00
parent d551c982b3
commit a19298beaf
2 changed files with 53 additions and 0 deletions

View File

@ -12,6 +12,16 @@ pub trait Guard {
async fn check(&self, ctx: &Context<'_>) -> Result<()>;
}
#[async_trait::async_trait]
impl<T> 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

View File

@ -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::<Role>() == 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,
}]
);
}