Adding temporary bans. Fixes #1423

temp_bans
Dessalines 2021-12-14 18:41:52 -05:00
parent b733df2903
commit 3b54acb479
20 changed files with 166 additions and 28 deletions

View File

@ -214,6 +214,7 @@ impl Perform for BanFromCommunity {
let community_id = data.community_id;
let banned_person_id = data.person_id;
let expires = data.expires.map(naive_from_unix);
// Verify that only mods or admins can ban
is_mod_or_admin(context.pool(), local_user_view.person.id, community_id).await?;
@ -221,6 +222,7 @@ impl Perform for BanFromCommunity {
let community_user_ban_form = CommunityPersonBanForm {
community_id: data.community_id,
person_id: data.person_id,
expires: Some(expires),
};
let community: ApubCommunity = blocking(context.pool(), move |conn: &'_ _| {
@ -304,9 +306,6 @@ impl Perform for BanFromCommunity {
}
// Mod tables
// TODO eventually do correct expires
let expires = data.expires.map(naive_from_unix);
let form = ModBanFromCommunityForm {
mod_person_id: local_user_view.person.id,
other_person_id: data.person_id,

View File

@ -256,6 +256,7 @@ impl Perform for SaveUserSettings {
shared_inbox_url: None,
matrix_user_id,
bot_account,
ban_expires: None,
};
blocking(context.pool(), move |conn| {
@ -452,7 +453,9 @@ impl Perform for BanPerson {
let ban = data.ban;
let banned_person_id = data.person_id;
let ban_person = move |conn: &'_ _| Person::ban_person(conn, banned_person_id, ban);
let expires = data.expires.map(naive_from_unix);
let ban_person = move |conn: &'_ _| Person::ban_person(conn, banned_person_id, ban, expires);
blocking(context.pool(), ban_person)
.await?
.map_err(LemmyError::from)
@ -495,8 +498,6 @@ impl Perform for BanPerson {
}
// Mod tables
let expires = data.expires.map(naive_from_unix);
let form = ModBanForm {
mod_person_id: local_user_view.person.id,
other_person_id: data.person_id,

View File

@ -127,7 +127,7 @@ pub async fn get_local_user_view_from_jwt(
let local_user_view =
blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??;
// Check for a site ban
if local_user_view.person.banned {
if local_user_view.person.is_banned() {
return Err(LemmyError::from_message("site_ban"));
}
@ -180,7 +180,7 @@ pub async fn get_local_user_settings_view_from_jwt(
})
.await??;
// Check for a site ban
if local_user_view.person.banned {
if local_user_view.person.is_banned() {
return Err(LemmyError::from_message("site_ban"));
}

View File

@ -101,6 +101,8 @@ impl ActivityHandler for BlockUserFromCommunity {
let community_user_ban_form = CommunityPersonBanForm {
community_id: community.id,
person_id: blocked_user.id,
// TODO how to carry across the ban expiration time?
expires: None,
};
blocking(context.pool(), move |conn: &'_ _| {

View File

@ -93,6 +93,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
let community_user_ban_form = CommunityPersonBanForm {
community_id: community.id,
person_id: blocked_user.id,
expires: None,
};
blocking(context.pool(), move |conn: &'_ _| {

View File

@ -168,6 +168,7 @@ impl ApubObject for ApubPerson {
inbox_url: Some(person.inbox.into()),
shared_inbox_url: Some(person.endpoints.shared_inbox.map(|s| s.into())),
matrix_user_id: Some(person.matrix_user_id),
ban_expires: None,
};
let person = blocking(context.pool(), move |conn| {
DbPerson::upsert(conn, &person_form)

View File

@ -225,6 +225,9 @@ impl Bannable for CommunityPersonBan {
use crate::schema::community_person_ban::dsl::*;
insert_into(community_person_ban)
.values(community_person_ban_form)
.on_conflict((community_id, person_id))
.do_update()
.set(community_person_ban_form)
.get_result::<Self>(conn)
}
@ -383,6 +386,7 @@ mod tests {
let community_person_ban_form = CommunityPersonBanForm {
community_id: inserted_community.id,
person_id: inserted_person.id,
expires: None,
};
let inserted_community_person_ban =
@ -393,6 +397,7 @@ mod tests {
community_id: inserted_community.id,
person_id: inserted_person.id,
published: inserted_community_person_ban.published,
expires: None,
};
let read_community = Community::read(&conn, inserted_community.id).unwrap();

View File

@ -3,7 +3,7 @@ use crate::{
naive_now,
newtypes::{DbUrl, PersonId},
schema::person::dsl::*,
source::person::{Person, PersonForm},
source::person::{Person, PersonForm, PersonSafe},
traits::Crud,
};
use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
@ -30,6 +30,7 @@ mod safe_type {
matrix_user_id,
admin,
bot_account,
ban_expires,
);
impl ToSafe for Person {
@ -53,6 +54,7 @@ mod safe_type {
matrix_user_id,
admin,
bot_account,
ban_expires,
)
}
}
@ -79,6 +81,7 @@ mod safe_type_alias_1 {
matrix_user_id,
admin,
bot_account,
ban_expires,
);
impl ToSafe for PersonAlias1 {
@ -102,6 +105,7 @@ mod safe_type_alias_1 {
matrix_user_id,
admin,
bot_account,
ban_expires,
)
}
}
@ -128,6 +132,7 @@ mod safe_type_alias_2 {
matrix_user_id,
admin,
bot_account,
ban_expires,
);
impl ToSafe for PersonAlias2 {
@ -151,6 +156,7 @@ mod safe_type_alias_2 {
matrix_user_id,
admin,
bot_account,
ban_expires,
)
}
}
@ -179,9 +185,14 @@ impl Crud for Person {
}
impl Person {
pub fn ban_person(conn: &PgConnection, person_id: PersonId, ban: bool) -> Result<Self, Error> {
pub fn ban_person(
conn: &PgConnection,
person_id: PersonId,
ban: bool,
expires: Option<chrono::NaiveDateTime>,
) -> Result<Self, Error> {
diesel::update(person.find(person_id))
.set(banned.eq(ban))
.set((banned.eq(ban), ban_expires.eq(expires)))
.get_result::<Self>(conn)
}
@ -259,6 +270,24 @@ impl Person {
.set(deleted.eq(new_deleted))
.get_result::<Self>(conn)
}
pub fn is_banned(&self) -> bool {
is_banned(self.banned, self.ban_expires)
}
}
impl PersonSafe {
pub fn is_banned(&self) -> bool {
is_banned(self.banned, self.ban_expires)
}
}
fn is_banned(banned_: bool, expires: Option<chrono::NaiveDateTime>) -> bool {
if let Some(expires) = expires {
banned_ && expires.gt(&naive_now())
} else {
banned_
}
}
#[cfg(test)]
@ -298,6 +327,7 @@ mod tests {
inbox_url: inserted_person.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
};
let read_person = Person::read(&conn, inserted_person.id).unwrap();

View File

@ -136,6 +136,7 @@ table! {
community_id -> Int4,
person_id -> Int4,
published -> Timestamp,
expires -> Nullable<Timestamp>,
}
}
@ -304,6 +305,7 @@ table! {
matrix_user_id -> Nullable<Text>,
admin -> Bool,
bot_account -> Bool,
ban_expires -> Nullable<Timestamp>,
}
}
@ -529,6 +531,7 @@ table! {
matrix_user_id -> Nullable<Text>,
admin -> Bool,
bot_account -> Bool,
ban_expires -> Nullable<Timestamp>,
}
}
@ -554,6 +557,7 @@ table! {
matrix_user_id -> Nullable<Text>,
admin -> Bool,
bot_account -> Bool,
ban_expires -> Nullable<Timestamp>,
}
}

View File

@ -95,6 +95,7 @@ pub struct CommunityPersonBan {
pub community_id: CommunityId,
pub person_id: PersonId,
pub published: chrono::NaiveDateTime,
pub expires: Option<chrono::NaiveDateTime>,
}
#[derive(Insertable, AsChangeset, Clone)]
@ -102,6 +103,7 @@ pub struct CommunityPersonBan {
pub struct CommunityPersonBanForm {
pub community_id: CommunityId,
pub person_id: PersonId,
pub expires: Option<Option<chrono::NaiveDateTime>>,
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]

View File

@ -27,6 +27,7 @@ pub struct Person {
pub matrix_user_id: Option<String>,
pub admin: bool,
pub bot_account: bool,
pub ban_expires: Option<chrono::NaiveDateTime>,
}
/// A safe representation of person, without the sensitive info
@ -50,6 +51,7 @@ pub struct PersonSafe {
pub matrix_user_id: Option<String>,
pub admin: bool,
pub bot_account: bool,
pub ban_expires: Option<chrono::NaiveDateTime>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
@ -75,6 +77,7 @@ pub struct PersonAlias1 {
pub matrix_user_id: Option<String>,
pub admin: bool,
pub bot_account: bool,
pub ban_expires: Option<chrono::NaiveDateTime>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
@ -97,6 +100,7 @@ pub struct PersonSafeAlias1 {
pub matrix_user_id: Option<String>,
pub admin: bool,
pub bot_account: bool,
pub ban_expires: Option<chrono::NaiveDateTime>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
@ -122,6 +126,7 @@ pub struct PersonAlias2 {
pub matrix_user_id: Option<String>,
pub admin: bool,
pub bot_account: bool,
pub ban_expires: Option<chrono::NaiveDateTime>,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
@ -144,6 +149,7 @@ pub struct PersonSafeAlias2 {
pub matrix_user_id: Option<String>,
pub admin: bool,
pub bot_account: bool,
pub ban_expires: Option<chrono::NaiveDateTime>,
}
#[derive(Insertable, AsChangeset, Clone, Default)]
@ -168,4 +174,5 @@ pub struct PersonForm {
pub matrix_user_id: Option<Option<String>>,
pub admin: Option<bool>,
pub bot_account: Option<bool>,
pub ban_expires: Option<Option<chrono::NaiveDateTime>>,
}

View File

@ -1,4 +1,4 @@
use diesel::{result::Error, *};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::comment_aggregates::CommentAggregates,
limit_and_offset,
@ -88,7 +88,12 @@ impl CommentReportView {
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
.and(community_person_ban::person_id.eq(comment::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
@ -229,7 +234,12 @@ impl<'a> CommentReportQueryBuilder<'a> {
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
.and(community_person_ban::person_id.eq(comment::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
@ -444,6 +454,7 @@ mod tests {
inbox_url: inserted_jessica.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
},
comment_creator: PersonSafeAlias1 {
id: inserted_timmy.id,
@ -463,6 +474,7 @@ mod tests {
inbox_url: inserted_timmy.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
},
creator_banned_from_community: false,
counts: CommentAggregates {
@ -499,6 +511,7 @@ mod tests {
inbox_url: inserted_sara.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
};
// Do a batch read of timmys reports
@ -554,6 +567,7 @@ mod tests {
inbox_url: inserted_timmy.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
});
assert_eq!(

View File

@ -1,4 +1,4 @@
use diesel::{result::Error, *};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::comment_aggregates::CommentAggregates,
functions::hot_rank,
@ -98,7 +98,12 @@ impl CommentView {
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
.and(community_person_ban::person_id.eq(comment::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
@ -345,7 +350,12 @@ impl<'a> CommentQueryBuilder<'a> {
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
.and(community_person_ban::person_id.eq(comment::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
@ -646,6 +656,7 @@ mod tests {
inbox_url: inserted_person.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
},
recipient: None,
post: Post {

View File

@ -1,4 +1,4 @@
use diesel::{result::Error, *};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::post_aggregates::PostAggregates,
limit_and_offset,
@ -79,7 +79,12 @@ impl PostReportView {
community_person_ban::table.on(
post::community_id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(post::creator_id)),
.and(community_person_ban::person_id.eq(post::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
@ -209,7 +214,12 @@ impl<'a> PostReportQueryBuilder<'a> {
community_person_ban::table.on(
post::community_id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(post::creator_id)),
.and(community_person_ban::person_id.eq(post::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
@ -422,6 +432,7 @@ mod tests {
inbox_url: inserted_jessica.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
},
post_creator: PersonSafeAlias1 {
id: inserted_timmy.id,
@ -441,6 +452,7 @@ mod tests {
inbox_url: inserted_timmy.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
},
creator_banned_from_community: false,
my_vote: None,
@ -482,6 +494,7 @@ mod tests {
inbox_url: inserted_sara.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
};
// Do a batch read of timmys reports
@ -535,6 +548,7 @@ mod tests {
inbox_url: inserted_timmy.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
});
assert_eq!(

View File

@ -1,4 +1,4 @@
use diesel::{pg::Pg, result::Error, *};
use diesel::{dsl::*, pg::Pg, result::Error, *};
use lemmy_db_schema::{
aggregates::post_aggregates::PostAggregates,
functions::hot_rank,
@ -86,7 +86,12 @@ impl PostView {
community_person_ban::table.on(
post::community_id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(post::creator_id)),
.and(community_person_ban::person_id.eq(post::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.inner_join(post_aggregates::table)
@ -284,7 +289,12 @@ impl<'a> PostQueryBuilder<'a> {
community_person_ban::table.on(
post::community_id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(post::creator_id)),
.and(community_person_ban::person_id.eq(post::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.inner_join(post_aggregates::table)
@ -653,6 +663,7 @@ mod tests {
inbox_url: inserted_person.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
},
creator_banned_from_community: false,
community: CommunitySafe {

View File

@ -1,4 +1,4 @@
use diesel::{result::Error, *};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
schema::{community, community_person_ban, person},
@ -31,6 +31,11 @@ impl CommunityPersonBanView {
))
.filter(community_person_ban::community_id.eq(from_community_id))
.filter(community_person_ban::person_id.eq(from_person_id))
.filter(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
)
.order_by(community_person_ban::published)
.first::<(CommunitySafe, PersonSafe)>(conn)?;

View File

@ -1,4 +1,4 @@
use diesel::{result::Error, *};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::comment_aggregates::CommentAggregates,
functions::hot_rank,
@ -96,7 +96,12 @@ impl PersonMentionView {
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
.and(community_person_ban::person_id.eq(comment::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
@ -241,7 +246,12 @@ impl<'a> PersonMentionQueryBuilder<'a> {
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
.and(community_person_ban::person_id.eq(comment::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(

View File

@ -44,7 +44,13 @@ impl PersonViewSafe {
let banned = person::table
.inner_join(person_aggregates::table)
.select((Person::safe_columns_tuple(), person_aggregates::all_columns))
.filter(person::banned.eq(true))
.filter(
person::banned.eq(true).and(
person::ban_expires
.is_null()
.or(person::ban_expires.gt(now)),
),
)
.load::<PersonViewSafeTuple>(conn)?;
Ok(Self::from_tuple_to_vec(banned))

View File

@ -0,0 +1,7 @@
drop view person_alias_1, person_alias_2;
alter table person drop column ban_expires;
alter table community_person_ban drop column expires;
create view person_alias_1 as select * from person;
create view person_alias_2 as select * from person;

View File

@ -0,0 +1,8 @@
-- Add ban_expires to person, community_person_ban
alter table person add column ban_expires timestamp;
alter table community_person_ban add column expires timestamp;
drop view person_alias_1, person_alias_2;
create view person_alias_1 as select * from person;
create view person_alias_2 as select * from person;