From 487ac435d7b687f071a0ed173d918fac480992b3 Mon Sep 17 00:00:00 2001 From: rtkay123 Date: Sat, 12 Jul 2025 15:57:19 +0200 Subject: feat: create user --- src/entity/user.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/entity/user.rs (limited to 'src/entity/user.rs') 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, + pub private_key: Option, + pub public_key: String, + pub inbox: Url, +} + +impl LocalUser { + pub fn new(username: &str) -> Result { + 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, + ) -> Result, 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) -> Result { + 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, + ) -> 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) -> Result { + todo!() + } +} + +impl Actor for LocalUser { + fn public_key_pem(&self) -> &str { + &self.public_key + } + + fn private_key_pem(&self) -> Option { + self.private_key.clone() + } + + fn inbox(&self) -> Url { + self.inbox.clone() + } +} -- cgit v1.2.3