Skip to content

Commit

Permalink
Merge pull request 'Fix #1001 Deny access to disabled sign-up strateg…
Browse files Browse the repository at this point in the history
…y' (#1002) from restrict-signup into main

Reviewed-on: https://git.joinplu.me/Plume/Plume/pulls/1002
  • Loading branch information
KitaitiMakoto committed Jan 12, 2022
2 parents 8c48abf + 43b46a8 commit 808b8f8
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 85 deletions.
18 changes: 1 addition & 17 deletions plume-common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ use heck::ToUpperCamelCase;
use openssl::rand::rand_bytes;
use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag};
use regex_syntax::is_word_character;
use rocket::{
http::uri::Uri,
response::{Flash, Redirect},
};
use rocket::http::uri::Uri;
use std::collections::HashSet;
use syntect::html::{ClassStyle, ClassedHTMLGenerator};
use syntect::parsing::SyntaxSet;
Expand Down Expand Up @@ -80,19 +77,6 @@ pub fn iri_percent_encode_seg_char(c: char) -> String {
}
}

/**
* Redirects to the login page with a given message.
*
* Note that the message should be translated before passed to this function.
*/
pub fn requires_login<T: Into<Uri<'static>>>(message: &str, url: T) -> Flash<Redirect> {
Flash::new(
Redirect::to(format!("/login?m={}", Uri::percent_encode(message))),
"callback",
url.into().to_string(),
)
}

#[derive(Debug)]
enum State {
Mention,
Expand Down
27 changes: 27 additions & 0 deletions plume-models/src/signups.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::CONFIG;
use rocket::request::{FromRequest, Outcome, Request};
use std::fmt;
use std::str::FromStr;

Expand Down Expand Up @@ -43,3 +45,28 @@ impl fmt::Display for StrategyError {
}

impl std::error::Error for StrategyError {}

pub struct Password();
pub struct Email();

impl<'a, 'r> FromRequest<'a, 'r> for Password {
type Error = ();

fn from_request(_request: &'a Request<'r>) -> Outcome<Self, ()> {
match matches!(CONFIG.signup, Strategy::Password) {
true => Outcome::Success(Self()),
false => Outcome::Forward(()),
}
}
}

impl<'a, 'r> FromRequest<'a, 'r> for Email {
type Error = ();

fn from_request(_request: &'a Request<'r>) -> Outcome<Self, ()> {
match matches!(CONFIG.signup, Strategy::Email) {
true => Outcome::Success(Self()),
false => Outcome::Forward(()),
}
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ init_i18n!(
mod api;
mod inbox;
mod mail;
mod utils;
#[macro_use]
mod template_utils;
mod routes;
Expand Down
3 changes: 2 additions & 1 deletion src/routes/blogs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use validator::{Validate, ValidationError, ValidationErrors};

use crate::routes::{errors::ErrorPage, Page, RespondOrRedirect};
use crate::template_utils::{IntoContext, Ructe};
use crate::utils::requires_login;
use plume_common::activity_pub::{ActivityStream, ApRequest};
use plume_common::utils;
use plume_models::{
Expand Down Expand Up @@ -62,7 +63,7 @@ pub fn new(conn: DbConn, rockets: PlumeRocket, _user: User) -> Ructe {

#[get("/blogs/new", rank = 2)]
pub fn new_auth(i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
requires_login(
&i18n!(
i18n.catalog,
"To create a new blog, you need to be logged in"
Expand Down
64 changes: 26 additions & 38 deletions src/routes/email_signups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::{
template_utils::{IntoContext, Ructe},
};
use plume_models::{
db_conn::DbConn, email_signups::EmailSignup, instance::Instance, lettre::Transport,
signups::Strategy as SignupStrategy, Error, PlumeRocket, CONFIG,
db_conn::DbConn, email_signups::EmailSignup, instance::Instance, lettre::Transport, signups,
Error, PlumeRocket, CONFIG,
};
use rocket::{
http::Status,
Expand Down Expand Up @@ -69,56 +69,43 @@ pub fn create(
form: LenientForm<EmailSignupForm>,
conn: DbConn,
rockets: PlumeRocket,
) -> Result<RespondOrRedirect, Ructe> {
use RespondOrRedirect::{FlashRedirect, Response};

if !matches!(CONFIG.signup, SignupStrategy::Email) {
return Ok(FlashRedirect(Flash::error(
Redirect::to(uri!(super::user::new)),
i18n!(
rockets.intl.catalog,
"Email registrations are not enabled. Please restart."
),
)));
}

let registration_open = !Instance::get_local()
_enabled: signups::Email,
) -> Result<RespondOrRedirect, ErrorPage> {
let registration_open = Instance::get_local()
.map(|i| i.open_registrations)
.unwrap_or(true);

if registration_open {
return Ok(FlashRedirect(Flash::error(
if !registration_open {
return Ok(Flash::error(
Redirect::to(uri!(super::user::new)),
i18n!(
rockets.intl.catalog,
"Registrations are closed on this instance."
),
))); // Actually, it is an error
)
.into()); // Actually, it is an error
}
let mut form = form.into_inner();
form.email = form.email.trim().to_owned();
form.validate().map_err(|err| {
render!(email_signups::new(
if let Err(err) = form.validate() {
return Ok(render!(email_signups::new(
&(&conn, &rockets).to_context(),
registration_open,
&form,
err
))
})?;
.into());
}
let res = EmailSignup::start(&conn, &form.email);
if let Some(err) = res.as_ref().err() {
return Ok(match err {
Error::UserAlreadyExists => {
// TODO: Notify to admin (and the user?)
warn!("Registration attempted for existing user: {}. Registraion halted and email sending skipped.", &form.email);
Response(render!(email_signups::create(
&(&conn, &rockets).to_context()
)))
render!(email_signups::create(&(&conn, &rockets).to_context())).into()
}
Error::NotFound => {
Response(render!(errors::not_found(&(&conn, &rockets).to_context())))
}
_ => Response(render!(errors::not_found(&(&conn, &rockets).to_context()))), // FIXME
Error::NotFound => render!(errors::not_found(&(&conn, &rockets).to_context())).into(),
_ => render!(errors::not_found(&(&conn, &rockets).to_context())).into(), // FIXME
});
}
let token = res.unwrap();
Expand All @@ -138,18 +125,21 @@ pub fn create(
mailer.send(message.into()).ok(); // TODO: Render error page
}

Ok(Response(render!(email_signups::create(
&(&conn, &rockets).to_context()
))))
Ok(render!(email_signups::create(&(&conn, &rockets).to_context())).into())
}

#[get("/email_signups/new")]
pub fn created(conn: DbConn, rockets: PlumeRocket) -> Ructe {
pub fn created(conn: DbConn, rockets: PlumeRocket, _enabled: signups::Email) -> Ructe {
render!(email_signups::create(&(&conn, &rockets).to_context()))
}

#[get("/email_signups/<token>")]
pub fn show(token: String, conn: DbConn, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
pub fn show(
token: String,
conn: DbConn,
rockets: PlumeRocket,
_enabled: signups::Email,
) -> Result<Ructe, ErrorPage> {
let signup = EmailSignup::find_by_token(&conn, token.into())?;
let confirmation = signup.confirm(&conn);
if let Some(err) = confirmation.err() {
Expand Down Expand Up @@ -185,6 +175,7 @@ pub fn signup(
form: LenientForm<NewUserForm>,
conn: DbConn,
rockets: PlumeRocket,
_enabled: signups::Email,
) -> Result<RespondOrRedirect, Status> {
use RespondOrRedirect::{FlashRedirect, Response};

Expand All @@ -206,11 +197,8 @@ pub fn signup(
let mut err = ValidationErrors::default();
err.add("email", ValidationError::new("Email couldn't changed"));
let form = NewUserForm {
username: form.username.clone(),
password: form.password.clone(),
password_confirmation: form.password_confirmation.clone(),
email: signup.email,
token: form.token.clone(),
..form.into_inner()
};
return Ok(Response(render!(email_signups::edit(
&(&conn, &rockets).to_context(),
Expand Down
16 changes: 6 additions & 10 deletions src/routes/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::template_utils::{IntoContext, Ructe};
use plume_models::{db_conn::DbConn, Error, PlumeRocket};
use rocket::{
http::Status,
response::{self, Responder},
Request,
};
Expand All @@ -16,18 +17,13 @@ impl From<Error> for ErrorPage {
}

impl<'r> Responder<'r> for ErrorPage {
fn respond_to(self, req: &Request<'_>) -> response::Result<'r> {
let conn = req.guard::<DbConn>().unwrap();
let rockets = req.guard::<PlumeRocket>().unwrap();
fn respond_to(self, _req: &Request<'_>) -> response::Result<'r> {
warn!("{:?}", self.0);

match self.0 {
Error::NotFound => {
render!(errors::not_found(&(&conn, &rockets).to_context())).respond_to(req)
}
Error::Unauthorized => {
render!(errors::not_found(&(&conn, &rockets).to_context())).respond_to(req)
}
_ => render!(errors::not_found(&(&conn, &rockets).to_context())).respond_to(req),
Error::NotFound => Err(Status::NotFound),
Error::Unauthorized => Err(Status::NotFound),
_ => Err(Status::InternalServerError),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/routes/likes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use rocket::response::{Flash, Redirect};
use rocket_i18n::I18n;

use crate::routes::errors::ErrorPage;
use crate::utils::requires_login;
use plume_common::activity_pub::broadcast;
use plume_common::utils;
use plume_models::{
blogs::Blog, db_conn::DbConn, inbox::inbox, likes, posts::Post, timeline::*, users::User,
Error, PlumeRocket, CONFIG,
Expand Down Expand Up @@ -54,7 +54,7 @@ pub fn create(

#[post("/~/<blog>/<slug>/like", rank = 2)]
pub fn create_auth(blog: String, slug: String, i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
requires_login(
&i18n!(i18n.catalog, "To like a post, you need to be logged in"),
uri!(create: blog = blog, slug = slug),
)
Expand Down
4 changes: 2 additions & 2 deletions src/routes/notifications.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rocket_i18n::I18n;

use crate::routes::{errors::ErrorPage, Page};
use crate::template_utils::{IntoContext, Ructe};
use plume_common::utils;
use crate::utils::requires_login;
use plume_models::{db_conn::DbConn, notifications::Notification, users::User, PlumeRocket};

#[get("/notifications?<page>")]
Expand All @@ -24,7 +24,7 @@ pub fn notifications(

#[get("/notifications?<page>", rank = 2)]
pub fn notifications_auth(i18n: I18n, page: Option<Page>) -> Flash<Redirect> {
utils::requires_login(
requires_login(
&i18n!(
i18n.catalog,
"To see your notifications, you need to be logged in"
Expand Down
9 changes: 5 additions & 4 deletions src/routes/posts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use crate::routes::{
comments::NewCommentForm, errors::ErrorPage, ContentLen, RemoteForm, RespondOrRedirect,
};
use crate::template_utils::{IntoContext, Ructe};
use crate::utils::requires_login;
use plume_common::activity_pub::{broadcast, ActivityStream, ApRequest};
use plume_common::utils;
use plume_common::utils::md_to_html;
use plume_models::{
blogs::*,
comments::{Comment, CommentTree},
Expand Down Expand Up @@ -120,7 +121,7 @@ pub fn activity_details(

#[get("/~/<blog>/new", rank = 2)]
pub fn new_auth(blog: String, i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
requires_login(
&i18n!(
i18n.catalog,
"To write a new post, you need to be logged in"
Expand Down Expand Up @@ -268,7 +269,7 @@ pub fn update(
)
.into()
} else {
let (content, mentions, hashtags) = utils::md_to_html(
let (content, mentions, hashtags) = md_to_html(
form.content.to_string().as_ref(),
Some(
&Instance::get_local()
Expand Down Expand Up @@ -452,7 +453,7 @@ pub fn create(
.into());
}

let (content, mentions, hashtags) = utils::md_to_html(
let (content, mentions, hashtags) = md_to_html(
form.content.to_string().as_ref(),
Some(
&Instance::get_local()
Expand Down
4 changes: 2 additions & 2 deletions src/routes/reshares.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use rocket::response::{Flash, Redirect};
use rocket_i18n::I18n;

use crate::routes::errors::ErrorPage;
use crate::utils::requires_login;
use plume_common::activity_pub::broadcast;
use plume_common::utils;
use plume_models::{
blogs::Blog, db_conn::DbConn, inbox::inbox, posts::Post, reshares::*, timeline::*, users::User,
Error, PlumeRocket, CONFIG,
Expand Down Expand Up @@ -54,7 +54,7 @@ pub fn create(

#[post("/~/<blog>/<slug>/reshare", rank = 1)]
pub fn create_auth(blog: String, slug: String, i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
requires_login(
&i18n!(i18n.catalog, "To reshare a post, you need to be logged in"),
uri!(create: blog = blog, slug = slug),
)
Expand Down
Loading

0 comments on commit 808b8f8

Please sign in to comment.