Fmt, clippy and remove post guard
This commit is contained in:
parent
a935b867c7
commit
35a21d1994
@ -69,8 +69,6 @@ pub struct SimpleObjectField {
|
|||||||
pub requires: Option<String>,
|
pub requires: Option<String>,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub guard: Option<Meta>,
|
pub guard: Option<Meta>,
|
||||||
#[darling(default)]
|
|
||||||
pub post_guard: Option<Meta>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromDeriveInput)]
|
#[derive(FromDeriveInput)]
|
||||||
@ -123,7 +121,6 @@ pub struct ObjectField {
|
|||||||
pub provides: Option<String>,
|
pub provides: Option<String>,
|
||||||
pub requires: Option<String>,
|
pub requires: Option<String>,
|
||||||
pub guard: Option<Meta>,
|
pub guard: Option<Meta>,
|
||||||
pub post_guard: Option<Meta>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromDeriveInput)]
|
#[derive(FromDeriveInput)]
|
||||||
@ -302,7 +299,6 @@ pub struct SubscriptionField {
|
|||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub deprecation: Option<String>,
|
pub deprecation: Option<String>,
|
||||||
pub guard: Option<Meta>,
|
pub guard: Option<Meta>,
|
||||||
pub post_guard: Option<Meta>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromMeta, Default)]
|
#[derive(FromMeta, Default)]
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::args;
|
use crate::args;
|
||||||
use crate::output_type::OutputType;
|
use crate::output_type::OutputType;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
generate_default, generate_guards, generate_post_guards, generate_validator, get_cfg_attrs,
|
generate_default, generate_guards, generate_validator, get_cfg_attrs, get_crate_name,
|
||||||
get_crate_name, get_param_getter_ident, get_rustdoc, parse_graphql_attrs, remove_graphql_attrs,
|
get_param_getter_ident, get_rustdoc, parse_graphql_attrs, remove_graphql_attrs,
|
||||||
GeneratorResult,
|
GeneratorResult,
|
||||||
};
|
};
|
||||||
use inflector::Inflector;
|
use inflector::Inflector;
|
||||||
@ -428,18 +428,6 @@ pub fn generate(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let post_guard = match &method_args.post_guard {
|
|
||||||
Some(meta_list) => generate_post_guards(&crate_name, meta_list)?,
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let post_guard = post_guard.map(|guard| {
|
|
||||||
quote! {
|
|
||||||
#guard.check(ctx, &res).await
|
|
||||||
.map_err(|err| err.into_server_error().at(ctx.item.pos))?;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
resolvers.push(quote! {
|
resolvers.push(quote! {
|
||||||
#(#cfg_attrs)*
|
#(#cfg_attrs)*
|
||||||
if ctx.item.node.name.node == #field_name {
|
if ctx.item.node.name.node == #field_name {
|
||||||
@ -447,7 +435,6 @@ pub fn generate(
|
|||||||
#guard
|
#guard
|
||||||
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
|
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
|
||||||
let res = #resolve_obj;
|
let res = #resolve_obj;
|
||||||
#post_guard
|
|
||||||
return #crate_name::OutputValueType::resolve(&res, &ctx_obj, ctx.item).await.map(::std::option::Option::Some);
|
return #crate_name::OutputValueType::resolve(&res, &ctx_obj, ctx.item).await.map(::std::option::Option::Some);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use crate::args;
|
use crate::args;
|
||||||
use crate::utils::{
|
use crate::utils::{generate_guards, get_crate_name, get_rustdoc, GeneratorResult};
|
||||||
generate_guards, generate_post_guards, get_crate_name, get_rustdoc, GeneratorResult,
|
|
||||||
};
|
|
||||||
use darling::ast::Data;
|
use darling::ast::Data;
|
||||||
use inflector::Inflector;
|
use inflector::Inflector;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
@ -102,12 +100,6 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||||||
};
|
};
|
||||||
let guard = guard.map(|guard| quote! { #guard.check(ctx).await.map_err(|err| err.into_server_error().at(ctx.item.pos))?; });
|
let guard = guard.map(|guard| quote! { #guard.check(ctx).await.map_err(|err| err.into_server_error().at(ctx.item.pos))?; });
|
||||||
|
|
||||||
let post_guard = match &field.post_guard {
|
|
||||||
Some(meta) => generate_post_guards(&crate_name, &meta)?,
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
let post_guard = post_guard.map(|guard| quote! { #guard.check(ctx, &res).await.map_err(|err| err.into_server_error().at(ctx.item.pos))?; });
|
|
||||||
|
|
||||||
getters.push(if !field.owned {
|
getters.push(if !field.owned {
|
||||||
quote! {
|
quote! {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -131,7 +123,6 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||||||
#guard
|
#guard
|
||||||
let res = self.#ident(ctx).await.map_err(|err| err.into_server_error().at(ctx.item.pos))?;
|
let res = self.#ident(ctx).await.map_err(|err| err.into_server_error().at(ctx.item.pos))?;
|
||||||
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
|
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
|
||||||
#post_guard
|
|
||||||
return #crate_name::OutputValueType::resolve(&res, &ctx_obj, ctx.item).await.map(::std::option::Option::Some);
|
return #crate_name::OutputValueType::resolve(&res, &ctx_obj, ctx.item).await.map(::std::option::Option::Some);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -260,13 +260,6 @@ pub fn generate(
|
|||||||
let guard = guard.map(|guard| quote! {
|
let guard = guard.map(|guard| quote! {
|
||||||
#guard.check(ctx).await.map_err(|err| err.into_server_error().at(ctx.item.pos))?;
|
#guard.check(ctx).await.map_err(|err| err.into_server_error().at(ctx.item.pos))?;
|
||||||
});
|
});
|
||||||
if field.post_guard.is_some() {
|
|
||||||
return Err(Error::new_spanned(
|
|
||||||
method,
|
|
||||||
"The subscription field does not support post guard",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream_fn = quote! {
|
let stream_fn = quote! {
|
||||||
#(#get_params)*
|
#(#get_params)*
|
||||||
|
@ -122,165 +122,120 @@ pub fn generate_guards(
|
|||||||
args: &Meta,
|
args: &Meta,
|
||||||
) -> GeneratorResult<Option<TokenStream>> {
|
) -> GeneratorResult<Option<TokenStream>> {
|
||||||
match args {
|
match args {
|
||||||
Meta::List(args) => {
|
Meta::List(args) => match args.path.get_ident() {
|
||||||
match args.path.get_ident() {
|
Some(ident) => match ident.to_string().as_str() {
|
||||||
Some(ident) => match ident.to_string().as_str() {
|
"guard" => {
|
||||||
"guard" => {
|
if args.nested.len() != 1 {
|
||||||
if args.nested.len() != 1 {
|
return Err(Error::new_spanned(
|
||||||
return Err(Error::new_spanned(
|
args,
|
||||||
args,
|
"Chained rules isn't possible anymore, please use operators.",
|
||||||
"Chained rules isn't possible anymore, please use operators.",
|
)
|
||||||
)
|
.into());
|
||||||
.into());
|
|
||||||
}
|
|
||||||
if let NestedMeta::Meta(rule) = &args.nested[0] {
|
|
||||||
generate_guards(crate_name, rule)
|
|
||||||
} else {
|
|
||||||
Err(Error::new_spanned(&args.nested[0], "Invalid rule.").into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"and" => {
|
if let NestedMeta::Meta(rule) = &args.nested[0] {
|
||||||
if args.nested.len() != 2 {
|
generate_guards(crate_name, rule)
|
||||||
return Err(Error::new_spanned(
|
} else {
|
||||||
args,
|
Err(Error::new_spanned(&args.nested[0], "Invalid rule.").into())
|
||||||
"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 {
|
"and" => {
|
||||||
return Err(Error::new_spanned(
|
if args.nested.len() != 2 {
|
||||||
args,
|
return Err(Error::new_spanned(
|
||||||
"or operator support only 2 operands.",
|
args,
|
||||||
)
|
"and operator support only 2 operands.",
|
||||||
.into());
|
)
|
||||||
}
|
.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) },
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
"chain" => {
|
let first_rule: Option<TokenStream>;
|
||||||
if args.nested.len() < 2 {
|
let second_rule: Option<TokenStream>;
|
||||||
return Err(Error::new_spanned(
|
if let NestedMeta::Meta(rule) = &args.nested[0] {
|
||||||
args,
|
first_rule = generate_guards(crate_name, rule)?;
|
||||||
"chain operator need at least 1 operand.",
|
} else {
|
||||||
)
|
return Err(Error::new_spanned(&args.nested[0], "Invalid rule.").into());
|
||||||
.into());
|
|
||||||
}
|
|
||||||
let mut guards: Option<TokenStream> = None;
|
|
||||||
for arg in &args.nested {
|
|
||||||
if let NestedMeta::Meta(rule) = &arg {
|
|
||||||
let guard = generate_guards(crate_name, rule)?;
|
|
||||||
if guards.is_none() {
|
|
||||||
guards = guard;
|
|
||||||
} else {
|
|
||||||
guards =
|
|
||||||
Some(quote! { #crate_name::guard::GuardExt::and(#guard, #guards) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(guards)
|
|
||||||
}
|
}
|
||||||
"race" => {
|
if let NestedMeta::Meta(rule) = &args.nested[1] {
|
||||||
if args.nested.len() < 2 {
|
second_rule = generate_guards(crate_name, rule)?;
|
||||||
return Err(Error::new_spanned(
|
} else {
|
||||||
args,
|
return Err(Error::new_spanned(&args.nested[1], "Invalid rule.").into());
|
||||||
"race operator need at least 1 operand.",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
let mut guards: Option<TokenStream> = None;
|
|
||||||
for arg in &args.nested {
|
|
||||||
if let NestedMeta::Meta(rule) = &arg {
|
|
||||||
let guard = generate_guards(crate_name, rule)?;
|
|
||||||
if guards.is_none() {
|
|
||||||
guards = guard;
|
|
||||||
} else {
|
|
||||||
guards =
|
|
||||||
Some(quote! { #crate_name::guard::GuardExt::or(#guard, #guards) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(guards)
|
|
||||||
}
|
}
|
||||||
_ => {
|
Ok(Some(
|
||||||
let ty = &args.path;
|
quote! { #crate_name::guard::GuardExt::and(#first_rule, #second_rule) },
|
||||||
let mut params = Vec::new();
|
))
|
||||||
for attr in &args.nested {
|
}
|
||||||
if let NestedMeta::Meta(Meta::NameValue(nv)) = attr {
|
"or" => {
|
||||||
let name = &nv.path;
|
if args.nested.len() != 2 {
|
||||||
if let Lit::Str(value) = &nv.lit {
|
return Err(Error::new_spanned(
|
||||||
let value_str = value.value();
|
args,
|
||||||
if value_str.starts_with('@') {
|
"or operator support only 2 operands.",
|
||||||
let getter_name = get_param_getter_ident(&value_str[1..]);
|
)
|
||||||
params.push(quote! { #name: #getter_name()? });
|
.into());
|
||||||
} else {
|
}
|
||||||
let expr = syn::parse_str::<Expr>(&value_str)?;
|
let first_rule: Option<TokenStream>;
|
||||||
params.push(quote! { #name: (#expr).into() });
|
let second_rule: Option<TokenStream>;
|
||||||
}
|
if let NestedMeta::Meta(rule) = &args.nested[0] {
|
||||||
} else {
|
first_rule = generate_guards(crate_name, rule)?;
|
||||||
return Err(Error::new_spanned(
|
} else {
|
||||||
&nv.lit,
|
return Err(Error::new_spanned(&args.nested[0], "Invalid rule.").into());
|
||||||
"Value must be string literal",
|
}
|
||||||
)
|
if let NestedMeta::Meta(rule) = &args.nested[1] {
|
||||||
.into());
|
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) },
|
||||||
|
))
|
||||||
|
}
|
||||||
|
"chain" => {
|
||||||
|
if args.nested.len() < 2 {
|
||||||
|
return Err(Error::new_spanned(
|
||||||
|
args,
|
||||||
|
"chain operator need at least 1 operand.",
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let mut guards: Option<TokenStream> = None;
|
||||||
|
for arg in &args.nested {
|
||||||
|
if let NestedMeta::Meta(rule) = &arg {
|
||||||
|
let guard = generate_guards(crate_name, rule)?;
|
||||||
|
if guards.is_none() {
|
||||||
|
guards = guard;
|
||||||
} else {
|
} else {
|
||||||
return Err(
|
guards = Some(
|
||||||
Error::new_spanned(attr, "Invalid property for guard").into()
|
quote! { #crate_name::guard::GuardExt::and(#guard, #guards) },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Some(quote! { #ty { #(#params),* } }))
|
|
||||||
}
|
}
|
||||||
},
|
Ok(guards)
|
||||||
None => Err(Error::new_spanned(args, "Invalid guards").into()),
|
}
|
||||||
}
|
"race" => {
|
||||||
}
|
if args.nested.len() < 2 {
|
||||||
_ => Err(Error::new_spanned(args, "Invalid guards").into()),
|
return Err(Error::new_spanned(
|
||||||
}
|
args,
|
||||||
}
|
"race operator need at least 1 operand.",
|
||||||
|
)
|
||||||
pub fn generate_post_guards(
|
.into());
|
||||||
crate_name: &TokenStream,
|
}
|
||||||
args: &Meta,
|
let mut guards: Option<TokenStream> = None;
|
||||||
) -> GeneratorResult<Option<TokenStream>> {
|
for arg in &args.nested {
|
||||||
match args {
|
if let NestedMeta::Meta(rule) = &arg {
|
||||||
Meta::List(args) => {
|
let guard = generate_guards(crate_name, rule)?;
|
||||||
let mut guards = None;
|
if guards.is_none() {
|
||||||
for item in &args.nested {
|
guards = guard;
|
||||||
if let NestedMeta::Meta(Meta::List(ls)) = item {
|
} else {
|
||||||
let ty = &ls.path;
|
guards = Some(
|
||||||
|
quote! { #crate_name::guard::GuardExt::or(#guard, #guards) },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(guards)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let ty = &args.path;
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
for attr in &ls.nested {
|
for attr in &args.nested {
|
||||||
if let NestedMeta::Meta(Meta::NameValue(nv)) = attr {
|
if let NestedMeta::Meta(Meta::NameValue(nv)) = attr {
|
||||||
let name = &nv.path;
|
let name = &nv.path;
|
||||||
if let Lit::Str(value) = &nv.lit {
|
if let Lit::Str(value) = &nv.lit {
|
||||||
@ -305,19 +260,11 @@ pub fn generate_post_guards(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let guard = quote! { #ty { #(#params),* } };
|
Ok(Some(quote! { #ty { #(#params),* } }))
|
||||||
if guards.is_none() {
|
|
||||||
guards = Some(guard);
|
|
||||||
} else {
|
|
||||||
guards =
|
|
||||||
Some(quote! { #crate_name::guard::PostGuardExt::and(#guard, #guards) });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(Error::new_spanned(item, "Invalid guard").into());
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Ok(guards)
|
None => Err(Error::new_spanned(args, "Invalid guards").into()),
|
||||||
}
|
},
|
||||||
_ => Err(Error::new_spanned(args, "Invalid guards").into()),
|
_ => Err(Error::new_spanned(args, "Invalid guards").into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,6 @@ pub use types::*;
|
|||||||
/// | provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
|
/// | provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
|
||||||
/// | requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
|
/// | requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
|
||||||
/// | guard | Field of guard | [`Guard`](guard/trait.Guard.html) | Y |
|
/// | guard | Field of guard | [`Guard`](guard/trait.Guard.html) | Y |
|
||||||
/// | post_guard | Field of post guard | [`PostGuard`](guard/trait.PostGuard.html) | Y |
|
|
||||||
///
|
///
|
||||||
/// # Field argument parameters
|
/// # Field argument parameters
|
||||||
///
|
///
|
||||||
@ -321,7 +320,6 @@ pub use async_graphql_derive::Object;
|
|||||||
/// | provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
|
/// | provides | Annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway. | string | Y |
|
||||||
/// | requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
|
/// | requires | Annotate the required input fieldset from a base type for a resolver. It is used to develop a query plan where the required fields may not be needed by the client, but the service may need additional information from other services. | string | Y |
|
||||||
/// | guard | Field of guard | [`Guard`](guard/trait.Guard.html) | Y |
|
/// | guard | Field of guard | [`Guard`](guard/trait.Guard.html) | Y |
|
||||||
/// | post_guard | Field of post guard | [`PostGuard`](guard/trait.PostGuard.html) | Y |
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -678,7 +676,6 @@ pub use async_graphql_derive::Union;
|
|||||||
/// | name | Field name | string | Y |
|
/// | name | Field name | string | Y |
|
||||||
/// | deprecation | Field deprecation reason | string | Y |
|
/// | deprecation | Field deprecation reason | string | Y |
|
||||||
/// | guard | Field of guard | [`Guard`](guard/trait.Guard.html) | Y |
|
/// | guard | Field of guard | [`Guard`](guard/trait.Guard.html) | Y |
|
||||||
/// | post_guard | Field of post guard | [`PostGuard`](guard/trait.PostGuard.html) | Y |
|
|
||||||
///
|
///
|
||||||
/// # Field argument parameters
|
/// # Field argument parameters
|
||||||
///
|
///
|
||||||
|
@ -291,7 +291,11 @@ pub async fn test_guard_or_operator() {
|
|||||||
pub async fn test_guard_chain_operator() {
|
pub async fn test_guard_chain_operator() {
|
||||||
#[derive(SimpleObject)]
|
#[derive(SimpleObject)]
|
||||||
struct Query {
|
struct Query {
|
||||||
#[graphql(guard(chain(RoleGuard(role = "Role::Admin"), UserGuard(username = r#""test""#), AgeGuard(age = r#"21"#))))]
|
#[graphql(guard(chain(
|
||||||
|
RoleGuard(role = "Role::Admin"),
|
||||||
|
UserGuard(username = r#""test""#),
|
||||||
|
AgeGuard(age = r#"21"#)
|
||||||
|
)))]
|
||||||
value: i32,
|
value: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,7 +400,11 @@ pub async fn test_guard_chain_operator() {
|
|||||||
pub async fn test_guard_race_operator() {
|
pub async fn test_guard_race_operator() {
|
||||||
#[derive(SimpleObject)]
|
#[derive(SimpleObject)]
|
||||||
struct Query {
|
struct Query {
|
||||||
#[graphql(guard(race(RoleGuard(role = "Role::Admin"), UserGuard(username = r#""test""#), AgeGuard(age = r#"21"#))))]
|
#[graphql(guard(race(
|
||||||
|
RoleGuard(role = "Role::Admin"),
|
||||||
|
UserGuard(username = r#""test""#),
|
||||||
|
AgeGuard(age = r#"21"#)
|
||||||
|
)))]
|
||||||
value: i32,
|
value: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,4 +485,4 @@ pub async fn test_guard_race_operator() {
|
|||||||
extensions: None,
|
extensions: None,
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,327 +0,0 @@
|
|||||||
use async_graphql::guard::PostGuard;
|
|
||||||
use async_graphql::*;
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Copy, Clone)]
|
|
||||||
enum Role {
|
|
||||||
Admin,
|
|
||||||
Guest,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RoleGuard {
|
|
||||||
role: Role,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl PostGuard<i32> for RoleGuard {
|
|
||||||
async fn check(&self, ctx: &Context<'_>, _result: &i32) -> Result<()> {
|
|
||||||
if ctx.data_opt::<Role>() == Some(&self.role) {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err("Forbidden".into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(SimpleObject)]
|
|
||||||
struct MyObj {
|
|
||||||
#[graphql(owned, post_guard(UserGuard(username = r#""test""#, value = "88")))]
|
|
||||||
value: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Username(String);
|
|
||||||
|
|
||||||
struct UserGuard {
|
|
||||||
value: i32,
|
|
||||||
username: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl PostGuard<i32> for UserGuard {
|
|
||||||
async fn check(&self, ctx: &Context<'_>, result: &i32) -> Result<()> {
|
|
||||||
assert_eq!(*result, self.value);
|
|
||||||
if ctx.data_opt::<Username>().as_ref().map(|s| s.0.as_str()) == Some(&self.username) {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err("Forbidden".into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl PostGuard<MyObj> for UserGuard {
|
|
||||||
async fn check(&self, ctx: &Context<'_>, result: &MyObj) -> Result<()> {
|
|
||||||
assert_eq!(result.value, self.value);
|
|
||||||
if ctx.data_opt::<Username>().as_ref().map(|s| s.0.as_str()) == Some(&self.username) {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err("Forbidden".into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
pub async fn test_post_guard() {
|
|
||||||
struct Query;
|
|
||||||
|
|
||||||
#[Object]
|
|
||||||
impl Query {
|
|
||||||
#[graphql(post_guard(UserGuard(username = r#""test""#, value = "99")))]
|
|
||||||
async fn value(&self) -> i32 {
|
|
||||||
99
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn obj(&self) -> MyObj {
|
|
||||||
MyObj { value: 88 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
|
||||||
|
|
||||||
let query = "{ value }";
|
|
||||||
assert_eq!(
|
|
||||||
schema
|
|
||||||
.execute(Request::new(query).data(Username("test".to_string())))
|
|
||||||
.await
|
|
||||||
.data,
|
|
||||||
serde_json::json!({
|
|
||||||
"value": 99
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let query = "{ value }";
|
|
||||||
assert_eq!(
|
|
||||||
schema
|
|
||||||
.execute(Request::new(query).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 = "{ obj { value } }";
|
|
||||||
assert_eq!(
|
|
||||||
schema
|
|
||||||
.execute(Request::new(query).data(Username("test".to_string())))
|
|
||||||
.await
|
|
||||||
.data,
|
|
||||||
serde_json::json!({
|
|
||||||
"obj": { "value": 88 }
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let query = "{ obj { value } }";
|
|
||||||
assert_eq!(
|
|
||||||
schema
|
|
||||||
.execute(Request::new(query).data(Username("test1".to_string())))
|
|
||||||
.await
|
|
||||||
.into_result()
|
|
||||||
.unwrap_err(),
|
|
||||||
vec![ServerError {
|
|
||||||
message: "Forbidden".to_string(),
|
|
||||||
locations: vec![Pos { line: 1, column: 9 }],
|
|
||||||
path: vec![
|
|
||||||
PathSegment::Field("obj".to_owned()),
|
|
||||||
PathSegment::Field("value".to_owned())
|
|
||||||
],
|
|
||||||
extensions: None,
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
pub async fn test_multiple_post_guards() {
|
|
||||||
#[derive(SimpleObject)]
|
|
||||||
struct Query {
|
|
||||||
#[graphql(post_guard(
|
|
||||||
RoleGuard(role = "Role::Admin"),
|
|
||||||
UserGuard(username = r#""test""#, value = "10")
|
|
||||||
))]
|
|
||||||
value: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
let schema = Schema::new(Query { value: 10 }, EmptyMutation, EmptySubscription);
|
|
||||||
|
|
||||||
let query = "{ value }";
|
|
||||||
assert_eq!(
|
|
||||||
schema
|
|
||||||
.execute(
|
|
||||||
Request::new(query)
|
|
||||||
.data(Role::Admin)
|
|
||||||
.data(Username("test".to_string()))
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.data,
|
|
||||||
serde_json::json!({"value": 10})
|
|
||||||
);
|
|
||||||
|
|
||||||
let query = "{ value }";
|
|
||||||
assert_eq!(
|
|
||||||
schema
|
|
||||||
.execute(
|
|
||||||
Request::new(query)
|
|
||||||
.data(Role::Guest)
|
|
||||||
.data(Username("test".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::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_post_guard_forward_arguments() {
|
|
||||||
struct UserGuard {
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl PostGuard<ID> for UserGuard {
|
|
||||||
async fn check(&self, ctx: &Context<'_>, result: &ID) -> Result<()> {
|
|
||||||
assert_eq!(result.as_str(), "haha");
|
|
||||||
if ctx.data_opt::<ID>() != Some(&self.id) {
|
|
||||||
Err("Forbidden".into())
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct QueryRoot;
|
|
||||||
|
|
||||||
#[Object]
|
|
||||||
impl QueryRoot {
|
|
||||||
#[graphql(post_guard(UserGuard(id = "@_id")))]
|
|
||||||
async fn user(&self, _id: ID) -> ID {
|
|
||||||
"haha".into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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": "haha"})
|
|
||||||
);
|
|
||||||
|
|
||||||
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,
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
pub async fn test_post_guard_generic() {
|
|
||||||
struct UserGuard {
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl<T: Send + Sync> PostGuard<T> for UserGuard {
|
|
||||||
async fn check(&self, ctx: &Context<'_>, _result: &T) -> Result<()> {
|
|
||||||
if ctx.data_opt::<ID>() != Some(&self.id) {
|
|
||||||
Err("Forbidden".into())
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct QueryRoot;
|
|
||||||
|
|
||||||
#[Object]
|
|
||||||
impl QueryRoot {
|
|
||||||
#[graphql(post_guard(UserGuard(id = r#""abc""#)))]
|
|
||||||
async fn user(&self) -> ID {
|
|
||||||
"haha".into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription);
|
|
||||||
|
|
||||||
let query = r#"{ user }"#;
|
|
||||||
assert_eq!(
|
|
||||||
schema
|
|
||||||
.execute(Request::new(query).data(ID::from("abc")))
|
|
||||||
.await
|
|
||||||
.data,
|
|
||||||
serde_json::json!({"user": "haha"})
|
|
||||||
);
|
|
||||||
|
|
||||||
let query = r#"{ user }"#;
|
|
||||||
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,
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user