This commit is contained in:
Aurelien Foucault 2020-10-03 23:03:40 +02:00
parent 5b03bce2e8
commit 549aa7cc72
2 changed files with 97 additions and 91 deletions

View File

@ -126,89 +126,101 @@ pub fn generate_guards(
Meta::List(args) => {
println!("args = {:#?}\n", args.path);
match args.path.get_ident() {
Some(ident) => {
match ident.to_string().as_str() {
"guard" => {
if args.nested.len() != 1 {
return Err(Error::new_spanned(args, "Chained rules isn't possible anymore, please use operators.").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());
}
Some(ident) => match ident.to_string().as_str() {
"guard" => {
if args.nested.len() != 1 {
return Err(Error::new_spanned(
args,
"Chained rules isn't possible anymore, please use operators.",
)
.into());
}
"and" => {
if args.nested.len() != 2 {
return Err(Error::new_spanned(args, "and operator support only 2 operands.").into());
}
let first_rule: Option<TokenStream>;
let second_rule: Option<TokenStream>;
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) }))
}
"or" => {
if args.nested.len() != 2 {
return Err(Error::new_spanned(args, "or operator support only 2 operands.").into());
}
let first_rule: Option<TokenStream>;
let second_rule: Option<TokenStream>;
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::or(#first_rule, #second_rule) }))
}
_ => {
let ty = &args.path;
let mut params = Vec::new();
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::<Expr>(&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()
);
}
}
Ok(Some(quote! { #ty { #(#params),* } }))
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" => {
if args.nested.len() != 2 {
return Err(Error::new_spanned(
args,
"and operator support only 2 operands.",
)
.into());
}
let first_rule: Option<TokenStream>;
let second_rule: Option<TokenStream>;
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) },
))
}
"or" => {
if args.nested.len() != 2 {
return Err(Error::new_spanned(
args,
"or operator support only 2 operands.",
)
.into());
}
let first_rule: Option<TokenStream>;
let second_rule: Option<TokenStream>;
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::or(#first_rule, #second_rule) },
))
}
_ => {
let ty = &args.path;
let mut params = Vec::new();
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::<Expr>(&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()
);
}
}
Ok(Some(quote! { #ty { #(#params),* } }))
}
},
None => {
Err(Error::new_spanned(args, "Invalid guards").into())
}
None => Err(Error::new_spanned(args, "Invalid guards").into()),
}
}
_ => Err(Error::new_spanned(args, "Invalid guards").into()),

View File

@ -42,7 +42,6 @@ impl Guard for UserGuard {
#[async_std::test]
pub async fn test_guard_simple_rule() {
#[derive(SimpleObject)]
struct Query {
#[graphql(guard(RoleGuard(role = "Role::Admin")))]
@ -54,10 +53,7 @@ pub async fn test_guard_simple_rule() {
let query = "{ value }";
assert_eq!(
schema
.execute(
Request::new(query)
.data(Role::Admin)
)
.execute(Request::new(query).data(Role::Admin))
.await
.data,
serde_json::json!({"value": 10})
@ -66,10 +62,7 @@ pub async fn test_guard_simple_rule() {
let query = "{ value }";
assert_eq!(
schema
.execute(
Request::new(query)
.data(Role::Guest)
)
.execute(Request::new(query).data(Role::Guest))
.await
.into_result()
.unwrap_err(),
@ -84,10 +77,12 @@ pub async fn test_guard_simple_rule() {
#[async_std::test]
pub async fn test_guard_and_operator() {
#[derive(SimpleObject)]
struct Query {
#[graphql(guard(and(RoleGuard(role = "Role::Admin"), UserGuard(username = r#""test""#))))]
#[graphql(guard(and(
RoleGuard(role = "Role::Admin"),
UserGuard(username = r#""test""#)
)))]
value: i32,
}
@ -166,7 +161,6 @@ pub async fn test_guard_and_operator() {
#[async_std::test]
pub async fn test_guard_or_operator() {
#[derive(SimpleObject)]
struct Query {
#[graphql(guard(or(RoleGuard(role = "Role::Admin"), UserGuard(username = r#""test""#))))]