From 4f5930dcf1da64f25b092ee639337e2eed681972 Mon Sep 17 00:00:00 2001 From: silverpill Date: Thu, 18 Nov 2021 21:48:49 +0000 Subject: [PATCH] Set post visibility to public by default --- config.yaml.example | 1 + migrations/V0012__post__add_visibility.sql | 2 + migrations/schema.sql | 1 + src/activitypub/receiver.rs | 3 +- src/mastodon_api/statuses/types.rs | 9 ++- src/models/posts/queries.rs | 4 +- src/models/posts/types.rs | 67 +++++++++++++++++++++- 7 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 migrations/V0012__post__add_visibility.sql diff --git a/config.yaml.example b/config.yaml.example index 9018866..0ffdb86 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -10,6 +10,7 @@ instance_title: myserver instance_short_description: my fedi instance # Long description can contain markdown syntax instance_description: my fedi instance +# RSA private key can be generated with `mitractl generate-rsa-key` instance_rsa_key: null registrations_open: false # Login message must contain instance URL diff --git a/migrations/V0012__post__add_visibility.sql b/migrations/V0012__post__add_visibility.sql new file mode 100644 index 0000000..9b8d3f8 --- /dev/null +++ b/migrations/V0012__post__add_visibility.sql @@ -0,0 +1,2 @@ +ALTER TABLE post ADD COLUMN visibility SMALLINT NOT NULL DEFAULT 1; +ALTER TABLE post ALTER COLUMN visibility DROP DEFAULT; diff --git a/migrations/schema.sql b/migrations/schema.sql index 99d4353..b8ba232 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -34,6 +34,7 @@ CREATE TABLE post ( author_id UUID NOT NULL REFERENCES actor_profile (id) ON DELETE CASCADE, content TEXT NOT NULL, in_reply_to_id UUID REFERENCES post (id) ON DELETE CASCADE, + visilibity SMALLINT NOT NULL, reply_count INTEGER NOT NULL CHECK (reply_count >= 0) DEFAULT 0, reaction_count INTEGER NOT NULL CHECK (reaction_count >= 0) DEFAULT 0, object_id VARCHAR(200) UNIQUE, diff --git a/src/activitypub/receiver.rs b/src/activitypub/receiver.rs index 335411a..91e68fe 100644 --- a/src/activitypub/receiver.rs +++ b/src/activitypub/receiver.rs @@ -9,7 +9,7 @@ use crate::config::{Config, Instance}; use crate::database::{Pool, get_database_client}; use crate::errors::{DatabaseError, HttpError, ValidationError}; use crate::models::attachments::queries::create_attachment; -use crate::models::posts::types::{Post, PostCreateData}; +use crate::models::posts::types::{Post, PostCreateData, Visibility}; use crate::models::posts::queries::{ create_post, get_post_by_id, @@ -217,6 +217,7 @@ pub async fn process_note( let post_data = PostCreateData { content, in_reply_to_id, + visibility: Visibility::Public, attachments: attachments, mentions: mentions, object_id: Some(object.id), diff --git a/src/mastodon_api/statuses/types.rs b/src/mastodon_api/statuses/types.rs index cc8a133..e8c9ae4 100644 --- a/src/mastodon_api/statuses/types.rs +++ b/src/mastodon_api/statuses/types.rs @@ -4,7 +4,7 @@ use uuid::Uuid; use crate::mastodon_api::accounts::types::Account; use crate::mastodon_api::media::types::Attachment; -use crate::models::posts::types::{Post, PostCreateData}; +use crate::models::posts::types::{Post, PostCreateData, Visibility}; use crate::models::profiles::types::DbActorProfile; /// https://docs.joinmastodon.org/entities/mention/ @@ -35,6 +35,7 @@ pub struct Status { pub account: Account, pub content: String, pub in_reply_to_id: Option, + pub visibility: String, pub replies_count: i32, pub favourites_count: i32, pub media_attachments: Vec, @@ -58,12 +59,17 @@ impl Status { .map(|item| Mention::from_profile(item, instance_url)) .collect(); let account = Account::from_profile(post.author, instance_url); + let visibility = match post.visibility { + Visibility::Public => "public", + Visibility::Direct => "direct", + }; Self { id: post.id, created_at: post.created_at, account: account, content: post.content, in_reply_to_id: post.in_reply_to_id, + visibility: visibility.to_string(), replies_count: post.reply_count, favourites_count: post.reaction_count, media_attachments: attachments, @@ -93,6 +99,7 @@ impl From for PostCreateData { Self { content: value.status, in_reply_to_id: value.in_reply_to_id, + visibility: Visibility::Public, attachments: value.media_ids.unwrap_or(vec![]), mentions: vec![], object_id: None, diff --git a/src/models/posts/queries.rs b/src/models/posts/queries.rs index 4aabdfd..4ebba49 100644 --- a/src/models/posts/queries.rs +++ b/src/models/posts/queries.rs @@ -116,10 +116,11 @@ pub async fn create_post( INSERT INTO post ( id, author_id, content, in_reply_to_id, + visibility, object_id, created_at ) - VALUES ($1, $2, $3, $4, $5, $6) + VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING post ", &[ @@ -127,6 +128,7 @@ pub async fn create_post( &author_id, &data.content, &data.in_reply_to_id, + &data.visibility, &data.object_id, &created_at, ], diff --git a/src/models/posts/types.rs b/src/models/posts/types.rs index 3aa1185..27891c3 100644 --- a/src/models/posts/types.rs +++ b/src/models/posts/types.rs @@ -1,15 +1,71 @@ use std::convert::TryFrom; use chrono::{DateTime, Utc}; -use postgres_types::FromSql; +use postgres_protocol::types::{int2_from_sql, int2_to_sql}; +use postgres_types::{ + FromSql, ToSql, IsNull, Type, + accepts, to_sql_checked, + private::BytesMut, +}; use tokio_postgres::Row; use uuid::Uuid; -use crate::errors::ValidationError; +use crate::errors::{ConversionError, ValidationError}; use crate::models::attachments::types::DbMediaAttachment; use crate::models::profiles::types::DbActorProfile; use crate::utils::html::clean_html; +#[derive(Debug)] +pub enum Visibility { + Public, + Direct, +} + +impl From<&Visibility> for i16 { + fn from(value: &Visibility) -> i16 { + match value { + Visibility::Public => 1, + Visibility::Direct => 2, + } + } +} + +impl TryFrom for Visibility { + type Error = ConversionError; + + fn try_from(value: i16) -> Result { + let visibility = match value { + 1 => Self::Public, + 2 => Self::Direct, + _ => return Err(ConversionError), + }; + Ok(visibility) + } +} + +type SqlError = Box; + +impl<'a> FromSql<'a> for Visibility { + fn from_sql(_: &Type, raw: &'a [u8]) -> Result { + let int_value = int2_from_sql(raw)?; + let visibility = Visibility::try_from(int_value)?; + Ok(visibility) + } + + accepts!(INT2); +} + +impl ToSql for Visibility { + fn to_sql(&self, _: &Type, out: &mut BytesMut) -> Result { + let int_value: i16 = self.into(); + int2_to_sql(int_value, out); + Ok(IsNull::No) + } + + accepts!(INT2); + to_sql_checked!(); +} + #[derive(FromSql)] #[postgres(name = "post")] pub struct DbPost { @@ -17,6 +73,7 @@ pub struct DbPost { pub author_id: Uuid, pub content: String, pub in_reply_to_id: Option, + pub visibility: Visibility, pub reply_count: i32, pub reaction_count: i32, pub object_id: Option, @@ -36,6 +93,7 @@ pub struct Post { pub author: DbActorProfile, pub content: String, pub in_reply_to_id: Option, + pub visibility: Visibility, pub reply_count: i32, pub reaction_count: i32, pub attachments: Vec, @@ -61,6 +119,7 @@ impl Post { author: db_author, content: db_post.content, in_reply_to_id: db_post.in_reply_to_id, + visibility: db_post.visibility, reply_count: db_post.reply_count, reaction_count: db_post.reaction_count, attachments: db_attachments, @@ -83,6 +142,7 @@ impl Default for Post { author: Default::default(), content: "".to_string(), in_reply_to_id: None, + visibility: Visibility::Public, reply_count: 0, reaction_count: 0, attachments: vec![], @@ -114,6 +174,7 @@ impl TryFrom<&Row> for Post { pub struct PostCreateData { pub content: String, pub in_reply_to_id: Option, + pub visibility: Visibility, pub attachments: Vec, pub mentions: Vec, pub object_id: Option, @@ -142,6 +203,7 @@ mod tests { let mut post_data_1 = PostCreateData { content: " ".to_string(), in_reply_to_id: None, + visibility: Visibility::Public, attachments: vec![], mentions: vec![], object_id: None, @@ -155,6 +217,7 @@ mod tests { let mut post_data_2 = PostCreateData { content: "test ".to_string(), in_reply_to_id: None, + visibility: Visibility::Public, attachments: vec![], mentions: vec![], object_id: None,