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:
asonix 2021-01-17 15:01:37 -06:00
parent c9b1c4fac0
commit 83b447b780
20 changed files with 154 additions and 103 deletions

View file

@ -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")?;

View file

@ -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")?;

View file

@ -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")?;

View file

@ -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")?;

View file

@ -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(())

View file

@ -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)?;

View file

@ -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")?;

View file

@ -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")?;

View file

@ -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");

View file

@ -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,

View file

@ -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,

View file

@ -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)?

View file

@ -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)?;

View file

@ -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

View file

@ -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> {

View file

@ -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)?;

View file

@ -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()),

View file

@ -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()),

View file

@ -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

View file

@ -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(())
}