Return 400 on bad names.

This commit is contained in:
Luca Palmieri 2020-12-11 15:50:09 +00:00
parent 56ee4e7746
commit 9dd3b0590a
4 changed files with 60 additions and 2 deletions

10
Cargo.lock generated
View file

@ -503,6 +503,15 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "claim"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ad37958d55b29a7088909368968d2fe876a24c203f8441195130f3b15194b9"
dependencies = [
"autocfg",
]
[[package]]
name = "config"
version = "0.10.1"
@ -2888,6 +2897,7 @@ dependencies = [
"actix-rt",
"actix-web",
"chrono",
"claim",
"config",
"lazy_static",
"reqwest",

View file

@ -33,3 +33,4 @@ unicode-segmentation = "1.7.1"
[dev-dependencies]
reqwest = { version = "0.10.7", features = ["json"] }
lazy_static = "1.4.0"
claim = "0.4.0"

View file

@ -5,6 +5,7 @@ pub struct NewSubscriber {
pub name: SubscriberName,
}
#[derive(Debug)]
pub struct SubscriberName(String);
impl SubscriberName {
@ -36,7 +37,7 @@ impl SubscriberName {
> 0;
if is_empty_or_whitespace || is_too_long || contains_forbidden_characters {
panic!(format!("{} is not a valid subscriber name.", s))
Err(format!("{} is not a valid subscriber name.", s))
} else {
Ok(Self(s))
}
@ -48,3 +49,47 @@ impl AsRef<str> for SubscriberName {
&self.0
}
}
#[cfg(test)]
mod tests {
use crate::domain::SubscriberName;
use claim::{assert_err, assert_ok};
#[test]
fn a_256_grapheme_long_name_is_valid() {
let name = "".repeat(256);
assert_ok!(SubscriberName::parse(name));
}
#[test]
fn a_name_longer_than_256_graphemes_is_rejected() {
let name = "a".repeat(257);
assert_err!(SubscriberName::parse(name));
}
#[test]
fn whitespace_only_names_are_rejected() {
let name = " ".to_string();
assert_err!(SubscriberName::parse(name));
}
#[test]
fn empty_string_is_rejected() {
let name = "".to_string();
assert_err!(SubscriberName::parse(name));
}
#[test]
fn names_containing_an_invalid_characters_are_rejected() {
for name in vec!['/', '(', ')', '"', '<', '>', '\\', '{', '}'] {
let name = name.to_string();
assert_err!(SubscriberName::parse(name));
}
}
#[test]
fn a_valid_name_is_parsed_successfully() {
let name = "Ursula Le Guin".to_string();
assert_ok!(SubscriberName::parse(name));
}
}

View file

@ -22,9 +22,11 @@ pub async fn subscribe(
form: web::Form<FormData>,
pool: web::Data<PgPool>,
) -> Result<HttpResponse, HttpResponse> {
let name =
SubscriberName::parse(form.0.name).map_err(|_| HttpResponse::BadRequest().finish())?;
let new_subscriber = NewSubscriber {
email: form.0.email,
name: SubscriberName::parse(form.0.name).expect("Name validation failed."),
name,
};
insert_subscriber(&pool, &new_subscriber)
.await