diff --git a/migration/src/lib.rs b/migration/src/lib.rs index 9f4c38e..edaba9f 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -3,6 +3,7 @@ pub use sea_orm_migration::prelude::*; mod m20230619_221344_create_user; mod m20230620_232650_create_keypair; mod m20230625_211327_create_session; +mod m20230626_055920_create_setting; pub struct Migrator; @@ -13,6 +14,7 @@ impl MigratorTrait for Migrator { Box::new(m20230619_221344_create_user::Migration), Box::new(m20230620_232650_create_keypair::Migration), Box::new(m20230625_211327_create_session::Migration), + Box::new(m20230626_055920_create_setting::Migration), ] } } diff --git a/migration/src/m20230625_211327_create_session.rs b/migration/src/m20230625_211327_create_session.rs index 529c4ae..e10a02e 100644 --- a/migration/src/m20230625_211327_create_session.rs +++ b/migration/src/m20230625_211327_create_session.rs @@ -47,5 +47,5 @@ enum Session { Expiry, Device, Ip, - LastUsage + LastUsage, } diff --git a/migration/src/m20230626_055920_create_setting.rs b/migration/src/m20230626_055920_create_setting.rs new file mode 100644 index 0000000..187de09 --- /dev/null +++ b/migration/src/m20230626_055920_create_setting.rs @@ -0,0 +1,203 @@ +use sea_orm_migration::prelude::*; +use crate::m20230619_221344_create_user::User; + +#[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(Setting::Table) + .if_not_exists() + .col( + ColumnDef::new(Setting::Id) + .string() + .not_null() + .primary_key(), + ) + .col(ColumnDef::new(Setting::Timestamp).date_time().not_null()) + // + // Instance metadata + .col( + ColumnDef::new(Setting::Domain) + .string() + .not_null() + ) + .col( + ColumnDef::new(Setting::Name) + .string() + .not_null() + .default("Slop"), + ) + .col(ColumnDef::new(Setting::Description).string()) + .col(ColumnDef::new(Setting::ExtendedDescription).string()) + .col(ColumnDef::new(Setting::PrivacyPolicy).string()) + // The following 2 columns will later get foreign keys when files are impl + .col(ColumnDef::new(Setting::Icon).string()) + .col(ColumnDef::new(Setting::Thumbnail).string()) + // + // Contact/Support info + .col(ColumnDef::new(Setting::ContactUser).string()) + .col(ColumnDef::new(Setting::ContactEmail).string()) + // + // Instance privacy + .col( + ColumnDef::new(Setting::ShowDomainBlocks) + .boolean() + .not_null() + .default(false), + ) + .col( + ColumnDef::new(Setting::ShowDomainBlockReason) + .boolean() + .not_null() + .default(false), + ) + .col( + ColumnDef::new(Setting::RegistrationsEnabled) + .boolean() + .not_null() + .default(false), + ) + .col( + ColumnDef::new(Setting::RegistrationsRequireApproval) + .boolean() + .not_null() + .default(true), + ) + .col(ColumnDef::new(Setting::RegistrationsDisabledMessage).boolean()) + .col( + ColumnDef::new(Setting::InvitesEnabled) + .boolean() + .not_null() + .default(true), + ) + .col( + ColumnDef::new(Setting::PublishStatistics) + .boolean() + .not_null() + .default(false), + ) + // + // Limits + .col( + ColumnDef::new(Setting::MaxPostCharacters) + .big_unsigned() + .not_null() + .default(2000), + ) + .col( + ColumnDef::new(Setting::MaxPostAttachments) + .big_unsigned() + .not_null() + .default(5), + ) + .col( + ColumnDef::new(Setting::ImageSizeLimit) + .big_unsigned() + .not_null() + .default(10485760), + ) + .col( + ColumnDef::new(Setting::VideoSizeLimit) + .big_unsigned() + .not_null() + .default(16777216), + ) + .col( + ColumnDef::new(Setting::AvatarSizeLimit) + .big_unsigned() + .not_null() + .default(10485760), + ) + .col( + ColumnDef::new(Setting::BannerSizeLimit) + .big_unsigned() + .not_null() + .default(10485760), + ) + // + // Foreign Keys + .foreign_key( + ForeignKey::create() + .name("fk-setting_contact_user-user_id") + .from(Setting::Table, Setting::ContactUser) + .to(User::Table, User::Id) + ) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Setting::Table).to_owned()) + .await + } +} + +/// Learn more at https://docs.rs/sea-query#iden +#[derive(Iden)] +enum Setting { + Table, + Id, + Timestamp, + + // Instance metadata + /// The domain of the instance + Domain, + /// Name of the instance + Name, + /// Description of the instance + Description, + /// A much longer "extended" description, formatted with markdown + ExtendedDescription, + /// The privacy policy for the instance, formatted with markdown + PrivacyPolicy, + /// Object file id pointing to the icon + Icon, + /// Object file id pointing to a 2:1 "thumbnail" image + Thumbnail, + + // Contact/Support info + /// Main central "support" account for the instance + ContactUser, + /// An email for off-site support and/or legal requests + ContactEmail, + + // Instance privacy + /// Show (publicly) blocked domains + ShowDomainBlocks, + /// Show (publicly) the reasoning behind blocked domains + ShowDomainBlockReason, + /// Enable or disable registration for the instance + RegistrationsEnabled, + /// Require approval by staff when registering + RegistrationsRequireApproval, + /// Message to show when registrations are disabled + RegistrationsDisabledMessage, + InvitesEnabled, + /// Publish instance statistics to the API (in weekly increments) + /// This includes: + /// * Locally published posts + /// * Active users + /// * New users + PublishStatistics, + + // Limits + /// Max amount of characters a post can have + MaxPostCharacters, + /// Max amount of attachments (images and videos) a post can have + MaxPostAttachments, + /// Max file size for an image uploaded as an attachment + ImageSizeLimit, + /// Max file size for a video uploaded as an attachment + VideoSizeLimit, + /// Maximum file size for a user's avatar + AvatarSizeLimit, + /// Maximum file size for a user's banner + BannerSizeLimit, +} diff --git a/slop-common/src/db/entities/mod.rs b/slop-common/src/db/entities/mod.rs index 0336908..8623e33 100644 --- a/slop-common/src/db/entities/mod.rs +++ b/slop-common/src/db/entities/mod.rs @@ -4,4 +4,5 @@ pub mod prelude; pub mod key_pair; pub mod session; +pub mod setting; pub mod user; diff --git a/slop-common/src/db/entities/prelude.rs b/slop-common/src/db/entities/prelude.rs index f9aa167..a49fc46 100644 --- a/slop-common/src/db/entities/prelude.rs +++ b/slop-common/src/db/entities/prelude.rs @@ -2,4 +2,5 @@ pub use super::key_pair::Entity as KeyPair; pub use super::session::Entity as Session; +pub use super::setting::Entity as Setting; pub use super::user::Entity as User; diff --git a/slop-common/src/db/entities/setting.rs b/slop-common/src/db/entities/setting.rs new file mode 100644 index 0000000..9dd113d --- /dev/null +++ b/slop-common/src/db/entities/setting.rs @@ -0,0 +1,53 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "setting")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub timestamp: DateTime, + pub domain: String, + pub name: String, + pub description: Option, + pub extended_description: Option, + pub privacy_policy: Option, + pub icon: Option, + pub thumbnail: Option, + pub contact_user: Option, + pub contact_email: Option, + pub show_domain_blocks: bool, + pub show_domain_block_reason: bool, + pub registrations_enabled: bool, + pub registrations_require_approval: bool, + pub registrations_disabled_message: Option, + pub invites_enabled: bool, + pub publish_statistics: bool, + pub max_post_characters: i64, + pub max_post_attachments: i64, + pub image_size_limit: i64, + pub video_size_limit: i64, + pub avatar_size_limit: i64, + pub banner_size_limit: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::ContactUser", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/slop-common/src/db/entities/user.rs b/slop-common/src/db/entities/user.rs index b641085..eb28be9 100644 --- a/slop-common/src/db/entities/user.rs +++ b/slop-common/src/db/entities/user.rs @@ -30,6 +30,8 @@ pub struct Model { pub enum Relation { #[sea_orm(has_many = "super::key_pair::Entity")] KeyPair, + #[sea_orm(has_many = "super::setting::Entity")] + Setting, } impl Related for Entity { @@ -38,4 +40,10 @@ impl Related for Entity { } } +impl Related for Entity { + fn to() -> RelationDef { + Relation::Setting.def() + } +} + impl ActiveModelBehavior for ActiveModel {} diff --git a/slop-common/src/db/mod.rs b/slop-common/src/db/mod.rs index 0b8f0b5..fc7fd10 100644 --- a/slop-common/src/db/mod.rs +++ b/slop-common/src/db/mod.rs @@ -1 +1,14 @@ +use sea_orm::{DatabaseConnection, EntityTrait, QueryOrder}; +use crate::db::entities::prelude::Setting; +use crate::db::entities::setting; + pub mod entities; + +pub async fn get_config(conn: &DatabaseConnection) -> setting::Model { + Setting::find() + .order_by_desc(setting::Column::Id) + .one(conn) + .await + .expect("Failed to access the database.") + .expect("No settings entry found?") +} \ No newline at end of file