License federation (#343)

* Federate license

* Make it possible to use no license
This commit is contained in:
Baptiste Gelez
2018-12-09 18:43:34 +01:00
committed by GitHub
parent e9f2f769be
commit b73fbd3768
16 changed files with 126 additions and 45 deletions
+30 -19
View File
@@ -1,4 +1,5 @@
use activitypub::{
CustomObject,
activity::{Create, Delete, Update},
link,
object::{Article, Image, Tombstone},
@@ -18,7 +19,7 @@ use plume_api::posts::PostEndpoint;
use plume_common::{
activity_pub::{
inbox::{Deletable, FromActivity},
Hashtag, Id, IntoId, Source, PUBLIC_VISIBILTY,
Hashtag, Id, IntoId, Licensed, Source, PUBLIC_VISIBILTY,
},
utils::md_to_html,
};
@@ -32,6 +33,8 @@ use tags::Tag;
use users::User;
use {ap_url, Connection, BASE_URL};
pub type LicensedArticle = CustomObject<Licensed, Article>;
#[derive(Queryable, Identifiable, Serialize, Clone, AsChangeset)]
#[changeset_options(treat_none_as_null = "true")]
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);
to.push(PUBLIC_VISIBILTY.to_string());
@@ -516,7 +519,9 @@ impl Post {
.object_props
.set_cc_link_vec::<Id>(vec![])
.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 {
@@ -527,7 +532,7 @@ impl Post {
.expect("Post::create_activity: id error");
act.object_props
.set_to_link_vec::<Id>(
article
article.object
.object_props
.to_link_vec()
.expect("Post::create_activity: Couldn't copy 'to'"),
@@ -535,7 +540,7 @@ impl Post {
.expect("Post::create_activity: to error");
act.object_props
.set_cc_link_vec::<Id>(
article
article.object
.object_props
.cc_link_vec()
.expect("Post::create_activity: Couldn't copy 'cc'"),
@@ -558,7 +563,7 @@ impl Post {
.expect("Post::update_activity: id error");
act.object_props
.set_to_link_vec::<Id>(
article
article.object
.object_props
.to_link_vec()
.expect("Post::update_activity: Couldn't copy 'to'"),
@@ -566,7 +571,7 @@ impl Post {
.expect("Post::update_activity: to error");
act.object_props
.set_cc_link_vec::<Id>(
article
article.object
.object_props
.cc_link_vec()
.expect("Post::update_activity: Couldn't copy 'cc'"),
@@ -577,44 +582,48 @@ impl Post {
.expect("Post::update_activity: actor error");
act.update_props
.set_object_object(article)
.expect("Article::update_activity: object error");
.expect("Post::update_activity: object error");
act
}
pub fn handle_update(conn: &Connection, updated: &Article, searcher: &Searcher) {
let id = updated
pub fn handle_update(conn: &Connection, updated: &LicensedArticle, searcher: &Searcher) {
let id = updated.object
.object_props
.id_string()
.expect("Post::handle_update: id 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.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);
}
if let Ok(subtitle) = updated.object_props.summary_string() {
if let Ok(subtitle) = updated.object.object_props.summary_string() {
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;
}
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;
}
if let Ok(license) = updated.custom_props.license_string() {
post.license = license;
}
let mut txt_hashtags = md_to_html(&post.source)
.2
.into_iter()
.map(|s| s.to_camel_case())
.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 tags = vec![];
let mut hashtags = vec![];
@@ -782,8 +791,10 @@ impl Post {
}
}
impl<'a> FromActivity<Article, (&'a Connection, &'a Searcher)> for Post {
fn from_activity((conn, searcher): &(&'a Connection, &'a Searcher), article: Article, _actor: Id) -> Post {
impl<'a> FromActivity<LicensedArticle, (&'a Connection, &'a Searcher)> for 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(
conn,
&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"),
),
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
ap_url: article.object_props.url_string().unwrap_or_else(|_|
article