mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-06-07 08:58:52 +00:00
Instance blocks with mod log entry and expiration (fixes #2506)
This commit is contained in:
parent
417e18e819
commit
2a1d3c9db8
15 changed files with 201 additions and 110 deletions
37
crates/api/src/site/admin_block_instance.rs
Normal file
37
crates/api/src/site/admin_block_instance.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
site::{AdminBlockInstance, AdminBlockInstanceResponse},
|
||||||
|
utils::is_admin,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::source::federation_blocklist::{FederationBlockList, FederationBlockListForm};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn block_instance(
|
||||||
|
data: Json<AdminBlockInstance>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
) -> LemmyResult<Json<AdminBlockInstanceResponse>> {
|
||||||
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let instance_block_form = FederationBlockListForm {
|
||||||
|
instance_id: data.instance_id,
|
||||||
|
admin_person_id: Some(local_user_view.person.id),
|
||||||
|
reason: data.reason.clone(),
|
||||||
|
expires: data.expires,
|
||||||
|
updated: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if data.block {
|
||||||
|
FederationBlockList::block(&mut context.pool(), &instance_block_form).await?;
|
||||||
|
} else {
|
||||||
|
FederationBlockList::unblock(&mut context.pool(), &instance_block_form).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Json(AdminBlockInstanceResponse {
|
||||||
|
blocked: data.block,
|
||||||
|
}))
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod admin_block_instance;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod federated_instances;
|
pub mod federated_instances;
|
||||||
pub mod leave_admin;
|
pub mod leave_admin;
|
||||||
|
|
|
@ -7,21 +7,10 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{source::local_site::LocalSite, ModlogActionType};
|
use lemmy_db_schema::{source::local_site::LocalSite, ModlogActionType};
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
use lemmy_db_views_moderator::structs::{
|
use lemmy_db_views_moderator::structs::{
|
||||||
AdminPurgeCommentView,
|
AdminBlockInstanceView, AdminPurgeCommentView, AdminPurgeCommunityView, AdminPurgePersonView,
|
||||||
AdminPurgeCommunityView,
|
AdminPurgePostView, ModAddCommunityView, ModAddView,
|
||||||
AdminPurgePersonView,
|
ModBanFromCommunityView, ModBanView, ModFeaturePostView, ModHideCommunityView, ModLockPostView,
|
||||||
AdminPurgePostView,
|
ModRemoveCommentView, ModRemoveCommunityView, ModRemovePostView, ModTransferCommunityView,
|
||||||
ModAddCommunityView,
|
|
||||||
ModAddView,
|
|
||||||
ModBanFromCommunityView,
|
|
||||||
ModBanView,
|
|
||||||
ModFeaturePostView,
|
|
||||||
ModHideCommunityView,
|
|
||||||
ModLockPostView,
|
|
||||||
ModRemoveCommentView,
|
|
||||||
ModRemoveCommunityView,
|
|
||||||
ModRemovePostView,
|
|
||||||
ModTransferCommunityView,
|
|
||||||
ModlogListParams,
|
ModlogListParams,
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
@ -121,6 +110,7 @@ pub async fn get_mod_log(
|
||||||
admin_purged_communities,
|
admin_purged_communities,
|
||||||
admin_purged_posts,
|
admin_purged_posts,
|
||||||
admin_purged_comments,
|
admin_purged_comments,
|
||||||
|
admin_block_instance,
|
||||||
) = if data.community_id.is_none() {
|
) = if data.community_id.is_none() {
|
||||||
(
|
(
|
||||||
match type_ {
|
match type_ {
|
||||||
|
@ -161,6 +151,12 @@ pub async fn get_mod_log(
|
||||||
}
|
}
|
||||||
_ => Default::default(),
|
_ => Default::default(),
|
||||||
},
|
},
|
||||||
|
match type_ {
|
||||||
|
All | AdminBlockInstance if other_person_id.is_none() => {
|
||||||
|
AdminBlockInstanceView::list(&mut context.pool(), params).await?
|
||||||
|
}
|
||||||
|
_ => Default::default(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Default::default()
|
||||||
|
@ -183,5 +179,6 @@ pub async fn get_mod_log(
|
||||||
admin_purged_posts,
|
admin_purged_posts,
|
||||||
admin_purged_comments,
|
admin_purged_comments,
|
||||||
hidden_communities,
|
hidden_communities,
|
||||||
|
admin_block_instance,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,7 @@ use crate::federate_retry_sleep_duration;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{
|
newtypes::{
|
||||||
CommentId,
|
CommentId, CommunityId, InstanceId, LanguageId, PersonId, PostId, RegistrationApplicationId,
|
||||||
CommunityId,
|
|
||||||
InstanceId,
|
|
||||||
LanguageId,
|
|
||||||
PersonId,
|
|
||||||
PostId,
|
|
||||||
RegistrationApplicationId,
|
|
||||||
},
|
},
|
||||||
source::{
|
source::{
|
||||||
community::Community,
|
community::Community,
|
||||||
|
@ -20,44 +14,20 @@ use lemmy_db_schema::{
|
||||||
person::Person,
|
person::Person,
|
||||||
tagline::Tagline,
|
tagline::Tagline,
|
||||||
},
|
},
|
||||||
CommentSortType,
|
CommentSortType, FederationMode, ListingType, ModlogActionType, PostListingMode, PostSortType,
|
||||||
FederationMode,
|
RegistrationMode, SearchType,
|
||||||
ListingType,
|
|
||||||
ModlogActionType,
|
|
||||||
PostListingMode,
|
|
||||||
PostSortType,
|
|
||||||
RegistrationMode,
|
|
||||||
SearchType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{
|
use lemmy_db_views::structs::{
|
||||||
CommentView,
|
CommentView, LocalUserView, PostView, RegistrationApplicationView, SiteView,
|
||||||
LocalUserView,
|
|
||||||
PostView,
|
|
||||||
RegistrationApplicationView,
|
|
||||||
SiteView,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::structs::{
|
use lemmy_db_views_actor::structs::{
|
||||||
CommunityFollowerView,
|
CommunityFollowerView, CommunityModeratorView, CommunityView, PersonView,
|
||||||
CommunityModeratorView,
|
|
||||||
CommunityView,
|
|
||||||
PersonView,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views_moderator::structs::{
|
use lemmy_db_views_moderator::structs::{
|
||||||
AdminPurgeCommentView,
|
AdminBlockInstanceView, AdminPurgeCommentView, AdminPurgeCommunityView, AdminPurgePersonView,
|
||||||
AdminPurgeCommunityView,
|
AdminPurgePostView, ModAddCommunityView, ModAddView, ModBanFromCommunityView, ModBanView,
|
||||||
AdminPurgePersonView,
|
ModFeaturePostView, ModHideCommunityView, ModLockPostView, ModRemoveCommentView,
|
||||||
AdminPurgePostView,
|
ModRemoveCommunityView, ModRemovePostView, ModTransferCommunityView,
|
||||||
ModAddCommunityView,
|
|
||||||
ModAddView,
|
|
||||||
ModBanFromCommunityView,
|
|
||||||
ModBanView,
|
|
||||||
ModFeaturePostView,
|
|
||||||
ModHideCommunityView,
|
|
||||||
ModLockPostView,
|
|
||||||
ModRemoveCommentView,
|
|
||||||
ModRemoveCommunityView,
|
|
||||||
ModRemovePostView,
|
|
||||||
ModTransferCommunityView,
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
@ -183,6 +153,7 @@ pub struct GetModlogResponse {
|
||||||
pub admin_purged_posts: Vec<AdminPurgePostView>,
|
pub admin_purged_posts: Vec<AdminPurgePostView>,
|
||||||
pub admin_purged_comments: Vec<AdminPurgeCommentView>,
|
pub admin_purged_comments: Vec<AdminPurgeCommentView>,
|
||||||
pub hidden_communities: Vec<ModHideCommunityView>,
|
pub hidden_communities: Vec<ModHideCommunityView>,
|
||||||
|
pub admin_block_instance: Vec<AdminBlockInstanceView>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -660,3 +631,20 @@ pub struct BlockInstance {
|
||||||
pub struct BlockInstanceResponse {
|
pub struct BlockInstanceResponse {
|
||||||
pub blocked: bool,
|
pub blocked: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct AdminBlockInstance {
|
||||||
|
pub instance_id: InstanceId,
|
||||||
|
pub block: bool,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub expires: Option<DateTime<Utc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct AdminBlockInstanceResponse {
|
||||||
|
pub blocked: bool,
|
||||||
|
}
|
|
@ -19,8 +19,6 @@ use lemmy_api_common::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
actor_language::SiteLanguage,
|
actor_language::SiteLanguage,
|
||||||
federation_allowlist::FederationAllowList,
|
|
||||||
federation_blocklist::FederationBlockList,
|
|
||||||
local_site::{LocalSite, LocalSiteUpdateForm},
|
local_site::{LocalSite, LocalSiteUpdateForm},
|
||||||
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitUpdateForm},
|
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitUpdateForm},
|
||||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||||
|
@ -152,12 +150,6 @@ pub async fn update_site(
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
// Replace the blocked and allowed instances
|
|
||||||
let allowed = data.allowed_instances.clone();
|
|
||||||
FederationAllowList::replace(&mut context.pool(), allowed).await?;
|
|
||||||
let blocked = data.blocked_instances.clone();
|
|
||||||
FederationBlockList::replace(&mut context.pool(), blocked).await?;
|
|
||||||
|
|
||||||
if let Some(url_blocklist) = data.blocked_urls.clone() {
|
if let Some(url_blocklist) = data.blocked_urls.clone() {
|
||||||
let parsed_urls = check_urls_are_valid(&url_blocklist)?;
|
let parsed_urls = check_urls_are_valid(&url_blocklist)?;
|
||||||
LocalSiteUrlBlocklist::replace(&mut context.pool(), parsed_urls).await?;
|
LocalSiteUrlBlocklist::replace(&mut context.pool(), parsed_urls).await?;
|
||||||
|
|
|
@ -1,49 +1,30 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::federation_blocklist,
|
schema::federation_blocklist,
|
||||||
source::{
|
source::federation_blocklist::{FederationBlockList, FederationBlockListForm},
|
||||||
federation_blocklist::{FederationBlockList, FederationBlockListForm},
|
|
||||||
instance::Instance,
|
|
||||||
},
|
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
|
use diesel::{delete, ExpressionMethods, QueryDsl};
|
||||||
use diesel::{dsl::insert_into, result::Error};
|
use diesel::{dsl::insert_into, result::Error};
|
||||||
use diesel_async::{AsyncPgConnection, RunQueryDsl};
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
impl FederationBlockList {
|
impl FederationBlockList {
|
||||||
pub async fn replace(pool: &mut DbPool<'_>, list_opt: Option<Vec<String>>) -> Result<(), Error> {
|
pub async fn block(pool: &mut DbPool<'_>, form: &FederationBlockListForm) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
conn
|
insert_into(federation_blocklist::table)
|
||||||
.build_transaction()
|
.values(form)
|
||||||
.run(|conn| {
|
.get_result::<Self>(conn)
|
||||||
Box::pin(async move {
|
|
||||||
if let Some(list) = list_opt {
|
|
||||||
Self::clear(conn).await?;
|
|
||||||
|
|
||||||
for domain in list {
|
|
||||||
// Upsert all of these as instances
|
|
||||||
let instance = Instance::read_or_create(&mut conn.into(), domain).await?;
|
|
||||||
|
|
||||||
let form = FederationBlockListForm {
|
|
||||||
instance_id: instance.id,
|
|
||||||
updated: None,
|
|
||||||
};
|
|
||||||
insert_into(federation_blocklist::table)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}) as _
|
|
||||||
})
|
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
pub async fn unblock(
|
||||||
async fn clear(conn: &mut AsyncPgConnection) -> Result<usize, Error> {
|
pool: &mut DbPool<'_>,
|
||||||
diesel::delete(federation_blocklist::table)
|
form: &FederationBlockListForm,
|
||||||
.execute(conn)
|
) -> Result<Self, Error> {
|
||||||
.await
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
delete(
|
||||||
|
federation_blocklist::table
|
||||||
|
.filter(federation_blocklist::dsl::instance_id.eq(form.instance_id)),
|
||||||
|
)
|
||||||
|
.get_result(conn)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,7 @@ pub enum ModlogActionType {
|
||||||
AdminPurgeCommunity,
|
AdminPurgeCommunity,
|
||||||
AdminPurgePost,
|
AdminPurgePost,
|
||||||
AdminPurgeComment,
|
AdminPurgeComment,
|
||||||
|
AdminBlockInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
|
@ -282,6 +282,9 @@ diesel::table! {
|
||||||
instance_id -> Int4,
|
instance_id -> Int4,
|
||||||
published -> Timestamptz,
|
published -> Timestamptz,
|
||||||
updated -> Nullable<Timestamptz>,
|
updated -> Nullable<Timestamptz>,
|
||||||
|
admin_person_id -> Nullable<Int4>,
|
||||||
|
reason -> Nullable<Text>,
|
||||||
|
expires -> Nullable<Timestamptz>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,6 +958,7 @@ diesel::joinable!(custom_emoji_keyword -> custom_emoji (custom_emoji_id));
|
||||||
diesel::joinable!(email_verification -> local_user (local_user_id));
|
diesel::joinable!(email_verification -> local_user (local_user_id));
|
||||||
diesel::joinable!(federation_allowlist -> instance (instance_id));
|
diesel::joinable!(federation_allowlist -> instance (instance_id));
|
||||||
diesel::joinable!(federation_blocklist -> instance (instance_id));
|
diesel::joinable!(federation_blocklist -> instance (instance_id));
|
||||||
|
diesel::joinable!(federation_blocklist -> person (admin_person_id));
|
||||||
diesel::joinable!(federation_queue_state -> instance (instance_id));
|
diesel::joinable!(federation_queue_state -> instance (instance_id));
|
||||||
diesel::joinable!(instance_actions -> instance (instance_id));
|
diesel::joinable!(instance_actions -> instance (instance_id));
|
||||||
diesel::joinable!(instance_actions -> person (person_id));
|
diesel::joinable!(instance_actions -> person (person_id));
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use crate::newtypes::InstanceId;
|
use crate::newtypes::{InstanceId, PersonId};
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::federation_blocklist;
|
use crate::schema::federation_blocklist;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use ts_rs::TS;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "full",
|
feature = "full",
|
||||||
derive(Queryable, Selectable, Associations, Identifiable)
|
derive(TS, Queryable, Selectable, Associations, Identifiable)
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "full",
|
feature = "full",
|
||||||
|
@ -17,10 +18,15 @@ use std::fmt::Debug;
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = federation_blocklist))]
|
#[cfg_attr(feature = "full", diesel(table_name = federation_blocklist))]
|
||||||
#[cfg_attr(feature = "full", diesel(primary_key(instance_id)))]
|
#[cfg_attr(feature = "full", diesel(primary_key(instance_id)))]
|
||||||
#[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))]
|
||||||
pub struct FederationBlockList {
|
pub struct FederationBlockList {
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
pub published: DateTime<Utc>,
|
pub published: DateTime<Utc>,
|
||||||
pub updated: Option<DateTime<Utc>>,
|
pub updated: Option<DateTime<Utc>>,
|
||||||
|
// TODO: would be good to make this mandatory but value doesnt exist for old entries
|
||||||
|
pub admin_person_id: Option<PersonId>,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub expires: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
@ -29,4 +35,7 @@ pub struct FederationBlockList {
|
||||||
pub struct FederationBlockListForm {
|
pub struct FederationBlockListForm {
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
pub updated: Option<DateTime<Utc>>,
|
pub updated: Option<DateTime<Utc>>,
|
||||||
|
pub admin_person_id: Option<PersonId>,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub expires: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
57
crates/db_views_moderator/src/admin_block_instance.rs
Normal file
57
crates/db_views_moderator/src/admin_block_instance.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use crate::structs::{AdminBlockInstanceView, ModlogListParams};
|
||||||
|
use diesel::{
|
||||||
|
result::Error,
|
||||||
|
BoolExpressionMethods,
|
||||||
|
ExpressionMethods,
|
||||||
|
IntoSql,
|
||||||
|
JoinOnDsl,
|
||||||
|
NullableExpressionMethods,
|
||||||
|
QueryDsl,
|
||||||
|
};
|
||||||
|
use diesel_async::RunQueryDsl;
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
newtypes::PersonId,
|
||||||
|
schema::{federation_blocklist, instance, person},
|
||||||
|
utils::{functions::coalesce, get_conn, limit_and_offset, DbPool},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl AdminBlockInstanceView {
|
||||||
|
pub async fn list(pool: &mut DbPool<'_>, params: ModlogListParams) -> Result<Vec<Self>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
|
||||||
|
let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
|
||||||
|
let show_mod_names = !params.hide_modlog_names;
|
||||||
|
let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
|
||||||
|
|
||||||
|
let admin_names_join = coalesce(federation_blocklist::admin_person_id, 0)
|
||||||
|
.eq(person::id)
|
||||||
|
.and(show_mod_names_expr.or(person::id.eq(admin_person_id_join)));
|
||||||
|
let mut query = federation_blocklist::table
|
||||||
|
.left_join(person::table.on(admin_names_join))
|
||||||
|
.inner_join(instance::table)
|
||||||
|
.select((
|
||||||
|
federation_blocklist::all_columns,
|
||||||
|
instance::all_columns,
|
||||||
|
person::all_columns.nullable(),
|
||||||
|
))
|
||||||
|
.into_boxed();
|
||||||
|
|
||||||
|
if let Some(admin_person_id) = params.mod_person_id {
|
||||||
|
query = query.filter(federation_blocklist::admin_person_id.eq(admin_person_id));
|
||||||
|
};
|
||||||
|
|
||||||
|
// If a post or comment ID is given, then don't find any results
|
||||||
|
if params.post_id.is_some() || params.comment_id.is_some() {
|
||||||
|
return Ok(vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (limit, offset) = limit_and_offset(params.page, params.limit)?;
|
||||||
|
|
||||||
|
query
|
||||||
|
.limit(limit)
|
||||||
|
.offset(offset)
|
||||||
|
.order_by(federation_blocklist::published.desc())
|
||||||
|
.load::<AdminBlockInstanceView>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
|
pub mod admin_block_instance;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
pub mod admin_purge_comment_view;
|
pub mod admin_purge_comment_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod admin_purge_community_view;
|
pub mod admin_purge_community_view;
|
||||||
|
|
|
@ -5,6 +5,8 @@ use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
community::Community,
|
community::Community,
|
||||||
|
federation_blocklist::FederationBlockList,
|
||||||
|
instance::Instance,
|
||||||
moderator::{
|
moderator::{
|
||||||
AdminPurgeComment,
|
AdminPurgeComment,
|
||||||
AdminPurgeCommunity,
|
AdminPurgeCommunity,
|
||||||
|
@ -233,6 +235,19 @@ pub struct AdminPurgePostView {
|
||||||
pub community: Community,
|
pub community: Community,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// When an admin purges a post.
|
||||||
|
pub struct AdminBlockInstanceView {
|
||||||
|
pub blocklist_entry: FederationBlockList,
|
||||||
|
pub instance: Instance,
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub admin: Option<Person>,
|
||||||
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
alter table federation_blocklist drop column reason;
|
||||||
|
alter table federation_blocklist drop column expires;
|
||||||
|
alter table federation_blocklist drop column admin_person_id;
|
|
@ -0,0 +1,3 @@
|
||||||
|
alter table federation_blocklist add column admin_person_id int REFERENCES person(id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||||
|
alter table federation_blocklist add column reason text;
|
||||||
|
alter table federation_blocklist add column expires timestamptz;
|
|
@ -19,15 +19,7 @@ use lemmy_api_common::{
|
||||||
use lemmy_api_crud::post::create::send_webmention;
|
use lemmy_api_crud::post::create::send_webmention;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
schema::{
|
schema::{
|
||||||
captcha_answer,
|
captcha_answer, comment, community, community_actions, federation_blocklist, instance, person, post, received_activity, sent_activity
|
||||||
comment,
|
|
||||||
community,
|
|
||||||
community_actions,
|
|
||||||
instance,
|
|
||||||
person,
|
|
||||||
post,
|
|
||||||
received_activity,
|
|
||||||
sent_activity,
|
|
||||||
},
|
},
|
||||||
source::{
|
source::{
|
||||||
community::Community,
|
community::Community,
|
||||||
|
@ -439,6 +431,15 @@ async fn update_banned_when_expired(pool: &mut DbPool<'_>) {
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("Failed to remove community_ban expired rows: {e}"))
|
.inspect_err(|e| error!("Failed to remove community_ban expired rows: {e}"))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
// TODO: need separate table for modlog, otherwise entry will disappear
|
||||||
|
diesel::delete(
|
||||||
|
federation_blocklist::table.filter(federation_blocklist::expires.lt(now().nullable())),
|
||||||
|
)
|
||||||
|
.execute(&mut conn)
|
||||||
|
.await
|
||||||
|
.inspect_err(|e| error!("Failed to remove federation_blocklist expired rows: {e}"))
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Failed to get connection from pool: {e}");
|
error!("Failed to get connection from pool: {e}");
|
||||||
|
|
Loading…
Reference in a new issue