Added documentation for most functions
This commit is contained in:
parent
8908c8b184
commit
c5ced6fa5e
9 changed files with 62 additions and 53 deletions
|
@ -30,6 +30,7 @@ fn populate_object_props(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send an activity to a list of recipients, using the correct headers etc.
|
||||||
fn send_activity<A>(activity: &A, to: Vec<String>) -> Result<(), Error>
|
fn send_activity<A>(activity: &A, to: Vec<String>) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
A: Serialize + Debug,
|
A: Serialize + Debug,
|
||||||
|
@ -47,7 +48,8 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_followers(conn: &PgConnection, community: &Community) -> Result<Vec<String>, Error> {
|
/// For a given community, returns the inboxes of all followers.
|
||||||
|
fn get_follower_inboxes(conn: &PgConnection, community: &Community) -> Result<Vec<String>, Error> {
|
||||||
Ok(
|
Ok(
|
||||||
CommunityFollowerView::for_community(conn, community.id)?
|
CommunityFollowerView::for_community(conn, community.id)?
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -57,6 +59,7 @@ fn get_followers(conn: &PgConnection, community: &Community) -> Result<Vec<Strin
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send out information about a newly created post, to the followers of the community.
|
||||||
pub fn post_create(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
|
pub fn post_create(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
|
||||||
let page = post.as_page(conn)?;
|
let page = post.as_page(conn)?;
|
||||||
let community = Community::read(conn, post.community_id)?;
|
let community = Community::read(conn, post.community_id)?;
|
||||||
|
@ -70,10 +73,11 @@ pub fn post_create(post: &Post, creator: &User_, conn: &PgConnection) -> Result<
|
||||||
.create_props
|
.create_props
|
||||||
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
||||||
.set_object_base_box(page)?;
|
.set_object_base_box(page)?;
|
||||||
send_activity(&create, get_followers(conn, &community)?)?;
|
send_activity(&create, get_follower_inboxes(conn, &community)?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send out information about an edited post, to the followers of the community.
|
||||||
pub fn post_update(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
|
pub fn post_update(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
|
||||||
let page = post.as_page(conn)?;
|
let page = post.as_page(conn)?;
|
||||||
let community = Community::read(conn, post.community_id)?;
|
let community = Community::read(conn, post.community_id)?;
|
||||||
|
@ -87,10 +91,11 @@ pub fn post_update(post: &Post, creator: &User_, conn: &PgConnection) -> Result<
|
||||||
.update_props
|
.update_props
|
||||||
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
||||||
.set_object_base_box(page)?;
|
.set_object_base_box(page)?;
|
||||||
send_activity(&update, get_followers(conn, &community)?)?;
|
send_activity(&update, get_follower_inboxes(conn, &community)?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// As a given local user, send out a follow request to a remote community.
|
||||||
pub fn follow_community(
|
pub fn follow_community(
|
||||||
community: &Community,
|
community: &Community,
|
||||||
user: &User_,
|
user: &User_,
|
||||||
|
@ -111,6 +116,7 @@ pub fn follow_community(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// As a local community, accept the follow request from a remote user.
|
||||||
pub fn accept_follow(follow: &Follow) -> Result<(), Error> {
|
pub fn accept_follow(follow: &Follow) -> Result<(), Error> {
|
||||||
let mut accept = Accept::new();
|
let mut accept = Accept::new();
|
||||||
accept
|
accept
|
||||||
|
|
|
@ -7,7 +7,6 @@ use crate::db::establish_unpooled_connection;
|
||||||
use crate::db::post::Post;
|
use crate::db::post::Post;
|
||||||
use crate::db::user::User_;
|
use crate::db::user::User_;
|
||||||
use crate::db::Crud;
|
use crate::db::Crud;
|
||||||
use crate::settings::Settings;
|
|
||||||
use crate::{convert_datetime, naive_now};
|
use crate::{convert_datetime, naive_now};
|
||||||
use activitystreams::actor::properties::ApActorProperties;
|
use activitystreams::actor::properties::ApActorProperties;
|
||||||
use activitystreams::collection::OrderedCollection;
|
use activitystreams::collection::OrderedCollection;
|
||||||
|
@ -30,30 +29,8 @@ pub struct CommunityQuery {
|
||||||
community_name: String,
|
community_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_apub_community_list(
|
|
||||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
|
||||||
) -> Result<HttpResponse<Body>, Error> {
|
|
||||||
// TODO: implement pagination
|
|
||||||
let communities = Community::list_local(&db.get().unwrap())?
|
|
||||||
.iter()
|
|
||||||
.map(|c| c.as_group(&db.get().unwrap()))
|
|
||||||
.collect::<Result<Vec<GroupExt>, Error>>()?;
|
|
||||||
let mut collection = UnorderedCollection::default();
|
|
||||||
let oprops: &mut ObjectProperties = collection.as_mut();
|
|
||||||
oprops.set_context_xsd_any_uri(context())?.set_id(format!(
|
|
||||||
"{}://{}/federation/communities",
|
|
||||||
get_apub_protocol_string(),
|
|
||||||
Settings::get().hostname
|
|
||||||
))?;
|
|
||||||
|
|
||||||
collection
|
|
||||||
.collection_props
|
|
||||||
.set_total_items(communities.len() as u64)?
|
|
||||||
.set_many_items_base_boxes(communities)?;
|
|
||||||
Ok(create_apub_response(&collection))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Community {
|
impl Community {
|
||||||
|
// Turn a Lemmy Community into an ActivityPub group that can be sent out over the network.
|
||||||
fn as_group(&self, conn: &PgConnection) -> Result<GroupExt, Error> {
|
fn as_group(&self, conn: &PgConnection) -> Result<GroupExt, Error> {
|
||||||
let mut group = Group::default();
|
let mut group = Group::default();
|
||||||
let oprops: &mut ObjectProperties = group.as_mut();
|
let oprops: &mut ObjectProperties = group.as_mut();
|
||||||
|
@ -104,6 +81,7 @@ impl Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommunityForm {
|
impl CommunityForm {
|
||||||
|
/// Parse an ActivityPub group received from another instance into a Lemmy community.
|
||||||
pub fn from_group(group: &GroupExt, conn: &PgConnection) -> Result<Self, Error> {
|
pub fn from_group(group: &GroupExt, conn: &PgConnection) -> Result<Self, Error> {
|
||||||
let oprops = &group.base.base.object_props;
|
let oprops = &group.base.base.object_props;
|
||||||
let aprops = &group.base.extension;
|
let aprops = &group.base.extension;
|
||||||
|
@ -142,6 +120,7 @@ impl CommunityForm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the community json over HTTP.
|
||||||
pub async fn get_apub_community_http(
|
pub async fn get_apub_community_http(
|
||||||
info: Path<CommunityQuery>,
|
info: Path<CommunityQuery>,
|
||||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
@ -151,6 +130,7 @@ pub async fn get_apub_community_http(
|
||||||
Ok(create_apub_response(&c))
|
Ok(create_apub_response(&c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an empty followers collection, only populating the siz (for privacy).
|
||||||
pub async fn get_apub_community_followers(
|
pub async fn get_apub_community_followers(
|
||||||
info: Path<CommunityQuery>,
|
info: Path<CommunityQuery>,
|
||||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
@ -173,6 +153,7 @@ pub async fn get_apub_community_followers(
|
||||||
Ok(create_apub_response(&collection))
|
Ok(create_apub_response(&collection))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an UnorderedCollection with the latest posts from the community.
|
||||||
pub async fn get_apub_community_outbox(
|
pub async fn get_apub_community_outbox(
|
||||||
info: Path<CommunityQuery>,
|
info: Path<CommunityQuery>,
|
||||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub struct Params {
|
||||||
community_name: String,
|
community_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handler for all incoming activities to community inboxes.
|
||||||
pub async fn community_inbox(
|
pub async fn community_inbox(
|
||||||
input: web::Json<CommunityAcceptedObjects>,
|
input: web::Json<CommunityAcceptedObjects>,
|
||||||
params: web::Query<Params>,
|
params: web::Query<Params>,
|
||||||
|
@ -38,6 +39,8 @@ pub async fn community_inbox(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle a follow request from a remote user, adding it to the local database and returning an
|
||||||
|
/// Accept activity.
|
||||||
fn handle_follow(follow: &Follow, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
fn handle_follow(follow: &Follow, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
// TODO: make sure this is a local community
|
// TODO: make sure this is a local community
|
||||||
let community_uri = follow
|
let community_uri = follow
|
||||||
|
|
|
@ -20,6 +20,7 @@ use serde::Deserialize;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
// Fetch nodeinfo metadata from a remote instance.
|
||||||
fn _fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
|
fn _fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
|
||||||
let well_known_uri = Url::parse(&format!(
|
let well_known_uri = Url::parse(&format!(
|
||||||
"{}://{}/.well-known/nodeinfo",
|
"{}://{}/.well-known/nodeinfo",
|
||||||
|
@ -60,7 +61,9 @@ fn upsert_post(post_form: &PostForm, conn: &PgConnection) -> Result<Post, Error>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add an optional param last_updated and only fetch if its too old
|
/// Fetch any type of ActivityPub object, handling things like HTTP headers, deserialisation,
|
||||||
|
/// timeouts etc.
|
||||||
|
/// TODO: add an optional param last_updated and only fetch if its too old
|
||||||
pub fn fetch_remote_object<Response>(url: &Url) -> Result<Response, Error>
|
pub fn fetch_remote_object<Response>(url: &Url) -> Result<Response, Error>
|
||||||
where
|
where
|
||||||
Response: for<'de> Deserialize<'de>,
|
Response: for<'de> Deserialize<'de>,
|
||||||
|
@ -81,6 +84,7 @@ where
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The types of ActivityPub objects that can be fetched directly by searching for their ID.
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub enum SearchAcceptedObjects {
|
pub enum SearchAcceptedObjects {
|
||||||
|
@ -89,6 +93,12 @@ pub enum SearchAcceptedObjects {
|
||||||
Page(Box<Page>),
|
Page(Box<Page>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempt to parse the query as URL, and fetch an ActivityPub object from it.
|
||||||
|
///
|
||||||
|
/// Some working examples for use with the docker/federation/ setup:
|
||||||
|
/// http://lemmy_alpha:8540/federation/c/main
|
||||||
|
/// http://lemmy_alpha:8540/federation/u/lemmy_alpha
|
||||||
|
/// http://lemmy_alpha:8540/federation/p/3
|
||||||
pub fn search_by_apub_id(query: &str, conn: &PgConnection) -> Result<SearchResponse, Error> {
|
pub fn search_by_apub_id(query: &str, conn: &PgConnection) -> Result<SearchResponse, Error> {
|
||||||
let query_url = Url::parse(&query)?;
|
let query_url = Url::parse(&query)?;
|
||||||
let mut response = SearchResponse {
|
let mut response = SearchResponse {
|
||||||
|
@ -98,10 +108,6 @@ pub fn search_by_apub_id(query: &str, conn: &PgConnection) -> Result<SearchRespo
|
||||||
communities: vec![],
|
communities: vec![],
|
||||||
users: vec![],
|
users: vec![],
|
||||||
};
|
};
|
||||||
// test with:
|
|
||||||
// http://lemmy_alpha:8540/federation/c/main
|
|
||||||
// http://lemmy_alpha:8540/federation/u/lemmy_alpha
|
|
||||||
// http://lemmy_alpha:8540/federation/p/3
|
|
||||||
match fetch_remote_object::<SearchAcceptedObjects>(&query_url)? {
|
match fetch_remote_object::<SearchAcceptedObjects>(&query_url)? {
|
||||||
SearchAcceptedObjects::Person(p) => {
|
SearchAcceptedObjects::Person(p) => {
|
||||||
let u = upsert_user(&UserForm::from_person(&p)?, conn)?;
|
let u = upsert_user(&UserForm::from_person(&p)?, conn)?;
|
||||||
|
@ -120,6 +126,7 @@ pub fn search_by_apub_id(query: &str, conn: &PgConnection) -> Result<SearchRespo
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetch all posts in the outbox of the given user, and insert them into the database.
|
||||||
fn fetch_community_outbox(community: &Community, conn: &PgConnection) -> Result<Vec<Post>, Error> {
|
fn fetch_community_outbox(community: &Community, conn: &PgConnection) -> Result<Vec<Post>, Error> {
|
||||||
let outbox_url = Url::parse(&community.get_outbox_url())?;
|
let outbox_url = Url::parse(&community.get_outbox_url())?;
|
||||||
let outbox = fetch_remote_object::<OrderedCollection>(&outbox_url)?;
|
let outbox = fetch_remote_object::<OrderedCollection>(&outbox_url)?;
|
||||||
|
@ -137,12 +144,14 @@ fn fetch_community_outbox(community: &Community, conn: &PgConnection) -> Result<
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetch a user, insert/update it in the database and return the user.
|
||||||
pub fn fetch_remote_user(apub_id: &Url, conn: &PgConnection) -> Result<User_, Error> {
|
pub fn fetch_remote_user(apub_id: &Url, conn: &PgConnection) -> Result<User_, Error> {
|
||||||
let person = fetch_remote_object::<PersonExt>(apub_id)?;
|
let person = fetch_remote_object::<PersonExt>(apub_id)?;
|
||||||
let uf = UserForm::from_person(&person)?;
|
let uf = UserForm::from_person(&person)?;
|
||||||
upsert_user(&uf, conn)
|
upsert_user(&uf, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetch a community, insert/update it in the database and return the community.
|
||||||
pub fn fetch_remote_community(apub_id: &Url, conn: &PgConnection) -> Result<Community, Error> {
|
pub fn fetch_remote_community(apub_id: &Url, conn: &PgConnection) -> Result<Community, Error> {
|
||||||
let group = fetch_remote_object::<GroupExt>(apub_id)?;
|
let group = fetch_remote_object::<GroupExt>(apub_id)?;
|
||||||
let cf = CommunityForm::from_group(&group, conn)?;
|
let cf = CommunityForm::from_group(&group, conn)?;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use activitystreams::ext::Ext;
|
||||||
use actix_web::body::Body;
|
use actix_web::body::Body;
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
use openssl::{pkey::PKey, rsa::Rsa};
|
use openssl::{pkey::PKey, rsa::Rsa};
|
||||||
|
use serde::ser::Serialize;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
type GroupExt = Ext<Ext<Group, ApActorProperties>, PublicKeyExtension>;
|
type GroupExt = Ext<Ext<Group, ApActorProperties>, PublicKeyExtension>;
|
||||||
|
@ -27,18 +28,22 @@ pub enum EndpointType {
|
||||||
Comment,
|
Comment,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_apub_response<T>(json: &T) -> HttpResponse<Body>
|
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
|
||||||
|
/// headers.
|
||||||
|
fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
|
||||||
where
|
where
|
||||||
T: serde::ser::Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.content_type(APUB_JSON_CONTENT_TYPE)
|
.content_type(APUB_JSON_CONTENT_TYPE)
|
||||||
.json(json)
|
.json(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we will probably need to change apub endpoint urls so that html and activity+json content
|
/// Generates the ActivityPub ID for a given object type and name.
|
||||||
// types are handled at the same endpoint, so that you can copy the url into mastodon search
|
///
|
||||||
// and have it fetch the object.
|
/// TODO: we will probably need to change apub endpoint urls so that html and activity+json content
|
||||||
|
/// types are handled at the same endpoint, so that you can copy the url into mastodon search
|
||||||
|
/// and have it fetch the object.
|
||||||
pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
|
pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
|
||||||
let point = match endpoint_type {
|
let point = match endpoint_type {
|
||||||
EndpointType::Community => "c",
|
EndpointType::Community => "c",
|
||||||
|
@ -67,21 +72,16 @@ pub fn get_apub_protocol_string() -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_keypair() -> (Vec<u8>, Vec<u8>) {
|
/// Generate the asymmetric keypair for ActivityPub HTTP signatures.
|
||||||
|
pub fn gen_keypair_str() -> (String, String) {
|
||||||
let rsa = Rsa::generate(2048).expect("sign::gen_keypair: key generation error");
|
let rsa = Rsa::generate(2048).expect("sign::gen_keypair: key generation error");
|
||||||
let pkey = PKey::from_rsa(rsa).expect("sign::gen_keypair: parsing error");
|
let pkey = PKey::from_rsa(rsa).expect("sign::gen_keypair: parsing error");
|
||||||
(
|
let public_key = pkey
|
||||||
pkey
|
.public_key_to_pem()
|
||||||
.public_key_to_pem()
|
.expect("sign::gen_keypair: public key encoding error");
|
||||||
.expect("sign::gen_keypair: public key encoding error"),
|
let private_key = pkey
|
||||||
pkey
|
.private_key_to_pem_pkcs8()
|
||||||
.private_key_to_pem_pkcs8()
|
.expect("sign::gen_keypair: private key encoding error");
|
||||||
.expect("sign::gen_keypair: private key encoding error"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gen_keypair_str() -> (String, String) {
|
|
||||||
let (public_key, private_key) = gen_keypair();
|
|
||||||
(vec_bytes_to_str(public_key), vec_bytes_to_str(private_key))
|
(vec_bytes_to_str(public_key), vec_bytes_to_str(private_key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub struct PostQuery {
|
||||||
post_id: String,
|
post_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the post json over HTTP.
|
||||||
pub async fn get_apub_post(
|
pub async fn get_apub_post(
|
||||||
info: Path<PostQuery>,
|
info: Path<PostQuery>,
|
||||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
@ -30,6 +31,7 @@ pub async fn get_apub_post(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Post {
|
impl Post {
|
||||||
|
// Turn a Lemmy post into an ActivityPub page that can be sent out over the network.
|
||||||
pub fn as_page(&self, conn: &PgConnection) -> Result<Page, Error> {
|
pub fn as_page(&self, conn: &PgConnection) -> Result<Page, Error> {
|
||||||
let mut page = Page::default();
|
let mut page = Page::default();
|
||||||
let oprops: &mut ObjectProperties = page.as_mut();
|
let oprops: &mut ObjectProperties = page.as_mut();
|
||||||
|
@ -67,6 +69,7 @@ impl Post {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PostForm {
|
impl PostForm {
|
||||||
|
/// Parse an ActivityPub page received from another instance into a Lemmy post.
|
||||||
pub fn from_page(page: &Page, conn: &PgConnection) -> Result<PostForm, Error> {
|
pub fn from_page(page: &Page, conn: &PgConnection) -> Result<PostForm, Error> {
|
||||||
let oprops = &page.object_props;
|
let oprops = &page.object_props;
|
||||||
let creator_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
|
let creator_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
// For this example, we'll use the Extensible trait, the Extension trait, the Actor trait, and
|
// For this example, we'll use the Extensible trait, the Extension trait, the Actor trait, and
|
||||||
// the Person type
|
// the Person type
|
||||||
use activitystreams::{actor::Actor, ext::Extension};
|
use activitystreams::{actor::Actor, ext::Extension};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// The following is taken from here:
|
// The following is taken from here:
|
||||||
// https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html
|
// https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PublicKey {
|
pub struct PublicKey {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
@ -13,7 +14,7 @@ pub struct PublicKey {
|
||||||
pub public_key_pem: String,
|
pub public_key_pem: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PublicKeyExtension {
|
pub struct PublicKeyExtension {
|
||||||
pub public_key: PublicKey,
|
pub public_key: PublicKey,
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub struct UserQuery {
|
||||||
user_name: String,
|
user_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn a Lemmy user into an ActivityPub person and return it as json.
|
||||||
pub async fn get_apub_user(
|
pub async fn get_apub_user(
|
||||||
info: Path<UserQuery>,
|
info: Path<UserQuery>,
|
||||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
@ -64,6 +65,7 @@ pub async fn get_apub_user(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserForm {
|
impl UserForm {
|
||||||
|
/// Parse an ActivityPub person received from another instance into a Lemmy user.
|
||||||
pub fn from_person(person: &PersonExt) -> Result<Self, Error> {
|
pub fn from_person(person: &PersonExt) -> Result<Self, Error> {
|
||||||
let oprops = &person.base.base.object_props;
|
let oprops = &person.base.base.object_props;
|
||||||
let aprops = &person.base.extension;
|
let aprops = &person.base.extension;
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub struct Params {
|
||||||
user_name: String,
|
user_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handler for all incoming activities to user inboxes.
|
||||||
pub async fn user_inbox(
|
pub async fn user_inbox(
|
||||||
input: web::Json<UserAcceptedObjects>,
|
input: web::Json<UserAcceptedObjects>,
|
||||||
params: web::Query<Params>,
|
params: web::Query<Params>,
|
||||||
|
@ -38,6 +39,7 @@ pub async fn user_inbox(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle create activities and insert them in the database.
|
||||||
fn handle_create(create: &Create, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
fn handle_create(create: &Create, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
let page = create
|
let page = create
|
||||||
.create_props
|
.create_props
|
||||||
|
@ -52,6 +54,7 @@ fn handle_create(create: &Create, conn: &PgConnection) -> Result<HttpResponse, E
|
||||||
Ok(HttpResponse::Ok().finish())
|
Ok(HttpResponse::Ok().finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle update activities and insert them in the database.
|
||||||
fn handle_update(update: &Update, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
fn handle_update(update: &Update, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
let page = update
|
let page = update
|
||||||
.update_props
|
.update_props
|
||||||
|
@ -67,6 +70,7 @@ fn handle_update(update: &Update, conn: &PgConnection) -> Result<HttpResponse, E
|
||||||
Ok(HttpResponse::Ok().finish())
|
Ok(HttpResponse::Ok().finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle accepted follows.
|
||||||
fn handle_accept(_accept: &Accept, _conn: &PgConnection) -> Result<HttpResponse, Error> {
|
fn handle_accept(_accept: &Accept, _conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
// TODO: make sure that we actually requested a follow
|
// TODO: make sure that we actually requested a follow
|
||||||
// TODO: at this point, indicate to the user that they are following the community
|
// TODO: at this point, indicate to the user that they are following the community
|
||||||
|
|
Loading…
Reference in a new issue