feat: process some Undo activities, small refactor
This commit is contained in:
parent
b99ca9fa7e
commit
b1b0aee2f9
2 changed files with 59 additions and 38 deletions
|
@ -1,4 +1,4 @@
|
||||||
use apb::{server::Inbox, ActivityType, Base, BaseType, ObjectType};
|
use apb::{server::Inbox, Activity, ActivityType, Base, BaseType, ObjectType};
|
||||||
use axum::{extract::{Query, State}, http::StatusCode, Json};
|
use axum::{extract::{Query, State}, http::StatusCode, Json};
|
||||||
use sea_orm::{Order, QueryFilter, QueryOrder, QuerySelect};
|
use sea_orm::{Order, QueryFilter, QueryOrder, QuerySelect};
|
||||||
|
|
||||||
|
@ -52,48 +52,27 @@ pub async fn post(
|
||||||
Identity::Local(_user) => return Err(UpubError::forbidden()),
|
Identity::Local(_user) => return Err(UpubError::forbidden()),
|
||||||
Identity::Anonymous => return Err(UpubError::unauthorized()),
|
Identity::Anonymous => return Err(UpubError::unauthorized()),
|
||||||
}
|
}
|
||||||
match activity.base_type() {
|
|
||||||
None => { Err(StatusCode::BAD_REQUEST.into()) },
|
|
||||||
|
|
||||||
Some(BaseType::Link(_x)) => {
|
// TODO we could process Links and bare Objects maybe, but probably out of AP spec?
|
||||||
tracing::warn!("skipping remote activity: {}", serde_json::to_string_pretty(&activity).unwrap());
|
match activity.activity_type().ok_or_else(UpubError::bad_request)? {
|
||||||
Err(StatusCode::UNPROCESSABLE_ENTITY.into()) // we could but not yet
|
ActivityType::Activity => {
|
||||||
},
|
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Activity))) => {
|
|
||||||
tracing::warn!("skipping unprocessable base activity: {}", serde_json::to_string_pretty(&activity).unwrap());
|
tracing::warn!("skipping unprocessable base activity: {}", serde_json::to_string_pretty(&activity).unwrap());
|
||||||
Err(StatusCode::UNPROCESSABLE_ENTITY.into()) // won't ingest useless stuff
|
Err(StatusCode::UNPROCESSABLE_ENTITY.into()) // won't ingest useless stuff
|
||||||
},
|
},
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Delete))) =>
|
ActivityType::Delete => Ok(ctx.delete(activity).await?),
|
||||||
Ok(ctx.delete(activity).await?),
|
ActivityType::Follow => Ok(ctx.follow(activity).await?),
|
||||||
|
ActivityType::Accept(_) => Ok(ctx.accept(activity).await?),
|
||||||
|
ActivityType::Reject(_) => Ok(ctx.reject(activity).await?),
|
||||||
|
ActivityType::Like => Ok(ctx.like(activity).await?),
|
||||||
|
ActivityType::Create => Ok(ctx.create(activity).await?),
|
||||||
|
ActivityType::Update => Ok(ctx.update(activity).await?),
|
||||||
|
ActivityType::Undo => Ok(ctx.undo(activity).await?),
|
||||||
|
// ActivityType::Announce => Ok(ctx.announce(activity).await?),
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Follow))) =>
|
_x => {
|
||||||
Ok(ctx.follow(activity).await?),
|
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Accept(_)))) =>
|
|
||||||
Ok(ctx.accept(activity).await?),
|
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Reject(_)))) =>
|
|
||||||
Ok(ctx.reject(activity).await?),
|
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Like))) =>
|
|
||||||
Ok(ctx.like(activity).await?),
|
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Create))) =>
|
|
||||||
Ok(ctx.create(activity).await?),
|
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(ActivityType::Update))) =>
|
|
||||||
Ok(ctx.update(activity).await?),
|
|
||||||
|
|
||||||
Some(BaseType::Object(ObjectType::Activity(_x))) => {
|
|
||||||
tracing::info!("received unimplemented activity on inbox: {}", serde_json::to_string_pretty(&activity).unwrap());
|
tracing::info!("received unimplemented activity on inbox: {}", serde_json::to_string_pretty(&activity).unwrap());
|
||||||
Err(StatusCode::NOT_IMPLEMENTED.into())
|
Err(StatusCode::NOT_IMPLEMENTED.into())
|
||||||
},
|
},
|
||||||
|
|
||||||
Some(_x) => {
|
|
||||||
tracing::warn!("ignoring non-activity object in inbox: {}", serde_json::to_string_pretty(&activity).unwrap());
|
|
||||||
Err(StatusCode::UNPROCESSABLE_ENTITY.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use apb::{target::Addressed, Activity, Base, Object};
|
use apb::{target::Addressed, Activity, Base, Object};
|
||||||
use sea_orm::{sea_query::Expr, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, Set};
|
use reqwest::StatusCode;
|
||||||
|
use sea_orm::{sea_query::Expr, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, Set};
|
||||||
|
|
||||||
use crate::{errors::{LoggableError, UpubError}, model};
|
use crate::{errors::{LoggableError, UpubError}, model};
|
||||||
|
|
||||||
|
@ -181,7 +182,48 @@ impl apb::server::Inbox for Context {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn undo(&self, _activity: serde_json::Value) -> crate::Result<()> {
|
async fn undo(&self, activity: serde_json::Value) -> crate::Result<()> {
|
||||||
todo!()
|
let uid = activity.actor().id().ok_or_else(UpubError::bad_request)?;
|
||||||
|
// TODO in theory we could work with just object_id but right now only accept embedded
|
||||||
|
let undone_activity = activity.object().extract().ok_or_else(UpubError::bad_request)?;
|
||||||
|
let undone_aid = undone_activity.id().ok_or_else(UpubError::bad_request)?;
|
||||||
|
let undone_object_id = undone_activity.object().id().ok_or_else(UpubError::bad_request)?;
|
||||||
|
let activity_type = undone_activity.activity_type().ok_or_else(UpubError::bad_request)?;
|
||||||
|
|
||||||
|
match activity_type {
|
||||||
|
apb::ActivityType::Like => {
|
||||||
|
model::like::Entity::delete_many()
|
||||||
|
.filter(
|
||||||
|
Condition::all()
|
||||||
|
.add(model::like::Column::Actor.eq(&uid))
|
||||||
|
.add(model::like::Column::Likes.eq(&undone_object_id))
|
||||||
|
)
|
||||||
|
.exec(self.db())
|
||||||
|
.await?;
|
||||||
|
model::object::Entity::update_many()
|
||||||
|
.filter(model::object::Column::Id.eq(&undone_object_id))
|
||||||
|
.col_expr(model::object::Column::Likes, Expr::col(model::object::Column::Likes).sub(1))
|
||||||
|
.exec(self.db())
|
||||||
|
.await?;
|
||||||
|
},
|
||||||
|
apb::ActivityType::Follow => {
|
||||||
|
model::relation::Entity::delete_many()
|
||||||
|
.filter(
|
||||||
|
Condition::all()
|
||||||
|
.add(model::relation::Column::Follower.eq(&uid))
|
||||||
|
.add(model::relation::Column::Following.eq(&undone_object_id))
|
||||||
|
)
|
||||||
|
.exec(self.db())
|
||||||
|
.await?;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
tracing::error!("received 'Undo' for unimplemented activity: {}", serde_json::to_string_pretty(&activity).unwrap());
|
||||||
|
return Err(StatusCode::NOT_IMPLEMENTED.into());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
model::activity::Entity::delete_by_id(undone_aid).exec(self.db()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue