fix: permit empty remove array in edit requests

This commit is contained in:
izzy
2025-08-07 12:57:33 +02:00
parent 947eb15771
commit 6ad3da5f35
11 changed files with 62 additions and 115 deletions

View File

@@ -132,8 +132,8 @@ auto_derived!(
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 2048)))] #[cfg_attr(feature = "validator", validate(length(min = 1, max = 2048)))]
pub interactions_url: Option<String>, pub interactions_url: Option<String>,
/// Fields to remove from bot object /// Fields to remove from bot object
#[cfg_attr(feature = "validator", validate(length(min = 1)))] #[cfg_attr(feature = "serde", serde(default))]
pub remove: Option<Vec<FieldsBot>>, pub remove: Vec<FieldsBot>,
} }
/// Where we are inviting a bot to /// Where we are inviting a bot to

View File

@@ -207,7 +207,7 @@ auto_derived!(
/// Fields to remove from channel /// Fields to remove from channel
#[cfg_attr(feature = "serde", serde(default))] #[cfg_attr(feature = "serde", serde(default))]
pub remove: Option<Vec<FieldsChannel>>, pub remove: Vec<FieldsChannel>,
} }
/// Create new group /// Create new group

View File

@@ -124,7 +124,7 @@ auto_derived!(
/// Timestamp this member is timed out until /// Timestamp this member is timed out until
pub timeout: Option<Timestamp>, pub timeout: Option<Timestamp>,
/// Fields to remove from channel object /// Fields to remove from channel object
#[cfg_attr(feature = "validator", validate(length(min = 1)))] #[cfg_attr(feature = "serde", serde(default))]
pub remove: Option<Vec<FieldsMember>>, pub remove: Vec<FieldsMember>,
} }
); );

View File

@@ -249,8 +249,8 @@ auto_derived!(
pub analytics: Option<bool>, pub analytics: Option<bool>,
/// Fields to remove from server object /// Fields to remove from server object
#[cfg_attr(feature = "validator", validate(length(min = 1)))] #[cfg_attr(feature = "serde", serde(default))]
pub remove: Option<Vec<FieldsServer>>, pub remove: Vec<FieldsServer>,
} }
/// New role information /// New role information
@@ -272,8 +272,8 @@ auto_derived!(
/// **Removed** - no effect, use the edit server role positions route /// **Removed** - no effect, use the edit server role positions route
pub rank: Option<i64>, pub rank: Option<i64>,
/// Fields to remove from role object /// Fields to remove from role object
#[cfg_attr(feature = "validator", validate(length(min = 1)))] #[cfg_attr(feature = "serde", serde(default))]
pub remove: Option<Vec<FieldsRole>>, pub remove: Vec<FieldsRole>,
} }
/// New role permissions /// New role permissions

View File

@@ -245,8 +245,8 @@ auto_derived!(
pub flags: Option<i32>, pub flags: Option<i32>,
/// Fields to remove from user object /// Fields to remove from user object
#[cfg_attr(feature = "validator", validate(length(min = 1)))] #[cfg_attr(feature = "serde", serde(default))]
pub remove: Option<Vec<FieldsUser>>, pub remove: Vec<FieldsUser>,
} }
/// User flag reponse /// User flag reponse

View File

@@ -37,7 +37,7 @@ pub async fn edit_bot(
if data.public.is_none() if data.public.is_none()
&& data.analytics.is_none() && data.analytics.is_none()
&& data.interactions_url.is_none() && data.interactions_url.is_none()
&& data.remove.is_none() && data.remove.is_empty()
{ {
return Ok(Json(v0::BotWithUserResponse { return Ok(Json(v0::BotWithUserResponse {
bot: bot.into(), bot: bot.into(),
@@ -64,7 +64,6 @@ pub async fn edit_bot(
db, db,
partial, partial,
remove remove
.unwrap_or_default()
.into_iter() .into_iter()
.map(|v| v.into()) .map(|v| v.into())
.collect(), .collect(),
@@ -100,7 +99,7 @@ mod test {
.body( .body(
json!(v0::DataEditBot { json!(v0::DataEditBot {
public: Some(true), public: Some(true),
remove: Some(vec![FieldsBot::Token]), remove: vec![FieldsBot::Token],
..Default::default() ..Default::default()
}) })
.to_string(), .to_string(),

View File

@@ -38,7 +38,7 @@ pub async fn edit(
&& data.icon.is_none() && data.icon.is_none()
&& data.nsfw.is_none() && data.nsfw.is_none()
&& data.owner.is_none() && data.owner.is_none()
&& data.remove.is_none() && data.remove.is_empty()
{ {
return Ok(Json(channel.into())); return Ok(Json(channel.into()));
} }
@@ -112,23 +112,21 @@ pub async fn edit(
nsfw, nsfw,
.. ..
} => { } => {
if let Some(fields) = &data.remove { if data.remove.contains(&v0::FieldsChannel::Icon) {
if fields.contains(&v0::FieldsChannel::Icon) { if let Some(icon) = &icon {
if let Some(icon) = &icon { db.mark_attachment_as_deleted(&icon.id).await?;
db.mark_attachment_as_deleted(&icon.id).await?;
}
} }
}
for field in fields { for field in &data.remove {
match field { match field {
v0::FieldsChannel::Description => { v0::FieldsChannel::Description => {
description.take(); description.take();
}
v0::FieldsChannel::Icon => {
icon.take();
}
_ => {}
} }
v0::FieldsChannel::Icon => {
icon.take();
}
_ => {}
} }
} }
@@ -214,11 +212,7 @@ pub async fn edit(
.update( .update(
db, db,
partial, partial,
data.remove data.remove.into_iter().map(|f| f.into()).collect(),
.unwrap_or_default()
.into_iter()
.map(|f| f.into())
.collect(),
) )
.await?; .await?;
} }

View File

@@ -39,13 +39,7 @@ pub async fn edit(
let permissions = calculate_server_permissions(&mut query).await; let permissions = calculate_server_permissions(&mut query).await;
// Check permissions in server // Check permissions in server
if data.nickname.is_some() if data.nickname.is_some() || data.remove.contains(&v0::FieldsMember::Nickname) {
|| data
.remove
.as_ref()
.map(|x| x.contains(&v0::FieldsMember::Nickname))
.unwrap_or_default()
{
if user.id == member.id.user { if user.id == member.id.user {
permissions.throw_if_lacking_channel_permission(ChannelPermission::ChangeNickname)?; permissions.throw_if_lacking_channel_permission(ChannelPermission::ChangeNickname)?;
} else { } else {
@@ -53,13 +47,7 @@ pub async fn edit(
} }
} }
if data.avatar.is_some() if data.avatar.is_some() || data.remove.contains(&v0::FieldsMember::Avatar) {
|| data
.remove
.as_ref()
.map(|x| x.contains(&v0::FieldsMember::Avatar))
.unwrap_or_default()
{
if user.id == member.id.user { if user.id == member.id.user {
permissions.throw_if_lacking_channel_permission(ChannelPermission::ChangeAvatar)?; permissions.throw_if_lacking_channel_permission(ChannelPermission::ChangeAvatar)?;
} else { } else {
@@ -67,23 +55,11 @@ pub async fn edit(
} }
} }
if data.roles.is_some() if data.roles.is_some() || data.remove.contains(&v0::FieldsMember::Roles) {
|| data
.remove
.as_ref()
.map(|x| x.contains(&v0::FieldsMember::Roles))
.unwrap_or_default()
{
permissions.throw_if_lacking_channel_permission(ChannelPermission::AssignRoles)?; permissions.throw_if_lacking_channel_permission(ChannelPermission::AssignRoles)?;
} }
if data.timeout.is_some() if data.timeout.is_some() || data.remove.contains(&v0::FieldsMember::Timeout) {
|| data
.remove
.as_ref()
.map(|x| x.contains(&v0::FieldsMember::Timeout))
.unwrap_or_default()
{
if data.timeout.is_some() && member.id.user == user.id { if data.timeout.is_some() && member.id.user == user.id {
return Err(create_error!(CannotTimeoutYourself)); return Err(create_error!(CannotTimeoutYourself));
} }
@@ -136,11 +112,9 @@ pub async fn edit(
}; };
// 1. Remove fields from object // 1. Remove fields from object
if let Some(fields) = &remove { if remove.contains(&v0::FieldsMember::Avatar) {
if fields.contains(&v0::FieldsMember::Avatar) { if let Some(avatar) = &member.avatar {
if let Some(avatar) = &member.avatar { db.mark_attachment_as_deleted(&avatar.id).await?;
db.mark_attachment_as_deleted(&avatar.id).await?;
}
} }
} }
@@ -150,13 +124,7 @@ pub async fn edit(
} }
member member
.update( .update(db, partial, remove.into_iter().map(Into::into).collect())
db,
partial,
remove
.map(|v| v.into_iter().map(Into::into).collect())
.unwrap_or_default(),
)
.await?; .await?;
Ok(Json(member.into())) Ok(Json(member.into()))

View File

@@ -61,9 +61,7 @@ pub async fn edit(
&server.id, &server.id,
&role_id, &role_id,
partial, partial,
remove remove.into_iter().map(Into::into).collect(),
.map(|v| v.into_iter().map(Into::into).collect())
.unwrap_or_default(),
) )
.await?; .await?;

View File

@@ -43,7 +43,7 @@ pub async fn edit(
&& data.flags.is_none() && data.flags.is_none()
&& data.analytics.is_none() && data.analytics.is_none()
&& data.discoverable.is_none() && data.discoverable.is_none()
&& data.remove.is_none() && data.remove.is_empty()
{ {
return Ok(Json(server.into())); return Ok(Json(server.into()));
} else if data.name.is_some() } else if data.name.is_some()
@@ -52,7 +52,7 @@ pub async fn edit(
|| data.banner.is_some() || data.banner.is_some()
|| data.system_messages.is_some() || data.system_messages.is_some()
|| data.analytics.is_some() || data.analytics.is_some()
|| data.remove.is_some() || !data.remove.is_empty()
{ {
permissions.throw_if_lacking_channel_permission(ChannelPermission::ManageServer)?; permissions.throw_if_lacking_channel_permission(ChannelPermission::ManageServer)?;
} }
@@ -96,17 +96,15 @@ pub async fn edit(
}; };
// 1. Remove fields from object // 1. Remove fields from object
if let Some(fields) = &remove { if remove.contains(&v0::FieldsServer::Banner) {
if fields.contains(&v0::FieldsServer::Banner) { if let Some(banner) = &server.banner {
if let Some(banner) = &server.banner { db.mark_attachment_as_deleted(&banner.id).await?;
db.mark_attachment_as_deleted(&banner.id).await?;
}
} }
}
if fields.contains(&v0::FieldsServer::Icon) { if remove.contains(&v0::FieldsServer::Icon) {
if let Some(icon) = &server.icon { if let Some(icon) = &server.icon {
db.mark_attachment_as_deleted(&icon.id).await?; db.mark_attachment_as_deleted(&icon.id).await?;
}
} }
} }
@@ -149,13 +147,7 @@ pub async fn edit(
} }
server server
.update( .update(db, partial, remove.into_iter().map(Into::into).collect())
db,
partial,
remove
.map(|v| v.into_iter().map(Into::into).collect())
.unwrap_or_default(),
)
.await?; .await?;
Ok(Json(server.into())) Ok(Json(server.into()))

View File

@@ -53,31 +53,29 @@ pub async fn edit(
&& data.avatar.is_none() && data.avatar.is_none()
&& data.badges.is_none() && data.badges.is_none()
&& data.flags.is_none() && data.flags.is_none()
&& data.remove.is_none() && data.remove.is_empty()
{ {
return Ok(Json(user.into_self(false).await)); return Ok(Json(user.into_self(false).await));
} }
// 1. Remove fields from object // 1. Remove fields from object
if let Some(fields) = &data.remove { if data.remove.contains(&v0::FieldsUser::Avatar) {
if fields.contains(&v0::FieldsUser::Avatar) { if let Some(avatar) = &user.avatar {
if let Some(avatar) = &user.avatar { db.mark_attachment_as_deleted(&avatar.id).await?;
db.mark_attachment_as_deleted(&avatar.id).await?; }
}
if data.remove.contains(&v0::FieldsUser::ProfileBackground) {
if let Some(profile) = &user.profile {
if let Some(background) = &profile.background {
db.mark_attachment_as_deleted(&background.id).await?;
} }
} }
}
if fields.contains(&v0::FieldsUser::ProfileBackground) { for field in &data.remove {
if let Some(profile) = &user.profile { let field: FieldsUser = field.clone().into();
if let Some(background) = &profile.background { user.remove_field(&field);
db.mark_attachment_as_deleted(&background.id).await?;
}
}
}
for field in fields {
let field: FieldsUser = field.clone().into();
user.remove_field(&field);
}
} }
let mut partial: PartialUser = PartialUser { let mut partial: PartialUser = PartialUser {
@@ -124,9 +122,7 @@ pub async fn edit(
user.update( user.update(
db, db,
partial, partial,
data.remove data.remove.into_iter().map(Into::into).collect(),
.map(|v| v.into_iter().map(Into::into).collect())
.unwrap_or_default(),
) )
.await?; .await?;