Add support for the list
operator to the input value validator. #579
This commit is contained in:
parent
1468cc91bb
commit
28d22dbe32
|
@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Implement `TryFrom<&[SelectionField<'a>]>` for `Lookahead<'a>`. [#575](https://github.com/async-graphql/async-graphql/issues/575)
|
||||
- Attach custom HTTP headers to the response when an error occurs. [#572](https://github.com/async-graphql/async-graphql/issues/572)
|
||||
- Allow field visible to support paths. [#578](https://github.com/async-graphql/async-graphql/pull/578)
|
||||
- Add support for the `list` operator to the input value validator. [#579](https://github.com/async-graphql/async-graphql/issues/579)
|
||||
|
||||
## [2.9.8] 2021-07-12
|
||||
|
||||
|
|
|
@ -77,6 +77,23 @@ fn generate_nested_validator(
|
|||
None => Some(item),
|
||||
})
|
||||
.unwrap())
|
||||
} else if ls.path.is_ident("list") {
|
||||
if ls.nested.len() > 1 {
|
||||
return Err(Error::new_spanned(
|
||||
ls,
|
||||
"Only one validator can be wrapped with list.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
if ls.nested.is_empty() {
|
||||
return Err(
|
||||
Error::new_spanned(ls, "At least one validator must be defined").into(),
|
||||
);
|
||||
}
|
||||
let validator = generate_nested_validator(crate_name, &ls.nested[0])?;
|
||||
Ok(quote! {
|
||||
#crate_name::validators::List(#validator)
|
||||
})
|
||||
} else {
|
||||
let ty = &ls.path;
|
||||
for item in &ls.nested {
|
||||
|
|
|
@ -24,7 +24,7 @@ impl Query {
|
|||
The following example verifies that the `i32` parameter `a` is greater than 10 and less than 100, or else equal to 0:
|
||||
|
||||
```rust
|
||||
use async_graphql:*;
|
||||
use async_graphql::*;
|
||||
use async_graphql::validators::{IntGreaterThan, IntLessThan, IntEqual};
|
||||
|
||||
struct Query;
|
||||
|
@ -36,7 +36,23 @@ impl Query {
|
|||
and(IntGreaterThan(value = "10"), IntLessThan(value = "100")),
|
||||
IntEqual(value = "0")
|
||||
)))] a: String) {
|
||||
} {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Validate the elements of the list.
|
||||
|
||||
You can use the `list` operator to indicate that the internal validator is used for all elements in a list:
|
||||
|
||||
```rust
|
||||
use async_graphql::*;
|
||||
use async_graphql::validators::Email;
|
||||
|
||||
struct Query;
|
||||
|
||||
#[Object]
|
||||
impl Query {
|
||||
async fn input(#[graphql(validator(list(Email)))] emails: Vec<String>) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -22,7 +22,7 @@ impl Query {
|
|||
下面的例子校验`i32`类型的参数`a`必须大于10,并且小于100,或者等于0:
|
||||
|
||||
```rust
|
||||
use async_graphql:*;
|
||||
use async_graphql::*;
|
||||
use async_graphql::validators::{IntGreaterThan, IntLessThan, IntEqual};
|
||||
|
||||
struct Query;
|
||||
|
@ -34,7 +34,23 @@ impl Query {
|
|||
and(IntGreaterThan(value = "10"), IntLessThan(value = "100")),
|
||||
IntEqual(value = "0")
|
||||
)))] a: String) {
|
||||
} {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 校验列表成员
|
||||
|
||||
你可以用`list`操作符表示内部的校验器作用于一个列表内的所有成员:
|
||||
|
||||
```rust
|
||||
use async_graphql::*;
|
||||
use async_graphql::validators::{Email};
|
||||
|
||||
struct Query;
|
||||
|
||||
#[Object]
|
||||
impl Query {
|
||||
async fn input(#[graphql(validator(list(Email)))] emails: Vec<String>) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -48,3 +48,17 @@ impl InputValueValidator for ListMaxLength {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct List<T>(pub T);
|
||||
|
||||
impl<T: InputValueValidator> InputValueValidator for List<T> {
|
||||
fn is_valid(&self, value: &Value) -> Result<(), String> {
|
||||
if let Value::List(elems) = value {
|
||||
for elem in elems {
|
||||
self.0.is_valid(elem)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ mod string_validators;
|
|||
use crate::{Error, Value};
|
||||
|
||||
pub use int_validators::{IntEqual, IntGreaterThan, IntLessThan, IntNonZero, IntRange};
|
||||
pub use list_validators::{ListMaxLength, ListMinLength};
|
||||
pub use list_validators::{List, ListMaxLength, ListMinLength};
|
||||
pub use string_validators::{Email, StringMaxLength, StringMinLength, MAC};
|
||||
|
||||
/// Input value validator
|
||||
|
|
|
@ -1829,3 +1829,62 @@ pub async fn test_custom_input_validator_with_extensions() {
|
|||
}]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_input_validator_list() {
|
||||
struct QueryRoot;
|
||||
|
||||
#[derive(InputObject)]
|
||||
struct InputEmail {
|
||||
#[graphql(validator(list(Email)))]
|
||||
pub emails: Vec<String>,
|
||||
}
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {
|
||||
async fn value(&self, #[graphql(validator(list(Email)))] _emails: Vec<String>) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.execute(
|
||||
r#"
|
||||
{
|
||||
value(
|
||||
emails: [
|
||||
"a@a.com",
|
||||
"b@abc.com",
|
||||
]
|
||||
)
|
||||
}"#
|
||||
)
|
||||
.await
|
||||
.into_result()
|
||||
.unwrap()
|
||||
.data,
|
||||
value!({"value": true})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
schema
|
||||
.execute(
|
||||
r#"
|
||||
{
|
||||
value(
|
||||
emails: [
|
||||
"123456",
|
||||
]
|
||||
)
|
||||
}"#
|
||||
)
|
||||
.await
|
||||
.into_result()
|
||||
.unwrap_err()[0]
|
||||
.message,
|
||||
"Invalid value for argument \"emails\", invalid email format"
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user