diff --git a/derive/src/utils.rs b/derive/src/utils.rs index 276f75f8..f51cb16b 100644 --- a/derive/src/utils.rs +++ b/derive/src/utils.rs @@ -121,52 +121,87 @@ pub fn generate_guards( crate_name: &TokenStream, args: &Meta, ) -> GeneratorResult> { + println!("{:#?}\n", args); match args { Meta::List(args) => { - let mut guards = None; - for item in &args.nested { - if let NestedMeta::Meta(Meta::List(ls)) = item { - let ty = &ls.path; - let mut params = Vec::new(); - for attr in &ls.nested { - if let NestedMeta::Meta(Meta::NameValue(nv)) = attr { - let name = &nv.path; - if let Lit::Str(value) = &nv.lit { - let value_str = value.value(); - if value_str.starts_with('@') { - let getter_name = get_param_getter_ident(&value_str[1..]); - params.push(quote! { #name: #getter_name()? }); - } else { - let expr = syn::parse_str::(&value_str)?; - params.push(quote! { #name: (#expr).into() }); - } - } else { - return Err(Error::new_spanned( - &nv.lit, - "Value must be string literal", - ) - .into()); + println!("args = {:#?}\n", args.path); + match args.path.get_ident() { + Some(ident) => { + match ident.to_string().as_str() { + "guard" => { + println!("ident guard found {:#?}\n", ident); + if args.nested.len() > 1 { + return Err(Error::new_spanned(args, "Chained rules isn't possible anymore, please use operators.").into()); } - } else { - return Err( - Error::new_spanned(attr, "Invalid property for guard").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()); + } + } + } + "and" => { + println!("ident and found {:#?}\n", ident); + return Err(Error::new_spanned(args, "WIP").into()); + } + _ => { + 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; + if let Lit::Str(value) = &nv.lit { + let value_str = value.value(); + if value_str.starts_with('@') { + let getter_name = get_param_getter_ident(&value_str[1..]); + params.push(quote! { #name: #getter_name()? }); + } else { + let expr = syn::parse_str::(&value_str)?; + params.push(quote! { #name: (#expr).into() }); + } + } else { + return Err(Error::new_spanned( + &nv.lit, + "Value must be string literal", + ) + .into()); + } + } else { + return Err( + Error::new_spanned(attr, "Invalid property for guard").into() + ); + } + } + 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()); } } - let guard = quote! { #ty { #(#params),* } }; - if guards.is_none() { - guards = Some(guard); - } else { - guards = - Some(quote! { #crate_name::guard::GuardExt::and(#guard, #guards) }); - } - } else { - return Err(Error::new_spanned(item, "Invalid guard").into()); + }, + None => { + println!("failed for the moment"); + return Err(Error::new_spanned(args, "WIP").into()); } } - Ok(guards) } - _ => Err(Error::new_spanned(args, "Invalid guards").into()), + _ => Err(Error::new_spanned(args, "Invalid guards (old)").into()), } } diff --git a/tests/guard.rs b/tests/guard.rs index 5a9e2afa..48a264da 100644 --- a/tests/guard.rs +++ b/tests/guard.rs @@ -40,137 +40,21 @@ impl Guard for UserGuard { } } -#[async_std::test] -pub async fn test_guard() { - #[derive(SimpleObject)] - struct MyObj { - #[graphql(guard(RoleGuard(role = "Role::Admin")))] - value: i32, - } - - struct Query; - - #[Object] - impl Query { - #[graphql(guard(RoleGuard(role = "Role::Admin")))] - async fn value(&self) -> i32 { - 1 - } - - async fn obj(&self) -> MyObj { - MyObj { value: 99 } - } - } - - struct Subscription; - - #[Subscription] - impl Subscription { - #[graphql(guard(RoleGuard(role = "Role::Admin")))] - async fn values(&self) -> impl Stream { - futures::stream::iter(vec![1, 2, 3]) - } - } - - let schema = Schema::new(Query, EmptyMutation, Subscription); - - let query = "{ obj { value } }"; - assert_eq!( - schema - .execute(Request::new(query).data(Role::Admin)) - .await - .data, - serde_json::json!({ - "obj": {"value": 99} - }) - ); - - let query = "{ obj { value } }"; - assert_eq!( - schema - .execute(Request::new(query).data(Role::Guest)) - .await - .into_result() - .unwrap_err(), - vec![ServerError { - message: "Forbidden".to_owned(), - locations: vec![Pos { line: 1, column: 9 }], - path: vec![ - PathSegment::Field("obj".to_owned()), - PathSegment::Field("value".to_owned()) - ], - extensions: None, - }] - ); - - let query = "{ value }"; - assert_eq!( - schema - .execute(Request::new(query).data(Role::Admin)) - .await - .data, - serde_json::json!({ - "value": 1, - }) - ); - - let query = "{ value }"; - assert_eq!( - schema - .execute(Request::new(query).data(Role::Guest)) - .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, - }] - ); - - assert_eq!( - schema - .execute_stream(Request::new("subscription { values }").data(Role::Admin)) - .map(|item| item.data) - .collect::>() - .await, - vec![ - serde_json::json! ({"values": 1}), - serde_json::json! ({"values": 2}), - serde_json::json! ({"values": 3}) - ] - ); - - assert_eq!( - schema - .execute_stream(Request::new("subscription { values }").data(Role::Guest)) - .boxed() - .next() - .await - .unwrap() - .errors, - vec![ServerError { - message: "Forbidden".to_string(), - locations: vec![Pos { - line: 1, - column: 16 - }], - path: vec![PathSegment::Field("values".to_owned())], - extensions: None, - }] - ); -} - #[async_std::test] pub async fn test_multiple_guards() { #[derive(SimpleObject)] struct Query { - #[graphql(guard(RoleGuard(role = "Role::Admin"), UserGuard(username = r#""test""#)))] + #[graphql(guard(RoleGuard(role = "Role::Admin")))] value: i32, } - let schema = Schema::new(Query { value: 10 }, EmptyMutation, EmptySubscription); + #[derive(SimpleObject)] + struct Mutation { + value: i32, + } + + + let schema = Schema::new(Query { value: 10 }, Mutation {value: 11}, EmptySubscription); let query = "{ value }"; assert_eq!( @@ -204,95 +88,4 @@ 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, - }] - ); - - let query = "{ value }"; - assert_eq!( - schema - .execute( - Request::new(query) - .data(Role::Guest) - .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, - }] - ); -} - -#[async_std::test] -pub async fn test_guard_forward_arguments() { - struct UserGuard { - id: ID, - } - - #[async_trait::async_trait] - impl Guard for UserGuard { - async fn check(&self, ctx: &Context<'_>) -> Result<()> { - if ctx.data_opt::() != Some(&self.id) { - Err("Forbidden".into()) - } else { - Ok(()) - } - } - } - - struct QueryRoot; - - #[Object] - impl QueryRoot { - #[graphql(guard(UserGuard(id = "@id")))] - async fn user(&self, id: ID) -> ID { - id - } - } - - let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription); - - let query = r#"{ user(id: "abc") }"#; - assert_eq!( - schema - .execute(Request::new(query).data(ID::from("abc"))) - .await - .data, - serde_json::json!({"user": "abc"}) - ); - - let query = r#"{ user(id: "abc") }"#; - assert_eq!( - schema - .execute(Request::new(query).data(ID::from("aaa"))) - .await - .into_result() - .unwrap_err(), - vec![ServerError { - message: "Forbidden".to_string(), - locations: vec![Pos { line: 1, column: 3 }], - path: vec![PathSegment::Field("user".to_owned())], - extensions: None, - }] - ); }