fix: object updates should only touch some fields

also reject updates for other types
This commit is contained in:
əlemi 2024-10-02 22:10:37 +02:00
parent 232069d56a
commit 30e647fc12
Signed by: alemi
GPG key ID: A4895B84D311642C

View file

@ -1,6 +1,6 @@
use apb::{field::OptionalString, target::Addressed, Activity, ActivityMut, Actor, Base, BaseMut, Object, ObjectMut}; use apb::{field::OptionalString, target::Addressed, Activity, ActivityMut, Base, BaseMut, Object, ObjectMut};
use sea_orm::{prelude::Expr, ColumnTrait, DbErr, EntityTrait, QueryFilter, QueryOrder, QuerySelect, SelectColumns, TransactionTrait}; use sea_orm::{prelude::Expr, ColumnTrait, DbErr, EntityTrait, QueryFilter, QueryOrder, QuerySelect, SelectColumns, TransactionTrait};
use upub::{model::{self, actor::Field}, traits::{Addresser, Processor}, Context}; use upub::{model::{self, actor::Field}, traits::{process::ProcessorError, Addresser, Processor}, Context};
pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<()> { pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<()> {
@ -65,38 +65,66 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
activity = activity.set_object(apb::Node::object(undone)); activity = activity.set_object(apb::Node::object(undone));
} }
macro_rules! update {
($prev:ident, $field:ident, $getter:expr) => {
if let Some($field) = $getter {
$prev.$field = Some($field.to_string());
}
};
}
if matches!(t, apb::ObjectType::Activity(apb::ActivityType::Update)) { if matches!(t, apb::ObjectType::Activity(apb::ActivityType::Update)) {
let mut updated = activity.object().extract().ok_or(crate::JobError::MissingPayload)?; let mut updated = activity.object().extract().ok_or(crate::JobError::MissingPayload)?;
if updated.actor_type().is_ok() { match updated.object_type()? {
let mut prev = model::actor::Entity::find_by_ap_id(updated.id()?) apb::ObjectType::Actor(_) => {
.one(&tx) let mut prev = model::actor::Entity::find_by_ap_id(updated.id()?)
.await? .one(&tx)
.ok_or_else(|| crate::JobError::MissingPayload)?; .await?
if prev.id != job.actor { .ok_or_else(|| crate::JobError::MissingPayload)?;
return Err(crate::JobError::Forbidden);
} if prev.id != job.actor {
if let Some(name) = updated.name().str() { return Err(crate::JobError::Forbidden);
prev.name = Some(name); }
}
if let Some(summary) = updated.summary().str() { update!(prev, name, updated.name().ok());
prev.summary = Some(summary); update!(prev, summary, updated.summary().ok());
} update!(prev, icon, updated.icon().get().and_then(|x| x.url().id().str()));
if let Some(icon) = updated.icon().get().and_then(|x| x.url().id().str()) { update!(prev, image, updated.image().get().and_then(|x| x.url().id().str()));
prev.icon = Some(icon);
} if !updated.attachment().is_empty() {
if let Some(image) = updated.image().get().and_then(|x| x.url().id().str()) { prev.fields = updated.attachment()
prev.image = Some(image); .flat()
} .into_iter()
if !updated.attachment().is_empty() { .filter_map(|x| x.extract())
prev.fields = updated.attachment() .map(Field::from)
.flat() .collect::<Vec<Field>>()
.into_iter() .into();
.filter_map(|x| x.extract()) }
.map(Field::from)
.collect::<Vec<Field>>() updated = prev.ap();
.into(); },
} apb::ObjectType::Note => {
updated = prev.ap(); let mut prev = model::object::Entity::find_by_ap_id(updated.id()?)
.one(&tx)
.await?
.ok_or_else(|| crate::JobError::MissingPayload)?;
if prev.attributed_to.as_ref() != Some(&job.actor) {
return Err(crate::JobError::Forbidden);
}
update!(prev, name, updated.name().ok());
update!(prev, summary, updated.summary().ok());
update!(prev, content, updated.content().ok());
update!(prev, image, updated.image().get().and_then(|x| x.url().id().str()));
if let Ok(sensitive) = updated.sensitive() {
prev.sensitive = sensitive;
}
updated = prev.ap();
},
t => return Err(crate::JobError::ProcessorError(ProcessorError::Unprocessable(format!("{t}")))),
} }
activity = activity.set_object(apb::Node::object(updated)); activity = activity.set_object(apb::Node::object(updated));
} }