diff --git a/src/model/activity.rs b/src/model/activity.rs index 3b48cef0..351d2f47 100644 --- a/src/model/activity.rs +++ b/src/model/activity.rs @@ -1,46 +1,95 @@ -use apb::{ActivityMut, BaseMut, ObjectMut}; +use apb::{ActivityMut, ActivityType, BaseMut, ObjectMut}; use sea_orm::entity::prelude::*; use crate::routes::activitypub::jsonld::LD; -use super::Audience; - #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "activities")] pub struct Model { #[sea_orm(primary_key)] - pub id: String, - - pub activity_type: apb::ActivityType, - pub actor: String, - pub object: Option, - - pub target: Option, // TODO relates to USER maybe?? - pub cc: Audience, - pub bcc: Audience, - pub to: Audience, - pub bto: Audience, + pub id: i32, + #[sea_orm(unique)] + pub ap_id: String, + pub activity_type: ActivityType, + pub actor: i32, + pub object: Option, + pub target: Option, + pub to: Option, + pub bto: Option, + pub cc: Option, + pub bcc: Option, pub published: ChronoDateTimeUtc, +} - // TODO: origin, result, instrument +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Actors, + #[sea_orm(has_many = "super::addressing::Entity")] + Addressing, + #[sea_orm(has_many = "super::delivery::Entity")] + Deliveries, + #[sea_orm( + belongs_to = "super::object::Entity", + from = "Column::Object", + to = "super::object::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Objects, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Addressing.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Deliveries.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Objects.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} + +impl ActiveModel { + pub fn new(activity: &impl apb::Activity) -> Result { + Ok(ActiveModel { + id: sea_orm::ActiveValue::NotSet, + ap_id: sea_orm::ActiveValue::Set(activity.id().ok_or(super::FieldError("id"))?.to_string()), + activity_type: sea_orm::ActiveValue::Set(activity.activity_type().ok_or(super::FieldError("type"))?), + actor: sea_orm::ActiveValue::Set(activity.actor().id().ok_or(super::FieldError("actor"))?), + object: sea_orm::ActiveValue::Set(activity.object().id()), + target: sea_orm::ActiveValue::Set(activity.target().id()), + published: sea_orm::ActiveValue::Set(activity.published().unwrap_or(chrono::Utc::now())), + to: sea_orm::ActiveValue::Set(activity.to().into()), + bto: sea_orm::ActiveValue::Set(activity.bto().into()), + cc: sea_orm::ActiveValue::Set(activity.cc().into()), + bcc: sea_orm::ActiveValue::Set(activity.bcc().into()), + }) + } } impl Model { - pub fn new(activity: &impl apb::Activity) -> Result { - Ok(Model { - id: activity.id().ok_or(super::FieldError("id"))?.to_string(), - activity_type: activity.activity_type().ok_or(super::FieldError("type"))?, - actor: activity.actor().id().ok_or(super::FieldError("actor"))?, - object: activity.object().id(), - target: activity.target().id(), - published: activity.published().unwrap_or(chrono::Utc::now()), - to: activity.to().into(), - bto: activity.bto().into(), - cc: activity.cc().into(), - bcc: activity.bcc().into(), - }) - } - pub fn ap(self) -> serde_json::Value { serde_json::Value::new_object() .set_id(Some(&self.id)) @@ -56,49 +105,6 @@ impl Model { } } -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::Actor", - to = "super::user::Column::Id" - )] - User, - - #[sea_orm( - belongs_to = "super::object::Entity", - from = "Column::Object", - to = "super::object::Column::Id" - )] - Object, - - #[sea_orm(has_many = "super::addressing::Entity")] - Addressing, - - #[sea_orm(has_many = "super::delivery::Entity")] - Delivery, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Object.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Addressing.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} - impl apb::target::Addressed for Model { fn addressed(&self) -> Vec { let mut to : Vec = self.to.0.clone(); diff --git a/src/model/user.rs b/src/model/actor.rs similarity index 50% rename from src/model/user.rs rename to src/model/actor.rs index 9aaf3410..66de0a1c 100644 --- a/src/model/user.rs +++ b/src/model/actor.rs @@ -5,68 +5,165 @@ use apb::{Actor, ActorMut, ActorType, BaseMut, DocumentMut, Endpoints, Endpoints use crate::routes::activitypub::jsonld::LD; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "users")] +#[sea_orm(table_name = "actors")] pub struct Model { #[sea_orm(primary_key)] - pub id: String, - pub domain: String, + pub id: i32, + #[sea_orm(unique)] + pub ap_id: String, pub actor_type: ActorType, - pub preferred_username: String, - + pub instance: i32, pub name: Option, pub summary: Option, pub image: Option, pub icon: Option, - + #[sea_orm(unique)] + pub preferred_username: String, pub inbox: Option, pub shared_inbox: Option, pub outbox: Option, pub following: Option, pub followers: Option, - - pub following_count: i64, - pub followers_count: i64, - pub statuses_count: i64, - + pub following_count: i32, + pub followers_count: i32, + pub statuses_count: i32, pub public_key: String, pub private_key: Option, - pub created: ChronoDateTimeUtc, pub updated: ChronoDateTimeUtc, - - // TODO these are also suggested - // pub liked: Option, - // pub streams: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::activity::Entity")] + Activities, + #[sea_orm(has_many = "super::addressing::Entity")] + Addressing, + #[sea_orm(has_many = "super::announce::Entity")] + Announces, + #[sea_orm(has_many = "super::config::Entity")] + Configs, + #[sea_orm(has_many = "super::credential::Entity")] + Credentials, + #[sea_orm(has_many = "super::delivery::Entity")] + Deliveries, + #[sea_orm( + belongs_to = "super::instance::Entity", + from = "Column::Instance", + to = "super::instance::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Instances, + #[sea_orm(has_many = "super::like::Entity")] + Likes, + #[sea_orm(has_many = "super::mention::Entity")] + Mentions, + #[sea_orm(has_many = "super::object::Entity")] + Objects, + #[sea_orm(has_many = "super::session::Entity")] + Sessions, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Activities.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Addressing.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Announces.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Configs.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Credentials.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Deliveries.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Instances.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Likes.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Mentions.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Objects.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Sessions.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} + +impl ActiveModel { + pub fn new(object: &impl Actor, instance: i32) -> Result { + let ap_id = object.id().ok_or(super::FieldError("id"))?.to_string(); + let (_domain, fallback_preferred_username) = split_user_id(&ap_id); + Ok(ActiveModel { + instance: sea_orm::ActiveValue::Set(instance), // TODO receiving it from outside is cheap + id: sea_orm::ActiveValue::NotSet, + ap_id: sea_orm::ActiveValue::Set(ap_id), + preferred_username: sea_orm::ActiveValue::Set(object.preferred_username().unwrap_or(&fallback_preferred_username).to_string()), + actor_type: sea_orm::ActiveValue::Set(object.actor_type().ok_or(super::FieldError("type"))?), + name: sea_orm::ActiveValue::Set(object.name().map(|x| x.to_string())), + summary: sea_orm::ActiveValue::Set(object.summary().map(|x| x.to_string())), + icon: sea_orm::ActiveValue::Set(object.icon().get().and_then(|x| x.url().id())), + image: sea_orm::ActiveValue::Set(object.image().get().and_then(|x| x.url().id())), + inbox: sea_orm::ActiveValue::Set(object.inbox().id()), + outbox: sea_orm::ActiveValue::Set(object.outbox().id()), + shared_inbox: sea_orm::ActiveValue::Set(object.endpoints().get().and_then(|x| Some(x.shared_inbox()?.to_string()))), + followers: sea_orm::ActiveValue::Set(object.followers().id()), + following: sea_orm::ActiveValue::Set(object.following().id()), + created: sea_orm::ActiveValue::Set(object.published().unwrap_or(chrono::Utc::now())), + updated: sea_orm::ActiveValue::Set(chrono::Utc::now()), + following_count: sea_orm::ActiveValue::Set(object.following_count().unwrap_or(0) as i64), + followers_count: sea_orm::ActiveValue::Set(object.followers_count().unwrap_or(0) as i64), + statuses_count: sea_orm::ActiveValue::Set(object.statuses_count().unwrap_or(0) as i64), + public_key: sea_orm::ActiveValue::Set(object.public_key().get().ok_or(super::FieldError("publicKey"))?.public_key_pem().to_string()), + private_key: sea_orm::ActiveValue::Set(None), // there's no way to transport privkey over AP json, must come from DB + }) + } } impl Model { - pub fn new(object: &impl Actor) -> Result { - let ap_id = object.id().ok_or(super::FieldError("id"))?.to_string(); - let (domain, fallback_preferred_username) = split_user_id(&ap_id); - Ok(Model { - id: ap_id, - domain, - preferred_username: object.preferred_username().unwrap_or(&fallback_preferred_username).to_string(), - actor_type: object.actor_type().ok_or(super::FieldError("type"))?, - name: object.name().map(|x| x.to_string()), - summary: object.summary().map(|x| x.to_string()), - icon: object.icon().get().and_then(|x| x.url().id()), - image: object.image().get().and_then(|x| x.url().id()), - inbox: object.inbox().id(), - outbox: object.outbox().id(), - shared_inbox: object.endpoints().get().and_then(|x| Some(x.shared_inbox()?.to_string())), - followers: object.followers().id(), - following: object.following().id(), - created: object.published().unwrap_or(chrono::Utc::now()), - updated: chrono::Utc::now(), - following_count: object.following_count().unwrap_or(0) as i64, - followers_count: object.followers_count().unwrap_or(0) as i64, - statuses_count: object.statuses_count().unwrap_or(0) as i64, - public_key: object.public_key().get().ok_or(super::FieldError("publicKey"))?.public_key_pem().to_string(), - private_key: None, // there's no way to transport privkey over AP json, must come from DB - }) - } - pub fn ap(self) -> serde_json::Value { serde_json::Value::new_object() .set_id(Some(&self.id)) @@ -106,65 +203,6 @@ impl Model { } } -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::activity::Entity")] - Activity, - - #[sea_orm(has_many = "super::object::Entity")] - Object, - - #[sea_orm(has_one = "super::config::Entity")] - Config, - - #[sea_orm(has_one = "super::credential::Entity")] - Credential, - - #[sea_orm(has_many = "super::session::Entity")] - Session, - - #[sea_orm(has_many = "super::addressing::Entity")] - Addressing, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Activity.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Object.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Config.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Credential.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Session.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Addressing.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} - fn split_user_id(id: &str) -> (String, String) { let clean = id .replace("http://", "") diff --git a/src/model/addressing.rs b/src/model/addressing.rs index fe855569..1e308d4e 100644 --- a/src/model/addressing.rs +++ b/src/model/addressing.rs @@ -7,53 +7,71 @@ use crate::routes::activitypub::jsonld::LD; #[sea_orm(table_name = "addressing")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, - pub actor: String, - pub server: String, - pub activity: Option, - pub object: Option, + pub id: i32, + pub actor: i32, + pub instance: i32, + pub activity: Option, + pub object: Option, pub published: ChronoDateTimeUtc, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { - #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::Actor", - to = "super::user::Column::Id" - )] - User, - #[sea_orm( belongs_to = "super::activity::Entity", from = "Column::Activity", - to = "super::activity::Column::Id" + to = "super::activity::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" )] - Activity, - + Activities, + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Actors, + #[sea_orm( + belongs_to = "super::instance::Entity", + from = "Column::Instance", + to = "super::instance::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Instances, #[sea_orm( belongs_to = "super::object::Entity", from = "Column::Object", - to = "super::object::Column::Id" + to = "super::object::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" )] - Object, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } + Objects, } impl Related for Entity { fn to() -> RelationDef { - Relation::Activity.def() + Relation::Activities.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Instances.def() } } impl Related for Entity { fn to() -> RelationDef { - Relation::Object.def() + Relation::Objects.def() } } diff --git a/src/model/announce.rs b/src/model/announce.rs new file mode 100644 index 00000000..fc7a4044 --- /dev/null +++ b/src/model/announce.rs @@ -0,0 +1,45 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "announces")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub actor: i32, + pub announces: i32, + pub published: ChronoDateTimeUtc, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Actors, + #[sea_orm( + belongs_to = "super::object::Entity", + from = "Column::Announces", + to = "super::object::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Objects, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Objects.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/model/application.rs b/src/model/application.rs deleted file mode 100644 index cde98aac..00000000 --- a/src/model/application.rs +++ /dev/null @@ -1,18 +0,0 @@ -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "application")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: i64, - - pub private_key: String, - pub public_key: String, - - pub created: ChronoDateTimeUtc, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/src/model/attachment.rs b/src/model/attachment.rs index 1a117969..c7c8914a 100644 --- a/src/model/attachment.rs +++ b/src/model/attachment.rs @@ -9,16 +9,36 @@ use super::addressing::Event; #[sea_orm(table_name = "attachments")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, - + pub id: i32, + #[sea_orm(unique)] pub url: String, - pub object: String, - pub document_type: apb::DocumentType, + pub object: i32, + pub document_type: String, pub name: Option, pub media_type: String, pub created: ChronoDateTimeUtc, } +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::object::Entity", + from = "Column::Object", + to = "super::object::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Objects, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Objects.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} + impl Model { pub fn ap(self) -> serde_json::Value { serde_json::Value::new_object() @@ -30,25 +50,6 @@ impl Model { } } -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::object::Entity", - from = "Column::Object", - to = "super::object::Column::Id" - )] - Object, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Object.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} - - #[axum::async_trait] pub trait BatchFillable { async fn load_attachments_batch(&self, db: &DatabaseConnection) -> Result>, DbErr>; diff --git a/src/model/config.rs b/src/model/config.rs index b34df1d3..f95bf43f 100644 --- a/src/model/config.rs +++ b/src/model/config.rs @@ -4,7 +4,8 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "configs")] pub struct Model { #[sea_orm(primary_key)] - pub id: String, + pub id: i32, + pub actor: i32, pub accept_follow_requests: bool, pub show_followers_count: bool, pub show_following_count: bool, @@ -15,7 +16,7 @@ pub struct Model { impl Default for Model { fn default() -> Self { Model { - id: "".to_string(), + id: 0, actor: 0, accept_follow_requests: true, show_following_count: true, show_following: true, @@ -28,16 +29,18 @@ impl Default for Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::Id", - to = "super::user::Column::Id" + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" )] - User, + Actors, } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { - Relation::User.def() + Relation::Actors.def() } } diff --git a/src/model/credential.rs b/src/model/credential.rs index f3cdc5fc..5255ead5 100644 --- a/src/model/credential.rs +++ b/src/model/credential.rs @@ -4,24 +4,27 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "credentials")] pub struct Model { #[sea_orm(primary_key)] - pub id: String, - pub email: String, + pub id: i32, + pub actor: i32, + pub login: String, pub password: String, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::Id", - to = "super::user::Column::Id" + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" )] - User, + Actors, } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { - Relation::User.def() + Relation::Actors.def() } } diff --git a/src/model/delivery.rs b/src/model/delivery.rs index ef712619..6835f4dd 100644 --- a/src/model/delivery.rs +++ b/src/model/delivery.rs @@ -4,10 +4,10 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "deliveries")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, - pub actor: String, + pub id: i32, + pub actor: i32, pub target: String, - pub activity: String, + pub activity: i32, pub created: ChronoDateTimeUtc, pub not_before: ChronoDateTimeUtc, pub attempt: i32, @@ -18,14 +18,30 @@ pub enum Relation { #[sea_orm( belongs_to = "super::activity::Entity", from = "Column::Activity", - to = "super::activity::Column::Id" + to = "super::activity::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" )] - Activity, + Activities, + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Actors, } impl Related for Entity { fn to() -> RelationDef { - Relation::Activity.def() + Relation::Activities.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() } } diff --git a/src/model/share.rs b/src/model/hashtag.rs similarity index 65% rename from src/model/share.rs rename to src/model/hashtag.rs index e677cf98..d17b1d3c 100644 --- a/src/model/share.rs +++ b/src/model/hashtag.rs @@ -1,28 +1,30 @@ use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "shares")] +#[sea_orm(table_name = "hashtags")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, - pub actor: String, - pub shares: String, - pub date: ChronoDateTimeUtc, + pub id: i32, + pub object: i32, + pub name: String, + pub published: ChronoDateTimeUtc, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( belongs_to = "super::object::Entity", - from = "Column::Shares", + from = "Column::Object", to = "super::object::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" )] - Object + Objects, } impl Related for Entity { fn to() -> RelationDef { - Relation::Object.def() + Relation::Objects.def() } } diff --git a/src/model/instance.rs b/src/model/instance.rs new file mode 100644 index 00000000..125fc1f1 --- /dev/null +++ b/src/model/instance.rs @@ -0,0 +1,39 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "instances")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub name: Option, + pub domain: String, + pub software: Option, + pub version: Option, + pub down_since: Option, + pub users: Option, + pub posts: Option, + pub published: ChronoDateTimeUtc, + pub updated: ChronoDateTimeUtc, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::actor::Entity")] + Actors, + #[sea_orm(has_many = "super::addressing::Entity")] + Addressing, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Addressing.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/model/like.rs b/src/model/like.rs index 2e072f6b..66456fcd 100644 --- a/src/model/like.rs +++ b/src/model/like.rs @@ -4,25 +4,41 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "likes")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, - pub actor: String, - pub likes: String, - pub date: ChronoDateTimeUtc, + pub id: i32, + pub actor: i32, + pub likes: i32, + pub published: ChronoDateTimeUtc, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Actors, #[sea_orm( belongs_to = "super::object::Entity", from = "Column::Likes", to = "super::object::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" )] - Object + Objects, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } } impl Related for Entity { fn to() -> RelationDef { - Relation::Object.def() + Relation::Objects.def() } } diff --git a/src/model/mention.rs b/src/model/mention.rs new file mode 100644 index 00000000..139d00c0 --- /dev/null +++ b/src/model/mention.rs @@ -0,0 +1,45 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "mentions")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub object: i32, + pub actor: i32, + pub published: ChronoDateTimeUtc, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Actors, + #[sea_orm( + belongs_to = "super::object::Entity", + from = "Column::Object", + to = "super::object::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Objects, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Objects.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/src/model/mod.rs b/src/model/mod.rs index 04bdb6d5..dc5fcf86 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -1,18 +1,23 @@ +pub mod actor; pub mod object; pub mod activity; -pub mod user; -pub mod config; -pub mod relay; -pub mod relation; -pub mod addressing; -pub mod share; -pub mod like; +pub mod config; pub mod credential; pub mod session; + +pub mod instance; pub mod delivery; + +pub mod relation; +pub mod announce; +pub mod like; + +pub mod hashtag; +pub mod mention; pub mod attachment; -pub mod application; + +pub mod addressing; #[derive(Debug, Clone, thiserror::Error)] #[error("missing required field: '{0}'")] diff --git a/src/model/object.rs b/src/model/object.rs index 82387a81..a56257b8 100644 --- a/src/model/object.rs +++ b/src/model/object.rs @@ -9,57 +9,137 @@ use super::Audience; #[sea_orm(table_name = "objects")] pub struct Model { #[sea_orm(primary_key)] - pub id: String, - pub object_type: apb::ObjectType, - pub attributed_to: Option, + pub id: i32, + #[sea_orm(unique)] + pub ap_id: String, + pub object_type: String, + pub attributed_to: Option, pub name: Option, pub summary: Option, pub content: Option, - pub likes: i64, - pub shares: i64, - pub comments: i64, - pub context: Option, - pub in_reply_to: Option, - pub cc: Audience, - pub bcc: Audience, - pub to: Audience, - pub bto: Audience, - pub url: Option, - pub published: ChronoDateTimeUtc, - pub updated: Option, - pub sensitive: bool, + pub in_reply_to: Option, + pub url: Option, + pub likes: i32, + pub announces: i32, + pub replies: i32, + pub context: Option, + pub to: Option, + pub bto: Option, + pub cc: Option, + pub bcc: Option, + pub published: ChronoDateTimeUtc, + pub updated: ChronoDateTimeUtc, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::activity::Entity")] + Activities, + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::AttributedTo", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Actors, + #[sea_orm(has_many = "super::addressing::Entity")] + Addressing, + #[sea_orm(has_many = "super::announce::Entity")] + Announces, + #[sea_orm(has_many = "super::attachment::Entity")] + Attachments, + #[sea_orm(has_many = "super::hashtag::Entity")] + Hashtags, + #[sea_orm(has_many = "super::like::Entity")] + Likes, + #[sea_orm(has_many = "super::mention::Entity")] + Mentions, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Activities.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Addressing.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Announces.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Attachments.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Hashtags.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Likes.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Mentions.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} + +impl ActiveModel { + pub fn new(object: &impl apb::Object) -> Result { + Ok(ActiveModel { + id: sea_orm::ActiveValue::NotSet, + ap_id: sea_orm::ActiveValue::Set(object.id().ok_or(super::FieldError("id"))?.to_string()), + object_type: sea_orm::ActiveValue::Set(object.object_type().ok_or(super::FieldError("type"))?), + attributed_to: sea_orm::ActiveValue::Set(object.attributed_to().id()), + name: sea_orm::ActiveValue::Set(object.name().map(|x| x.to_string())), + summary: sea_orm::ActiveValue::Set(object.summary().map(|x| x.to_string())), + content: sea_orm::ActiveValue::Set(object.content().map(|x| x.to_string())), + context: sea_orm::ActiveValue::Set(object.context().id()), + in_reply_to: sea_orm::ActiveValue::Set(object.in_reply_to().id()), + published: sea_orm::ActiveValue::Set(object.published().ok_or(super::FieldError("published"))?), + updated: sea_orm::ActiveValue::Set(object.updated()), + url: sea_orm::ActiveValue::Set(object.url().id()), + replies: sea_orm::ActiveValue::Set(object.replies().get() + .map_or(0, |x| x.total_items().unwrap_or(0)) as i64), + likes: sea_orm::ActiveValue::Set(object.likes().get() + .map_or(0, |x| x.total_items().unwrap_or(0)) as i64), + announces: sea_orm::ActiveValue::Set(object.shares().get() + .map_or(0, |x| x.total_items().unwrap_or(0)) as i64), + to: sea_orm::ActiveValue::Set(object.to().into()), + bto: sea_orm::ActiveValue::Set(object.bto().into()), + cc: sea_orm::ActiveValue::Set(object.cc().into()), + bcc: sea_orm::ActiveValue::Set(object.bcc().into()), + + sensitive: sea_orm::ActiveValue::Set(object.sensitive().unwrap_or(false)), + }) + } } impl Model { - pub fn new(object: &impl apb::Object) -> Result { - Ok(Model { - id: object.id().ok_or(super::FieldError("id"))?.to_string(), - object_type: object.object_type().ok_or(super::FieldError("type"))?, - attributed_to: object.attributed_to().id(), - name: object.name().map(|x| x.to_string()), - summary: object.summary().map(|x| x.to_string()), - content: object.content().map(|x| x.to_string()), - context: object.context().id(), - in_reply_to: object.in_reply_to().id(), - published: object.published().ok_or(super::FieldError("published"))?, - updated: object.updated(), - url: object.url().id(), - comments: object.replies().get() - .map_or(0, |x| x.total_items().unwrap_or(0)) as i64, - likes: object.likes().get() - .map_or(0, |x| x.total_items().unwrap_or(0)) as i64, - shares: object.shares().get() - .map_or(0, |x| x.total_items().unwrap_or(0)) as i64, - to: object.to().into(), - bto: object.bto().into(), - cc: object.cc().into(), - bcc: object.bcc().into(), - - sensitive: object.sensitive().unwrap_or(false), - }) - } - pub fn ap(self) -> serde_json::Value { serde_json::Value::new_object() .set_id(Some(&self.id)) @@ -72,7 +152,7 @@ impl Model { .set_conversation(apb::Node::maybe_link(self.context.clone())) // duplicate context for mastodon .set_in_reply_to(apb::Node::maybe_link(self.in_reply_to.clone())) .set_published(Some(self.published)) - .set_updated(self.updated) + .set_updated(Some(self.updated)) .set_to(apb::Node::links(self.to.0.clone())) .set_bto(apb::Node::Empty) .set_cc(apb::Node::links(self.cc.0.clone())) @@ -97,69 +177,6 @@ impl Model { } } -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::activity::Entity")] - Activity, - - #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::AttributedTo", - to = "super::user::Column::Id", - )] - User, - - #[sea_orm(has_many = "super::addressing::Entity")] - Addressing, - - #[sea_orm(has_many = "super::attachment::Entity")] - Attachment, - - #[sea_orm(has_many = "super::like::Entity")] - Like, - - #[sea_orm(has_many = "super::share::Entity")] - Share, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Activity.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Addressing.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Attachment.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Like.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Share.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} - impl apb::target::Addressed for Model { fn addressed(&self) -> Vec { let mut to : Vec = self.to.0.clone(); diff --git a/src/model/relation.rs b/src/model/relation.rs index 41bcc27c..44d01df6 100644 --- a/src/model/relation.rs +++ b/src/model/relation.rs @@ -4,13 +4,47 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "relations")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, - pub follower: String, - pub following: String, + pub id: i32, + pub follower: i32, + pub following: i32, + pub accept: Option, + pub activity: i32, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} -// TODO how to represent this User-to-User relation in sea orm?? +pub enum Relation { + #[sea_orm( + belongs_to = "super::activity::Entity", + from = "Column::Accept", + to = "super::activity::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Activities2, + #[sea_orm( + belongs_to = "super::activity::Entity", + from = "Column::Activity", + to = "super::activity::Column::Id", + on_update = "Cascade", + on_delete = "NoAction" + )] + Activities1, + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Follower", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Actors2, + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Following", + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Actors1, +} impl ActiveModelBehavior for ActiveModel {} diff --git a/src/model/relay.rs b/src/model/relay.rs deleted file mode 100644 index 0ea3b596..00000000 --- a/src/model/relay.rs +++ /dev/null @@ -1,16 +0,0 @@ -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "relays")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: String, - pub accepted: bool, - pub forwarding: bool, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} -// TODO how to represent this User-to-User relation in sea orm?? - -impl ActiveModelBehavior for ActiveModel {} diff --git a/src/model/session.rs b/src/model/session.rs index a2216e25..0e7dfea2 100644 --- a/src/model/session.rs +++ b/src/model/session.rs @@ -4,24 +4,27 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "sessions")] pub struct Model { #[sea_orm(primary_key)] - pub id: String, - pub actor: String, + pub id: i32, + pub actor: i32, + pub secret: String, pub expires: ChronoDateTimeUtc, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( - belongs_to = "super::user::Entity", + belongs_to = "super::actor::Entity", from = "Column::Actor", - to = "super::user::Column::Id" + to = "super::actor::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" )] - User, + Actors, } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { - Relation::User.def() + Relation::Actors.def() } }