Skip to content

Instantly share code, notes, and snippets.

@oscartbeaumont
Created December 26, 2021 01:30
Show Gist options
  • Save oscartbeaumont/6341b14282d6fff7f6849c62a6573128 to your computer and use it in GitHub Desktop.
Save oscartbeaumont/6341b14282d6fff7f6849c62a6573128 to your computer and use it in GitHub Desktop.
Async GraphQL Field Guard on Complex Object Not Working
[package]
name = "async-graphql-example"
version = "0.1.0"
authors = ["Oscar Beaumont <[email protected]>"]
edition = "2018"
[dependencies]
async-graphql = "3.0.17"
actix-web = "4.0.0-beta.14"
async-graphql-actix-web = "3.0.17"
async-trait = "0.1.52"
use actix_web::guard;
use actix_web::web::Data;
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig};
use async_graphql::{
ComplexObject, Context, EmptyMutation, EmptySubscription, Error, Guard, Object, SimpleObject,
};
use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};
#[derive(Eq, PartialEq, Copy, Clone)]
enum Role {
Admin,
Guest,
}
struct RoleGuard {
role: Role,
}
impl RoleGuard {
fn new(role: Role) -> Self {
Self { role }
}
}
#[async_trait::async_trait]
impl Guard for RoleGuard {
async fn check(&self, ctx: &Context<'_>) -> Result<(), Error> {
if ctx.data_opt::<Role>() == Some(&self.role) {
Ok(())
} else {
Err("Forbidden".into())
}
}
}
#[derive(SimpleObject)]
#[graphql(complex)]
pub struct Test {
pub name: String,
}
#[ComplexObject]
impl Test {
#[graphql(guard = "RoleGuard::new(Role::Admin)")] // This line is what is causing the code to not compile
async fn test(&self) -> String {
"Hello World".into()
}
}
pub struct QueryRoot;
#[Object]
impl QueryRoot {
#[graphql(guard = "RoleGuard::new(Role::Admin)")]
async fn test(&self) -> Test {
Test {
name: "Oscar".into(),
}
}
}
pub type Schema = async_graphql::Schema<QueryRoot, EmptyMutation, EmptySubscription>;
pub async fn handler(schema: web::Data<Schema>, req: GraphQLRequest) -> GraphQLResponse {
schema.execute(req.into_inner()).await.into()
}
pub async fn playground() -> impl Responder {
HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(playground_source(GraphQLPlaygroundConfig::new("/")))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish();
println!("Listening http://localhost:8080/ ...");
HttpServer::new(move || {
App::new()
.app_data(Data::new(schema.clone()))
.service(web::resource("/").guard(guard::Post()).to(handler))
.service(web::resource("/").guard(guard::Get()).to(playground))
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment