Merge pull request 'Fix #1121: Check email block list when email sign-up' (#1122) from block-on-email-signup into main
Reviewed-on: https://git.joinplu.me/Plume/Plume/pulls/1122
This commit is contained in:
commit
85c1bfa300
@ -126,11 +126,9 @@ pub(crate) mod tests {
|
|||||||
.id,
|
.id,
|
||||||
various[1].id
|
various[1].id
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(BlocklistedEmail::matches_blocklist(&conn, no_match)
|
||||||
BlocklistedEmail::matches_blocklist(&conn, no_match)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.is_none()
|
.is_none());
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
blocklisted_emails::BlocklistedEmail,
|
||||||
db_conn::DbConn,
|
db_conn::DbConn,
|
||||||
schema::email_signups,
|
schema::email_signups,
|
||||||
users::{NewUser, Role, User},
|
users::{NewUser, Role, User},
|
||||||
@ -60,6 +61,8 @@ pub struct NewEmailSignup<'a> {
|
|||||||
|
|
||||||
impl EmailSignup {
|
impl EmailSignup {
|
||||||
pub fn start(conn: &DbConn, email: &str) -> Result<Token> {
|
pub fn start(conn: &DbConn, email: &str) -> Result<Token> {
|
||||||
|
Self::ensure_email_not_blocked(conn, email)?;
|
||||||
|
|
||||||
conn.transaction(|| {
|
conn.transaction(|| {
|
||||||
Self::ensure_user_not_exist_by_email(conn, email)?;
|
Self::ensure_user_not_exist_by_email(conn, email)?;
|
||||||
let _rows = Self::delete_existings_by_email(conn, email)?;
|
let _rows = Self::delete_existings_by_email(conn, email)?;
|
||||||
@ -90,6 +93,8 @@ impl EmailSignup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn confirm(&self, conn: &DbConn) -> Result<()> {
|
pub fn confirm(&self, conn: &DbConn) -> Result<()> {
|
||||||
|
Self::ensure_email_not_blocked(conn, &self.email)?;
|
||||||
|
|
||||||
conn.transaction(|| {
|
conn.transaction(|| {
|
||||||
Self::ensure_user_not_exist_by_email(conn, &self.email)?;
|
Self::ensure_user_not_exist_by_email(conn, &self.email)?;
|
||||||
if self.expired() {
|
if self.expired() {
|
||||||
@ -101,6 +106,8 @@ impl EmailSignup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn complete(&self, conn: &DbConn, username: String, password: String) -> Result<User> {
|
pub fn complete(&self, conn: &DbConn, username: String, password: String) -> Result<User> {
|
||||||
|
Self::ensure_email_not_blocked(conn, &self.email)?;
|
||||||
|
|
||||||
conn.transaction(|| {
|
conn.transaction(|| {
|
||||||
Self::ensure_user_not_exist_by_email(conn, &self.email)?;
|
Self::ensure_user_not_exist_by_email(conn, &self.email)?;
|
||||||
let user = NewUser::new_local(
|
let user = NewUser::new_local(
|
||||||
@ -122,6 +129,14 @@ impl EmailSignup {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ensure_email_not_blocked(conn: &DbConn, email: &str) -> Result<()> {
|
||||||
|
if let Some(x) = BlocklistedEmail::matches_blocklist(conn, email)? {
|
||||||
|
Err(Error::Blocklisted(x.notify_user, x.notification_text))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ensure_user_not_exist_by_email(conn: &DbConn, email: &str) -> Result<()> {
|
fn ensure_user_not_exist_by_email(conn: &DbConn, email: &str) -> Result<()> {
|
||||||
if User::email_used(conn, email)? {
|
if User::email_used(conn, email)? {
|
||||||
let _rows = Self::delete_existings_by_email(conn, email)?;
|
let _rows = Self::delete_existings_by_email(conn, email)?;
|
||||||
|
@ -107,12 +107,7 @@ impl Follow {
|
|||||||
res.notify(conn)?;
|
res.notify(conn)?;
|
||||||
|
|
||||||
let accept = res.build_accept(from, target, follow)?;
|
let accept = res.build_accept(from, target, follow)?;
|
||||||
broadcast(
|
broadcast(target, accept, vec![from.clone()], CONFIG.proxy().cloned());
|
||||||
target,
|
|
||||||
accept,
|
|
||||||
vec![from.clone()],
|
|
||||||
CONFIG.proxy().cloned(),
|
|
||||||
);
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,8 @@ impl Post {
|
|||||||
.filter(posts::id.eq_any(ids))
|
.filter(posts::id.eq_any(ids))
|
||||||
.filter(posts::published.eq(true))
|
.filter(posts::published.eq(true))
|
||||||
.count()
|
.count()
|
||||||
.load(conn)?.first()
|
.load(conn)?
|
||||||
|
.first()
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(Error::NotFound)
|
.ok_or(Error::NotFound)
|
||||||
}
|
}
|
||||||
|
@ -291,13 +291,7 @@ mod tests {
|
|||||||
"all".to_owned(),
|
"all".to_owned(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
List::new(
|
List::new(conn, "languages I speak", Some(&users[1]), ListType::Prefix).unwrap();
|
||||||
conn,
|
|
||||||
"languages I speak",
|
|
||||||
Some(&users[1]),
|
|
||||||
ListType::Prefix,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let tl2_u1 = Timeline::new_for_user(
|
let tl2_u1 = Timeline::new_for_user(
|
||||||
conn,
|
conn,
|
||||||
users[0].id,
|
users[0].id,
|
||||||
@ -337,18 +331,14 @@ mod tests {
|
|||||||
|
|
||||||
let tl_instance = Timeline::list_for_user(conn, None).unwrap();
|
let tl_instance = Timeline::list_for_user(conn, None).unwrap();
|
||||||
assert_eq!(3, tl_instance.len()); // there are also the local and federated feed by default
|
assert_eq!(3, tl_instance.len()); // there are also the local and federated feed by default
|
||||||
assert!(tl_instance
|
assert!(tl_instance.iter().any(|tl| *tl == tl1_instance));
|
||||||
.iter()
|
|
||||||
.any(|tl| *tl == tl1_instance));
|
|
||||||
|
|
||||||
tl1_u1.name = "My Super TL".to_owned();
|
tl1_u1.name = "My Super TL".to_owned();
|
||||||
let new_tl1_u2 = tl1_u2.update(conn).unwrap();
|
let new_tl1_u2 = tl1_u2.update(conn).unwrap();
|
||||||
|
|
||||||
let tl_u2 = Timeline::list_for_user(conn, Some(users[1].id)).unwrap();
|
let tl_u2 = Timeline::list_for_user(conn, Some(users[1].id)).unwrap();
|
||||||
assert_eq!(2, tl_u2.len()); // same here
|
assert_eq!(2, tl_u2.len()); // same here
|
||||||
assert!(tl_u2
|
assert!(tl_u2.iter().any(|tl| *tl == new_tl1_u2));
|
||||||
.iter()
|
|
||||||
.any(|tl| *tl == new_tl1_u2));
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
@ -463,20 +463,24 @@ mod tests {
|
|||||||
Instance::cache_local(conn);
|
Instance::cache_local(conn);
|
||||||
instance
|
instance
|
||||||
});
|
});
|
||||||
let mut user = NewUser::default();
|
let user = NewUser {
|
||||||
user.instance_id = instance.id;
|
instance_id: instance.id,
|
||||||
user.username = random_hex();
|
username: random_hex(),
|
||||||
user.ap_url = random_hex();
|
ap_url: random_hex(),
|
||||||
user.inbox_url = random_hex();
|
inbox_url: random_hex(),
|
||||||
user.outbox_url = random_hex();
|
outbox_url: random_hex(),
|
||||||
user.followers_endpoint = random_hex();
|
followers_endpoint: random_hex(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
let user = User::insert(conn, user).unwrap();
|
let user = User::insert(conn, user).unwrap();
|
||||||
let mut blog = NewBlog::default();
|
let blog = NewBlog {
|
||||||
blog.instance_id = instance.id;
|
instance_id: instance.id,
|
||||||
blog.actor_id = random_hex();
|
actor_id: random_hex(),
|
||||||
blog.ap_url = random_hex();
|
ap_url: random_hex(),
|
||||||
blog.inbox_url = random_hex();
|
inbox_url: random_hex(),
|
||||||
blog.outbox_url = random_hex();
|
outbox_url: random_hex(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
let blog = Blog::insert(conn, blog).unwrap();
|
let blog = Blog::insert(conn, blog).unwrap();
|
||||||
BlogAuthor::insert(
|
BlogAuthor::insert(
|
||||||
conn,
|
conn,
|
||||||
|
@ -3,6 +3,7 @@ use crate::{
|
|||||||
routes::{errors::ErrorPage, RespondOrRedirect},
|
routes::{errors::ErrorPage, RespondOrRedirect},
|
||||||
template_utils::{IntoContext, Ructe},
|
template_utils::{IntoContext, Ructe},
|
||||||
};
|
};
|
||||||
|
|
||||||
use plume_models::{
|
use plume_models::{
|
||||||
db_conn::DbConn, email_signups::EmailSignup, instance::Instance, lettre::Transport, signups,
|
db_conn::DbConn, email_signups::EmailSignup, instance::Instance, lettre::Transport, signups,
|
||||||
Error, PlumeRocket, CONFIG,
|
Error, PlumeRocket, CONFIG,
|
||||||
@ -13,7 +14,11 @@ use rocket::{
|
|||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
State,
|
State,
|
||||||
};
|
};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use validator::{Validate, ValidationError, ValidationErrors};
|
use validator::{Validate, ValidationError, ValidationErrors};
|
||||||
|
|
||||||
@ -105,6 +110,26 @@ pub fn create(
|
|||||||
render!(email_signups::create(&(&conn, &rockets).to_context())).into()
|
render!(email_signups::create(&(&conn, &rockets).to_context())).into()
|
||||||
}
|
}
|
||||||
Error::NotFound => render!(errors::not_found(&(&conn, &rockets).to_context())).into(),
|
Error::NotFound => render!(errors::not_found(&(&conn, &rockets).to_context())).into(),
|
||||||
|
Error::Blocklisted(show, msg) => {
|
||||||
|
let mut errors = ValidationErrors::new();
|
||||||
|
if *show {
|
||||||
|
errors.add(
|
||||||
|
"email",
|
||||||
|
ValidationError {
|
||||||
|
code: Cow::from("blocklisted"),
|
||||||
|
message: Some(Cow::from(msg.clone())),
|
||||||
|
params: HashMap::new(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
render!(email_signups::new(
|
||||||
|
&(&conn, &rockets).to_context(),
|
||||||
|
registration_open,
|
||||||
|
&form,
|
||||||
|
errors
|
||||||
|
))
|
||||||
|
.into()
|
||||||
|
}
|
||||||
_ => render!(errors::not_found(&(&conn, &rockets).to_context())).into(), // FIXME
|
_ => render!(errors::not_found(&(&conn, &rockets).to_context())).into(), // FIXME
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -153,6 +178,28 @@ pub fn show(
|
|||||||
)))
|
)))
|
||||||
} // TODO: Flash and redirect
|
} // TODO: Flash and redirect
|
||||||
Error::NotFound => return Err(Error::NotFound.into()),
|
Error::NotFound => return Err(Error::NotFound.into()),
|
||||||
|
Error::Blocklisted(show, msg) => {
|
||||||
|
let mut errors = ValidationErrors::new();
|
||||||
|
if show {
|
||||||
|
errors.add(
|
||||||
|
"email",
|
||||||
|
ValidationError {
|
||||||
|
code: Cow::from("blocklisted"),
|
||||||
|
message: Some(Cow::from(msg)),
|
||||||
|
params: HashMap::new(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Ok(render!(email_signups::new(
|
||||||
|
&(&conn, &rockets).to_context(),
|
||||||
|
Instance::get_local()?.open_registrations,
|
||||||
|
&EmailSignupForm {
|
||||||
|
email: signup.email.clone(),
|
||||||
|
email_confirmation: signup.email
|
||||||
|
},
|
||||||
|
errors
|
||||||
|
)));
|
||||||
|
}
|
||||||
_ => return Err(Error::NotFound.into()), // FIXME
|
_ => return Err(Error::NotFound.into()), // FIXME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,12 +254,38 @@ pub fn signup(
|
|||||||
err
|
err
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
let _user = signup
|
let user = signup.complete(&conn, form.username.clone(), form.password.clone());
|
||||||
.complete(&conn, form.username.clone(), form.password.clone())
|
match user {
|
||||||
.map_err(|e| {
|
Err(Error::Blocklisted(show, msg)) => {
|
||||||
|
let instance = Instance::get_local().map_err(|_| Status::UnprocessableEntity)?;
|
||||||
|
let mut errors = ValidationErrors::new();
|
||||||
|
if show {
|
||||||
|
errors.add(
|
||||||
|
"email",
|
||||||
|
ValidationError {
|
||||||
|
code: Cow::from("blocklisted"),
|
||||||
|
message: Some(Cow::from(msg)),
|
||||||
|
params: HashMap::new(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Ok(render!(email_signups::new(
|
||||||
|
&(&conn, &rockets).to_context(),
|
||||||
|
instance.open_registrations,
|
||||||
|
&EmailSignupForm {
|
||||||
|
email: signup.email.clone(),
|
||||||
|
email_confirmation: signup.email
|
||||||
|
},
|
||||||
|
errors
|
||||||
|
))
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
warn!("{:?}", e);
|
warn!("{:?}", e);
|
||||||
Status::UnprocessableEntity
|
return Err(Status::UnprocessableEntity);
|
||||||
})?;
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
Ok(FlashRedirect(Flash::success(
|
Ok(FlashRedirect(Flash::success(
|
||||||
Redirect::to(uri!(super::session::new: m = _)),
|
Redirect::to(uri!(super::session::new: m = _)),
|
||||||
i18n!(
|
i18n!(
|
||||||
|
Loading…
Reference in New Issue
Block a user