Add some feedback when performing some actions (#552)
* Add a way to display flash messages * Make the flash messages look nice * Add actual feedback messages * cargo fmt * Move flash messages to PlumeRocket And add trait to convert PlumeRocket to BaseContext * Remove useless lifetime
This commit is contained in:
@@ -45,7 +45,6 @@ use plume_models::{
|
||||
search::{Searcher as UnmanagedSearcher, SearcherError},
|
||||
Connection, Error, CONFIG,
|
||||
};
|
||||
use rocket::State;
|
||||
use rocket_csrf::CsrfFairingBuilder;
|
||||
use scheduled_thread_pool::ScheduledThreadPool;
|
||||
use std::process::exit;
|
||||
@@ -69,8 +68,6 @@ include!(concat!(env!("OUT_DIR"), "/templates.rs"));
|
||||
|
||||
compile_i18n!();
|
||||
|
||||
type Searcher<'a> = State<'a, Arc<UnmanagedSearcher>>;
|
||||
|
||||
/// Initializes a database pool.
|
||||
fn init_pool() -> Option<DbPool> {
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
+41
-37
@@ -17,21 +17,19 @@ use plume_models::{
|
||||
users::User, Connection, PlumeRocket,
|
||||
};
|
||||
use routes::{errors::ErrorPage, Page};
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/~/<name>?<page>", rank = 2)]
|
||||
pub fn details(name: String, page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let conn = &*rockets.conn;
|
||||
let blog = Blog::find_by_fqn(&rockets, &name)?;
|
||||
let posts = Post::blog_page(&*conn, &blog, page.limits())?;
|
||||
let articles_count = Post::count_for_blog(&*conn, &blog)?;
|
||||
let authors = &blog.list_authors(&*conn)?;
|
||||
let user = rockets.user;
|
||||
let intl = rockets.intl;
|
||||
let posts = Post::blog_page(conn, &blog, page.limits())?;
|
||||
let articles_count = Post::count_for_blog(conn, &blog)?;
|
||||
let authors = &blog.list_authors(conn)?;
|
||||
|
||||
Ok(render!(blogs::details(
|
||||
&(&*conn, &intl.catalog, user.clone()),
|
||||
&rockets.to_context(),
|
||||
blog,
|
||||
authors,
|
||||
page.0,
|
||||
@@ -51,13 +49,9 @@ pub fn activity_details(
|
||||
}
|
||||
|
||||
#[get("/blogs/new")]
|
||||
pub fn new(rockets: PlumeRocket) -> Ructe {
|
||||
let user = rockets.user.unwrap();
|
||||
let intl = rockets.intl;
|
||||
let conn = &*rockets.conn;
|
||||
|
||||
pub fn new(rockets: PlumeRocket, _user: User) -> Ructe {
|
||||
render!(blogs::new(
|
||||
&(&*conn, &intl.catalog, Some(user)),
|
||||
&rockets.to_context(),
|
||||
&NewBlogForm::default(),
|
||||
ValidationErrors::default()
|
||||
))
|
||||
@@ -90,7 +84,10 @@ fn valid_slug(title: &str) -> Result<(), ValidationError> {
|
||||
}
|
||||
|
||||
#[post("/blogs/new", data = "<form>")]
|
||||
pub fn create(form: LenientForm<NewBlogForm>, rockets: PlumeRocket) -> Result<Redirect, Ructe> {
|
||||
pub fn create(
|
||||
form: LenientForm<NewBlogForm>,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
let slug = utils::make_actor_id(&form.title);
|
||||
let conn = &*rockets.conn;
|
||||
let intl = &rockets.intl.catalog;
|
||||
@@ -139,37 +136,40 @@ pub fn create(form: LenientForm<NewBlogForm>, rockets: PlumeRocket) -> Result<Re
|
||||
)
|
||||
.expect("blog::create: author error");
|
||||
|
||||
Ok(Redirect::to(uri!(details: name = slug.clone(), page = _)))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(details: name = slug.clone(), page = _)),
|
||||
&i18n!(intl, "Your blog was successfully created!"),
|
||||
))
|
||||
} else {
|
||||
Err(render!(blogs::new(
|
||||
&(&*conn, intl, Some(user)),
|
||||
&*form,
|
||||
errors
|
||||
)))
|
||||
Err(render!(blogs::new(&rockets.to_context(), &*form, errors)))
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/~/<name>/delete")]
|
||||
pub fn delete(name: String, rockets: PlumeRocket) -> Result<Redirect, Ructe> {
|
||||
pub fn delete(name: String, rockets: PlumeRocket) -> Result<Flash<Redirect>, Ructe> {
|
||||
let conn = &*rockets.conn;
|
||||
let blog = Blog::find_by_fqn(&rockets, &name).expect("blog::delete: blog not found");
|
||||
let user = rockets.user;
|
||||
let intl = rockets.intl;
|
||||
let searcher = rockets.searcher;
|
||||
|
||||
if user
|
||||
if rockets
|
||||
.user
|
||||
.clone()
|
||||
.and_then(|u| u.is_author_in(&*conn, &blog).ok())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
blog.delete(&conn, &searcher)
|
||||
blog.delete(&conn, &rockets.searcher)
|
||||
.expect("blog::expect: deletion error");
|
||||
Ok(Redirect::to(uri!(super::instance::index)))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(super::instance::index)),
|
||||
i18n!(rockets.intl.catalog, "Your blog was deleted."),
|
||||
))
|
||||
} else {
|
||||
// TODO actually return 403 error code
|
||||
Err(render!(errors::not_authorized(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
i18n!(intl.catalog, "You are not allowed to delete this blog.")
|
||||
&rockets.to_context(),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"You are not allowed to delete this blog."
|
||||
)
|
||||
)))
|
||||
}
|
||||
}
|
||||
@@ -190,15 +190,16 @@ pub fn edit(name: String, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
if rockets
|
||||
.user
|
||||
.clone()
|
||||
.and_then(|u| u.is_author_in(&*conn, &blog).ok())
|
||||
.and_then(|u| u.is_author_in(conn, &blog).ok())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let user = rockets
|
||||
.user
|
||||
.clone()
|
||||
.expect("blogs::edit: User was None while it shouldn't");
|
||||
let medias = Media::for_user(&*conn, user.id).expect("Couldn't list media");
|
||||
let medias = Media::for_user(conn, user.id).expect("Couldn't list media");
|
||||
Ok(render!(blogs::edit(
|
||||
&(&*conn, &rockets.intl.catalog, Some(user)),
|
||||
&rockets.to_context(),
|
||||
&blog,
|
||||
medias,
|
||||
&EditForm {
|
||||
@@ -212,7 +213,7 @@ pub fn edit(name: String, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
} else {
|
||||
// TODO actually return 403 error code
|
||||
Ok(render!(errors::not_authorized(
|
||||
&(&*conn, &rockets.intl.catalog, rockets.user),
|
||||
&rockets.to_context(),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"You are not allowed to edit this blog."
|
||||
@@ -235,7 +236,7 @@ pub fn update(
|
||||
name: String,
|
||||
form: LenientForm<EditForm>,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, Ructe> {
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
let conn = &*rockets.conn;
|
||||
let intl = &rockets.intl.catalog;
|
||||
let mut blog = Blog::find_by_fqn(&rockets, &name).expect("blog::update: blog not found");
|
||||
@@ -308,12 +309,15 @@ pub fn update(
|
||||
blog.banner_id = form.banner;
|
||||
blog.save_changes::<Blog>(&*conn)
|
||||
.expect("Couldn't save blog changes");
|
||||
Ok(Redirect::to(uri!(details: name = name, page = _)))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(details: name = name, page = _)),
|
||||
i18n!(intl, "Your blog information have been updated."),
|
||||
))
|
||||
})
|
||||
.map_err(|err| {
|
||||
let medias = Media::for_user(&*conn, user.id).expect("Couldn't list media");
|
||||
render!(blogs::edit(
|
||||
&(&*conn, intl, Some(user)),
|
||||
&rockets.to_context(),
|
||||
&blog,
|
||||
medias,
|
||||
&*form,
|
||||
@@ -323,7 +327,7 @@ pub fn update(
|
||||
} else {
|
||||
// TODO actually return 403 error code
|
||||
Err(render!(errors::not_authorized(
|
||||
&(&*conn, &rockets.intl.catalog, rockets.user),
|
||||
&rockets.to_context(),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"You are not allowed to edit this blog."
|
||||
|
||||
+16
-8
@@ -1,5 +1,8 @@
|
||||
use activitypub::object::Note;
|
||||
use rocket::{request::LenientForm, response::Redirect};
|
||||
use rocket::{
|
||||
request::LenientForm,
|
||||
response::{Flash, Redirect},
|
||||
};
|
||||
use template_utils::Ructe;
|
||||
use validator::Validate;
|
||||
|
||||
@@ -14,6 +17,7 @@ use plume_models::{
|
||||
posts::Post, safe_string::SafeString, tags::Tag, users::User, Error, PlumeRocket,
|
||||
};
|
||||
use routes::errors::ErrorPage;
|
||||
use template_utils::IntoContext;
|
||||
|
||||
#[derive(Default, FromForm, Debug, Validate)]
|
||||
pub struct NewCommentForm {
|
||||
@@ -30,7 +34,7 @@ pub fn create(
|
||||
form: LenientForm<NewCommentForm>,
|
||||
user: User,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, Ructe> {
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
let conn = &*rockets.conn;
|
||||
let blog = Blog::find_by_fqn(&rockets, &blog_name).expect("comments::create: blog error");
|
||||
let post = Post::find_by_slug(&*conn, &slug, blog.id).expect("comments::create: post error");
|
||||
@@ -83,8 +87,11 @@ pub fn create(
|
||||
.worker
|
||||
.execute(move || broadcast(&user_clone, new_comment, dest));
|
||||
|
||||
Redirect::to(
|
||||
uri!(super::posts::details: blog = blog_name, slug = slug, responding_to = _),
|
||||
Flash::success(
|
||||
Redirect::to(
|
||||
uri!(super::posts::details: blog = blog_name, slug = slug, responding_to = _),
|
||||
),
|
||||
i18n!(&rockets.intl.catalog, "Your comment have been posted."),
|
||||
)
|
||||
})
|
||||
.map_err(|errors| {
|
||||
@@ -97,7 +104,7 @@ pub fn create(
|
||||
.and_then(|r| Comment::get(&*conn, r).ok());
|
||||
|
||||
render!(posts::details(
|
||||
&(&*conn, &rockets.intl.catalog, Some(user.clone())),
|
||||
&rockets.to_context(),
|
||||
post.clone(),
|
||||
blog,
|
||||
&*form,
|
||||
@@ -134,7 +141,7 @@ pub fn delete(
|
||||
id: i32,
|
||||
user: User,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, ErrorPage> {
|
||||
) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
if let Ok(comment) = Comment::get(&*rockets.conn, id) {
|
||||
if comment.author_id == user.id {
|
||||
let dest = User::one_by_instance(&*rockets.conn)?;
|
||||
@@ -157,8 +164,9 @@ pub fn delete(
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(Redirect::to(
|
||||
uri!(super::posts::details: blog = blog, slug = slug, responding_to = _),
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(super::posts::details: blog = blog, slug = slug, responding_to = _)),
|
||||
i18n!(&rockets.intl.catalog, "Your comment have been deleted."),
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
+16
-57
@@ -1,12 +1,9 @@
|
||||
use plume_models::users::User;
|
||||
use plume_models::{db_conn::DbConn, Error};
|
||||
use plume_models::{Error, PlumeRocket};
|
||||
use rocket::{
|
||||
request::FromRequest,
|
||||
response::{self, Responder},
|
||||
Request,
|
||||
};
|
||||
use rocket_i18n::I18n;
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ErrorPage(Error);
|
||||
@@ -19,78 +16,40 @@ 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>().succeeded();
|
||||
let intl = req.guard::<I18n>().succeeded();
|
||||
let user = User::from_request(req).succeeded();
|
||||
let rockets = req.guard::<PlumeRocket>().unwrap();
|
||||
|
||||
match self.0 {
|
||||
Error::NotFound => render!(errors::not_found(&(
|
||||
&*conn.unwrap(),
|
||||
&intl.unwrap().catalog,
|
||||
user
|
||||
)))
|
||||
.respond_to(req),
|
||||
Error::Unauthorized => render!(errors::not_found(&(
|
||||
&*conn.unwrap(),
|
||||
&intl.unwrap().catalog,
|
||||
user
|
||||
)))
|
||||
.respond_to(req),
|
||||
_ => render!(errors::not_found(&(
|
||||
&*conn.unwrap(),
|
||||
&intl.unwrap().catalog,
|
||||
user
|
||||
)))
|
||||
.respond_to(req),
|
||||
Error::NotFound => render!(errors::not_found(&rockets.to_context())).respond_to(req),
|
||||
Error::Unauthorized => {
|
||||
render!(errors::not_found(&rockets.to_context())).respond_to(req)
|
||||
}
|
||||
_ => render!(errors::not_found(&rockets.to_context())).respond_to(req),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[catch(404)]
|
||||
pub fn not_found(req: &Request) -> Ructe {
|
||||
let conn = req.guard::<DbConn>().succeeded();
|
||||
let intl = req.guard::<I18n>().succeeded();
|
||||
let user = User::from_request(req).succeeded();
|
||||
render!(errors::not_found(&(
|
||||
&*conn.unwrap(),
|
||||
&intl.unwrap().catalog,
|
||||
user
|
||||
)))
|
||||
let rockets = req.guard::<PlumeRocket>().unwrap();
|
||||
render!(errors::not_found(&rockets.to_context()))
|
||||
}
|
||||
|
||||
#[catch(422)]
|
||||
pub fn unprocessable_entity(req: &Request) -> Ructe {
|
||||
let conn = req.guard::<DbConn>().succeeded();
|
||||
let intl = req.guard::<I18n>().succeeded();
|
||||
let user = User::from_request(req).succeeded();
|
||||
render!(errors::unprocessable_entity(&(
|
||||
&*conn.unwrap(),
|
||||
&intl.unwrap().catalog,
|
||||
user
|
||||
)))
|
||||
let rockets = req.guard::<PlumeRocket>().unwrap();
|
||||
render!(errors::unprocessable_entity(&rockets.to_context()))
|
||||
}
|
||||
|
||||
#[catch(500)]
|
||||
pub fn server_error(req: &Request) -> Ructe {
|
||||
let conn = req.guard::<DbConn>().succeeded();
|
||||
let intl = req.guard::<I18n>().succeeded();
|
||||
let user = User::from_request(req).succeeded();
|
||||
render!(errors::server_error(&(
|
||||
&*conn.unwrap(),
|
||||
&intl.unwrap().catalog,
|
||||
user
|
||||
)))
|
||||
let rockets = req.guard::<PlumeRocket>().unwrap();
|
||||
render!(errors::server_error(&rockets.to_context()))
|
||||
}
|
||||
|
||||
#[post("/csrf-violation?<target>")]
|
||||
pub fn csrf_violation(
|
||||
target: Option<String>,
|
||||
conn: DbConn,
|
||||
intl: I18n,
|
||||
user: Option<User>,
|
||||
) -> Ructe {
|
||||
pub fn csrf_violation(target: Option<String>, rockets: PlumeRocket) -> Ructe {
|
||||
if let Some(uri) = target {
|
||||
eprintln!("Csrf violation while acceding \"{}\"", uri)
|
||||
}
|
||||
render!(errors::csrf(&(&*conn, &intl.catalog, user)))
|
||||
render!(errors::csrf(&rockets.to_context()))
|
||||
}
|
||||
|
||||
+98
-89
@@ -1,6 +1,6 @@
|
||||
use rocket::{
|
||||
request::LenientForm,
|
||||
response::{status, Redirect},
|
||||
response::{status, Flash, Redirect},
|
||||
};
|
||||
use rocket_contrib::json::Json;
|
||||
use rocket_i18n::I18n;
|
||||
@@ -14,25 +14,26 @@ use plume_models::{
|
||||
safe_string::SafeString, users::User, Error, PlumeRocket, CONFIG,
|
||||
};
|
||||
use routes::{errors::ErrorPage, rocket_uri_macro_static_files, Page};
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/")]
|
||||
pub fn index(conn: DbConn, user: Option<User>, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
let inst = Instance::get_local(&*conn)?;
|
||||
let federated = Post::get_recents_page(&*conn, Page::default().limits())?;
|
||||
let local = Post::get_instance_page(&*conn, inst.id, Page::default().limits())?;
|
||||
let user_feed = user.clone().and_then(|user| {
|
||||
let followed = user.get_followed(&*conn).ok()?;
|
||||
pub fn index(rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let conn = &*rockets.conn;
|
||||
let inst = Instance::get_local(conn)?;
|
||||
let federated = Post::get_recents_page(conn, Page::default().limits())?;
|
||||
let local = Post::get_instance_page(conn, inst.id, Page::default().limits())?;
|
||||
let user_feed = rockets.user.clone().and_then(|user| {
|
||||
let followed = user.get_followed(conn).ok()?;
|
||||
let mut in_feed = followed.into_iter().map(|u| u.id).collect::<Vec<i32>>();
|
||||
in_feed.push(user.id);
|
||||
Post::user_feed_page(&*conn, in_feed, Page::default().limits()).ok()
|
||||
Post::user_feed_page(conn, in_feed, Page::default().limits()).ok()
|
||||
});
|
||||
|
||||
Ok(render!(instance::index(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
&rockets.to_context(),
|
||||
inst,
|
||||
User::count_local(&*conn)?,
|
||||
Post::count_local(&*conn)?,
|
||||
User::count_local(conn)?,
|
||||
Post::count_local(conn)?,
|
||||
local,
|
||||
federated,
|
||||
user_feed
|
||||
@@ -40,61 +41,51 @@ pub fn index(conn: DbConn, user: Option<User>, intl: I18n) -> Result<Ructe, Erro
|
||||
}
|
||||
|
||||
#[get("/local?<page>")]
|
||||
pub fn local(
|
||||
conn: DbConn,
|
||||
user: Option<User>,
|
||||
page: Option<Page>,
|
||||
intl: I18n,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
pub fn local(page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let instance = Instance::get_local(&*conn)?;
|
||||
let articles = Post::get_instance_page(&*conn, instance.id, page.limits())?;
|
||||
let instance = Instance::get_local(&*rockets.conn)?;
|
||||
let articles = Post::get_instance_page(&*rockets.conn, instance.id, page.limits())?;
|
||||
Ok(render!(instance::local(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
&rockets.to_context(),
|
||||
instance,
|
||||
articles,
|
||||
page.0,
|
||||
Page::total(Post::count_local(&*conn)? as i32)
|
||||
Page::total(Post::count_local(&*rockets.conn)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
#[get("/feed?<page>")]
|
||||
pub fn feed(conn: DbConn, user: User, page: Option<Page>, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
pub fn feed(user: User, page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let followed = user.get_followed(&*conn)?;
|
||||
let followed = user.get_followed(&*rockets.conn)?;
|
||||
let mut in_feed = followed.into_iter().map(|u| u.id).collect::<Vec<i32>>();
|
||||
in_feed.push(user.id);
|
||||
let articles = Post::user_feed_page(&*conn, in_feed, page.limits())?;
|
||||
let articles = Post::user_feed_page(&*rockets.conn, in_feed, page.limits())?;
|
||||
Ok(render!(instance::feed(
|
||||
&(&*conn, &intl.catalog, Some(user)),
|
||||
&rockets.to_context(),
|
||||
articles,
|
||||
page.0,
|
||||
Page::total(Post::count_local(&*conn)? as i32)
|
||||
Page::total(Post::count_local(&*rockets.conn)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
#[get("/federated?<page>")]
|
||||
pub fn federated(
|
||||
conn: DbConn,
|
||||
user: Option<User>,
|
||||
page: Option<Page>,
|
||||
intl: I18n,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
pub fn federated(page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let articles = Post::get_recents_page(&*conn, page.limits())?;
|
||||
let articles = Post::get_recents_page(&*rockets.conn, page.limits())?;
|
||||
Ok(render!(instance::federated(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
&rockets.to_context(),
|
||||
articles,
|
||||
page.0,
|
||||
Page::total(Post::count_local(&*conn)? as i32)
|
||||
Page::total(Post::count_local(&*rockets.conn)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
#[get("/admin")]
|
||||
pub fn admin(conn: DbConn, admin: Admin, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
let local_inst = Instance::get_local(&*conn)?;
|
||||
pub fn admin(_admin: Admin, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let local_inst = Instance::get_local(&*rockets.conn)?;
|
||||
Ok(render!(instance::admin(
|
||||
&(&*conn, &intl.catalog, Some(admin.0)),
|
||||
&rockets.to_context(),
|
||||
local_inst.clone(),
|
||||
InstanceSettingsForm {
|
||||
name: local_inst.name.clone(),
|
||||
@@ -120,31 +111,34 @@ pub struct InstanceSettingsForm {
|
||||
|
||||
#[post("/admin", data = "<form>")]
|
||||
pub fn update_settings(
|
||||
conn: DbConn,
|
||||
admin: Admin,
|
||||
_admin: Admin,
|
||||
form: LenientForm<InstanceSettingsForm>,
|
||||
intl: I18n,
|
||||
) -> Result<Redirect, Ructe> {
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
let conn = &*rockets.conn;
|
||||
form.validate()
|
||||
.and_then(|_| {
|
||||
let instance = Instance::get_local(&*conn)
|
||||
.expect("instance::update_settings: local instance error");
|
||||
let instance =
|
||||
Instance::get_local(conn).expect("instance::update_settings: local instance error");
|
||||
instance
|
||||
.update(
|
||||
&*conn,
|
||||
conn,
|
||||
form.name.clone(),
|
||||
form.open_registrations,
|
||||
form.short_description.clone(),
|
||||
form.long_description.clone(),
|
||||
)
|
||||
.expect("instance::update_settings: save error");
|
||||
Ok(Redirect::to(uri!(admin)))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(admin)),
|
||||
i18n!(rockets.intl.catalog, "Instance settings have been saved."),
|
||||
))
|
||||
})
|
||||
.or_else(|e| {
|
||||
let local_inst = Instance::get_local(&*conn)
|
||||
.expect("instance::update_settings: local instance error");
|
||||
let local_inst =
|
||||
Instance::get_local(conn).expect("instance::update_settings: local instance error");
|
||||
Err(render!(instance::admin(
|
||||
&(&*conn, &intl.catalog, Some(admin.0)),
|
||||
&rockets.to_context(),
|
||||
local_inst,
|
||||
form.clone(),
|
||||
e
|
||||
@@ -154,64 +148,78 @@ pub fn update_settings(
|
||||
|
||||
#[get("/admin/instances?<page>")]
|
||||
pub fn admin_instances(
|
||||
admin: Admin,
|
||||
conn: DbConn,
|
||||
_admin: Admin,
|
||||
page: Option<Page>,
|
||||
intl: I18n,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let instances = Instance::page(&*conn, page.limits())?;
|
||||
let instances = Instance::page(&*rockets.conn, page.limits())?;
|
||||
Ok(render!(instance::list(
|
||||
&(&*conn, &intl.catalog, Some(admin.0)),
|
||||
Instance::get_local(&*conn)?,
|
||||
&rockets.to_context(),
|
||||
Instance::get_local(&*rockets.conn)?,
|
||||
instances,
|
||||
page.0,
|
||||
Page::total(Instance::count(&*conn)? as i32)
|
||||
Page::total(Instance::count(&*rockets.conn)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
#[post("/admin/instances/<id>/block")]
|
||||
pub fn toggle_block(_admin: Admin, conn: DbConn, id: i32) -> Result<Redirect, ErrorPage> {
|
||||
if let Ok(inst) = Instance::get(&*conn, id) {
|
||||
inst.toggle_block(&*conn)?;
|
||||
}
|
||||
pub fn toggle_block(
|
||||
_admin: Admin,
|
||||
conn: DbConn,
|
||||
id: i32,
|
||||
intl: I18n,
|
||||
) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
let inst = Instance::get(&*conn, id)?;
|
||||
let message = if inst.blocked {
|
||||
i18n!(intl.catalog, "{} have been unblocked."; &inst.name)
|
||||
} else {
|
||||
i18n!(intl.catalog, "{} have been blocked."; &inst.name)
|
||||
};
|
||||
|
||||
Ok(Redirect::to(uri!(admin_instances: page = _)))
|
||||
inst.toggle_block(&*conn)?;
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(admin_instances: page = _)),
|
||||
message,
|
||||
))
|
||||
}
|
||||
|
||||
#[get("/admin/users?<page>")]
|
||||
pub fn admin_users(
|
||||
admin: Admin,
|
||||
conn: DbConn,
|
||||
_admin: Admin,
|
||||
page: Option<Page>,
|
||||
intl: I18n,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
Ok(render!(instance::users(
|
||||
&(&*conn, &intl.catalog, Some(admin.0)),
|
||||
User::get_local_page(&*conn, page.limits())?,
|
||||
&rockets.to_context(),
|
||||
User::get_local_page(&*rockets.conn, page.limits())?,
|
||||
page.0,
|
||||
Page::total(User::count_local(&*conn)? as i32)
|
||||
Page::total(User::count_local(&*rockets.conn)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
#[post("/admin/users/<id>/ban")]
|
||||
pub fn ban(_admin: Admin, id: i32, rockets: PlumeRocket) -> Result<Redirect, ErrorPage> {
|
||||
if let Ok(u) = User::get(&*rockets.conn, id) {
|
||||
u.delete(&*rockets.conn, &rockets.searcher)?;
|
||||
pub fn ban(_admin: Admin, id: i32, rockets: PlumeRocket) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
let u = User::get(&*rockets.conn, id)?;
|
||||
u.delete(&*rockets.conn, &rockets.searcher)?;
|
||||
|
||||
if Instance::get_local(&*rockets.conn)
|
||||
.map(|i| u.instance_id == i.id)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let target = User::one_by_instance(&*rockets.conn)?;
|
||||
let delete_act = u.delete_activity(&*rockets.conn)?;
|
||||
rockets
|
||||
.worker
|
||||
.execute(move || broadcast(&u, delete_act, target));
|
||||
}
|
||||
if Instance::get_local(&*rockets.conn)
|
||||
.map(|i| u.instance_id == i.id)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let target = User::one_by_instance(&*rockets.conn)?;
|
||||
let delete_act = u.delete_activity(&*rockets.conn)?;
|
||||
let u_clone = u.clone();
|
||||
rockets
|
||||
.worker
|
||||
.execute(move || broadcast(&u_clone, delete_act, target));
|
||||
}
|
||||
Ok(Redirect::to(uri!(admin_users: page = _)))
|
||||
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(admin_users: page = _)),
|
||||
i18n!(rockets.intl.catalog, "{} have been banned."; u.name()),
|
||||
))
|
||||
}
|
||||
|
||||
#[post("/inbox", data = "<data>")]
|
||||
@@ -293,14 +301,15 @@ pub fn nodeinfo(conn: DbConn, version: String) -> Result<Json<serde_json::Value>
|
||||
}
|
||||
|
||||
#[get("/about")]
|
||||
pub fn about(user: Option<User>, conn: DbConn, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
pub fn about(rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let conn = &*rockets.conn;
|
||||
Ok(render!(instance::about(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
Instance::get_local(&*conn)?,
|
||||
Instance::get_local(&*conn)?.main_admin(&*conn)?,
|
||||
User::count_local(&*conn)?,
|
||||
Post::count_local(&*conn)?,
|
||||
Instance::count(&*conn)? - 1
|
||||
&rockets.to_context(),
|
||||
Instance::get_local(conn)?,
|
||||
Instance::get_local(conn)?.main_admin(conn)?,
|
||||
User::count_local(conn)?,
|
||||
Post::count_local(conn)?,
|
||||
Instance::count(conn)? - 1
|
||||
)))
|
||||
}
|
||||
|
||||
|
||||
+37
-19
@@ -3,32 +3,32 @@ use multipart::server::{
|
||||
save::{SaveResult, SavedData},
|
||||
Multipart,
|
||||
};
|
||||
use plume_models::{db_conn::DbConn, medias::*, users::User, Error};
|
||||
use plume_models::{db_conn::DbConn, medias::*, users::User, Error, PlumeRocket};
|
||||
use rocket::{
|
||||
http::ContentType,
|
||||
response::{status, Redirect},
|
||||
response::{status, Flash, Redirect},
|
||||
Data,
|
||||
};
|
||||
use rocket_i18n::I18n;
|
||||
use routes::{errors::ErrorPage, Page};
|
||||
use std::fs;
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/medias?<page>")]
|
||||
pub fn list(user: User, conn: DbConn, intl: I18n, page: Option<Page>) -> Result<Ructe, ErrorPage> {
|
||||
pub fn list(user: User, page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let medias = Media::page_for_user(&*conn, &user, page.limits())?;
|
||||
let medias = Media::page_for_user(&*rockets.conn, &user, page.limits())?;
|
||||
Ok(render!(medias::index(
|
||||
&(&*conn, &intl.catalog, Some(user.clone())),
|
||||
&rockets.to_context(),
|
||||
medias,
|
||||
page.0,
|
||||
Page::total(Media::count_for_user(&*conn, &user)? as i32)
|
||||
Page::total(Media::count_for_user(&*rockets.conn, &user)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
#[get("/medias/new")]
|
||||
pub fn new(user: User, conn: DbConn, intl: I18n) -> Ructe {
|
||||
render!(medias::new(&(&*conn, &intl.catalog, Some(user))))
|
||||
pub fn new(_user: User, rockets: PlumeRocket) -> Ructe {
|
||||
render!(medias::new(&rockets.to_context()))
|
||||
}
|
||||
|
||||
#[post("/medias/new", data = "<data>")]
|
||||
@@ -122,32 +122,50 @@ fn read(data: &SavedData) -> Result<String, status::BadRequest<&'static str>> {
|
||||
}
|
||||
|
||||
#[get("/medias/<id>")]
|
||||
pub fn details(id: i32, user: User, conn: DbConn, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
let media = Media::get(&*conn, id)?;
|
||||
pub fn details(id: i32, user: User, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let media = Media::get(&*rockets.conn, id)?;
|
||||
if media.owner_id == user.id {
|
||||
Ok(render!(medias::details(
|
||||
&(&*conn, &intl.catalog, Some(user)),
|
||||
media
|
||||
)))
|
||||
Ok(render!(medias::details(&rockets.to_context(), media)))
|
||||
} else {
|
||||
Err(Error::Unauthorized.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/medias/<id>/delete")]
|
||||
pub fn delete(id: i32, user: User, conn: DbConn) -> Result<Redirect, ErrorPage> {
|
||||
pub fn delete(id: i32, user: User, conn: DbConn, intl: I18n) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
let media = Media::get(&*conn, id)?;
|
||||
if media.owner_id == user.id {
|
||||
media.delete(&*conn)?;
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(list: page = _)),
|
||||
i18n!(intl.catalog, "Your media have been deleted."),
|
||||
))
|
||||
} else {
|
||||
Ok(Flash::error(
|
||||
Redirect::to(uri!(list: page = _)),
|
||||
i18n!(intl.catalog, "You are not allowed to delete this media."),
|
||||
))
|
||||
}
|
||||
Ok(Redirect::to(uri!(list: page = _)))
|
||||
}
|
||||
|
||||
#[post("/medias/<id>/avatar")]
|
||||
pub fn set_avatar(id: i32, user: User, conn: DbConn) -> Result<Redirect, ErrorPage> {
|
||||
pub fn set_avatar(
|
||||
id: i32,
|
||||
user: User,
|
||||
conn: DbConn,
|
||||
intl: I18n,
|
||||
) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
let media = Media::get(&*conn, id)?;
|
||||
if media.owner_id == user.id {
|
||||
user.set_avatar(&*conn, media.id)?;
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(details: id = id)),
|
||||
i18n!(intl.catalog, "Your avatar have been updated."),
|
||||
))
|
||||
} else {
|
||||
Ok(Flash::error(
|
||||
Redirect::to(uri!(details: id = id)),
|
||||
i18n!(intl.catalog, "You are not allowed to use this media."),
|
||||
))
|
||||
}
|
||||
Ok(Redirect::to(uri!(details: id = id)))
|
||||
}
|
||||
|
||||
@@ -2,23 +2,22 @@ use rocket::response::{Flash, Redirect};
|
||||
use rocket_i18n::I18n;
|
||||
|
||||
use plume_common::utils;
|
||||
use plume_models::{db_conn::DbConn, notifications::Notification, users::User};
|
||||
use plume_models::{notifications::Notification, users::User, PlumeRocket};
|
||||
use routes::{errors::ErrorPage, Page};
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/notifications?<page>")]
|
||||
pub fn notifications(
|
||||
conn: DbConn,
|
||||
user: User,
|
||||
page: Option<Page>,
|
||||
intl: I18n,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
Ok(render!(notifications::index(
|
||||
&(&*conn, &intl.catalog, Some(user.clone())),
|
||||
Notification::page_for_user(&*conn, &user, page.limits())?,
|
||||
&rockets.to_context(),
|
||||
Notification::page_for_user(&*rockets.conn, &user, page.limits())?,
|
||||
page.0,
|
||||
Page::total(Notification::count_for_user(&*conn, &user)? as i32)
|
||||
Page::total(Notification::count_for_user(&*rockets.conn, &user)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
|
||||
+46
-38
@@ -27,7 +27,7 @@ use plume_models::{
|
||||
Error, PlumeRocket,
|
||||
};
|
||||
use routes::{comments::NewCommentForm, errors::ErrorPage, ContentLen, RemoteForm};
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/~/<blog>/<slug>?<responding_to>", rank = 4)]
|
||||
pub fn details(
|
||||
@@ -51,7 +51,7 @@ pub fn details(
|
||||
let previous = responding_to.and_then(|r| Comment::get(&*conn, r).ok());
|
||||
|
||||
Ok(render!(posts::details(
|
||||
&(&*conn, &rockets.intl.catalog, user.clone()),
|
||||
&rockets.to_context(),
|
||||
post.clone(),
|
||||
blog,
|
||||
&NewCommentForm {
|
||||
@@ -89,7 +89,7 @@ pub fn details(
|
||||
)))
|
||||
} else {
|
||||
Ok(render!(errors::not_authorized(
|
||||
&(&*conn, &rockets.intl.catalog, user.clone()),
|
||||
&rockets.to_context(),
|
||||
i18n!(rockets.intl.catalog, "This post isn't published yet.")
|
||||
)))
|
||||
}
|
||||
@@ -130,21 +130,20 @@ pub fn new_auth(blog: String, i18n: I18n) -> Flash<Redirect> {
|
||||
pub fn new(blog: String, cl: ContentLen, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let conn = &*rockets.conn;
|
||||
let b = Blog::find_by_fqn(&rockets, &blog)?;
|
||||
let user = rockets.user.unwrap();
|
||||
let intl = rockets.intl;
|
||||
let user = rockets.user.clone().unwrap();
|
||||
|
||||
if !user.is_author_in(&*conn, &b)? {
|
||||
// TODO actually return 403 error code
|
||||
return Ok(render!(errors::not_authorized(
|
||||
&(&*conn, &intl.catalog, Some(user)),
|
||||
i18n!(intl.catalog, "You are not an author of this blog.")
|
||||
&rockets.to_context(),
|
||||
i18n!(rockets.intl.catalog, "You are not an author of this blog.")
|
||||
)));
|
||||
}
|
||||
|
||||
let medias = Media::for_user(&*conn, user.id)?;
|
||||
Ok(render!(posts::new(
|
||||
&(&*conn, &intl.catalog, Some(user)),
|
||||
i18n!(intl.catalog, "New post"),
|
||||
&rockets.to_context(),
|
||||
i18n!(rockets.intl.catalog, "New post"),
|
||||
b,
|
||||
false,
|
||||
&NewPostForm {
|
||||
@@ -170,11 +169,11 @@ pub fn edit(
|
||||
let intl = &rockets.intl.catalog;
|
||||
let b = Blog::find_by_fqn(&rockets, &blog)?;
|
||||
let post = Post::find_by_slug(&*conn, &slug, b.id)?;
|
||||
let user = rockets.user.unwrap();
|
||||
let user = rockets.user.clone().unwrap();
|
||||
|
||||
if !user.is_author_in(&*conn, &b)? {
|
||||
return Ok(render!(errors::not_authorized(
|
||||
&(&*conn, intl, Some(user)),
|
||||
&rockets.to_context(),
|
||||
i18n!(intl, "You are not an author of this blog.")
|
||||
)));
|
||||
}
|
||||
@@ -188,7 +187,7 @@ pub fn edit(
|
||||
let medias = Media::for_user(&*conn, user.id)?;
|
||||
let title = post.title.clone();
|
||||
Ok(render!(posts::new(
|
||||
&(&*conn, intl, Some(user)),
|
||||
&rockets.to_context(),
|
||||
i18n!(intl, "Edit {0}"; &title),
|
||||
b,
|
||||
true,
|
||||
@@ -220,7 +219,7 @@ pub fn update(
|
||||
cl: ContentLen,
|
||||
form: LenientForm<NewPostForm>,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, Ructe> {
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
let conn = &*rockets.conn;
|
||||
let b = Blog::find_by_fqn(&rockets, &blog).expect("post::update: blog error");
|
||||
let mut post =
|
||||
@@ -256,8 +255,9 @@ pub fn update(
|
||||
.expect("posts::update: is author in error")
|
||||
{
|
||||
// actually it's not "Ok"…
|
||||
Ok(Redirect::to(
|
||||
uri!(super::blogs::details: name = blog, page = _),
|
||||
Ok(Flash::error(
|
||||
Redirect::to(uri!(super::blogs::details: name = blog, page = _)),
|
||||
i18n!(&intl, "You are not allowed to publish on this blog."),
|
||||
))
|
||||
} else {
|
||||
let (content, mentions, hashtags) = utils::md_to_html(
|
||||
@@ -343,14 +343,15 @@ pub fn update(
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Redirect::to(
|
||||
uri!(details: blog = blog, slug = new_slug, responding_to = _),
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(details: blog = blog, slug = new_slug, responding_to = _)),
|
||||
i18n!(intl, "Your article have been updated."),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
let medias = Media::for_user(&*conn, user.id).expect("posts:update: medias error");
|
||||
Err(render!(posts::new(
|
||||
&(&*conn, intl, Some(user)),
|
||||
&rockets.to_context(),
|
||||
i18n!(intl, "Edit {0}"; &form.title),
|
||||
b,
|
||||
true,
|
||||
@@ -393,7 +394,7 @@ pub fn create(
|
||||
form: LenientForm<NewPostForm>,
|
||||
cl: ContentLen,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, Result<Ructe, ErrorPage>> {
|
||||
) -> Result<Flash<Redirect>, Result<Ructe, ErrorPage>> {
|
||||
let conn = &*rockets.conn;
|
||||
let blog = Blog::find_by_fqn(&rockets, &blog_name).expect("post::create: blog error");;
|
||||
let slug = form.title.to_string().to_kebab_case();
|
||||
@@ -420,8 +421,12 @@ pub fn create(
|
||||
.expect("post::create: is author in error")
|
||||
{
|
||||
// actually it's not "Ok"…
|
||||
return Ok(Redirect::to(
|
||||
uri!(super::blogs::details: name = blog_name, page = _),
|
||||
return Ok(Flash::error(
|
||||
Redirect::to(uri!(super::blogs::details: name = blog_name, page = _)),
|
||||
i18n!(
|
||||
&rockets.intl.catalog,
|
||||
"You are not allowed to publish on this blog."
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -518,15 +523,15 @@ pub fn create(
|
||||
worker.execute(move || broadcast(&user, act, dest));
|
||||
}
|
||||
|
||||
Ok(Redirect::to(
|
||||
uri!(details: blog = blog_name, slug = slug, responding_to = _),
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(details: blog = blog_name, slug = slug, responding_to = _)),
|
||||
i18n!(&rockets.intl.catalog, "Your post have been saved."),
|
||||
))
|
||||
} else {
|
||||
let medias = Media::for_user(&*conn, user.id).expect("posts::create: medias error");
|
||||
let intl = rockets.intl;
|
||||
Err(Ok(render!(posts::new(
|
||||
&(&*conn, &intl.catalog, Some(user)),
|
||||
i18n!(intl.catalog, "New post"),
|
||||
&rockets.to_context(),
|
||||
i18n!(rockets.intl.catalog, "New post"),
|
||||
blog,
|
||||
false,
|
||||
&*form,
|
||||
@@ -544,7 +549,8 @@ pub fn delete(
|
||||
blog_name: String,
|
||||
slug: String,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, ErrorPage> {
|
||||
intl: I18n,
|
||||
) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
let user = rockets.user.clone().unwrap();
|
||||
let post = Blog::find_by_fqn(&rockets, &blog_name)
|
||||
.and_then(|blog| Post::find_by_slug(&*rockets.conn, &slug, blog.id));
|
||||
@@ -555,8 +561,11 @@ pub fn delete(
|
||||
.into_iter()
|
||||
.any(|a| a.id == user.id)
|
||||
{
|
||||
return Ok(Redirect::to(
|
||||
uri!(details: blog = blog_name.clone(), slug = slug.clone(), responding_to = _),
|
||||
return Ok(Flash::error(
|
||||
Redirect::to(
|
||||
uri!(details: blog = blog_name.clone(), slug = slug.clone(), responding_to = _),
|
||||
),
|
||||
i18n!(intl.catalog, "You are not allowed to delete this article."),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -579,13 +588,14 @@ pub fn delete(
|
||||
.expect("Failed to rotate keypair");
|
||||
});
|
||||
|
||||
Ok(Redirect::to(
|
||||
uri!(super::blogs::details: name = blog_name, page = _),
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(super::blogs::details: name = blog_name, page = _)),
|
||||
i18n!(intl.catalog, "Your article have been deleted."),
|
||||
))
|
||||
} else {
|
||||
Ok(Redirect::to(
|
||||
Ok(Flash::error(Redirect::to(
|
||||
uri!(super::blogs::details: name = blog_name, page = _),
|
||||
))
|
||||
), i18n!(intl.catalog, "It looks like the article you tried to delete doesn't exist. Maybe it is already gone?")))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,12 +604,11 @@ pub fn remote_interact(
|
||||
rockets: PlumeRocket,
|
||||
blog_name: String,
|
||||
slug: String,
|
||||
i18n: I18n,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
let target = Blog::find_by_fqn(&rockets, &blog_name)
|
||||
.and_then(|blog| Post::find_by_slug(&rockets.conn, &slug, blog.id))?;
|
||||
Ok(render!(posts::remote_interact(
|
||||
&(&rockets.conn, &i18n.catalog, None),
|
||||
&rockets.to_context(),
|
||||
target,
|
||||
super::session::LoginForm::default(),
|
||||
ValidationErrors::default(),
|
||||
@@ -614,7 +623,6 @@ pub fn remote_interact_post(
|
||||
blog_name: String,
|
||||
slug: String,
|
||||
remote: LenientForm<RemoteForm>,
|
||||
i18n: I18n,
|
||||
) -> Result<Result<Ructe, Redirect>, ErrorPage> {
|
||||
let target = Blog::find_by_fqn(&rockets, &blog_name)
|
||||
.and_then(|blog| Post::find_by_slug(&rockets.conn, &slug, blog.id))?;
|
||||
@@ -627,12 +635,12 @@ pub fn remote_interact_post(
|
||||
let mut errs = ValidationErrors::new();
|
||||
errs.add("remote", ValidationError {
|
||||
code: Cow::from("invalid_remote"),
|
||||
message: Some(Cow::from(i18n!(&i18n.catalog, "Couldn't obtain enough information about your account. Please make sure your username is correct."))),
|
||||
message: Some(Cow::from(i18n!(rockets.intl.catalog, "Couldn't obtain enough information about your account. Please make sure your username is correct."))),
|
||||
params: HashMap::new(),
|
||||
});
|
||||
//could not get your remote url?
|
||||
Ok(Ok(render!(posts::remote_interact(
|
||||
&(&rockets.conn, &i18n.catalog, None),
|
||||
&rockets.to_context(),
|
||||
target,
|
||||
super::session::LoginForm::default(),
|
||||
ValidationErrors::default(),
|
||||
|
||||
+9
-14
@@ -1,12 +1,10 @@
|
||||
use chrono::offset::Utc;
|
||||
use rocket::request::Form;
|
||||
use rocket_i18n::I18n;
|
||||
|
||||
use plume_models::{db_conn::DbConn, search::Query, users::User};
|
||||
use plume_models::{search::Query, PlumeRocket};
|
||||
use routes::Page;
|
||||
use std::str::FromStr;
|
||||
use template_utils::Ructe;
|
||||
use Searcher;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[derive(Default, FromForm)]
|
||||
pub struct SearchQuery {
|
||||
@@ -52,13 +50,8 @@ macro_rules! param_to_query {
|
||||
}
|
||||
|
||||
#[get("/search?<query..>")]
|
||||
pub fn search(
|
||||
query: Option<Form<SearchQuery>>,
|
||||
conn: DbConn,
|
||||
searcher: Searcher,
|
||||
user: Option<User>,
|
||||
intl: I18n,
|
||||
) -> Ructe {
|
||||
pub fn search(query: Option<Form<SearchQuery>>, rockets: PlumeRocket) -> Ructe {
|
||||
let conn = &*rockets.conn;
|
||||
let query = query.map(Form::into_inner).unwrap_or_default();
|
||||
let page = query.page.unwrap_or_default();
|
||||
let mut parsed_query =
|
||||
@@ -73,14 +66,16 @@ pub fn search(
|
||||
|
||||
if str_query.is_empty() {
|
||||
render!(search::index(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
&rockets.to_context(),
|
||||
&format!("{}", Utc::today().format("%Y-%m-d"))
|
||||
))
|
||||
} else {
|
||||
let res = searcher.search_document(&conn, parsed_query, page.limits());
|
||||
let res = rockets
|
||||
.searcher
|
||||
.search_document(&conn, parsed_query, page.limits());
|
||||
let next_page = if res.is_empty() { 0 } else { page.0 + 1 };
|
||||
render!(search::result(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
&rockets.to_context(),
|
||||
&str_query,
|
||||
res,
|
||||
page.0,
|
||||
|
||||
+61
-54
@@ -2,8 +2,8 @@ use lettre::Transport;
|
||||
use rocket::http::ext::IntoOwned;
|
||||
use rocket::{
|
||||
http::{uri::Uri, Cookie, Cookies, SameSite},
|
||||
request::{FlashMessage, Form, LenientForm},
|
||||
response::Redirect,
|
||||
request::{Form, LenientForm},
|
||||
response::{Flash, Redirect},
|
||||
State,
|
||||
};
|
||||
use rocket_i18n::I18n;
|
||||
@@ -12,21 +12,20 @@ use std::{
|
||||
sync::{Arc, Mutex},
|
||||
time::Instant,
|
||||
};
|
||||
use template_utils::Ructe;
|
||||
use validator::{Validate, ValidationError, ValidationErrors};
|
||||
|
||||
use mail::{build_mail, Mailer};
|
||||
use plume_models::{
|
||||
db_conn::DbConn,
|
||||
users::{User, AUTH_COOKIE},
|
||||
Error, PlumeRocket, CONFIG,
|
||||
};
|
||||
use routes::errors::ErrorPage;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/login?<m>")]
|
||||
pub fn new(user: Option<User>, conn: DbConn, m: Option<String>, intl: I18n) -> Ructe {
|
||||
pub fn new(m: Option<String>, rockets: PlumeRocket) -> Ructe {
|
||||
render!(session::login(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
&rockets.to_context(),
|
||||
m,
|
||||
&LoginForm::default(),
|
||||
ValidationErrors::default()
|
||||
@@ -44,10 +43,9 @@ pub struct LoginForm {
|
||||
#[post("/login", data = "<form>")]
|
||||
pub fn create(
|
||||
form: LenientForm<LoginForm>,
|
||||
flash: Option<FlashMessage>,
|
||||
mut cookies: Cookies,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, Ructe> {
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
let conn = &*rockets.conn;
|
||||
let user = User::find_by_email(&*conn, &form.email_or_name)
|
||||
.or_else(|_| User::find_by_fqn(&rockets, &form.email_or_name));
|
||||
@@ -84,31 +82,38 @@ pub fn create(
|
||||
.same_site(SameSite::Lax)
|
||||
.finish(),
|
||||
);
|
||||
let destination = flash
|
||||
.and_then(|f| {
|
||||
if f.name() == "callback" {
|
||||
Some(f.msg().to_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
let destination = rockets
|
||||
.flash_msg
|
||||
.clone()
|
||||
.and_then(
|
||||
|(name, msg)| {
|
||||
if name == "callback" {
|
||||
Some(msg)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap_or_else(|| "/".to_owned());
|
||||
|
||||
let uri = Uri::parse(&destination)
|
||||
.map(IntoOwned::into_owned)
|
||||
.map_err(|_| {
|
||||
render!(session::login(
|
||||
&(&*conn, &rockets.intl.catalog, None),
|
||||
&(conn, &rockets.intl.catalog, None, None),
|
||||
None,
|
||||
&*form,
|
||||
errors
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(Redirect::to(uri))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri),
|
||||
i18n!(&rockets.intl.catalog, "You are now connected."),
|
||||
))
|
||||
} else {
|
||||
Err(render!(session::login(
|
||||
&(&*conn, &rockets.intl.catalog, None),
|
||||
&rockets.to_context(),
|
||||
None,
|
||||
&*form,
|
||||
errors
|
||||
@@ -117,11 +122,14 @@ pub fn create(
|
||||
}
|
||||
|
||||
#[get("/logout")]
|
||||
pub fn delete(mut cookies: Cookies) -> Redirect {
|
||||
pub fn delete(mut cookies: Cookies, intl: I18n) -> Flash<Redirect> {
|
||||
if let Some(cookie) = cookies.get_private(AUTH_COOKIE) {
|
||||
cookies.remove_private(cookie);
|
||||
}
|
||||
Redirect::to("/")
|
||||
Flash::success(
|
||||
Redirect::to("/"),
|
||||
i18n!(intl.catalog, "You are now logged off."),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -138,9 +146,9 @@ impl PartialEq for ResetRequest {
|
||||
}
|
||||
|
||||
#[get("/password-reset")]
|
||||
pub fn password_reset_request_form(conn: DbConn, intl: I18n) -> Ructe {
|
||||
pub fn password_reset_request_form(rockets: PlumeRocket) -> Ructe {
|
||||
render!(session::password_reset_request(
|
||||
&(&*conn, &intl.catalog, None),
|
||||
&rockets.to_context(),
|
||||
&ResetForm::default(),
|
||||
ValidationErrors::default()
|
||||
))
|
||||
@@ -154,17 +162,16 @@ pub struct ResetForm {
|
||||
|
||||
#[post("/password-reset", data = "<form>")]
|
||||
pub fn password_reset_request(
|
||||
conn: DbConn,
|
||||
intl: I18n,
|
||||
mail: State<Arc<Mutex<Mailer>>>,
|
||||
form: Form<ResetForm>,
|
||||
requests: State<Arc<Mutex<Vec<ResetRequest>>>>,
|
||||
rockets: PlumeRocket,
|
||||
) -> Ructe {
|
||||
let mut requests = requests.lock().unwrap();
|
||||
// Remove outdated requests (more than 1 day old) to avoid the list to grow too much
|
||||
requests.retain(|r| r.creation_date.elapsed().as_secs() < 24 * 60 * 60);
|
||||
|
||||
if User::find_by_email(&*conn, &form.email).is_ok()
|
||||
if User::find_by_email(&*rockets.conn, &form.email).is_ok()
|
||||
&& !requests.iter().any(|x| x.mail == form.email.clone())
|
||||
{
|
||||
let id = plume_common::utils::random_hex();
|
||||
@@ -178,8 +185,8 @@ pub fn password_reset_request(
|
||||
let link = format!("https://{}/password-reset/{}", CONFIG.base_url, id);
|
||||
if let Some(message) = build_mail(
|
||||
form.email.clone(),
|
||||
i18n!(intl.catalog, "Password reset"),
|
||||
i18n!(intl.catalog, "Here is the link to reset your password: {0}"; link),
|
||||
i18n!(rockets.intl.catalog, "Password reset"),
|
||||
i18n!(rockets.intl.catalog, "Here is the link to reset your password: {0}"; link),
|
||||
) {
|
||||
if let Some(ref mut mail) = *mail.lock().unwrap() {
|
||||
mail.send(message.into())
|
||||
@@ -188,19 +195,14 @@ pub fn password_reset_request(
|
||||
}
|
||||
}
|
||||
}
|
||||
render!(session::password_reset_request_ok(&(
|
||||
&*conn,
|
||||
&intl.catalog,
|
||||
None
|
||||
)))
|
||||
render!(session::password_reset_request_ok(&rockets.to_context()))
|
||||
}
|
||||
|
||||
#[get("/password-reset/<token>")]
|
||||
pub fn password_reset_form(
|
||||
conn: DbConn,
|
||||
intl: I18n,
|
||||
token: String,
|
||||
requests: State<Arc<Mutex<Vec<ResetRequest>>>>,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
requests
|
||||
.lock()
|
||||
@@ -209,7 +211,7 @@ pub fn password_reset_form(
|
||||
.find(|x| x.id == token.clone())
|
||||
.ok_or(Error::NotFound)?;
|
||||
Ok(render!(session::password_reset(
|
||||
&(&*conn, &intl.catalog, None),
|
||||
&rockets.to_context(),
|
||||
&NewPasswordForm::default(),
|
||||
ValidationErrors::default()
|
||||
)))
|
||||
@@ -236,12 +238,11 @@ fn passwords_match(form: &NewPasswordForm) -> Result<(), ValidationError> {
|
||||
|
||||
#[post("/password-reset/<token>", data = "<form>")]
|
||||
pub fn password_reset(
|
||||
conn: DbConn,
|
||||
intl: I18n,
|
||||
token: String,
|
||||
requests: State<Arc<Mutex<Vec<ResetRequest>>>>,
|
||||
form: Form<NewPasswordForm>,
|
||||
) -> Result<Redirect, Ructe> {
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
form.validate()
|
||||
.and_then(|_| {
|
||||
let mut requests = requests.lock().unwrap();
|
||||
@@ -253,24 +254,30 @@ pub fn password_reset(
|
||||
if req.creation_date.elapsed().as_secs() < 60 * 60 * 2 {
|
||||
// Reset link is only valid for 2 hours
|
||||
requests.retain(|r| *r != req);
|
||||
let user = User::find_by_email(&*conn, &req.mail).map_err(to_validation)?;
|
||||
user.reset_password(&*conn, &form.password).ok();
|
||||
Ok(Redirect::to(uri!(
|
||||
new: m = i18n!(intl.catalog, "Your password was successfully reset.")
|
||||
)))
|
||||
let user = User::find_by_email(&*rockets.conn, &req.mail).map_err(to_validation)?;
|
||||
user.reset_password(&*rockets.conn, &form.password).ok();
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(
|
||||
new: m = _
|
||||
)),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"Your password was successfully reset."
|
||||
),
|
||||
))
|
||||
} else {
|
||||
Ok(Redirect::to(uri!(
|
||||
new: m = i18n!(intl.catalog, "Sorry, but the link expired. Try again")
|
||||
)))
|
||||
Ok(Flash::error(
|
||||
Redirect::to(uri!(
|
||||
new: m = _
|
||||
)),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"Sorry, but the link expired. Try again"
|
||||
),
|
||||
))
|
||||
}
|
||||
})
|
||||
.map_err(|err| {
|
||||
render!(session::password_reset(
|
||||
&(&*conn, &intl.catalog, None),
|
||||
&form,
|
||||
err
|
||||
))
|
||||
})
|
||||
.map_err(|err| render!(session::password_reset(&rockets.to_context(), &form, err)))
|
||||
}
|
||||
|
||||
fn to_validation<T>(_: T) -> ValidationErrors {
|
||||
|
||||
+6
-14
@@ -1,24 +1,16 @@
|
||||
use rocket_i18n::I18n;
|
||||
|
||||
use plume_models::{db_conn::DbConn, posts::Post, users::User};
|
||||
use plume_models::{posts::Post, PlumeRocket};
|
||||
use routes::{errors::ErrorPage, Page};
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/tag/<name>?<page>")]
|
||||
pub fn tag(
|
||||
user: Option<User>,
|
||||
conn: DbConn,
|
||||
name: String,
|
||||
page: Option<Page>,
|
||||
intl: I18n,
|
||||
) -> Result<Ructe, ErrorPage> {
|
||||
pub fn tag(name: String, page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let page = page.unwrap_or_default();
|
||||
let posts = Post::list_by_tag(&*conn, name.clone(), page.limits())?;
|
||||
let posts = Post::list_by_tag(&*rockets.conn, name.clone(), page.limits())?;
|
||||
Ok(render!(tags::index(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
&rockets.to_context(),
|
||||
name.clone(),
|
||||
posts,
|
||||
page.0,
|
||||
Page::total(Post::count_for_tag(&*conn, name)? as i32)
|
||||
Page::total(Post::count_for_tag(&*rockets.conn, name)? as i32)
|
||||
)))
|
||||
}
|
||||
|
||||
+82
-40
@@ -26,7 +26,7 @@ use plume_models::{
|
||||
Error, PlumeRocket,
|
||||
};
|
||||
use routes::{errors::ErrorPage, Page, RemoteForm};
|
||||
use template_utils::Ructe;
|
||||
use template_utils::{IntoContext, Ructe};
|
||||
|
||||
#[get("/me")]
|
||||
pub fn me(user: Option<User>) -> Result<Redirect, Flash<Redirect>> {
|
||||
@@ -48,7 +48,7 @@ pub fn details(
|
||||
let user = User::find_by_fqn(&rockets, &name)?;
|
||||
let recents = Post::get_recents_for_author(&*conn, &user, 6)?;
|
||||
let reshares = Reshare::get_recents_for_author(&*conn, &user, 6)?;
|
||||
let worker = rockets.worker;
|
||||
let worker = &rockets.worker;
|
||||
|
||||
if !user.get_instance(&*conn)?.local {
|
||||
// Fetch new articles
|
||||
@@ -101,12 +101,12 @@ pub fn details(
|
||||
}
|
||||
}
|
||||
|
||||
let account = rockets.user;
|
||||
let intl = rockets.intl;
|
||||
Ok(render!(users::details(
|
||||
&(&*conn, &intl.catalog, account.clone()),
|
||||
&rockets.to_context(),
|
||||
user.clone(),
|
||||
account
|
||||
rockets
|
||||
.user
|
||||
.clone()
|
||||
.and_then(|x| x.is_following(&*conn, user.id).ok())
|
||||
.unwrap_or(false),
|
||||
user.instance_id != Instance::get_local(&*conn)?.id,
|
||||
@@ -120,12 +120,12 @@ pub fn details(
|
||||
}
|
||||
|
||||
#[get("/dashboard")]
|
||||
pub fn dashboard(user: User, conn: DbConn, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
let blogs = Blog::find_for_author(&*conn, &user)?;
|
||||
pub fn dashboard(user: User, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let blogs = Blog::find_for_author(&*rockets.conn, &user)?;
|
||||
Ok(render!(users::dashboard(
|
||||
&(&*conn, &intl.catalog, Some(user.clone())),
|
||||
&rockets.to_context(),
|
||||
blogs,
|
||||
Post::drafts_by_author(&*conn, &user)?
|
||||
Post::drafts_by_author(&*rockets.conn, &user)?
|
||||
)))
|
||||
}
|
||||
|
||||
@@ -141,19 +141,25 @@ pub fn dashboard_auth(i18n: I18n) -> Flash<Redirect> {
|
||||
}
|
||||
|
||||
#[post("/@/<name>/follow")]
|
||||
pub fn follow(name: String, user: User, rockets: PlumeRocket) -> Result<Redirect, ErrorPage> {
|
||||
pub fn follow(
|
||||
name: String,
|
||||
user: User,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
let conn = &*rockets.conn;
|
||||
let target = User::find_by_fqn(&rockets, &name)?;
|
||||
if let Ok(follow) = follows::Follow::find(&*conn, user.id, target.id) {
|
||||
let message = if let Ok(follow) = follows::Follow::find(&*conn, user.id, target.id) {
|
||||
let delete_act = follow.build_undo(&*conn)?;
|
||||
local_inbox(
|
||||
&rockets,
|
||||
serde_json::to_value(&delete_act).map_err(Error::from)?,
|
||||
)?;
|
||||
|
||||
let msg = i18n!(rockets.intl.catalog, "You are no longer following {}."; target.name());
|
||||
rockets
|
||||
.worker
|
||||
.execute(move || broadcast(&user, delete_act, vec![target]));
|
||||
msg
|
||||
} else {
|
||||
let f = follows::Follow::insert(
|
||||
&*conn,
|
||||
@@ -166,11 +172,16 @@ pub fn follow(name: String, user: User, rockets: PlumeRocket) -> Result<Redirect
|
||||
f.notify(&*conn)?;
|
||||
|
||||
let act = f.to_activity(&*conn)?;
|
||||
let msg = i18n!(rockets.intl.catalog, "You are now following {}."; target.name());
|
||||
rockets
|
||||
.worker
|
||||
.execute(move || broadcast(&user, act, vec![target]));
|
||||
}
|
||||
Ok(Redirect::to(uri!(details: name = name)))
|
||||
msg
|
||||
};
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(details: name = name)),
|
||||
message,
|
||||
))
|
||||
}
|
||||
|
||||
#[post("/@/<name>/follow", data = "<remote_form>", rank = 2)]
|
||||
@@ -209,7 +220,7 @@ pub fn follow_not_connected(
|
||||
);
|
||||
Ok(Ok(Flash::new(
|
||||
render!(users::follow_remote(
|
||||
&(&rockets.conn, &i18n.catalog, None),
|
||||
&rockets.to_context(),
|
||||
target,
|
||||
super::session::LoginForm::default(),
|
||||
ValidationErrors::default(),
|
||||
@@ -223,7 +234,7 @@ pub fn follow_not_connected(
|
||||
} else {
|
||||
Ok(Ok(Flash::new(
|
||||
render!(users::follow_remote(
|
||||
&(&rockets.conn, &i18n.catalog, None),
|
||||
&rockets.to_context(),
|
||||
target,
|
||||
super::session::LoginForm::default(),
|
||||
ValidationErrors::default(),
|
||||
@@ -260,10 +271,11 @@ pub fn followers(
|
||||
let followers_count = user.count_followers(&*conn)?;
|
||||
|
||||
Ok(render!(users::followers(
|
||||
&(&*conn, &rockets.intl.catalog, rockets.user.clone()),
|
||||
&rockets.to_context(),
|
||||
user.clone(),
|
||||
rockets
|
||||
.user
|
||||
.clone()
|
||||
.and_then(|x| x.is_following(&*conn, user.id).ok())
|
||||
.unwrap_or(false),
|
||||
user.instance_id != Instance::get_local(&*conn)?.id,
|
||||
@@ -283,18 +295,19 @@ pub fn followed(
|
||||
let conn = &*rockets.conn;
|
||||
let page = page.unwrap_or_default();
|
||||
let user = User::find_by_fqn(&rockets, &name)?;
|
||||
let followed_count = user.count_followed(&*conn)?;
|
||||
let followed_count = user.count_followed(conn)?;
|
||||
|
||||
Ok(render!(users::followed(
|
||||
&(&*conn, &rockets.intl.catalog, rockets.user.clone()),
|
||||
&rockets.to_context(),
|
||||
user.clone(),
|
||||
rockets
|
||||
.user
|
||||
.and_then(|x| x.is_following(&*conn, user.id).ok())
|
||||
.clone()
|
||||
.and_then(|x| x.is_following(conn, user.id).ok())
|
||||
.unwrap_or(false),
|
||||
user.instance_id != Instance::get_local(&*conn)?.id,
|
||||
user.get_instance(&*conn)?.public_domain,
|
||||
user.get_followed_page(&*conn, page.limits())?,
|
||||
user.instance_id != Instance::get_local(conn)?.id,
|
||||
user.get_instance(conn)?.public_domain,
|
||||
user.get_followed_page(conn, page.limits())?,
|
||||
page.0,
|
||||
Page::total(followed_count as i32)
|
||||
)))
|
||||
@@ -311,20 +324,20 @@ pub fn activity_details(
|
||||
}
|
||||
|
||||
#[get("/users/new")]
|
||||
pub fn new(user: Option<User>, conn: DbConn, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
pub fn new(rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
Ok(render!(users::new(
|
||||
&(&*conn, &intl.catalog, user),
|
||||
Instance::get_local(&*conn)?.open_registrations,
|
||||
&rockets.to_context(),
|
||||
Instance::get_local(&*rockets.conn)?.open_registrations,
|
||||
&NewUserForm::default(),
|
||||
ValidationErrors::default()
|
||||
)))
|
||||
}
|
||||
|
||||
#[get("/@/<name>/edit")]
|
||||
pub fn edit(name: String, user: User, conn: DbConn, intl: I18n) -> Result<Ructe, ErrorPage> {
|
||||
pub fn edit(name: String, user: User, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
if user.username == name && !name.contains('@') {
|
||||
Ok(render!(users::edit(
|
||||
&(&*conn, &intl.catalog, Some(user.clone())),
|
||||
&rockets.to_context(),
|
||||
UpdateUserForm {
|
||||
display_name: user.display_name.clone(),
|
||||
email: user.email.clone().unwrap_or_default(),
|
||||
@@ -361,7 +374,8 @@ pub fn update(
|
||||
conn: DbConn,
|
||||
user: User,
|
||||
form: LenientForm<UpdateUserForm>,
|
||||
) -> Result<Redirect, ErrorPage> {
|
||||
intl: I18n,
|
||||
) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
user.update(
|
||||
&*conn,
|
||||
if !form.display_name.is_empty() {
|
||||
@@ -380,7 +394,10 @@ pub fn update(
|
||||
user.summary.to_string()
|
||||
},
|
||||
)?;
|
||||
Ok(Redirect::to(uri!(me)))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(me)),
|
||||
i18n!(intl.catalog, "Your profile have been updated."),
|
||||
))
|
||||
}
|
||||
|
||||
#[post("/@/<name>/delete")]
|
||||
@@ -389,7 +406,7 @@ pub fn delete(
|
||||
user: User,
|
||||
mut cookies: Cookies,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Redirect, ErrorPage> {
|
||||
) -> Result<Flash<Redirect>, ErrorPage> {
|
||||
let account = User::find_by_fqn(&rockets, &name)?;
|
||||
if user.id == account.id {
|
||||
account.delete(&*rockets.conn, &rockets.searcher)?;
|
||||
@@ -404,9 +421,18 @@ pub fn delete(
|
||||
cookies.remove_private(cookie);
|
||||
}
|
||||
|
||||
Ok(Redirect::to(uri!(super::instance::index)))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(super::instance::index)),
|
||||
i18n!(rockets.intl.catalog, "Your account have been deleted."),
|
||||
))
|
||||
} else {
|
||||
Ok(Redirect::to(uri!(edit: name = name)))
|
||||
Ok(Flash::error(
|
||||
Redirect::to(uri!(edit: name = name)),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"You can't delete someone else's account."
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,12 +489,22 @@ fn to_validation(_: Error) -> ValidationErrors {
|
||||
}
|
||||
|
||||
#[post("/users/new", data = "<form>")]
|
||||
pub fn create(conn: DbConn, form: LenientForm<NewUserForm>, intl: I18n) -> Result<Redirect, Ructe> {
|
||||
if !Instance::get_local(&*conn)
|
||||
pub fn create(
|
||||
form: LenientForm<NewUserForm>,
|
||||
rockets: PlumeRocket,
|
||||
) -> Result<Flash<Redirect>, Ructe> {
|
||||
let conn = &*rockets.conn;
|
||||
if !Instance::get_local(conn)
|
||||
.map(|i| i.open_registrations)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
return Ok(Redirect::to(uri!(new))); // Actually, it is an error
|
||||
return Ok(Flash::error(
|
||||
Redirect::to(uri!(new)),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"Registrations are closed on this instance."
|
||||
),
|
||||
)); // Actually, it is an error
|
||||
}
|
||||
|
||||
let mut form = form.into_inner();
|
||||
@@ -477,7 +513,7 @@ pub fn create(conn: DbConn, form: LenientForm<NewUserForm>, intl: I18n) -> Resul
|
||||
form.validate()
|
||||
.and_then(|_| {
|
||||
NewUser::new_local(
|
||||
&*conn,
|
||||
conn,
|
||||
form.username.to_string(),
|
||||
form.username.to_string(),
|
||||
false,
|
||||
@@ -486,12 +522,18 @@ pub fn create(conn: DbConn, form: LenientForm<NewUserForm>, intl: I18n) -> Resul
|
||||
User::hash_pass(&form.password).map_err(to_validation)?,
|
||||
)
|
||||
.map_err(to_validation)?;
|
||||
Ok(Redirect::to(uri!(super::session::new: m = _)))
|
||||
Ok(Flash::success(
|
||||
Redirect::to(uri!(super::session::new: m = _)),
|
||||
i18n!(
|
||||
rockets.intl.catalog,
|
||||
"Your account have been created. You just need to login before you can use it."
|
||||
),
|
||||
))
|
||||
})
|
||||
.map_err(|err| {
|
||||
render!(users::new(
|
||||
&(&*conn, &intl.catalog, None),
|
||||
Instance::get_local(&*conn)
|
||||
&rockets.to_context(),
|
||||
Instance::get_local(conn)
|
||||
.map(|i| i.open_registrations)
|
||||
.unwrap_or(true),
|
||||
&form,
|
||||
|
||||
+36
-2
@@ -1,4 +1,4 @@
|
||||
use plume_models::{notifications::*, users::User, Connection};
|
||||
use plume_models::{notifications::*, users::User, Connection, PlumeRocket};
|
||||
|
||||
use rocket::http::hyper::header::{ETag, EntityTag};
|
||||
use rocket::http::{Method, Status};
|
||||
@@ -13,7 +13,41 @@ pub use askama_escape::escape;
|
||||
|
||||
pub static CACHE_NAME: &str = env!("CACHE_ID");
|
||||
|
||||
pub type BaseContext<'a> = &'a (&'a Connection, &'a Catalog, Option<User>);
|
||||
pub type BaseContext<'a> = &'a (
|
||||
&'a Connection,
|
||||
&'a Catalog,
|
||||
Option<User>,
|
||||
Option<(String, String)>,
|
||||
);
|
||||
|
||||
pub trait IntoContext {
|
||||
fn to_context(
|
||||
&self,
|
||||
) -> (
|
||||
&Connection,
|
||||
&Catalog,
|
||||
Option<User>,
|
||||
Option<(String, String)>,
|
||||
);
|
||||
}
|
||||
|
||||
impl IntoContext for PlumeRocket {
|
||||
fn to_context(
|
||||
&self,
|
||||
) -> (
|
||||
&Connection,
|
||||
&Catalog,
|
||||
Option<User>,
|
||||
Option<(String, String)>,
|
||||
) {
|
||||
(
|
||||
&*self.conn,
|
||||
&self.intl.catalog,
|
||||
self.user.clone(),
|
||||
self.flash_msg.clone(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Ructe(pub Vec<u8>);
|
||||
|
||||
Reference in New Issue
Block a user