Prepare Actions for use outside of activitypub paths

Catch (but not fix) but related to unfollowing durin blocks
This commit is contained in:
asonix 2021-01-05 00:09:59 -06:00
parent 8552d10cdc
commit 6ffc4e9fa3
20 changed files with 539 additions and 313 deletions

View file

@ -36,7 +36,7 @@ pub(crate) fn block(
if let Some(true) = context.store.profiles.is_local(object)? {
return Ok(Ok(Box::new(CreateBlock {
apub_id: id.to_owned(),
block_apub_id: Some(id.to_owned()),
blocked_profile: object,
blocked_by_profile: actor,
published: published.into(),
@ -59,12 +59,8 @@ pub(crate) fn undo_block(
}
let block_id = block.id_unchecked().req()?;
let id = recover!(block_id, context.apub.id_for_apub(block_id)?);
let id = id.block().req()?;
Ok(Ok(Box::new(DeleteBlock {
apub_id: block_id.to_owned(),
block_id: id,
})))
Ok(Ok(Box::new(DeleteBlock { block_id: id })))
}

View file

@ -1,7 +1,7 @@
use crate::{
apub::actions::{
AcceptFollowRequest, CreateFollowRequest, DeleteFollow, DeleteFollowRequest,
RejectFollowRequest,
AcceptFollowRequest, CreateFollowRequest, RejectFollowRequest, UndoAcceptFollow,
UndoFollow, UndoFollowRequest,
},
recover,
store::view::Relationship,
@ -52,7 +52,7 @@ pub(crate) fn follow(
let object = object.profile().req()?;
Ok(Ok(Box::new(CreateFollowRequest {
apub_id: follow_id.to_owned(),
follow_apub_id: Some(follow_id.to_owned()),
followed_profile: object,
followed_by_profile: actor,
published: published.into(),
@ -81,7 +81,6 @@ pub(crate) fn reject_follow(
}
Ok(Ok(Box::new(RejectFollowRequest {
apub_id: follow_id.to_owned(),
follow_request_id: id,
})))
}
@ -111,7 +110,7 @@ pub(crate) fn accept_follow(
}
Ok(Ok(Box::new(AcceptFollowRequest {
apub_id: accept_id.to_owned(),
accept_apub_id: Some(accept_id.to_owned()),
follow_request_id: id,
published: published.into(),
})))
@ -146,8 +145,8 @@ pub(crate) fn undo_follow(
.by_forward(follow_object, follow_actor)?;
if let Some(follow_id) = follow_id_opt {
return Ok(Ok(Box::new(DeleteFollow {
apub_id: follow_object_id.to_owned(),
return Ok(Ok(Box::new(UndoFollow {
follow_apub_id: follow_object_id.to_owned(),
follow_id,
})));
}
@ -159,10 +158,7 @@ pub(crate) fn undo_follow(
.by_forward(follow_object, follow_actor)?
.req()?;
Ok(Ok(Box::new(DeleteFollowRequest {
apub_id: follow_object_id.to_owned(),
follow_request_id,
})))
Ok(Ok(Box::new(UndoFollowRequest { follow_request_id })))
}
pub(crate) fn undo_accept_follow(
@ -188,8 +184,8 @@ pub(crate) fn undo_accept_follow(
return Ok(Err(e));
}
Ok(Ok(Box::new(DeleteFollow {
apub_id: follow_id.to_owned(),
Ok(Ok(Box::new(UndoAcceptFollow {
follow_apub_id: follow_id.to_owned(),
follow_id: id,
})))
}

View file

@ -27,7 +27,7 @@ pub(crate) fn like(
if let Some(submission_id) = object_id.submission() {
return Ok(Ok(Box::new(CreateReact {
apub_id: like_id.to_owned(),
like_apub_id: Some(like_id.to_owned()),
submission_id,
profile_id: actor_id,
comment_id: None,
@ -45,7 +45,7 @@ pub(crate) fn like(
.submission_id();
return Ok(Ok(Box::new(CreateReact {
apub_id: like_id.to_owned(),
like_apub_id: Some(like_id.to_owned()),
submission_id,
profile_id: actor_id,
comment_id: Some(comment_id),
@ -99,8 +99,5 @@ pub(crate) fn undo_like(
}
}
Ok(Ok(Box::new(DeleteReact {
apub_id: like_id.to_owned(),
react_id,
})))
Ok(Ok(Box::new(DeleteReact { react_id })))
}

View file

@ -62,7 +62,7 @@ pub(crate) fn note(
if let Some(submission_id) = in_reply_to.submission() {
return Ok(Ok(Box::new(CreateComment {
apub_id: note_id.to_owned(),
note_apub_id: Some(note_id.to_owned()),
submission_id,
profile_id,
comment_id: None,
@ -80,7 +80,7 @@ pub(crate) fn note(
.submission_id();
return Ok(Ok(Box::new(CreateComment {
apub_id: note_id.to_owned(),
note_apub_id: Some(note_id.to_owned()),
submission_id,
profile_id,
comment_id: Some(comment_id),
@ -129,7 +129,7 @@ pub(crate) fn note(
}
return Ok(Ok(Box::new(CreateSubmission {
apub_id: note_id.to_owned(),
note_apub_id: Some(note_id.to_owned()),
profile_id,
title: title.to_owned(),
description,
@ -198,6 +198,7 @@ pub(crate) fn update_note(
note: &activitystreams::object::Note,
context: &Context,
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
let update_id = update.id_unchecked().req()?;
let actor_id = update.actor()?.as_single_id().req()?;
let attributed_to = note.attributed_to().req()?.as_single_id().req()?;
@ -222,7 +223,11 @@ pub(crate) fn update_note(
.and_then(|c| c.as_single_xsd_string())
.map(|s| s.to_owned());
return Ok(Ok(Box::new(UpdateComment { comment_id, body })));
return Ok(Ok(Box::new(UpdateComment {
update_apub_id: Some(update_id.to_owned()),
comment_id,
body,
})));
}
let submission_id = note_id.submission().req()?;
@ -304,7 +309,7 @@ pub(crate) fn delete_note(
}
return Ok(Ok(Box::new(DeleteComment {
apub_id: note_object_id.to_owned(),
note_apub_id: note_object_id.to_owned(),
comment_id,
})));
}
@ -316,8 +321,5 @@ pub(crate) fn delete_note(
return Err(Error::Invalid);
}
Ok(Ok(Box::new(DeleteSubmission {
apub_id: note_object_id.to_owned(),
submission_id,
})))
Ok(Ok(Box::new(DeleteSubmission { submission_id })))
}

View file

@ -82,7 +82,7 @@ pub(crate) fn person(
.unwrap_or(true);
Ok(Ok(Box::new(CreateProfile {
apub_id: id.to_owned(),
person_apub_id: Some(id.to_owned()),
owner_source: OwnerSource::Remote(id.to_string()),
handle,
domain,
@ -177,8 +177,5 @@ pub(crate) fn delete_person(
let profile_id = recover!(id, context.apub.id_for_apub(id)?);
let profile_id = profile_id.profile().req()?;
Ok(Ok(Box::new(DeleteProfile {
apub_id: id.to_owned(),
profile_id,
})))
Ok(Ok(Box::new(DeleteProfile { profile_id })))
}

View file

@ -1,17 +1,19 @@
use crate::{
apub::actions::{CreateBlock, DeleteBlock, DeleteFollow, RejectFollowRequest},
Action, Context, Error, Required,
apub::actions::{CreateBlock, DeleteBlock, RejectFollowRequest, UndoFollow},
Action, Completed, Context, Error, Required,
};
impl Action for CreateBlock {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let block = context.store.view.blocks.new(
self.blocked_profile,
self.blocked_by_profile,
self.published,
)?;
context.apub.block(&self.apub_id, block.id)?;
if let Some(apub_id) = &self.block_apub_id {
context.apub.block(&apub_id, block.id)?;
}
if let Ok(Some(follow_request_id)) = context
.store
@ -19,17 +21,7 @@ impl Action for CreateBlock {
.follow_requests
.by_forward(self.blocked_profile, self.blocked_by_profile)
{
let apub_id = context
.apub
.apub_for_follow_request(follow_request_id)?
.req()?;
Action::perform(
&RejectFollowRequest {
apub_id,
follow_request_id,
},
context,
)?;
Action::perform(&RejectFollowRequest { follow_request_id }, context)?;
}
if let Ok(Some(follow_request_id)) = context
@ -38,17 +30,7 @@ impl Action for CreateBlock {
.follow_requests
.by_backward(self.blocked_by_profile, self.blocked_profile)
{
let apub_id = context
.apub
.apub_for_follow_request(follow_request_id)?
.req()?;
Action::perform(
&RejectFollowRequest {
apub_id,
follow_request_id,
},
context,
)?;
Action::perform(&RejectFollowRequest { follow_request_id }, context)?;
}
if let Ok(Some(follow_id)) = context
@ -57,8 +39,17 @@ impl Action for CreateBlock {
.follows
.by_forward(self.blocked_profile, self.blocked_by_profile)
{
let apub_id = context.apub.apub_for_follow(follow_id)?.req()?;
Action::perform(&DeleteFollow { apub_id, follow_id }, context)?;
unimplemented!();
/*
let follow_apub_id = context.apub.apub_for_follow_request(follow_id)?.req()?;
Action::perform(
&UndoFollow {
follow_apub_id,
follow_id,
},
context,
)?;
*/
}
if let Ok(Some(follow_id)) = context
@ -67,18 +58,44 @@ impl Action for CreateBlock {
.follows
.by_backward(self.blocked_by_profile, self.blocked_profile)
{
let apub_id = context.apub.apub_for_follow(follow_id)?.req()?;
Action::perform(&DeleteFollow { apub_id, follow_id }, context)?;
unimplemented!();
/*
let follow_apub_id = context.apub.apub_for_follow_request(follow_id)?.req()?;
Action::perform(
&DeleteFollow {
follow_apub_id,
follow_id,
},
context,
)?;
*/
}
Ok(())
if context.is_local(self.blocked_by_profile)? && !context.is_local(self.blocked_profile)? {
return Ok(Some(Box::new(crate::apub::results::Block {
block_id: block.id,
})));
}
Ok(None)
}
}
impl Action for DeleteBlock {
fn perform(&self, context: &Context) -> Result<(), Error> {
context.store.view.blocks.remove(self.block_id)?;
context.apub.delete_object(&self.apub_id)?;
Ok(())
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let opt = context.store.view.blocks.remove(self.block_id)?;
let block_apub_id = context.apub.apub_for_block(self.block_id)?.req()?;
context.apub.delete_object(&block_apub_id)?;
if let Some(undo_block) = opt {
if context.is_local(undo_block.0.right)? {
return Ok(Some(Box::new(crate::apub::results::UndoBlock {
block_apub_id,
profile_id: undo_block.0.right,
})));
}
}
Ok(None)
}
}

View file

@ -1,10 +1,10 @@
use crate::{
apub::actions::{AnnounceComment, CreateComment, DeleteComment, DeleteReact, UpdateComment},
Action, Context, Error, Required,
Action, Completed, Context, Error, Required,
};
impl Action for CreateComment {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let submissioner_id = context
.store
.submissions
@ -37,10 +37,12 @@ impl Action for CreateComment {
self.published,
)?;
context.apub.comment(&self.apub_id, comment.id())?;
if let Some(apub_id) = &self.note_apub_id {
context.apub.comment(apub_id, comment.id())?;
}
if let Some(commenter_id) = comment_data {
if let Ok(Some(true)) = context.store.profiles.is_local(commenter_id) {
if let Ok(true) = context.is_local(commenter_id) {
context
.store
.view
@ -49,7 +51,7 @@ impl Action for CreateComment {
}
};
if let Ok(Some(true)) = context.store.profiles.is_local(submissioner_id) {
if let Ok(true) = context.is_local(submissioner_id) {
context
.store
.view
@ -57,18 +59,33 @@ impl Action for CreateComment {
.new(submissioner_id, comment.id(), self.published);
}
Ok(())
if context.is_local(self.profile_id)? {
return Ok(Some(Box::new(crate::apub::results::CommentCreated {
comment_id: comment.id(),
})));
}
if context.is_local(submissioner_id)? {
if let Some(apub_id) = &self.note_apub_id {
return Ok(Some(Box::new(crate::apub::results::RemoteCommentCreated {
note_apub_id: apub_id.clone(),
profile_id: submissioner_id,
})));
}
}
Ok(None)
}
}
impl Action for AnnounceComment {
fn perform(&self, _: &Context) -> Result<(), Error> {
Ok(())
fn perform(&self, _: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
Ok(None)
}
}
impl Action for UpdateComment {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let comment = context.store.comments.by_id(self.comment_id)?.req()?;
let mut changes = comment.update();
@ -77,24 +94,45 @@ impl Action for UpdateComment {
}
context.store.comments.update(&changes)?;
Ok(())
if context.is_local(comment.profile_id())? {
return Ok(Some(Box::new(crate::apub::results::CommentUpdated {
comment_id: comment.id(),
})));
}
let submissioner_id = context
.store
.submissions
.by_id(comment.submission_id())?
.req()?
.profile_id();
if context.is_local(submissioner_id)? {
if let Some(apub_id) = &self.update_apub_id {
return Ok(Some(Box::new(crate::apub::results::RemoteCommentUpdated {
update_apub_id: apub_id.to_owned(),
profile_id: submissioner_id,
})));
}
}
Ok(None)
}
}
fn delete_react(react_id: uuid::Uuid, context: &Context) -> Result<(), Error> {
let apub_id = context.apub.apub_for_react(react_id)?.req()?;
Action::perform(&DeleteReact { apub_id, react_id }, context)?;
Action::perform(&DeleteReact { react_id }, context)?;
Ok(())
}
impl Action for DeleteComment {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let opt = context.store.comments.delete(self.comment_id)?;
context.store.view.comments.remove(self.comment_id);
context.apub.delete_object(&self.apub_id)?;
context.apub.delete_object(&self.note_apub_id)?;
if opt.is_some() {
let comment_id = self.comment_id;
if let Some(undo_comment) = opt {
let comment_id = undo_comment.0.id();
let context_clone = context.clone();
context.spawn_blocking(move || {
@ -104,8 +142,28 @@ impl Action for DeleteComment {
}
}
});
if context.is_local(undo_comment.0.profile_id())? {
return Ok(Some(Box::new(crate::apub::results::CommentCreated {
comment_id: undo_comment.0.id(),
})));
}
let submissioner_id = context
.store
.submissions
.by_id(undo_comment.0.submission_id())?
.req()?
.profile_id();
if context.is_local(submissioner_id)? {
return Ok(Some(Box::new(crate::apub::results::RemoteCommentCreated {
note_apub_id: self.note_apub_id.clone(),
profile_id: submissioner_id,
})));
}
}
Ok(())
Ok(None)
}
}

View file

@ -1,9 +1,44 @@
use crate::{apub::actions::DeleteFollow, Action, Context, Error};
use crate::{
apub::actions::{UndoAcceptFollow, UndoFollow},
Action, Completed, Context, Error, Required,
};
impl Action for DeleteFollow {
fn perform(&self, context: &Context) -> Result<(), Error> {
context.store.view.follows.remove(self.follow_id)?;
context.apub.delete_object(&self.apub_id)?;
Ok(())
impl Action for UndoFollow {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let opt = context.store.view.follows.remove(self.follow_id)?;
let accept_apub_id = context.apub.apub_for_follow(self.follow_id)?.req()?;
context.apub.delete_object(&accept_apub_id)?;
context.apub.delete_object(&self.follow_apub_id)?;
if let Some(undo_follow) = opt {
if context.is_local(undo_follow.0.right)? {
return Ok(Some(Box::new(crate::apub::results::UndoFollow {
follow_apub_id: self.follow_apub_id.clone(),
profile_id: undo_follow.0.right,
})));
}
}
Ok(None)
}
}
impl Action for UndoAcceptFollow {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let opt = context.store.view.follows.remove(self.follow_id)?;
let accept_apub_id = context.apub.apub_for_follow(self.follow_id)?.req()?;
context.apub.delete_object(&accept_apub_id)?;
context.apub.delete_object(&self.follow_apub_id)?;
if let Some(undo_follow) = opt {
if context.is_local(undo_follow.0.right)? {
return Ok(Some(Box::new(crate::apub::results::UndoAcceptFollow {
accept_apub_id,
profile_id: undo_follow.0.right,
})));
}
}
Ok(None)
}
}

View file

@ -1,12 +1,12 @@
use crate::{
apub::actions::{
AcceptFollowRequest, CreateFollowRequest, DeleteFollowRequest, RejectFollowRequest,
AcceptFollowRequest, CreateFollowRequest, RejectFollowRequest, UndoFollowRequest,
},
Action, Context, Error,
Action, Completed, Context, Error, Required,
};
impl Action for CreateFollowRequest {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
context.check_block(self.followed_by_profile, self.followed_profile)?;
let follow_request = context.store.view.follow_requests.new(
@ -15,11 +15,11 @@ impl Action for CreateFollowRequest {
self.published,
)?;
context
.apub
.follow_request(&self.apub_id, follow_request.id)?;
if let Some(apub_id) = &self.follow_apub_id {
context.apub.follow_request(apub_id, follow_request.id)?;
}
if let Ok(Some(true)) = context.store.profiles.is_local(self.followed_profile) {
if let Ok(true) = context.is_local(self.followed_profile) {
context.store.view.follow_request_notifs.new(
self.followed_profile,
follow_request.id,
@ -27,12 +27,20 @@ impl Action for CreateFollowRequest {
);
}
Ok(())
if context.is_local(self.followed_by_profile)?
&& !context.is_local(self.followed_profile)?
{
return Ok(Some(Box::new(crate::apub::results::Follow {
follow_request_id: follow_request.id,
})));
}
Ok(None)
}
}
impl Action for AcceptFollowRequest {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let opt = context
.store
.view
@ -52,15 +60,29 @@ impl Action for AcceptFollowRequest {
self.published,
)?;
context.apub.follow(&self.apub_id, follow.id)?;
if let Some(apub_id) = &self.accept_apub_id {
context.apub.follow(apub_id, follow.id)?;
}
if context.is_local(follow.right)? && !context.is_local(follow.left)? {
let follow_apub_id = context
.apub
.apub_for_follow_request(undo_follow_request.0.id)?
.req()?;
return Ok(Some(Box::new(crate::apub::results::AcceptFollow {
follow_apub_id,
profile_id: follow.left,
follow_id: follow.id,
})));
}
}
Ok(())
Ok(None)
}
}
impl Action for RejectFollowRequest {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let opt = context
.store
.view
@ -68,21 +90,34 @@ impl Action for RejectFollowRequest {
.remove(self.follow_request_id)?;
if let Some(undo_follow_request) = opt {
let follow_apub_id = context
.apub
.apub_for_follow_request(self.follow_request_id)?
.req()?;
context.apub.delete_object(&follow_apub_id)?;
context
.store
.view
.follow_request_notifs
.remove(undo_follow_request.0.id);
if context.is_local(undo_follow_request.0.left)?
&& !context.is_local(undo_follow_request.0.right)?
{
return Ok(Some(Box::new(crate::apub::results::RejectFollow {
follow_apub_id,
profile_id: undo_follow_request.0.left,
})));
}
}
context.apub.delete_object(&self.apub_id)?;
Ok(())
Ok(None)
}
}
impl Action for DeleteFollowRequest {
fn perform(&self, context: &Context) -> Result<(), Error> {
impl Action for UndoFollowRequest {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let opt = context
.store
.view
@ -90,15 +125,28 @@ impl Action for DeleteFollowRequest {
.remove(self.follow_request_id)?;
if let Some(undo_follow_request) = opt {
let follow_apub_id = context
.apub
.apub_for_follow_request(self.follow_request_id)?
.req()?;
context.apub.delete_object(&follow_apub_id)?;
context
.store
.view
.follow_request_notifs
.remove(undo_follow_request.0.id);
if context.is_local(undo_follow_request.0.right)?
&& !context.is_local(undo_follow_request.0.left)?
{
return Ok(Some(Box::new(crate::apub::results::UndoFollow {
follow_apub_id,
profile_id: undo_follow_request.0.right,
})));
}
}
context.apub.delete_object(&self.apub_id)?;
Ok(())
Ok(None)
}
}

View file

@ -15,7 +15,7 @@ mod submission;
pub(crate) use apub::ingest;
pub struct CreateReact {
apub_id: Url,
like_apub_id: Option<Url>,
submission_id: Uuid,
profile_id: Uuid,
comment_id: Option<Uuid>,
@ -24,12 +24,11 @@ pub struct CreateReact {
}
pub struct DeleteReact {
apub_id: Url,
react_id: Uuid,
}
pub struct CreateComment {
apub_id: Url,
note_apub_id: Option<Url>,
submission_id: Uuid,
profile_id: Uuid,
comment_id: Option<Uuid>,
@ -40,17 +39,18 @@ pub struct CreateComment {
pub struct AnnounceComment;
pub struct UpdateComment {
update_apub_id: Option<Url>,
comment_id: Uuid,
body: Option<String>,
}
pub struct DeleteComment {
apub_id: Url,
note_apub_id: Url,
comment_id: Uuid,
}
pub struct CreateSubmission {
apub_id: Url,
note_apub_id: Option<Url>,
profile_id: Uuid,
title: String,
description: Option<String>,
@ -69,12 +69,11 @@ pub struct UpdateSubmission {
}
pub struct DeleteSubmission {
apub_id: Url,
submission_id: Uuid,
}
pub struct CreateProfile {
apub_id: Url,
person_apub_id: Option<Url>,
owner_source: OwnerSource,
handle: String,
domain: String,
@ -100,46 +99,47 @@ pub struct UpdateProfile {
}
pub struct DeleteProfile {
apub_id: Url,
profile_id: Uuid,
}
pub struct CreateFollowRequest {
apub_id: Url,
follow_apub_id: Option<Url>,
followed_profile: Uuid,
followed_by_profile: Uuid,
published: DateTime<Utc>,
}
pub struct AcceptFollowRequest {
apub_id: Url,
accept_apub_id: Option<Url>,
follow_request_id: Uuid,
published: DateTime<Utc>,
}
pub struct RejectFollowRequest {
apub_id: Url,
follow_request_id: Uuid,
}
pub struct DeleteFollowRequest {
apub_id: Url,
pub struct UndoFollowRequest {
follow_request_id: Uuid,
}
pub struct CreateBlock {
apub_id: Url,
block_apub_id: Option<Url>,
blocked_profile: Uuid,
blocked_by_profile: Uuid,
published: DateTime<Utc>,
}
pub struct DeleteBlock {
apub_id: Url,
block_id: Uuid,
}
pub struct DeleteFollow {
apub_id: Url,
pub struct UndoFollow {
follow_apub_id: Url,
follow_id: Uuid,
}
pub struct UndoAcceptFollow {
follow_apub_id: Url,
follow_id: Uuid,
}

View file

@ -1,10 +1,10 @@
use crate::{
apub::actions::{CreateProfile, DeleteProfile, DeleteSubmission, UpdateProfile},
Action, Context, Error, Required,
Action, Completed, Context, Error, Required,
};
impl Action for CreateProfile {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let profile = context.store.profiles.create(
self.owner_source.clone(),
&self.handle,
@ -38,14 +38,23 @@ impl Action for CreateProfile {
context
.apub
.store_public_key(profile.id(), &self.public_key_id, &self.public_key)?;
context.apub.profile(&self.apub_id, profile.id())?;
Ok(())
if let Some(apub_id) = &self.person_apub_id {
context.apub.profile(apub_id, profile.id())?;
}
if profile.owner_source().is_local() {
return Ok(Some(Box::new(crate::apub::results::ProfileCreated {
profile_id: profile.id(),
})));
}
Ok(None)
}
}
impl Action for UpdateProfile {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let profile = context.store.profiles.by_id(self.profile_id)?.req()?;
let mut changes = profile.update();
@ -74,28 +83,30 @@ impl Action for UpdateProfile {
.apub
.store_public_key(profile.id(), &self.public_key_id, &self.public_key)?;
Ok(())
if profile.owner_source().is_local() {
return Ok(Some(Box::new(crate::apub::results::ProfileUpdated {
profile_id: profile.id(),
})));
}
Ok(None)
}
}
fn delete_submission(submission_id: uuid::Uuid, context: &Context) -> Result<(), Error> {
let apub_id = context.apub.apub_for_submission(submission_id)?.req()?;
Action::perform(
&DeleteSubmission {
apub_id,
submission_id,
},
context,
)?;
Action::perform(&DeleteSubmission { submission_id }, context)?;
Ok(())
}
impl Action for DeleteProfile {
fn perform(&self, context: &Context) -> Result<(), Error> {
let opt = context.store.profiles.delete(self.profile_id)?;
context.apub.delete_object(&self.apub_id)?;
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let profile_id = self.profile_id;
let opt = context.store.profiles.delete(profile_id)?;
if let Some(undo_profile) = opt {
let person_apub_id = context.apub.apub_for_profile(profile_id)?.req()?;
context.apub.delete_object(&person_apub_id)?;
if let Some(banner) = undo_profile.0.banner() {
context.spawner.purge_file(banner);
}
@ -103,7 +114,6 @@ impl Action for DeleteProfile {
context.spawner.purge_file(icon);
}
let profile_id = self.profile_id;
let context_clone = context.clone();
context.spawn_blocking(move || {
@ -113,8 +123,14 @@ impl Action for DeleteProfile {
}
}
});
if undo_profile.0.owner_source().is_local() {
return Ok(Some(Box::new(crate::apub::results::ProfileDeleted {
profile_id,
})));
}
}
Ok(())
Ok(None)
}
}

View file

@ -1,10 +1,10 @@
use crate::{
apub::actions::{CreateReact, DeleteReact},
Action, Context, Error, Required,
Action, Completed, Context, Error, Required,
};
impl Action for CreateReact {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let submissioner_id = context
.store
.submissions
@ -37,7 +37,9 @@ impl Action for CreateReact {
self.published,
)?;
context.apub.react(&self.apub_id, react.id())?;
if let Some(apub_id) = &self.like_apub_id {
context.apub.react(&apub_id, react.id())?;
}
let notifier_id = commenter_id.unwrap_or(submissioner_id);
@ -49,16 +51,37 @@ impl Action for CreateReact {
.new(notifier_id, react.id(), self.published);
}
Ok(())
if context.is_local(react.profile_id())? {
return Ok(Some(Box::new(crate::apub::results::React {
react_id: react.id(),
})));
}
Ok(None)
}
}
impl Action for DeleteReact {
fn perform(&self, context: &Context) -> Result<(), Error> {
context.store.reacts.delete(self.react_id)?;
context.store.view.reacts.remove(self.react_id);
context.apub.delete_object(&self.apub_id)?;
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let react_id = self.react_id;
let opt = context.store.reacts.delete(react_id)?;
Ok(())
if let Some(undo_react) = opt {
context.store.view.reacts.remove(react_id);
let like_apub_id = context.apub.apub_for_react(react_id)?.req()?;
context.apub.delete_object(&like_apub_id)?;
let profile_id = undo_react.0.profile_id();
if context.is_local(profile_id)? {
return Ok(Some(Box::new(crate::apub::results::UndoReact {
like_apub_id,
profile_id,
})));
}
}
Ok(None)
}
}

View file

@ -2,18 +2,20 @@ use crate::{
apub::actions::{
AnnounceSubmission, CreateSubmission, DeleteComment, DeleteSubmission, UpdateSubmission,
},
Action, Context, Error, Required,
Action, Completed, Context, Error, Required,
};
use std::collections::HashSet;
impl Action for CreateSubmission {
fn perform(&self, context: &Context) -> Result<(), Error> {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let submission =
context
.store
.submissions
.create(self.profile_id, &self.title, self.visibility)?;
let submission_id = submission.id();
let mut changes = submission.update();
changes.publish(Some(self.published));
if let Some(description) = &self.description {
@ -28,41 +30,45 @@ impl Action for CreateSubmission {
}
let submission = context.store.submissions.update_files(&changes)?;
context.apub.submission(&self.apub_id, submission.id())?;
if let Some(apub_id) = &self.note_apub_id {
context.apub.submission(apub_id, submission_id)?;
}
let submission_id = submission.id();
let profile_id = self.profile_id;
let published = submission.published().req()?;
let context_clone = context.clone();
context.arbiter.send(Box::pin(async move {
let _ = actix_web::web::block(move || {
for follower_id in context_clone.store.view.follows.forward_iter(profile_id) {
if let Ok(Some(true)) = context_clone.store.profiles.is_local(follower_id) {
context_clone.store.view.submissions.new(
follower_id,
submission_id,
published,
);
}
context.spawn_blocking(move || {
for follower_id in context_clone.store.view.follows.forward_iter(profile_id) {
if let Ok(Some(true)) = context_clone.store.profiles.is_local(follower_id) {
context_clone
.store
.view
.submissions
.new(follower_id, submission_id, published);
}
Ok(()) as Result<(), ()>
})
.await;
}));
}
});
Ok(())
if context.is_local(submission.profile_id())? {
return Ok(Some(Box::new(crate::apub::results::SubmissionCreated {
submission_id,
})));
}
Ok(None)
}
}
impl Action for AnnounceSubmission {
fn perform(&self, _: &Context) -> Result<(), Error> {
Ok(())
fn perform(&self, _: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
Ok(None)
}
}
impl Action for UpdateSubmission {
fn perform(&self, context: &Context) -> Result<(), Error> {
let submission = context.store.submissions.by_id(self.submission_id)?.req()?;
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let submission_id = self.submission_id;
let submission = context.store.submissions.by_id(submission_id)?.req()?;
let mut changes = submission.update();
if let Some(title) = &self.title {
@ -86,15 +92,22 @@ impl Action for UpdateSubmission {
context.spawner.purge_file(file);
}
Ok(())
let profile_id = submission.profile_id();
if context.is_local(profile_id)? {
return Ok(Some(Box::new(crate::apub::results::SubmissionUpdated {
submission_id,
})));
}
Ok(None)
}
}
fn delete_comment(comment_id: uuid::Uuid, context: &Context) -> Result<(), Error> {
let apub_id = context.apub.apub_for_comment(comment_id)?.req()?;
let note_apub_id = context.apub.apub_for_comment(comment_id)?.req()?;
Action::perform(
&DeleteComment {
apub_id,
note_apub_id,
comment_id,
},
context,
@ -103,12 +116,14 @@ fn delete_comment(comment_id: uuid::Uuid, context: &Context) -> Result<(), Error
}
impl Action for DeleteSubmission {
fn perform(&self, context: &Context) -> Result<(), Error> {
let opt = context.store.submissions.delete(self.submission_id)?;
context.apub.delete_object(&self.apub_id)?;
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error> {
let submission_id = self.submission_id;
let opt = context.store.submissions.delete(submission_id)?;
if let Some(undo_submission) = opt {
let submission_id = undo_submission.0.id();
let note_apub_id = context.apub.apub_for_submission(submission_id)?.req()?;
context.apub.delete_object(&note_apub_id)?;
let context_clone = context.clone();
context.spawn_blocking(move || {
for comment_id in context_clone.store.comments.for_submission(submission_id) {
@ -122,13 +137,20 @@ impl Action for DeleteSubmission {
context.spawner.purge_file(*file_id);
}
let submission_id = undo_submission.0.id();
let context_clone = context.clone();
context.spawn_blocking(move || {
context_clone.store.view.submissions.remove(submission_id);
});
let profile_id = undo_submission.0.profile_id();
if context.is_local(profile_id)? {
return Ok(Some(Box::new(crate::apub::results::SubmissionDeleted {
profile_id,
submission_id,
})));
}
}
Ok(())
Ok(None)
}
}

View file

@ -1,4 +1,4 @@
use super::{Blocked, Unblocked};
use super::{Block as Blocked, UndoBlock};
use crate::{Completed, Context, Error, Required};
use activitystreams::{
activity::{Block, Undo},
@ -28,11 +28,10 @@ impl Completed for Blocked {
}
}
impl Completed for Unblocked {
impl Completed for UndoBlock {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let block_id = ctx.apub.apub_for_block(self.block_id)?.req()?;
let block = ctx.apub.object(&block_id)?.req()?;
let block = ctx.apub.object(&self.block_apub_id)?.req()?;
let mut undo = Undo::new(person_id, block);
undo.set_id(ctx.apub.info.gen_id())

View file

@ -1,7 +1,9 @@
use super::{CommentCreated, CommentDeleted, CommentUpdated};
use super::{
CommentCreated, CommentDeleted, CommentUpdated, RemoteCommentCreated, RemoteCommentUpdated,
};
use crate::{store::Comment, Completed, Context, Error, Required};
use activitystreams::{
activity::{Create, Delete, Update},
activity::{Announce, Create, Delete, Update},
base::AnyBase,
context,
object::Note,
@ -45,6 +47,7 @@ impl Completed for CommentCreated {
let comment = ctx.store.comments.by_id(self.comment_id)?.req()?;
let person_id = ctx.apub.apub_for_profile(comment.profile_id())?.req()?;
let note_id = ctx.apub.info.gen_id();
ctx.apub.comment(&note_id, self.comment_id)?;
let note = build_comment(comment, note_id, person_id.clone(), ctx)?;
let mut create = Create::new(person_id, note);
@ -59,6 +62,23 @@ impl Completed for CommentCreated {
}
}
impl Completed for RemoteCommentCreated {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let comment = ctx.apub.object(&self.note_apub_id)?.req()?;
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let mut announce = Announce::new(person_id, comment);
announce
.set_id(ctx.apub.info.gen_id())
.add_context(context())
.add_context(security());
let announce = announce.into_any_base()?;
ctx.apub.store_object(&announce)?;
Ok(announce)
}
}
impl Completed for CommentUpdated {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let comment = ctx.store.comments.by_id(self.comment_id)?.req()?;
@ -78,11 +98,27 @@ impl Completed for CommentUpdated {
}
}
impl Completed for RemoteCommentUpdated {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let update = ctx.apub.object(&self.update_apub_id)?.req()?;
let mut announce = Announce::new(person_id, update);
announce
.set_id(ctx.apub.info.gen_id())
.add_context(context())
.add_context(security());
let announce = announce.into_any_base()?;
ctx.apub.store_object(&announce)?;
Ok(announce)
}
}
impl Completed for CommentDeleted {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let note_id = ctx.apub.apub_for_comment(self.comment_id)?.req()?;
let note = ctx.apub.object(&note_id)?.req()?;
let note = ctx.apub.object(&self.note_apub_id)?.req()?;
let mut delete = Delete::new(person_id, note);
delete

View file

@ -1,7 +1,4 @@
use super::{
FollowRequestAccepted, FollowRequestDeleted, FollowRequestRejected, FollowRequested,
UndoneFollowRequestAccepted, Unfollowed,
};
use super::{AcceptFollow, Follow as FollowRequested, RejectFollow, UndoAcceptFollow, UndoFollow};
use crate::{Completed, Context, Error, Required};
use activitystreams::{
activity::{Accept, Follow, Reject, Undo},
@ -23,9 +20,13 @@ impl Completed for FollowRequested {
let object_id = ctx.apub.apub_for_profile(follow.left)?.req()?;
let published = follow.published;
let follow_id = ctx.apub.info.gen_id();
ctx.apub
.follow_request(&follow_id, self.follow_request_id)?;
let mut follow = Follow::new(actor_id, object_id);
follow
.set_id(ctx.apub.info.gen_id())
.set_id(follow_id)
.set_published(published.into())
.add_context(context())
.add_context(security());
@ -36,34 +37,10 @@ impl Completed for FollowRequested {
}
}
impl Completed for FollowRequestDeleted {
impl Completed for RejectFollow {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let follow_request_id = ctx
.apub
.apub_for_follow_request(self.follow_request_id)?
.req()?;
let follow_request = ctx.apub.object(&follow_request_id)?.req()?;
let mut undo = Undo::new(person_id, follow_request);
undo.set_id(ctx.apub.info.gen_id())
.add_context(context())
.add_context(security());
let undo = undo.into_any_base()?;
ctx.apub.store_object(&undo)?;
Ok(undo)
}
}
impl Completed for FollowRequestRejected {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let follow_request_id = ctx
.apub
.apub_for_follow_request(self.follow_request_id)?
.req()?;
let follow_request = ctx.apub.object(&follow_request_id)?.req()?;
let follow_request = ctx.apub.object(&self.follow_apub_id)?.req()?;
let mut reject = Reject::new(person_id, follow_request);
reject
@ -77,14 +54,10 @@ impl Completed for FollowRequestRejected {
}
}
impl Completed for FollowRequestAccepted {
impl Completed for AcceptFollow {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let follow_request_id = ctx
.apub
.apub_for_follow_request(self.follow_request_id)?
.req()?;
let follow_request = ctx.apub.object(&follow_request_id)?.req()?;
let follow_request = ctx.apub.object(&self.follow_apub_id)?.req()?;
let accept_id = ctx.apub.info.gen_id();
ctx.apub.follow(&accept_id, self.follow_id)?;
@ -101,28 +74,26 @@ impl Completed for FollowRequestAccepted {
}
}
impl Completed for UndoneFollowRequestAccepted {
impl Completed for UndoAcceptFollow {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let follow_id = ctx.apub.apub_for_follow(self.follow_id)?.req()?;
let follow = ctx.apub.object(&follow_id)?.req()?;
let mut undo = Undo::new(person_id, follow);
undo.set_id(ctx.apub.info.gen_id())
.add_context(context())
.add_context(security());
let undo = undo.into_any_base()?;
ctx.apub.store_object(&undo)?;
Ok(undo)
}
}
impl Completed for Unfollowed {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let follow_id = ctx.apub.apub_for_follow(self.follow_id)?.req()?;
let follow = ctx.apub.object(&follow_id)?.req()?;
let accept = ctx.apub.object(&self.accept_apub_id)?.req()?;
let mut undo = Undo::new(person_id, accept);
undo.set_id(ctx.apub.info.gen_id())
.add_context(context())
.add_context(security());
let undo = undo.into_any_base()?;
ctx.apub.store_object(&undo)?;
Ok(undo)
}
}
impl Completed for UndoFollow {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let follow = ctx.apub.object(&self.follow_apub_id)?.req()?;
let mut undo = Undo::new(person_id, follow);
undo.set_id(ctx.apub.info.gen_id())

View file

@ -1,3 +1,4 @@
use url::Url;
use uuid::Uuid;
mod block;
@ -7,88 +8,93 @@ mod profile;
mod react;
mod submission;
pub(crate) struct ProfileCreated {
profile_id: Uuid,
pub(super) struct ProfileCreated {
pub(super) profile_id: Uuid,
}
pub(crate) struct ProfileUpdated {
profile_id: Uuid,
pub(super) struct ProfileUpdated {
pub(super) profile_id: Uuid,
}
pub(crate) struct ProfileDeleted {
profile_id: Uuid,
pub(super) struct ProfileDeleted {
pub(super) profile_id: Uuid,
}
pub(crate) struct SubmissionCreated {
submission_id: Uuid,
pub(super) struct SubmissionCreated {
pub(super) submission_id: Uuid,
}
pub(crate) struct SubmissionUpdated {
submission_id: Uuid,
pub(super) struct SubmissionUpdated {
pub(super) submission_id: Uuid,
}
pub(crate) struct SubmissionDeleted {
profile_id: Uuid,
submission_id: Uuid,
pub(super) struct SubmissionDeleted {
pub(super) profile_id: Uuid,
pub(super) submission_id: Uuid,
}
pub(crate) struct CommentCreated {
comment_id: Uuid,
pub(super) struct CommentCreated {
pub(super) comment_id: Uuid,
}
pub(crate) struct CommentUpdated {
comment_id: Uuid,
pub(super) struct RemoteCommentCreated {
pub(super) note_apub_id: Url,
pub(super) profile_id: Uuid,
}
pub(crate) struct CommentDeleted {
profile_id: Uuid,
comment_id: Uuid,
pub(super) struct CommentUpdated {
pub(super) comment_id: Uuid,
}
pub(crate) struct ReactCreated {
react_id: Uuid,
pub(super) struct RemoteCommentUpdated {
pub(super) update_apub_id: Url,
pub(super) profile_id: Uuid,
}
pub(crate) struct ReactDeleted {
profile_id: Uuid,
react_id: Uuid,
pub(super) struct CommentDeleted {
pub(super) note_apub_id: Url,
pub(super) profile_id: Uuid,
}
pub(crate) struct FollowRequested {
follow_request_id: Uuid,
pub(super) struct React {
pub(super) react_id: Uuid,
}
pub(crate) struct FollowRequestDeleted {
profile_id: Uuid,
follow_request_id: Uuid,
pub(super) struct UndoReact {
pub(super) like_apub_id: Url,
pub(super) profile_id: Uuid,
}
pub(crate) struct FollowRequestRejected {
profile_id: Uuid,
follow_request_id: Uuid,
pub(super) struct Follow {
pub(super) follow_request_id: Uuid,
}
pub(crate) struct FollowRequestAccepted {
profile_id: Uuid,
follow_id: Uuid,
follow_request_id: Uuid,
pub(super) struct RejectFollow {
pub(super) follow_apub_id: Url,
pub(super) profile_id: Uuid,
}
pub(crate) struct UndoneFollowRequestAccepted {
profile_id: Uuid,
follow_id: Uuid,
pub(super) struct AcceptFollow {
pub(super) follow_apub_id: Url,
pub(super) profile_id: Uuid,
pub(super) follow_id: Uuid,
}
pub(crate) struct Unfollowed {
profile_id: Uuid,
follow_id: Uuid,
pub(super) struct UndoAcceptFollow {
pub(super) accept_apub_id: Url,
pub(super) profile_id: Uuid,
}
pub(crate) struct Blocked {
block_id: Uuid,
pub(super) struct UndoFollow {
pub(super) follow_apub_id: Url,
pub(super) profile_id: Uuid,
}
pub(crate) struct Unblocked {
profile_id: Uuid,
block_id: Uuid,
pub(super) struct Block {
pub(super) block_id: Uuid,
}
pub(super) struct UndoBlock {
pub(super) block_apub_id: Url,
pub(super) profile_id: Uuid,
}

View file

@ -1,4 +1,4 @@
use super::{ReactCreated, ReactDeleted};
use super::{React, UndoReact};
use crate::{Completed, Context, Error, Required};
use activitystreams::{
activity::{Create, Delete, Like},
@ -8,7 +8,7 @@ use activitystreams::{
public, security,
};
impl Completed for ReactCreated {
impl Completed for React {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let react = ctx.store.reacts.by_id(self.react_id)?.req()?;
let person_id = ctx.apub.apub_for_profile(react.profile_id())?.req()?;
@ -46,11 +46,10 @@ impl Completed for ReactCreated {
}
}
impl Completed for ReactDeleted {
impl Completed for UndoReact {
fn to_apub(&self, ctx: &Context) -> Result<AnyBase, Error> {
let person_id = ctx.apub.apub_for_profile(self.profile_id)?.req()?;
let like_id = ctx.apub.apub_for_react(self.react_id)?.req()?;
let like = ctx.apub.object(&like_id)?.req()?;
let like = ctx.apub.object(&self.like_apub_id)?.req()?;
let mut delete = Delete::new(person_id, like);
delete

View file

@ -44,6 +44,10 @@ impl Context {
}
}
fn is_local(&self, id: Uuid) -> Result<bool, Error> {
Ok(self.store.profiles.is_local(id)?.req()?)
}
fn check_block(&self, left: Uuid, right: Uuid) -> Result<(), Error> {
let forward = self.store.view.blocks.by_forward(left, right)?.is_some();
let backward = self.store.view.blocks.by_backward(right, left)?.is_some();
@ -105,7 +109,7 @@ enum RecoverableError {
}
trait Action {
fn perform(&self, context: &Context) -> Result<(), Error>;
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Completed>>, Error>;
}
pub trait Completed {

View file

@ -81,6 +81,10 @@ impl Profile {
self.id
}
pub(crate) fn owner_source(&self) -> &OwnerSource {
&self.owner_source
}
pub(crate) fn handle(&self) -> &str {
&self.handle
}