async-graphql/docs/zh-CN/src/field_guard.md
2020-10-07 13:40:03 +08:00

1.9 KiB
Raw Blame History

字段守卫(Field Guard)

您可以在给Object的字段定义守卫。 这允许在运行字段的代码逻辑之前添加检查。 义守卫由你预先定义的规则组成。 规则是一种实现Guard特质的结构。

#[derive(Eq, PartialEq, Copy, Clone)]
enum Role {
    Admin,
    Guest,
}

struct RoleGuard {
    role: Role,
}

#[async_trait::async_trait]
impl Guard for RoleGuard {
    async fn check(&self, ctx: &Context<'_>) -> Result<()> {
        if ctx.data_opt::<Role>() == Some(&self.role) {
            Ok(())
        } else {
            Err("Forbidden".into())
        }
    }
}

一旦定义了规则,就可以在guard字段属性中使用它。 此属性支持4个运算符创建复杂的规则

-and:在两个规则之间执行运算。 (如果一个规则返回错误,则and运算符将返回错误。如果两个规则均返回错误,则将是第一个返回的错误)。

-or:在两个规则之间执行运算。 (如果两个规则都返回错误,则返回的错误是第一个)

-chain:采用一组规则并运行它们,直到返回错误或如果所有规则都通过则返回Ok

-race:采用一组规则并运行它们,直到其中一个返回Ok

#[derive(SimpleObject)]
struct Query {
    #[graphql(guard(RoleGuard(role = "Role::Admin")))]
    value: i32,
    #[graphql(guard(and(
        RoleGuard(role = "Role::Admin"),
        UserGuard(username = r#""test""#)
    )))]
    value2: i32,
    #[graphql(guard(or(
        RoleGuard(role = "Role::Admin"),
        UserGuard(username = r#""test""#)
    )))]
    value3: i32,
    #[graphql(guard(chain(
        RoleGuard(role = "Role::Admin"),
        UserGuard(username = r#""test""#),
        AgeGuard(age = r#"21"#)
    )))]
    value4: i32,
    #[graphql(guard(race(
        RoleGuard(role = "Role::Admin"),
        UserGuard(username = r#""test""#),
        AgeGuard(age = r#"21"#)
    )))]
    value5: i32,
}