summaryrefslogtreecommitdiffstats
path: root/src/entity/user.rs
diff options
context:
space:
mode:
authorrtkay123 <dev@kanjala.com>2025-07-16 14:07:00 +0200
committerrtkay123 <dev@kanjala.com>2025-07-16 14:07:00 +0200
commitef6b5100f120c58199103d8641e381c119507350 (patch)
tree0f2c16c49f8db8132d5d8f0e5f499277cfab426c /src/entity/user.rs
parentc2ca0fae98c535dccb52d9ab949e1e534a9078a3 (diff)
downloadsellershut-ef6b5100f120c58199103d8641e381c119507350.tar.bz2
sellershut-ef6b5100f120c58199103d8641e381c119507350.zip
feat: user type
Diffstat (limited to 'src/entity/user.rs')
-rw-r--r--src/entity/user.rs82
1 files changed, 75 insertions, 7 deletions
diff --git a/src/entity/user.rs b/src/entity/user.rs
index 24315e0..47a761a 100644
--- a/src/entity/user.rs
+++ b/src/entity/user.rs
@@ -1,10 +1,12 @@
pub mod followers;
+use std::fmt::Display;
+
use activitypub_federation::{
config::Data,
fetch::object_id::ObjectId,
http_signatures::generate_actor_keypair,
- kinds::actor::PersonType,
+ kinds::actor::{ApplicationType, GroupType, OrganizationType, PersonType, ServiceType},
protocol::public_key::PublicKey,
traits::{Actor, Object},
};
@@ -29,6 +31,7 @@ pub(crate) struct User {
pub public_key: String,
pub inbox: Url,
pub outbox: Option<Url>,
+ pub user_type: UserType,
}
pub struct DbUser {
@@ -44,6 +47,48 @@ pub struct DbUser {
pub local: bool,
pub updated_at: OffsetDateTime,
pub created_at: OffsetDateTime,
+ pub user_type: UserType,
+}
+
+#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
+#[serde(rename_all = "PascalCase")]
+#[serde(untagged)]
+pub enum UserType {
+ Person(PersonType),
+ Application(ApplicationType),
+ Group(GroupType),
+ Organization(OrganizationType),
+ Service(ServiceType),
+}
+
+impl Display for UserType {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ UserType::Person(person) => person.to_string(),
+ UserType::Application(application_type) => application_type.to_string(),
+ UserType::Group(group_type) => group_type.to_string(),
+ UserType::Organization(organization_type) => organization_type.to_string(),
+ UserType::Service(service_type) => service_type.to_string(),
+ }
+ .to_uppercase()
+ )
+ }
+}
+
+impl From<String> for UserType {
+ fn from(value: String) -> Self {
+ match value.to_lowercase().as_str() {
+ "person" => Self::Person(PersonType::Person),
+ "application" => Self::Application(ApplicationType::Application),
+ "group" => Self::Group(GroupType::Group),
+ "organization" => Self::Organization(OrganizationType::Organization),
+ "service" => Self::Service(ServiceType::Service),
+ _ => unreachable!("{}", value),
+ }
+ }
}
impl TryFrom<DbUser> for User {
@@ -62,6 +107,7 @@ impl TryFrom<DbUser> for User {
},
description: value.description,
avatar_url: value.avatar_url,
+ user_type: value.user_type,
})
}
}
@@ -102,10 +148,12 @@ impl User {
);
let id = Uuid::now_v7();
+ let kind = UserType::Service(ServiceType::Service);
+
trace!(id = ?id, "creating a new user");
let user = sqlx::query_as!(
DbUser,
- "insert into account (id, username, ap_id, private_key, public_key, inbox, outbox, local) values ($1, $2, $3, $4, $5, $6, $7, $8) returning *",
+ "insert into account (id, username, ap_id, private_key, public_key, inbox, outbox, local, user_type) values ($1, $2, $3, $4, $5, $6, $7, $8, $9) returning *",
id,
username,
stub,
@@ -113,7 +161,8 @@ impl User {
keys.public_key,
&format!("{stub}/inbox"),
&format!("{stub}/outbox"),
- true
+ true,
+ kind.to_string(),
).fetch_one(&services.postgres).await?;
Self::try_from(user)
}
@@ -123,7 +172,7 @@ impl User {
#[serde(rename_all = "camelCase")]
pub struct Person {
#[serde(rename = "type")]
- kind: PersonType,
+ kind: UserType,
preferred_username: String,
id: ObjectId<User>,
inbox: Url,
@@ -161,7 +210,15 @@ impl Object for User {
object_id: Url,
data: &Data<Self::DataType>,
) -> Result<Option<Self>, Self::Error> {
- todo!()
+ let id = object_id.as_str();
+ let result = sqlx::query_as!(DbUser, "select * from account where ap_id = $1", id)
+ .fetch_optional(&data.services.postgres)
+ .await?;
+ let user = match result {
+ Some(user) => Some(User::try_from(user)?),
+ None => None,
+ };
+ Ok(user)
}
#[doc = " Convert database type to Activitypub type."]
@@ -170,7 +227,7 @@ impl Object for User {
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
Ok(Person {
preferred_username: self.username.clone(),
- kind: Default::default(),
+ kind: self.user_type.clone(),
id: self.ap_id.clone(),
inbox: self.inbox.clone(),
public_key: self.public_key(),
@@ -203,7 +260,18 @@ impl Object for User {
#[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!()
+ Ok(Self {
+ id: todo!(),
+ username: todo!(),
+ ap_id: todo!(),
+ private_key: todo!(),
+ description: todo!(),
+ avatar_url: todo!(),
+ public_key: todo!(),
+ inbox: todo!(),
+ outbox: todo!(),
+ user_type: todo!(),
+ })
}
}