summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2019-01-22 15:37:15 +0100
committerPietro Albini <pietro@pietroalbini.org>2019-01-22 15:38:52 +0100
commita019513efb557941dcf301aba5585aa5111f2279 (patch)
treed772db52fe2cb83de68314d6108aa194463549cb /src
parentb04ab9108b4324da2bad7e5b560c9339b2a90066 (diff)
add support for `email = false` to disable email validation
This allows a person to explicitly opt out from the mailing lists.
Diffstat (limited to 'src')
-rw-r--r--src/data.rs7
-rw-r--r--src/schema.rs45
-rw-r--r--src/validate.rs5
3 files changed, 48 insertions, 9 deletions
diff --git a/src/data.rs b/src/data.rs
index 22af7a2..a93fc4b 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -21,11 +21,14 @@ impl Data {
};
data.load_dir("people", |this, person: Person| {
+ person.validate()?;
this.people.insert(person.github().to_string(), person);
+ Ok(())
})?;
data.load_dir("teams", |this, team: Team| {
this.teams.insert(team.name().to_string(), team);
+ Ok(())
})?;
Ok(data)
@@ -34,13 +37,13 @@ impl Data {
fn load_dir<T, F>(&mut self, dir: &str, f: F) -> Result<(), Error>
where
T: for<'de> Deserialize<'de>,
- F: Fn(&mut Self, T),
+ F: Fn(&mut Self, T) -> Result<(), Error>,
{
for entry in std::fs::read_dir(dir)? {
let path = entry?.path();
if path.is_file() && path.extension() == Some(OsStr::new("toml")) {
- f(self, load_file(&path)?);
+ f(self, load_file(&path)?)?;
}
}
diff --git a/src/schema.rs b/src/schema.rs
index de30b08..f527827 100644
--- a/src/schema.rs
+++ b/src/schema.rs
@@ -1,5 +1,5 @@
use crate::data::Data;
-use failure::{err_msg, Error};
+use failure::{bail, err_msg, Error};
use std::collections::HashSet;
#[derive(serde_derive::Deserialize, Debug)]
@@ -14,13 +14,36 @@ impl Config {
}
}
+// This is an enum to allow two kinds of values for the email field:
+// email = false
+// email = "foo@example.com"
+#[derive(serde_derive::Deserialize, Debug)]
+#[serde(untagged)]
+enum EmailField {
+ Disabled(bool),
+ Explicit(Option<String>),
+}
+
+impl Default for EmailField {
+ fn default() -> Self {
+ EmailField::Explicit(None)
+ }
+}
+
+pub(crate) enum Email<'a> {
+ Missing,
+ Disabled,
+ Present(&'a str),
+}
+
#[derive(serde_derive::Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub(crate) struct Person {
name: String,
github: String,
irc: Option<String>,
- email: Option<String>,
+ #[serde(default)]
+ email: EmailField,
discord: Option<String>,
}
@@ -43,13 +66,25 @@ impl Person {
}
}
- pub(crate) fn email(&self) -> Option<&str> {
- self.email.as_ref().map(|e| e.as_str())
+ pub(crate) fn email(&self) -> Email {
+ match &self.email {
+ EmailField::Disabled(false) => Email::Disabled,
+ EmailField::Disabled(true) => Email::Missing,
+ EmailField::Explicit(None) => Email::Missing,
+ EmailField::Explicit(Some(addr)) => Email::Present(addr.as_str()),
+ }
}
pub(crate) fn discord(&self) -> Option<&str> {
self.discord.as_ref().map(|e| e.as_str())
}
+
+ pub(crate) fn validate(&self) -> Result<(), Error> {
+ if let EmailField::Disabled(true) = &self.email {
+ bail!("`email = true` is not valid (for person {})", self.github);
+ }
+ Ok(())
+ }
}
#[derive(serde_derive::Deserialize, Debug)]
@@ -137,7 +172,7 @@ impl Team {
let member = data
.person(member)
.ok_or_else(|| err_msg(format!("member {} is missing", member)))?;
- if let Some(email) = member.email() {
+ if let Email::Present(email) = member.email() {
list.emails.push(email.to_string());
}
}
diff --git a/src/validate.rs b/src/validate.rs
index 3c2d6c7..c9c66a5 100644
--- a/src/validate.rs
+++ b/src/validate.rs
@@ -1,5 +1,6 @@
use crate::data::Data;
use failure::{bail, Error};
+use crate::schema::Email;
use regex::Regex;
use std::collections::HashSet;
@@ -107,7 +108,7 @@ fn validate_list_email_addresses(data: &Data, errors: &mut Vec<String>) {
}
wrapper(team.members(data)?.iter(), errors, |member, _| {
let member = data.person(member).unwrap();
- if member.email().is_none() {
+ if let Email::Missing = member.email() {
bail!(
"person `{}` is a member of a mailing list but has no email address",
member.github()
@@ -179,7 +180,7 @@ fn validate_list_addresses(data: &Data, errors: &mut Vec<String>) {
/// Ensure people email addresses are correct
fn validate_people_addresses(data: &Data, errors: &mut Vec<String>) {
wrapper(data.people(), errors, |person, _| {
- if let Some(email) = person.email() {
+ if let Email::Present(email) = person.email() {
if !email.contains('@') {
bail!("invalid email address of `{}`: {}", person.github(), email);
}