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?;
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: &'_ _| {
&community,
&banned_person,
&local_user_view.person.clone().into(),
+ expires,
context,
)
.await?;
}
// 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,
shared_inbox_url: None,
matrix_user_id,
bot_account,
+ ban_expires: None,
};
blocking(context.pool(), move |conn| {
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)
}
// 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,
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"));
}
})
.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"));
}
],
"target": "http://enterprise.lemmy.ml/c/main",
"type": "Block",
+ "expires": "2021-11-01T12:23:50.151874+00:00",
"id": "http://enterprise.lemmy.ml/activities/block/5d42fffb-0903-4625-86d4-0b39bb344fc2"
-}
\ No newline at end of file
+}
protocol::activities::community::block_user::BlockUserFromCommunity,
};
use activitystreams_kinds::{activity::BlockType, public};
+use chrono::NaiveDateTime;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
},
traits::{Bannable, Followable},
};
-use lemmy_utils::LemmyError;
+use lemmy_utils::{utils::convert_datetime, LemmyError};
use lemmy_websocket::LemmyContext;
impl BlockUserFromCommunity {
community: &ApubCommunity,
target: &ApubPerson,
actor: &ApubPerson,
+ expires: Option<NaiveDateTime>,
context: &LemmyContext,
) -> Result<BlockUserFromCommunity, LemmyError> {
Ok(BlockUserFromCommunity {
BlockType::Block,
&context.settings().get_protocol_and_hostname(),
)?,
+ expires: expires.map(convert_datetime),
unparsed: Default::default(),
})
}
community: &ApubCommunity,
target: &ApubPerson,
actor: &ApubPerson,
+ expires: Option<NaiveDateTime>,
context: &LemmyContext,
) -> Result<(), LemmyError> {
- let block = BlockUserFromCommunity::new(community, target, actor, context)?;
+ let block = BlockUserFromCommunity::new(community, target, actor, expires, context)?;
let block_id = block.id.clone();
let activity = AnnouncableActivities::BlockUserFromCommunity(block);
let community_user_ban_form = CommunityPersonBanForm {
community_id: community.id,
person_id: blocked_user.id,
+ expires: Some(self.expires.map(|u| u.naive_local())),
};
blocking(context.pool(), move |conn: &'_ _| {
actor: &ApubPerson,
context: &LemmyContext,
) -> Result<(), LemmyError> {
- let block = BlockUserFromCommunity::new(community, target, actor, context)?;
+ let block = BlockUserFromCommunity::new(community, target, actor, None, context)?;
let id = generate_activity_id(
UndoType::Undo,
let community_user_ban_form = CommunityPersonBanForm {
community_id: community.id,
person_id: blocked_user.id,
+ expires: None,
};
blocking(context.pool(), move |conn: &'_ _| {
name: person.preferred_username,
display_name: Some(person.name),
banned: None,
+ ban_expires: None,
deleted: None,
avatar: Some(person.icon.map(|i| i.url.into())),
banner: Some(person.image.map(|i| i.url.into())),
protocol::Unparsed,
};
use activitystreams_kinds::activity::BlockType;
+use chrono::{DateTime, FixedOffset};
use lemmy_apub_lib::object_id::ObjectId;
use serde::{Deserialize, Serialize};
use url::Url;
pub(crate) id: Url,
#[serde(flatten)]
pub(crate) unparsed: Unparsed,
+ pub(crate) expires: Option<DateTime<FixedOffset>>,
}
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)
}
let community_person_ban_form = CommunityPersonBanForm {
community_id: inserted_community.id,
person_id: inserted_person.id,
+ expires: None,
};
let inserted_community_person_ban =
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();
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};
matrix_user_id,
admin,
bot_account,
+ ban_expires,
);
impl ToSafe for Person {
matrix_user_id,
admin,
bot_account,
+ ban_expires,
)
}
}
matrix_user_id,
admin,
bot_account,
+ ban_expires,
);
impl ToSafe for PersonAlias1 {
matrix_user_id,
admin,
bot_account,
+ ban_expires,
)
}
}
matrix_user_id,
admin,
bot_account,
+ ban_expires,
);
impl ToSafe for PersonAlias2 {
matrix_user_id,
admin,
bot_account,
+ ban_expires,
)
}
}
}
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)
}
.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)]
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();
community_id -> Int4,
person_id -> Int4,
published -> Timestamp,
+ expires -> Nullable<Timestamp>,
}
}
matrix_user_id -> Nullable<Text>,
admin -> Bool,
bot_account -> Bool,
+ ban_expires -> Nullable<Timestamp>,
}
}
matrix_user_id -> Nullable<Text>,
admin -> Bool,
bot_account -> Bool,
+ ban_expires -> Nullable<Timestamp>,
}
}
matrix_user_id -> Nullable<Text>,
admin -> Bool,
bot_account -> Bool,
+ ban_expires -> Nullable<Timestamp>,
}
}
pub community_id: CommunityId,
pub person_id: PersonId,
pub published: chrono::NaiveDateTime,
+ pub expires: Option<chrono::NaiveDateTime>,
}
#[derive(Insertable, AsChangeset, Clone)]
pub struct CommunityPersonBanForm {
pub community_id: CommunityId,
pub person_id: PersonId,
+ pub expires: Option<Option<chrono::NaiveDateTime>>,
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
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
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)]
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)]
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)]
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)]
pub matrix_user_id: Option<String>,
pub admin: bool,
pub bot_account: bool,
+ pub ban_expires: Option<chrono::NaiveDateTime>,
}
#[derive(Insertable, AsChangeset, Clone, Default)]
pub matrix_user_id: Option<Option<String>>,
pub admin: Option<bool>,
pub bot_account: Option<bool>,
+ pub ban_expires: Option<Option<chrono::NaiveDateTime>>,
}
-use diesel::{result::Error, *};
+use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::comment_aggregates::CommentAggregates,
limit_and_offset,
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(
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(
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,
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 {
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
inbox_url: inserted_timmy.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
+ ban_expires: None,
});
assert_eq!(
-use diesel::{result::Error, *};
+use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::comment_aggregates::CommentAggregates,
functions::hot_rank,
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(
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(
inbox_url: inserted_person.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
+ ban_expires: None,
},
recipient: None,
post: Post {
-use diesel::{result::Error, *};
+use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::post_aggregates::PostAggregates,
limit_and_offset,
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(
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(
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,
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,
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
inbox_url: inserted_timmy.inbox_url.to_owned(),
shared_inbox_url: None,
matrix_user_id: None,
+ ban_expires: None,
});
assert_eq!(
-use diesel::{pg::Pg, result::Error, *};
+use diesel::{dsl::*, pg::Pg, result::Error, *};
use lemmy_db_schema::{
aggregates::post_aggregates::PostAggregates,
functions::hot_rank,
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)
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)
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 {
actor_id: inserted_sara_person.actor_id.to_owned(),
local: true,
banned: false,
+ ban_expires: None,
deleted: false,
admin: false,
bot_account: false,
actor_id: inserted_timmy_person.actor_id.to_owned(),
local: true,
banned: false,
+ ban_expires: None,
deleted: false,
admin: true,
bot_account: false,
-use diesel::{result::Error, *};
+use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
schema::{community, community_person_ban, person},
))
.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)?;
-use diesel::{result::Error, *};
+use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
aggregates::comment_aggregates::CommentAggregates,
functions::hot_rank,
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(
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(
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))
--- /dev/null
+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;
--- /dev/null
+-- 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;
+