activitypub/src/objects/person.rs

257 lines
7.8 KiB
Rust
Raw Normal View History

2024-04-18 04:03:52 +02:00
use crate::{
2024-05-09 23:07:20 +02:00
activities::{
create_post::CreatePost,
follow::{self, Follow},
},
2024-04-18 04:03:52 +02:00
database::{State, StateHandle},
entities::{self, user},
2024-07-27 16:24:04 +02:00
error::Error,
API_DOMAIN,
2024-04-18 04:03:52 +02:00
};
2024-04-09 19:48:18 +02:00
use activitypub_federation::{
config::Data,
fetch::object_id::ObjectId,
http_signatures::generate_actor_keypair,
kinds::actor::PersonType,
protocol::{public_key::PublicKey, verification::verify_domains_match},
traits::{ActivityHandler, Actor, Object},
};
use actix_web::http::header::Accept;
2024-04-18 03:41:52 +02:00
use chrono::{prelude, DateTime, Utc};
2024-05-04 19:07:34 +02:00
use entities::prelude::User;
2024-04-18 03:41:52 +02:00
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
2024-04-09 19:48:18 +02:00
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
2024-04-20 17:35:40 +02:00
use tracing::info;
2024-04-09 19:48:18 +02:00
use url::Url;
2024-07-16 19:35:04 +02:00
use uuid::Uuid;
2024-04-09 19:48:18 +02:00
2024-04-16 19:53:24 +02:00
#[derive(Debug, Clone)]
2024-04-09 19:48:18 +02:00
pub struct DbUser {
pub name: String,
2024-04-18 03:41:52 +02:00
pub ap_id: ObjectId<user::Model>,
2024-04-09 19:48:18 +02:00
pub inbox: Url,
// exists for all users (necessary to verify http signatures)
pub public_key: String,
// exists only for local users
pub private_key: Option<String>,
last_refreshed_at: DateTime<Utc>,
pub followers: Vec<Url>,
pub local: bool,
}
/// List of all activities which this actor can receive.
#[derive(Deserialize, Serialize, Debug)]
#[serde(untagged)]
#[enum_delegate::implement(ActivityHandler)]
pub enum PersonAcceptedActivities {
CreateNote(CreatePost),
Follow(Follow),
2024-05-09 23:07:20 +02:00
Accept(follow::Accept),
2024-04-09 19:48:18 +02:00
}
impl DbUser {
pub fn new(hostname: &str, name: &str) -> Result<DbUser, Error> {
let ap_id = Url::parse(&format!("https://{}/{}", hostname, &name))?.into();
let inbox = Url::parse(&format!("https://{}/{}/inbox", hostname, &name))?;
let keypair = generate_actor_keypair()?;
Ok(DbUser {
name: name.to_string(),
ap_id,
inbox,
public_key: keypair.public_key,
private_key: Some(keypair.private_key),
last_refreshed_at: Utc::now(),
followers: vec![],
local: true,
})
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Person {
#[serde(rename = "type")]
2024-07-17 02:08:39 +02:00
pub kind: PersonType,
pub preferred_username: String,
pub name: String,
pub summary: Option<String>,
pub url: Url,
pub id: ObjectId<user::Model>,
pub inbox: Url,
pub public_key: PublicKey,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub indexable: Option<bool>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub discoverable: Option<bool>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub manually_approves_followers: Option<bool>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub followers: Option<Url>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub following: Option<Url>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub featured: Option<Url>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub endpoints: Option<EndpointType>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub outbox: Option<Url>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub featured_tags: Option<Url>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub tag: Option<Vec<TagType>>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub icon: Option<IconType>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub image: Option<IconType>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 19:37:08 +02:00
pub attachment: Option<Vec<AttachmentType>>,
2024-07-26 17:24:33 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-26 17:33:07 +02:00
pub also_known_as: Option<Vec<Url>>,
2024-07-21 19:37:08 +02:00
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TagType {
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 21:04:13 +02:00
pub id: Option<Url>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 21:04:13 +02:00
pub href: Option<Url>,
2024-07-21 19:37:08 +02:00
pub name: String,
#[serde(rename = "type")]
pub type_: String,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 21:04:13 +02:00
pub updated: Option<DateTime<Utc>>,
2024-07-26 00:26:13 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
2024-07-21 21:04:13 +02:00
pub icon: Option<IconType>,
2024-07-21 19:37:08 +02:00
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EndpointType {
pub shared_inbox: Url,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
2024-07-21 20:56:53 +02:00
#[serde(rename_all = "camelCase")]
2024-07-21 19:37:08 +02:00
pub struct IconType {
#[serde(rename = "type")]
pub type_: String, //Always "Image"
2024-07-26 17:24:33 +02:00
#[serde(skip_serializing_if = "Option::is_none")]
pub media_type: Option<String>,
2024-07-21 19:37:08 +02:00
pub url: Url,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AttachmentType {
#[serde(rename = "type")]
pub type_: String, //Always "PropertyValue"
pub name: String,
pub value: String,
2024-04-09 19:48:18 +02:00
}
#[async_trait::async_trait]
2024-04-18 03:41:52 +02:00
impl Object for user::Model {
type DataType = StateHandle;
2024-04-09 19:48:18 +02:00
type Kind = Person;
type Error = Error;
fn last_refreshed_at(&self) -> Option<DateTime<Utc>> {
Some(self.last_refreshed_at)
}
async fn read_from_id(
object_id: Url,
data: &Data<Self::DataType>,
) -> Result<Option<Self>, Self::Error> {
2024-08-03 11:34:46 +02:00
println!("!!!!!!!!Reading user from id!!!!!!!!!!!: {}", object_id);
2024-04-18 03:41:52 +02:00
let res = entities::prelude::User::find()
2024-08-03 11:43:04 +02:00
.filter(entities::user::Column::Url.eq(object_id.to_string()))
2024-04-18 03:41:52 +02:00
.one(data.database_connection.as_ref())
.await?;
2024-08-03 15:30:34 +02:00
println!(
"!!!!!!!!Reading user from id!!!!!!!!!!!: {}",
res.clone().is_some()
);
2024-04-09 19:48:18 +02:00
Ok(res)
}
async fn into_json(self, _data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
2024-07-21 19:37:08 +02:00
let serialized = serde_json::from_str(self.ap_json.as_ref().unwrap().as_str())?;
Ok(serialized)
2024-04-09 19:48:18 +02:00
}
async fn verify(
json: &Self::Kind,
expected_domain: &Url,
_data: &Data<Self::DataType>,
) -> Result<(), Self::Error> {
verify_domains_match(json.id.inner(), expected_domain)?;
Ok(())
}
async fn from_json(
json: Self::Kind,
_data: &Data<Self::DataType>,
) -> Result<Self, Self::Error> {
2024-05-04 01:26:10 +02:00
let query = User::find()
.filter(user::Column::Id.eq(json.id.inner().as_str()))
2024-05-04 19:07:34 +02:00
.one(_data.database_connection.as_ref())
.await?;
2024-05-04 01:26:10 +02:00
if let Some(user) = query {
return Ok(user);
}
2024-07-21 19:37:08 +02:00
let copied_json = json.clone();
2024-04-18 03:41:52 +02:00
let model = user::ActiveModel {
2024-07-16 19:35:04 +02:00
id: Set(Uuid::now_v7().to_string()),
2024-04-18 03:41:52 +02:00
username: Set(json.preferred_username),
2024-04-18 19:01:14 +02:00
name: Set(json.name),
2024-04-18 03:41:52 +02:00
inbox: Set(json.inbox.to_string()),
public_key: Set(json.public_key.public_key_pem),
local: Set(false),
2024-04-18 19:01:14 +02:00
summary: Set(json.summary),
url: Set(json.id.to_string()),
follower_count: Set(0),
following_count: Set(0),
created_at: Set(Utc::now()),
last_refreshed_at: Set(Utc::now()),
2024-07-21 19:37:08 +02:00
ap_json: Set(Some(serde_json::to_string(&copied_json).unwrap())),
2024-04-18 03:41:52 +02:00
..Default::default()
};
2024-04-18 19:01:14 +02:00
let model = model.insert(_data.database_connection.as_ref()).await;
if let Err(err) = model {
eprintln!("Error inserting user: {:?}", err);
Err(err.into())
} else {
info!("User inserted: {:?}", model.as_ref().unwrap());
Ok(model.unwrap())
}
2024-04-09 19:48:18 +02:00
}
}
2024-04-18 03:41:52 +02:00
impl Actor for user::Model {
2024-04-09 19:48:18 +02:00
fn id(&self) -> Url {
2024-07-26 18:11:08 +02:00
Url::parse(&format!(
"https://{}/apbridge/user/{}",
API_DOMAIN.to_string(),
&self.id
2024-07-27 16:24:04 +02:00
))
.unwrap()
2024-04-09 19:48:18 +02:00
}
fn public_key_pem(&self) -> &str {
&self.public_key
}
fn private_key_pem(&self) -> Option<String> {
self.private_key.clone()
}
fn inbox(&self) -> Url {
2024-04-18 03:41:52 +02:00
Url::parse(&self.inbox).unwrap()
2024-04-09 19:48:18 +02:00
}
2024-06-27 05:13:38 +02:00
//TODO: Differenciate shared inbox
fn shared_inbox(&self) -> Option<Url> {
None
}
2024-04-09 19:48:18 +02:00
}