diff --git a/plume-models/src/blogs.rs b/plume-models/src/blogs.rs index 4863305b..0c8e2aa8 100644 --- a/plume-models/src/blogs.rs +++ b/plume-models/src/blogs.rs @@ -86,14 +86,14 @@ impl Blog { inserted.ap_url = instance.compute_box(BLOG_PREFIX, &inserted.actor_id, ""); } - if inserted.fqn.is_empty() { + if inserted.fqn.to_string().is_empty() { // This might not enough for some titles such as all-Japanese title, // but better than doing nothing. - let fqn = make_fqn(&inserted.title); + let username = make_fqn(&inserted.title); if instance.local { - inserted.fqn = fqn; + inserted.fqn = Fqn::new_local(username)?; } else { - inserted.fqn = format!("{}@{}", &fqn, instance.public_domain); + inserted.fqn = Fqn::new_remote(username, instance.public_domain)?; } } @@ -174,7 +174,7 @@ impl Blog { pub fn to_activity(&self, conn: &Connection) -> Result { let mut blog = ApActor::new(self.inbox_url.parse()?, Group::new()); - blog.set_preferred_username(&self.fqn); + blog.set_preferred_username(self.fqn.to_string()); blog.set_name(self.title.clone()); blog.set_outbox(self.outbox_url.parse()?); blog.set_summary(self.summary_html.to_string()); @@ -399,27 +399,18 @@ impl FromId for Blog { ) }; - let mut new_blog = NewBlog { - actor_id: iri_percent_encode_seg( - &acct - .name() - .and_then(|name| name.to_as_string()) - .ok_or(Error::MissingApProperty)?, - ), - outbox_url, - inbox_url, - public_key: acct.ext_one.public_key.public_key_pem.to_string(), - private_key: None, - theme: None, - ..NewBlog::default() - }; - + let actor_id = iri_percent_encode_seg( + &acct + .name() + .and_then(|name| name.to_as_string()) + .ok_or(Error::MissingApProperty)?, + ); let object = ApObject::new(acct.inner); - new_blog.title = object + let title = object .name() .and_then(|name| name.to_as_string()) - .unwrap_or(name); - new_blog.summary_html = SafeString::new( + .unwrap_or(name.clone()); + let summary_html = SafeString::new( &object .summary() .and_then(|summary| summary.to_as_string()) @@ -441,7 +432,6 @@ impl FromId for Blog { }) }) .map(|m| m.id); - new_blog.icon_id = icon_id; let banner_id = object .image() @@ -458,13 +448,12 @@ impl FromId for Blog { }) }) .map(|m| m.id); - new_blog.banner_id = banner_id; - new_blog.summary = acct.ext_two.source.content; + let summary = acct.ext_two.source.content; let any_base = AnyBase::from_extended(object)?; let id = any_base.id().ok_or(Error::MissingApProperty)?; - new_blog.ap_url = id.to_string(); + let ap_url = id.to_string(); let inst = id .authority_components() @@ -488,7 +477,29 @@ impl FromId for Blog { }, ) })?; - new_blog.instance_id = instance.id; + let instance_id = instance.id; + let fqn = if instance.local { + Fqn::new_local(name)? + } else { + Fqn::new_remote(name, instance.public_domain)? + }; + + let new_blog = NewBlog { + actor_id, + outbox_url, + inbox_url, + fqn, + public_key: acct.ext_one.public_key.public_key_pem.to_string(), + private_key: None, + theme: None, + title, + summary, + ap_url, + summary_html, + icon_id, + banner_id, + instance_id, + }; Blog::insert(conn, new_blog) } @@ -544,12 +555,19 @@ impl NewBlog { let (pub_key, priv_key) = sign::gen_keypair(); Ok(NewBlog { actor_id, + fqn: Fqn::new_local(make_fqn(&title))?, title, summary, instance_id, public_key: String::from_utf8(pub_key).or(Err(Error::Signature))?, private_key: Some(String::from_utf8(priv_key).or(Err(Error::Signature))?), - ..NewBlog::default() + outbox_url: Default::default(), + inbox_url: Default::default(), + ap_url: Default::default(), + summary_html: Default::default(), + icon_id: Default::default(), + banner_id: Default::default(), + theme: Default::default(), }) } } @@ -836,7 +854,7 @@ pub(crate) mod tests { conn.test_transaction::<_, (), _>(|| { fill_database(conn); - let blog = Blog::insert( + let _ = Blog::insert( conn, NewBlog::new_local( "Some%20Name".to_owned(), @@ -848,7 +866,6 @@ pub(crate) mod tests { ) .unwrap(); - assert_eq!(blog.fqn, "SomeName"); Ok(()) }) } diff --git a/plume-models/src/posts.rs b/plume-models/src/posts.rs index cc5f7fb1..878dbdb3 100644 --- a/plume-models/src/posts.rs +++ b/plume-models/src/posts.rs @@ -1,7 +1,7 @@ use crate::{ ap_url, blogs::Blog, db_conn::DbConn, instance::Instance, medias::Media, mentions::Mention, post_authors::*, safe_string::SafeString, schema::posts, tags::*, timeline::*, users::User, - Connection, Error, PostEvent::*, Result, CONFIG, POST_CHAN, + Connection, Error, Fqn, PostEvent::*, Result, CONFIG, POST_CHAN, }; use activitystreams::{ activity::{Create, Delete, Update}, @@ -28,7 +28,7 @@ use riker::actors::{Publish, Tell}; use std::collections::{HashMap, HashSet}; use std::sync::{Arc, Mutex}; -static BLOG_FQN_CACHE: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new())); +static BLOG_FQN_CACHE: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new())); #[derive(Queryable, Identifiable, Clone, AsChangeset, Debug)] #[changeset_options(treat_none_as_null = "true")] @@ -255,7 +255,7 @@ impl Post { ap_url(&format!( "{}/~/{}/{}/", CONFIG.base_url, - iri_percent_encode_seg(&blog.fqn), + &blog.fqn, iri_percent_encode_seg(slug) )) } @@ -298,9 +298,9 @@ impl Post { /// This caches query result. The best way to cache query result is holding it in `Post`s field /// but Diesel doesn't allow it currently. /// If sometime Diesel allow it, this method should be removed. - pub fn get_blog_fqn(&self, conn: &Connection) -> String { + pub fn get_blog_fqn(&self, conn: &Connection) -> Fqn { if let Some(blog_fqn) = BLOG_FQN_CACHE.lock().unwrap().get(&self.blog_id) { - return blog_fqn.to_string(); + return blog_fqn.to_owned(); } let blog_fqn = self.get_blog(conn).unwrap().fqn; BLOG_FQN_CACHE diff --git a/plume-models/src/search/actor.rs b/plume-models/src/search/actor.rs index 0b8afcfb..597ef924 100644 --- a/plume-models/src/search/actor.rs +++ b/plume-models/src/search/actor.rs @@ -77,6 +77,7 @@ impl ActorFactoryArgs<(Arc, DbPool)> for SearchActor { #[cfg(test)] mod tests { use crate::diesel::Connection; + use crate::Fqn; use crate::{ blog_authors::{BlogAuthor, NewBlogAuthor}, blogs::{Blog, NewBlog}, @@ -90,7 +91,7 @@ mod tests { Connection as Conn, CONFIG, }; use diesel::r2d2::ConnectionManager; - use plume_common::utils::random_hex; + use plume_common::utils::{make_fqn, random_hex}; use std::str::FromStr; use std::sync::Arc; use std::thread::sleep; @@ -190,13 +191,22 @@ mod tests { }, ) .unwrap(); + let title = random_hex(); let blog = NewBlog { instance_id: instance.id, actor_id: random_hex(), ap_url: random_hex(), inbox_url: random_hex(), outbox_url: random_hex(), - ..Default::default() + fqn: Fqn::new_local(make_fqn(&title)).unwrap(), + title, + summary: Default::default(), + summary_html: Default::default(), + private_key: Default::default(), + public_key: Default::default(), + icon_id: Default::default(), + banner_id: Default::default(), + theme: Default::default(), }; let blog = Blog::insert(conn, blog).unwrap(); BlogAuthor::insert( diff --git a/src/routes/blogs.rs b/src/routes/blogs.rs index 8fed6f45..a2cb3698 100644 --- a/src/routes/blogs.rs +++ b/src/routes/blogs.rs @@ -385,7 +385,7 @@ mod tests { use super::valid_slug; use crate::init_rocket; use diesel::Connection; - use plume_common::utils::random_hex; + use plume_common::utils::{random_hex, make_fqn}; use plume_models::{ blog_authors::{BlogAuthor, NewBlogAuthor}, blogs::{Blog, NewBlog}, @@ -394,7 +394,7 @@ mod tests { post_authors::{NewPostAuthor, PostAuthor}, posts::{NewPost, Post}, safe_string::SafeString, - users::{NewUser, User, AUTH_COOKIE}, + users::{NewUser, User, AUTH_COOKIE}, Fqn, }; use rocket::{ http::{Cookie, Cookies, SameSite}, @@ -424,9 +424,9 @@ mod tests { fn edit_link_within_post_card() { let (client, (instance, user, blog, post)) = setup(); - let blog_path = uri!(super::activity_details: name = &blog.fqn).to_string(); + let blog_path = uri!(super::activity_details: name = &blog.fqn.to_string()).to_string(); let edit_link = uri!( - super::super::posts::edit: blog = &blog.fqn, + super::super::posts::edit: blog = &blog.fqn.to_string(), slug = &post.slug ) .to_string(); @@ -497,14 +497,23 @@ mod tests { ..Default::default() }; let user = User::insert(conn, user).unwrap(); + let title = random_hex(); let blog = NewBlog { instance_id: instance.id, - title: random_hex(), + fqn: Fqn::new_local(make_fqn(&title)).unwrap(), + title, actor_id: random_hex(), ap_url: random_hex(), inbox_url: random_hex(), outbox_url: random_hex(), - ..Default::default() + summary: Default::default(), + summary_html: Default::default(), + public_key: Default::default(), + private_key: Default::default(), + icon_id: Default::default(), + banner_id: Default::default(), + theme: Default::default(), + }; let blog = Blog::insert(conn, blog).unwrap(); BlogAuthor::insert( diff --git a/src/routes/instance.rs b/src/routes/instance.rs index b4ac399b..c0a06d0c 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -407,7 +407,7 @@ pub fn interact(conn: DbConn, user: Option, target: String) -> Option, target: String) -> Option - + @if !ctx.2.clone().map(|u| u.hide_custom_css).unwrap_or(false) { @@ -31,7 +31,7 @@ } } }, { - @blog.title + @blog.title }, { @@ -76,7 +76,7 @@

@i18n!(ctx.1, "Latest articles") - @icon!("rss") + @icon!("rss")

@if posts.is_empty() {

@i18n!(ctx.1, "No posts to see here yet.")

diff --git a/templates/blogs/edit.rs.html b/templates/blogs/edit.rs.html index b7806830..9efd45aa 100644 --- a/templates/blogs/edit.rs.html +++ b/templates/blogs/edit.rs.html @@ -12,10 +12,10 @@ @(ctx: BaseContext, blog: &Blog, medias: Vec, form: &EditForm, errors: ValidationErrors) @:base(ctx, i18n!(ctx.1, "Edit \"{}\""; &blog.title), {}, { - @blog.title + @blog.title }, {

@i18n!(ctx.1, "Edit \"{}\""; &blog.title)

-
+ @@ -53,7 +53,7 @@

@i18n!(ctx.1, "Danger zone")

@i18n!(ctx.1, "Be very careful, any action taken here can't be reversed.")

- +
}) diff --git a/templates/partials/post_card.rs.html b/templates/partials/post_card.rs.html index e91d8311..2dd4c8f7 100644 --- a/templates/partials/post_card.rs.html +++ b/templates/partials/post_card.rs.html @@ -6,19 +6,19 @@
@if article.cover_id.is_some() { - +
}

- + @article.title

@if ctx.2.clone().and_then(|u| article.is_author(ctx.0, u.id).ok()).unwrap_or(false) { }
@@ -35,7 +35,7 @@ @if article.published { ⋅ @article.creation_date.format("%B %e, %Y") } - ⋅ @article.get_blog(ctx.0).unwrap().title + ⋅ @article.get_blog(ctx.0).unwrap().title
@if !article.published { diff --git a/templates/posts/details.rs.html b/templates/posts/details.rs.html index 8ffd6ca8..f177f82e 100644 --- a/templates/posts/details.rs.html +++ b/templates/posts/details.rs.html @@ -18,7 +18,7 @@ @if article.cover_id.is_some() { } - + @@ -28,7 +28,7 @@ } } }, { - @blog.title + @blog.title }, {
@if ctx.2.is_some() {
- -
+

@n_reshares

@@ -104,7 +104,7 @@ } else {

@Html(i18n!(ctx.1, "{0}Log in{1}, or {2}use your Fediverse account{3} to interact with this article"; format!("", escape(&uri!(session::new: m = _).to_string())), "", - format!("", escape(&uri!(posts::remote_interact: blog_name = &blog.fqn, slug = &article.slug).to_string())), "" + format!("", escape(&uri!(posts::remote_interact: blog_name = &blog.fqn.to_string(), slug = &article.slug).to_string())), "" ))

@@ -112,14 +112,14 @@

@n_likes

- @icon!("heart") @i18n!(ctx.1, "Add yours") + @icon!("heart") @i18n!(ctx.1, "Add yours")
} @@ -144,7 +144,7 @@

@i18n!(ctx.1, "Comments")

@if ctx.2.is_some() { - + @(Input::new("warning", i18n!(ctx.1, "Content warning")) .default(&comment_form.warning) .error(&comment_errors) @@ -162,7 +162,7 @@ @if !comments.is_empty() { @for comm in comments { - @:comment(ctx, &comm, Some(&article.ap_url), &blog.fqn, &article.slug) + @:comment(ctx, &comm, Some(&article.ap_url), &blog.fqn.to_string(), &article.slug) } } else {

@i18n!(ctx.1, "No comments yet. Be the first to react!")

@@ -173,7 +173,7 @@ @if ctx.2.clone().and_then(|u| article.is_author(ctx.0, u.id).ok()).unwrap_or(false) { }