feat: specify users to remove notifications from

This commit is contained in:
sychic
2026-06-02 17:09:50 +01:00
committed by Calum H. (IMB11)
parent f12ea058de
commit d2e24ea4ae
3 changed files with 42 additions and 9 deletions
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT id\n FROM notifications\n WHERE body @> $1::jsonb\n ",
"query": "\n SELECT id\n FROM notifications\n WHERE body @> $1::jsonb\n AND user_id = ANY($2::bigint[])\n ",
"describe": {
"columns": [
{
@@ -11,12 +11,13 @@
],
"parameters": {
"Left": [
"Jsonb"
"Jsonb",
"Int8Array"
]
},
"nullable": [
false
]
},
"hash": "00d809d1dc9dd1eb2c49ebaac2387f82c5730d835ae1c52d5df23b5f09cd1925"
"hash": "147f31c59219c5485531914897618427375b203777a68fd6ece1a50feaf41df9"
}
@@ -599,16 +599,21 @@ impl DBNotification {
pub async fn remove_many_matching_body(
body_filter: &serde_json::Value,
users: &[DBUserId],
transaction: &mut PgTransaction<'_>,
redis: &RedisPool,
) -> Result<usize, DatabaseError> {
let user_ids = users.iter().map(|x| x.0).collect::<Vec<i64>>();
let ids = sqlx::query!(
"
SELECT id
FROM notifications
WHERE body @> $1::jsonb
AND user_id = ANY($2::bigint[])
",
body_filter
body_filter,
&user_ids
)
.fetch(&mut *transaction)
.map_ok(|x| DBNotificationId(x.id))
@@ -7,7 +7,7 @@ use crate::database::models::user_item::DBUser;
use crate::database::redis::RedisPool;
use crate::models::users::Role;
use crate::models::v3::notifications::{
NotificationBody, NotificationDeliveryStatus, NotificationType,
NotificationBody, NotificationDeliveryStatus,
};
use crate::models::v3::pats::Scopes;
use crate::queue::email::EmailQueue;
@@ -160,18 +160,45 @@ pub async fn create_direct_email(
Ok(web::Json(failed).customize().with_status(status))
}
#[derive(Deserialize)]
struct NotificationFilter {
pub user_ids: Vec<UserId>,
#[serde(flatten)]
pub body: serde_json::Map<String, serde_json::Value>,
}
#[delete("external_notifications", guard = "external_notification_key_guard")]
pub async fn remove(
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
notification_filter: web::Json<serde_json::Value>,
notification_filter: web::Json<NotificationFilter>,
) -> Result<HttpResponse, ApiError> {
let NotificationFilter { user_ids, body } =
notification_filter.into_inner();
if user_ids.is_empty() {
return Err(ApiError::Request(eyre!(
"at least one user must be provided to remove notifications from"
)));
}
if body.is_empty() {
return Err(ApiError::Request(eyre!(
"at least one `body` field must be provided to match notifications"
)));
}
let filters = serde_json::Value::Object(body);
let user_ids = user_ids
.into_iter()
.map(|x| DBUserId(x.0 as i64))
.collect::<Vec<_>>();
let mut txn = pool.begin().await?;
DBNotification::remove_many_matching_body(
&notification_filter,
&mut txn,
&redis,
&filters, &user_ids, &mut txn, &redis,
)
.await?;