diff --git a/upub/core/src/model/activity.rs b/upub/core/src/model/activity.rs index 45c14e1e..7916dc3b 100644 --- a/upub/core/src/model/activity.rs +++ b/upub/core/src/model/activity.rs @@ -33,6 +33,8 @@ pub enum Relation { Actors, #[sea_orm(has_many = "super::addressing::Entity")] Addressing, + #[sea_orm(has_many = "super::notification::Entity")] + Notifications, #[sea_orm( belongs_to = "super::object::Entity", from = "Column::Object", @@ -55,6 +57,12 @@ impl Related for Entity { } } +impl Related for Entity { + fn to() -> RelationDef { + Relation::Notifications.def() + } +} + impl Related for Entity { fn to() -> RelationDef { Relation::Objects.def() diff --git a/upub/core/src/model/actor.rs b/upub/core/src/model/actor.rs index e4b47656..c092f7d0 100644 --- a/upub/core/src/model/actor.rs +++ b/upub/core/src/model/actor.rs @@ -56,6 +56,8 @@ pub enum Relation { Likes, #[sea_orm(has_many = "super::mention::Entity")] Mentions, + #[sea_orm(has_many = "super::notification::Entity")] + Notifications, #[sea_orm(has_many = "super::object::Entity")] Objects, #[sea_orm(has_many = "super::relation::Entity")] @@ -118,6 +120,12 @@ impl Related for Entity { } } +impl Related for Entity { + fn to() -> RelationDef { + Relation::Notifications.def() + } +} + impl Related for Entity { fn to() -> RelationDef { Relation::Objects.def() diff --git a/upub/core/src/model/mod.rs b/upub/core/src/model/mod.rs index cdb408ff..b049a1af 100644 --- a/upub/core/src/model/mod.rs +++ b/upub/core/src/model/mod.rs @@ -7,10 +7,11 @@ pub mod credential; pub mod session; pub mod instance; -pub mod addressing; pub mod job; - +pub mod addressing; +pub mod notification; pub mod relation; + pub mod announce; pub mod like; pub mod dislike; diff --git a/upub/core/src/model/notification.rs b/upub/core/src/model/notification.rs new file mode 100644 index 00000000..7dc90ce5 --- /dev/null +++ b/upub/core/src/model/notification.rs @@ -0,0 +1,46 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "notifications")] +pub struct Model { + #[sea_orm(primary_key)] + pub internal: i64, + pub activity: i64, + pub actor: i64, + pub seen: bool, + pub published: ChronoDateTimeUtc, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::activity::Entity", + from = "Column::Activity", + to = "super::activity::Column::Internal", + on_update = "Cascade", + on_delete = "Cascade" + )] + Activities, + #[sea_orm( + belongs_to = "super::actor::Entity", + from = "Column::Actor", + to = "super::actor::Column::Internal", + on_update = "Cascade", + on_delete = "Cascade" + )] + Actors, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Actors.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Activities.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/upub/migrations/src/lib.rs b/upub/migrations/src/lib.rs index 96f8f029..9f66b6ee 100644 --- a/upub/migrations/src/lib.rs +++ b/upub/migrations/src/lib.rs @@ -11,6 +11,7 @@ mod m20240606_000001_add_audience_to_objects; mod m20240607_000001_activity_ref_is_optional; mod m20240609_000001_add_instance_field_to_relations; mod m20240623_000001_add_dislikes_table; +mod m20240626_000001_add_notifications_table; pub struct Migrator; @@ -29,6 +30,7 @@ impl MigratorTrait for Migrator { Box::new(m20240607_000001_activity_ref_is_optional::Migration), Box::new(m20240609_000001_add_instance_field_to_relations::Migration), Box::new(m20240623_000001_add_dislikes_table::Migration), + Box::new(m20240626_000001_add_notifications_table::Migration), ] } } diff --git a/upub/migrations/src/m20240626_000001_add_notifications_table.rs b/upub/migrations/src/m20240626_000001_add_notifications_table.rs new file mode 100644 index 00000000..30e2d189 --- /dev/null +++ b/upub/migrations/src/m20240626_000001_add_notifications_table.rs @@ -0,0 +1,78 @@ +use sea_orm_migration::prelude::*; + +use crate::m20240524_000001_create_actor_activity_object_tables::{Activities, Actors}; + +#[derive(DeriveIden)] +#[allow(clippy::enum_variant_names)] +pub enum Notifications { + Table, + Internal, + Activity, + Actor, + Seen, + Published, +} + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Notifications::Table) + .comment("notifications table, connecting activities to users") + .col( + ColumnDef::new(Notifications::Internal) + .big_integer() + .not_null() + .primary_key() + .auto_increment() + ) + .col(ColumnDef::new(Notifications::Actor).big_integer().not_null()) + .foreign_key( + ForeignKey::create() + .name("fkey-notifications-actor") + .from(Notifications::Table, Notifications::Actor) + .to(Actors::Table, Actors::Internal) + .on_update(ForeignKeyAction::Cascade) + .on_delete(ForeignKeyAction::Cascade) + ) + .col(ColumnDef::new(Notifications::Activity).big_integer().not_null()) + .foreign_key( + ForeignKey::create() + .name("fkey-notifications-activity") + .from(Notifications::Table, Notifications::Activity) + .to(Activities::Table, Activities::Internal) + .on_update(ForeignKeyAction::Cascade) + .on_delete(ForeignKeyAction::Cascade) + ) + .col(ColumnDef::new(Notifications::Seen).boolean().not_null().default(false)) + .col(ColumnDef::new(Notifications::Published).timestamp_with_time_zone().not_null().default(Expr::current_timestamp())) + .to_owned() + ) + .await?; + + manager + .create_index( + Index::create() + .name("index-notifications-actor-published") + .table(Notifications::Table) + .col(Notifications::Actor) + .col((Notifications::Published, IndexOrder::Desc)) + .to_owned() + ).await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Notifications::Table).to_owned()) + .await?; + + Ok(()) + } +}