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)
|
- 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)
|
- 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)
|
- 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
|
## [2.9.8] 2021-07-12
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,23 @@ fn generate_nested_validator(
|
||||||
None => Some(item),
|
None => Some(item),
|
||||||
})
|
})
|
||||||
.unwrap())
|
.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 {
|
} else {
|
||||||
let ty = &ls.path;
|
let ty = &ls.path;
|
||||||
for item in &ls.nested {
|
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:
|
The following example verifies that the `i32` parameter `a` is greater than 10 and less than 100, or else equal to 0:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use async_graphql:*;
|
use async_graphql::*;
|
||||||
use async_graphql::validators::{IntGreaterThan, IntLessThan, IntEqual};
|
use async_graphql::validators::{IntGreaterThan, IntLessThan, IntEqual};
|
||||||
|
|
||||||
struct Query;
|
struct Query;
|
||||||
|
@ -36,7 +36,23 @@ impl Query {
|
||||||
and(IntGreaterThan(value = "10"), IntLessThan(value = "100")),
|
and(IntGreaterThan(value = "10"), IntLessThan(value = "100")),
|
||||||
IntEqual(value = "0")
|
IntEqual(value = "0")
|
||||||
)))] a: String) {
|
)))] 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:
|
下面的例子校验`i32`类型的参数`a`必须大于10,并且小于100,或者等于0:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use async_graphql:*;
|
use async_graphql::*;
|
||||||
use async_graphql::validators::{IntGreaterThan, IntLessThan, IntEqual};
|
use async_graphql::validators::{IntGreaterThan, IntLessThan, IntEqual};
|
||||||
|
|
||||||
struct Query;
|
struct Query;
|
||||||
|
@ -34,7 +34,23 @@ impl Query {
|
||||||
and(IntGreaterThan(value = "10"), IntLessThan(value = "100")),
|
and(IntGreaterThan(value = "10"), IntLessThan(value = "100")),
|
||||||
IntEqual(value = "0")
|
IntEqual(value = "0")
|
||||||
)))] a: String) {
|
)))] 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};
|
use crate::{Error, Value};
|
||||||
|
|
||||||
pub use int_validators::{IntEqual, IntGreaterThan, IntLessThan, IntNonZero, IntRange};
|
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};
|
pub use string_validators::{Email, StringMaxLength, StringMinLength, MAC};
|
||||||
|
|
||||||
/// Input value validator
|
/// 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