3 pub mod community_inbox;
10 use activitystreams::{
11 activity::{Accept, Create, Follow, Update},
12 actor::{properties::ApActorProperties, Actor, Group, Person},
13 collection::UnorderedCollection,
15 ext::{Ext, Extensible, Extension},
16 object::{properties::ObjectProperties, Page},
19 use actix_web::body::Body;
20 use actix_web::web::Path;
21 use actix_web::{web, HttpRequest, HttpResponse, Result};
22 use diesel::result::Error::NotFound;
23 use diesel::PgConnection;
25 use failure::_core::fmt::Debug;
26 use http::request::Builder;
27 use http_signature_normalization::Config;
28 use isahc::prelude::*;
30 use openssl::hash::MessageDigest;
31 use openssl::sign::{Signer, Verifier};
32 use openssl::{pkey::PKey, rsa::Rsa};
33 use serde::{Deserialize, Serialize};
34 use std::collections::BTreeMap;
35 use std::time::Duration;
38 use crate::api::site::SearchResponse;
39 use crate::db::community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm};
40 use crate::db::community_view::{CommunityFollowerView, CommunityView};
41 use crate::db::post::{Post, PostForm};
42 use crate::db::post_view::PostView;
43 use crate::db::user::{UserForm, User_};
44 use crate::db::user_view::UserView;
45 use crate::db::{Crud, Followable, SearchType};
46 use crate::routes::nodeinfo::{NodeInfo, NodeInfoWellKnown};
47 use crate::routes::{ChatServerParam, DbPoolParam};
48 use crate::{convert_datetime, naive_now, Settings};
50 use activities::accept_follow;
51 use fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user};
52 use signatures::verify;
53 use signatures::{sign, PublicKey, PublicKeyExtension};
55 type GroupExt = Ext<Ext<Group, ApActorProperties>, PublicKeyExtension>;
56 type PersonExt = Ext<Ext<Person, ApActorProperties>, PublicKeyExtension>;
58 pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
60 pub enum EndpointType {
67 /// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
69 fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
74 .content_type(APUB_JSON_CONTENT_TYPE)
78 /// Generates the ActivityPub ID for a given object type and name.
80 /// TODO: we will probably need to change apub endpoint urls so that html and activity+json content
81 /// types are handled at the same endpoint, so that you can copy the url into mastodon search
82 /// and have it fetch the object.
83 pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
84 let point = match endpoint_type {
85 EndpointType::Community => "c",
86 EndpointType::User => "u",
87 EndpointType::Post => "post",
88 // TODO I have to change this else my update advanced_migrations crashes the
89 // server if a comment exists.
90 EndpointType::Comment => "comment",
95 get_apub_protocol_string(),
96 Settings::get().hostname,
103 pub fn get_apub_protocol_string() -> &'static str {
104 if Settings::get().federation.tls_enabled {
111 // Checks if the ID has a valid format, correct scheme, and is in the whitelist.
112 fn is_apub_id_valid(apub_id: &Url) -> bool {
113 if apub_id.scheme() != get_apub_protocol_string() {
117 let whitelist: Vec<String> = Settings::get()
121 .map(|d| d.to_string())
123 match apub_id.domain() {
124 Some(d) => whitelist.contains(&d.to_owned()),
129 // TODO Not sure good names for these
132 fn to_apub(&self, conn: &PgConnection) -> Result<Self::Response, Error>;
137 fn from_apub(apub: &Self::ApubType, conn: &PgConnection) -> Result<Self, Error>
142 pub trait ActorType {
143 fn actor_id(&self) -> String;
145 fn public_key(&self) -> String;
147 fn get_inbox_url(&self) -> String {
148 format!("{}/inbox", &self.actor_id())
150 fn get_outbox_url(&self) -> String {
151 format!("{}/outbox", &self.actor_id())
154 fn get_followers_url(&self) -> String {
155 format!("{}/followers", &self.actor_id())
157 fn get_following_url(&self) -> String {
158 format!("{}/following", &self.actor_id())
160 fn get_liked_url(&self) -> String {
161 format!("{}/liked", &self.actor_id())
164 fn get_public_key_ext(&self) -> PublicKeyExtension {
166 id: format!("{}#main-key", self.actor_id()),
167 owner: self.actor_id(),
168 public_key_pem: self.public_key(),