Remove dead code #81

Merged
dessalines merged 7 commits from remove-dead-code into main 2020-08-12 12:30:54 +00:00
20 changed files with 352 additions and 165 deletions
Showing only changes of commit 6b0bc1029f - Show all commits

View File

@ -31,6 +31,18 @@ use regex::{Regex, RegexBuilder};
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use url::Url; use url::Url;
#[macro_export]
macro_rules! location_info {
() => {
format!(
"None value at {}:{}, column {}",
file!(),
line!(),
column!()
)
};
}
pub fn to_datetime_utc(ndt: NaiveDateTime) -> DateTime<Utc> { pub fn to_datetime_utc(ndt: NaiveDateTime) -> DateTime<Utc> {
DateTime::<Utc>::from_utc(ndt, Utc) DateTime::<Utc>::from_utc(ndt, Utc)
} }

View File

@ -41,6 +41,7 @@ use activitystreams::{
public, public,
}; };
use actix_web::{body::Body, client::Client, web::Path, HttpResponse}; use actix_web::{body::Body, client::Client, web::Path, HttpResponse};
use anyhow::Context;
use itertools::Itertools; use itertools::Itertools;
use lemmy_db::{ use lemmy_db::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
@ -49,7 +50,13 @@ use lemmy_db::{
user::User_, user::User_,
Crud, Crud,
}; };
use lemmy_utils::{convert_datetime, remove_slurs, scrape_text_for_mentions, MentionData}; use lemmy_utils::{
convert_datetime,
location_info,
remove_slurs,
scrape_text_for_mentions,
MentionData,
};
use log::debug; use log::debug;
use serde::Deserialize; use serde::Deserialize;
use serde_json::Error; use serde_json::Error;
@ -136,21 +143,21 @@ impl FromApub for CommentForm {
) -> Result<CommentForm, LemmyError> { ) -> Result<CommentForm, LemmyError> {
let creator_actor_id = &note let creator_actor_id = &note
.attributed_to() .attributed_to()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.unwrap(); .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?; let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?;
let mut in_reply_tos = note let mut in_reply_tos = note
.in_reply_to() .in_reply_to()
.as_ref() .as_ref()
.unwrap() .context(location_info!())?
.as_many() .as_many()
.unwrap() .context(location_info!())?
.iter() .iter()
.map(|i| i.as_xsd_any_uri().unwrap()); .map(|i| i.as_xsd_any_uri().context(""));
let post_ap_id = in_reply_tos.next().unwrap(); let post_ap_id = in_reply_tos.next().context(location_info!())??;
// This post, or the parent comment might not yet exist on this server yet, fetch them. // This post, or the parent comment might not yet exist on this server yet, fetch them.
let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?; let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?;
@ -159,7 +166,7 @@ impl FromApub for CommentForm {
// For deeply nested comments, FromApub automatically gets called recursively // For deeply nested comments, FromApub automatically gets called recursively
let parent_id: Option<i32> = match in_reply_tos.next() { let parent_id: Option<i32> = match in_reply_tos.next() {
Some(parent_comment_uri) => { Some(parent_comment_uri) => {
let parent_comment_ap_id = &parent_comment_uri; let parent_comment_ap_id = &parent_comment_uri?;
let parent_comment = let parent_comment =
get_or_fetch_and_insert_comment(&parent_comment_ap_id, client, pool).await?; get_or_fetch_and_insert_comment(&parent_comment_ap_id, client, pool).await?;
@ -169,9 +176,9 @@ impl FromApub for CommentForm {
}; };
let content = note let content = note
.content() .content()
.unwrap() .context(location_info!())?
.as_single_xsd_string() .as_single_xsd_string()
.unwrap() .context(location_info!())?
.to_string(); .to_string();
let content_slurs_removed = remove_slurs(&content); let content_slurs_removed = remove_slurs(&content);

View File

@ -40,6 +40,7 @@ use activitystreams::{
}; };
use activitystreams_ext::Ext2; use activitystreams_ext::Ext2;
use actix_web::{body::Body, client::Client, web, HttpResponse}; use actix_web::{body::Body, client::Client, web, HttpResponse};
use anyhow::Context;
use itertools::Itertools; use itertools::Itertools;
use lemmy_db::{ use lemmy_db::{
community::{Community, CommunityForm}, community::{Community, CommunityForm},
@ -48,7 +49,7 @@ use lemmy_db::{
post::Post, post::Post,
user::User_, user::User_,
}; };
use lemmy_utils::convert_datetime; use lemmy_utils::{convert_datetime, location_info};
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
@ -142,7 +143,11 @@ impl ActorType for Community {
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let actor_uri = follow.actor()?.as_single_xsd_any_uri().unwrap().to_string(); let actor_uri = follow
.actor()?
.as_single_xsd_any_uri()
.context(location_info!())?
.to_string();
let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?); let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?);
let to = format!("{}/inbox", actor_uri); let to = format!("{}/inbox", actor_uri);
@ -330,44 +335,50 @@ impl FromApub for CommunityForm {
pool: &DbPool, pool: &DbPool,
expected_domain: Option<Url>, expected_domain: Option<Url>,
) -> Result<Self, LemmyError> { ) -> Result<Self, LemmyError> {
let creator_and_moderator_uris = group.inner.attributed_to().unwrap(); let creator_and_moderator_uris = group.inner.attributed_to().context(location_info!())?;
let creator_uri = creator_and_moderator_uris let creator_uri = creator_and_moderator_uris
.as_many() .as_many()
.unwrap() .context(location_info!())?
.iter() .iter()
.next() .next()
.unwrap() .context(location_info!())?
.as_xsd_any_uri() .as_xsd_any_uri()
.unwrap(); .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_uri, client, pool).await?; let creator = get_or_fetch_and_upsert_user(creator_uri, client, pool).await?;
let name = group let name = group
.inner .inner
.name() .name()
.unwrap() .context(location_info!())?
.as_one() .as_one()
.unwrap() .context(location_info!())?
.as_xsd_string() .as_xsd_string()
.unwrap() .context(location_info!())?
.to_string();
let title = group
.inner
.preferred_username()
.context(location_info!())?
.to_string(); .to_string();
let title = group.inner.preferred_username().unwrap().to_string();
// TODO: should be parsed as html and tags like <script> removed (or use markdown source) // TODO: should be parsed as html and tags like <script> removed (or use markdown source)
// -> same for post.content etc // -> same for post.content etc
let description = group let description = group
.inner .inner
.content() .content()
.map(|s| s.as_single_xsd_string().unwrap().into()); .map(|s| s.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
check_slurs(&name)?; check_slurs(&name)?;
check_slurs(&title)?; check_slurs(&title)?;
check_slurs_opt(&description)?; check_slurs_opt(&description)?;
let icon = match group.icon() { let icon = match group.icon() {
Some(any_image) => Some( Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone()) Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
.unwrap() .context(location_info!())?
.unwrap() .context(location_info!())?
.url() .url()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.map(|u| u.to_string()), .map(|u| u.to_string()),
), ),
@ -376,11 +387,11 @@ impl FromApub for CommunityForm {
let banner = match group.image() { let banner = match group.image() {
Some(any_image) => Some( Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone()) Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
.unwrap() .context(location_info!())?
.unwrap() .context(location_info!())?
.url() .url()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.map(|u| u.to_string()), .map(|u| u.to_string()),
), ),

View File

@ -37,8 +37,8 @@ pub async fn sign(
activity, activity,
move |signing_string| { move |signing_string| {
let private_key = PKey::private_key_from_pem(private_key.as_bytes())?; let private_key = PKey::private_key_from_pem(private_key.as_bytes())?;
let mut signer = Signer::new(MessageDigest::sha256(), &private_key).unwrap(); let mut signer = Signer::new(MessageDigest::sha256(), &private_key)?;
signer.update(signing_string.as_bytes()).unwrap(); signer.update(signing_string.as_bytes())?;
Ok(base64::encode(signer.sign_to_vec()?)) as Result<_, LemmyError> Ok(base64::encode(signer.sign_to_vec()?)) as Result<_, LemmyError>
}, },
@ -62,8 +62,8 @@ pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyE
&signing_string &signing_string
); );
let public_key = PKey::public_key_from_pem(actor.public_key().as_bytes())?; let public_key = PKey::public_key_from_pem(actor.public_key().as_bytes())?;
let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key).unwrap(); let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?;
verifier.update(&signing_string.as_bytes()).unwrap(); verifier.update(&signing_string.as_bytes())?;
Ok(verifier.verify(&base64::decode(signature)?)?) Ok(verifier.verify(&base64::decode(signature)?)?)
})?; })?;

View File

@ -17,7 +17,7 @@ use crate::{
}; };
use activitystreams::{base::BaseExt, collection::OrderedCollection, object::Note, prelude::*}; use activitystreams::{base::BaseExt, collection::OrderedCollection, object::Note, prelude::*};
use actix_web::client::Client; use actix_web::client::Client;
use anyhow::anyhow; use anyhow::{anyhow, Context};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use diesel::{result::Error::NotFound, PgConnection}; use diesel::{result::Error::NotFound, PgConnection};
use lemmy_db::{ use lemmy_db::{
@ -34,7 +34,7 @@ use lemmy_db::{
Joinable, Joinable,
SearchType, SearchType,
}; };
use lemmy_utils::get_apub_protocol_string; use lemmy_utils::{get_apub_protocol_string, location_info};
use log::debug; use log::debug;
use serde::Deserialize; use serde::Deserialize;
use std::{fmt::Debug, time::Duration}; use std::{fmt::Debug, time::Duration};
@ -144,10 +144,10 @@ pub async fn search_by_apub_id(
users: vec![], users: vec![],
}; };
let domain = query_url.domain().unwrap(); let domain = query_url.domain().context("url has no domain")?;
let response = match fetch_remote_object::<SearchAcceptedObjects>(client, &query_url).await? { let response = match fetch_remote_object::<SearchAcceptedObjects>(client, &query_url).await? {
SearchAcceptedObjects::Person(p) => { SearchAcceptedObjects::Person(p) => {
let user_uri = p.inner.id(domain)?.unwrap(); let user_uri = p.inner.id(domain)?.context("person has no id")?;
let user = get_or_fetch_and_upsert_user(&user_uri, client, pool).await?; let user = get_or_fetch_and_upsert_user(&user_uri, client, pool).await?;
@ -157,7 +157,7 @@ pub async fn search_by_apub_id(
response response
} }
SearchAcceptedObjects::Group(g) => { SearchAcceptedObjects::Group(g) => {
let community_uri = g.inner.id(domain)?.unwrap(); let community_uri = g.inner.id(domain)?.context("group has no id")?;
let community = get_or_fetch_and_upsert_community(community_uri, client, pool).await?; let community = get_or_fetch_and_upsert_community(community_uri, client, pool).await?;
@ -181,10 +181,19 @@ pub async fn search_by_apub_id(
response response
} }
SearchAcceptedObjects::Comment(c) => { SearchAcceptedObjects::Comment(c) => {
let post_url = c.in_reply_to().as_ref().unwrap().as_many().unwrap(); let post_url = c
.in_reply_to()
.as_ref()
.context(location_info!())?
.as_many()
.context(location_info!())?;
// TODO: also fetch parent comments if any // TODO: also fetch parent comments if any
let x = post_url.first().unwrap().as_xsd_any_uri().unwrap(); let x = post_url
.first()
.context(location_info!())?
.as_xsd_any_uri()
.context(location_info!())?;
let post = fetch_remote_object(client, x).await?; let post = fetch_remote_object(client, x).await?;
let post_form = PostForm::from_apub(&post, client, pool, Some(query_url.clone())).await?; let post_form = PostForm::from_apub(&post, client, pool, Some(query_url.clone())).await?;
let comment_form = CommentForm::from_apub(&c, client, pool, Some(query_url)).await?; let comment_form = CommentForm::from_apub(&c, client, pool, Some(query_url)).await?;
@ -312,13 +321,13 @@ async fn fetch_remote_community(
.await??; .await??;
// Also add the community moderators too // Also add the community moderators too
let attributed_to = group.inner.attributed_to().unwrap(); let attributed_to = group.inner.attributed_to().context(location_info!())?;
let creator_and_moderator_uris: Vec<&Url> = attributed_to let creator_and_moderator_uris: Vec<&Url> = attributed_to
.as_many() .as_many()
.unwrap() .context(location_info!())?
.iter() .iter()
.map(|a| a.as_xsd_any_uri().unwrap()) .map(|a| a.as_xsd_any_uri().context(""))
.collect(); .collect::<Result<Vec<&Url>, anyhow::Error>>()?;
let mut creator_and_moderators = Vec::new(); let mut creator_and_moderators = Vec::new();
@ -348,9 +357,9 @@ async fn fetch_remote_community(
// fetch outbox (maybe make this conditional) // fetch outbox (maybe make this conditional)
let outbox = let outbox =
fetch_remote_object::<OrderedCollection>(client, &community.get_outbox_url()?).await?; fetch_remote_object::<OrderedCollection>(client, &community.get_outbox_url()?).await?;
let outbox_items = outbox.items().unwrap().clone(); let outbox_items = outbox.items().context(location_info!())?.clone();
for o in outbox_items.many().unwrap() { for o in outbox_items.many().context(location_info!())? {
let page = PageExt::from_any_base(o)?.unwrap(); let page = PageExt::from_any_base(o)?.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?; let post = PostForm::from_apub(&page, client, pool, None).await?;
let post_ap_id = post.ap_id.clone(); let post_ap_id = post.ap_id.clone();
// Check whether the post already exists in the local db // Check whether the post already exists in the local db
@ -452,7 +461,7 @@ pub async fn get_or_fetch_and_insert_comment(
// Ok( // Ok(
// items // items
// .unwrap() // .context(location_info!())?
// .map(|obox: &BaseBox| -> Result<PostForm, LemmyError> { // .map(|obox: &BaseBox| -> Result<PostForm, LemmyError> {
// let page = obox.clone().to_concrete::<Page>()?; // let page = obox.clone().to_concrete::<Page>()?;
// PostForm::from_page(&page, conn) // PostForm::from_page(&page, conn)

View File

@ -21,6 +21,8 @@ use activitystreams::{
prelude::ExtendsExt, prelude::ExtendsExt,
}; };
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_utils::location_info;
pub async fn receive_announce( pub async fn receive_announce(
activity: AnyBase, activity: AnyBase,
@ -28,15 +30,15 @@ pub async fn receive_announce(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let announce = Announce::from_any_base(activity)?.unwrap(); let announce = Announce::from_any_base(activity)?.context(location_info!())?;
// ensure that announce and community come from the same instance // ensure that announce and community come from the same instance
let community = get_community_id_from_activity(&announce)?; let community = get_community_id_from_activity(&announce)?;
announce.id(community.domain().unwrap())?; announce.id(community.domain().context(location_info!())?)?;
let kind = announce.object().as_single_kind_str(); let kind = announce.object().as_single_kind_str();
let object = announce.object(); let object = announce.object();
let object2 = object.clone().one().unwrap(); let object2 = object.clone().one().context(location_info!())?;
match kind { match kind {
Some("Create") => receive_create(object2, client, pool, chat_server).await, Some("Create") => receive_create(object2, client, pool, chat_server).await,
Some("Update") => receive_update(object2, client, pool, chat_server).await, Some("Update") => receive_update(object2, client, pool, chat_server).await,

View File

@ -24,6 +24,7 @@ use crate::{
}; };
use activitystreams::{activity::Create, base::AnyBase, object::Note, prelude::*}; use activitystreams::{activity::Create, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
comment_view::CommentView, comment_view::CommentView,
@ -31,7 +32,7 @@ use lemmy_db::{
post_view::PostView, post_view::PostView,
Crud, Crud,
}; };
use lemmy_utils::scrape_text_for_mentions; use lemmy_utils::{location_info, scrape_text_for_mentions};
pub async fn receive_create( pub async fn receive_create(
activity: AnyBase, activity: AnyBase,
@ -39,11 +40,11 @@ pub async fn receive_create(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let create = Create::from_any_base(activity)?.unwrap(); let create = Create::from_any_base(activity)?.context(location_info!())?;
// ensure that create and actor come from the same instance // ensure that create and actor come from the same instance
let user = get_user_from_activity(&create, client, pool).await?; let user = get_user_from_activity(&create, client, pool).await?;
create.id(user.actor_id()?.domain().unwrap())?; create.id(user.actor_id()?.domain().context(location_info!())?)?;
match create.object().as_single_kind_str() { match create.object().as_single_kind_str() {
Some("Page") => receive_create_post(create, client, pool, chat_server).await, Some("Page") => receive_create_post(create, client, pool, chat_server).await,
@ -59,7 +60,8 @@ async fn receive_create_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&create, client, pool).await?; let user = get_user_from_activity(&create, client, pool).await?;
let page = PageExt::from_any_base(create.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?; let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?;
@ -91,7 +93,8 @@ async fn receive_create_comment(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&create, client, pool).await?; let user = get_user_from_activity(&create, client, pool).await?;
let note = Note::from_any_base(create.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(create.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)).await?; let comment = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)).await?;

View File

@ -23,6 +23,7 @@ use crate::{
}; };
use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*}; use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
comment_view::CommentView, comment_view::CommentView,
@ -33,6 +34,7 @@ use lemmy_db::{
post_view::PostView, post_view::PostView,
Crud, Crud,
}; };
use lemmy_utils::location_info;
pub async fn receive_delete( pub async fn receive_delete(
activity: AnyBase, activity: AnyBase,
@ -40,7 +42,7 @@ pub async fn receive_delete(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(activity)?.unwrap(); let delete = Delete::from_any_base(activity)?.context(location_info!())?;
match delete.object().as_single_kind_str() { match delete.object().as_single_kind_str() {
Some("Page") => receive_delete_post(delete, client, pool, chat_server).await, Some("Page") => receive_delete_post(delete, client, pool, chat_server).await,
Some("Note") => receive_delete_comment(delete, client, pool, chat_server).await, Some("Note") => receive_delete_comment(delete, client, pool, chat_server).await,
@ -56,7 +58,8 @@ async fn receive_delete_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&delete, client, pool).await?; let user = get_user_from_activity(&delete, client, pool).await?;
let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)) let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?))
.await? .await?
@ -110,7 +113,8 @@ async fn receive_delete_comment(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&delete, client, pool).await?; let user = get_user_from_activity(&delete, client, pool).await?;
let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)) let comment_ap_id = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?))
.await? .await?
@ -166,7 +170,8 @@ async fn receive_delete_community(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let user = get_user_from_activity(&delete, client, pool).await?; let user = get_user_from_activity(&delete, client, pool).await?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?)) let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?))

View File

@ -21,6 +21,7 @@ use crate::{
}; };
use activitystreams::{activity::Dislike, base::AnyBase, object::Note, prelude::*}; use activitystreams::{activity::Dislike, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
comment::{CommentForm, CommentLike, CommentLikeForm}, comment::{CommentForm, CommentLike, CommentLikeForm},
comment_view::CommentView, comment_view::CommentView,
@ -28,6 +29,7 @@ use lemmy_db::{
post_view::PostView, post_view::PostView,
Likeable, Likeable,
}; };
use lemmy_utils::location_info;
pub async fn receive_dislike( pub async fn receive_dislike(
activity: AnyBase, activity: AnyBase,
@ -35,7 +37,7 @@ pub async fn receive_dislike(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let dislike = Dislike::from_any_base(activity)?.unwrap(); let dislike = Dislike::from_any_base(activity)?.context(location_info!())?;
match dislike.object().as_single_kind_str() { match dislike.object().as_single_kind_str() {
Some("Page") => receive_dislike_post(dislike, client, pool, chat_server).await, Some("Page") => receive_dislike_post(dislike, client, pool, chat_server).await,
Some("Note") => receive_dislike_comment(dislike, client, pool, chat_server).await, Some("Note") => receive_dislike_comment(dislike, client, pool, chat_server).await,
@ -50,7 +52,14 @@ async fn receive_dislike_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&dislike, client, pool).await?; let user = get_user_from_activity(&dislike, client, pool).await?;
let page = PageExt::from_any_base(dislike.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(
dislike
.object()
.to_owned()
.one()
.context(location_info!())?,
)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?; let post = PostForm::from_apub(&page, client, pool, None).await?;
@ -90,7 +99,14 @@ async fn receive_dislike_comment(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let note = Note::from_any_base(dislike.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(
dislike
.object()
.to_owned()
.one()
.context(location_info!())?,
)?
.context(location_info!())?;
let user = get_user_from_activity(&dislike, client, pool).await?; let user = get_user_from_activity(&dislike, client, pool).await?;
let comment = CommentForm::from_apub(&note, client, pool, None).await?; let comment = CommentForm::from_apub(&note, client, pool, None).await?;

View File

@ -21,6 +21,7 @@ use crate::{
}; };
use activitystreams::{activity::Like, base::AnyBase, object::Note, prelude::*}; use activitystreams::{activity::Like, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
comment::{CommentForm, CommentLike, CommentLikeForm}, comment::{CommentForm, CommentLike, CommentLikeForm},
comment_view::CommentView, comment_view::CommentView,
@ -28,6 +29,7 @@ use lemmy_db::{
post_view::PostView, post_view::PostView,
Likeable, Likeable,
}; };
use lemmy_utils::location_info;
pub async fn receive_like( pub async fn receive_like(
activity: AnyBase, activity: AnyBase,
@ -35,7 +37,7 @@ pub async fn receive_like(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let like = Like::from_any_base(activity)?.unwrap(); let like = Like::from_any_base(activity)?.context(location_info!())?;
match like.object().as_single_kind_str() { match like.object().as_single_kind_str() {
Some("Page") => receive_like_post(like, client, pool, chat_server).await, Some("Page") => receive_like_post(like, client, pool, chat_server).await,
Some("Note") => receive_like_comment(like, client, pool, chat_server).await, Some("Note") => receive_like_comment(like, client, pool, chat_server).await,
@ -50,7 +52,8 @@ async fn receive_like_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&like, client, pool).await?; let user = get_user_from_activity(&like, client, pool).await?;
let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?; let post = PostForm::from_apub(&page, client, pool, None).await?;
@ -90,7 +93,8 @@ async fn receive_like_comment(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let user = get_user_from_activity(&like, client, pool).await?; let user = get_user_from_activity(&like, client, pool).await?;
let comment = CommentForm::from_apub(&note, client, pool, None).await?; let comment = CommentForm::from_apub(&note, client, pool, None).await?;

View File

@ -24,7 +24,7 @@ use crate::{
}; };
use activitystreams::{activity::Remove, base::AnyBase, object::Note, prelude::*}; use activitystreams::{activity::Remove, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::anyhow; use anyhow::{anyhow, Context};
use lemmy_db::{ use lemmy_db::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
comment_view::CommentView, comment_view::CommentView,
@ -35,6 +35,7 @@ use lemmy_db::{
post_view::PostView, post_view::PostView,
Crud, Crud,
}; };
use lemmy_utils::location_info;
pub async fn receive_remove( pub async fn receive_remove(
activity: AnyBase, activity: AnyBase,
@ -42,7 +43,7 @@ pub async fn receive_remove(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let remove = Remove::from_any_base(activity)?.unwrap(); let remove = Remove::from_any_base(activity)?.context(location_info!())?;
let actor = get_user_from_activity(&remove, client, pool).await?; let actor = get_user_from_activity(&remove, client, pool).await?;
let community = get_community_id_from_activity(&remove)?; let community = get_community_id_from_activity(&remove)?;
if actor.actor_id()?.domain() != community.domain() { if actor.actor_id()?.domain() != community.domain() {
@ -64,7 +65,8 @@ async fn receive_remove_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(&remove, client, pool).await?; let mod_ = get_user_from_activity(&remove, client, pool).await?;
let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, None) let post_ap_id = PostForm::from_apub(&page, client, pool, None)
.await? .await?
@ -118,7 +120,8 @@ async fn receive_remove_comment(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(&remove, client, pool).await?; let mod_ = get_user_from_activity(&remove, client, pool).await?;
let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, None) let comment_ap_id = CommentForm::from_apub(&note, client, pool, None)
.await? .await?
@ -175,7 +178,8 @@ async fn receive_remove_community(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(&remove, client, pool).await?; let mod_ = get_user_from_activity(&remove, client, pool).await?;
let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?)) let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?))
.await? .await?

View File

@ -28,7 +28,7 @@ use activitystreams::{
prelude::*, prelude::*,
}; };
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::anyhow; use anyhow::{anyhow, Context};
use lemmy_db::{ use lemmy_db::{
comment::{Comment, CommentForm, CommentLike, CommentLikeForm}, comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
comment_view::CommentView, comment_view::CommentView,
@ -40,6 +40,7 @@ use lemmy_db::{
Crud, Crud,
Likeable, Likeable,
}; };
use lemmy_utils::location_info;
pub async fn receive_undo( pub async fn receive_undo(
activity: AnyBase, activity: AnyBase,
@ -47,7 +48,7 @@ pub async fn receive_undo(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let undo = Undo::from_any_base(activity)?.unwrap(); let undo = Undo::from_any_base(activity)?.context(location_info!())?;
match undo.object().as_single_kind_str() { match undo.object().as_single_kind_str() {
Some("Delete") => receive_undo_delete(undo, client, pool, chat_server).await, Some("Delete") => receive_undo_delete(undo, client, pool, chat_server).await,
Some("Remove") => receive_undo_remove(undo, client, pool, chat_server).await, Some("Remove") => receive_undo_remove(undo, client, pool, chat_server).await,
@ -62,10 +63,14 @@ where
T: AsBase<A> + ActorAndObjectRef, T: AsBase<A> + ActorAndObjectRef,
{ {
let outer_actor = outer_activity.actor()?; let outer_actor = outer_activity.actor()?;
let outer_actor_uri = outer_actor.as_single_xsd_any_uri().unwrap(); let outer_actor_uri = outer_actor
.as_single_xsd_any_uri()
.context(location_info!())?;
let inner_actor = inner_activity.actor()?; let inner_actor = inner_activity.actor()?;
let inner_actor_uri = inner_actor.as_single_xsd_any_uri().unwrap(); let inner_actor_uri = inner_actor
.as_single_xsd_any_uri()
.context(location_info!())?;
if outer_actor_uri.domain() != inner_actor_uri.domain() { if outer_actor_uri.domain() != inner_actor_uri.domain() {
Err(anyhow!("Cant undo activities from a different instance").into()) Err(anyhow!("Cant undo activities from a different instance").into())
@ -80,9 +85,13 @@ async fn receive_undo_delete(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap(); let delete = Delete::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &delete)?; check_is_undo_valid(&undo, &delete)?;
let type_ = delete.object().as_single_kind_str().unwrap(); let type_ = delete
.object()
.as_single_kind_str()
.context(location_info!())?;
match type_ { match type_ {
"Note" => receive_undo_delete_comment(undo, &delete, client, pool, chat_server).await, "Note" => receive_undo_delete_comment(undo, &delete, client, pool, chat_server).await,
"Page" => receive_undo_delete_post(undo, &delete, client, pool, chat_server).await, "Page" => receive_undo_delete_post(undo, &delete, client, pool, chat_server).await,
@ -97,10 +106,14 @@ async fn receive_undo_remove(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let remove = Remove::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap(); let remove = Remove::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &remove)?; check_is_undo_valid(&undo, &remove)?;
let type_ = remove.object().as_single_kind_str().unwrap(); let type_ = remove
.object()
.as_single_kind_str()
.context(location_info!())?;
match type_ { match type_ {
"Note" => receive_undo_remove_comment(undo, &remove, client, pool, chat_server).await, "Note" => receive_undo_remove_comment(undo, &remove, client, pool, chat_server).await,
"Page" => receive_undo_remove_post(undo, &remove, client, pool, chat_server).await, "Page" => receive_undo_remove_post(undo, &remove, client, pool, chat_server).await,
@ -115,10 +128,14 @@ async fn receive_undo_like(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let like = Like::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap(); let like = Like::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &like)?; check_is_undo_valid(&undo, &like)?;
let type_ = like.object().as_single_kind_str().unwrap(); let type_ = like
.object()
.as_single_kind_str()
.context(location_info!())?;
match type_ { match type_ {
"Note" => receive_undo_like_comment(undo, &like, client, pool, chat_server).await, "Note" => receive_undo_like_comment(undo, &like, client, pool, chat_server).await,
"Page" => receive_undo_like_post(undo, &like, client, pool, chat_server).await, "Page" => receive_undo_like_post(undo, &like, client, pool, chat_server).await,
@ -132,12 +149,16 @@ async fn receive_undo_dislike(
_pool: &DbPool, _pool: &DbPool,
_chat_server: ChatServerParam, _chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let dislike = Dislike::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap(); let dislike = Dislike::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &dislike)?; check_is_undo_valid(&undo, &dislike)?;
// TODO: need to implement Undo<Dislike> // TODO: need to implement Undo<Dislike>
let type_ = dislike.object().as_single_kind_str().unwrap(); let type_ = dislike
.object()
.as_single_kind_str()
.context(location_info!())?;
Err(anyhow!("Undo Delete type {} not supported", type_).into()) Err(anyhow!("Undo Delete type {} not supported", type_).into())
} }
@ -149,7 +170,8 @@ async fn receive_undo_delete_comment(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(delete, client, pool).await?; let user = get_user_from_activity(delete, client, pool).await?;
let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)) let comment_ap_id = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?))
.await? .await?
@ -207,7 +229,8 @@ async fn receive_undo_remove_comment(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(remove, client, pool).await?; let mod_ = get_user_from_activity(remove, client, pool).await?;
let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, None) let comment_ap_id = CommentForm::from_apub(&note, client, pool, None)
.await? .await?
@ -265,7 +288,8 @@ async fn receive_undo_delete_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(delete, client, pool).await?; let user = get_user_from_activity(delete, client, pool).await?;
let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)) let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?))
.await? .await?
@ -320,7 +344,8 @@ async fn receive_undo_remove_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(remove, client, pool).await?; let mod_ = get_user_from_activity(remove, client, pool).await?;
let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, None) let post_ap_id = PostForm::from_apub(&page, client, pool, None)
.await? .await?
@ -375,7 +400,8 @@ async fn receive_undo_delete_community(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(delete, client, pool).await?; let user = get_user_from_activity(delete, client, pool).await?;
let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?)) let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?))
.await? .await?
@ -441,7 +467,8 @@ async fn receive_undo_remove_community(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(remove, client, pool).await?; let mod_ = get_user_from_activity(remove, client, pool).await?;
let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?)) let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?))
.await? .await?
@ -507,7 +534,8 @@ async fn receive_undo_like_comment(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(like, client, pool).await?; let user = get_user_from_activity(like, client, pool).await?;
let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment = CommentForm::from_apub(&note, client, pool, None).await?; let comment = CommentForm::from_apub(&note, client, pool, None).await?;
@ -553,7 +581,8 @@ async fn receive_undo_like_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(like, client, pool).await?; let user = get_user_from_activity(like, client, pool).await?;
let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?; let post = PostForm::from_apub(&page, client, pool, None).await?;

View File

@ -25,6 +25,7 @@ use crate::{
}; };
use activitystreams::{activity::Update, base::AnyBase, object::Note, prelude::*}; use activitystreams::{activity::Update, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse}; use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
comment::{Comment, CommentForm}, comment::{Comment, CommentForm},
comment_view::CommentView, comment_view::CommentView,
@ -32,7 +33,7 @@ use lemmy_db::{
post_view::PostView, post_view::PostView,
Crud, Crud,
}; };
use lemmy_utils::scrape_text_for_mentions; use lemmy_utils::{location_info, scrape_text_for_mentions};
pub async fn receive_update( pub async fn receive_update(
activity: AnyBase, activity: AnyBase,
@ -40,11 +41,11 @@ pub async fn receive_update(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let update = Update::from_any_base(activity)?.unwrap(); let update = Update::from_any_base(activity)?.context(location_info!())?;
// ensure that update and actor come from the same instance // ensure that update and actor come from the same instance
let user = get_user_from_activity(&update, client, pool).await?; let user = get_user_from_activity(&update, client, pool).await?;
update.id(user.actor_id()?.domain().unwrap())?; update.id(user.actor_id()?.domain().context(location_info!())?)?;
match update.object().as_single_kind_str() { match update.object().as_single_kind_str() {
Some("Page") => receive_update_post(update, client, pool, chat_server).await, Some("Page") => receive_update_post(update, client, pool, chat_server).await,
@ -60,7 +61,8 @@ async fn receive_update_post(
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&update, client, pool).await?; let user = get_user_from_activity(&update, client, pool).await?;
let page = PageExt::from_any_base(update.object().to_owned().one().unwrap())?.unwrap(); let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?; let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?;
@ -97,7 +99,8 @@ async fn receive_update_comment(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let note = Note::from_any_base(update.object().to_owned().one().unwrap())?.unwrap(); let note = Note::from_any_base(update.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let user = get_user_from_activity(&update, client, pool).await?; let user = get_user_from_activity(&update, client, pool).await?;
let comment = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)).await?; let comment = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)).await?;

View File

@ -16,12 +16,13 @@ use activitystreams::{
prelude::*, prelude::*,
}; };
use actix_web::{client::Client, web, HttpRequest, HttpResponse}; use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use anyhow::anyhow; use anyhow::{anyhow, Context};
use lemmy_db::{ use lemmy_db::{
community::{Community, CommunityFollower, CommunityFollowerForm}, community::{Community, CommunityFollower, CommunityFollowerForm},
user::User_, user::User_,
Followable, Followable,
}; };
use lemmy_utils::location_info;
use log::debug; use log::debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
@ -62,7 +63,10 @@ pub async fn community_inbox(
"Community {} received activity {:?}", "Community {} received activity {:?}",
&community.name, &activity &community.name, &activity
); );
let user_uri = activity.actor()?.as_single_xsd_any_uri().unwrap(); let user_uri = activity
.actor()?
.as_single_xsd_any_uri()
.context(location_info!())?;
check_is_apub_id_valid(user_uri)?; check_is_apub_id_valid(user_uri)?;
let user = get_or_fetch_and_upsert_user(&user_uri, &client, &db).await?; let user = get_or_fetch_and_upsert_user(&user_uri, &client, &db).await?;
@ -70,7 +74,7 @@ pub async fn community_inbox(
verify(&request, &user)?; verify(&request, &user)?;
let any_base = activity.clone().into_any_base()?; let any_base = activity.clone().into_any_base()?;
let kind = activity.kind().unwrap(); let kind = activity.kind().context(location_info!())?;
let user_id = user.id; let user_id = user.id;
let res = match kind { let res = match kind {
ValidTypes::Follow => handle_follow(any_base, user, community, &client, &db).await, ValidTypes::Follow => handle_follow(any_base, user, community, &client, &db).await,
@ -90,7 +94,7 @@ async fn handle_follow(
client: &Client, client: &Client,
db: &DbPoolParam, db: &DbPoolParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let follow = Follow::from_any_base(activity)?.unwrap(); let follow = Follow::from_any_base(activity)?.context(location_info!())?;
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: community.id, community_id: community.id,
user_id: user.id, user_id: user.id,
@ -113,7 +117,7 @@ async fn handle_undo_follow(
community: Community, community: Community,
db: &DbPoolParam, db: &DbPoolParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let _undo = Undo::from_any_base(activity)?.unwrap(); let _undo = Undo::from_any_base(activity)?.context(location_info!())?;
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: community.id, community_id: community.id,

View File

@ -31,7 +31,9 @@ use activitystreams::{
prelude::*, prelude::*,
}; };
use actix_web::{client::Client, web, HttpRequest, HttpResponse}; use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use anyhow::Context;
use lemmy_db::user::User_; use lemmy_db::user::User_;
use lemmy_utils::location_info;
use log::debug; use log::debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
@ -67,7 +69,11 @@ pub async fn shared_inbox(
let json = serde_json::to_string(&activity)?; let json = serde_json::to_string(&activity)?;
debug!("Shared inbox received activity: {}", json); debug!("Shared inbox received activity: {}", json);
let sender = &activity.actor()?.to_owned().single_xsd_any_uri().unwrap(); let sender = &activity
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let community = get_community_id_from_activity(&activity)?; let community = get_community_id_from_activity(&activity)?;
check_is_apub_id_valid(sender)?; check_is_apub_id_valid(sender)?;
@ -77,7 +83,7 @@ pub async fn shared_inbox(
verify(&request, actor.as_ref())?; verify(&request, actor.as_ref())?;
let any_base = activity.clone().into_any_base()?; let any_base = activity.clone().into_any_base()?;
let kind = activity.kind().unwrap(); let kind = activity.kind().context(location_info!())?;
let res = match kind { let res = match kind {
ValidTypes::Announce => receive_announce(any_base, &client, &pool, chat_server).await, ValidTypes::Announce => receive_announce(any_base, &client, &pool, chat_server).await,
ValidTypes::Create => receive_create(any_base, &client, &pool, chat_server).await, ValidTypes::Create => receive_create(any_base, &client, &pool, chat_server).await,
@ -112,7 +118,7 @@ where
T: AsBase<A> + ActorAndObjectRef, T: AsBase<A> + ActorAndObjectRef,
{ {
let actor = activity.actor()?; let actor = activity.actor()?;
let user_uri = actor.as_single_xsd_any_uri().unwrap(); let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?;
get_or_fetch_and_upsert_user(&user_uri, client, pool).await get_or_fetch_and_upsert_user(&user_uri, client, pool).await
} }
@ -122,9 +128,15 @@ pub(in crate::apub::inbox) fn get_community_id_from_activity<T, A>(
where where
T: AsBase<A> + ActorAndObjectRef + AsObject<A>, T: AsBase<A> + ActorAndObjectRef + AsObject<A>,
{ {
let cc = activity.cc().unwrap(); let cc = activity.cc().context(location_info!())?;
let cc = cc.as_many().unwrap(); let cc = cc.as_many().context(location_info!())?;
Ok(cc.first().unwrap().as_xsd_any_uri().unwrap().to_owned()) Ok(
cc.first()
.context(location_info!())?
.as_xsd_any_uri()
.context(location_info!())?
.to_owned(),
)
} }
pub(in crate::apub::inbox) async fn announce_if_community_is_local<T, Kind>( pub(in crate::apub::inbox) async fn announce_if_community_is_local<T, Kind>(
@ -139,9 +151,13 @@ where
Kind: Serialize, Kind: Serialize,
<T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static, <T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static,
{ {
let cc = activity.cc().unwrap(); let cc = activity.cc().context(location_info!())?;
let cc = cc.as_many().unwrap(); let cc = cc.as_many().context(location_info!())?;
let community_followers_uri = cc.first().unwrap().as_xsd_any_uri().unwrap(); let community_followers_uri = cc
.first()
.context(location_info!())?
.as_xsd_any_uri()
.context(location_info!())?;
// TODO: this is hacky but seems to be the only way to get the community ID // TODO: this is hacky but seems to be the only way to get the community ID
let community_uri = community_followers_uri let community_uri = community_followers_uri
.to_string() .to_string()

View File

@ -20,6 +20,7 @@ use activitystreams::{
prelude::*, prelude::*,
}; };
use actix_web::{client::Client, web, HttpRequest, HttpResponse}; use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
community::{CommunityFollower, CommunityFollowerForm}, community::{CommunityFollower, CommunityFollowerForm},
naive_now, naive_now,
@ -29,6 +30,7 @@ use lemmy_db::{
Crud, Crud,
Followable, Followable,
}; };
use lemmy_utils::location_info;
use log::debug; use log::debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
@ -58,7 +60,10 @@ pub async fn user_inbox(
let username = path.into_inner(); let username = path.into_inner();
debug!("User {} received activity: {:?}", &username, &activity); debug!("User {} received activity: {:?}", &username, &activity);
let actor_uri = activity.actor()?.as_single_xsd_any_uri().unwrap(); let actor_uri = activity
.actor()?
.as_single_xsd_any_uri()
.context(location_info!())?;
check_is_apub_id_valid(actor_uri)?; check_is_apub_id_valid(actor_uri)?;
@ -66,7 +71,7 @@ pub async fn user_inbox(
verify(&request, actor.as_ref())?; verify(&request, actor.as_ref())?;
let any_base = activity.clone().into_any_base()?; let any_base = activity.clone().into_any_base()?;
let kind = activity.kind().unwrap(); let kind = activity.kind().context(location_info!())?;
let res = match kind { let res = match kind {
ValidTypes::Accept => receive_accept(any_base, username, &client, &pool).await, ValidTypes::Accept => receive_accept(any_base, username, &client, &pool).await,
ValidTypes::Create => { ValidTypes::Create => {
@ -94,8 +99,12 @@ async fn receive_accept(
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let accept = Accept::from_any_base(activity)?.unwrap(); let accept = Accept::from_any_base(activity)?.context(location_info!())?;
let community_uri = accept.actor()?.to_owned().single_xsd_any_uri().unwrap(); let community_uri = accept
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let community = get_or_fetch_and_upsert_community(&community_uri, client, pool).await?; let community = get_or_fetch_and_upsert_community(&community_uri, client, pool).await?;
@ -123,10 +132,17 @@ async fn receive_create_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let create = Create::from_any_base(activity)?.unwrap(); let create = Create::from_any_base(activity)?.context(location_info!())?;
let note = Note::from_any_base(create.object().as_one().unwrap().to_owned())?.unwrap(); let note = Note::from_any_base(
create
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(create.id_unchecked().unwrap().to_owned()); let domain = Some(create.id_unchecked().context(location_info!())?.to_owned());
let private_message = PrivateMessageForm::from_apub(&note, client, pool, domain).await?; let private_message = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let inserted_private_message = blocking(pool, move |conn| { let inserted_private_message = blocking(pool, move |conn| {
@ -159,10 +175,17 @@ async fn receive_update_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let update = Update::from_any_base(activity)?.unwrap(); let update = Update::from_any_base(activity)?.context(location_info!())?;
let note = Note::from_any_base(update.object().as_one().unwrap().to_owned())?.unwrap(); let note = Note::from_any_base(
update
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(update.id_unchecked().unwrap().to_owned()); let domain = Some(update.id_unchecked().context(location_info!())?.to_owned());
let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, domain).await?; let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let private_message_ap_id = private_message_form.ap_id.clone(); let private_message_ap_id = private_message_form.ap_id.clone();
@ -203,10 +226,17 @@ async fn receive_delete_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(activity)?.unwrap(); let delete = Delete::from_any_base(activity)?.context(location_info!())?;
let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap(); let note = Note::from_any_base(
delete
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(delete.id_unchecked().unwrap().to_owned()); let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned());
let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, domain).await?; let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let private_message_ap_id = private_message_form.ap_id; let private_message_ap_id = private_message_form.ap_id;
@ -259,11 +289,19 @@ async fn receive_undo_delete_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let undo = Undo::from_any_base(activity)?.unwrap(); let undo = Undo::from_any_base(activity)?.context(location_info!())?;
let delete = Delete::from_any_base(undo.object().as_one().unwrap().to_owned())?.unwrap(); let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())?
let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap(); .context(location_info!())?;
let note = Note::from_any_base(
delete
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(undo.id_unchecked().unwrap().to_owned()); let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned());
let private_message = PrivateMessageForm::from_apub(&note, client, pool, domain).await?; let private_message = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let private_message_ap_id = private_message.ap_id.clone(); let private_message_ap_id = private_message.ap_id.clone();

View File

@ -30,10 +30,16 @@ use activitystreams::{
}; };
use activitystreams_ext::{Ext1, Ext2}; use activitystreams_ext::{Ext1, Ext2};
use actix_web::{body::Body, client::Client, HttpResponse}; use actix_web::{body::Body, client::Client, HttpResponse};
use anyhow::anyhow; use anyhow::{anyhow, Context};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use lemmy_db::{activity::do_insert_activity, user::User_}; use lemmy_db::{activity::do_insert_activity, user::User_};
use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings, MentionData}; use lemmy_utils::{
convert_datetime,
get_apub_protocol_string,
location_info,
settings::Settings,
MentionData,
};
use log::debug; use log::debug;
use serde::Serialize; use serde::Serialize;
use url::{ParseError, Url}; use url::{ParseError, Url};
@ -80,7 +86,12 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
// instance. replace is needed to remove the port in our federation test setup. // instance. replace is needed to remove the port in our federation test setup.
let settings = Settings::get(); let settings = Settings::get();
let local_instance = settings.hostname.split(':').collect::<Vec<&str>>(); let local_instance = settings.hostname.split(':').collect::<Vec<&str>>();
allowed_instances.push(local_instance.first().unwrap().to_string()); allowed_instances.push(
local_instance
.first()
.context(location_info!())?
.to_string(),
);
match apub_id.domain() { match apub_id.domain() {
Some(d) => { Some(d) => {
@ -197,10 +208,10 @@ where
T: Base + AsBase<Kind>, T: Base + AsBase<Kind>,
{ {
let actor_id = if let Some(url) = expected_domain { let actor_id = if let Some(url) = expected_domain {
let domain = url.domain().unwrap(); let domain = url.domain().context(location_info!())?;
apub.id(domain)?.unwrap() apub.id(domain)?.context(location_info!())?
} else { } else {
let actor_id = apub.id_unchecked().unwrap(); let actor_id = apub.id_unchecked().context(location_info!())?;
check_is_apub_id_valid(&actor_id)?; check_is_apub_id_valid(&actor_id)?;
actor_id actor_id
}; };

View File

@ -38,13 +38,14 @@ use activitystreams::{
}; };
use activitystreams_ext::Ext1; use activitystreams_ext::Ext1;
use actix_web::{body::Body, client::Client, web, HttpResponse}; use actix_web::{body::Body, client::Client, web, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
community::Community, community::Community,
post::{Post, PostForm}, post::{Post, PostForm},
user::User_, user::User_,
Crud, Crud,
}; };
use lemmy_utils::{convert_datetime, remove_slurs}; use lemmy_utils::{convert_datetime, location_info, remove_slurs};
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
@ -163,9 +164,9 @@ impl FromApub for PostForm {
.inner .inner
.attributed_to() .attributed_to()
.as_ref() .as_ref()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.unwrap(); .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?; let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?;
@ -173,17 +174,23 @@ impl FromApub for PostForm {
.inner .inner
.to() .to()
.as_ref() .as_ref()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.unwrap(); .context(location_info!())?;
let community = get_or_fetch_and_upsert_community(community_actor_id, client, pool).await?; let community = get_or_fetch_and_upsert_community(community_actor_id, client, pool).await?;
let thumbnail_url = match &page.inner.image() { let thumbnail_url = match &page.inner.image() {
Some(any_image) => Image::from_any_base(any_image.to_owned().as_one().unwrap().to_owned())? Some(any_image) => Image::from_any_base(
.unwrap() any_image
.to_owned()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?
.url() .url()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.map(|u| u.to_string()), .map(|u| u.to_string()),
None => None, None => None,
@ -210,9 +217,9 @@ impl FromApub for PostForm {
.inner .inner
.summary() .summary()
.as_ref() .as_ref()
.unwrap() .context(location_info!())?
.as_single_xsd_string() .as_single_xsd_string()
.unwrap() .context(location_info!())?
.to_string(); .to_string();
let url = page let url = page
.inner .inner

View File

@ -27,12 +27,13 @@ use activitystreams::{
prelude::*, prelude::*,
}; };
use actix_web::client::Client; use actix_web::client::Client;
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
private_message::{PrivateMessage, PrivateMessageForm}, private_message::{PrivateMessage, PrivateMessageForm},
user::User_, user::User_,
Crud, Crud,
}; };
use lemmy_utils::convert_datetime; use lemmy_utils::{convert_datetime, location_info};
use url::Url; use url::Url;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
@ -81,15 +82,20 @@ impl FromApub for PrivateMessageForm {
) -> Result<PrivateMessageForm, LemmyError> { ) -> Result<PrivateMessageForm, LemmyError> {
let creator_actor_id = note let creator_actor_id = note
.attributed_to() .attributed_to()
.unwrap() .context(location_info!())?
.clone() .clone()
.single_xsd_any_uri() .single_xsd_any_uri()
.unwrap(); .context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(&creator_actor_id, client, pool).await?; let creator = get_or_fetch_and_upsert_user(&creator_actor_id, client, pool).await?;
let recipient_actor_id = note.to().unwrap().clone().single_xsd_any_uri().unwrap(); let recipient_actor_id = note
.to()
.context(location_info!())?
.clone()
.single_xsd_any_uri()
.context(location_info!())?;
let recipient = get_or_fetch_and_upsert_user(&recipient_actor_id, client, pool).await?; let recipient = get_or_fetch_and_upsert_user(&recipient_actor_id, client, pool).await?;
let ap_id = note.id_unchecked().unwrap().to_string(); let ap_id = note.id_unchecked().context(location_info!())?.to_string();
check_is_apub_id_valid(&Url::parse(&ap_id)?)?; check_is_apub_id_valid(&Url::parse(&ap_id)?)?;
Ok(PrivateMessageForm { Ok(PrivateMessageForm {
@ -97,9 +103,9 @@ impl FromApub for PrivateMessageForm {
recipient_id: recipient.id, recipient_id: recipient.id,
content: note content: note
.content() .content()
.unwrap() .context(location_info!())?
.as_single_xsd_string() .as_single_xsd_string()
.unwrap() .context(location_info!())?
.to_string(), .to_string(),
published: note.published().map(|u| u.to_owned().naive_local()), published: note.published().map(|u| u.to_owned().naive_local()),
updated: note.updated().map(|u| u.to_owned().naive_local()), updated: note.updated().map(|u| u.to_owned().naive_local()),

View File

@ -28,11 +28,12 @@ use activitystreams::{
}; };
use activitystreams_ext::Ext1; use activitystreams_ext::Ext1;
use actix_web::{body::Body, client::Client, web, HttpResponse}; use actix_web::{body::Body, client::Client, web, HttpResponse};
use anyhow::Context;
use lemmy_db::{ use lemmy_db::{
naive_now, naive_now,
user::{UserForm, User_}, user::{UserForm, User_},
}; };
use lemmy_utils::convert_datetime; use lemmy_utils::{convert_datetime, location_info};
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
@ -221,11 +222,10 @@ impl FromApub for UserForm {
) -> Result<Self, LemmyError> { ) -> Result<Self, LemmyError> {
let avatar = match person.icon() { let avatar = match person.icon() {
Some(any_image) => Some( Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone()) Image::from_any_base(any_image.as_one().context(location_info!())?.clone())?
.unwrap() .context(location_info!())?
.unwrap()
.url() .url()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.map(|u| u.to_string()), .map(|u| u.to_string()),
), ),
@ -234,11 +234,11 @@ impl FromApub for UserForm {
let banner = match person.image() { let banner = match person.image() {
Some(any_image) => Some( Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone()) Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
.unwrap() .context(location_info!())?
.unwrap() .context(location_info!())?
.url() .url()
.unwrap() .context(location_info!())?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.map(|u| u.to_string()), .map(|u| u.to_string()),
), ),
@ -247,11 +247,11 @@ impl FromApub for UserForm {
let name = person let name = person
.name() .name()
.unwrap() .context(location_info!())?
.one() .one()
.unwrap() .context(location_info!())?
.as_xsd_string() .as_xsd_string()
.unwrap() .context(location_info!())?
.to_string(); .to_string();
let preferred_username = person.inner.preferred_username().map(|u| u.to_string()); let preferred_username = person.inner.preferred_username().map(|u| u.to_string());
let bio = person let bio = person