mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-03-13 23:12:40 +00:00
Changes to community visibility (#5478)
* Move community.hidden to visibility (fixes #5458) * fix up migration by dropping index * also add enum variant `LocalOnlyPublic`, rename `LocalOnly` to `LocalOnlyPrivate` fixes #5351 * fix column order in down.sql * wip * more wip * fixes * migration for modlog * fix migration * wip * db_schema compiling * make the code compile * lint * fix down migration * fix test * make hidden status federate * ts attr * fix * fix api test * update api client * review * Extracting filter_not_hidden_or_is_subscribed (#5497) * Extracting filter_not_hidden_or_is_subscribed * Cleanup. * Cleanup 2. * rename hidden to unlisted --------- Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
parent
d93bfdd2fa
commit
8ffeeca52d
39 changed files with 583 additions and 293 deletions
api_tests
crates
api/src/community
api_common/src
api_crud/src/community
apub/src
activities
http
objects
protocol/objects
db_schema
db_views/src
routes/src
utils/src
migrations/2025-03-11-124442_community-hidden-visibility
src
|
@ -29,7 +29,7 @@
|
||||||
"eslint": "^9.20.0",
|
"eslint": "^9.20.0",
|
||||||
"eslint-plugin-prettier": "^5.2.3",
|
"eslint-plugin-prettier": "^5.2.3",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
"lemmy-js-client": "0.20.0-remove-aggregate-tables.5",
|
"lemmy-js-client": "0.20.0-move-community-hidden.3",
|
||||||
"prettier": "^3.5.0",
|
"prettier": "^3.5.0",
|
||||||
"ts-jest": "^29.1.0",
|
"ts-jest": "^29.1.0",
|
||||||
"tsoa": "^6.6.0",
|
"tsoa": "^6.6.0",
|
||||||
|
|
|
@ -33,8 +33,8 @@ importers:
|
||||||
specifier: ^29.5.0
|
specifier: ^29.5.0
|
||||||
version: 29.7.0(@types/node@22.13.1)
|
version: 29.7.0(@types/node@22.13.1)
|
||||||
lemmy-js-client:
|
lemmy-js-client:
|
||||||
specifier: 0.20.0-remove-aggregate-tables.5
|
specifier: 0.20.0-move-community-hidden.3
|
||||||
version: 0.20.0-remove-aggregate-tables.5
|
version: 0.20.0-move-community-hidden.3
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.5.0
|
specifier: ^3.5.0
|
||||||
version: 3.5.0
|
version: 3.5.0
|
||||||
|
@ -1528,8 +1528,8 @@ packages:
|
||||||
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
lemmy-js-client@0.20.0-remove-aggregate-tables.5:
|
lemmy-js-client@0.20.0-move-community-hidden.3:
|
||||||
resolution: {integrity: sha512-A/p4LLWNiVp7fsQOctbFm/biBAunk0FIl5X79WJ/hRu/UiD1M+tCLGYPGdy308R+zscZsDNqECe1LYBenOFzOA==}
|
resolution: {integrity: sha512-X7bbSrnGGgupr//Qk2M1Z9nvFawNU4T116X+4/j912GO6KbQdWN7+10obbQJuoEYr15oCXwSaK8DLusofLxIig==}
|
||||||
|
|
||||||
leven@3.1.0:
|
leven@3.1.0:
|
||||||
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
||||||
|
@ -4169,7 +4169,7 @@ snapshots:
|
||||||
|
|
||||||
kleur@3.0.3: {}
|
kleur@3.0.3: {}
|
||||||
|
|
||||||
lemmy-js-client@0.20.0-remove-aggregate-tables.5: {}
|
lemmy-js-client@0.20.0-move-community-hidden.3: {}
|
||||||
|
|
||||||
leven@3.1.0: {}
|
leven@3.1.0: {}
|
||||||
|
|
||||||
|
|
|
@ -521,7 +521,7 @@ test("Content in local-only community doesn't federate", async () => {
|
||||||
let communityRes = (await createCommunity(alpha)).community_view.community;
|
let communityRes = (await createCommunity(alpha)).community_view.community;
|
||||||
let form: EditCommunity = {
|
let form: EditCommunity = {
|
||||||
community_id: communityRes.id,
|
community_id: communityRes.id,
|
||||||
visibility: "LocalOnly",
|
visibility: "LocalOnlyPublic",
|
||||||
};
|
};
|
||||||
await editCommunity(alpha, form);
|
await editCommunity(alpha, form);
|
||||||
|
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
use activitypub_federation::config::Data;
|
|
||||||
use actix_web::web::Json;
|
|
||||||
use lemmy_api_common::{
|
|
||||||
community::HideCommunity,
|
|
||||||
context::LemmyContext,
|
|
||||||
send_activity::{ActivityChannel, SendActivityData},
|
|
||||||
utils::is_admin,
|
|
||||||
SuccessResponse,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
source::{
|
|
||||||
community::{Community, CommunityUpdateForm},
|
|
||||||
mod_log::moderator::{ModHideCommunity, ModHideCommunityForm},
|
|
||||||
},
|
|
||||||
traits::Crud,
|
|
||||||
};
|
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
|
||||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
|
||||||
|
|
||||||
pub async fn hide_community(
|
|
||||||
data: Json<HideCommunity>,
|
|
||||||
context: Data<LemmyContext>,
|
|
||||||
local_user_view: LocalUserView,
|
|
||||||
) -> LemmyResult<Json<SuccessResponse>> {
|
|
||||||
// Verify its a admin (only admin can hide or unhide it)
|
|
||||||
is_admin(&local_user_view)?;
|
|
||||||
|
|
||||||
let community_form = CommunityUpdateForm {
|
|
||||||
hidden: Some(data.hidden),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mod_hide_community_form = ModHideCommunityForm {
|
|
||||||
community_id: data.community_id,
|
|
||||||
mod_person_id: local_user_view.person.id,
|
|
||||||
reason: data.reason.clone(),
|
|
||||||
hidden: Some(data.hidden),
|
|
||||||
};
|
|
||||||
|
|
||||||
let community_id = data.community_id;
|
|
||||||
let community = Community::update(&mut context.pool(), community_id, &community_form)
|
|
||||||
.await
|
|
||||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateCommunityHiddenStatus)?;
|
|
||||||
|
|
||||||
ModHideCommunity::create(&mut context.pool(), &mod_hide_community_form).await?;
|
|
||||||
|
|
||||||
ActivityChannel::submit_activity(
|
|
||||||
SendActivityData::UpdateCommunity(local_user_view.person.clone(), community),
|
|
||||||
&context,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(Json(SuccessResponse::default()))
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ pub mod add_mod;
|
||||||
pub mod ban;
|
pub mod ban;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod follow;
|
pub mod follow;
|
||||||
pub mod hide;
|
|
||||||
pub mod pending_follows;
|
pub mod pending_follows;
|
||||||
pub mod random;
|
pub mod random;
|
||||||
pub mod transfer;
|
pub mod transfer;
|
||||||
|
|
|
@ -44,7 +44,6 @@ use lemmy_db_schema::{
|
||||||
},
|
},
|
||||||
traits::{Crud, Likeable},
|
traits::{Crud, Likeable},
|
||||||
utils::DbPool,
|
utils::DbPool,
|
||||||
CommunityVisibility,
|
|
||||||
FederationMode,
|
FederationMode,
|
||||||
RegistrationMode,
|
RegistrationMode,
|
||||||
};
|
};
|
||||||
|
@ -1190,7 +1189,7 @@ pub fn read_auth_token(req: &HttpRequest) -> LemmyResult<Option<String>> {
|
||||||
|
|
||||||
pub fn send_webmention(post: Post, community: Community) {
|
pub fn send_webmention(post: Post, community: Community) {
|
||||||
if let Some(url) = post.url.clone() {
|
if let Some(url) = post.url.clone() {
|
||||||
if community.visibility == CommunityVisibility::Public {
|
if community.visibility.can_view_without_login() {
|
||||||
spawn_try_task(async move {
|
spawn_try_task(async move {
|
||||||
let mut webmention = Webmention::new::<Url>(post.ap_id.clone().into(), url.clone().into())?;
|
let mut webmention = Webmention::new::<Url>(post.ap_id.clone().into(), url.clone().into())?;
|
||||||
webmention.set_checked(true);
|
webmention.set_checked(true);
|
||||||
|
|
|
@ -9,13 +9,15 @@ pub mod list;
|
||||||
pub mod remove;
|
pub mod remove;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
|
|
||||||
/// For now only admins can make communities private, in order to prevent abuse.
|
/// For now only admins can make communities private or hidden, in order to
|
||||||
/// Need to implement admin approval for new communities to get rid of this.
|
/// prevent abuse. Need to implement admin approval for new communities to
|
||||||
|
/// get rid of this.
|
||||||
fn check_community_visibility_allowed(
|
fn check_community_visibility_allowed(
|
||||||
visibility: Option<CommunityVisibility>,
|
visibility: Option<CommunityVisibility>,
|
||||||
local_user_view: &LocalUserView,
|
local_user_view: &LocalUserView,
|
||||||
) -> LemmyResult<()> {
|
) -> LemmyResult<()> {
|
||||||
if visibility == Some(lemmy_db_schema::CommunityVisibility::Private) {
|
use CommunityVisibility::*;
|
||||||
|
if visibility == Some(Private) || visibility == Some(Unlisted) {
|
||||||
is_admin(local_user_view)?;
|
is_admin(local_user_view)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -23,10 +23,7 @@ use activitypub_federation::{
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{ActivityHandler, Actor},
|
||||||
};
|
};
|
||||||
use lemmy_api_common::context::LemmyContext;
|
use lemmy_api_common::context::LemmyContext;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::source::{activity::ActivitySendTargets, community::CommunityFollower};
|
||||||
source::{activity::ActivitySendTargets, community::CommunityFollower},
|
|
||||||
CommunityVisibility,
|
|
||||||
};
|
|
||||||
use lemmy_utils::error::{FederationError, LemmyError, LemmyErrorType, LemmyResult};
|
use lemmy_utils::error::{FederationError, LemmyError, LemmyErrorType, LemmyResult};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -211,7 +208,7 @@ async fn can_accept_activity_in_community(
|
||||||
) -> LemmyResult<()> {
|
) -> LemmyResult<()> {
|
||||||
if let Some(community) = community {
|
if let Some(community) = community {
|
||||||
// Local only community can't federate
|
// Local only community can't federate
|
||||||
if community.visibility == CommunityVisibility::LocalOnly {
|
if !community.visibility.can_federate() {
|
||||||
return Err(LemmyErrorType::NotFound.into());
|
return Err(LemmyErrorType::NotFound.into());
|
||||||
}
|
}
|
||||||
if !community.local {
|
if !community.local {
|
||||||
|
|
|
@ -14,7 +14,6 @@ use lemmy_db_schema::{
|
||||||
site::Site,
|
site::Site,
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
CommunityVisibility,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::CommunityModeratorView;
|
use lemmy_db_views::structs::CommunityModeratorView;
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
@ -50,7 +49,7 @@ pub(crate) async fn send_activity_in_community(
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
) -> LemmyResult<()> {
|
) -> LemmyResult<()> {
|
||||||
// If community is local only, don't send anything out
|
// If community is local only, don't send anything out
|
||||||
if community.visibility == CommunityVisibility::LocalOnly {
|
if !community.visibility.can_federate() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ impl ActivityHandler for Follow {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, context: &Data<LemmyContext>) -> LemmyResult<()> {
|
async fn receive(self, context: &Data<LemmyContext>) -> LemmyResult<()> {
|
||||||
|
use CommunityVisibility::*;
|
||||||
insert_received_activity(&self.id, context).await?;
|
insert_received_activity(&self.id, context).await?;
|
||||||
let actor = self.actor.dereference(context).await?;
|
let actor = self.actor.dereference(context).await?;
|
||||||
let object = self.object.dereference(context).await?;
|
let object = self.object.dereference(context).await?;
|
||||||
|
@ -111,10 +112,10 @@ impl ActivityHandler for Follow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let state = Some(match c.visibility {
|
let state = Some(match c.visibility {
|
||||||
CommunityVisibility::Public => CommunityFollowerState::Accepted,
|
Public | Unlisted => CommunityFollowerState::Accepted,
|
||||||
CommunityVisibility::Private => CommunityFollowerState::ApprovalRequired,
|
Private => CommunityFollowerState::ApprovalRequired,
|
||||||
// Dont allow following local-only community via federation.
|
// Dont allow following local-only community via federation.
|
||||||
CommunityVisibility::LocalOnly => return Err(LemmyErrorType::NotFound.into()),
|
LocalOnlyPrivate | LocalOnlyPublic => return Err(LemmyErrorType::NotFound.into()),
|
||||||
});
|
});
|
||||||
let form = CommunityFollowerForm {
|
let form = CommunityFollowerForm {
|
||||||
state,
|
state,
|
||||||
|
|
|
@ -125,9 +125,8 @@ pub(crate) fn verify_visibility(to: &[Url], cc: &[Url], community: &Community) -
|
||||||
use CommunityVisibility::*;
|
use CommunityVisibility::*;
|
||||||
let object_is_public = [to, cc].iter().any(|set| set.contains(&public()));
|
let object_is_public = [to, cc].iter().any(|set| set.contains(&public()));
|
||||||
match community.visibility {
|
match community.visibility {
|
||||||
Public if !object_is_public => Err(FederationError::ObjectIsNotPublic)?,
|
Public | Unlisted if !object_is_public => Err(FederationError::ObjectIsNotPublic)?,
|
||||||
Private if object_is_public => Err(FederationError::ObjectIsNotPrivate)?,
|
Private if object_is_public => Err(FederationError::ObjectIsNotPrivate)?,
|
||||||
LocalOnly => Err(LemmyErrorType::NotFound.into()),
|
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,7 @@ pub(crate) mod tests {
|
||||||
#[serial]
|
#[serial]
|
||||||
async fn test_get_deleted_community() -> LemmyResult<()> {
|
async fn test_get_deleted_community() -> LemmyResult<()> {
|
||||||
let context = LemmyContext::init_test_context().await;
|
let context = LemmyContext::init_test_context().await;
|
||||||
let (instance, _, path) = init(true, CommunityVisibility::LocalOnly, &context).await?;
|
let (instance, _, path) = init(true, CommunityVisibility::Public, &context).await?;
|
||||||
let request = TestRequest::default().to_http_request();
|
let request = TestRequest::default().to_http_request();
|
||||||
|
|
||||||
// should return tombstone
|
// should return tombstone
|
||||||
|
@ -320,7 +320,7 @@ pub(crate) mod tests {
|
||||||
#[serial]
|
#[serial]
|
||||||
async fn test_get_local_only_community() -> LemmyResult<()> {
|
async fn test_get_local_only_community() -> LemmyResult<()> {
|
||||||
let context = LemmyContext::init_test_context().await;
|
let context = LemmyContext::init_test_context().await;
|
||||||
let (instance, _, path) = init(false, CommunityVisibility::LocalOnly, &context).await?;
|
let (instance, _, path) = init(false, CommunityVisibility::LocalOnlyPrivate, &context).await?;
|
||||||
let request = TestRequest::default().to_http_request();
|
let request = TestRequest::default().to_http_request();
|
||||||
|
|
||||||
let res = get_apub_community_http(path.clone().into(), context.reset_request_count()).await;
|
let res = get_apub_community_http(path.clone().into(), context.reset_request_count()).await;
|
||||||
|
|
|
@ -122,7 +122,7 @@ pub(crate) async fn get_activity(
|
||||||
/// Ensure that the community is public and not removed/deleted.
|
/// Ensure that the community is public and not removed/deleted.
|
||||||
fn check_community_fetchable(community: &Community) -> LemmyResult<()> {
|
fn check_community_fetchable(community: &Community) -> LemmyResult<()> {
|
||||||
check_community_removed_or_deleted(community)?;
|
check_community_removed_or_deleted(community)?;
|
||||||
if community.visibility == CommunityVisibility::LocalOnly {
|
if !community.visibility.can_federate() {
|
||||||
return Err(LemmyErrorType::NotFound.into());
|
return Err(LemmyErrorType::NotFound.into());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -137,12 +137,7 @@ async fn check_community_content_fetchable(
|
||||||
use CommunityVisibility::*;
|
use CommunityVisibility::*;
|
||||||
check_community_removed_or_deleted(community)?;
|
check_community_removed_or_deleted(community)?;
|
||||||
match community.visibility {
|
match community.visibility {
|
||||||
// content in public community can always be fetched
|
Public | Unlisted => Ok(()),
|
||||||
Public => Ok(()),
|
|
||||||
// no federation for local only community
|
|
||||||
LocalOnly => Err(LemmyErrorType::NotFound.into()),
|
|
||||||
// for private community check http signature of request, if there is any approved follower
|
|
||||||
// from the fetching instance then fetching is allowed
|
|
||||||
Private => {
|
Private => {
|
||||||
let signing_actor = signing_actor::<SiteOrCommunityOrUser>(request, None, context).await?;
|
let signing_actor = signing_actor::<SiteOrCommunityOrUser>(request, None, context).await?;
|
||||||
if community.local {
|
if community.local {
|
||||||
|
@ -167,6 +162,7 @@ async fn check_community_content_fetchable(
|
||||||
Err(LemmyErrorType::NotFound.into())
|
Err(LemmyErrorType::NotFound.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LocalOnlyPublic | LocalOnlyPrivate => Err(LemmyErrorType::NotFound.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@ impl Object for ApubCommunity {
|
||||||
posting_restricted_to_mods: Some(self.posting_restricted_to_mods),
|
posting_restricted_to_mods: Some(self.posting_restricted_to_mods),
|
||||||
attributed_to: Some(generate_moderators_url(&self.ap_id)?.into()),
|
attributed_to: Some(generate_moderators_url(&self.ap_id)?.into()),
|
||||||
manually_approves_followers: Some(self.visibility == CommunityVisibility::Private),
|
manually_approves_followers: Some(self.visibility == CommunityVisibility::Private),
|
||||||
|
discoverable: Some(self.visibility != CommunityVisibility::Unlisted),
|
||||||
};
|
};
|
||||||
Ok(group)
|
Ok(group)
|
||||||
}
|
}
|
||||||
|
@ -148,6 +149,8 @@ impl Object for ApubCommunity {
|
||||||
let banner = proxy_image_link_opt_apub(group.image.map(|i| i.url), context).await?;
|
let banner = proxy_image_link_opt_apub(group.image.map(|i| i.url), context).await?;
|
||||||
let visibility = Some(if group.manually_approves_followers.unwrap_or_default() {
|
let visibility = Some(if group.manually_approves_followers.unwrap_or_default() {
|
||||||
CommunityVisibility::Private
|
CommunityVisibility::Private
|
||||||
|
} else if !group.discoverable.unwrap_or(true) {
|
||||||
|
CommunityVisibility::Unlisted
|
||||||
} else {
|
} else {
|
||||||
CommunityVisibility::Public
|
CommunityVisibility::Public
|
||||||
});
|
});
|
||||||
|
|
|
@ -77,6 +77,8 @@ pub struct Group {
|
||||||
pub(crate) manually_approves_followers: Option<bool>,
|
pub(crate) manually_approves_followers: Option<bool>,
|
||||||
pub(crate) published: Option<DateTime<Utc>>,
|
pub(crate) published: Option<DateTime<Utc>>,
|
||||||
pub(crate) updated: Option<DateTime<Utc>>,
|
pub(crate) updated: Option<DateTime<Utc>>,
|
||||||
|
/// https://docs.joinmastodon.org/spec/activitypub/#discoverable
|
||||||
|
pub(crate) discoverable: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Group {
|
impl Group {
|
||||||
|
|
|
@ -595,7 +595,7 @@ CALL r.create_person_saved_combined_trigger ('comment');
|
||||||
-- mod_ban
|
-- mod_ban
|
||||||
-- mod_ban_from_community
|
-- mod_ban_from_community
|
||||||
-- mod_feature_post
|
-- mod_feature_post
|
||||||
-- mod_hide_community
|
-- mod_change_community_visibility
|
||||||
-- mod_lock_post
|
-- mod_lock_post
|
||||||
-- mod_remove_comment
|
-- mod_remove_comment
|
||||||
-- mod_remove_community
|
-- mod_remove_community
|
||||||
|
@ -646,7 +646,7 @@ CALL r.create_modlog_combined_trigger ('mod_ban_from_community');
|
||||||
|
|
||||||
CALL r.create_modlog_combined_trigger ('mod_feature_post');
|
CALL r.create_modlog_combined_trigger ('mod_feature_post');
|
||||||
|
|
||||||
CALL r.create_modlog_combined_trigger ('mod_hide_community');
|
CALL r.create_modlog_combined_trigger ('mod_change_community_visibility');
|
||||||
|
|
||||||
CALL r.create_modlog_combined_trigger ('mod_lock_post');
|
CALL r.create_modlog_combined_trigger ('mod_lock_post');
|
||||||
|
|
||||||
|
|
|
@ -634,7 +634,6 @@ mod tests {
|
||||||
inbox_url: inserted_community.inbox_url.clone(),
|
inbox_url: inserted_community.inbox_url.clone(),
|
||||||
moderators_url: None,
|
moderators_url: None,
|
||||||
featured_url: None,
|
featured_url: None,
|
||||||
hidden: false,
|
|
||||||
posting_restricted_to_mods: false,
|
posting_restricted_to_mods: false,
|
||||||
instance_id: inserted_instance.id,
|
instance_id: inserted_instance.id,
|
||||||
visibility: CommunityVisibility::Public,
|
visibility: CommunityVisibility::Public,
|
||||||
|
|
|
@ -4,8 +4,8 @@ use crate::{
|
||||||
ModAddId,
|
ModAddId,
|
||||||
ModBanFromCommunityId,
|
ModBanFromCommunityId,
|
||||||
ModBanId,
|
ModBanId,
|
||||||
|
ModChangeCommunityVisibilityId,
|
||||||
ModFeaturePostId,
|
ModFeaturePostId,
|
||||||
ModHideCommunityId,
|
|
||||||
ModLockPostId,
|
ModLockPostId,
|
||||||
ModRemoveCommentId,
|
ModRemoveCommentId,
|
||||||
ModRemoveCommunityId,
|
ModRemoveCommunityId,
|
||||||
|
@ -17,8 +17,8 @@ use crate::{
|
||||||
mod_add_community,
|
mod_add_community,
|
||||||
mod_ban,
|
mod_ban,
|
||||||
mod_ban_from_community,
|
mod_ban_from_community,
|
||||||
|
mod_change_community_visibility,
|
||||||
mod_feature_post,
|
mod_feature_post,
|
||||||
mod_hide_community,
|
|
||||||
mod_lock_post,
|
mod_lock_post,
|
||||||
mod_remove_comment,
|
mod_remove_comment,
|
||||||
mod_remove_community,
|
mod_remove_community,
|
||||||
|
@ -34,10 +34,10 @@ use crate::{
|
||||||
ModBanForm,
|
ModBanForm,
|
||||||
ModBanFromCommunity,
|
ModBanFromCommunity,
|
||||||
ModBanFromCommunityForm,
|
ModBanFromCommunityForm,
|
||||||
|
ModChangeCommunityVisibility,
|
||||||
|
ModChangeCommunityVisibilityForm,
|
||||||
ModFeaturePost,
|
ModFeaturePost,
|
||||||
ModFeaturePostForm,
|
ModFeaturePostForm,
|
||||||
ModHideCommunity,
|
|
||||||
ModHideCommunityForm,
|
|
||||||
ModLockPost,
|
ModLockPost,
|
||||||
ModLockPostForm,
|
ModLockPostForm,
|
||||||
ModRemoveComment,
|
ModRemoveComment,
|
||||||
|
@ -263,14 +263,14 @@ impl Crud for ModBan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud for ModHideCommunity {
|
impl Crud for ModChangeCommunityVisibility {
|
||||||
type InsertForm = ModHideCommunityForm;
|
type InsertForm = ModChangeCommunityVisibilityForm;
|
||||||
type UpdateForm = ModHideCommunityForm;
|
type UpdateForm = ModChangeCommunityVisibilityForm;
|
||||||
type IdType = ModHideCommunityId;
|
type IdType = ModChangeCommunityVisibilityId;
|
||||||
|
|
||||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
insert_into(mod_hide_community::table)
|
insert_into(mod_change_community_visibility::table)
|
||||||
.values(form)
|
.values(form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
|
@ -282,7 +282,7 @@ impl Crud for ModHideCommunity {
|
||||||
form: &Self::UpdateForm,
|
form: &Self::UpdateForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::update(mod_hide_community::table.find(from_id))
|
diesel::update(mod_change_community_visibility::table.find(from_id))
|
||||||
.set(form)
|
.set(form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -205,7 +205,7 @@ pub enum ModlogActionType {
|
||||||
ModTransferCommunity,
|
ModTransferCommunity,
|
||||||
ModAdd,
|
ModAdd,
|
||||||
ModBan,
|
ModBan,
|
||||||
ModHideCommunity,
|
ModChangeCommunityVisibility,
|
||||||
AdminPurgePerson,
|
AdminPurgePerson,
|
||||||
AdminPurgeCommunity,
|
AdminPurgeCommunity,
|
||||||
AdminPurgePost,
|
AdminPurgePost,
|
||||||
|
@ -277,12 +277,28 @@ pub enum CommunityVisibility {
|
||||||
/// Public community, any local or federated user can interact.
|
/// Public community, any local or federated user can interact.
|
||||||
#[default]
|
#[default]
|
||||||
Public,
|
Public,
|
||||||
/// Unfederated community, only local users can interact.
|
/// Community is hidden and doesn't appear in community list. Post from the community
|
||||||
LocalOnly,
|
/// are not shown in Local and All feeds, except for subscribed users.
|
||||||
|
Unlisted,
|
||||||
|
/// Unfederated community, only local users can interact (with or without login).
|
||||||
|
LocalOnlyPublic,
|
||||||
|
/// Unfederated community, only logged-in local users can interact.
|
||||||
|
LocalOnlyPrivate,
|
||||||
/// Users need to be approved by mods before they are able to browse or post.
|
/// Users need to be approved by mods before they are able to browse or post.
|
||||||
Private,
|
Private,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CommunityVisibility {
|
||||||
|
pub fn can_federate(&self) -> bool {
|
||||||
|
use CommunityVisibility::*;
|
||||||
|
self != &LocalOnlyPublic && self != &LocalOnlyPrivate
|
||||||
|
}
|
||||||
|
pub fn can_view_without_login(&self) -> bool {
|
||||||
|
use CommunityVisibility::*;
|
||||||
|
self == &Public || self == &LocalOnlyPublic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, Hash,
|
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, Hash,
|
||||||
)]
|
)]
|
||||||
|
|
|
@ -295,7 +295,7 @@ pub struct ModBanId(pub i32);
|
||||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||||
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
pub struct ModHideCommunityId(pub i32);
|
pub struct ModChangeCommunityVisibilityId(pub i32);
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||||
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
||||||
|
|
|
@ -204,7 +204,6 @@ diesel::table! {
|
||||||
followers_url -> Nullable<Varchar>,
|
followers_url -> Nullable<Varchar>,
|
||||||
#[max_length = 255]
|
#[max_length = 255]
|
||||||
inbox_url -> Varchar,
|
inbox_url -> Varchar,
|
||||||
hidden -> Bool,
|
|
||||||
posting_restricted_to_mods -> Bool,
|
posting_restricted_to_mods -> Bool,
|
||||||
instance_id -> Int4,
|
instance_id -> Int4,
|
||||||
#[max_length = 255]
|
#[max_length = 255]
|
||||||
|
@ -435,6 +434,7 @@ diesel::table! {
|
||||||
comment_downvotes -> FederationModeEnum,
|
comment_downvotes -> FederationModeEnum,
|
||||||
disable_donation_dialog -> Bool,
|
disable_donation_dialog -> Bool,
|
||||||
default_post_time_range_seconds -> Nullable<Int4>,
|
default_post_time_range_seconds -> Nullable<Int4>,
|
||||||
|
disallow_nsfw_content -> Bool,
|
||||||
users -> Int8,
|
users -> Int8,
|
||||||
posts -> Int8,
|
posts -> Int8,
|
||||||
comments -> Int8,
|
comments -> Int8,
|
||||||
|
@ -443,7 +443,6 @@ diesel::table! {
|
||||||
users_active_week -> Int8,
|
users_active_week -> Int8,
|
||||||
users_active_month -> Int8,
|
users_active_month -> Int8,
|
||||||
users_active_half_year -> Int8,
|
users_active_half_year -> Int8,
|
||||||
disallow_nsfw_content -> Bool,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,6 +587,20 @@ diesel::table! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
use diesel::sql_types::*;
|
||||||
|
use super::sql_types::CommunityVisibility;
|
||||||
|
|
||||||
|
mod_change_community_visibility (id) {
|
||||||
|
id -> Int4,
|
||||||
|
community_id -> Int4,
|
||||||
|
mod_person_id -> Int4,
|
||||||
|
published -> Timestamptz,
|
||||||
|
reason -> Nullable<Text>,
|
||||||
|
visibility -> CommunityVisibility,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
mod_feature_post (id) {
|
mod_feature_post (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
|
@ -599,17 +612,6 @@ diesel::table! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diesel::table! {
|
|
||||||
mod_hide_community (id) {
|
|
||||||
id -> Int4,
|
|
||||||
community_id -> Int4,
|
|
||||||
mod_person_id -> Int4,
|
|
||||||
published -> Timestamptz,
|
|
||||||
reason -> Nullable<Text>,
|
|
||||||
hidden -> Bool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
mod_lock_post (id) {
|
mod_lock_post (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
|
@ -678,12 +680,12 @@ diesel::table! {
|
||||||
mod_ban_id -> Nullable<Int4>,
|
mod_ban_id -> Nullable<Int4>,
|
||||||
mod_ban_from_community_id -> Nullable<Int4>,
|
mod_ban_from_community_id -> Nullable<Int4>,
|
||||||
mod_feature_post_id -> Nullable<Int4>,
|
mod_feature_post_id -> Nullable<Int4>,
|
||||||
mod_hide_community_id -> Nullable<Int4>,
|
|
||||||
mod_lock_post_id -> Nullable<Int4>,
|
mod_lock_post_id -> Nullable<Int4>,
|
||||||
mod_remove_comment_id -> Nullable<Int4>,
|
mod_remove_comment_id -> Nullable<Int4>,
|
||||||
mod_remove_community_id -> Nullable<Int4>,
|
mod_remove_community_id -> Nullable<Int4>,
|
||||||
mod_remove_post_id -> Nullable<Int4>,
|
mod_remove_post_id -> Nullable<Int4>,
|
||||||
mod_transfer_community_id -> Nullable<Int4>,
|
mod_transfer_community_id -> Nullable<Int4>,
|
||||||
|
mod_change_community_visibility_id -> Nullable<Int4>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,10 +1109,10 @@ diesel::joinable!(local_user_language -> local_user (local_user_id));
|
||||||
diesel::joinable!(login_token -> local_user (user_id));
|
diesel::joinable!(login_token -> local_user (user_id));
|
||||||
diesel::joinable!(mod_add_community -> community (community_id));
|
diesel::joinable!(mod_add_community -> community (community_id));
|
||||||
diesel::joinable!(mod_ban_from_community -> community (community_id));
|
diesel::joinable!(mod_ban_from_community -> community (community_id));
|
||||||
|
diesel::joinable!(mod_change_community_visibility -> community (community_id));
|
||||||
|
diesel::joinable!(mod_change_community_visibility -> person (mod_person_id));
|
||||||
diesel::joinable!(mod_feature_post -> person (mod_person_id));
|
diesel::joinable!(mod_feature_post -> person (mod_person_id));
|
||||||
diesel::joinable!(mod_feature_post -> post (post_id));
|
diesel::joinable!(mod_feature_post -> post (post_id));
|
||||||
diesel::joinable!(mod_hide_community -> community (community_id));
|
|
||||||
diesel::joinable!(mod_hide_community -> person (mod_person_id));
|
|
||||||
diesel::joinable!(mod_lock_post -> person (mod_person_id));
|
diesel::joinable!(mod_lock_post -> person (mod_person_id));
|
||||||
diesel::joinable!(mod_lock_post -> post (post_id));
|
diesel::joinable!(mod_lock_post -> post (post_id));
|
||||||
diesel::joinable!(mod_remove_comment -> comment (comment_id));
|
diesel::joinable!(mod_remove_comment -> comment (comment_id));
|
||||||
|
@ -1130,8 +1132,8 @@ diesel::joinable!(modlog_combined -> mod_add (mod_add_id));
|
||||||
diesel::joinable!(modlog_combined -> mod_add_community (mod_add_community_id));
|
diesel::joinable!(modlog_combined -> mod_add_community (mod_add_community_id));
|
||||||
diesel::joinable!(modlog_combined -> mod_ban (mod_ban_id));
|
diesel::joinable!(modlog_combined -> mod_ban (mod_ban_id));
|
||||||
diesel::joinable!(modlog_combined -> mod_ban_from_community (mod_ban_from_community_id));
|
diesel::joinable!(modlog_combined -> mod_ban_from_community (mod_ban_from_community_id));
|
||||||
|
diesel::joinable!(modlog_combined -> mod_change_community_visibility (mod_change_community_visibility_id));
|
||||||
diesel::joinable!(modlog_combined -> mod_feature_post (mod_feature_post_id));
|
diesel::joinable!(modlog_combined -> mod_feature_post (mod_feature_post_id));
|
||||||
diesel::joinable!(modlog_combined -> mod_hide_community (mod_hide_community_id));
|
|
||||||
diesel::joinable!(modlog_combined -> mod_lock_post (mod_lock_post_id));
|
diesel::joinable!(modlog_combined -> mod_lock_post (mod_lock_post_id));
|
||||||
diesel::joinable!(modlog_combined -> mod_remove_comment (mod_remove_comment_id));
|
diesel::joinable!(modlog_combined -> mod_remove_comment (mod_remove_comment_id));
|
||||||
diesel::joinable!(modlog_combined -> mod_remove_community (mod_remove_community_id));
|
diesel::joinable!(modlog_combined -> mod_remove_community (mod_remove_community_id));
|
||||||
|
@ -1214,8 +1216,8 @@ diesel::allow_tables_to_appear_in_same_query!(
|
||||||
mod_add_community,
|
mod_add_community,
|
||||||
mod_ban,
|
mod_ban,
|
||||||
mod_ban_from_community,
|
mod_ban_from_community,
|
||||||
|
mod_change_community_visibility,
|
||||||
mod_feature_post,
|
mod_feature_post,
|
||||||
mod_hide_community,
|
|
||||||
mod_lock_post,
|
mod_lock_post,
|
||||||
mod_remove_comment,
|
mod_remove_comment,
|
||||||
mod_remove_community,
|
mod_remove_community,
|
||||||
|
|
|
@ -9,8 +9,8 @@ use crate::newtypes::{
|
||||||
ModAddId,
|
ModAddId,
|
||||||
ModBanFromCommunityId,
|
ModBanFromCommunityId,
|
||||||
ModBanId,
|
ModBanId,
|
||||||
|
ModChangeCommunityVisibilityId,
|
||||||
ModFeaturePostId,
|
ModFeaturePostId,
|
||||||
ModHideCommunityId,
|
|
||||||
ModLockPostId,
|
ModLockPostId,
|
||||||
ModRemoveCommentId,
|
ModRemoveCommentId,
|
||||||
ModRemoveCommunityId,
|
ModRemoveCommunityId,
|
||||||
|
@ -48,7 +48,7 @@ pub struct ModlogCombined {
|
||||||
pub mod_ban_id: Option<ModBanId>,
|
pub mod_ban_id: Option<ModBanId>,
|
||||||
pub mod_ban_from_community_id: Option<ModBanFromCommunityId>,
|
pub mod_ban_from_community_id: Option<ModBanFromCommunityId>,
|
||||||
pub mod_feature_post_id: Option<ModFeaturePostId>,
|
pub mod_feature_post_id: Option<ModFeaturePostId>,
|
||||||
pub mod_hide_community_id: Option<ModHideCommunityId>,
|
pub mod_change_community_visibility_id: Option<ModChangeCommunityVisibilityId>,
|
||||||
pub mod_lock_post_id: Option<ModLockPostId>,
|
pub mod_lock_post_id: Option<ModLockPostId>,
|
||||||
pub mod_remove_comment_id: Option<ModRemoveCommentId>,
|
pub mod_remove_comment_id: Option<ModRemoveCommentId>,
|
||||||
pub mod_remove_community_id: Option<ModRemoveCommunityId>,
|
pub mod_remove_community_id: Option<ModRemoveCommunityId>,
|
||||||
|
|
|
@ -61,8 +61,6 @@ pub struct Community {
|
||||||
#[cfg_attr(feature = "full", ts(skip))]
|
#[cfg_attr(feature = "full", ts(skip))]
|
||||||
#[serde(skip, default = "placeholder_apub_url")]
|
#[serde(skip, default = "placeholder_apub_url")]
|
||||||
pub inbox_url: DbUrl,
|
pub inbox_url: DbUrl,
|
||||||
/// Whether the community is hidden.
|
|
||||||
pub hidden: bool,
|
|
||||||
/// Whether posting is restricted to mods only.
|
/// Whether posting is restricted to mods only.
|
||||||
pub posting_restricted_to_mods: bool,
|
pub posting_restricted_to_mods: bool,
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
|
@ -140,8 +138,6 @@ pub struct CommunityInsertForm {
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub featured_url: Option<DbUrl>,
|
pub featured_url: Option<DbUrl>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub hidden: Option<bool>,
|
|
||||||
#[new(default)]
|
|
||||||
pub posting_restricted_to_mods: Option<bool>,
|
pub posting_restricted_to_mods: Option<bool>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub visibility: Option<CommunityVisibility>,
|
pub visibility: Option<CommunityVisibility>,
|
||||||
|
@ -171,7 +167,6 @@ pub struct CommunityUpdateForm {
|
||||||
pub inbox_url: Option<DbUrl>,
|
pub inbox_url: Option<DbUrl>,
|
||||||
pub moderators_url: Option<DbUrl>,
|
pub moderators_url: Option<DbUrl>,
|
||||||
pub featured_url: Option<DbUrl>,
|
pub featured_url: Option<DbUrl>,
|
||||||
pub hidden: Option<bool>,
|
|
||||||
pub posting_restricted_to_mods: Option<bool>,
|
pub posting_restricted_to_mods: Option<bool>,
|
||||||
pub visibility: Option<CommunityVisibility>,
|
pub visibility: Option<CommunityVisibility>,
|
||||||
pub description: Option<Option<String>>,
|
pub description: Option<Option<String>>,
|
||||||
|
|
|
@ -89,6 +89,8 @@ pub struct LocalSite {
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
/// A default time range limit to apply to post sorts, in seconds.
|
/// A default time range limit to apply to post sorts, in seconds.
|
||||||
pub default_post_time_range_seconds: Option<i32>,
|
pub default_post_time_range_seconds: Option<i32>,
|
||||||
|
/// Block NSFW content being created
|
||||||
|
pub disallow_nsfw_content: bool,
|
||||||
pub users: i64,
|
pub users: i64,
|
||||||
pub posts: i64,
|
pub posts: i64,
|
||||||
pub comments: i64,
|
pub comments: i64,
|
||||||
|
@ -101,8 +103,6 @@ pub struct LocalSite {
|
||||||
pub users_active_month: i64,
|
pub users_active_month: i64,
|
||||||
/// The number of users with any activity in the last half year.
|
/// The number of users with any activity in the last half year.
|
||||||
pub users_active_half_year: i64,
|
pub users_active_half_year: i64,
|
||||||
/// Block NSFW content being created
|
|
||||||
pub disallow_nsfw_content: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, derive_new::new)]
|
#[derive(Clone, derive_new::new)]
|
||||||
|
|
|
@ -1,34 +1,37 @@
|
||||||
use crate::newtypes::{
|
|
||||||
CommentId,
|
|
||||||
CommunityId,
|
|
||||||
ModAddCommunityId,
|
|
||||||
ModAddId,
|
|
||||||
ModBanFromCommunityId,
|
|
||||||
ModBanId,
|
|
||||||
ModFeaturePostId,
|
|
||||||
ModHideCommunityId,
|
|
||||||
ModLockPostId,
|
|
||||||
ModRemoveCommentId,
|
|
||||||
ModRemoveCommunityId,
|
|
||||||
ModRemovePostId,
|
|
||||||
ModTransferCommunityId,
|
|
||||||
PersonId,
|
|
||||||
PostId,
|
|
||||||
};
|
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::{
|
use crate::schema::{
|
||||||
mod_add,
|
mod_add,
|
||||||
mod_add_community,
|
mod_add_community,
|
||||||
mod_ban,
|
mod_ban,
|
||||||
mod_ban_from_community,
|
mod_ban_from_community,
|
||||||
|
mod_change_community_visibility,
|
||||||
mod_feature_post,
|
mod_feature_post,
|
||||||
mod_hide_community,
|
|
||||||
mod_lock_post,
|
mod_lock_post,
|
||||||
mod_remove_comment,
|
mod_remove_comment,
|
||||||
mod_remove_community,
|
mod_remove_community,
|
||||||
mod_remove_post,
|
mod_remove_post,
|
||||||
mod_transfer_community,
|
mod_transfer_community,
|
||||||
};
|
};
|
||||||
|
use crate::{
|
||||||
|
newtypes::{
|
||||||
|
CommentId,
|
||||||
|
CommunityId,
|
||||||
|
ModAddCommunityId,
|
||||||
|
ModAddId,
|
||||||
|
ModBanFromCommunityId,
|
||||||
|
ModBanId,
|
||||||
|
ModChangeCommunityVisibilityId,
|
||||||
|
ModFeaturePostId,
|
||||||
|
ModLockPostId,
|
||||||
|
ModRemoveCommentId,
|
||||||
|
ModRemoveCommunityId,
|
||||||
|
ModRemovePostId,
|
||||||
|
ModTransferCommunityId,
|
||||||
|
PersonId,
|
||||||
|
PostId,
|
||||||
|
},
|
||||||
|
CommunityVisibility,
|
||||||
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
@ -210,29 +213,28 @@ pub struct ModBan {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = mod_hide_community))]
|
#[cfg_attr(feature = "full", diesel(table_name = mod_change_community_visibility))]
|
||||||
pub struct ModHideCommunityForm {
|
pub struct ModChangeCommunityVisibilityForm {
|
||||||
pub community_id: CommunityId,
|
pub community_id: CommunityId,
|
||||||
pub mod_person_id: PersonId,
|
pub mod_person_id: PersonId,
|
||||||
pub hidden: Option<bool>,
|
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
|
pub visibility: CommunityVisibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = mod_hide_community))]
|
#[cfg_attr(feature = "full", diesel(table_name = mod_change_community_visibility))]
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// When a community is hidden from public view.
|
pub struct ModChangeCommunityVisibility {
|
||||||
pub struct ModHideCommunity {
|
pub id: ModChangeCommunityVisibilityId,
|
||||||
pub id: ModHideCommunityId,
|
|
||||||
pub community_id: CommunityId,
|
pub community_id: CommunityId,
|
||||||
pub mod_person_id: PersonId,
|
pub mod_person_id: PersonId,
|
||||||
pub published: DateTime<Utc>,
|
pub published: DateTime<Utc>,
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub hidden: bool,
|
pub visibility: CommunityVisibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
use crate::structs::{
|
use crate::{
|
||||||
AdminAllowInstanceView,
|
structs::{
|
||||||
AdminBlockInstanceView,
|
AdminAllowInstanceView,
|
||||||
AdminPurgeCommentView,
|
AdminBlockInstanceView,
|
||||||
AdminPurgeCommunityView,
|
AdminPurgeCommentView,
|
||||||
AdminPurgePersonView,
|
AdminPurgeCommunityView,
|
||||||
AdminPurgePostView,
|
AdminPurgePersonView,
|
||||||
ModAddCommunityView,
|
AdminPurgePostView,
|
||||||
ModAddView,
|
ModAddCommunityView,
|
||||||
ModBanFromCommunityView,
|
ModAddView,
|
||||||
ModBanView,
|
ModBanFromCommunityView,
|
||||||
ModFeaturePostView,
|
ModBanView,
|
||||||
ModHideCommunityView,
|
ModChangeCommunityVisibilityView,
|
||||||
ModLockPostView,
|
ModFeaturePostView,
|
||||||
ModRemoveCommentView,
|
ModLockPostView,
|
||||||
ModRemoveCommunityView,
|
ModRemoveCommentView,
|
||||||
ModRemovePostView,
|
ModRemoveCommunityView,
|
||||||
ModTransferCommunityView,
|
ModRemovePostView,
|
||||||
ModlogCombinedView,
|
ModTransferCommunityView,
|
||||||
ModlogCombinedViewInternal,
|
ModlogCombinedView,
|
||||||
|
ModlogCombinedViewInternal,
|
||||||
|
},
|
||||||
|
utils::{filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||||
};
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
BoolExpressionMethods,
|
BoolExpressionMethods,
|
||||||
|
@ -49,8 +52,8 @@ use lemmy_db_schema::{
|
||||||
mod_add_community,
|
mod_add_community,
|
||||||
mod_ban,
|
mod_ban,
|
||||||
mod_ban_from_community,
|
mod_ban_from_community,
|
||||||
|
mod_change_community_visibility,
|
||||||
mod_feature_post,
|
mod_feature_post,
|
||||||
mod_hide_community,
|
|
||||||
mod_lock_post,
|
mod_lock_post,
|
||||||
mod_remove_comment,
|
mod_remove_comment,
|
||||||
mod_remove_community,
|
mod_remove_community,
|
||||||
|
@ -103,7 +106,7 @@ impl ModlogCombinedViewInternal {
|
||||||
.or(mod_ban::mod_person_id.eq(person::id))
|
.or(mod_ban::mod_person_id.eq(person::id))
|
||||||
.or(mod_ban_from_community::mod_person_id.eq(person::id))
|
.or(mod_ban_from_community::mod_person_id.eq(person::id))
|
||||||
.or(mod_feature_post::mod_person_id.eq(person::id))
|
.or(mod_feature_post::mod_person_id.eq(person::id))
|
||||||
.or(mod_hide_community::mod_person_id.eq(person::id))
|
.or(mod_change_community_visibility::mod_person_id.eq(person::id))
|
||||||
.or(mod_lock_post::mod_person_id.eq(person::id))
|
.or(mod_lock_post::mod_person_id.eq(person::id))
|
||||||
.or(mod_remove_comment::mod_person_id.eq(person::id))
|
.or(mod_remove_comment::mod_person_id.eq(person::id))
|
||||||
.or(mod_remove_community::mod_person_id.eq(person::id))
|
.or(mod_remove_community::mod_person_id.eq(person::id))
|
||||||
|
@ -167,7 +170,7 @@ impl ModlogCombinedViewInternal {
|
||||||
.is_not_null()
|
.is_not_null()
|
||||||
.and(post::community_id.eq(community::id)),
|
.and(post::community_id.eq(community::id)),
|
||||||
)
|
)
|
||||||
.or(mod_hide_community::community_id.eq(community::id))
|
.or(mod_change_community_visibility::community_id.eq(community::id))
|
||||||
.or(
|
.or(
|
||||||
mod_lock_post::id
|
mod_lock_post::id
|
||||||
.is_not_null()
|
.is_not_null()
|
||||||
|
@ -211,7 +214,7 @@ impl ModlogCombinedViewInternal {
|
||||||
.left_join(mod_ban::table)
|
.left_join(mod_ban::table)
|
||||||
.left_join(mod_ban_from_community::table)
|
.left_join(mod_ban_from_community::table)
|
||||||
.left_join(mod_feature_post::table)
|
.left_join(mod_feature_post::table)
|
||||||
.left_join(mod_hide_community::table)
|
.left_join(mod_change_community_visibility::table)
|
||||||
.left_join(mod_lock_post::table)
|
.left_join(mod_lock_post::table)
|
||||||
.left_join(mod_remove_comment::table)
|
.left_join(mod_remove_comment::table)
|
||||||
.left_join(mod_remove_community::table)
|
.left_join(mod_remove_community::table)
|
||||||
|
@ -230,24 +233,25 @@ impl ModlogCombinedViewInternal {
|
||||||
impl PaginationCursorBuilder for ModlogCombinedView {
|
impl PaginationCursorBuilder for ModlogCombinedView {
|
||||||
type CursorData = ModlogCombined;
|
type CursorData = ModlogCombined;
|
||||||
fn to_cursor(&self) -> PaginationCursor {
|
fn to_cursor(&self) -> PaginationCursor {
|
||||||
|
use ModlogCombinedView::*;
|
||||||
let (prefix, id) = match &self {
|
let (prefix, id) = match &self {
|
||||||
ModlogCombinedView::AdminAllowInstance(v) => ('A', v.admin_allow_instance.id.0),
|
AdminAllowInstance(v) => ('A', v.admin_allow_instance.id.0),
|
||||||
ModlogCombinedView::AdminBlockInstance(v) => ('B', v.admin_block_instance.id.0),
|
AdminBlockInstance(v) => ('B', v.admin_block_instance.id.0),
|
||||||
ModlogCombinedView::AdminPurgeComment(v) => ('C', v.admin_purge_comment.id.0),
|
AdminPurgeComment(v) => ('C', v.admin_purge_comment.id.0),
|
||||||
ModlogCombinedView::AdminPurgeCommunity(v) => ('D', v.admin_purge_community.id.0),
|
AdminPurgeCommunity(v) => ('D', v.admin_purge_community.id.0),
|
||||||
ModlogCombinedView::AdminPurgePerson(v) => ('E', v.admin_purge_person.id.0),
|
AdminPurgePerson(v) => ('E', v.admin_purge_person.id.0),
|
||||||
ModlogCombinedView::AdminPurgePost(v) => ('F', v.admin_purge_post.id.0),
|
AdminPurgePost(v) => ('F', v.admin_purge_post.id.0),
|
||||||
ModlogCombinedView::ModAdd(v) => ('G', v.mod_add.id.0),
|
ModAdd(v) => ('G', v.mod_add.id.0),
|
||||||
ModlogCombinedView::ModAddCommunity(v) => ('H', v.mod_add_community.id.0),
|
ModAddCommunity(v) => ('H', v.mod_add_community.id.0),
|
||||||
ModlogCombinedView::ModBan(v) => ('I', v.mod_ban.id.0),
|
ModBan(v) => ('I', v.mod_ban.id.0),
|
||||||
ModlogCombinedView::ModBanFromCommunity(v) => ('J', v.mod_ban_from_community.id.0),
|
ModBanFromCommunity(v) => ('J', v.mod_ban_from_community.id.0),
|
||||||
ModlogCombinedView::ModFeaturePost(v) => ('K', v.mod_feature_post.id.0),
|
ModFeaturePost(v) => ('K', v.mod_feature_post.id.0),
|
||||||
ModlogCombinedView::ModHideCommunity(v) => ('L', v.mod_hide_community.id.0),
|
ModChangeCommunityVisibility(v) => ('L', v.mod_change_community_visibility.id.0),
|
||||||
ModlogCombinedView::ModLockPost(v) => ('M', v.mod_lock_post.id.0),
|
ModLockPost(v) => ('M', v.mod_lock_post.id.0),
|
||||||
ModlogCombinedView::ModRemoveComment(v) => ('N', v.mod_remove_comment.id.0),
|
ModRemoveComment(v) => ('N', v.mod_remove_comment.id.0),
|
||||||
ModlogCombinedView::ModRemoveCommunity(v) => ('O', v.mod_remove_community.id.0),
|
ModRemoveCommunity(v) => ('O', v.mod_remove_community.id.0),
|
||||||
ModlogCombinedView::ModRemovePost(v) => ('P', v.mod_remove_post.id.0),
|
ModRemovePost(v) => ('P', v.mod_remove_post.id.0),
|
||||||
ModlogCombinedView::ModTransferCommunity(v) => ('Q', v.mod_transfer_community.id.0),
|
ModTransferCommunity(v) => ('Q', v.mod_transfer_community.id.0),
|
||||||
};
|
};
|
||||||
PaginationCursor::new(prefix, id)
|
PaginationCursor::new(prefix, id)
|
||||||
}
|
}
|
||||||
|
@ -275,7 +279,7 @@ impl PaginationCursorBuilder for ModlogCombinedView {
|
||||||
'I' => query.filter(modlog_combined::mod_ban_id.eq(id)),
|
'I' => query.filter(modlog_combined::mod_ban_id.eq(id)),
|
||||||
'J' => query.filter(modlog_combined::mod_ban_from_community_id.eq(id)),
|
'J' => query.filter(modlog_combined::mod_ban_from_community_id.eq(id)),
|
||||||
'K' => query.filter(modlog_combined::mod_feature_post_id.eq(id)),
|
'K' => query.filter(modlog_combined::mod_feature_post_id.eq(id)),
|
||||||
'L' => query.filter(modlog_combined::mod_hide_community_id.eq(id)),
|
'L' => query.filter(modlog_combined::mod_change_community_visibility_id.eq(id)),
|
||||||
'M' => query.filter(modlog_combined::mod_lock_post_id.eq(id)),
|
'M' => query.filter(modlog_combined::mod_lock_post_id.eq(id)),
|
||||||
'N' => query.filter(modlog_combined::mod_remove_comment_id.eq(id)),
|
'N' => query.filter(modlog_combined::mod_remove_comment_id.eq(id)),
|
||||||
'O' => query.filter(modlog_combined::mod_remove_community_id.eq(id)),
|
'O' => query.filter(modlog_combined::mod_remove_community_id.eq(id)),
|
||||||
|
@ -355,7 +359,9 @@ impl ModlogCombinedQuery<'_> {
|
||||||
}
|
}
|
||||||
ModAdd => query.filter(modlog_combined::mod_add_id.is_not_null()),
|
ModAdd => query.filter(modlog_combined::mod_add_id.is_not_null()),
|
||||||
ModBan => query.filter(modlog_combined::mod_ban_id.is_not_null()),
|
ModBan => query.filter(modlog_combined::mod_ban_id.is_not_null()),
|
||||||
ModHideCommunity => query.filter(modlog_combined::mod_hide_community_id.is_not_null()),
|
ModChangeCommunityVisibility => {
|
||||||
|
query.filter(modlog_combined::mod_change_community_visibility_id.is_not_null())
|
||||||
|
}
|
||||||
AdminPurgePerson => query.filter(modlog_combined::admin_purge_person_id.is_not_null()),
|
AdminPurgePerson => query.filter(modlog_combined::admin_purge_person_id.is_not_null()),
|
||||||
AdminPurgeCommunity => {
|
AdminPurgeCommunity => {
|
||||||
query.filter(modlog_combined::admin_purge_community_id.is_not_null())
|
query.filter(modlog_combined::admin_purge_community_id.is_not_null())
|
||||||
|
@ -367,13 +373,12 @@ impl ModlogCombinedQuery<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_subscribed = community_actions::followed.is_not_null();
|
|
||||||
query = match self.listing_type.unwrap_or(ListingType::All) {
|
query = match self.listing_type.unwrap_or(ListingType::All) {
|
||||||
ListingType::All => query,
|
ListingType::All => query,
|
||||||
ListingType::Subscribed => query.filter(is_subscribed),
|
ListingType::Subscribed => query.filter(filter_is_subscribed()),
|
||||||
ListingType::Local => query
|
ListingType::Local => query
|
||||||
.filter(community::local.eq(true))
|
.filter(community::local.eq(true))
|
||||||
.filter(community::hidden.eq(false).or(is_subscribed)),
|
.filter(filter_not_hidden_or_is_subscribed()),
|
||||||
ListingType::ModeratorView => query.filter(community_actions::became_moderator.is_not_null()),
|
ListingType::ModeratorView => query.filter(community_actions::became_moderator.is_not_null()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -507,14 +512,16 @@ impl InternalToCombinedView for ModlogCombinedViewInternal {
|
||||||
community,
|
community,
|
||||||
post,
|
post,
|
||||||
}))
|
}))
|
||||||
} else if let (Some(mod_hide_community), Some(community)) =
|
} else if let (Some(mod_change_community_visibility), Some(community)) =
|
||||||
(v.mod_hide_community, v.community.clone())
|
(v.mod_change_community_visibility, v.community.clone())
|
||||||
{
|
{
|
||||||
Some(ModlogCombinedView::ModHideCommunity(ModHideCommunityView {
|
Some(ModlogCombinedView::ModChangeCommunityVisibility(
|
||||||
mod_hide_community,
|
ModChangeCommunityVisibilityView {
|
||||||
admin: v.moderator,
|
mod_change_community_visibility,
|
||||||
community,
|
moderator: v.moderator,
|
||||||
}))
|
community,
|
||||||
|
},
|
||||||
|
))
|
||||||
} else if let (Some(mod_lock_post), Some(other_person), Some(community), Some(post)) = (
|
} else if let (Some(mod_lock_post), Some(other_person), Some(community), Some(post)) = (
|
||||||
v.mod_lock_post,
|
v.mod_lock_post,
|
||||||
v.other_person.clone(),
|
v.other_person.clone(),
|
||||||
|
@ -626,10 +633,10 @@ mod tests {
|
||||||
ModBanForm,
|
ModBanForm,
|
||||||
ModBanFromCommunity,
|
ModBanFromCommunity,
|
||||||
ModBanFromCommunityForm,
|
ModBanFromCommunityForm,
|
||||||
|
ModChangeCommunityVisibility,
|
||||||
|
ModChangeCommunityVisibilityForm,
|
||||||
ModFeaturePost,
|
ModFeaturePost,
|
||||||
ModFeaturePostForm,
|
ModFeaturePostForm,
|
||||||
ModHideCommunity,
|
|
||||||
ModHideCommunityForm,
|
|
||||||
ModLockPost,
|
ModLockPost,
|
||||||
ModLockPostForm,
|
ModLockPostForm,
|
||||||
ModRemoveComment,
|
ModRemoveComment,
|
||||||
|
@ -647,6 +654,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
utils::{build_db_pool_for_tests, DbPool},
|
utils::{build_db_pool_for_tests, DbPool},
|
||||||
|
CommunityVisibility,
|
||||||
ModlogActionType,
|
ModlogActionType,
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
@ -778,43 +786,49 @@ mod tests {
|
||||||
};
|
};
|
||||||
AdminPurgePost::create(pool, &form).await?;
|
AdminPurgePost::create(pool, &form).await?;
|
||||||
|
|
||||||
let form = ModHideCommunityForm {
|
let form = ModChangeCommunityVisibilityForm {
|
||||||
mod_person_id: data.timmy.id,
|
mod_person_id: data.timmy.id,
|
||||||
community_id: data.community.id,
|
community_id: data.community.id,
|
||||||
hidden: Some(true),
|
visibility: CommunityVisibility::Unlisted,
|
||||||
reason: None,
|
reason: None,
|
||||||
};
|
};
|
||||||
ModHideCommunity::create(pool, &form).await?;
|
ModChangeCommunityVisibility::create(pool, &form).await?;
|
||||||
|
|
||||||
// A 2nd mod hide community, but to a different community, and with jessica
|
// A 2nd mod hide community, but to a different community, and with jessica
|
||||||
let form = ModHideCommunityForm {
|
let form = ModChangeCommunityVisibilityForm {
|
||||||
mod_person_id: data.jessica.id,
|
mod_person_id: data.jessica.id,
|
||||||
community_id: data.community_2.id,
|
community_id: data.community_2.id,
|
||||||
hidden: Some(true),
|
visibility: CommunityVisibility::Unlisted,
|
||||||
reason: None,
|
reason: None,
|
||||||
};
|
};
|
||||||
ModHideCommunity::create(pool, &form).await?;
|
ModChangeCommunityVisibility::create(pool, &form).await?;
|
||||||
|
|
||||||
let modlog = ModlogCombinedQuery::default().list(pool).await?;
|
let modlog = ModlogCombinedQuery::default().list(pool).await?;
|
||||||
assert_eq!(8, modlog.len());
|
assert_eq!(8, modlog.len());
|
||||||
|
|
||||||
if let ModlogCombinedView::ModHideCommunity(v) = &modlog[0] {
|
if let ModlogCombinedView::ModChangeCommunityVisibility(v) = &modlog[0] {
|
||||||
assert_eq!(data.community_2.id, v.mod_hide_community.community_id);
|
assert_eq!(
|
||||||
|
data.community_2.id,
|
||||||
|
v.mod_change_community_visibility.community_id
|
||||||
|
);
|
||||||
assert_eq!(data.community_2.id, v.community.id);
|
assert_eq!(data.community_2.id, v.community.id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data.jessica.id,
|
data.jessica.id,
|
||||||
v.admin.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
v.moderator.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("wrong type");
|
panic!("wrong type");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ModlogCombinedView::ModHideCommunity(v) = &modlog[1] {
|
if let ModlogCombinedView::ModChangeCommunityVisibility(v) = &modlog[1] {
|
||||||
assert_eq!(data.community.id, v.mod_hide_community.community_id);
|
assert_eq!(
|
||||||
|
data.community.id,
|
||||||
|
v.mod_change_community_visibility.community_id
|
||||||
|
);
|
||||||
assert_eq!(data.community.id, v.community.id);
|
assert_eq!(data.community.id, v.community.id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data.timmy.id,
|
data.timmy.id,
|
||||||
v.admin.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
v.moderator.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("wrong type");
|
panic!("wrong type");
|
||||||
|
@ -906,7 +920,7 @@ mod tests {
|
||||||
|
|
||||||
// Filter by type
|
// Filter by type
|
||||||
let modlog_type_filter = ModlogCombinedQuery {
|
let modlog_type_filter = ModlogCombinedQuery {
|
||||||
type_: Some(ModlogActionType::ModHideCommunity),
|
type_: Some(ModlogActionType::ModChangeCommunityVisibility),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.list(pool)
|
.list(pool)
|
||||||
|
@ -915,23 +929,29 @@ mod tests {
|
||||||
// 2 of these, one is jessicas
|
// 2 of these, one is jessicas
|
||||||
assert_eq!(2, modlog_type_filter.len());
|
assert_eq!(2, modlog_type_filter.len());
|
||||||
|
|
||||||
if let ModlogCombinedView::ModHideCommunity(v) = &modlog_type_filter[0] {
|
if let ModlogCombinedView::ModChangeCommunityVisibility(v) = &modlog_type_filter[0] {
|
||||||
assert_eq!(data.community_2.id, v.mod_hide_community.community_id);
|
assert_eq!(
|
||||||
|
data.community_2.id,
|
||||||
|
v.mod_change_community_visibility.community_id
|
||||||
|
);
|
||||||
assert_eq!(data.community_2.id, v.community.id);
|
assert_eq!(data.community_2.id, v.community.id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data.jessica.id,
|
data.jessica.id,
|
||||||
v.admin.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
v.moderator.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("wrong type");
|
panic!("wrong type");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ModlogCombinedView::ModHideCommunity(v) = &modlog_type_filter[1] {
|
if let ModlogCombinedView::ModChangeCommunityVisibility(v) = &modlog_type_filter[1] {
|
||||||
assert_eq!(data.community.id, v.mod_hide_community.community_id);
|
assert_eq!(
|
||||||
|
data.community.id,
|
||||||
|
v.mod_change_community_visibility.community_id
|
||||||
|
);
|
||||||
assert_eq!(data.community.id, v.community.id);
|
assert_eq!(data.community.id, v.community.id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data.timmy.id,
|
data.timmy.id,
|
||||||
v.admin.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
v.moderator.as_ref().map(|a| a.id).unwrap_or(PersonId(-1))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("wrong type");
|
panic!("wrong type");
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use crate::structs::{
|
use crate::{
|
||||||
CommentView,
|
structs::{
|
||||||
CommunityView,
|
CommentView,
|
||||||
LocalUserView,
|
CommunityView,
|
||||||
PersonView,
|
LocalUserView,
|
||||||
PostView,
|
PersonView,
|
||||||
SearchCombinedView,
|
PostView,
|
||||||
SearchCombinedViewInternal,
|
SearchCombinedView,
|
||||||
|
SearchCombinedViewInternal,
|
||||||
|
},
|
||||||
|
utils::{filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||||
};
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
dsl::not,
|
dsl::not,
|
||||||
|
@ -350,24 +353,19 @@ impl SearchCombinedQuery {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listing type
|
// Listing type
|
||||||
let is_subscribed = community_actions::followed.is_not_null();
|
|
||||||
match self.listing_type.unwrap_or_default() {
|
match self.listing_type.unwrap_or_default() {
|
||||||
ListingType::Subscribed => query = query.filter(is_subscribed),
|
ListingType::Subscribed => query = query.filter(filter_is_subscribed()),
|
||||||
ListingType::Local => {
|
ListingType::Local => {
|
||||||
query = query.filter(
|
query = query.filter(
|
||||||
community::local
|
community::local
|
||||||
.eq(true)
|
.eq(true)
|
||||||
.and(community::hidden.eq(false).or(is_subscribed))
|
.and(filter_not_hidden_or_is_subscribed())
|
||||||
.or(search_combined::person_id.is_not_null().and(person::local)),
|
.or(search_combined::person_id.is_not_null().and(person::local)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ListingType::All => {
|
ListingType::All => {
|
||||||
query = query.filter(
|
query = query
|
||||||
community::hidden
|
.filter(filter_not_hidden_or_is_subscribed().or(search_combined::person_id.is_not_null()))
|
||||||
.eq(false)
|
|
||||||
.or(is_subscribed)
|
|
||||||
.or(search_combined::person_id.is_not_null()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ListingType::ModeratorView => {
|
ListingType::ModeratorView => {
|
||||||
query = query.filter(community_actions::became_moderator.is_not_null());
|
query = query.filter(community_actions::became_moderator.is_not_null());
|
||||||
|
|
|
@ -972,7 +972,6 @@ mod tests {
|
||||||
description: None,
|
description: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
hidden: false,
|
|
||||||
posting_restricted_to_mods: false,
|
posting_restricted_to_mods: false,
|
||||||
published: data.inserted_community.published,
|
published: data.inserted_community.published,
|
||||||
instance_id: data.inserted_instance.id,
|
instance_id: data.inserted_instance.id,
|
||||||
|
@ -1012,7 +1011,7 @@ mod tests {
|
||||||
pool,
|
pool,
|
||||||
data.inserted_community.id,
|
data.inserted_community.id,
|
||||||
&CommunityUpdateForm {
|
&CommunityUpdateForm {
|
||||||
visibility: Some(CommunityVisibility::LocalOnly),
|
visibility: Some(CommunityVisibility::LocalOnlyPrivate),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::structs::{CommunityModeratorView, CommunitySortType, CommunityView, PersonView};
|
use crate::{
|
||||||
|
structs::{CommunityModeratorView, CommunitySortType, CommunityView, PersonView},
|
||||||
|
utils::{filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||||
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
result::Error,
|
result::Error,
|
||||||
BoolExpressionMethods,
|
BoolExpressionMethods,
|
||||||
|
@ -13,11 +16,7 @@ use lemmy_db_schema::{
|
||||||
impls::local_user::LocalUserOptionHelper,
|
impls::local_user::LocalUserOptionHelper,
|
||||||
newtypes::{CommunityId, PersonId},
|
newtypes::{CommunityId, PersonId},
|
||||||
schema::{community, community_actions, instance_actions, local_user},
|
schema::{community, community_actions, instance_actions, local_user},
|
||||||
source::{
|
source::{community::Community, local_user::LocalUser, site::Site},
|
||||||
community::{Community, CommunityFollowerState},
|
|
||||||
local_user::LocalUser,
|
|
||||||
site::Site,
|
|
||||||
},
|
|
||||||
utils::{functions::lower, get_conn, limit_and_offset, now, seconds_to_pg_interval, DbPool},
|
utils::{functions::lower, get_conn, limit_and_offset, now, seconds_to_pg_interval, DbPool},
|
||||||
ListingType,
|
ListingType,
|
||||||
};
|
};
|
||||||
|
@ -130,22 +129,18 @@ impl CommunityQuery<'_> {
|
||||||
|
|
||||||
// Hide deleted and removed for non-admins or mods
|
// Hide deleted and removed for non-admins or mods
|
||||||
if !o.is_mod_or_admin {
|
if !o.is_mod_or_admin {
|
||||||
query = query.filter(Community::hide_removed_and_deleted()).filter(
|
query = query
|
||||||
community::hidden
|
.filter(Community::hide_removed_and_deleted())
|
||||||
.eq(false)
|
.filter(filter_not_hidden_or_is_subscribed());
|
||||||
.or(community_actions::follow_state.is_not_null()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_subscribed = community_actions::follow_state.eq(Some(CommunityFollowerState::Accepted));
|
|
||||||
|
|
||||||
if let Some(listing_type) = o.listing_type {
|
if let Some(listing_type) = o.listing_type {
|
||||||
query = match listing_type {
|
query = match listing_type {
|
||||||
ListingType::All => query.filter(community::hidden.eq(false).or(is_subscribed)),
|
ListingType::All => query.filter(filter_not_hidden_or_is_subscribed()),
|
||||||
ListingType::Subscribed => query.filter(is_subscribed),
|
ListingType::Subscribed => query.filter(filter_is_subscribed()),
|
||||||
ListingType::Local => query
|
ListingType::Local => query
|
||||||
.filter(community::local.eq(true))
|
.filter(community::local.eq(true))
|
||||||
.filter(community::hidden.eq(false).or(is_subscribed)),
|
.filter(filter_not_hidden_or_is_subscribed()),
|
||||||
ListingType::ModeratorView => {
|
ListingType::ModeratorView => {
|
||||||
query.filter(community_actions::became_moderator.is_not_null())
|
query.filter(community_actions::became_moderator.is_not_null())
|
||||||
}
|
}
|
||||||
|
@ -386,7 +381,7 @@ mod tests {
|
||||||
pool,
|
pool,
|
||||||
data.communities[0].id,
|
data.communities[0].id,
|
||||||
&CommunityUpdateForm {
|
&CommunityUpdateForm {
|
||||||
visibility: Some(CommunityVisibility::LocalOnly),
|
visibility: Some(CommunityVisibility::LocalOnlyPrivate),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
structs::{PostPaginationCursor, PostView},
|
structs::{PostPaginationCursor, PostView},
|
||||||
utils::filter_blocked,
|
utils::{filter_blocked, filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||||
};
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
debug_query,
|
debug_query,
|
||||||
|
@ -460,15 +460,14 @@ impl<'a> PostQuery<'a> {
|
||||||
query = query.filter(post::creator_id.eq(creator_id));
|
query = query.filter(post::creator_id.eq(creator_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_subscribed = community_actions::followed.is_not_null();
|
|
||||||
match o.listing_type.unwrap_or_default() {
|
match o.listing_type.unwrap_or_default() {
|
||||||
ListingType::Subscribed => query = query.filter(is_subscribed),
|
ListingType::Subscribed => query = query.filter(filter_is_subscribed()),
|
||||||
ListingType::Local => {
|
ListingType::Local => {
|
||||||
query = query
|
query = query
|
||||||
.filter(community::local.eq(true))
|
.filter(community::local.eq(true))
|
||||||
.filter(community::hidden.eq(false).or(is_subscribed));
|
.filter(filter_not_hidden_or_is_subscribed());
|
||||||
}
|
}
|
||||||
ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)),
|
ListingType::All => query = query.filter(filter_not_hidden_or_is_subscribed()),
|
||||||
ListingType::ModeratorView => {
|
ListingType::ModeratorView => {
|
||||||
query = query.filter(community_actions::became_moderator.is_not_null());
|
query = query.filter(community_actions::became_moderator.is_not_null());
|
||||||
}
|
}
|
||||||
|
@ -1564,7 +1563,7 @@ mod tests {
|
||||||
pool,
|
pool,
|
||||||
data.community.id,
|
data.community.id,
|
||||||
&CommunityUpdateForm {
|
&CommunityUpdateForm {
|
||||||
hidden: Some(true),
|
visibility: Some(CommunityVisibility::Unlisted),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -2010,7 +2009,6 @@ mod tests {
|
||||||
description: None,
|
description: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
hidden: false,
|
|
||||||
posting_restricted_to_mods: false,
|
posting_restricted_to_mods: false,
|
||||||
published: inserted_community.published,
|
published: inserted_community.published,
|
||||||
instance_id: data.instance.id,
|
instance_id: data.instance.id,
|
||||||
|
@ -2056,7 +2054,7 @@ mod tests {
|
||||||
pool,
|
pool,
|
||||||
data.community.id,
|
data.community.id,
|
||||||
&CommunityUpdateForm {
|
&CommunityUpdateForm {
|
||||||
visibility: Some(CommunityVisibility::LocalOnly),
|
visibility: Some(CommunityVisibility::LocalOnlyPrivate),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -53,8 +53,8 @@ use lemmy_db_schema::{
|
||||||
ModAddCommunity,
|
ModAddCommunity,
|
||||||
ModBan,
|
ModBan,
|
||||||
ModBanFromCommunity,
|
ModBanFromCommunity,
|
||||||
|
ModChangeCommunityVisibility,
|
||||||
ModFeaturePost,
|
ModFeaturePost,
|
||||||
ModHideCommunity,
|
|
||||||
ModLockPost,
|
ModLockPost,
|
||||||
ModRemoveComment,
|
ModRemoveComment,
|
||||||
ModRemoveCommunity,
|
ModRemoveCommunity,
|
||||||
|
@ -867,11 +867,11 @@ pub struct ModBanView {
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// When a community is hidden from public view.
|
/// When the visibility of a community is changed
|
||||||
pub struct ModHideCommunityView {
|
pub struct ModChangeCommunityVisibilityView {
|
||||||
pub mod_hide_community: ModHideCommunity,
|
pub mod_change_community_visibility: ModChangeCommunityVisibility,
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub admin: Option<Person>,
|
pub moderator: Option<Person>,
|
||||||
pub community: Community,
|
pub community: Community,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1068,7 +1068,7 @@ pub(crate) struct ModlogCombinedViewInternal {
|
||||||
#[cfg_attr(feature = "full", diesel(embed))]
|
#[cfg_attr(feature = "full", diesel(embed))]
|
||||||
pub mod_feature_post: Option<ModFeaturePost>,
|
pub mod_feature_post: Option<ModFeaturePost>,
|
||||||
#[cfg_attr(feature = "full", diesel(embed))]
|
#[cfg_attr(feature = "full", diesel(embed))]
|
||||||
pub mod_hide_community: Option<ModHideCommunity>,
|
pub mod_change_community_visibility: Option<ModChangeCommunityVisibility>,
|
||||||
#[cfg_attr(feature = "full", diesel(embed))]
|
#[cfg_attr(feature = "full", diesel(embed))]
|
||||||
pub mod_lock_post: Option<ModLockPost>,
|
pub mod_lock_post: Option<ModLockPost>,
|
||||||
#[cfg_attr(feature = "full", diesel(embed))]
|
#[cfg_attr(feature = "full", diesel(embed))]
|
||||||
|
@ -1118,7 +1118,7 @@ pub enum ModlogCombinedView {
|
||||||
ModBan(ModBanView),
|
ModBan(ModBanView),
|
||||||
ModBanFromCommunity(ModBanFromCommunityView),
|
ModBanFromCommunity(ModBanFromCommunityView),
|
||||||
ModFeaturePost(ModFeaturePostView),
|
ModFeaturePost(ModFeaturePostView),
|
||||||
ModHideCommunity(ModHideCommunityView),
|
ModChangeCommunityVisibility(ModChangeCommunityVisibilityView),
|
||||||
ModLockPost(ModLockPostView),
|
ModLockPost(ModLockPostView),
|
||||||
ModRemoveComment(ModRemoveCommentView),
|
ModRemoveComment(ModRemoveCommentView),
|
||||||
ModRemoveCommunity(ModRemoveCommunityView),
|
ModRemoveCommunity(ModRemoveCommunityView),
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
use diesel::{BoolExpressionMethods, ExpressionMethods};
|
use diesel::{
|
||||||
use lemmy_db_schema::schema::{community_actions, instance_actions, person_actions};
|
helper_types::{Eq, NotEq, Or},
|
||||||
|
BoolExpressionMethods,
|
||||||
|
ExpressionMethods,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
schema::{community, community_actions, instance_actions, person_actions},
|
||||||
|
source::community::CommunityFollowerState,
|
||||||
|
CommunityVisibility,
|
||||||
|
};
|
||||||
|
|
||||||
/// Hide all content from blocked communities and persons. Content from blocked instances is also
|
/// Hide all content from blocked communities and persons. Content from blocked instances is also
|
||||||
/// hidden, unless the user followed the community explicitly.
|
/// hidden, unless the user followed the community explicitly.
|
||||||
|
@ -11,3 +19,17 @@ pub(crate) fn filter_blocked() -> _ {
|
||||||
.and(community_actions::blocked.is_null())
|
.and(community_actions::blocked.is_null())
|
||||||
.and(person_actions::blocked.is_null())
|
.and(person_actions::blocked.is_null())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IsSubscribedType =
|
||||||
|
Eq<lemmy_db_schema::schema::community_actions::follow_state, Option<CommunityFollowerState>>;
|
||||||
|
|
||||||
|
pub(crate) fn filter_is_subscribed() -> IsSubscribedType {
|
||||||
|
community_actions::follow_state.eq(Some(CommunityFollowerState::Accepted))
|
||||||
|
}
|
||||||
|
|
||||||
|
type IsNotHiddenType = NotEq<lemmy_db_schema::schema::community::visibility, CommunityVisibility>;
|
||||||
|
|
||||||
|
pub(crate) fn filter_not_hidden_or_is_subscribed() -> Or<IsNotHiddenType, IsSubscribedType> {
|
||||||
|
let not_hidden = community::visibility.ne(CommunityVisibility::Unlisted);
|
||||||
|
not_hidden.or(filter_is_subscribed())
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{community::Community, person::Person},
|
source::{community::Community, person::Person},
|
||||||
traits::ApubActor,
|
traits::ApubActor,
|
||||||
CommunityVisibility,
|
|
||||||
ListingType,
|
ListingType,
|
||||||
PostSortType,
|
PostSortType,
|
||||||
};
|
};
|
||||||
|
@ -274,7 +273,7 @@ async fn get_feed_community(
|
||||||
let community = Community::read_from_name(&mut context.pool(), community_name, false)
|
let community = Community::read_from_name(&mut context.pool(), community_name, false)
|
||||||
.await?
|
.await?
|
||||||
.ok_or(LemmyErrorType::NotFound)?;
|
.ok_or(LemmyErrorType::NotFound)?;
|
||||||
if community.visibility != CommunityVisibility::Public {
|
if !community.visibility.can_view_without_login() {
|
||||||
return Err(LemmyErrorType::NotFound.into());
|
return Err(LemmyErrorType::NotFound.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ use lemmy_api_common::{context::LemmyContext, LemmyErrorType};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{community::Community, person::Person},
|
source::{community::Community, person::Person},
|
||||||
traits::ApubActor,
|
traits::ApubActor,
|
||||||
CommunityVisibility,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
cache_header::cache_3days,
|
cache_header::cache_3days,
|
||||||
|
@ -57,7 +56,7 @@ async fn get_webfinger_response(
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
if c.visibility == CommunityVisibility::Public {
|
if c.visibility.can_federate() {
|
||||||
let id: Url = c.ap_id.into();
|
let id: Url = c.ap_id.into();
|
||||||
Some(id)
|
Some(id)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -98,7 +98,6 @@ pub enum LemmyErrorType {
|
||||||
CommunityUserAlreadyBanned,
|
CommunityUserAlreadyBanned,
|
||||||
CommunityBlockAlreadyExists,
|
CommunityBlockAlreadyExists,
|
||||||
CommunityFollowerAlreadyExists,
|
CommunityFollowerAlreadyExists,
|
||||||
CouldntUpdateCommunityHiddenStatus,
|
|
||||||
PersonBlockAlreadyExists,
|
PersonBlockAlreadyExists,
|
||||||
UserAlreadyExists,
|
UserAlreadyExists,
|
||||||
CouldntLikePost,
|
CouldntLikePost,
|
||||||
|
|
|
@ -0,0 +1,240 @@
|
||||||
|
-- recreate columns in the original order
|
||||||
|
ALTER TABLE community
|
||||||
|
ADD COLUMN hidden bool DEFAULT FALSE NOT NULL,
|
||||||
|
ADD COLUMN posting_restricted_to_mods_new bool NOT NULL DEFAULT FALSE,
|
||||||
|
ADD COLUMN instance_id_new int NOT NULL,
|
||||||
|
ADD COLUMN moderators_url_new varchar(255),
|
||||||
|
ADD COLUMN featured_url_new varchar(255),
|
||||||
|
ADD COLUMN visibility_new community_visibility NOT NULL DEFAULT 'Public',
|
||||||
|
ADD COLUMN description_new varchar(150),
|
||||||
|
ADD COLUMN random_number_new smallint NOT NULL DEFAULT random_smallint (),
|
||||||
|
ADD COLUMN subscribers_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN posts_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN comments_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN users_active_day_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN users_active_week_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN users_active_month_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN users_active_half_year_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN hot_rank_new double precision NOT NULL DEFAULT 0.0001,
|
||||||
|
ADD COLUMN subscribers_local_new bigint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN report_count_new smallint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN unresolved_report_count_new smallint NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN interactions_month_new bigint NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
community
|
||||||
|
SET
|
||||||
|
(posting_restricted_to_mods_new,
|
||||||
|
instance_id_new,
|
||||||
|
moderators_url_new,
|
||||||
|
featured_url_new,
|
||||||
|
visibility_new,
|
||||||
|
description_new,
|
||||||
|
random_number_new,
|
||||||
|
subscribers_new,
|
||||||
|
posts_new,
|
||||||
|
comments_new,
|
||||||
|
users_active_day_new,
|
||||||
|
users_active_week_new,
|
||||||
|
users_active_month_new,
|
||||||
|
users_active_half_year_new,
|
||||||
|
hot_rank_new,
|
||||||
|
subscribers_local_new,
|
||||||
|
report_count_new,
|
||||||
|
unresolved_report_count_new,
|
||||||
|
interactions_month_new) = (posting_restricted_to_mods,
|
||||||
|
instance_id,
|
||||||
|
moderators_url,
|
||||||
|
featured_url,
|
||||||
|
visibility,
|
||||||
|
description,
|
||||||
|
random_number,
|
||||||
|
subscribers,
|
||||||
|
posts,
|
||||||
|
comments,
|
||||||
|
users_active_day,
|
||||||
|
users_active_week,
|
||||||
|
users_active_month,
|
||||||
|
users_active_half_year,
|
||||||
|
hot_rank,
|
||||||
|
subscribers_local,
|
||||||
|
report_count,
|
||||||
|
unresolved_report_count,
|
||||||
|
interactions_month);
|
||||||
|
|
||||||
|
ALTER TABLE community
|
||||||
|
DROP COLUMN posting_restricted_to_mods,
|
||||||
|
DROP COLUMN instance_id,
|
||||||
|
DROP COLUMN moderators_url,
|
||||||
|
DROP COLUMN featured_url,
|
||||||
|
DROP COLUMN visibility,
|
||||||
|
DROP COLUMN description,
|
||||||
|
DROP COLUMN random_number,
|
||||||
|
DROP COLUMN subscribers,
|
||||||
|
DROP COLUMN posts,
|
||||||
|
DROP COLUMN comments,
|
||||||
|
DROP COLUMN users_active_day,
|
||||||
|
DROP COLUMN users_active_week,
|
||||||
|
DROP COLUMN users_active_month,
|
||||||
|
DROP COLUMN users_active_half_year,
|
||||||
|
DROP COLUMN hot_rank,
|
||||||
|
DROP COLUMN subscribers_local,
|
||||||
|
DROP COLUMN report_count,
|
||||||
|
DROP COLUMN unresolved_report_count,
|
||||||
|
DROP COLUMN interactions_month;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN posting_restricted_to_mods_new TO posting_restricted_to_mods;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN instance_id_new TO instance_id;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN moderators_url_new TO moderators_url;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN featured_url_new TO featured_url;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN visibility_new TO visibility;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN description_new TO description;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN random_number_new TO random_number;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN subscribers_new TO subscribers;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN posts_new TO posts;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN comments_new TO comments;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN users_active_day_new TO users_active_day;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN users_active_week_new TO users_active_week;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN users_active_month_new TO users_active_month;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN users_active_half_year_new TO users_active_half_year;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN hot_rank_new TO hot_rank;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN subscribers_local_new TO subscribers_local;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN report_count_new TO report_count;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN unresolved_report_count_new TO unresolved_report_count;
|
||||||
|
|
||||||
|
ALTER TABLE community RENAME COLUMN interactions_month_new TO interactions_month;
|
||||||
|
|
||||||
|
ALTER TABLE community
|
||||||
|
ADD CONSTRAINT community_featured_url_key UNIQUE (featured_url),
|
||||||
|
ADD CONSTRAINT community_moderators_url_key UNIQUE (moderators_url),
|
||||||
|
ADD CONSTRAINT community_instance_id_fkey FOREIGN KEY (instance_id) REFERENCES instance (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
|
||||||
|
|
||||||
|
-- same changes as up.sql, but the other way round
|
||||||
|
UPDATE
|
||||||
|
community
|
||||||
|
SET
|
||||||
|
(hidden,
|
||||||
|
visibility) = (TRUE,
|
||||||
|
'Public')
|
||||||
|
WHERE
|
||||||
|
visibility = 'Unlisted';
|
||||||
|
|
||||||
|
ALTER TYPE community_visibility RENAME VALUE 'LocalOnlyPrivate' TO 'LocalOnly';
|
||||||
|
|
||||||
|
ALTER TYPE community_visibility RENAME TO community_visibility__;
|
||||||
|
|
||||||
|
CREATE TYPE community_visibility AS enum (
|
||||||
|
'Public',
|
||||||
|
'LocalOnly',
|
||||||
|
'Private'
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN visibility DROP DEFAULT;
|
||||||
|
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN visibility TYPE community_visibility
|
||||||
|
USING visibility::text::community_visibility;
|
||||||
|
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN visibility SET DEFAULT 'Public';
|
||||||
|
|
||||||
|
CREATE INDEX idx_community_random_number ON community (random_number) INCLUDE (local, nsfw)
|
||||||
|
WHERE
|
||||||
|
NOT (deleted OR removed OR visibility = 'Private');
|
||||||
|
|
||||||
|
CREATE INDEX idx_community_nonzero_hotrank ON community USING btree (published)
|
||||||
|
WHERE (hot_rank <> (0)::double precision);
|
||||||
|
|
||||||
|
CREATE INDEX idx_community_subscribers ON community USING btree (subscribers DESC);
|
||||||
|
|
||||||
|
CREATE INDEX idx_community_users_active_month ON community USING btree (users_active_month DESC);
|
||||||
|
|
||||||
|
CREATE INDEX idx_community_hot ON public.community USING btree (hot_rank DESC);
|
||||||
|
|
||||||
|
REINDEX TABLE community;
|
||||||
|
|
||||||
|
-- revert modlog table changes
|
||||||
|
CREATE TABLE mod_hide_community (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
|
||||||
|
mod_person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
|
||||||
|
published timestamptz NOT NULL DEFAULT now(),
|
||||||
|
reason text,
|
||||||
|
hidden boolean DEFAULT FALSE NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined
|
||||||
|
DROP COLUMN mod_change_community_visibility_id,
|
||||||
|
ADD COLUMN mod_hide_community_id int REFERENCES mod_hide_community ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
ADD COLUMN mod_lock_post_id_new int,
|
||||||
|
ADD COLUMN mod_remove_comment_id_new int,
|
||||||
|
ADD COLUMN mod_remove_community_id_new int,
|
||||||
|
ADD COLUMN mod_remove_post_id_new int,
|
||||||
|
ADD COLUMN mod_transfer_community_id_new int;
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
modlog_combined
|
||||||
|
SET
|
||||||
|
(mod_lock_post_id_new,
|
||||||
|
mod_remove_comment_id_new,
|
||||||
|
mod_remove_community_id_new,
|
||||||
|
mod_remove_post_id_new,
|
||||||
|
mod_transfer_community_id_new) = (mod_lock_post_id,
|
||||||
|
mod_remove_comment_id,
|
||||||
|
mod_remove_community_id,
|
||||||
|
mod_remove_post_id,
|
||||||
|
mod_transfer_community_id);
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined
|
||||||
|
DROP COLUMN mod_lock_post_id,
|
||||||
|
DROP COLUMN mod_remove_comment_id,
|
||||||
|
DROP COLUMN mod_remove_community_id,
|
||||||
|
DROP COLUMN mod_remove_post_id,
|
||||||
|
DROP COLUMN mod_transfer_community_id;
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined RENAME COLUMN mod_lock_post_id_new TO mod_lock_post_id;
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined RENAME COLUMN mod_remove_comment_id_new TO mod_remove_comment_id;
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined RENAME COLUMN mod_remove_community_id_new TO mod_remove_community_id;
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined RENAME COLUMN mod_remove_post_id_new TO mod_remove_post_id;
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined RENAME COLUMN mod_transfer_community_id_new TO mod_transfer_community_id;
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_hide_community_id_key UNIQUE (mod_hide_community_id),
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_lock_post_id_key UNIQUE (mod_lock_post_id),
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_remove_comment_id_key UNIQUE (mod_remove_comment_id),
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_remove_community_id_key UNIQUE (mod_remove_community_id),
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_remove_post_id_key UNIQUE (mod_remove_post_id),
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_transfer_community_id_key UNIQUE (mod_transfer_community_id),
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_lock_post_id_fkey FOREIGN KEY (mod_lock_post_id) REFERENCES mod_lock_post (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_remove_comment_id_fkey FOREIGN KEY (mod_remove_comment_id) REFERENCES mod_remove_comment (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_remove_community_id_fkey FOREIGN KEY (mod_remove_community_id) REFERENCES mod_remove_community (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_remove_post_id_fkey FOREIGN KEY (mod_remove_post_id) REFERENCES mod_remove_post (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT modlog_combined_mod_transfer_community_id_fkey FOREIGN KEY (mod_transfer_community_id) REFERENCES mod_transfer_community (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT modlog_combined_check CHECK ((num_nonnulls (admin_allow_instance_id, admin_block_instance_id, admin_purge_comment_id, admin_purge_community_id, admin_purge_person_id, admin_purge_post_id, mod_add_id, mod_add_community_id, mod_ban_id, mod_ban_from_community_id, mod_feature_post_id, mod_hide_community_id, mod_lock_post_id, mod_remove_comment_id, mod_remove_community_id, mod_remove_post_id, mod_transfer_community_id) = 1));
|
||||||
|
|
||||||
|
DROP TABLE mod_change_community_visibility;
|
||||||
|
|
||||||
|
DROP TYPE community_visibility__;
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
-- Change community.visibility to allow values:
|
||||||
|
-- ('Public', 'LocalOnlyPublic', 'LocalOnlyPrivate','Private', 'Hidden')
|
||||||
|
-- rename old enum and add new one
|
||||||
|
ALTER TYPE community_visibility RENAME TO community_visibility__;
|
||||||
|
|
||||||
|
CREATE TYPE community_visibility AS enum (
|
||||||
|
'Public',
|
||||||
|
'LocalOnlyPublic',
|
||||||
|
'LocalOnly',
|
||||||
|
'Private',
|
||||||
|
'Unlisted'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- drop default value and index which reference old enum
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN visibility DROP DEFAULT;
|
||||||
|
|
||||||
|
DROP INDEX idx_community_random_number;
|
||||||
|
|
||||||
|
-- change the column type
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN visibility TYPE community_visibility
|
||||||
|
USING visibility::text::community_visibility;
|
||||||
|
|
||||||
|
-- add default and index back in
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN visibility SET DEFAULT 'Public';
|
||||||
|
|
||||||
|
CREATE INDEX idx_community_random_number ON community (random_number) INCLUDE (local, nsfw)
|
||||||
|
WHERE
|
||||||
|
NOT (deleted OR removed OR visibility = 'Private' OR visibility = 'Unlisted');
|
||||||
|
|
||||||
|
DROP TYPE community_visibility__ CASCADE;
|
||||||
|
|
||||||
|
ALTER TYPE community_visibility RENAME VALUE 'LocalOnly' TO 'LocalOnlyPrivate';
|
||||||
|
|
||||||
|
-- write hidden value to visibility column
|
||||||
|
UPDATE
|
||||||
|
community
|
||||||
|
SET
|
||||||
|
visibility = 'Unlisted'
|
||||||
|
WHERE
|
||||||
|
hidden;
|
||||||
|
|
||||||
|
-- drop the old hidden column
|
||||||
|
ALTER TABLE community
|
||||||
|
DROP COLUMN hidden;
|
||||||
|
|
||||||
|
-- change modlog tables
|
||||||
|
ALTER TABLE modlog_combined
|
||||||
|
DROP COLUMN mod_hide_community_id;
|
||||||
|
|
||||||
|
DROP TABLE mod_hide_community;
|
||||||
|
|
||||||
|
CREATE TABLE mod_change_community_visibility (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
community_id int REFERENCES community ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
|
||||||
|
mod_person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
|
||||||
|
published timestamptz NOT NULL DEFAULT now(),
|
||||||
|
reason text,
|
||||||
|
visibility community_visibility NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE modlog_combined
|
||||||
|
ADD COLUMN mod_change_community_visibility_id int REFERENCES mod_change_community_visibility (id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT modlog_combined_check CHECK ((num_nonnulls (admin_allow_instance_id, admin_block_instance_id, admin_purge_comment_id, admin_purge_community_id, admin_purge_person_id, admin_purge_post_id, mod_add_id, mod_add_community_id, mod_ban_id, mod_ban_from_community_id, mod_feature_post_id, mod_change_community_visibility_id, mod_lock_post_id, mod_remove_comment_id, mod_remove_community_id, mod_remove_post_id, mod_transfer_community_id) = 1));
|
||||||
|
|
|
@ -11,7 +11,6 @@ use lemmy_api::{
|
||||||
ban::ban_from_community,
|
ban::ban_from_community,
|
||||||
block::user_block_community,
|
block::user_block_community,
|
||||||
follow::follow_community,
|
follow::follow_community,
|
||||||
hide::hide_community,
|
|
||||||
transfer::transfer_community,
|
transfer::transfer_community,
|
||||||
},
|
},
|
||||||
local_user::{
|
local_user::{
|
||||||
|
@ -184,7 +183,6 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
.wrap(rate_limit.message())
|
.wrap(rate_limit.message())
|
||||||
.route("", get().to(get_community))
|
.route("", get().to(get_community))
|
||||||
.route("", put().to(update_community))
|
.route("", put().to(update_community))
|
||||||
.route("/hide", put().to(hide_community))
|
|
||||||
.route("/list", get().to(list_communities))
|
.route("/list", get().to(list_communities))
|
||||||
.route("/follow", post().to(follow_community))
|
.route("/follow", post().to(follow_community))
|
||||||
.route("/block", post().to(user_block_community))
|
.route("/block", post().to(user_block_community))
|
||||||
|
|
|
@ -11,7 +11,6 @@ use lemmy_api::{
|
||||||
ban::ban_from_community,
|
ban::ban_from_community,
|
||||||
block::user_block_community,
|
block::user_block_community,
|
||||||
follow::follow_community,
|
follow::follow_community,
|
||||||
hide::hide_community,
|
|
||||||
pending_follows::{
|
pending_follows::{
|
||||||
approve::post_pending_follows_approve,
|
approve::post_pending_follows_approve,
|
||||||
count::get_pending_follows_count,
|
count::get_pending_follows_count,
|
||||||
|
@ -215,7 +214,6 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
.route("", get().to(get_community))
|
.route("", get().to(get_community))
|
||||||
.route("", put().to(update_community))
|
.route("", put().to(update_community))
|
||||||
.route("/random", get().to(get_random_community))
|
.route("/random", get().to(get_random_community))
|
||||||
.route("/hide", put().to(hide_community))
|
|
||||||
.route("/list", get().to(list_communities))
|
.route("/list", get().to(list_communities))
|
||||||
.route("/follow", post().to(follow_community))
|
.route("/follow", post().to(follow_community))
|
||||||
.route("/report", post().to(create_community_report))
|
.route("/report", post().to(create_community_report))
|
||||||
|
|
Loading…
Reference in a new issue