forked from alemi/upub
fix: when updating must reset changing fields
This commit is contained in:
parent
95ad0d92b7
commit
44de7040ec
2 changed files with 82 additions and 36 deletions
|
@ -1,6 +1,6 @@
|
||||||
use apb::{target::Addressed, Activity, Base, Object};
|
use apb::{target::Addressed, Activity, Base, Object};
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use sea_orm::{sea_query::Expr, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, Set};
|
use sea_orm::{sea_query::Expr, ActiveModelTrait, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, Set};
|
||||||
|
|
||||||
use crate::{errors::{LoggableError, UpubError}, model::{self, FieldError}};
|
use crate::{errors::{LoggableError, UpubError}, model::{self, FieldError}};
|
||||||
|
|
||||||
|
@ -238,12 +238,22 @@ impl apb::server::Inbox for Context {
|
||||||
// TODO oof here is an example of the weakness of this model, we have to go all the way
|
// TODO oof here is an example of the weakness of this model, we have to go all the way
|
||||||
// back up to serde_json::Value because impl Object != impl Actor
|
// back up to serde_json::Value because impl Object != impl Actor
|
||||||
let actor_model = model::user::Model::new(&object_node)?;
|
let actor_model = model::user::Model::new(&object_node)?;
|
||||||
model::user::Entity::update(actor_model.into_active_model())
|
let update_model = actor_model.into_active_model();
|
||||||
|
update_model.reset(model::user::Column::Name);
|
||||||
|
update_model.reset(model::user::Column::Summary);
|
||||||
|
update_model.reset(model::user::Column::Image);
|
||||||
|
update_model.reset(model::user::Column::Icon);
|
||||||
|
model::user::Entity::update(update_model)
|
||||||
.exec(self.db()).await?;
|
.exec(self.db()).await?;
|
||||||
},
|
},
|
||||||
Some(apb::ObjectType::Note) => {
|
Some(apb::ObjectType::Note) => {
|
||||||
let object_model = model::object::Model::new(&object_node)?;
|
let object_model = model::object::Model::new(&object_node)?;
|
||||||
model::object::Entity::update(object_model.into_active_model())
|
let update_model = object_model.into_active_model();
|
||||||
|
update_model.reset(model::object::Column::Name);
|
||||||
|
update_model.reset(model::object::Column::Summary);
|
||||||
|
update_model.reset(model::object::Column::Content);
|
||||||
|
update_model.reset(model::object::Column::Sensitive);
|
||||||
|
model::object::Entity::update(update_model)
|
||||||
.exec(self.db()).await?;
|
.exec(self.db()).await?;
|
||||||
},
|
},
|
||||||
Some(t) => tracing::warn!("no side effects implemented for update type {t:?}"),
|
Some(t) => tracing::warn!("no side effects implemented for update type {t:?}"),
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use apb::{target::Addressed, Activity, ActivityMut, BaseMut, Node, ObjectMut};
|
use apb::{target::Addressed, Activity, ActivityMut, ActorMut, BaseMut, Node, Object, ObjectMut, PublicKeyMut};
|
||||||
use sea_orm::{sea_query::Expr, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, Set};
|
use reqwest::StatusCode;
|
||||||
|
use sea_orm::{sea_query::Expr, ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, Set};
|
||||||
|
|
||||||
use crate::{errors::UpubError, model};
|
use crate::{errors::UpubError, model, routes::activitypub::jsonld::LD};
|
||||||
|
|
||||||
use super::{fetcher::Fetcher, Context};
|
use super::{fetcher::Fetcher, Context};
|
||||||
|
|
||||||
|
@ -299,34 +300,74 @@ impl apb::server::Outbox for Context {
|
||||||
async fn update(&self, uid: String, activity: serde_json::Value) -> crate::Result<String> {
|
async fn update(&self, uid: String, activity: serde_json::Value) -> crate::Result<String> {
|
||||||
let aid = self.aid(uuid::Uuid::new_v4().to_string());
|
let aid = self.aid(uuid::Uuid::new_v4().to_string());
|
||||||
let object_node = activity.object().extract().ok_or_else(UpubError::bad_request)?;
|
let object_node = activity.object().extract().ok_or_else(UpubError::bad_request)?;
|
||||||
let mut object_model = model::object::Model::new(
|
|
||||||
&object_node.set_published(Some(chrono::Utc::now()))
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let old_object_model = model::object::Entity::find_by_id(&object_model.id)
|
match object_node.object_type() {
|
||||||
.one(self.db())
|
Some(apb::ObjectType::Actor(_)) => {
|
||||||
.await?
|
let actor_model = model::user::Model::new(
|
||||||
.ok_or_else(UpubError::not_found)?;
|
&object_node
|
||||||
|
// TODO must set these, but we will ignore them
|
||||||
|
.set_actor_type(Some(apb::ActorType::Person))
|
||||||
|
.set_public_key(apb::Node::object(
|
||||||
|
serde_json::Value::new_object().set_public_key_pem("")
|
||||||
|
))
|
||||||
|
)?;
|
||||||
|
let old_actor_model = model::user::Entity::find_by_id(&actor_model.id)
|
||||||
|
.one(self.db())
|
||||||
|
.await?
|
||||||
|
.ok_or_else(UpubError::not_found)?;
|
||||||
|
|
||||||
// can't change local objects attributed to nobody
|
if old_actor_model.id != uid {
|
||||||
let author_id = old_object_model.attributed_to.ok_or_else(UpubError::forbidden)?;
|
// can't change user fields of others
|
||||||
if author_id != uid {
|
return Err(UpubError::forbidden());
|
||||||
// can't change objects of others
|
}
|
||||||
return Err(UpubError::forbidden());
|
|
||||||
|
if actor_model.name.is_none() { actor_model.name = old_actor_model.name }
|
||||||
|
if actor_model.summary.is_none() { actor_model.summary = old_actor_model.summary }
|
||||||
|
if actor_model.image.is_none() { actor_model.image = old_actor_model.image }
|
||||||
|
if actor_model.icon.is_none() { actor_model.icon = old_actor_model.icon }
|
||||||
|
|
||||||
|
let update_model = actor_model.into_active_model();
|
||||||
|
update_model.reset(model::user::Column::Name);
|
||||||
|
update_model.reset(model::user::Column::Summary);
|
||||||
|
update_model.reset(model::user::Column::Image);
|
||||||
|
update_model.reset(model::user::Column::Icon);
|
||||||
|
|
||||||
|
model::user::Entity::update(update_model)
|
||||||
|
.exec(self.db()).await?;
|
||||||
|
},
|
||||||
|
Some(apb::ObjectType::Note) => {
|
||||||
|
let mut object_model = model::object::Model::new(
|
||||||
|
&object_node.set_published(Some(chrono::Utc::now()))
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let old_object_model = model::object::Entity::find_by_id(&object_model.id)
|
||||||
|
.one(self.db())
|
||||||
|
.await?
|
||||||
|
.ok_or_else(UpubError::not_found)?;
|
||||||
|
|
||||||
|
// can't change local objects attributed to nobody
|
||||||
|
let author_id = old_object_model.attributed_to.ok_or_else(UpubError::forbidden)?;
|
||||||
|
if author_id != uid {
|
||||||
|
// can't change objects of others
|
||||||
|
return Err(UpubError::forbidden());
|
||||||
|
}
|
||||||
|
|
||||||
|
if object_model.name.is_none() { object_model.name = old_object_model.name }
|
||||||
|
if object_model.summary.is_none() { object_model.summary = old_object_model.summary }
|
||||||
|
if object_model.content.is_none() { object_model.content = old_object_model.content }
|
||||||
|
|
||||||
|
let update_model = object_model.into_active_model();
|
||||||
|
update_model.reset(model::object::Column::Name);
|
||||||
|
update_model.reset(model::object::Column::Summary);
|
||||||
|
update_model.reset(model::object::Column::Content);
|
||||||
|
update_model.reset(model::object::Column::Sensitive);
|
||||||
|
|
||||||
|
model::object::Entity::update(update_model)
|
||||||
|
.exec(self.db()).await?;
|
||||||
|
},
|
||||||
|
_ => return Err(UpubError::Status(StatusCode::NOT_IMPLEMENTED)),
|
||||||
}
|
}
|
||||||
|
|
||||||
object_model.id = old_object_model.id;
|
|
||||||
object_model.attributed_to = Some(uid.clone());
|
|
||||||
object_model.context = old_object_model.context;
|
|
||||||
object_model.likes = old_object_model.likes;
|
|
||||||
object_model.shares = old_object_model.shares;
|
|
||||||
object_model.comments = old_object_model.comments;
|
|
||||||
object_model.bto = old_object_model.bto;
|
|
||||||
object_model.to = old_object_model.to;
|
|
||||||
object_model.bcc = old_object_model.bcc;
|
|
||||||
object_model.cc = old_object_model.cc;
|
|
||||||
object_model.published = old_object_model.published;
|
|
||||||
|
|
||||||
let addressed = activity.addressed();
|
let addressed = activity.addressed();
|
||||||
let activity_model = model::activity::Model::new(
|
let activity_model = model::activity::Model::new(
|
||||||
&activity
|
&activity
|
||||||
|
@ -335,13 +376,8 @@ impl apb::server::Outbox for Context {
|
||||||
.set_published(Some(chrono::Utc::now()))
|
.set_published(Some(chrono::Utc::now()))
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
model::object::Entity::update(object_model.into_active_model())
|
|
||||||
.exec(self.db())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
model::activity::Entity::insert(activity_model.into_active_model())
|
model::activity::Entity::insert(activity_model.into_active_model())
|
||||||
.exec(self.db())
|
.exec(self.db()).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.dispatch(&uid, addressed, &aid, None).await?;
|
self.dispatch(&uid, addressed, &aid, None).await?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue