summaryrefslogtreecommitdiffstats
path: root/src/entity/user.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/entity/user.rs')
-rw-r--r--src/entity/user.rs109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/entity/user.rs b/src/entity/user.rs
new file mode 100644
index 0000000..af27ea2
--- /dev/null
+++ b/src/entity/user.rs
@@ -0,0 +1,109 @@
+use activitypub_federation::{
+ config::Data,
+ fetch::object_id::ObjectId,
+ http_signatures::generate_actor_keypair,
+ traits::{Actor, Object},
+};
+use async_trait::async_trait;
+use serde::Deserialize;
+use tracing::trace;
+use url::Url;
+
+use crate::{error::AppError, state::AppHandle};
+
+#[derive(PartialEq, Clone, Debug)]
+pub(crate) struct LocalUser {
+ pub username: String,
+ pub ap_id: ObjectId<LocalUser>,
+ pub private_key: Option<String>,
+ pub public_key: String,
+ pub inbox: Url,
+}
+
+impl LocalUser {
+ pub fn new(username: &str) -> Result<Self, AppError> {
+ trace!("creating a new user");
+ let keys = generate_actor_keypair()?;
+ let stub = &format!("http://localhost/users/{username}");
+
+ Ok(Self {
+ username: username.to_owned(),
+ ap_id: Url::parse(stub)?.into(),
+ private_key: Some(keys.private_key),
+ public_key: keys.public_key,
+ inbox: Url::parse(&format!("{stub}/inbox"))?,
+ })
+ }
+}
+
+#[derive(Deserialize)]
+pub struct User {}
+
+#[async_trait]
+impl Object for LocalUser {
+ #[doc = " App data type passed to handlers. Must be identical to"]
+ #[doc = " [crate::config::FederationConfigBuilder::app_data] type."]
+ type DataType = AppHandle;
+
+ #[doc = " The type of protocol struct which gets sent over network to federate this database struct."]
+ type Kind = User;
+
+ #[doc = " Error type returned by handler methods"]
+ type Error = AppError;
+
+ #[doc = " `id` field of the object"]
+ fn id(&self) -> &Url {
+ self.ap_id.inner()
+ }
+
+ #[doc = " Try to read the object with given `id` from local database."]
+ #[doc = " Should return `Ok(None)` if not found."]
+ async fn read_from_id(
+ object_id: Url,
+ data: &Data<Self::DataType>,
+ ) -> Result<Option<Self>, Self::Error> {
+ todo!()
+ }
+
+ #[doc = " Convert database type to Activitypub type."]
+ #[doc = " Called when a local object gets fetched by another instance over HTTP, or when an object"]
+ #[doc = " gets sent in an activity."]
+ async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
+ todo!()
+ }
+
+ #[doc = " Verifies that the received object is valid."]
+ #[doc = " You should check here that the domain of id matches `expected_domain`. Additionally you"]
+ #[doc = " should perform any application specific checks."]
+ #[doc = " It is necessary to use a separate method for this, because it might be used for activities"]
+ #[doc = " like `Delete/Note`, which shouldn\'t perform any database write for the inner `Note`."]
+ async fn verify(
+ json: &Self::Kind,
+ expected_domain: &Url,
+ data: &Data<Self::DataType>,
+ ) -> Result<(), Self::Error> {
+ todo!()
+ }
+
+ #[doc = " Convert object from ActivityPub type to database type."]
+ #[doc = " Called when an object is received from HTTP fetch or as part of an activity. This method"]
+ #[doc = " should write the received object to database. Note that there is no distinction between"]
+ #[doc = " create and update, so an `upsert` operation should be used."]
+ async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
+ todo!()
+ }
+}
+
+impl Actor for LocalUser {
+ fn public_key_pem(&self) -> &str {
+ &self.public_key
+ }
+
+ fn private_key_pem(&self) -> Option<String> {
+ self.private_key.clone()
+ }
+
+ fn inbox(&self) -> Url {
+ self.inbox.clone()
+ }
+}