Skip to content

Commit

Permalink
Adding dmain serving daemon
Browse files Browse the repository at this point in the history
Signed-off-by: Till Wegmueller <[email protected]>
  • Loading branch information
Toasterson committed Jul 24, 2023
1 parent 6a214e1 commit 4d31e7a
Show file tree
Hide file tree
Showing 15 changed files with 1,073 additions and 82 deletions.
357 changes: 337 additions & 20 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ tower = { version = "0.4.13", features = ["full", "tokio"] }
reqwest = "0.11.18"
hyper = { version = "0.14.26", features = ["full"] }
tower-http = { version = "0.4.1", features = ["tracing", "trace"] }
activitypub_federation = { version = "0.4.6", default-features = false, features = ["axum"] }
activitypub = {version ="0.1.0-dev", path = "crates/activitypub"}

[profile.dev.package.num-bigint-dig]
opt-level = 3
opt-level = 3
9 changes: 9 additions & 0 deletions crates/activitypub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,12 @@ license.workspace = true
categories.workspace = true

[dependencies]
miette.workspace = true
thiserror.workspace = true
serde.workspace = true
serde_json.workspace = true
axum.workspace = true
url.workspace = true
chrono.workspace = true
activitypub_federation.workspace = true
serde_with = { version = "3.1.0", features = ["json", "chrono"] }
15 changes: 15 additions & 0 deletions crates/activitypub/src/activities.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::*;

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Activity {
Create {
context: Context,
id: Url,
actor: Url,
published: chrono::NaiveDateTime,
to: Vec<Url>,
cc: Vec<Url>,
object: Object,
},
}
224 changes: 215 additions & 9 deletions crates/activitypub/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,220 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
pub mod activities;

use activitypub_federation::protocol::{
helpers::{deserialize_one_or_many, deserialize_skip_error},
values::{MediaTypeMarkdown, MediaTypeMarkdownOrHtml},
};
use chrono::{DateTime, FixedOffset};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_with::skip_serializing_none;
use url::Url;

/// Public key of actors which is used for HTTP signatures.
///
/// This needs to be federated in the `public_key` field of all actors.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PublicKey {
/// Id of this private key.
pub id: String,
/// ID of the actor that this public key belongs to
pub owner: Url,
/// The actual public key in PEM format
pub public_key_pem: String,
}

impl PublicKey {
/// Create a new [PublicKey] struct for the `owner` with `public_key_pem`.
///
/// It uses an standard key id of `{actor_id}#main-key`
pub fn new(owner: Url, public_key_pem: String) -> Self {
let id = main_key_id(&owner);
PublicKey {
id,
owner,
public_key_pem,
}
}
}

pub fn main_key_id(owner: &Url) -> String {
format!("{}#main-key", &owner)
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Context {
Single(KnownContext),
List(Vec<KnownContext>),
}

#[derive(Debug, Serialize, Deserialize)]
pub enum KnownContext {
#[serde(rename = "https://www.w3.org/ns/activitystreams")]
ActivityStreams,
#[serde(rename = "https://w3id.org/security/v1")]
SecurityV1,
#[serde(rename = "@language")]
Language(String),
}

#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Object {
Person(Person),
Note(Note),
Article(Article),
Document(Document),
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Source {
pub content: String,
pub media_type: MediaTypeMarkdown,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ImageObject {
pub url: Url,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Endpoints {
pub shared_inbox: Url,
}

#[skip_serializing_none]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Person {
pub id: Url,
pub preferred_username: String,
pub public_key: PublicKey,

/// displayname
pub name: Option<String>,
pub summary: Option<String>,
#[serde(deserialize_with = "deserialize_skip_error", default)]
pub source: Option<Source>,
/// user avatar
pub icon: Option<ImageObject>,
/// user banner
pub image: Option<ImageObject>,
pub matrix_user_id: Option<String>,
pub endpoints: Option<Endpoints>,
pub published: Option<DateTime<FixedOffset>>,
pub updated: Option<DateTime<FixedOffset>>,
}

#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum MentionOrValue {
Mention(Mention),
Value(Value),
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Mention {
pub href: Url,
name: Option<String>,
}

/// As specified in https://schema.org/Language
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LanguageTag {
pub identifier: String,
pub name: String,
}

#[skip_serializing_none]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Note {
pub id: Url,
pub attributed_to: Url,
#[serde(deserialize_with = "deserialize_one_or_many")]
pub to: Vec<Url>,
#[serde(deserialize_with = "deserialize_one_or_many", default)]
pub cc: Vec<Url>,
pub content: String,
pub in_reply_to: Url,

pub media_type: Option<MediaTypeMarkdownOrHtml>,
#[serde(deserialize_with = "deserialize_skip_error", default)]
pub source: Option<Source>,
pub published: Option<DateTime<FixedOffset>>,
pub updated: Option<DateTime<FixedOffset>>,
#[serde(default)]
pub tag: Vec<MentionOrValue>,
// lemmy extension
pub distinguished: Option<bool>,
pub language: Option<LanguageTag>,
pub audience: Option<Url>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Article {
pub id: Url,
pub attributed_to: Url,
pub content: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Document {
pub id: Url,
pub name: String,
pub url: Url,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Actors {
Person(PersonActor),
}

pub const ACTOR_ID_FORMAT: &str = "{}/actors/{}";
pub const ACTOR_PROFILE_URL: &str = "{}/@{}";
pub const ACTOR_INBOX_FORMAT: &str = "{}/actors/{}/inbox";
pub const ACTOR_OUTBOX_FORMAT: &str = "{}/actors/{}/outbox";
pub const SHARED_INBOX_FORMAT: &str = "{}/inbox";

#[derive(Debug, Serialize, Deserialize)]
pub struct PersonActor {
pub id: Url,
pub inbox: Url,
pub outbox: Url,
pub endpoints: Vec<Endpoint>,
pub preferred_username: String,
pub public_key: PublicKey,
}

impl PersonActor {
pub fn new(domain: &str, username: &str, public_key: PublicKey) -> Self {
Self {
id: format!("{}/actors/{}", domain, username).parse().unwrap(),
inbox: format!("{}/actors/{}/inbox", domain, username)
.parse()
.unwrap(),
outbox: format!("{}/actors/{}/outbox", domain, username)
.parse()
.unwrap(),
endpoints: vec![Endpoint {
shared_inbox: format!("{}/inbox", domain).parse().unwrap(),
}],
preferred_username: username.clone().to_owned(),
public_key,
}
}
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Endpoint {
shared_inbox: Url,
}
18 changes: 18 additions & 0 deletions crates/domainservd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,21 @@ license.workspace = true
categories.workspace = true

[dependencies]
axum.workspace = true
serde.workspace = true
serde_json.workspace = true
activitypub.workspace = true
thiserror.workspace = true
miette.workspace = true
clap.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
url.workspace = true
uuid.workspace = true
tokio.workspace = true
tower.workspace = true
tower-http.workspace = true
config.workspace = true
webfinger = "0.5.1"
lapin.workspace = true
deadpool-lapin = "0.10.0"
Loading

0 comments on commit 4d31e7a

Please sign in to comment.