diff --git a/Cargo.lock b/Cargo.lock index 02988cfb..50c8e560 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -949,6 +949,8 @@ name = "plume" version = "0.1.0" dependencies = [ "activitypub 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "activitystreams-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "activitystreams-traits 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "array_tool 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 957e6938..12a68255 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ name = "plume" version = "0.1.0" [dependencies] activitypub = "0.1.1" +activitystreams-derive = "0.1.0" +activitystreams-traits = "0.1.0" ammonia = "1.1.0" array_tool = "1.0" base64 = "0.9" @@ -18,7 +20,6 @@ hex = "0.3" hyper = "*" lazy_static = "*" openssl = "0.10.6" -pulldown-cmark = { version = "0.1.2", default-features = false } reqwest = "0.8" rpassword = "2.0" serde = "*" @@ -36,6 +37,10 @@ version = "0.4" features = ["postgres", "r2d2", "chrono"] version = "*" +[dependencies.pulldown-cmark] +default-features = false +version = "0.1.2" + [dependencies.rocket] git = "https://github.com/SergioBenitez/Rocket" rev = "df7111143e466c18d1f56377a8d9530a5a306aba" diff --git a/src/activity_pub/mod.rs b/src/activity_pub/mod.rs index b7eb6155..87fb5798 100644 --- a/src/activity_pub/mod.rs +++ b/src/activity_pub/mod.rs @@ -115,3 +115,27 @@ pub trait IntoId { } impl Link for Id {} + +#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)] +#[serde(rename_all = "camelCase")] +pub struct ApSignature { + #[serde(skip_serializing_if = "Option::is_none")] + #[activitystreams(concrete(PublicKey), functional)] + pub public_key: Option +} + +#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)] +#[serde(rename_all = "camelCase")] +pub struct PublicKey { + #[serde(skip_serializing_if = "Option::is_none")] + #[activitystreams(concrete(String), functional)] + pub id: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[activitystreams(concrete(String), functional)] + pub owner: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[activitystreams(concrete(String), functional)] + pub public_key_pem: Option +} diff --git a/src/main.rs b/src/main.rs index 3a42db26..85b4584e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,9 @@ #![plugin(rocket_codegen)] extern crate activitypub; +#[macro_use] +extern crate activitystreams_derive; +extern crate activitystreams_traits; extern crate ammonia; extern crate array_tool; extern crate base64; diff --git a/src/models/users.rs b/src/models/users.rs index 3cbf1df6..538cc868 100644 --- a/src/models/users.rs +++ b/src/models/users.rs @@ -1,5 +1,5 @@ use activitypub::{ - Actor, Object, Endpoint, + Actor, Object, Endpoint, CustomObject, actor::Person, collection::OrderedCollection }; @@ -27,7 +27,7 @@ use webfinger::*; use BASE_URL; use activity_pub::{ - ap_url, ActivityStream, Id, IntoId, + ap_url, ActivityStream, Id, IntoId, ApSignature, inbox::{Inbox, WithInbox}, sign::{Signer, gen_keypair} }; @@ -45,6 +45,8 @@ use safe_string::SafeString; pub const AUTH_COOKIE: &'static str = "user_id"; +pub type CustomPerson = CustomObject; + #[derive(Queryable, Identifiable, Serialize, Deserialize, Clone, Debug)] pub struct User { pub id: i32, @@ -157,14 +159,14 @@ impl User { .send(); match req { Ok(mut res) => { - let json: serde_json::Value = serde_json::from_str(&res.text().unwrap()).unwrap(); + let json: CustomPerson = serde_json::from_str(&res.text().unwrap()).unwrap(); Some(User::from_activity(conn, json, Url::parse(url.as_ref()).unwrap().host_str().unwrap().to_string())) }, Err(_) => None } } - fn from_activity(conn: &PgConnection, acct: serde_json::Value, inst: String) -> User { + fn from_activity(conn: &PgConnection, acct: CustomPerson, inst: String) -> User { let instance = match Instance::find_by_domain(conn, inst.clone()) { Some(instance) => instance, None => { @@ -176,19 +178,21 @@ impl User { } }; User::insert(conn, NewUser { - username: acct["preferredUsername"].as_str().unwrap().to_string(), - display_name: acct["name"].as_str().unwrap().to_string(), - outbox_url: acct["outbox"].as_str().unwrap().to_string(), - inbox_url: acct["inbox"].as_str().unwrap().to_string(), + username: acct.object.ap_actor_props.preferred_username_string().expect("User::from_activity: preferredUsername error"), + display_name: acct.object.object_props.name_string().expect("User::from_activity: name error"), + outbox_url: acct.object.ap_actor_props.outbox_string().expect("User::from_activity: outbox error"), + inbox_url: acct.object.ap_actor_props.inbox_string().expect("User::from_activity: inbox error"), is_admin: false, - summary: SafeString::new(&acct["summary"].as_str().unwrap().to_string()), + summary: SafeString::new(&acct.object.object_props.summary_string().expect("User::from_activity: summary error")), email: None, hashed_password: None, instance_id: instance.id, - ap_url: acct["id"].as_str().unwrap().to_string(), - public_key: acct["publicKey"]["publicKeyPem"].as_str().unwrap().to_string(), + ap_url: acct.object.object_props.id_string().expect("User::from_activity: id error"), + public_key: acct.custom_props.public_key_publickey().expect("User::from_activity: publicKey error") + .public_key_pem_string().expect("User::from_activity: publicKey.publicKeyPem error"), private_key: None, - shared_inbox_url: acct["endpoints"]["sharedInbox"].as_str().map(|s| s.to_string()) + shared_inbox_url: acct.object.ap_actor_props.endpoints_endpoint() + .and_then(|e| e.shared_inbox_string()).ok() }) }