From 1ea15c549d49355655a8c46a33db58ae7cf9ae66 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 3 Apr 2020 20:04:57 -0400 Subject: [PATCH] Adding post and comment ap_id columns. --- .../down.sql | 7 ++ .../up.sql | 14 +++ server/src/api/comment.rs | 11 ++ server/src/api/post.rs | 11 ++ server/src/api/user.rs | 108 +----------------- server/src/apub/mod.rs | 8 +- server/src/db/code_migrations.rs | 44 +++++++ server/src/db/comment.rs | 45 ++++++++ server/src/db/comment_view.rs | 4 + server/src/db/moderator.rs | 4 + server/src/db/post.rs | 36 ++++++ server/src/db/post_view.rs | 2 + server/src/db/user.rs | 19 ++- server/src/db/user_mention.rs | 4 + server/src/schema.rs | 4 + 15 files changed, 213 insertions(+), 108 deletions(-) create mode 100644 server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/down.sql create mode 100644 server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/up.sql diff --git a/server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/down.sql b/server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/down.sql new file mode 100644 index 00000000..50c95bb2 --- /dev/null +++ b/server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/down.sql @@ -0,0 +1,7 @@ +alter table post +drop column ap_id, +drop column local; + +alter table comment +drop column ap_id, +drop column local; diff --git a/server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/up.sql b/server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/up.sql new file mode 100644 index 00000000..a3fb9562 --- /dev/null +++ b/server/migrations/2020-04-03-194936_add_activitypub_for_posts_and_comments/up.sql @@ -0,0 +1,14 @@ +-- Add federation columns to post, comment + +alter table post +-- TODO uniqueness constraints should be added on these 3 columns later +add column ap_id character varying(255) not null default 'changeme', -- This needs to be checked and updated in code, building from the site url if local +add column local boolean not null default true +; + +alter table comment +-- TODO uniqueness constraints should be added on these 3 columns later +add column ap_id character varying(255) not null default 'changeme', -- This needs to be checked and updated in code, building from the site url if local +add column local boolean not null default true +; + diff --git a/server/src/api/comment.rs b/server/src/api/comment.rs index 8373a338..1528f509 100644 --- a/server/src/api/comment.rs +++ b/server/src/api/comment.rs @@ -99,6 +99,8 @@ impl Perform for Oper { deleted: None, read: None, updated: None, + ap_id: "changeme".into(), + local: true, }; let inserted_comment = match Comment::create(&conn, &comment_form) { @@ -106,6 +108,11 @@ impl Perform for Oper { Err(_e) => return Err(APIError::err("couldnt_create_comment").into()), }; + match Comment::update_ap_id(&conn, inserted_comment.id) { + Ok(comment) => comment, + Err(_e) => return Err(APIError::err("couldnt_create_comment").into()), + }; + let mut recipient_ids = Vec::new(); // Scan the comment for user mentions, add those rows @@ -272,6 +279,8 @@ impl Perform for Oper { let content_slurs_removed = remove_slurs(&data.content.to_owned()); + let read_comment = Comment::read(&conn, data.edit_id)?; + let comment_form = CommentForm { content: content_slurs_removed, parent_id: data.parent_id, @@ -285,6 +294,8 @@ impl Perform for Oper { } else { Some(naive_now()) }, + ap_id: read_comment.ap_id, + local: read_comment.local, }; let _updated_comment = match Comment::update(&conn, data.edit_id, &comment_form) { diff --git a/server/src/api/post.rs b/server/src/api/post.rs index 651d5769..cfb71941 100644 --- a/server/src/api/post.rs +++ b/server/src/api/post.rs @@ -131,6 +131,8 @@ impl Perform for Oper { embed_description: iframely_description, embed_html: iframely_html, thumbnail_url: pictshare_thumbnail, + ap_id: "changeme".into(), + local: true, }; let inserted_post = match Post::create(&conn, &post_form) { @@ -146,6 +148,11 @@ impl Perform for Oper { } }; + match Post::update_ap_id(&conn, inserted_post.id) { + Ok(post) => post, + Err(_e) => return Err(APIError::err("couldnt_create_post").into()), + }; + // They like their own post by default let like_form = PostLikeForm { post_id: inserted_post.id, @@ -371,6 +378,8 @@ impl Perform for Oper { let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) = fetch_iframely_and_pictshare_data(data.url.to_owned()); + let read_post = Post::read(&conn, data.edit_id)?; + let post_form = PostForm { name: data.name.to_owned(), url: data.url.to_owned(), @@ -387,6 +396,8 @@ impl Perform for Oper { embed_description: iframely_description, embed_html: iframely_html, thumbnail_url: pictshare_thumbnail, + ap_id: read_post.ap_id, + local: read_post.local, }; let _updated_post = match Post::update(&conn, data.edit_id, &post_form) { diff --git a/server/src/api/user.rs b/server/src/api/user.rs index 59a3d623..629ce8e5 100644 --- a/server/src/api/user.rs +++ b/server/src/api/user.rs @@ -563,36 +563,7 @@ impl Perform for Oper { return Err(APIError::err("not_an_admin").into()); } - let read_user = User_::read(&conn, data.user_id)?; - - // TODO make addadmin easier - let user_form = UserForm { - name: read_user.name, - fedi_name: read_user.fedi_name, - email: read_user.email, - matrix_user_id: read_user.matrix_user_id, - avatar: read_user.avatar, - password_encrypted: read_user.password_encrypted, - preferred_username: read_user.preferred_username, - updated: Some(naive_now()), - admin: data.added, - banned: read_user.banned, - show_nsfw: read_user.show_nsfw, - theme: read_user.theme, - default_sort_type: read_user.default_sort_type, - default_listing_type: read_user.default_listing_type, - lang: read_user.lang, - show_avatars: read_user.show_avatars, - send_notifications_to_email: read_user.send_notifications_to_email, - actor_id: read_user.actor_id, - bio: read_user.bio, - local: read_user.local, - private_key: read_user.private_key, - public_key: read_user.public_key, - last_refreshed_at: None, - }; - - match User_::update(&conn, data.user_id, &user_form) { + match User_::add_admin(&conn, user_id, data.added) { Ok(user) => user, Err(_e) => return Err(APIError::err("couldnt_update_user").into()), }; @@ -632,36 +603,7 @@ impl Perform for Oper { return Err(APIError::err("not_an_admin").into()); } - let read_user = User_::read(&conn, data.user_id)?; - - // TODO make bans and addadmins easier - let user_form = UserForm { - name: read_user.name, - fedi_name: read_user.fedi_name, - email: read_user.email, - matrix_user_id: read_user.matrix_user_id, - avatar: read_user.avatar, - password_encrypted: read_user.password_encrypted, - preferred_username: read_user.preferred_username, - updated: Some(naive_now()), - admin: read_user.admin, - banned: data.ban, - show_nsfw: read_user.show_nsfw, - theme: read_user.theme, - default_sort_type: read_user.default_sort_type, - default_listing_type: read_user.default_listing_type, - lang: read_user.lang, - show_avatars: read_user.show_avatars, - send_notifications_to_email: read_user.send_notifications_to_email, - actor_id: read_user.actor_id, - bio: read_user.bio, - local: read_user.local, - private_key: read_user.private_key, - public_key: read_user.public_key, - last_refreshed_at: None, - }; - - match User_::update(&conn, data.user_id, &user_form) { + match User_::ban_user(&conn, user_id, data.ban) { Ok(user) => user, Err(_e) => return Err(APIError::err("couldnt_update_user").into()), }; @@ -790,18 +732,7 @@ impl Perform for Oper { .list()?; for reply in &replies { - let comment_form = CommentForm { - content: reply.to_owned().content, - parent_id: reply.to_owned().parent_id, - post_id: reply.to_owned().post_id, - creator_id: reply.to_owned().creator_id, - removed: None, - deleted: None, - read: Some(true), - updated: reply.to_owned().updated, - }; - - let _updated_comment = match Comment::update(&conn, reply.id, &comment_form) { + match Comment::mark_as_read(&conn, reply.id) { Ok(comment) => comment, Err(_e) => return Err(APIError::err("couldnt_update_comment").into()), }; @@ -882,18 +813,7 @@ impl Perform for Oper { .list()?; for comment in &comments { - let comment_form = CommentForm { - content: "*Permananently Deleted*".to_string(), - parent_id: comment.to_owned().parent_id, - post_id: comment.to_owned().post_id, - creator_id: comment.to_owned().creator_id, - removed: None, - deleted: Some(true), - read: None, - updated: Some(naive_now()), - }; - - let _updated_comment = match Comment::update(&conn, comment.id, &comment_form) { + let _updated_comment = match Comment::permadelete(&conn, comment.id) { Ok(comment) => comment, Err(_e) => return Err(APIError::err("couldnt_update_comment").into()), }; @@ -907,25 +827,7 @@ impl Perform for Oper { .list()?; for post in &posts { - let post_form = PostForm { - name: "*Permananently Deleted*".to_string(), - url: Some("https://deleted.com".to_string()), - body: Some("*Permananently Deleted*".to_string()), - creator_id: post.to_owned().creator_id, - community_id: post.to_owned().community_id, - removed: None, - deleted: Some(true), - nsfw: post.to_owned().nsfw, - locked: None, - stickied: None, - updated: Some(naive_now()), - embed_title: None, - embed_description: None, - embed_html: None, - thumbnail_url: None, - }; - - let _updated_post = match Post::update(&conn, post.id, &post_form) { + let _updated_post = match Post::permadelete(&conn, post.id) { Ok(post) => post, Err(_e) => return Err(APIError::err("couldnt_update_post").into()), }; diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index 0f08fc98..f4afdb1f 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -26,13 +26,15 @@ pub enum EndpointType { Community, User, Post, + Comment, } pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url { let point = match endpoint_type { - EndpointType::Community => "c", - EndpointType::User => "u", - EndpointType::Post => "p", + EndpointType::Community => "community", + EndpointType::User => "user", + EndpointType::Post => "post", + EndpointType::Comment => "comment", }; Url::parse(&format!( diff --git a/server/src/db/code_migrations.rs b/server/src/db/code_migrations.rs index e0c736e1..2fdf03d5 100644 --- a/server/src/db/code_migrations.rs +++ b/server/src/db/code_migrations.rs @@ -1,5 +1,7 @@ // This is for db migrations that require code +use super::comment::Comment; use super::community::{Community, CommunityForm}; +use super::post::Post; use super::user::{UserForm, User_}; use super::*; use crate::apub::{gen_keypair_str, make_apub_endpoint, EndpointType}; @@ -9,6 +11,8 @@ use log::info; pub fn run_advanced_migrations(conn: &PgConnection) -> Result<(), Error> { user_updates_2020_04_02(conn)?; community_updates_2020_04_02(conn)?; + post_updates_2020_04_03(conn)?; + comment_updates_2020_04_03(conn)?; Ok(()) } @@ -99,3 +103,43 @@ fn community_updates_2020_04_02(conn: &PgConnection) -> Result<(), Error> { Ok(()) } + +fn post_updates_2020_04_03(conn: &PgConnection) -> Result<(), Error> { + use crate::schema::post::dsl::*; + + info!("Running post_updates_2020_04_03"); + + // Update the ap_id + let incorrect_posts = post + .filter(ap_id.eq("changeme")) + .filter(local.eq(true)) + .load::(conn)?; + + for cpost in &incorrect_posts { + Post::update_ap_id(&conn, cpost.id)?; + } + + info!("{} post rows updated.", incorrect_posts.len()); + + Ok(()) +} + +fn comment_updates_2020_04_03(conn: &PgConnection) -> Result<(), Error> { + use crate::schema::comment::dsl::*; + + info!("Running comment_updates_2020_04_03"); + + // Update the ap_id + let incorrect_comments = comment + .filter(ap_id.eq("changeme")) + .filter(local.eq(true)) + .load::(conn)?; + + for ccomment in &incorrect_comments { + Comment::update_ap_id(&conn, ccomment.id)?; + } + + info!("{} comment rows updated.", incorrect_comments.len()); + + Ok(()) +} diff --git a/server/src/db/comment.rs b/server/src/db/comment.rs index 8110fc5b..7550f072 100644 --- a/server/src/db/comment.rs +++ b/server/src/db/comment.rs @@ -1,5 +1,7 @@ use super::post::Post; use super::*; +use crate::apub::{make_apub_endpoint, EndpointType}; +use crate::naive_now; use crate::schema::{comment, comment_like, comment_saved}; // WITH RECURSIVE MyTree AS ( @@ -23,6 +25,8 @@ pub struct Comment { pub published: chrono::NaiveDateTime, pub updated: Option, pub deleted: bool, + pub ap_id: String, + pub local: bool, } #[derive(Insertable, AsChangeset, Clone)] @@ -36,6 +40,8 @@ pub struct CommentForm { pub read: Option, pub updated: Option, pub deleted: Option, + pub ap_id: String, + pub local: bool, } impl Crud for Comment { @@ -68,6 +74,37 @@ impl Crud for Comment { } } +impl Comment { + pub fn update_ap_id(conn: &PgConnection, comment_id: i32) -> Result { + use crate::schema::comment::dsl::*; + + let apid = make_apub_endpoint(EndpointType::Comment, &comment_id.to_string()).to_string(); + diesel::update(comment.find(comment_id)) + .set(ap_id.eq(apid)) + .get_result::(conn) + } + + pub fn mark_as_read(conn: &PgConnection, comment_id: i32) -> Result { + use crate::schema::comment::dsl::*; + + diesel::update(comment.find(comment_id)) + .set(read.eq(true)) + .get_result::(conn) + } + + pub fn permadelete(conn: &PgConnection, comment_id: i32) -> Result { + use crate::schema::comment::dsl::*; + + diesel::update(comment.find(comment_id)) + .set(( + content.eq("*Permananently Deleted*"), + deleted.eq(true), + updated.eq(naive_now()), + )) + .get_result::(conn) + } +} + #[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Clone)] #[belongs_to(Comment)] #[table_name = "comment_like"] @@ -231,6 +268,8 @@ mod tests { embed_description: None, embed_html: None, thumbnail_url: None, + ap_id: "changeme".into(), + local: true, }; let inserted_post = Post::create(&conn, &new_post).unwrap(); @@ -244,6 +283,8 @@ mod tests { read: None, parent_id: None, updated: None, + ap_id: "changeme".into(), + local: true, }; let inserted_comment = Comment::create(&conn, &comment_form).unwrap(); @@ -259,6 +300,8 @@ mod tests { parent_id: None, published: inserted_comment.published, updated: None, + ap_id: "changeme".into(), + local: true, }; let child_comment_form = CommentForm { @@ -270,6 +313,8 @@ mod tests { deleted: None, read: None, updated: None, + ap_id: "changeme".into(), + local: true, }; let inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap(); diff --git a/server/src/db/comment_view.rs b/server/src/db/comment_view.rs index 97c03c53..f0ca7231 100644 --- a/server/src/db/comment_view.rs +++ b/server/src/db/comment_view.rs @@ -495,6 +495,8 @@ mod tests { embed_description: None, embed_html: None, thumbnail_url: None, + ap_id: "changeme".into(), + local: true, }; let inserted_post = Post::create(&conn, &new_post).unwrap(); @@ -508,6 +510,8 @@ mod tests { deleted: None, read: None, updated: None, + ap_id: "changeme".into(), + local: true, }; let inserted_comment = Comment::create(&conn, &comment_form).unwrap(); diff --git a/server/src/db/moderator.rs b/server/src/db/moderator.rs index b01dc5cc..01acc25e 100644 --- a/server/src/db/moderator.rs +++ b/server/src/db/moderator.rs @@ -527,6 +527,8 @@ mod tests { embed_description: None, embed_html: None, thumbnail_url: None, + ap_id: "changeme".into(), + local: true, }; let inserted_post = Post::create(&conn, &new_post).unwrap(); @@ -540,6 +542,8 @@ mod tests { read: None, parent_id: None, updated: None, + ap_id: "changeme".into(), + local: true, }; let inserted_comment = Comment::create(&conn, &comment_form).unwrap(); diff --git a/server/src/db/post.rs b/server/src/db/post.rs index bd8d9e43..b0b9bddc 100644 --- a/server/src/db/post.rs +++ b/server/src/db/post.rs @@ -1,4 +1,6 @@ use super::*; +use crate::apub::{make_apub_endpoint, EndpointType}; +use crate::naive_now; use crate::schema::{post, post_like, post_read, post_saved}; #[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)] @@ -21,6 +23,8 @@ pub struct Post { pub embed_description: Option, pub embed_html: Option, pub thumbnail_url: Option, + pub ap_id: String, + pub local: bool, } #[derive(Insertable, AsChangeset, Clone)] @@ -41,6 +45,8 @@ pub struct PostForm { pub embed_description: Option, pub embed_html: Option, pub thumbnail_url: Option, + pub ap_id: String, + pub local: bool, } impl Post { @@ -58,6 +64,32 @@ impl Post { .filter(community_id.eq(the_community_id)) .load::(conn) } + + pub fn update_ap_id(conn: &PgConnection, post_id: i32) -> Result { + use crate::schema::post::dsl::*; + + let apid = make_apub_endpoint(EndpointType::Post, &post_id.to_string()).to_string(); + diesel::update(post.find(post_id)) + .set(ap_id.eq(apid)) + .get_result::(conn) + } + + pub fn permadelete(conn: &PgConnection, post_id: i32) -> Result { + use crate::schema::post::dsl::*; + + let perma_deleted = "*Permananently Deleted*"; + let perma_deleted_url = "https://deleted.com"; + + diesel::update(post.find(post_id)) + .set(( + name.eq(perma_deleted), + url.eq(perma_deleted_url), + body.eq(perma_deleted), + deleted.eq(true), + updated.eq(naive_now()), + )) + .get_result::(conn) + } } impl Crud for Post { @@ -269,6 +301,8 @@ mod tests { embed_description: None, embed_html: None, thumbnail_url: None, + ap_id: "changeme".into(), + local: true, }; let inserted_post = Post::create(&conn, &new_post).unwrap(); @@ -291,6 +325,8 @@ mod tests { embed_description: None, embed_html: None, thumbnail_url: None, + ap_id: "changeme".into(), + local: true, }; // Post Like diff --git a/server/src/db/post_view.rs b/server/src/db/post_view.rs index 587ae52b..29ff2f1b 100644 --- a/server/src/db/post_view.rs +++ b/server/src/db/post_view.rs @@ -420,6 +420,8 @@ mod tests { embed_description: None, embed_html: None, thumbnail_url: None, + ap_id: "changeme".into(), + local: true, }; let inserted_post = Post::create(&conn, &new_post).unwrap(); diff --git a/server/src/db/user.rs b/server/src/db/user.rs index 32596c27..1669d722 100644 --- a/server/src/db/user.rs +++ b/server/src/db/user.rs @@ -1,7 +1,7 @@ use super::*; use crate::schema::user_; use crate::schema::user_::dsl::*; -use crate::{is_email_regex, Settings}; +use crate::{is_email_regex, naive_now, Settings}; use bcrypt::{hash, DEFAULT_COST}; use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation}; @@ -99,13 +99,28 @@ impl User_ { let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password"); diesel::update(user_.find(user_id)) - .set(password_encrypted.eq(password_hash)) + .set(( + password_encrypted.eq(password_hash), + updated.eq(naive_now()), + )) .get_result::(conn) } pub fn read_from_name(conn: &PgConnection, from_user_name: String) -> Result { user_.filter(name.eq(from_user_name)).first::(conn) } + + pub fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result { + diesel::update(user_.find(user_id)) + .set(admin.eq(added)) + .get_result::(conn) + } + + pub fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result { + diesel::update(user_.find(user_id)) + .set(banned.eq(ban)) + .get_result::(conn) + } } #[derive(Debug, Serialize, Deserialize)] diff --git a/server/src/db/user_mention.rs b/server/src/db/user_mention.rs index 48814c89..801df6fe 100644 --- a/server/src/db/user_mention.rs +++ b/server/src/db/user_mention.rs @@ -153,6 +153,8 @@ mod tests { embed_description: None, embed_html: None, thumbnail_url: None, + ap_id: "changeme".into(), + local: true, }; let inserted_post = Post::create(&conn, &new_post).unwrap(); @@ -166,6 +168,8 @@ mod tests { read: None, parent_id: None, updated: None, + ap_id: "changeme".into(), + local: true, }; let inserted_comment = Comment::create(&conn, &comment_form).unwrap(); diff --git a/server/src/schema.rs b/server/src/schema.rs index 41769ded..819fcd1c 100644 --- a/server/src/schema.rs +++ b/server/src/schema.rs @@ -28,6 +28,8 @@ table! { published -> Timestamp, updated -> Nullable, deleted -> Bool, + ap_id -> Varchar, + local -> Bool, } } @@ -227,6 +229,8 @@ table! { embed_description -> Nullable, embed_html -> Nullable, thumbnail_url -> Nullable, + ap_id -> Varchar, + local -> Bool, } }