may_fail! macro

Returns an error template if an Option is None, else runs the given block
This commit is contained in:
Bat 2018-06-18 18:28:28 +01:00
parent 7e3cdec0b6
commit 51571d6320
5 changed files with 90 additions and 57 deletions

View File

@ -19,14 +19,16 @@ use utils;
#[get("/~/<name>", rank = 2)] #[get("/~/<name>", rank = 2)]
fn details(name: String, conn: DbConn, user: Option<User>) -> Template { fn details(name: String, conn: DbConn, user: Option<User>) -> Template {
let blog = Blog::find_by_fqn(&*conn, name).unwrap(); may_fail!(Blog::find_by_fqn(&*conn, name), "Requested blog couldn't be found", |blog| {
let recents = Post::get_recents_for_blog(&*conn, &blog, 5); let recents = Post::get_recents_for_blog(&*conn, &blog, 5);
Template::render("blogs/details", json!({
"blog": blog, Template::render("blogs/details", json!({
"account": user, "blog": blog,
"is_author": user.map(|x| x.is_author_in(&*conn, blog)), "account": user,
"recents": recents.into_iter().map(|p| p.to_json(&*conn)).collect::<Vec<serde_json::Value>>() "is_author": user.map(|x| x.is_author_in(&*conn, blog)),
})) "recents": recents.into_iter().map(|p| p.to_json(&*conn)).collect::<Vec<serde_json::Value>>()
}))
})
} }
#[get("/~/<name>", format = "application/activity+json", rank = 1)] #[get("/~/<name>", format = "application/activity+json", rank = 1)]

View File

@ -17,11 +17,12 @@ use safe_string::SafeString;
#[get("/~/<_blog>/<slug>/comment")] #[get("/~/<_blog>/<slug>/comment")]
fn new(_blog: String, slug: String, user: User, conn: DbConn) -> Template { fn new(_blog: String, slug: String, user: User, conn: DbConn) -> Template {
let post = Post::find_by_slug(&*conn, slug).unwrap(); may_fail!(Post::find_by_slug(&*conn, slug), "Couldn't find this post", |post| {
Template::render("comments/new", json!({ Template::render("comments/new", json!({
"post": post, "post": post,
"account": user "account": user
})) }))
})
} }
#[get("/~/<blog>/<slug>/comment", rank=2)] #[get("/~/<blog>/<slug>/comment", rank=2)]

View File

@ -1,6 +1,32 @@
use rocket::response::NamedFile; use rocket::response::NamedFile;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
macro_rules! may_fail {
($expr:expr, $template:expr, $msg:expr, | $res:ident | $block:block) => {
{
let res = $expr;
if res.is_some() {
let $res = res.unwrap();
$block
} else {
Template::render(concat!("errors/", stringify!($template)), json!({
"error_message": $msg
}))
}
}
};
($expr:expr, $msg:expr, | $res:ident | $block:block) => {
may_fail!($expr, "404", $msg, |$res| {
$block
})
};
($expr:expr, | $res:ident | $block:block) => {
may_fail!($expr, "", |$res| {
$block
})
};
}
pub mod blogs; pub mod blogs;
pub mod comments; pub mod comments;
pub mod errors; pub mod errors;

View File

@ -19,22 +19,24 @@ use safe_string::SafeString;
#[get("/~/<blog>/<slug>", rank = 4)] #[get("/~/<blog>/<slug>", rank = 4)]
fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Template { fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Template {
let blog = Blog::find_by_fqn(&*conn, blog).unwrap(); may_fail!(Blog::find_by_fqn(&*conn, blog), "Couldn't find this blog", |blog| {
let post = Post::find_by_slug(&*conn, slug).unwrap(); may_fail!(Post::find_by_slug(&*conn, slug), "Couldn't find this post", |post| {
let comments = Comment::find_by_post(&*conn, post.id); let comments = Comment::find_by_post(&*conn, post.id);
Template::render("posts/details", json!({ Template::render("posts/details", json!({
"author": post.get_authors(&*conn)[0].to_json(&*conn), "author": post.get_authors(&*conn)[0].to_json(&*conn),
"post": post, "post": post,
"blog": blog, "blog": blog,
"comments": comments.into_iter().map(|c| c.to_json(&*conn)).collect::<Vec<serde_json::Value>>(), "comments": comments.into_iter().map(|c| c.to_json(&*conn)).collect::<Vec<serde_json::Value>>(),
"n_likes": post.get_likes(&*conn).len(), "n_likes": post.get_likes(&*conn).len(),
"has_liked": user.clone().map(|u| u.has_liked(&*conn, &post)).unwrap_or(false), "has_liked": user.clone().map(|u| u.has_liked(&*conn, &post)).unwrap_or(false),
"n_reshares": post.get_reshares(&*conn).len(), "n_reshares": post.get_reshares(&*conn).len(),
"has_reshared": user.clone().map(|u| u.has_reshared(&*conn, &post)).unwrap_or(false), "has_reshared": user.clone().map(|u| u.has_reshared(&*conn, &post)).unwrap_or(false),
"account": user, "account": user,
"date": &post.creation_date.timestamp() "date": &post.creation_date.timestamp()
})) }))
})
})
} }
#[get("/~/<_blog>/<slug>", rank = 3, format = "application/activity+json")] #[get("/~/<_blog>/<slug>", rank = 3, format = "application/activity+json")]

View File

@ -25,7 +25,7 @@ use models::{
use utils; use utils;
#[get("/me")] #[get("/me")]
fn me(user: Option<User>) -> Result<Redirect,Flash<Redirect>> { fn me(user: Option<User>) -> Result<Redirect, Flash<Redirect>> {
match user { match user {
Some(user) => Ok(Redirect::to(format!("/@/{}/", user.username))), Some(user) => Ok(Redirect::to(format!("/@/{}/", user.username))),
None => Err(utils::requires_login("", "/me")) None => Err(utils::requires_login("", "/me"))
@ -34,23 +34,24 @@ fn me(user: Option<User>) -> Result<Redirect,Flash<Redirect>> {
#[get("/@/<name>", rank = 2)] #[get("/@/<name>", rank = 2)]
fn details(name: String, conn: DbConn, account: Option<User>) -> Template { fn details(name: String, conn: DbConn, account: Option<User>) -> Template {
let user = User::find_by_fqn(&*conn, name).unwrap(); may_fail!(User::find_by_fqn(&*conn, name), "Couldn't find requested user", |user| {
let recents = Post::get_recents_for_author(&*conn, &user, 6); let recents = Post::get_recents_for_author(&*conn, &user, 6);
let reshares = Reshare::get_recents_for_author(&*conn, &user, 6); let reshares = Reshare::get_recents_for_author(&*conn, &user, 6);
let user_id = user.id.clone(); let user_id = user.id.clone();
let n_followers = user.get_followers(&*conn).len(); let n_followers = user.get_followers(&*conn).len();
Template::render("users/details", json!({ Template::render("users/details", json!({
"user": serde_json::to_value(user.clone()).unwrap(), "user": serde_json::to_value(user.clone()).unwrap(),
"instance_url": user.get_instance(&*conn).public_domain, "instance_url": user.get_instance(&*conn).public_domain,
"is_remote": user.instance_id != Instance::local_id(&*conn), "is_remote": user.instance_id != Instance::local_id(&*conn),
"follows": account.clone().map(|x| x.is_following(&*conn, user.id)).unwrap_or(false), "follows": account.clone().map(|x| x.is_following(&*conn, user.id)).unwrap_or(false),
"account": account, "account": account,
"recents": recents.into_iter().map(|p| p.to_json(&*conn)).collect::<Vec<serde_json::Value>>(), "recents": recents.into_iter().map(|p| p.to_json(&*conn)).collect::<Vec<serde_json::Value>>(),
"reshares": reshares.into_iter().map(|r| r.get_post(&*conn).unwrap().to_json(&*conn)).collect::<Vec<serde_json::Value>>(), "reshares": reshares.into_iter().map(|r| r.get_post(&*conn).unwrap().to_json(&*conn)).collect::<Vec<serde_json::Value>>(),
"is_self": account.map(|a| a.id == user_id).unwrap_or(false), "is_self": account.map(|a| a.id == user_id).unwrap_or(false),
"n_followers": n_followers "n_followers": n_followers
})) }))
})
} }
#[get("/dashboard")] #[get("/dashboard")]
@ -91,19 +92,20 @@ fn follow_auth(name: String) -> Flash<Redirect> {
#[get("/@/<name>/followers", rank = 2)] #[get("/@/<name>/followers", rank = 2)]
fn followers(name: String, conn: DbConn, account: Option<User>) -> Template { fn followers(name: String, conn: DbConn, account: Option<User>) -> Template {
let user = User::find_by_fqn(&*conn, name.clone()).unwrap(); may_fail!(User::find_by_fqn(&*conn, name.clone()), "Couldn't find requested user", |user| {
let user_id = user.id.clone(); let user_id = user.id.clone();
Template::render("users/followers", json!({ Template::render("users/followers", json!({
"user": serde_json::to_value(user.clone()).unwrap(), "user": serde_json::to_value(user.clone()).unwrap(),
"instance_url": user.get_instance(&*conn).public_domain, "instance_url": user.get_instance(&*conn).public_domain,
"is_remote": user.instance_id != Instance::local_id(&*conn), "is_remote": user.instance_id != Instance::local_id(&*conn),
"follows": account.clone().map(|x| x.is_following(&*conn, user.id)).unwrap_or(false), "follows": account.clone().map(|x| x.is_following(&*conn, user.id)).unwrap_or(false),
"followers": user.get_followers(&*conn).into_iter().map(|f| f.to_json(&*conn)).collect::<Vec<serde_json::Value>>(), "followers": user.get_followers(&*conn).into_iter().map(|f| f.to_json(&*conn)).collect::<Vec<serde_json::Value>>(),
"account": account, "account": account,
"is_self": account.map(|a| a.id == user_id).unwrap_or(false), "is_self": account.map(|a| a.id == user_id).unwrap_or(false),
"n_followers": user.get_followers(&*conn).len() "n_followers": user.get_followers(&*conn).len()
})) }))
})
} }
#[get("/@/<name>", format = "application/activity+json", rank = 1)] #[get("/@/<name>", format = "application/activity+json", rank = 1)]