Modify the location of the Guard call.
This commit is contained in:
parent
40e78a02b7
commit
9b917e19b3
|
@ -3,7 +3,6 @@ use crate::output_type::OutputType;
|
|||
use crate::utils::{build_value_repr, check_reserved_name, get_crate_name};
|
||||
use inflector::Inflector;
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Ident, Span};
|
||||
use quote::quote;
|
||||
use syn::{Block, Error, FnArg, ImplItem, ItemImpl, Pat, Result, ReturnType, Type, TypeReference};
|
||||
|
||||
|
@ -52,7 +51,6 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
};
|
||||
let mut create_ctx = true;
|
||||
let mut arg_ctx = Ident::new("ctx", Span::call_site());
|
||||
let mut args = Vec::new();
|
||||
|
||||
for (idx, arg) in method.sig.inputs.iter_mut().enumerate() {
|
||||
|
@ -91,18 +89,6 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
));
|
||||
} else {
|
||||
create_ctx = false;
|
||||
match arg {
|
||||
Pat::Wild(_) => {
|
||||
pat.pat = Box::new(
|
||||
syn::parse2::<Pat>(quote! { #arg_ctx })
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
Pat::Ident(arg_ident) => {
|
||||
arg_ctx = arg_ident.ident.clone();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,8 +98,8 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
|
||||
if create_ctx {
|
||||
let arg = syn::parse2::<FnArg>(quote! { #arg_ctx: &#crate_name::Context<'_> })
|
||||
.unwrap();
|
||||
let arg =
|
||||
syn::parse2::<FnArg>(quote! { _: &#crate_name::Context<'_> }).unwrap();
|
||||
method.sig.inputs.insert(1, arg);
|
||||
}
|
||||
|
||||
|
@ -168,19 +154,16 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
let do_find = quote! { self.#field_ident(ctx, #(#use_keys),*).await.map_err(|err| err.into_error(pos))? };
|
||||
|
||||
if let Some(guard) = &entity.guard {
|
||||
method.block.stmts.insert(
|
||||
0,
|
||||
syn::parse2(quote! { #guard.check(#arg_ctx).await?; })
|
||||
.expect("invalid guard"),
|
||||
);
|
||||
}
|
||||
let guard = entity.guard.map(
|
||||
|guard| quote! { #guard.check(ctx).await.map_err(|err| err.into_error(pos))?; },
|
||||
);
|
||||
|
||||
find_entities.push((
|
||||
args.len(),
|
||||
quote! {
|
||||
if typename == &<#entity_type as #crate_name::Type>::type_name() {
|
||||
if let (#(#key_pat),*) = (#(#key_getter),*) {
|
||||
#guard
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return #crate_name::OutputValueType::resolve(&#do_find, &ctx_obj, pos).await;
|
||||
}
|
||||
|
@ -243,7 +226,6 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
};
|
||||
|
||||
let mut create_ctx = true;
|
||||
let mut arg_ctx = Ident::new("ctx", Span::call_site());
|
||||
let mut args = Vec::new();
|
||||
|
||||
for (idx, arg) in method.sig.inputs.iter_mut().enumerate() {
|
||||
|
@ -283,17 +265,6 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
|
||||
create_ctx = false;
|
||||
match arg {
|
||||
Pat::Wild(_) => {
|
||||
pat.pat = Box::new(
|
||||
syn::parse2::<Pat>(quote! { #arg_ctx }).unwrap(),
|
||||
);
|
||||
}
|
||||
Pat::Ident(arg_ident) => {
|
||||
arg_ctx = arg_ident.ident.clone();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::new_spanned(arg, "Invalid argument type.")),
|
||||
|
@ -302,8 +273,8 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
|
||||
if create_ctx {
|
||||
let arg = syn::parse2::<FnArg>(quote! { #arg_ctx: &#crate_name::Context<'_> })
|
||||
.unwrap();
|
||||
let arg =
|
||||
syn::parse2::<FnArg>(quote! { _: &#crate_name::Context<'_> }).unwrap();
|
||||
method.sig.inputs.insert(1, arg);
|
||||
}
|
||||
|
||||
|
@ -399,27 +370,27 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
let resolve_obj = quote! {
|
||||
{
|
||||
let res:#crate_name::FieldResult<_> = self.#field_ident(ctx, #(#use_params),*).await;
|
||||
let res = self.#field_ident(ctx, #(#use_params),*).await;
|
||||
res.map_err(|err| err.into_error_with_path(ctx.position, ctx.path_node.as_ref().unwrap().to_json()))?
|
||||
}
|
||||
};
|
||||
|
||||
let guard = field
|
||||
.guard
|
||||
.map(|guard| quote! {
|
||||
#guard.check(ctx).await
|
||||
.map_err(|err| err.into_error_with_path(ctx.position, ctx.path_node.as_ref().unwrap().to_json()))?;
|
||||
});
|
||||
|
||||
resolvers.push(quote! {
|
||||
if ctx.name.as_str() == #field_name {
|
||||
#guard
|
||||
#(#get_params)*
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return #crate_name::OutputValueType::resolve(&#resolve_obj, &ctx_obj, ctx.position).await;
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(guard) = field.guard {
|
||||
method.block.stmts.insert(
|
||||
0,
|
||||
syn::parse2(quote! { #guard.check(#arg_ctx).await?; })
|
||||
.expect("invalid guard"),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((idx, _)) = method
|
||||
.attrs
|
||||
.iter()
|
||||
|
|
|
@ -91,17 +91,14 @@ pub fn generate(object_args: &args::Object, input: &mut DeriveInput) -> Result<T
|
|||
});
|
||||
|
||||
let ident = &item.ident;
|
||||
let guard = if let Some(guard) = &field.guard {
|
||||
quote! { #guard.check(ctx).await?; }
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
let guard = field
|
||||
.guard
|
||||
.map(|guard| quote! { #guard.check(ctx).await.map_err(|err| err.into_error_with_path(ctx.position, ctx.path_node.as_ref().unwrap().to_json()))?; });
|
||||
|
||||
if field.is_ref {
|
||||
getters.push(quote! {
|
||||
#[inline]
|
||||
#vis async fn #ident(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::FieldResult<&#ty> {
|
||||
#guard
|
||||
Ok(&self.#ident)
|
||||
}
|
||||
});
|
||||
|
@ -109,7 +106,6 @@ pub fn generate(object_args: &args::Object, input: &mut DeriveInput) -> Result<T
|
|||
getters.push(quote! {
|
||||
#[inline]
|
||||
#vis async fn #ident(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::FieldResult<#ty> {
|
||||
#guard
|
||||
Ok(self.#ident.clone())
|
||||
}
|
||||
});
|
||||
|
@ -117,6 +113,7 @@ pub fn generate(object_args: &args::Object, input: &mut DeriveInput) -> Result<T
|
|||
|
||||
resolvers.push(quote! {
|
||||
if ctx.name.as_str() == #field_name {
|
||||
#guard
|
||||
let res = self.#ident(ctx).await.map_err(|err| err.into_error_with_path(ctx.position, ctx.path_node.as_ref().unwrap().to_json()))?;
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return #crate_name::OutputValueType::resolve(&res, &ctx_obj, ctx.position).await;
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::output_type::OutputType;
|
|||
use crate::utils::{build_value_repr, check_reserved_name, get_crate_name};
|
||||
use inflector::Inflector;
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Ident, Span};
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
Block, Error, FnArg, ImplItem, ItemImpl, Pat, Result, ReturnType, Type, TypeImplTrait,
|
||||
|
@ -75,7 +74,6 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
};
|
||||
|
||||
let mut create_ctx = true;
|
||||
let mut arg_ctx = Ident::new("ctx", Span::call_site());
|
||||
let mut args = Vec::new();
|
||||
|
||||
for (idx, arg) in method.sig.inputs.iter_mut().enumerate() {
|
||||
|
@ -114,18 +112,6 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
));
|
||||
} else {
|
||||
create_ctx = false;
|
||||
match arg {
|
||||
Pat::Wild(_) => {
|
||||
pat.pat = Box::new(
|
||||
syn::parse2::<Pat>(quote! { #arg_ctx })
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
Pat::Ident(arg_ident) => {
|
||||
arg_ctx = arg_ident.ident.clone();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,8 +125,8 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
|
||||
if create_ctx {
|
||||
let arg = syn::parse2::<FnArg>(quote! { #arg_ctx: &#crate_name::Context<'_> })
|
||||
.unwrap();
|
||||
let arg =
|
||||
syn::parse2::<FnArg>(quote! { _: &#crate_name::Context<'_> }).unwrap();
|
||||
method.sig.inputs.insert(1, arg);
|
||||
}
|
||||
|
||||
|
@ -244,18 +230,16 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
map_err(|err| err.into_error_with_path(ctx.position, ctx.path_node.as_ref().unwrap().to_json()))?)
|
||||
};
|
||||
|
||||
if let Some(guard) = &field.guard {
|
||||
method.block.stmts.insert(
|
||||
0,
|
||||
syn::parse2(quote! { #guard.check(#arg_ctx).await?; })
|
||||
.expect("invalid guard"),
|
||||
);
|
||||
}
|
||||
let guard = field.guard.map(|guard| quote! {
|
||||
#guard.check(ctx).await.map_err(|err| err.into_error_with_path(ctx.position, ctx.path_node.as_ref().unwrap().to_json()))?;
|
||||
});
|
||||
|
||||
create_stream.push(quote! {
|
||||
if ctx.name.as_str() == #field_name {
|
||||
use #crate_name::futures::stream::{StreamExt, TryStreamExt};
|
||||
|
||||
#guard
|
||||
|
||||
let field_name = std::sync::Arc::new(ctx.result_name().to_string());
|
||||
#(#get_params)*
|
||||
let field_selection_set = std::sync::Arc::new(ctx.selection_set.clone());
|
||||
|
|
165
tests/guard.rs
165
tests/guard.rs
|
@ -54,18 +54,8 @@ pub async fn test_guard() {
|
|||
#[Object]
|
||||
impl Query {
|
||||
#[field(guard(RoleGuard(role = "Role::Admin")))]
|
||||
async fn value1(&self) -> FieldResult<i32> {
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
#[field(guard(RoleGuard(role = "Role::Admin")))]
|
||||
async fn value2(&self, ctx1: &Context<'_>) -> FieldResult<i32> {
|
||||
Ok(2)
|
||||
}
|
||||
|
||||
#[field(guard(RoleGuard(role = "Role::Admin")))]
|
||||
async fn value3(&self, _: &Context<'_>) -> i32 {
|
||||
3
|
||||
async fn value(&self) -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
async fn obj(&self) -> MyObj {
|
||||
|
@ -73,19 +63,7 @@ pub async fn test_guard() {
|
|||
}
|
||||
|
||||
#[entity(guard(RoleGuard(role = "Role::Admin")))]
|
||||
async fn find_obj1(&self, value: i32) -> FieldResult<MyObj> {
|
||||
Ok(MyObj { value })
|
||||
}
|
||||
|
||||
#[entity(guard(RoleGuard(role = "Role::Admin")))]
|
||||
#[allow(unused_variables)]
|
||||
async fn find_obj2(&self, ctx1: &Context<'_>, value: i32, n: i32) -> FieldResult<MyObj> {
|
||||
Ok(MyObj { value })
|
||||
}
|
||||
|
||||
#[entity(guard(RoleGuard(role = "Role::Admin")))]
|
||||
#[allow(unused_variables)]
|
||||
async fn find_obj3(&self, _: &Context<'_>, value: i32, a: i32, b: i32) -> MyObj {
|
||||
async fn find_obj(&self, value: i32) -> MyObj {
|
||||
MyObj { value }
|
||||
}
|
||||
}
|
||||
|
@ -95,17 +73,7 @@ pub async fn test_guard() {
|
|||
#[Subscription]
|
||||
impl Subscription {
|
||||
#[field(guard(RoleGuard(role = "Role::Admin")))]
|
||||
async fn values1(&self) -> FieldResult<impl Stream<Item = i32>> {
|
||||
Ok(futures::stream::iter(vec![1, 2, 3]))
|
||||
}
|
||||
|
||||
#[field(guard(RoleGuard(role = "Role::Admin")))]
|
||||
async fn values2(&self, ctx1: &Context<'_>) -> FieldResult<impl Stream<Item = i32>> {
|
||||
Ok(futures::stream::iter(vec![1, 2, 3]))
|
||||
}
|
||||
|
||||
#[field(guard(RoleGuard(role = "Role::Admin")))]
|
||||
async fn values3(&self, _: &Context<'_>) -> impl Stream<Item = i32> {
|
||||
async fn values(&self) -> impl Stream<Item = i32> {
|
||||
futures::stream::iter(vec![1, 2, 3])
|
||||
}
|
||||
}
|
||||
|
@ -125,19 +93,6 @@ pub async fn test_guard() {
|
|||
})
|
||||
);
|
||||
|
||||
let query = "{ obj { value } }";
|
||||
assert_eq!(
|
||||
QueryBuilder::new(query)
|
||||
.data(Role::Admin)
|
||||
.execute(&schema)
|
||||
.await
|
||||
.unwrap()
|
||||
.data,
|
||||
serde_json::json!({
|
||||
"obj": {"value": 99}
|
||||
})
|
||||
);
|
||||
|
||||
let query = "{ obj { value } }";
|
||||
assert_eq!(
|
||||
QueryBuilder::new(query)
|
||||
|
@ -155,7 +110,7 @@ pub async fn test_guard() {
|
|||
}
|
||||
);
|
||||
|
||||
let query = "{ value1 value2 value3 }";
|
||||
let query = "{ value }";
|
||||
assert_eq!(
|
||||
QueryBuilder::new(query)
|
||||
.data(Role::Admin)
|
||||
|
@ -164,13 +119,11 @@ pub async fn test_guard() {
|
|||
.unwrap()
|
||||
.data,
|
||||
serde_json::json!({
|
||||
"value1": 1,
|
||||
"value2": 2,
|
||||
"value3": 3,
|
||||
"value": 1,
|
||||
})
|
||||
);
|
||||
|
||||
let query = "{ value1 }";
|
||||
let query = "{ value }";
|
||||
assert_eq!(
|
||||
QueryBuilder::new(query)
|
||||
.data(Role::Guest)
|
||||
|
@ -179,7 +132,7 @@ pub async fn test_guard() {
|
|||
.unwrap_err(),
|
||||
Error::Query {
|
||||
pos: Pos { line: 1, column: 3 },
|
||||
path: Some(serde_json::json!(["value1"])),
|
||||
path: Some(serde_json::json!(["value"])),
|
||||
err: QueryError::FieldError {
|
||||
err: "Forbidden".to_string(),
|
||||
extended_error: None,
|
||||
|
@ -190,7 +143,7 @@ pub async fn test_guard() {
|
|||
assert_eq!(
|
||||
schema
|
||||
.create_subscription_stream(
|
||||
"subscription { values1 }",
|
||||
"subscription { values }",
|
||||
None,
|
||||
Variables::default(),
|
||||
Some(Arc::new({
|
||||
|
@ -204,62 +157,16 @@ pub async fn test_guard() {
|
|||
.collect::<Vec<_>>()
|
||||
.await,
|
||||
vec![
|
||||
Ok(serde_json::json! ({"values1": 1})),
|
||||
Ok(serde_json::json! ({"values1": 2})),
|
||||
Ok(serde_json::json! ({"values1": 3}))
|
||||
Ok(serde_json::json! ({"values": 1})),
|
||||
Ok(serde_json::json! ({"values": 2})),
|
||||
Ok(serde_json::json! ({"values": 3}))
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.create_subscription_stream(
|
||||
"subscription { values2 }",
|
||||
None,
|
||||
Variables::default(),
|
||||
Some(Arc::new({
|
||||
let mut data = Data::default();
|
||||
data.insert(Role::Admin);
|
||||
data
|
||||
})),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.collect::<Vec<_>>()
|
||||
.await,
|
||||
vec![
|
||||
Ok(serde_json::json! ({"values2": 1})),
|
||||
Ok(serde_json::json! ({"values2": 2})),
|
||||
Ok(serde_json::json! ({"values2": 3}))
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.create_subscription_stream(
|
||||
"subscription { values3 }",
|
||||
None,
|
||||
Variables::default(),
|
||||
Some(Arc::new({
|
||||
let mut data = Data::default();
|
||||
data.insert(Role::Admin);
|
||||
data
|
||||
})),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.collect::<Vec<_>>()
|
||||
.await,
|
||||
vec![
|
||||
Ok(serde_json::json! ({"values3": 1})),
|
||||
Ok(serde_json::json! ({"values3": 2})),
|
||||
Ok(serde_json::json! ({"values3": 3}))
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.create_subscription_stream(
|
||||
"subscription { values1 }",
|
||||
"subscription { values }",
|
||||
None,
|
||||
Variables::default(),
|
||||
Some(Arc::new({
|
||||
|
@ -276,7 +183,7 @@ pub async fn test_guard() {
|
|||
line: 1,
|
||||
column: 16
|
||||
},
|
||||
path: Some(serde_json::json!(["values1"])),
|
||||
path: Some(serde_json::json!(["values"])),
|
||||
err: QueryError::FieldError {
|
||||
err: "Forbidden".to_string(),
|
||||
extended_error: None,
|
||||
|
@ -306,50 +213,6 @@ pub async fn test_guard() {
|
|||
})
|
||||
);
|
||||
|
||||
let query = r#"{
|
||||
_entities(representations: [{__typename: "MyObj", value: 1, n: 1}]) {
|
||||
__typename
|
||||
... on MyObj {
|
||||
value
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
assert_eq!(
|
||||
QueryBuilder::new(query)
|
||||
.data(Role::Admin)
|
||||
.execute(&schema)
|
||||
.await
|
||||
.unwrap()
|
||||
.data,
|
||||
serde_json::json!({
|
||||
"_entities": [
|
||||
{"__typename": "MyObj", "value": 1},
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
let query = r#"{
|
||||
_entities(representations: [{__typename: "MyObj", value: 1, a: 1, b: 2}]) {
|
||||
__typename
|
||||
... on MyObj {
|
||||
value
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
assert_eq!(
|
||||
QueryBuilder::new(query)
|
||||
.data(Role::Admin)
|
||||
.execute(&schema)
|
||||
.await
|
||||
.unwrap()
|
||||
.data,
|
||||
serde_json::json!({
|
||||
"_entities": [
|
||||
{"__typename": "MyObj", "value": 1},
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
let query = r#"{
|
||||
_entities(representations: [{__typename: "MyObj", value: 1}]) {
|
||||
__typename
|
||||
|
|
Loading…
Reference in New Issue
Block a user