License federation (#343)
* Federate license * Make it possible to use no license
This commit is contained in:
parent
e9f2f769be
commit
b73fbd3768
@ -220,3 +220,12 @@ pub struct Source {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Object for Source {}
|
impl Object for Source {}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Licensed {
|
||||||
|
#[activitystreams(concrete(String), functional)]
|
||||||
|
pub license: Option<serde_json::Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object for Licensed {}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use activitypub::{
|
use activitypub::{
|
||||||
|
CustomObject,
|
||||||
activity::{Create, Delete, Update},
|
activity::{Create, Delete, Update},
|
||||||
link,
|
link,
|
||||||
object::{Article, Image, Tombstone},
|
object::{Article, Image, Tombstone},
|
||||||
@ -18,7 +19,7 @@ use plume_api::posts::PostEndpoint;
|
|||||||
use plume_common::{
|
use plume_common::{
|
||||||
activity_pub::{
|
activity_pub::{
|
||||||
inbox::{Deletable, FromActivity},
|
inbox::{Deletable, FromActivity},
|
||||||
Hashtag, Id, IntoId, Source, PUBLIC_VISIBILTY,
|
Hashtag, Id, IntoId, Licensed, Source, PUBLIC_VISIBILTY,
|
||||||
},
|
},
|
||||||
utils::md_to_html,
|
utils::md_to_html,
|
||||||
};
|
};
|
||||||
@ -32,6 +33,8 @@ use tags::Tag;
|
|||||||
use users::User;
|
use users::User;
|
||||||
use {ap_url, Connection, BASE_URL};
|
use {ap_url, Connection, BASE_URL};
|
||||||
|
|
||||||
|
pub type LicensedArticle = CustomObject<Licensed, Article>;
|
||||||
|
|
||||||
#[derive(Queryable, Identifiable, Serialize, Clone, AsChangeset)]
|
#[derive(Queryable, Identifiable, Serialize, Clone, AsChangeset)]
|
||||||
#[changeset_options(treat_none_as_null = "true")]
|
#[changeset_options(treat_none_as_null = "true")]
|
||||||
pub struct Post {
|
pub struct Post {
|
||||||
@ -418,7 +421,7 @@ impl Post {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_activity(&self, conn: &Connection) -> Article {
|
pub fn to_activity(&self, conn: &Connection) -> LicensedArticle {
|
||||||
let mut to = self.get_receivers_urls(conn);
|
let mut to = self.get_receivers_urls(conn);
|
||||||
to.push(PUBLIC_VISIBILTY.to_string());
|
to.push(PUBLIC_VISIBILTY.to_string());
|
||||||
|
|
||||||
@ -516,7 +519,9 @@ impl Post {
|
|||||||
.object_props
|
.object_props
|
||||||
.set_cc_link_vec::<Id>(vec![])
|
.set_cc_link_vec::<Id>(vec![])
|
||||||
.expect("Post::to_activity: cc error");
|
.expect("Post::to_activity: cc error");
|
||||||
article
|
let mut license = Licensed::default();
|
||||||
|
license.set_license_string(self.license.clone()).expect("Post::to_activity: license error");
|
||||||
|
LicensedArticle::new(article, license)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_activity(&self, conn: &Connection) -> Create {
|
pub fn create_activity(&self, conn: &Connection) -> Create {
|
||||||
@ -527,7 +532,7 @@ impl Post {
|
|||||||
.expect("Post::create_activity: id error");
|
.expect("Post::create_activity: id error");
|
||||||
act.object_props
|
act.object_props
|
||||||
.set_to_link_vec::<Id>(
|
.set_to_link_vec::<Id>(
|
||||||
article
|
article.object
|
||||||
.object_props
|
.object_props
|
||||||
.to_link_vec()
|
.to_link_vec()
|
||||||
.expect("Post::create_activity: Couldn't copy 'to'"),
|
.expect("Post::create_activity: Couldn't copy 'to'"),
|
||||||
@ -535,7 +540,7 @@ impl Post {
|
|||||||
.expect("Post::create_activity: to error");
|
.expect("Post::create_activity: to error");
|
||||||
act.object_props
|
act.object_props
|
||||||
.set_cc_link_vec::<Id>(
|
.set_cc_link_vec::<Id>(
|
||||||
article
|
article.object
|
||||||
.object_props
|
.object_props
|
||||||
.cc_link_vec()
|
.cc_link_vec()
|
||||||
.expect("Post::create_activity: Couldn't copy 'cc'"),
|
.expect("Post::create_activity: Couldn't copy 'cc'"),
|
||||||
@ -558,7 +563,7 @@ impl Post {
|
|||||||
.expect("Post::update_activity: id error");
|
.expect("Post::update_activity: id error");
|
||||||
act.object_props
|
act.object_props
|
||||||
.set_to_link_vec::<Id>(
|
.set_to_link_vec::<Id>(
|
||||||
article
|
article.object
|
||||||
.object_props
|
.object_props
|
||||||
.to_link_vec()
|
.to_link_vec()
|
||||||
.expect("Post::update_activity: Couldn't copy 'to'"),
|
.expect("Post::update_activity: Couldn't copy 'to'"),
|
||||||
@ -566,7 +571,7 @@ impl Post {
|
|||||||
.expect("Post::update_activity: to error");
|
.expect("Post::update_activity: to error");
|
||||||
act.object_props
|
act.object_props
|
||||||
.set_cc_link_vec::<Id>(
|
.set_cc_link_vec::<Id>(
|
||||||
article
|
article.object
|
||||||
.object_props
|
.object_props
|
||||||
.cc_link_vec()
|
.cc_link_vec()
|
||||||
.expect("Post::update_activity: Couldn't copy 'cc'"),
|
.expect("Post::update_activity: Couldn't copy 'cc'"),
|
||||||
@ -577,44 +582,48 @@ impl Post {
|
|||||||
.expect("Post::update_activity: actor error");
|
.expect("Post::update_activity: actor error");
|
||||||
act.update_props
|
act.update_props
|
||||||
.set_object_object(article)
|
.set_object_object(article)
|
||||||
.expect("Article::update_activity: object error");
|
.expect("Post::update_activity: object error");
|
||||||
act
|
act
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_update(conn: &Connection, updated: &Article, searcher: &Searcher) {
|
pub fn handle_update(conn: &Connection, updated: &LicensedArticle, searcher: &Searcher) {
|
||||||
let id = updated
|
let id = updated.object
|
||||||
.object_props
|
.object_props
|
||||||
.id_string()
|
.id_string()
|
||||||
.expect("Post::handle_update: id error");
|
.expect("Post::handle_update: id error");
|
||||||
let mut post = Post::find_by_ap_url(conn, &id).expect("Post::handle_update: finding error");
|
let mut post = Post::find_by_ap_url(conn, &id).expect("Post::handle_update: finding error");
|
||||||
|
|
||||||
if let Ok(title) = updated.object_props.name_string() {
|
if let Ok(title) = updated.object.object_props.name_string() {
|
||||||
post.slug = title.to_kebab_case();
|
post.slug = title.to_kebab_case();
|
||||||
post.title = title;
|
post.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(content) = updated.object_props.content_string() {
|
if let Ok(content) = updated.object.object_props.content_string() {
|
||||||
post.content = SafeString::new(&content);
|
post.content = SafeString::new(&content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(subtitle) = updated.object_props.summary_string() {
|
if let Ok(subtitle) = updated.object.object_props.summary_string() {
|
||||||
post.subtitle = subtitle;
|
post.subtitle = subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(ap_url) = updated.object_props.url_string() {
|
if let Ok(ap_url) = updated.object.object_props.url_string() {
|
||||||
post.ap_url = ap_url;
|
post.ap_url = ap_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(source) = updated.ap_object_props.source_object::<Source>() {
|
if let Ok(source) = updated.object.ap_object_props.source_object::<Source>() {
|
||||||
post.source = source.content;
|
post.source = source.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Ok(license) = updated.custom_props.license_string() {
|
||||||
|
post.license = license;
|
||||||
|
}
|
||||||
|
|
||||||
let mut txt_hashtags = md_to_html(&post.source)
|
let mut txt_hashtags = md_to_html(&post.source)
|
||||||
.2
|
.2
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| s.to_camel_case())
|
.map(|s| s.to_camel_case())
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
if let Some(serde_json::Value::Array(mention_tags)) = updated.object_props.tag.clone() {
|
if let Some(serde_json::Value::Array(mention_tags)) = updated.object.object_props.tag.clone() {
|
||||||
let mut mentions = vec![];
|
let mut mentions = vec![];
|
||||||
let mut tags = vec![];
|
let mut tags = vec![];
|
||||||
let mut hashtags = vec![];
|
let mut hashtags = vec![];
|
||||||
@ -782,8 +791,10 @@ impl Post {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromActivity<Article, (&'a Connection, &'a Searcher)> for Post {
|
impl<'a> FromActivity<LicensedArticle, (&'a Connection, &'a Searcher)> for Post {
|
||||||
fn from_activity((conn, searcher): &(&'a Connection, &'a Searcher), article: Article, _actor: Id) -> Post {
|
fn from_activity((conn, searcher): &(&'a Connection, &'a Searcher), article: LicensedArticle, _actor: Id) -> Post {
|
||||||
|
let license = article.custom_props.license_string().unwrap_or_default();
|
||||||
|
let article = article.object;
|
||||||
if let Some(post) = Post::find_by_ap_url(
|
if let Some(post) = Post::find_by_ap_url(
|
||||||
conn,
|
conn,
|
||||||
&article.object_props.id_string().unwrap_or_default(),
|
&article.object_props.id_string().unwrap_or_default(),
|
||||||
@ -829,7 +840,7 @@ impl<'a> FromActivity<Article, (&'a Connection, &'a Searcher)> for Post {
|
|||||||
.expect("Post::from_activity: content error"),
|
.expect("Post::from_activity: content error"),
|
||||||
),
|
),
|
||||||
published: true,
|
published: true,
|
||||||
license: String::from("CC-BY-SA"), // TODO
|
license: license,
|
||||||
// FIXME: This is wrong: with this logic, we may use the display URL as the AP ID. We need two different fields
|
// FIXME: This is wrong: with this logic, we may use the display URL as the AP ID. We need two different fields
|
||||||
ap_url: article.object_props.url_string().unwrap_or_else(|_|
|
ap_url: article.object_props.url_string().unwrap_or_else(|_|
|
||||||
article
|
article
|
||||||
|
7
po/de.po
7
po/de.po
@ -609,6 +609,13 @@ msgstr "Administration"
|
|||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr "Falls es dies nicht gibt, lass es leer"
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Home to"
|
#~ msgid "Home to"
|
||||||
#~ msgstr "Heimat von"
|
#~ msgstr "Heimat von"
|
||||||
|
|
||||||
|
6
po/en.po
6
po/en.po
@ -593,3 +593,9 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
7
po/fr.po
7
po/fr.po
@ -609,3 +609,10 @@ msgstr "Illustration"
|
|||||||
|
|
||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr "Aucun"
|
msgstr "Aucun"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr "Laisser vide s’il n’y en a pas"
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
7
po/gl.po
7
po/gl.po
@ -600,6 +600,13 @@ msgstr "Administración"
|
|||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr "Deixar baldeiro si non hai ningunha"
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Home to"
|
#~ msgid "Home to"
|
||||||
#~ msgstr "Fogar de"
|
#~ msgstr "Fogar de"
|
||||||
|
|
||||||
|
7
po/it.po
7
po/it.po
@ -603,6 +603,13 @@ msgstr "Amministrazione"
|
|||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr "Lascialo vuoto se non è presente nessuno"
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Home to"
|
#~ msgid "Home to"
|
||||||
#~ msgstr "Casa di"
|
#~ msgstr "Casa di"
|
||||||
|
|
||||||
|
7
po/ja.po
7
po/ja.po
@ -595,6 +595,13 @@ msgstr "図"
|
|||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr "なし"
|
msgstr "なし"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr "不要な場合は空にしてください"
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Welcome to {{ instance_name | escape }}"
|
#~ msgid "Welcome to {{ instance_name | escape }}"
|
||||||
#~ msgstr "{{ instance_name | escape }} へようこそ"
|
#~ msgstr "{{ instance_name | escape }} へようこそ"
|
||||||
|
|
||||||
|
6
po/nb.po
6
po/nb.po
@ -615,6 +615,12 @@ msgstr "Administrasjon"
|
|||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Home to"
|
#~ msgid "Home to"
|
||||||
#~ msgstr "Hjem for"
|
#~ msgstr "Hjem for"
|
||||||
|
|
||||||
|
7
po/pl.po
7
po/pl.po
@ -609,6 +609,13 @@ msgstr "Ilustracja"
|
|||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr "Brak"
|
msgstr "Brak"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr "Pozostaw puste, jeżeli niepotrzebne"
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Home to"
|
#~ msgid "Home to"
|
||||||
#~ msgstr "Dom dla"
|
#~ msgstr "Dom dla"
|
||||||
|
|
||||||
|
@ -579,3 +579,9 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
7
po/ru.po
7
po/ru.po
@ -620,6 +620,13 @@ msgstr "Иллюстрация"
|
|||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr "Нет"
|
msgstr "Нет"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Let it empty reserve all rights"
|
||||||
|
msgstr "Оставьте пустым если нет"
|
||||||
|
|
||||||
|
msgid "All rights reserved."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Home to"
|
#~ msgid "Home to"
|
||||||
#~ msgstr "Дом для"
|
#~ msgstr "Дом для"
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use activitypub::object::Article;
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use heck::{CamelCase, KebabCase};
|
use heck::{CamelCase, KebabCase};
|
||||||
use rocket::request::LenientForm;
|
use rocket::request::LenientForm;
|
||||||
@ -89,7 +88,7 @@ pub fn details_response(blog: String, slug: String, conn: DbConn, user: Option<U
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/~/<blog>/<slug>", rank = 3)]
|
#[get("/~/<blog>/<slug>", rank = 3)]
|
||||||
pub fn activity_details(blog: String, slug: String, conn: DbConn, _ap: ApRequest) -> Result<ActivityStream<Article>, Option<String>> {
|
pub fn activity_details(blog: String, slug: String, conn: DbConn, _ap: ApRequest) -> Result<ActivityStream<LicensedArticle>, Option<String>> {
|
||||||
let blog = Blog::find_by_fqn(&*conn, &blog).ok_or(None)?;
|
let blog = Blog::find_by_fqn(&*conn, &blog).ok_or(None)?;
|
||||||
let post = Post::find_by_slug(&*conn, &slug, blog.id).ok_or(None)?;
|
let post = Post::find_by_slug(&*conn, &slug, blog.id).ok_or(None)?;
|
||||||
if post.published {
|
if post.published {
|
||||||
@ -123,11 +122,13 @@ pub fn new(blog: String, user: User, conn: DbConn, intl: I18n) -> Option<Ructe>
|
|||||||
&(&*conn, &intl.catalog, Some(user)),
|
&(&*conn, &intl.catalog, Some(user)),
|
||||||
b,
|
b,
|
||||||
false,
|
false,
|
||||||
&NewPostForm::default(),
|
&NewPostForm {
|
||||||
|
license: Instance::get_local(&*conn).map(|i| i.default_license).unwrap_or_else(||String::from("CC-BY-SA")),
|
||||||
|
..NewPostForm::default()
|
||||||
|
},
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
ValidationErrors::default(),
|
ValidationErrors::default(),
|
||||||
Instance::get_local(&*conn).expect("posts::new error: Local instance is null").default_license,
|
|
||||||
medias
|
medias
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
@ -171,7 +172,6 @@ pub fn edit(blog: String, slug: String, user: User, conn: DbConn, intl: I18n) ->
|
|||||||
!post.published,
|
!post.published,
|
||||||
Some(post),
|
Some(post),
|
||||||
ValidationErrors::default(),
|
ValidationErrors::default(),
|
||||||
Instance::get_local(&*conn).expect("posts::new error: Local instance is null").default_license,
|
|
||||||
medias
|
medias
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
@ -209,12 +209,6 @@ pub fn update(blog: String, slug: String, user: User, conn: DbConn, form: Lenien
|
|||||||
} else {
|
} else {
|
||||||
let (content, mentions, hashtags) = utils::md_to_html(form.content.to_string().as_ref());
|
let (content, mentions, hashtags) = utils::md_to_html(form.content.to_string().as_ref());
|
||||||
|
|
||||||
let license = if !form.license.is_empty() {
|
|
||||||
form.license.to_string()
|
|
||||||
} else {
|
|
||||||
Instance::get_local(&*conn).map(|i| i.default_license).unwrap_or_else(|| String::from("CC-BY-SA"))
|
|
||||||
};
|
|
||||||
|
|
||||||
// update publication date if when this article is no longer a draft
|
// update publication date if when this article is no longer a draft
|
||||||
let newly_published = if !post.published && !form.draft {
|
let newly_published = if !post.published && !form.draft {
|
||||||
post.published = true;
|
post.published = true;
|
||||||
@ -229,7 +223,7 @@ pub fn update(blog: String, slug: String, user: User, conn: DbConn, form: Lenien
|
|||||||
post.subtitle = form.subtitle.clone();
|
post.subtitle = form.subtitle.clone();
|
||||||
post.content = SafeString::new(&content);
|
post.content = SafeString::new(&content);
|
||||||
post.source = form.content.clone();
|
post.source = form.content.clone();
|
||||||
post.license = license;
|
post.license = form.license.clone();
|
||||||
post.cover_id = form.cover;
|
post.cover_id = form.cover;
|
||||||
post.update(&*conn, &searcher);
|
post.update(&*conn, &searcher);
|
||||||
let post = post.update_ap_url(&*conn);
|
let post = post.update_ap_url(&*conn);
|
||||||
@ -270,7 +264,6 @@ pub fn update(blog: String, slug: String, user: User, conn: DbConn, form: Lenien
|
|||||||
form.draft.clone(),
|
form.draft.clone(),
|
||||||
Some(post),
|
Some(post),
|
||||||
errors.clone(),
|
errors.clone(),
|
||||||
Instance::get_local(&*conn).expect("posts::new error: Local instance is null").default_license,
|
|
||||||
medias.clone()
|
medias.clone()
|
||||||
));
|
));
|
||||||
Err(Some(temp))
|
Err(Some(temp))
|
||||||
@ -330,11 +323,7 @@ pub fn create(blog_name: String, form: LenientForm<NewPostForm>, user: User, con
|
|||||||
title: form.title.to_string(),
|
title: form.title.to_string(),
|
||||||
content: SafeString::new(&content),
|
content: SafeString::new(&content),
|
||||||
published: !form.draft,
|
published: !form.draft,
|
||||||
license: if !form.license.is_empty() {
|
license: form.license.clone(),
|
||||||
form.license.to_string()
|
|
||||||
} else {
|
|
||||||
Instance::get_local(&*conn).map(|i| i.default_license).unwrap_or_else(||String::from("CC-BY-SA"))
|
|
||||||
},
|
|
||||||
ap_url: "".to_string(),
|
ap_url: "".to_string(),
|
||||||
creation_date: None,
|
creation_date: None,
|
||||||
subtitle: form.subtitle.clone(),
|
subtitle: form.subtitle.clone(),
|
||||||
@ -390,7 +379,6 @@ pub fn create(blog_name: String, form: LenientForm<NewPostForm>, user: User, con
|
|||||||
form.draft,
|
form.draft,
|
||||||
None,
|
None,
|
||||||
errors.clone(),
|
errors.clone(),
|
||||||
Instance::get_local(&*conn).expect("posts::new error: Local instance is null").default_license,
|
|
||||||
medias
|
medias
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use activitypub::{activity::Create, collection::OrderedCollection, object::Article};
|
use activitypub::{activity::Create, collection::OrderedCollection};
|
||||||
use atom_syndication::{Entry, FeedBuilder};
|
use atom_syndication::{Entry, FeedBuilder};
|
||||||
use rocket::{
|
use rocket::{
|
||||||
http::{ContentType, Cookies},
|
http::{ContentType, Cookies},
|
||||||
@ -18,7 +18,7 @@ use plume_common::activity_pub::{
|
|||||||
};
|
};
|
||||||
use plume_common::utils;
|
use plume_common::utils;
|
||||||
use plume_models::{
|
use plume_models::{
|
||||||
blogs::Blog, db_conn::DbConn, follows, headers::Headers, instance::Instance, posts::Post,
|
blogs::Blog, db_conn::DbConn, follows, headers::Headers, instance::Instance, posts::{LicensedArticle, Post},
|
||||||
reshares::Reshare, users::*,
|
reshares::Reshare, users::*,
|
||||||
};
|
};
|
||||||
use routes::Page;
|
use routes::Page;
|
||||||
@ -56,7 +56,7 @@ pub fn details(
|
|||||||
let searcher = searcher.clone();
|
let searcher = searcher.clone();
|
||||||
worker.execute(move || {
|
worker.execute(move || {
|
||||||
for create_act in user_clone.fetch_outbox::<Create>() {
|
for create_act in user_clone.fetch_outbox::<Create>() {
|
||||||
match create_act.create_props.object_object::<Article>() {
|
match create_act.create_props.object_object::<LicensedArticle>() {
|
||||||
Ok(article) => {
|
Ok(article) => {
|
||||||
Post::from_activity(
|
Post::from_activity(
|
||||||
&(&*fetch_articles_conn, &searcher),
|
&(&*fetch_articles_conn, &searcher),
|
||||||
|
@ -53,7 +53,13 @@
|
|||||||
@Html(&article.content)
|
@Html(&article.content)
|
||||||
</article>
|
</article>
|
||||||
<div class="article-meta">
|
<div class="article-meta">
|
||||||
<p>@i18n!(ctx.1, "This article is under the {0} license."; &article.license)</p>
|
<p>
|
||||||
|
@if article.license.is_empty() {
|
||||||
|
@i18n!(ctx.1, "All rights reserved."; &article.license)
|
||||||
|
} else {
|
||||||
|
@i18n!(ctx.1, "This article is under the {0} license."; &article.license)
|
||||||
|
}
|
||||||
|
</p>
|
||||||
<ul class="tags">
|
<ul class="tags">
|
||||||
@for tag in tags {
|
@for tag in tags {
|
||||||
@if !tag.is_hashtag {
|
@if !tag.is_hashtag {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
@use routes::posts::NewPostForm;
|
@use routes::posts::NewPostForm;
|
||||||
@use routes::*;
|
@use routes::*;
|
||||||
|
|
||||||
@(ctx: BaseContext, blog: Blog, editing: bool, form: &NewPostForm, is_draft: bool, article: Option<Post>, errors: ValidationErrors, default_license: String, medias: Vec<Media>)
|
@(ctx: BaseContext, blog: Blog, editing: bool, form: &NewPostForm, is_draft: bool, article: Option<Post>, errors: ValidationErrors, medias: Vec<Media>)
|
||||||
|
|
||||||
@:base(ctx, &i18n!(ctx.1, if editing { "Edit {0}" } else { "New post" }; &form.title), {}, {}, {
|
@:base(ctx, &i18n!(ctx.1, if editing { "Edit {0}" } else { "New post" }; &form.title), {}, {}, {
|
||||||
<h1>
|
<h1>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
@input!(ctx.1, tags (optional text), "Tags, separated by commas", form, errors.clone(), "")
|
@input!(ctx.1, tags (optional text), "Tags, separated by commas", form, errors.clone(), "")
|
||||||
|
|
||||||
@input!(ctx.1, license (optional text), "License", &i18n!(ctx.1, "Default license will be {0}"; &default_license), form, errors, "")
|
@input!(ctx.1, license (optional text), "License", "Let it empty reserve all rights", form, errors, "")
|
||||||
|
|
||||||
<label for="cover">@i18n!(ctx.1, "Illustration")<small>@i18n!(ctx.1, "Optional")</small></label>
|
<label for="cover">@i18n!(ctx.1, "Illustration")<small>@i18n!(ctx.1, "Optional")</small></label>
|
||||||
<select id="cover" name="cover">
|
<select id="cover" name="cover">
|
||||||
|
Loading…
Reference in New Issue
Block a user