From beb4b2238a94d64a4b411263e5545f9a9aaf6332 Mon Sep 17 00:00:00 2001 From: Aurelien Foucault Date: Sat, 3 Oct 2020 21:34:29 +0200 Subject: [PATCH] Implement the new and operator --- derive/src/utils.rs | 56 +++++++++++++++++++-------------------------- tests/guard.rs | 26 ++++++++++++++++++--- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/derive/src/utils.rs b/derive/src/utils.rs index f51cb16b..f3585f19 100644 --- a/derive/src/utils.rs +++ b/derive/src/utils.rs @@ -129,34 +129,36 @@ pub fn generate_guards( Some(ident) => { match ident.to_string().as_str() { "guard" => { - println!("ident guard found {:#?}\n", ident); - if args.nested.len() > 1 { + if args.nested.len() != 1 { return Err(Error::new_spanned(args, "Chained rules isn't possible anymore, please use operators.").into()); } - // why moved ? Want to use it in error - match &args.nested[0] { - NestedMeta::Meta(rule) => { - println! ("rule sended = {:#?}\n", rule); - return generate_guards(crate_name, rule); - } - _ => { - return Err(Error::new_spanned(args, "Invalid guard (to be improve)").into()); - } + if let NestedMeta::Meta(rule) = &args.nested[0] { + return generate_guards(crate_name, rule); + } else { + return Err(Error::new_spanned(&args.nested[0], "Invalid rule.").into()); } } "and" => { - println!("ident and found {:#?}\n", ident); - return Err(Error::new_spanned(args, "WIP").into()); + if args.nested.len() != 2 { + return Err(Error::new_spanned(args, "and operator support only 2 operands.").into()); + } + let first_rule: Option; + let second_rule: Option; + if let NestedMeta::Meta(rule) = &args.nested[0] { + first_rule = generate_guards(crate_name, rule)?; + } else { + return Err(Error::new_spanned(&args.nested[0], "Invalid rule.").into()); + } + if let NestedMeta::Meta(rule) = &args.nested[1] { + second_rule = generate_guards(crate_name, rule)?; + } else { + return Err(Error::new_spanned(&args.nested[1], "Invalid rule.").into()); + } + Ok(Some(quote! { #crate_name::guard::GuardExt::and(#first_rule, #second_rule) })) } _ => { - let mut guards = None; - //args == "guard" - println!("items = {:#?}\n", &args.nested); let ty = &args.path; - //ty = the rule - println!("ty = {:#?}\n", ty); let mut params = Vec::new(); - //rules params for attr in &args.nested { if let NestedMeta::Meta(Meta::NameValue(nv)) = attr { let name = &nv.path; @@ -182,26 +184,16 @@ pub fn generate_guards( ); } } - let guard = quote! { #ty { #(#params),* } }; - if guards.is_none() { - guards = Some(guard); - } else { - guards = - Some(quote! { #crate_name::guard::GuardExt::and(#guard, #guards) }); - } - println!("end of function"); - Ok(guards) - //return Err(Error::new_spanned(ident, "Invalid guard (to be improve 2)").into()); + Ok(Some(quote! { #ty { #(#params),* } })) } } }, None => { - println!("failed for the moment"); - return Err(Error::new_spanned(args, "WIP").into()); + Err(Error::new_spanned(args, "Invalid guards").into()) } } } - _ => Err(Error::new_spanned(args, "Invalid guards (old)").into()), + _ => Err(Error::new_spanned(args, "Invalid guards").into()), } } diff --git a/tests/guard.rs b/tests/guard.rs index 48a264da..91819757 100644 --- a/tests/guard.rs +++ b/tests/guard.rs @@ -42,19 +42,20 @@ impl Guard for UserGuard { #[async_std::test] pub async fn test_multiple_guards() { + #[derive(SimpleObject)] struct Query { - #[graphql(guard(RoleGuard(role = "Role::Admin")))] + #[graphql(guard(and(RoleGuard(role = "Role::Admin"), UserGuard(username = r#""test""#))))] value: i32, } #[derive(SimpleObject)] struct Mutation { - value: i32, + value_m: i32, } - let schema = Schema::new(Query { value: 10 }, Mutation {value: 11}, EmptySubscription); + let schema = Schema::new(Query { value: 10 }, Mutation {valueM: 11}, EmptySubscription); let query = "{ value }"; assert_eq!( @@ -88,4 +89,23 @@ pub async fn test_multiple_guards() { }] ); + let query = "{ value }"; + assert_eq!( + schema + .execute( + Request::new(query) + .data(Role::Admin) + .data(Username("test1".to_string())) + ) + .await + .into_result() + .unwrap_err(), + vec![ServerError { + message: "Forbidden".to_string(), + locations: vec![Pos { line: 1, column: 3 }], + path: vec![PathSegment::Field("value".to_owned())], + extensions: None, + }] + ); + }