Merge branch 'master' into setup-script

This commit is contained in:
Bat 2018-06-19 22:26:31 +01:00
commit 635ac6cf42
10 changed files with 109 additions and 91 deletions

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: plume\n" "Project-Id-Version: plume\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-06-15 16:33-0700\n" "POT-Creation-Date: 2018-06-15 16:33-0700\n"
"PO-Revision-Date: 2018-06-17 20:57+0200\n" "PO-Revision-Date: 2018-06-19 21:15+0200\n"
"Last-Translator: Marcin Mikołajczak <me@m4sk.in>\n" "Last-Translator: Marcin Mikołajczak <me@m4sk.in>\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: pl\n" "Language: pl\n"
@ -12,6 +12,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n" "|| n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.0.8\n"
msgid "Latest articles" msgid "Latest articles"
msgstr "Najnowsze artykuły" msgstr "Najnowsze artykuły"
@ -117,7 +118,7 @@ msgid "Publish"
msgstr "Opublikuj" msgstr "Opublikuj"
msgid "Login" msgid "Login"
msgstr "" msgstr "Logowanie"
msgid "Username or email" msgid "Username or email"
msgstr "Nazwa użytkownika lub adres e-mail" msgstr "Nazwa użytkownika lub adres e-mail"
@ -261,22 +262,22 @@ msgid "By {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name }}{{ link_4 }}"
msgstr "Napisano przez {{ link_1 }}{{ url }}{{ link_2 }}{{ name }}{{ link_3 }}" msgstr "Napisano przez {{ link_1 }}{{ url }}{{ link_2 }}{{ name }}{{ link_3 }}"
msgid "{{ data }} reshared your article" msgid "{{ data }} reshared your article"
msgstr "" msgstr "{{ data }} udostępnił Twój artykuł"
msgid "{{ data }} started following you" msgid "{{ data }} started following you"
msgstr "" msgstr "{{ data }} zaczął Cię obserwować"
msgid "{{ data }} liked your article" msgid "{{ data }} liked your article"
msgstr "" msgstr "{{ data }} polubił Twój artykuł"
msgid "{{ data }} commented your article" msgid "{{ data }} commented your article"
msgstr "" msgstr "{{ data }} skomentował Twój artykuł"
msgid "We couldn't find this page." msgid "We couldn't find this page."
msgstr "" msgstr "Nie udało się odnaleźć tej strony."
msgid "The link that led you here may be broken." msgid "The link that led you here may be broken."
msgstr "" msgstr "Odnośnik który Cię tu zaprowadził może być uszkodzony."
#~ msgid "Logowanie" #~ msgid "Logowanie"
#~ msgstr "Zaloguj się" #~ msgstr "Zaloguj się"

@ -52,7 +52,7 @@ pub struct NewPost {
impl Post { impl Post {
insert!(posts, NewPost); insert!(posts, NewPost);
get!(posts); get!(posts);
find_by!(posts, find_by_slug, slug as String); find_by!(posts, find_by_slug, slug as String, blog_id as i32);
find_by!(posts, find_by_ap_url, ap_url as String); find_by!(posts, find_by_ap_url, ap_url as String);
pub fn count_local(conn: &PgConnection) -> usize { pub fn count_local(conn: &PgConnection) -> usize {

@ -46,7 +46,7 @@ fn new(user: User) -> Template {
#[get("/blogs/new", rank = 2)] #[get("/blogs/new", rank = 2)]
fn new_auth() -> Flash<Redirect>{ fn new_auth() -> Flash<Redirect>{
utils::requires_login("You need to be logged in order to create a new blog", "/blogs/new") utils::requires_login("You need to be logged in order to create a new blog", uri!(new))
} }
#[derive(FromForm)] #[derive(FromForm)]
@ -59,21 +59,25 @@ fn create(conn: DbConn, data: Form<NewBlogForm>, user: User) -> Redirect {
let form = data.get(); let form = data.get();
let slug = utils::make_actor_id(form.title.to_string()); let slug = utils::make_actor_id(form.title.to_string());
let blog = Blog::insert(&*conn, NewBlog::new_local( if Blog::find_local(&*conn, slug.clone()).is_some() || slug.len() == 0 {
slug.to_string(), Redirect::to(uri!(new))
form.title.to_string(), } else {
String::from(""), let blog = Blog::insert(&*conn, NewBlog::new_local(
Instance::local_id(&*conn) slug.to_string(),
)); form.title.to_string(),
blog.update_boxes(&*conn); String::from(""),
Instance::local_id(&*conn)
));
blog.update_boxes(&*conn);
BlogAuthor::insert(&*conn, NewBlogAuthor { BlogAuthor::insert(&*conn, NewBlogAuthor {
blog_id: blog.id, blog_id: blog.id,
author_id: user.id, author_id: user.id,
is_owner: true is_owner: true
}); });
Redirect::to(format!("/~/{}/", slug)) Redirect::to(uri!(details: name = slug))
}
} }
#[get("/~/<name>/outbox")] #[get("/~/<name>/outbox")]

@ -7,6 +7,7 @@ use rocket_contrib::Template;
use activity_pub::{broadcast, IntoId, inbox::Notify}; use activity_pub::{broadcast, IntoId, inbox::Notify};
use db_conn::DbConn; use db_conn::DbConn;
use models::{ use models::{
blogs::Blog,
comments::*, comments::*,
posts::Post, posts::Post,
users::User users::User
@ -15,19 +16,21 @@ use models::{
use utils; use utils;
use safe_string::SafeString; 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 {
may_fail!(Post::find_by_slug(&*conn, slug), "Couldn't find this post", |post| { may_fail!(Blog::find_by_fqn(&*conn, blog), "Couldn't find this blog", |blog| {
Template::render("comments/new", json!({ may_fail!(Post::find_by_slug(&*conn, slug, blog.id), "Couldn't find this post", |post| {
"post": post, Template::render("comments/new", json!({
"account": user "post": post,
})) "account": user
}))
})
}) })
} }
#[get("/~/<blog>/<slug>/comment", rank=2)] #[get("/~/<blog>/<slug>/comment", rank=2)]
fn new_auth(blog: String, slug: String) -> Flash<Redirect>{ fn new_auth(blog: String, slug: String) -> Flash<Redirect>{
utils::requires_login("You need to be logged in order to post a comment", &format!("~/{}/{}/comment", blog, slug)) utils::requires_login("You need to be logged in order to post a comment", uri!(new: blog = blog, slug = slug))
} }
#[derive(FromForm)] #[derive(FromForm)]
@ -40,9 +43,10 @@ struct NewCommentForm {
pub content: String pub content: String
} }
#[post("/~/<blog>/<slug>/comment?<query>", data = "<data>")] #[post("/~/<blog_name>/<slug>/comment?<query>", data = "<data>")]
fn create(blog: String, slug: String, query: CommentQuery, data: Form<NewCommentForm>, user: User, conn: DbConn) -> Redirect { fn create(blog_name: String, slug: String, query: CommentQuery, data: Form<NewCommentForm>, user: User, conn: DbConn) -> Redirect {
let post = Post::find_by_slug(&*conn, slug.clone()).unwrap(); let blog = Blog::find_by_fqn(&*conn, blog_name.clone()).unwrap();
let post = Post::find_by_slug(&*conn, slug.clone(), blog.id).unwrap();
let form = data.get(); let form = data.get();
let comment = Comment::insert(&*conn, NewComment { let comment = Comment::insert(&*conn, NewComment {
content: SafeString::new(&form.content.clone()), content: SafeString::new(&form.content.clone()),
@ -57,5 +61,5 @@ fn create(blog: String, slug: String, query: CommentQuery, data: Form<NewComment
Comment::notify(&*conn, comment.into_activity(&*conn), user.clone().into_id()); Comment::notify(&*conn, comment.into_activity(&*conn), user.clone().into_id());
broadcast(&*conn, &user, comment.create_activity(&*conn), user.get_followers(&*conn)); broadcast(&*conn, &user, comment.create_activity(&*conn), user.get_followers(&*conn));
Redirect::to(format!("/~/{}/{}/#comment-{}", blog, slug, comment.id)) Redirect::to(format!("/~/{}/{}/#comment-{}", blog_name, slug, comment.id))
} }

@ -3,6 +3,7 @@ use rocket::response::{Redirect, Flash};
use activity_pub::{broadcast, IntoId, inbox::Notify}; use activity_pub::{broadcast, IntoId, inbox::Notify};
use db_conn::DbConn; use db_conn::DbConn;
use models::{ use models::{
blogs::Blog,
likes, likes,
posts::Post, posts::Post,
users::User users::User
@ -12,7 +13,8 @@ use utils;
#[get("/~/<blog>/<slug>/like")] #[get("/~/<blog>/<slug>/like")]
fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect { fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
let post = Post::find_by_slug(&*conn, slug.clone()).unwrap(); let b = Blog::find_by_fqn(&*conn, blog.clone()).unwrap();
let post = Post::find_by_slug(&*conn, slug.clone(), b.id).unwrap();
if !user.has_liked(&*conn, &post) { if !user.has_liked(&*conn, &post) {
let like = likes::Like::insert(&*conn, likes::NewLike { let like = likes::Like::insert(&*conn, likes::NewLike {
@ -30,10 +32,10 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
broadcast(&*conn, &user, delete_act, user.get_followers(&*conn)); broadcast(&*conn, &user, delete_act, user.get_followers(&*conn));
} }
Redirect::to(format!("/~/{}/{}/", blog, slug)) Redirect::to(uri!(super::posts::details: blog = blog, slug = slug))
} }
#[get("/~/<blog>/<slug>/like", rank = 2)] #[get("/~/<blog>/<slug>/like", rank = 2)]
fn create_auth(blog: String, slug: String) -> Flash<Redirect>{ fn create_auth(blog: String, slug: String) -> Flash<Redirect>{
utils::requires_login("You need to be logged in order to like a post", &format!("/~/{}/{}/like", blog, slug)) utils::requires_login("You need to be logged in order to like a post", uri!(create: blog = blog, slug = slug))
} }

@ -16,5 +16,5 @@ fn notifications(conn: DbConn, user: User) -> Template {
#[get("/notifications", rank = 2)] #[get("/notifications", rank = 2)]
fn notifications_auth() -> Flash<Redirect>{ fn notifications_auth() -> Flash<Redirect>{
utils::requires_login("You need to be logged in order to see your notifications", "/notifications") utils::requires_login("You need to be logged in order to see your notifications", uri!(notifications))
} }

@ -20,7 +20,7 @@ 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 {
may_fail!(Blog::find_by_fqn(&*conn, blog), "Couldn't find this blog", |blog| { may_fail!(Blog::find_by_fqn(&*conn, blog), "Couldn't find this blog", |blog| {
may_fail!(Post::find_by_slug(&*conn, slug), "Couldn't find this post", |post| { may_fail!(Post::find_by_slug(&*conn, slug, blog.id), "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!({
@ -39,10 +39,10 @@ fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Temp
}) })
} }
#[get("/~/<_blog>/<slug>", rank = 3, format = "application/activity+json")] #[get("/~/<blog>/<slug>", rank = 3, format = "application/activity+json")]
fn activity_details(_blog: String, slug: String, conn: DbConn) -> ActivityPub { fn activity_details(blog: String, slug: String, conn: DbConn) -> ActivityPub {
// FIXME: posts in different blogs may have the same slug let blog = Blog::find_by_fqn(&*conn, blog).unwrap();
let post = Post::find_by_slug(&*conn, slug).unwrap(); let post = Post::find_by_slug(&*conn, slug, blog.id).unwrap();
let mut act = post.serialize(&*conn); let mut act = post.serialize(&*conn);
act["@context"] = context(); act["@context"] = context();
@ -51,11 +51,12 @@ fn activity_details(_blog: String, slug: String, conn: DbConn) -> ActivityPub {
#[get("/~/<blog>/new", rank = 2)] #[get("/~/<blog>/new", rank = 2)]
fn new_auth(blog: String) -> Flash<Redirect> { fn new_auth(blog: String) -> Flash<Redirect> {
utils::requires_login("You need to be logged in order to write a new post", &format!("/~/{}/new",blog)) utils::requires_login("You need to be logged in order to write a new post", uri!(new: blog = blog))
} }
#[get("/~/<_blog>/new", rank = 1)] #[get("/~/<blog>/new", rank = 1)]
fn new(_blog: String, user: User) -> Template { #[allow(unused_variables)]
fn new(blog: String, user: User) -> Template {
Template::render("posts/new", json!({ Template::render("posts/new", json!({
"account": user "account": user
})) }))
@ -74,37 +75,41 @@ fn create(blog_name: String, data: Form<NewPostForm>, user: User, conn: DbConn)
let form = data.get(); let form = data.get();
let slug = form.title.to_string().to_kebab_case(); let slug = form.title.to_string().to_kebab_case();
let content = markdown_to_html(form.content.to_string().as_ref(), &ComrakOptions{ if slug == "new" || Post::find_by_slug(&*conn, slug.clone(), blog.id).is_some() {
smart: true, Redirect::to(uri!(new: blog = blog_name))
safe: true, } else {
ext_strikethrough: true, let content = markdown_to_html(form.content.to_string().as_ref(), &ComrakOptions{
ext_tagfilter: true, smart: true,
ext_table: true, safe: true,
ext_autolink: true, ext_strikethrough: true,
ext_tasklist: true, ext_tagfilter: true,
ext_superscript: true, ext_table: true,
ext_header_ids: Some("title".to_string()), ext_autolink: true,
ext_footnotes: true, ext_tasklist: true,
..ComrakOptions::default() ext_superscript: true,
}); ext_header_ids: Some("title".to_string()),
ext_footnotes: true,
..ComrakOptions::default()
});
let post = Post::insert(&*conn, NewPost { let post = Post::insert(&*conn, NewPost {
blog_id: blog.id, blog_id: blog.id,
slug: slug.to_string(), slug: slug.to_string(),
title: form.title.to_string(), title: form.title.to_string(),
content: SafeString::new(&content), content: SafeString::new(&content),
published: true, published: true,
license: form.license.to_string(), license: form.license.to_string(),
ap_url: "".to_string() ap_url: "".to_string()
}); });
post.update_ap_url(&*conn); post.update_ap_url(&*conn);
PostAuthor::insert(&*conn, NewPostAuthor { PostAuthor::insert(&*conn, NewPostAuthor {
post_id: post.id, post_id: post.id,
author_id: user.id author_id: user.id
}); });
let act = post.create_activity(&*conn); let act = post.create_activity(&*conn);
broadcast(&*conn, &user, act, user.get_followers(&*conn)); broadcast(&*conn, &user, act, user.get_followers(&*conn));
Redirect::to(format!("/~/{}/{}/", blog_name, slug)) Redirect::to(uri!(details: blog = blog_name, slug = slug))
}
} }

@ -3,6 +3,7 @@ use rocket::response::{Redirect, Flash};
use activity_pub::{broadcast, IntoId, inbox::Notify}; use activity_pub::{broadcast, IntoId, inbox::Notify};
use db_conn::DbConn; use db_conn::DbConn;
use models::{ use models::{
blogs::Blog,
posts::Post, posts::Post,
reshares::*, reshares::*,
users::User users::User
@ -12,7 +13,8 @@ use utils;
#[get("/~/<blog>/<slug>/reshare")] #[get("/~/<blog>/<slug>/reshare")]
fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect { fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
let post = Post::find_by_slug(&*conn, slug.clone()).unwrap(); let b = Blog::find_by_fqn(&*conn, blog.clone()).unwrap();
let post = Post::find_by_slug(&*conn, slug.clone(), b.id).unwrap();
if !user.has_reshared(&*conn, &post) { if !user.has_reshared(&*conn, &post) {
let reshare = Reshare::insert(&*conn, NewReshare { let reshare = Reshare::insert(&*conn, NewReshare {
@ -30,10 +32,10 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
broadcast(&*conn, &user, delete_act, user.get_followers(&*conn)); broadcast(&*conn, &user, delete_act, user.get_followers(&*conn));
} }
Redirect::to(format!("/~/{}/{}/", blog, slug)) Redirect::to(uri!(super::posts::details: blog = blog, slug = slug))
} }
#[get("/~/<blog>/<slug>/reshare", rank=1)] #[get("/~/<blog>/<slug>/reshare", rank=1)]
fn create_auth(blog: String, slug: String) -> Flash<Redirect> { fn create_auth(blog: String, slug: String) -> Flash<Redirect> {
utils::requires_login("You need to be logged in order to reshare a post", &format!("/~/{}/{}/reshare",blog, slug)) utils::requires_login("You need to be logged in order to reshare a post", uri!(create: blog = blog, slug = slug))
} }

@ -27,8 +27,8 @@ 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(uri!(details: name = user.username))),
None => Err(utils::requires_login("", "/me")) None => Err(utils::requires_login("", uri!(me)))
} }
} }
@ -65,7 +65,7 @@ fn dashboard(user: User, conn: DbConn) -> Template {
#[get("/dashboard", rank = 2)] #[get("/dashboard", rank = 2)]
fn dashboard_auth() -> Flash<Redirect> { fn dashboard_auth() -> Flash<Redirect> {
utils::requires_login("You need to be logged in order to access your dashboard", "/dashboard") utils::requires_login("You need to be logged in order to access your dashboard", uri!(dashboard))
} }
#[get("/@/<name>/follow")] #[get("/@/<name>/follow")]
@ -82,12 +82,12 @@ fn follow(name: String, conn: DbConn, user: User) -> Redirect {
follows::Follow::notify(&*conn, act.clone(), user.clone().into_id()); follows::Follow::notify(&*conn, act.clone(), user.clone().into_id());
broadcast(&*conn, &user, act, vec![target]); broadcast(&*conn, &user, act, vec![target]);
Redirect::to(format!("/@/{}/", name)) Redirect::to(uri!(details: name = name))
} }
#[get("/@/<name>/follow", rank = 2)] #[get("/@/<name>/follow", rank = 2)]
fn follow_auth(name: String) -> Flash<Redirect> { fn follow_auth(name: String) -> Flash<Redirect> {
utils::requires_login("You need to be logged in order to follow someone", &format!("/@/{}/follow", name)) utils::requires_login("You need to be logged in order to follow someone", uri!(follow: name = name))
} }
#[get("/@/<name>/followers", rank = 2)] #[get("/@/<name>/followers", rank = 2)]
@ -134,7 +134,7 @@ fn edit(name: String, user: User) -> Option<Template> {
#[get("/@/<name>/edit", rank = 2)] #[get("/@/<name>/edit", rank = 2)]
fn edit_auth(name: String) -> Flash<Redirect> { fn edit_auth(name: String) -> Flash<Redirect> {
utils::requires_login("You need to be logged in order to edit your profile", &format!("/@/{}/edit", name)) utils::requires_login("You need to be logged in order to edit your profile", uri!(edit: name = name))
} }
#[derive(FromForm)] #[derive(FromForm)]
@ -151,7 +151,7 @@ fn update(_name: String, conn: DbConn, user: User, data: Form<UpdateUserForm>) -
data.get().email.clone().unwrap_or(user.email.clone().unwrap()).to_string(), data.get().email.clone().unwrap_or(user.email.clone().unwrap()).to_string(),
data.get().summary.clone().unwrap_or(user.summary.to_string()) data.get().summary.clone().unwrap_or(user.summary.to_string())
); );
Redirect::to("/me") Redirect::to(uri!(me))
} }
#[derive(FromForm)] #[derive(FromForm)]
@ -182,7 +182,7 @@ fn create(conn: DbConn, data: Form<NewUserForm>) -> Result<Redirect, String> {
form.email.to_string(), form.email.to_string(),
User::hash_pass(form.password.to_string()) User::hash_pass(form.password.to_string())
).update_boxes(&*conn); ).update_boxes(&*conn);
Ok(Redirect::to(format!("/@/{}/", data.get().username))) Ok(Redirect::to(uri!(super::session::new)))
} else { } else {
Err(String::from("Passwords don't match")) Err(String::from("Passwords don't match"))
} }

@ -15,6 +15,6 @@ pub fn make_actor_id(name: String) -> String {
.collect() .collect()
} }
pub fn requires_login(message: &str, url: &str) -> Flash<Redirect> { pub fn requires_login(message: &str, url: Uri) -> Flash<Redirect> {
Flash::new(Redirect::to(Uri::new(format!("/login?m={}", gettext(message.to_string())))), "callback", url) Flash::new(Redirect::to(Uri::new(format!("/login?m={}", gettext(message.to_string())))), "callback", url.as_str())
} }