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::user::{UserForm, User_};
43 use crate::db::user_view::UserView;
44 use crate::db::{Crud, Followable, SearchType};
45 use crate::routes::nodeinfo::{NodeInfo, NodeInfoWellKnown};
46 use crate::routes::{ChatServerParam, DbPoolParam};
47 use crate::{convert_datetime, naive_now, Settings};
49 use activities::accept_follow;
50 use fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user};
51 use signatures::verify;
52 use signatures::{sign, PublicKey, PublicKeyExtension};
54 type GroupExt = Ext<Ext<Group, ApActorProperties>, PublicKeyExtension>;
55 type PersonExt = Ext<Ext<Person, ApActorProperties>, PublicKeyExtension>;
57 pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
59 pub enum EndpointType {
66 /// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
68 fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
73 .content_type(APUB_JSON_CONTENT_TYPE)
77 /// Generates the ActivityPub ID for a given object type and name.
79 /// TODO: we will probably need to change apub endpoint urls so that html and activity+json content
80 /// types are handled at the same endpoint, so that you can copy the url into mastodon search
81 /// and have it fetch the object.
82 pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
83 let point = match endpoint_type {
84 EndpointType::Community => "c",
85 EndpointType::User => "u",
86 EndpointType::Post => "post",
87 // TODO I have to change this else my update advanced_migrations crashes the
88 // server if a comment exists.
89 EndpointType::Comment => "comment",
94 get_apub_protocol_string(),
95 Settings::get().hostname,
102 pub fn get_apub_protocol_string() -> &'static str {
103 if Settings::get().federation.tls_enabled {
110 // Checks if the ID has a valid format, correct scheme, and is in the whitelist.
111 fn is_apub_id_valid(apub_id: &Url) -> bool {
112 if apub_id.scheme() != get_apub_protocol_string() {
116 let whitelist: Vec<String> = Settings::get()
120 .map(|d| d.to_string())
122 match apub_id.domain() {
123 Some(d) => whitelist.contains(&d.to_owned()),
128 // TODO Not sure good names for these
131 fn to_apub(&self, conn: &PgConnection) -> Result<Self::Response, Error>;
136 fn from_apub(apub: &Self::ApubType, conn: &PgConnection) -> Result<Self, Error>
141 pub trait ActorType {
142 fn actor_id(&self) -> String;
144 fn public_key(&self) -> String;
146 fn get_inbox_url(&self) -> String {
147 format!("{}/inbox", &self.actor_id())
149 fn get_outbox_url(&self) -> String {
150 format!("{}/outbox", &self.actor_id())
153 fn get_followers_url(&self) -> String {
154 format!("{}/followers", &self.actor_id())
156 fn get_following_url(&self) -> String {
157 format!("{}/following", &self.actor_id())
159 fn get_liked_url(&self) -> String {
160 format!("{}/liked", &self.actor_id())
163 fn get_public_key_ext(&self) -> PublicKeyExtension {
165 id: format!("{}#main-key", self.actor_id()),
166 owner: self.actor_id(),
167 public_key_pem: self.public_key(),