aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'fedi/live_federation/objects/person.rs')
-rw-r--r--fedi/live_federation/objects/person.rs140
1 files changed, 140 insertions, 0 deletions
diff --git a/fedi/live_federation/objects/person.rs b/fedi/live_federation/objects/person.rs
new file mode 100644
index 0000000..d9439ea
--- /dev/null
+++ b/fedi/live_federation/objects/person.rs
@@ -0,0 +1,140 @@
1use crate::{activities::create_post::CreatePost, database::DatabaseHandle, error::Error};
2use activitypub_federation::{
3 config::Data,
4 fetch::object_id::ObjectId,
5 http_signatures::generate_actor_keypair,
6 kinds::actor::PersonType,
7 protocol::{public_key::PublicKey, verification::verify_domains_match},
8 traits::{ActivityHandler, Actor, Object},
9};
10use chrono::{DateTime, Utc};
11use serde::{Deserialize, Serialize};
12use std::fmt::Debug;
13use url::Url;
14
15#[derive(Debug, Clone)]
16pub struct DbUser {
17 pub name: String,
18 pub ap_id: ObjectId<DbUser>,
19 pub inbox: Url,
20 // exists for all users (necessary to verify http signatures)
21 pub public_key: String,
22 // exists only for local users
23 pub private_key: Option<String>,
24 last_refreshed_at: DateTime<Utc>,
25 pub followers: Vec<Url>,
26 pub local: bool,
27}
28
29/// List of all activities which this actor can receive.
30#[derive(Deserialize, Serialize, Debug)]
31#[serde(untagged)]
32#[enum_delegate::implement(ActivityHandler)]
33pub enum PersonAcceptedActivities {
34 CreateNote(CreatePost),
35}
36
37impl DbUser {
38 pub fn new(hostname: &str, name: &str) -> Result<DbUser, Error> {
39 let ap_id = Url::parse(&format!("https://{}/{}", hostname, &name))?.into();
40 let inbox = Url::parse(&format!("https://{}/{}/inbox", hostname, &name))?;
41 let keypair = generate_actor_keypair()?;
42 Ok(DbUser {
43 name: name.to_string(),
44 ap_id,
45 inbox,
46 public_key: keypair.public_key,
47 private_key: Some(keypair.private_key),
48 last_refreshed_at: Utc::now(),
49 followers: vec![],
50 local: true,
51 })
52 }
53}
54
55#[derive(Clone, Debug, Deserialize, Serialize)]
56#[serde(rename_all = "camelCase")]
57pub struct Person {
58 #[serde(rename = "type")]
59 kind: PersonType,
60 preferred_username: String,
61 id: ObjectId<DbUser>,
62 inbox: Url,
63 public_key: PublicKey,
64}
65
66#[async_trait::async_trait]
67impl Object for DbUser {
68 type DataType = DatabaseHandle;
69 type Kind = Person;
70 type Error = Error;
71
72 fn last_refreshed_at(&self) -> Option<DateTime<Utc>> {
73 Some(self.last_refreshed_at)
74 }
75
76 async fn read_from_id(
77 object_id: Url,
78 data: &Data<Self::DataType>,
79 ) -> Result<Option<Self>, Self::Error> {
80 let users = data.users.lock().unwrap();
81 let res = users
82 .clone()
83 .into_iter()
84 .find(|u| u.ap_id.inner() == &object_id);
85 Ok(res)
86 }
87
88 async fn into_json(self, _data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
89 Ok(Person {
90 preferred_username: self.name.clone(),
91 kind: Default::default(),
92 id: self.ap_id.clone(),
93 inbox: self.inbox.clone(),
94 public_key: self.public_key(),
95 })
96 }
97
98 async fn verify(
99 json: &Self::Kind,
100 expected_domain: &Url,
101 _data: &Data<Self::DataType>,
102 ) -> Result<(), Self::Error> {
103 verify_domains_match(json.id.inner(), expected_domain)?;
104 Ok(())
105 }
106
107 async fn from_json(
108 json: Self::Kind,
109 _data: &Data<Self::DataType>,
110 ) -> Result<Self, Self::Error> {
111 Ok(DbUser {
112 name: json.preferred_username,
113 ap_id: json.id,
114 inbox: json.inbox,
115 public_key: json.public_key.public_key_pem,
116 private_key: None,
117 last_refreshed_at: Utc::now(),
118 followers: vec![],
119 local: false,
120 })
121 }
122}
123
124impl Actor for DbUser {
125 fn id(&self) -> Url {
126 self.ap_id.inner().clone()
127 }
128
129 fn public_key_pem(&self) -> &str {
130 &self.public_key
131 }
132
133 fn private_key_pem(&self) -> Option<String> {
134 self.private_key.clone()
135 }
136
137 fn inbox(&self) -> Url {
138 self.inbox.clone()
139 }
140}
Powered by cgit v1.2.3 (git 2.41.0)