Profiles: Federation fixes
- Fix image federation - Enable submission & comment create/update federation - Improve checks to ensure we don't federate when we don't need to
This commit is contained in:
parent
c9b1c4fac0
commit
83b447b780
|
@ -8,11 +8,10 @@ use crate::{
|
|||
},
|
||||
recover,
|
||||
store::view::Relationship,
|
||||
Action, Context, Error, RecoverableError, Required,
|
||||
Action, Context, Error, KeyOwner, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::prelude::*;
|
||||
use chrono::Utc;
|
||||
use url::Url;
|
||||
|
||||
fn validate_follow_application(
|
||||
follow: &activitystreams::activity::Follow,
|
||||
|
@ -38,7 +37,7 @@ fn validate_follow_application(
|
|||
pub(crate) fn follow_application(
|
||||
follow: &activitystreams::activity::Follow,
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let follow_id = follow.id_unchecked().req("follow id")?;
|
||||
|
@ -76,7 +75,7 @@ pub(crate) fn reject_follow_application(
|
|||
reject: &activitystreams::activity::Reject,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let reject_actor = reject.actor()?.as_single_id().req("reject actor")?;
|
||||
|
@ -113,7 +112,7 @@ pub(crate) fn accept_follow_application(
|
|||
accept: &activitystreams::activity::Accept,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let accept_actor = accept.actor()?.as_single_id().req("accept actor")?;
|
||||
|
@ -158,7 +157,7 @@ pub(crate) fn undo_follow_application(
|
|||
undo: &activitystreams::activity::Undo,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let undo_actor = undo.actor()?.as_single_id().req("undo actor id")?;
|
||||
|
@ -202,7 +201,7 @@ pub(crate) fn undo_accept_follow_application(
|
|||
accept: &activitystreams::activity::Accept,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let undo_actor = undo.actor()?.as_single_id().req("undo actor id")?;
|
||||
|
|
|
@ -6,17 +6,16 @@ use crate::{
|
|||
},
|
||||
Endpoints, ExtendedApplication,
|
||||
},
|
||||
recover, Action, Context, Error, RecoverableError, Required,
|
||||
recover, Action, Context, Error, KeyOwner, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::prelude::*;
|
||||
use chrono::Utc;
|
||||
use url::Url;
|
||||
|
||||
pub mod follow;
|
||||
|
||||
pub(crate) fn application(
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let id = application.id_unchecked().req("application id")?;
|
||||
|
@ -96,7 +95,7 @@ pub(crate) fn application(
|
|||
pub(crate) fn create_application(
|
||||
create: &activitystreams::activity::Create,
|
||||
application_obj: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let actor_id = create.actor()?.as_single_id().req("create actor id")?;
|
||||
|
@ -114,7 +113,7 @@ pub(crate) fn create_application(
|
|||
pub(crate) fn update_application(
|
||||
update: &activitystreams::activity::Update,
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let update_actor = update.actor()?.as_single_id().req("update actor id")?;
|
||||
|
@ -181,7 +180,7 @@ pub(crate) fn update_application(
|
|||
pub(crate) fn delete_application(
|
||||
delete: &activitystreams::activity::Delete,
|
||||
application: &ExtendedApplication,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let delete_actor = delete.actor()?.as_single_id().req("delete actor id")?;
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
use crate::{
|
||||
apub::actions::{apub::require_federation, CreateReport, Reported, Reporter},
|
||||
recover, Action, Context, Error, RecoverableError, Required,
|
||||
recover, Action, Context, Error, KeyOwner, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::prelude::*;
|
||||
use url::Url;
|
||||
|
||||
pub(crate) fn flag(
|
||||
flag: &activitystreams::activity::Flag,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let flag_id = flag.id_unchecked().req("flag id")?;
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
use crate::{
|
||||
apub::actions::{apub::require_federation, CreateReact, DeleteReact},
|
||||
recover, Action, Context, Error, RecoverableError, Required,
|
||||
recover, Action, Context, Error, KeyOwner, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::prelude::*;
|
||||
use url::Url;
|
||||
|
||||
pub(crate) fn like(
|
||||
like: &activitystreams::activity::Like,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let like_id = like.id_unchecked().req("like id")?;
|
||||
|
@ -75,7 +74,7 @@ pub(crate) fn like(
|
|||
pub(crate) fn undo_like(
|
||||
undo: &activitystreams::activity::Undo,
|
||||
like: &activitystreams::activity::Like,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let like_id = like.id_unchecked().req("like id")?;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Action, Context, Error, OnBehalfOf, RecoverableError, Required};
|
||||
use crate::{Action, Context, Error, KeyOwner, OnBehalfOf, RecoverableError, Required};
|
||||
use activitystreams::{base::AnyBase, prelude::*};
|
||||
use url::Url;
|
||||
|
||||
|
@ -40,11 +40,12 @@ fn log_unsupported(path: &[&str]) -> Result<Result<Box<dyn Action>, RecoverableE
|
|||
|
||||
pub(crate) fn ingest(
|
||||
any_base: AnyBase,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
mut stack: Vec<AnyBase>,
|
||||
) -> Result<(), Error> {
|
||||
log::debug!("Ingest");
|
||||
|
||||
if any_base.kind_str().is_none() {
|
||||
log::debug!("Spawining download for URL");
|
||||
ctx.spawner.download_apub(
|
||||
|
@ -95,6 +96,7 @@ where
|
|||
let any_base = if object.kind_str().is_none() {
|
||||
let id = object.id().req("id from object")?;
|
||||
if ctx.apub.deleted(id)? {
|
||||
log::warn!("Attempting to ingest deleted activity");
|
||||
return Err(Error::Invalid);
|
||||
}
|
||||
match ctx.apub.object(id)? {
|
||||
|
@ -132,7 +134,7 @@ where
|
|||
|
||||
fn parse(
|
||||
any_base: AnyBase,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
match any_base.kind_str().req("kind")? {
|
||||
|
@ -337,7 +339,11 @@ fn parse(
|
|||
}
|
||||
}
|
||||
|
||||
fn require_federation(key_owner: Option<&Url>, actor: &Url, ctx: &Context) -> Result<(), Error> {
|
||||
fn require_federation(
|
||||
key_owner: Option<KeyOwner>,
|
||||
actor: &Url,
|
||||
ctx: &Context,
|
||||
) -> Result<(), Error> {
|
||||
if let Some(key_owner) = key_owner {
|
||||
if !ctx.is_or_is_server_of(key_owner, actor)? {
|
||||
log::debug!("Key Owner does not control Actor");
|
||||
|
@ -355,9 +361,14 @@ fn require_federation(key_owner: Option<&Url>, actor: &Url, ctx: &Context) -> Re
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn require_not_blocked(key_owner: Option<&Url>, actor: &Url, ctx: &Context) -> Result<(), Error> {
|
||||
fn require_not_blocked(
|
||||
key_owner: Option<KeyOwner>,
|
||||
actor: &Url,
|
||||
ctx: &Context,
|
||||
) -> Result<(), Error> {
|
||||
if let Some(key_owner) = key_owner {
|
||||
if key_owner != actor {
|
||||
if !ctx.is_or_is_server_of(key_owner, actor)? {
|
||||
log::debug!("Key Owner does not control Actor");
|
||||
return Err(Error::Invalid);
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +376,8 @@ fn require_not_blocked(key_owner: Option<&Url>, actor: &Url, ctx: &Context) -> R
|
|||
let domain = actor.domain().req("domain from actor")?;
|
||||
|
||||
if ctx.store.is_domain_blocked(domain)? {
|
||||
return Err(Error::Invalid);
|
||||
log::debug!("Domain is blocked");
|
||||
return Err(Error::Blocked);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -5,10 +5,9 @@ use crate::{
|
|||
},
|
||||
recover,
|
||||
store::Visibility,
|
||||
Action, Context, Error, MissingImage, RecoverableError, Required,
|
||||
Action, Context, Error, KeyOwner, MissingImage, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::{object::Image, prelude::*, public};
|
||||
use url::Url;
|
||||
|
||||
fn find_visibility(note: &activitystreams::object::Note) -> Visibility {
|
||||
if note
|
||||
|
@ -40,9 +39,10 @@ fn find_visibility(note: &activitystreams::object::Note) -> Visibility {
|
|||
|
||||
pub(super) fn note(
|
||||
note: &activitystreams::object::Note,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Ingest Note");
|
||||
let note_id = note.id_unchecked().req("note id")?;
|
||||
|
||||
// Double create
|
||||
|
@ -71,6 +71,7 @@ pub(super) fn note(
|
|||
}
|
||||
|
||||
if let Some(in_reply_to) = note.in_reply_to() {
|
||||
log::debug!("Reply Note");
|
||||
let in_reply_to = in_reply_to.as_single_id().req("in reply to id")?;
|
||||
let in_reply_to = recover!(in_reply_to, ctx.apub.id_for_apub(in_reply_to)?);
|
||||
|
||||
|
@ -112,6 +113,8 @@ pub(super) fn note(
|
|||
return Err(Error::Invalid);
|
||||
}
|
||||
|
||||
log::debug!("Standalone Note");
|
||||
|
||||
let title = note
|
||||
.summary()
|
||||
.req("summary")?
|
||||
|
@ -143,7 +146,7 @@ pub(super) fn note(
|
|||
continue;
|
||||
};
|
||||
|
||||
match ctx.apub.id_for_apub(url) {
|
||||
match ctx.apub.id_for_apub(id) {
|
||||
Ok(Some(id)) => {
|
||||
existing_files.push(id.file().req("file id for image url")?);
|
||||
}
|
||||
|
@ -158,6 +161,7 @@ pub(super) fn note(
|
|||
}
|
||||
|
||||
if !missing_files.is_empty() {
|
||||
log::debug!("Files needed before further processing");
|
||||
return Ok(Err(RecoverableError::MissingImages(missing_files)));
|
||||
}
|
||||
|
||||
|
@ -175,9 +179,10 @@ pub(super) fn note(
|
|||
pub(super) fn create_note(
|
||||
create: &activitystreams::activity::Create,
|
||||
note_obj: &activitystreams::object::Note,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Ingest Create Note");
|
||||
let actor_id = create.actor()?.as_single_id().req("create actor id")?;
|
||||
require_federation(key_owner, actor_id, ctx)?;
|
||||
|
||||
|
@ -197,9 +202,10 @@ pub(super) fn create_note(
|
|||
pub(super) fn announce_note(
|
||||
announce: &activitystreams::activity::Announce,
|
||||
note: &activitystreams::object::Note,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Ingest Announce Note");
|
||||
let actor_id = announce.actor()?.as_single_id().req("announce actor id")?;
|
||||
require_federation(key_owner, actor_id, ctx)?;
|
||||
|
||||
|
@ -227,9 +233,10 @@ pub(super) fn announce_update_note(
|
|||
announce: &activitystreams::activity::Announce,
|
||||
update: &activitystreams::activity::Update,
|
||||
_: &activitystreams::object::Note,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Ingest Announce Update Note");
|
||||
let actor_id = announce.actor()?.as_single_id().req("announce actor id")?;
|
||||
require_federation(key_owner, actor_id, ctx)?;
|
||||
|
||||
|
@ -257,9 +264,10 @@ pub(super) fn announce_delete_note(
|
|||
announce: &activitystreams::activity::Announce,
|
||||
delete: &activitystreams::activity::Delete,
|
||||
_: &activitystreams::object::Note,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Ingest Announce Delete Note");
|
||||
let actor_id = announce.actor()?.as_single_id().req("announce actor id")?;
|
||||
require_federation(key_owner, actor_id, ctx)?;
|
||||
|
||||
|
@ -286,9 +294,10 @@ pub(super) fn announce_delete_note(
|
|||
pub(super) fn update_note(
|
||||
update: &activitystreams::activity::Update,
|
||||
note: &activitystreams::object::Note,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Ingest Update Note");
|
||||
let update_id = update.id_unchecked().req("update id")?;
|
||||
let actor_id = update.actor()?.as_single_id().req("update actor id")?;
|
||||
require_federation(key_owner, actor_id, ctx)?;
|
||||
|
@ -378,7 +387,7 @@ pub(super) fn update_note(
|
|||
continue;
|
||||
};
|
||||
|
||||
match ctx.apub.id_for_apub(url) {
|
||||
match ctx.apub.id_for_apub(id) {
|
||||
Ok(Some(id)) => {
|
||||
existing_files.push(id.file().req("image url as file id")?);
|
||||
}
|
||||
|
@ -416,9 +425,10 @@ pub(super) fn update_note(
|
|||
pub(super) fn delete_note(
|
||||
delete: &activitystreams::activity::Delete,
|
||||
note: &activitystreams::object::Note,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Ingest Delete Note");
|
||||
let delete_id = delete.id_unchecked().req("delete id")?;
|
||||
let actor_id = delete.actor()?.as_single_id().req("delete actor id")?;
|
||||
require_federation(key_owner, actor_id, ctx)?;
|
||||
|
|
|
@ -3,15 +3,14 @@ use crate::{
|
|||
actions::{apub::require_federation, CreateBlock, DeleteBlock},
|
||||
ExtendedPerson,
|
||||
},
|
||||
recover, Action, Context, Error, RecoverableError, Required,
|
||||
recover, Action, Context, Error, KeyOwner, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::prelude::*;
|
||||
use url::Url;
|
||||
|
||||
pub(crate) fn block_person(
|
||||
block: &activitystreams::activity::Block,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let id = block.id_unchecked().req("block id")?;
|
||||
|
@ -61,7 +60,7 @@ pub(crate) fn undo_block_person(
|
|||
undo: &activitystreams::activity::Undo,
|
||||
block: &activitystreams::activity::Block,
|
||||
_person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let undo_actor = undo.actor()?.as_single_id().req("undo actor id")?;
|
||||
|
|
|
@ -8,11 +8,10 @@ use crate::{
|
|||
},
|
||||
recover,
|
||||
store::view::Relationship,
|
||||
Action, Context, Error, RecoverableError, Required,
|
||||
Action, Context, Error, KeyOwner, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::prelude::*;
|
||||
use chrono::Utc;
|
||||
use url::Url;
|
||||
|
||||
fn validate_follow_person(
|
||||
follow: &activitystreams::activity::Follow,
|
||||
|
@ -40,7 +39,7 @@ fn validate_follow_person(
|
|||
pub(crate) fn follow_person(
|
||||
follow: &activitystreams::activity::Follow,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let follow_id = follow.id_unchecked().req("follow id")?;
|
||||
|
@ -86,7 +85,7 @@ pub(crate) fn reject_follow_person(
|
|||
reject: &activitystreams::activity::Reject,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let reject_actor = reject.actor()?.as_single_id().req("reject actor id")?;
|
||||
|
@ -131,7 +130,7 @@ pub(crate) fn accept_follow_person(
|
|||
accept: &activitystreams::activity::Accept,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let accept_actor = accept.actor()?.as_single_id().req("accept actor id")?;
|
||||
|
@ -184,7 +183,7 @@ pub(crate) fn undo_follow_person(
|
|||
undo: &activitystreams::activity::Undo,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let undo_actor = undo.actor()?.as_single_id().req("undo actor id")?;
|
||||
|
@ -240,7 +239,7 @@ pub(crate) fn undo_accept_follow_person(
|
|||
accept: &activitystreams::activity::Accept,
|
||||
follow: &activitystreams::activity::Follow,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
let undo_actor = undo.actor()?.as_single_id().req("undo actor id")?;
|
||||
|
|
|
@ -8,10 +8,9 @@ use crate::{
|
|||
},
|
||||
recover,
|
||||
store::OwnerSource,
|
||||
Action, Context, Error, MissingImage, RecoverableError, Required,
|
||||
Action, Context, Error, KeyOwner, MissingImage, RecoverableError, Required,
|
||||
};
|
||||
use activitystreams::{base::AnyBase, object::Image, prelude::*, primitives::OneOrMany, public};
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub mod block;
|
||||
|
@ -22,13 +21,11 @@ fn from_image(
|
|||
missing_files: &mut Vec<MissingImage>,
|
||||
ctx: &Context,
|
||||
) -> Result<Option<Uuid>, Error> {
|
||||
log::debug!("Parsing Image {:?}", image);
|
||||
let image = if let Some(image) = image.and_then(|i| i.as_one()) {
|
||||
image
|
||||
} else {
|
||||
return Ok(None);
|
||||
};
|
||||
log::debug!("Parsing Image {:?}", image);
|
||||
|
||||
let image = if let Some(image) = Image::from_any_base(image.clone())? {
|
||||
image
|
||||
|
@ -45,10 +42,8 @@ fn from_image(
|
|||
.req("Single Image Url")?
|
||||
.to_owned();
|
||||
|
||||
log::debug!("Url: {}", url);
|
||||
|
||||
match ctx.apub.id_for_apub(&id)? {
|
||||
Some(uuid) => Ok(Some(uuid.file().req("image url as file")?)),
|
||||
Some(stored_id) => Ok(Some(stored_id.file().req("image url as file")?)),
|
||||
None => {
|
||||
missing_files.push(MissingImage {
|
||||
apub_id: id,
|
||||
|
@ -61,7 +56,7 @@ fn from_image(
|
|||
|
||||
pub(crate) fn person(
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Person");
|
||||
|
@ -74,7 +69,6 @@ pub(crate) fn person(
|
|||
let mut missing_files = Vec::new();
|
||||
let banner = from_image(person.image(), &mut missing_files, ctx)?;
|
||||
let icon = from_image(person.icon(), &mut missing_files, ctx)?;
|
||||
log::debug!("Missing files {:?}", missing_files);
|
||||
if !missing_files.is_empty() {
|
||||
return Ok(Err(RecoverableError::MissingImages(missing_files)));
|
||||
}
|
||||
|
@ -164,7 +158,7 @@ pub(crate) fn person(
|
|||
pub(crate) fn create_person(
|
||||
create: &activitystreams::activity::Create,
|
||||
person_obj: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Create Person");
|
||||
|
@ -177,7 +171,7 @@ pub(crate) fn create_person(
|
|||
pub(crate) fn update_person(
|
||||
update: &activitystreams::activity::Update,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Update Person");
|
||||
|
@ -260,7 +254,7 @@ pub(crate) fn update_person(
|
|||
pub(crate) fn delete_person(
|
||||
delete: &activitystreams::activity::Delete,
|
||||
person: &ExtendedPerson,
|
||||
key_owner: Option<&Url>,
|
||||
key_owner: Option<KeyOwner>,
|
||||
ctx: &Context,
|
||||
) -> Result<Result<Box<dyn Action>, RecoverableError>, Error> {
|
||||
log::debug!("Delete Person");
|
||||
|
|
|
@ -68,7 +68,7 @@ impl Action for DeleteBlock {
|
|||
ctx.apub.delete_object(&block_apub_id)?;
|
||||
|
||||
if let Some(undo_block) = opt {
|
||||
if ctx.is_local(undo_block.0.right)? {
|
||||
if ctx.is_local(undo_block.0.right)? && !ctx.is_local(undo_block.0.left)? {
|
||||
return Ok(Some(Box::new(crate::apub::results::UndoBlock {
|
||||
block_apub_id,
|
||||
profile_id: undo_block.0.right,
|
||||
|
|
|
@ -31,7 +31,7 @@ impl Action for UndoFollow {
|
|||
ctx.apub.delete_object(&follow_apub_id)?;
|
||||
|
||||
if let Some(undo_follow) = opt {
|
||||
if ctx.is_local(undo_follow.0.right)? {
|
||||
if ctx.is_local(undo_follow.0.right)? || !ctx.is_local(undo_follow.0.left)? {
|
||||
return Ok(Some(Box::new(crate::apub::results::UndoFollow {
|
||||
follow_apub_id,
|
||||
profile_id: undo_follow.0.right,
|
||||
|
@ -55,7 +55,7 @@ impl Action for UndoAcceptFollow {
|
|||
ctx.apub.delete_object(&follow_apub_id)?;
|
||||
|
||||
if let Some(undo_follow) = opt {
|
||||
if ctx.is_local(undo_follow.0.right)? {
|
||||
if ctx.is_local(undo_follow.0.left)? && !ctx.is_local(undo_follow.0.right)? {
|
||||
return Ok(Some(Box::new(crate::apub::results::UndoAcceptFollow {
|
||||
accept_apub_id,
|
||||
profile_id: undo_follow.0.left,
|
||||
|
|
|
@ -61,7 +61,7 @@ impl Action for AcceptFollowRequest {
|
|||
ctx.apub.follow(apub_id, follow.id)?;
|
||||
}
|
||||
|
||||
if ctx.is_local(follow.right)? && !ctx.is_local(follow.left)? {
|
||||
if ctx.is_local(follow.left)? && !ctx.is_local(follow.right)? {
|
||||
let follow_apub_id = ctx
|
||||
.apub
|
||||
.apub_for_follow_request(undo_follow_request.0.id)?
|
||||
|
|
|
@ -38,7 +38,7 @@ impl Action for CreateProfile {
|
|||
}
|
||||
if let Some(icon) = self.icon {
|
||||
if let Ok(Some(file)) = ctx.store.files.by_id(icon) {
|
||||
changes.banner(&file);
|
||||
changes.icon(&file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,6 @@ fn clean_profile(profile: &Profile, ctx: &Context) -> Result<(), Error> {
|
|||
|
||||
impl Action for DeleteProfile {
|
||||
fn perform(&self, ctx: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
|
||||
log::debug!("DeleteProfile");
|
||||
let profile_id = self.profile_id;
|
||||
let opt = ctx.store.profiles.suspend(profile_id)?;
|
||||
|
||||
|
@ -249,7 +248,6 @@ impl Action for DeleteProfile {
|
|||
|
||||
impl Action for SuspendProfile {
|
||||
fn perform(&self, ctx: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
|
||||
log::debug!("SuspendProfile");
|
||||
let profile_id = self.profile_id;
|
||||
let opt = ctx.store.profiles.suspend(profile_id)?;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
|||
|
||||
impl Action for CreateSubmission {
|
||||
fn perform(&self, ctx: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
|
||||
log::debug!("CreateSubmission");
|
||||
let submission =
|
||||
ctx.store
|
||||
.submissions
|
||||
|
@ -63,14 +64,19 @@ impl Action for CreateSubmission {
|
|||
})));
|
||||
}
|
||||
|
||||
Ok(Some(Box::new(
|
||||
crate::apub::results::UnpublishedSubmissionCreated { submission_id },
|
||||
)))
|
||||
if submission.published().is_none() {
|
||||
return Ok(Some(Box::new(
|
||||
crate::apub::results::UnpublishedSubmissionCreated { submission_id },
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl Action for UpdateSubmission {
|
||||
fn perform(&self, ctx: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
|
||||
log::debug!("UpdateSubmission");
|
||||
let submission_id = self.submission_id;
|
||||
let submission = ctx
|
||||
.store
|
||||
|
|
|
@ -71,7 +71,8 @@ pub enum StoredRecords {
|
|||
}
|
||||
|
||||
fn url_from_ivec(ivec: sled::IVec) -> Option<Url> {
|
||||
String::from_utf8_lossy(&ivec).parse::<Url>().ok()
|
||||
let s = String::from_utf8_lossy(&ivec);
|
||||
s.parse::<Url>().ok()
|
||||
}
|
||||
|
||||
fn record_from_ivec(ivec: sled::IVec) -> Option<StoredRecords> {
|
||||
|
|
|
@ -104,13 +104,16 @@ fn build_comment(
|
|||
if let Some(followers) = endpoints.followers {
|
||||
note.add_to(followers);
|
||||
}
|
||||
if let Some(comment_id) = comment.comment_id() {
|
||||
let in_reply_to = ctx
|
||||
.apub
|
||||
let in_reply_to = if let Some(comment_id) = comment.comment_id() {
|
||||
ctx.apub
|
||||
.apub_for_comment(comment_id)?
|
||||
.req("apub for comment")?;
|
||||
note.set_in_reply_to(in_reply_to);
|
||||
}
|
||||
.req("apub for comment")?
|
||||
} else {
|
||||
ctx.apub
|
||||
.apub_for_submission(comment.submission_id())?
|
||||
.req("apub for submission")?
|
||||
};
|
||||
note.set_in_reply_to(in_reply_to);
|
||||
|
||||
let any_base = note.into_any_base()?;
|
||||
ctx.apub.store_object(&any_base)?;
|
||||
|
|
|
@ -97,7 +97,7 @@ impl Outbound for ProfileCreated {
|
|||
public_key: public_key_id.clone(),
|
||||
},
|
||||
)?;
|
||||
let public_key_pem = ctx.apub.gen_profile_keys(profile.id(), &person_id)?;
|
||||
let public_key_pem = ctx.apub.gen_profile_keys(profile.id(), &public_key_id)?;
|
||||
|
||||
let mut person = ExtendedPerson::new(
|
||||
ApActor::new(inbox, Person::new()),
|
||||
|
|
|
@ -60,7 +60,7 @@ impl Outbound for ServerCreated {
|
|||
public_key: public_key_id.clone(),
|
||||
},
|
||||
)?;
|
||||
let public_key_pem = ctx.apub.gen_server_keys(server.id(), &application_id)?;
|
||||
let public_key_pem = ctx.apub.gen_server_keys(server.id(), &public_key_id)?;
|
||||
|
||||
let mut application = ExtendedApplication::new(
|
||||
ApActor::new(inbox, Application::new()),
|
||||
|
|
|
@ -30,8 +30,10 @@ fn build_image(file_id: Uuid, ctx: &Context) -> Result<AnyBase, Error> {
|
|||
ctx.apub.file(&image_id, file_id)?;
|
||||
|
||||
let mut image = Image::new();
|
||||
image.set_url(ctx.pictrs.image_url(pictrs_file.key()));
|
||||
image.set_media_type(pictrs_file.media_type().clone());
|
||||
image
|
||||
.set_id(image_id)
|
||||
.set_url(ctx.pictrs.image_url(pictrs_file.key()))
|
||||
.set_media_type(pictrs_file.media_type().clone());
|
||||
|
||||
let image = image.into_any_base()?;
|
||||
ctx.apub.store_object(&image)?;
|
||||
|
@ -228,7 +230,7 @@ impl Outbound for SubmissionUpdated {
|
|||
.apub
|
||||
.apub_for_submission(submission.id())?
|
||||
.req("apub id for submission")?;
|
||||
let note = build_submission(submission, person_id.clone(), note_id, ctx)?;
|
||||
let note = build_submission(submission, note_id, person_id.clone(), ctx)?;
|
||||
|
||||
let mut update = Update::new(person_id, note);
|
||||
update
|
||||
|
|
|
@ -73,26 +73,38 @@ impl Context {
|
|||
Ok(self.store.servers.is_self(id)?)
|
||||
}
|
||||
|
||||
fn is_or_is_server_of(&self, key_owner: &Url, actor: &Url) -> Result<bool, Error> {
|
||||
if key_owner == actor {
|
||||
return Ok(true);
|
||||
}
|
||||
fn is_or_is_server_of(&self, key_owner: KeyOwner, actor: &Url) -> Result<bool, Error> {
|
||||
let actor_id = self.apub.id_for_apub(actor)?.req("Apub for Actor")?;
|
||||
|
||||
if let Some(server_id) = self.apub.id_for_apub(key_owner)?.and_then(|id| id.server()) {
|
||||
if let Some(profile_id) = self.apub.id_for_apub(actor)?.and_then(|id| id.profile()) {
|
||||
let profile = self
|
||||
.store
|
||||
.profiles
|
||||
.by_id(profile_id)?
|
||||
.req("profile by id")?;
|
||||
if let OwnerSource::Remote(remote_id) = profile.owner_source() {
|
||||
if *remote_id == server_id {
|
||||
match key_owner {
|
||||
KeyOwner::Server(server_id) => {
|
||||
if let Some(actor_profile_id) = actor_id.profile() {
|
||||
let profile = self
|
||||
.store
|
||||
.profiles
|
||||
.by_id(actor_profile_id)?
|
||||
.req("profile by id")?;
|
||||
if let OwnerSource::Remote(actor_server_id) = profile.owner_source() {
|
||||
if *actor_server_id == server_id {
|
||||
return Ok(true);
|
||||
}
|
||||
} else {
|
||||
let self_id = self.store.servers.get_self()?.req("get self server")?;
|
||||
|
||||
if self_id == server_id {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(actor_server_id) = actor_id.server() {
|
||||
if server_id == actor_server_id {
|
||||
return Ok(true);
|
||||
}
|
||||
} else {
|
||||
let local_server = self.store.servers.get_self()?.req("self server id")?;
|
||||
|
||||
if server_id == local_server {
|
||||
}
|
||||
}
|
||||
KeyOwner::Profile(profile_id) => {
|
||||
if let Some(actor_profile_id) = actor_id.profile() {
|
||||
if profile_id == actor_profile_id {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
@ -227,6 +239,12 @@ impl<T> Required<T> for Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum KeyOwner {
|
||||
Server(Uuid),
|
||||
Profile(Uuid),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct State {
|
||||
pub store: store::Store,
|
||||
|
@ -300,13 +318,26 @@ impl State {
|
|||
pub async fn ingest(
|
||||
&self,
|
||||
any_base: AnyBase,
|
||||
key_owner: Option<Url>,
|
||||
key_id: Option<Url>,
|
||||
stack: Vec<AnyBase>,
|
||||
) -> Result<(), Error> {
|
||||
let ctx = Context::from_state(self).await;
|
||||
|
||||
actix_web::web::block(move || apub::ingest(any_base, key_owner.as_ref(), &ctx, stack))
|
||||
.await?;
|
||||
actix_web::web::block(move || {
|
||||
if let Some(key_id) = key_id {
|
||||
if let Some(profile) = ctx.apub.profile_for_key(&key_id)? {
|
||||
return apub::ingest(any_base, Some(KeyOwner::Profile(profile)), &ctx, stack);
|
||||
}
|
||||
if let Some(server) = ctx.apub.server_for_key(&key_id)? {
|
||||
return apub::ingest(any_base, Some(KeyOwner::Server(server)), &ctx, stack);
|
||||
}
|
||||
} else {
|
||||
return apub::ingest(any_base, None, &ctx, stack);
|
||||
}
|
||||
|
||||
Err(Error::Invalid)
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue