@@ -1,9 +1,11 @@
|
||||
use diesel::PgConnection;
|
||||
use reqwest::Client;
|
||||
use serde_json;
|
||||
|
||||
use BASE_URL;
|
||||
use activity_pub::{activity_pub, ActivityPub, context, ap_url};
|
||||
use activity_pub::activity::Activity;
|
||||
use activity_pub::sign::*;
|
||||
use models::instance::Instance;
|
||||
|
||||
pub enum ActorType {
|
||||
@@ -33,8 +35,12 @@ pub trait Actor: Sized {
|
||||
|
||||
fn get_actor_type() -> ActorType;
|
||||
|
||||
fn custom_props(&self, _conn: &PgConnection) -> serde_json::Map<String, serde_json::Value> {
|
||||
serde_json::Map::new()
|
||||
}
|
||||
|
||||
fn as_activity_pub (&self, conn: &PgConnection) -> ActivityPub {
|
||||
activity_pub(json!({
|
||||
let mut repr = json!({
|
||||
"@context": context(),
|
||||
"id": self.compute_id(conn),
|
||||
"type": Self::get_actor_type().to_string(),
|
||||
@@ -47,7 +53,11 @@ pub trait Actor: Sized {
|
||||
"endpoints": {
|
||||
"sharedInbox": ap_url(format!("{}/inbox", BASE_URL.as_str()))
|
||||
}
|
||||
}))
|
||||
});
|
||||
|
||||
self.custom_props(conn).iter().for_each(|p| repr[p.0] = p.1.clone());
|
||||
|
||||
activity_pub(repr)
|
||||
}
|
||||
|
||||
fn compute_outbox(&self, conn: &PgConnection) -> String {
|
||||
@@ -71,10 +81,12 @@ pub trait Actor: Sized {
|
||||
))
|
||||
}
|
||||
|
||||
fn send_to_inbox<A: Activity>(&self, conn: &PgConnection, act: A) {
|
||||
fn send_to_inbox<A: Activity, S: Actor + Signer>(&self, conn: &PgConnection, sender: &S, act: A) {
|
||||
let mut act = act.serialize();
|
||||
let signed = act.sign(sender, conn);
|
||||
let res = Client::new()
|
||||
.post(&self.compute_inbox(conn)[..])
|
||||
.body(act.serialize().to_string())
|
||||
.body(signed.to_string())
|
||||
.send();
|
||||
match res {
|
||||
Ok(_) => println!("Successfully sent activity to inbox"),
|
||||
|
||||
@@ -3,6 +3,7 @@ use serde_json;
|
||||
|
||||
use activity_pub::activity;
|
||||
use activity_pub::actor::Actor;
|
||||
use activity_pub::sign::*;
|
||||
use models::blogs::Blog;
|
||||
use models::follows::{Follow, NewFollow};
|
||||
use models::posts::{Post, NewPost};
|
||||
@@ -45,13 +46,21 @@ pub trait Inbox: Actor + Sized {
|
||||
}
|
||||
}
|
||||
|
||||
fn accept_follow<A: Actor, B: Actor, T: activity::Activity>(&self, conn: &PgConnection, from: &A, target: &B, follow: &T, from_id: i32, target_id: i32) {
|
||||
fn accept_follow<A: Actor, B: Actor + Signer, T: activity::Activity>(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
from: &A,
|
||||
target: &B,
|
||||
follow: &T,
|
||||
from_id: i32,
|
||||
target_id: i32
|
||||
) {
|
||||
Follow::insert(conn, NewFollow {
|
||||
follower_id: from_id,
|
||||
following_id: target_id
|
||||
});
|
||||
|
||||
let accept = activity::Accept::new(target, follow, conn);
|
||||
from.send_to_inbox(conn, accept)
|
||||
from.send_to_inbox(conn, target, accept)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::sync::Arc;
|
||||
use activity_pub::{activity_pub, ActivityPub, context};
|
||||
use activity_pub::activity::Activity;
|
||||
use activity_pub::actor::Actor;
|
||||
use activity_pub::sign::Signer;
|
||||
use models::users::User;
|
||||
|
||||
pub struct Outbox {
|
||||
@@ -41,8 +42,8 @@ impl<'r> Responder<'r> for Outbox {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn broadcast<A: Activity + Clone>(conn: &PgConnection, act: A, to: Vec<User>) {
|
||||
pub fn broadcast<A: Activity + Clone, S: Actor + Signer>(conn: &PgConnection, sender: &S, act: A, to: Vec<User>) {
|
||||
for user in to {
|
||||
user.send_to_inbox(conn, act.clone()); // TODO: run it in Sidekiq or something like that
|
||||
user.send_to_inbox(conn, sender, act.clone()); // TODO: run it in Sidekiq or something like that
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,18 @@ use base64;
|
||||
use diesel::PgConnection;
|
||||
use hex;
|
||||
use chrono::Utc;
|
||||
use openssl::pkey::PKey;
|
||||
use openssl::rsa::Rsa;
|
||||
use openssl::sha::sha256;
|
||||
use serde_json;
|
||||
|
||||
/// Returns (public key, private key)
|
||||
pub fn gen_keypair() -> (Vec<u8>, Vec<u8>) {
|
||||
let keypair = Rsa::generate(2048).unwrap();
|
||||
let keypair = PKey::from_rsa(keypair).unwrap();
|
||||
(keypair.public_key_to_pem().unwrap(), keypair.private_key_to_pem_pkcs8().unwrap())
|
||||
}
|
||||
|
||||
pub trait Signer {
|
||||
fn get_key_id(&self, conn: &PgConnection) -> String;
|
||||
|
||||
@@ -13,7 +22,7 @@ pub trait Signer {
|
||||
}
|
||||
|
||||
pub trait Signable {
|
||||
fn sign<T>(&mut self, creator: T, conn: &PgConnection) -> &mut Self where T: Signer;
|
||||
fn sign<T>(&mut self, creator: &T, conn: &PgConnection) -> &mut Self where T: Signer;
|
||||
|
||||
fn hash(data: String) -> String {
|
||||
let bytes = data.into_bytes();
|
||||
@@ -22,7 +31,7 @@ pub trait Signable {
|
||||
}
|
||||
|
||||
impl Signable for serde_json::Value {
|
||||
fn sign<T: Signer>(&mut self, creator: T, conn: &PgConnection) -> &mut serde_json::Value {
|
||||
fn sign<T: Signer>(&mut self, creator: &T, conn: &PgConnection) -> &mut serde_json::Value {
|
||||
let creation_date = Utc::now().to_rfc3339();
|
||||
let mut options = json!({
|
||||
"type": "RsaSignature2017",
|
||||
|
||||
Reference in New Issue
Block a user