Adding local site settings to reject federated upvotes or downvotes. (#5038)
* Adding local site settings to reject federated upvotes or downvotes. - Should help defend against downvote spamming instances. - Fixes #4086 * Adding new vote mode types. * Simpler activitypub vote check. * Adding undo vote for failed vote mode check. * Update crates/api_common/src/utils.rs --------- Co-authored-by: Nutomic <me@nutomic.com>
This commit is contained in:
parent
e3edc317be
commit
ffb94fde85
13 changed files with 217 additions and 39 deletions
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
||||||
comment::{CommentResponse, CreateCommentLike},
|
comment::{CommentResponse, CreateCommentLike},
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
send_activity::{ActivityChannel, SendActivityData},
|
||||||
utils::{check_bot_account, check_community_user_action, check_downvotes_enabled},
|
utils::{check_bot_account, check_community_user_action, check_local_vote_mode, VoteItem},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::LocalUserId,
|
newtypes::LocalUserId,
|
||||||
|
@ -27,14 +27,20 @@ pub async fn like_comment(
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<CommentResponse>> {
|
) -> LemmyResult<Json<CommentResponse>> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
let comment_id = data.comment_id;
|
||||||
|
|
||||||
let mut recipient_ids = Vec::<LocalUserId>::new();
|
let mut recipient_ids = Vec::<LocalUserId>::new();
|
||||||
|
|
||||||
// Don't do a downvote if site has downvotes disabled
|
check_local_vote_mode(
|
||||||
check_downvotes_enabled(data.score, &local_site)?;
|
data.score,
|
||||||
|
VoteItem::Comment(comment_id),
|
||||||
|
&local_site,
|
||||||
|
local_user_view.person.id,
|
||||||
|
&mut context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
check_bot_account(&local_user_view.person)?;
|
check_bot_account(&local_user_view.person)?;
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
|
||||||
let orig_comment = CommentView::read(
|
let orig_comment = CommentView::read(
|
||||||
&mut context.pool(),
|
&mut context.pool(),
|
||||||
comment_id,
|
comment_id,
|
||||||
|
|
|
@ -8,8 +8,9 @@ use lemmy_api_common::{
|
||||||
utils::{
|
utils::{
|
||||||
check_bot_account,
|
check_bot_account,
|
||||||
check_community_user_action,
|
check_community_user_action,
|
||||||
check_downvotes_enabled,
|
check_local_vote_mode,
|
||||||
mark_post_as_read,
|
mark_post_as_read,
|
||||||
|
VoteItem,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
@ -31,13 +32,19 @@ pub async fn like_post(
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<PostResponse>> {
|
) -> LemmyResult<Json<PostResponse>> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
let post_id = data.post_id;
|
||||||
|
|
||||||
// Don't do a downvote if site has downvotes disabled
|
check_local_vote_mode(
|
||||||
check_downvotes_enabled(data.score, &local_site)?;
|
data.score,
|
||||||
|
VoteItem::Post(post_id),
|
||||||
|
&local_site,
|
||||||
|
local_user_view.person.id,
|
||||||
|
&mut context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
check_bot_account(&local_user_view.person)?;
|
check_bot_account(&local_user_view.person)?;
|
||||||
|
|
||||||
// Check for a community ban
|
// Check for a community ban
|
||||||
let post_id = data.post_id;
|
|
||||||
let post = Post::read(&mut context.pool(), post_id).await?;
|
let post = Post::read(&mut context.pool(), post_id).await?;
|
||||||
|
|
||||||
check_community_user_action(
|
check_community_user_action(
|
||||||
|
|
|
@ -21,6 +21,7 @@ use lemmy_db_schema::{
|
||||||
tagline::Tagline,
|
tagline::Tagline,
|
||||||
},
|
},
|
||||||
CommentSortType,
|
CommentSortType,
|
||||||
|
FederationMode,
|
||||||
ListingType,
|
ListingType,
|
||||||
ModlogActionType,
|
ModlogActionType,
|
||||||
PostListingMode,
|
PostListingMode,
|
||||||
|
@ -170,7 +171,6 @@ pub struct CreateSite {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<String>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
pub enable_downvotes: Option<bool>,
|
|
||||||
pub enable_nsfw: Option<bool>,
|
pub enable_nsfw: Option<bool>,
|
||||||
pub community_creation_admin_only: Option<bool>,
|
pub community_creation_admin_only: Option<bool>,
|
||||||
pub require_email_verification: Option<bool>,
|
pub require_email_verification: Option<bool>,
|
||||||
|
@ -208,6 +208,10 @@ pub struct CreateSite {
|
||||||
pub registration_mode: Option<RegistrationMode>,
|
pub registration_mode: Option<RegistrationMode>,
|
||||||
pub oauth_registration: Option<bool>,
|
pub oauth_registration: Option<bool>,
|
||||||
pub content_warning: Option<String>,
|
pub content_warning: Option<String>,
|
||||||
|
pub post_upvotes: Option<FederationMode>,
|
||||||
|
pub post_downvotes: Option<FederationMode>,
|
||||||
|
pub comment_upvotes: Option<FederationMode>,
|
||||||
|
pub comment_downvotes: Option<FederationMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -224,8 +228,6 @@ pub struct EditSite {
|
||||||
pub icon: Option<String>,
|
pub icon: Option<String>,
|
||||||
/// A url for your site's banner.
|
/// A url for your site's banner.
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
/// Whether to enable downvotes.
|
|
||||||
pub enable_downvotes: Option<bool>,
|
|
||||||
/// Whether to enable NSFW.
|
/// Whether to enable NSFW.
|
||||||
pub enable_nsfw: Option<bool>,
|
pub enable_nsfw: Option<bool>,
|
||||||
/// Limits community creation to admins only.
|
/// Limits community creation to admins only.
|
||||||
|
@ -291,13 +293,21 @@ pub struct EditSite {
|
||||||
/// A list of blocked URLs
|
/// A list of blocked URLs
|
||||||
pub blocked_urls: Option<Vec<String>>,
|
pub blocked_urls: Option<Vec<String>>,
|
||||||
pub registration_mode: Option<RegistrationMode>,
|
pub registration_mode: Option<RegistrationMode>,
|
||||||
/// Whether or not external auth methods can auto-register users.
|
|
||||||
pub oauth_registration: Option<bool>,
|
|
||||||
/// Whether to email admins for new reports.
|
/// Whether to email admins for new reports.
|
||||||
pub reports_email_admins: Option<bool>,
|
pub reports_email_admins: Option<bool>,
|
||||||
/// If present, nsfw content is visible by default. Should be displayed by frontends/clients
|
/// If present, nsfw content is visible by default. Should be displayed by frontends/clients
|
||||||
/// when the site is first opened by a user.
|
/// when the site is first opened by a user.
|
||||||
pub content_warning: Option<String>,
|
pub content_warning: Option<String>,
|
||||||
|
/// Whether or not external auth methods can auto-register users.
|
||||||
|
pub oauth_registration: Option<bool>,
|
||||||
|
/// What kind of post upvotes your site allows.
|
||||||
|
pub post_upvotes: Option<FederationMode>,
|
||||||
|
/// What kind of post downvotes your site allows.
|
||||||
|
pub post_downvotes: Option<FederationMode>,
|
||||||
|
/// What kind of comment upvotes your site allows.
|
||||||
|
pub comment_upvotes: Option<FederationMode>,
|
||||||
|
/// What kind of comment downvotes your site allows.
|
||||||
|
pub comment_downvotes: Option<FederationMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
|
|
@ -13,7 +13,7 @@ use lemmy_db_schema::{
|
||||||
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
|
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
|
||||||
newtypes::{CommentId, CommunityId, DbUrl, InstanceId, PersonId, PostId},
|
newtypes::{CommentId, CommunityId, DbUrl, InstanceId, PersonId, PostId},
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentUpdateForm},
|
comment::{Comment, CommentLike, CommentUpdateForm},
|
||||||
community::{Community, CommunityModerator, CommunityUpdateForm},
|
community::{Community, CommunityModerator, CommunityUpdateForm},
|
||||||
community_block::CommunityBlock,
|
community_block::CommunityBlock,
|
||||||
email_verification::{EmailVerification, EmailVerificationForm},
|
email_verification::{EmailVerification, EmailVerificationForm},
|
||||||
|
@ -28,12 +28,13 @@ use lemmy_db_schema::{
|
||||||
password_reset_request::PasswordResetRequest,
|
password_reset_request::PasswordResetRequest,
|
||||||
person::{Person, PersonUpdateForm},
|
person::{Person, PersonUpdateForm},
|
||||||
person_block::PersonBlock,
|
person_block::PersonBlock,
|
||||||
post::{Post, PostRead},
|
post::{Post, PostLike, PostRead},
|
||||||
registration_application::RegistrationApplication,
|
registration_application::RegistrationApplication,
|
||||||
site::Site,
|
site::Site,
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::{Crud, Likeable},
|
||||||
utils::DbPool,
|
utils::DbPool,
|
||||||
|
FederationMode,
|
||||||
RegistrationMode,
|
RegistrationMode,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
|
@ -297,13 +298,36 @@ pub async fn check_person_instance_community_block(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A vote item type used to check the vote mode.
|
||||||
|
pub enum VoteItem {
|
||||||
|
Post(PostId),
|
||||||
|
Comment(CommentId),
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub fn check_downvotes_enabled(score: i16, local_site: &LocalSite) -> LemmyResult<()> {
|
pub async fn check_local_vote_mode(
|
||||||
if score == -1 && !local_site.enable_downvotes {
|
score: i16,
|
||||||
Err(LemmyErrorType::DownvotesAreDisabled)?
|
vote_item: VoteItem,
|
||||||
} else {
|
local_site: &LocalSite,
|
||||||
Ok(())
|
person_id: PersonId,
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
) -> LemmyResult<()> {
|
||||||
|
let (downvote_setting, upvote_setting) = match vote_item {
|
||||||
|
VoteItem::Post(_) => (local_site.post_downvotes, local_site.post_upvotes),
|
||||||
|
VoteItem::Comment(_) => (local_site.comment_downvotes, local_site.comment_upvotes),
|
||||||
|
};
|
||||||
|
|
||||||
|
let downvote_fail = score == -1 && downvote_setting == FederationMode::Disable;
|
||||||
|
let upvote_fail = score == 1 && upvote_setting == FederationMode::Disable;
|
||||||
|
|
||||||
|
// Undo previous vote for item if new vote fails
|
||||||
|
if downvote_fail || upvote_fail {
|
||||||
|
match vote_item {
|
||||||
|
VoteItem::Post(post_id) => PostLike::remove(pool, person_id, post_id).await?,
|
||||||
|
VoteItem::Comment(comment_id) => CommentLike::remove(pool, person_id, comment_id).await?,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dont allow bots to do certain actions, like voting
|
/// Dont allow bots to do certain actions, like voting
|
||||||
|
|
|
@ -90,7 +90,6 @@ pub async fn create_site(
|
||||||
let local_site_form = LocalSiteUpdateForm {
|
let local_site_form = LocalSiteUpdateForm {
|
||||||
// Set the site setup to true
|
// Set the site setup to true
|
||||||
site_setup: Some(true),
|
site_setup: Some(true),
|
||||||
enable_downvotes: data.enable_downvotes,
|
|
||||||
registration_mode: data.registration_mode,
|
registration_mode: data.registration_mode,
|
||||||
community_creation_admin_only: data.community_creation_admin_only,
|
community_creation_admin_only: data.community_creation_admin_only,
|
||||||
require_email_verification: data.require_email_verification,
|
require_email_verification: data.require_email_verification,
|
||||||
|
@ -110,6 +109,10 @@ pub async fn create_site(
|
||||||
captcha_enabled: data.captcha_enabled,
|
captcha_enabled: data.captcha_enabled,
|
||||||
captcha_difficulty: data.captcha_difficulty.clone(),
|
captcha_difficulty: data.captcha_difficulty.clone(),
|
||||||
default_post_listing_mode: data.default_post_listing_mode,
|
default_post_listing_mode: data.default_post_listing_mode,
|
||||||
|
post_upvotes: data.post_upvotes,
|
||||||
|
post_downvotes: data.post_downvotes,
|
||||||
|
comment_upvotes: data.comment_upvotes,
|
||||||
|
comment_downvotes: data.comment_downvotes,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,6 @@ pub async fn update_site(
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let local_site_form = LocalSiteUpdateForm {
|
let local_site_form = LocalSiteUpdateForm {
|
||||||
enable_downvotes: data.enable_downvotes,
|
|
||||||
registration_mode: data.registration_mode,
|
registration_mode: data.registration_mode,
|
||||||
community_creation_admin_only: data.community_creation_admin_only,
|
community_creation_admin_only: data.community_creation_admin_only,
|
||||||
require_email_verification: data.require_email_verification,
|
require_email_verification: data.require_email_verification,
|
||||||
|
@ -121,6 +120,10 @@ pub async fn update_site(
|
||||||
reports_email_admins: data.reports_email_admins,
|
reports_email_admins: data.reports_email_admins,
|
||||||
default_post_listing_mode: data.default_post_listing_mode,
|
default_post_listing_mode: data.default_post_listing_mode,
|
||||||
oauth_registration: data.oauth_registration,
|
oauth_registration: data.oauth_registration,
|
||||||
|
post_upvotes: data.post_upvotes,
|
||||||
|
post_downvotes: data.post_downvotes,
|
||||||
|
comment_upvotes: data.comment_upvotes,
|
||||||
|
comment_downvotes: data.comment_downvotes,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use activitypub_federation::{
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{ActivityHandler, Actor},
|
||||||
};
|
};
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::check_bot_account};
|
use lemmy_api_common::{context::LemmyContext, utils::check_bot_account};
|
||||||
use lemmy_db_schema::source::local_site::LocalSite;
|
use lemmy_db_schema::{source::local_site::LocalSite, FederationMode};
|
||||||
use lemmy_utils::error::{LemmyError, LemmyResult};
|
use lemmy_utils::error::{LemmyError, LemmyResult};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -68,12 +68,22 @@ impl ActivityHandler for Vote {
|
||||||
|
|
||||||
check_bot_account(&actor.0)?;
|
check_bot_account(&actor.0)?;
|
||||||
|
|
||||||
let enable_downvotes = LocalSite::read(&mut context.pool())
|
// Check for enabled federation votes
|
||||||
|
let local_site = LocalSite::read(&mut context.pool())
|
||||||
.await
|
.await
|
||||||
.map(|l| l.enable_downvotes)
|
.unwrap_or_default();
|
||||||
.unwrap_or(true);
|
|
||||||
if self.kind == VoteType::Dislike && !enable_downvotes {
|
let (downvote_setting, upvote_setting) = match object {
|
||||||
// If this is a downvote but downvotes are ignored, only undo any existing vote
|
PostOrComment::Post(_) => (local_site.post_downvotes, local_site.post_upvotes),
|
||||||
|
PostOrComment::Comment(_) => (local_site.comment_downvotes, local_site.comment_upvotes),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Don't allow dislikes for either disabled, or local only votes
|
||||||
|
let downvote_fail = self.kind == VoteType::Dislike && downvote_setting != FederationMode::All;
|
||||||
|
let upvote_fail = self.kind == VoteType::Like && upvote_setting != FederationMode::All;
|
||||||
|
|
||||||
|
if downvote_fail || upvote_fail {
|
||||||
|
// If this is a rejection, undo the vote
|
||||||
match object {
|
match object {
|
||||||
PostOrComment::Post(p) => undo_vote_post(actor, &p, context).await,
|
PostOrComment::Post(p) => undo_vote_post(actor, &p, context).await,
|
||||||
PostOrComment::Comment(c) => undo_vote_comment(actor, &c, context).await,
|
PostOrComment::Comment(c) => undo_vote_comment(actor, &c, context).await,
|
||||||
|
|
|
@ -251,6 +251,27 @@ pub enum CommunityVisibility {
|
||||||
LocalOnly,
|
LocalOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, Hash,
|
||||||
|
)]
|
||||||
|
#[cfg_attr(feature = "full", derive(DbEnum, TS))]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "full",
|
||||||
|
ExistingTypePath = "crate::schema::sql_types::FederationModeEnum"
|
||||||
|
)]
|
||||||
|
#[cfg_attr(feature = "full", DbValueStyle = "verbatim")]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// The federation mode for an item
|
||||||
|
pub enum FederationMode {
|
||||||
|
#[default]
|
||||||
|
/// Allows all
|
||||||
|
All,
|
||||||
|
/// Allows only local
|
||||||
|
Local,
|
||||||
|
/// Disables
|
||||||
|
Disable,
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper for assert_eq! macro. Checks that vec matches the given length, and prints the
|
/// Wrapper for assert_eq! macro. Checks that vec matches the given length, and prints the
|
||||||
/// vec on failure.
|
/// vec on failure.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
@ -13,6 +13,10 @@ pub mod sql_types {
|
||||||
#[diesel(postgres_type(name = "community_visibility"))]
|
#[diesel(postgres_type(name = "community_visibility"))]
|
||||||
pub struct CommunityVisibility;
|
pub struct CommunityVisibility;
|
||||||
|
|
||||||
|
#[derive(diesel::sql_types::SqlType)]
|
||||||
|
#[diesel(postgres_type(name = "federation_mode_enum"))]
|
||||||
|
pub struct FederationModeEnum;
|
||||||
|
|
||||||
#[derive(diesel::sql_types::SqlType)]
|
#[derive(diesel::sql_types::SqlType)]
|
||||||
#[diesel(postgres_type(name = "listing_type_enum"))]
|
#[diesel(postgres_type(name = "listing_type_enum"))]
|
||||||
pub struct ListingTypeEnum;
|
pub struct ListingTypeEnum;
|
||||||
|
@ -368,12 +372,12 @@ diesel::table! {
|
||||||
use super::sql_types::PostListingModeEnum;
|
use super::sql_types::PostListingModeEnum;
|
||||||
use super::sql_types::PostSortTypeEnum;
|
use super::sql_types::PostSortTypeEnum;
|
||||||
use super::sql_types::CommentSortTypeEnum;
|
use super::sql_types::CommentSortTypeEnum;
|
||||||
|
use super::sql_types::FederationModeEnum;
|
||||||
|
|
||||||
local_site (id) {
|
local_site (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
site_id -> Int4,
|
site_id -> Int4,
|
||||||
site_setup -> Bool,
|
site_setup -> Bool,
|
||||||
enable_downvotes -> Bool,
|
|
||||||
community_creation_admin_only -> Bool,
|
community_creation_admin_only -> Bool,
|
||||||
require_email_verification -> Bool,
|
require_email_verification -> Bool,
|
||||||
application_question -> Nullable<Text>,
|
application_question -> Nullable<Text>,
|
||||||
|
@ -398,6 +402,10 @@ diesel::table! {
|
||||||
default_post_sort_type -> PostSortTypeEnum,
|
default_post_sort_type -> PostSortTypeEnum,
|
||||||
default_comment_sort_type -> CommentSortTypeEnum,
|
default_comment_sort_type -> CommentSortTypeEnum,
|
||||||
oauth_registration -> Bool,
|
oauth_registration -> Bool,
|
||||||
|
post_upvotes -> FederationModeEnum,
|
||||||
|
post_downvotes -> FederationModeEnum,
|
||||||
|
comment_upvotes -> FederationModeEnum,
|
||||||
|
comment_downvotes -> FederationModeEnum,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::schema::local_site;
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{LocalSiteId, SiteId},
|
newtypes::{LocalSiteId, SiteId},
|
||||||
CommentSortType,
|
CommentSortType,
|
||||||
|
FederationMode,
|
||||||
ListingType,
|
ListingType,
|
||||||
PostListingMode,
|
PostListingMode,
|
||||||
PostSortType,
|
PostSortType,
|
||||||
|
@ -27,8 +28,6 @@ pub struct LocalSite {
|
||||||
pub site_id: SiteId,
|
pub site_id: SiteId,
|
||||||
/// True if the site is set up.
|
/// True if the site is set up.
|
||||||
pub site_setup: bool,
|
pub site_setup: bool,
|
||||||
/// Whether downvotes are enabled.
|
|
||||||
pub enable_downvotes: bool,
|
|
||||||
/// Whether only admins can create communities.
|
/// Whether only admins can create communities.
|
||||||
pub community_creation_admin_only: bool,
|
pub community_creation_admin_only: bool,
|
||||||
/// Whether emails are required.
|
/// Whether emails are required.
|
||||||
|
@ -72,6 +71,14 @@ pub struct LocalSite {
|
||||||
pub default_comment_sort_type: CommentSortType,
|
pub default_comment_sort_type: CommentSortType,
|
||||||
/// Whether or not external auth methods can auto-register users.
|
/// Whether or not external auth methods can auto-register users.
|
||||||
pub oauth_registration: bool,
|
pub oauth_registration: bool,
|
||||||
|
/// What kind of post upvotes your site allows.
|
||||||
|
pub post_upvotes: FederationMode,
|
||||||
|
/// What kind of post downvotes your site allows.
|
||||||
|
pub post_downvotes: FederationMode,
|
||||||
|
/// What kind of comment upvotes your site allows.
|
||||||
|
pub comment_upvotes: FederationMode,
|
||||||
|
/// What kind of comment downvotes your site allows.
|
||||||
|
pub comment_downvotes: FederationMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, derive_new::new)]
|
#[derive(Clone, derive_new::new)]
|
||||||
|
@ -82,8 +89,6 @@ pub struct LocalSiteInsertForm {
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub site_setup: Option<bool>,
|
pub site_setup: Option<bool>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub enable_downvotes: Option<bool>,
|
|
||||||
#[new(default)]
|
|
||||||
pub community_creation_admin_only: Option<bool>,
|
pub community_creation_admin_only: Option<bool>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub require_email_verification: Option<bool>,
|
pub require_email_verification: Option<bool>,
|
||||||
|
@ -114,8 +119,6 @@ pub struct LocalSiteInsertForm {
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub registration_mode: Option<RegistrationMode>,
|
pub registration_mode: Option<RegistrationMode>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub oauth_registration: Option<bool>,
|
|
||||||
#[new(default)]
|
|
||||||
pub reports_email_admins: Option<bool>,
|
pub reports_email_admins: Option<bool>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub federation_signed_fetch: Option<bool>,
|
pub federation_signed_fetch: Option<bool>,
|
||||||
|
@ -125,6 +128,16 @@ pub struct LocalSiteInsertForm {
|
||||||
pub default_post_sort_type: Option<PostSortType>,
|
pub default_post_sort_type: Option<PostSortType>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub default_comment_sort_type: Option<CommentSortType>,
|
pub default_comment_sort_type: Option<CommentSortType>,
|
||||||
|
#[new(default)]
|
||||||
|
pub oauth_registration: Option<bool>,
|
||||||
|
#[new(default)]
|
||||||
|
pub post_upvotes: Option<FederationMode>,
|
||||||
|
#[new(default)]
|
||||||
|
pub post_downvotes: Option<FederationMode>,
|
||||||
|
#[new(default)]
|
||||||
|
pub comment_upvotes: Option<FederationMode>,
|
||||||
|
#[new(default)]
|
||||||
|
pub comment_downvotes: Option<FederationMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
@ -132,7 +145,6 @@ pub struct LocalSiteInsertForm {
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = local_site))]
|
#[cfg_attr(feature = "full", diesel(table_name = local_site))]
|
||||||
pub struct LocalSiteUpdateForm {
|
pub struct LocalSiteUpdateForm {
|
||||||
pub site_setup: Option<bool>,
|
pub site_setup: Option<bool>,
|
||||||
pub enable_downvotes: Option<bool>,
|
|
||||||
pub community_creation_admin_only: Option<bool>,
|
pub community_creation_admin_only: Option<bool>,
|
||||||
pub require_email_verification: Option<bool>,
|
pub require_email_verification: Option<bool>,
|
||||||
pub application_question: Option<Option<String>>,
|
pub application_question: Option<Option<String>>,
|
||||||
|
@ -148,11 +160,15 @@ pub struct LocalSiteUpdateForm {
|
||||||
pub captcha_enabled: Option<bool>,
|
pub captcha_enabled: Option<bool>,
|
||||||
pub captcha_difficulty: Option<String>,
|
pub captcha_difficulty: Option<String>,
|
||||||
pub registration_mode: Option<RegistrationMode>,
|
pub registration_mode: Option<RegistrationMode>,
|
||||||
pub oauth_registration: Option<bool>,
|
|
||||||
pub reports_email_admins: Option<bool>,
|
pub reports_email_admins: Option<bool>,
|
||||||
pub updated: Option<Option<DateTime<Utc>>>,
|
pub updated: Option<Option<DateTime<Utc>>>,
|
||||||
pub federation_signed_fetch: Option<bool>,
|
pub federation_signed_fetch: Option<bool>,
|
||||||
pub default_post_listing_mode: Option<PostListingMode>,
|
pub default_post_listing_mode: Option<PostListingMode>,
|
||||||
pub default_post_sort_type: Option<PostSortType>,
|
pub default_post_sort_type: Option<PostSortType>,
|
||||||
pub default_comment_sort_type: Option<CommentSortType>,
|
pub default_comment_sort_type: Option<CommentSortType>,
|
||||||
|
pub oauth_registration: Option<bool>,
|
||||||
|
pub post_upvotes: Option<FederationMode>,
|
||||||
|
pub post_downvotes: Option<FederationMode>,
|
||||||
|
pub comment_upvotes: Option<FederationMode>,
|
||||||
|
pub comment_downvotes: Option<FederationMode>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub enum LemmyErrorType {
|
||||||
PersonIsBlocked,
|
PersonIsBlocked,
|
||||||
CommunityIsBlocked,
|
CommunityIsBlocked,
|
||||||
InstanceIsBlocked,
|
InstanceIsBlocked,
|
||||||
DownvotesAreDisabled,
|
VoteNotAllowed,
|
||||||
InstanceIsPrivate,
|
InstanceIsPrivate,
|
||||||
/// Password must be between 10 and 60 characters
|
/// Password must be between 10 and 60 characters
|
||||||
InvalidPassword,
|
InvalidPassword,
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
-- Add back the enable_downvotes column
|
||||||
|
ALTER TABLE local_site
|
||||||
|
ADD COLUMN enable_downvotes boolean DEFAULT TRUE NOT NULL;
|
||||||
|
|
||||||
|
-- regenerate their values (from post_downvotes alone)
|
||||||
|
WITH subquery AS (
|
||||||
|
SELECT
|
||||||
|
post_downvotes,
|
||||||
|
CASE WHEN post_downvotes = 'Disable'::federation_mode_enum THEN
|
||||||
|
FALSE
|
||||||
|
ELSE
|
||||||
|
TRUE
|
||||||
|
END
|
||||||
|
FROM
|
||||||
|
local_site)
|
||||||
|
UPDATE
|
||||||
|
local_site
|
||||||
|
SET
|
||||||
|
enable_downvotes = subquery.case
|
||||||
|
FROM
|
||||||
|
subquery;
|
||||||
|
|
||||||
|
-- Drop the new columns
|
||||||
|
ALTER TABLE local_site
|
||||||
|
DROP COLUMN post_upvotes,
|
||||||
|
DROP COLUMN post_downvotes,
|
||||||
|
DROP COLUMN comment_upvotes,
|
||||||
|
DROP COLUMN comment_downvotes;
|
||||||
|
|
||||||
|
DROP TYPE federation_mode_enum;
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
-- This removes the simple enable_downvotes setting, in favor of an
|
||||||
|
-- expanded federation mode type for post/comment up/downvotes.
|
||||||
|
-- Create the federation mode enum
|
||||||
|
CREATE TYPE federation_mode_enum AS ENUM (
|
||||||
|
'All',
|
||||||
|
'Local',
|
||||||
|
'Disable'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Add the new columns
|
||||||
|
ALTER TABLE local_site
|
||||||
|
ADD COLUMN post_upvotes federation_mode_enum DEFAULT 'All'::federation_mode_enum NOT NULL,
|
||||||
|
ADD COLUMN post_downvotes federation_mode_enum DEFAULT 'All'::federation_mode_enum NOT NULL,
|
||||||
|
ADD COLUMN comment_upvotes federation_mode_enum DEFAULT 'All'::federation_mode_enum NOT NULL,
|
||||||
|
ADD COLUMN comment_downvotes federation_mode_enum DEFAULT 'All'::federation_mode_enum NOT NULL;
|
||||||
|
|
||||||
|
-- Copy over the enable_downvotes into the post and comment downvote settings
|
||||||
|
WITH subquery AS (
|
||||||
|
SELECT
|
||||||
|
enable_downvotes,
|
||||||
|
CASE WHEN enable_downvotes = TRUE THEN
|
||||||
|
'All'::federation_mode_enum
|
||||||
|
ELSE
|
||||||
|
'Disable'::federation_mode_enum
|
||||||
|
END
|
||||||
|
FROM
|
||||||
|
local_site)
|
||||||
|
UPDATE
|
||||||
|
local_site
|
||||||
|
SET
|
||||||
|
post_downvotes = subquery.case,
|
||||||
|
comment_downvotes = subquery.case
|
||||||
|
FROM
|
||||||
|
subquery;
|
||||||
|
|
||||||
|
-- Drop the enable_downvotes column
|
||||||
|
ALTER TABLE local_site
|
||||||
|
DROP COLUMN enable_downvotes;
|
||||||
|
|
Loading…
Reference in a new issue