diff --git a/src/activitypub/mod.rs b/src/activitypub/mod.rs index 2c364461..c9d90a45 100644 --- a/src/activitypub/mod.rs +++ b/src/activitypub/mod.rs @@ -12,7 +12,7 @@ use axum::{extract::State, http::StatusCode, Json}; use rand::Rng; use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter}; -use crate::{activitystream::{object::{actor::{ActorMut, ActorType}, ObjectMut}, BaseMut}, model, server::Context, url}; +use crate::{activitystream::{key::PublicKeyMut, object::{actor::{ActorMut, ActorType}, ObjectMut}, BaseMut, Node}, model, server::Context, url}; use self::jsonld::LD; @@ -47,12 +47,17 @@ pub struct Pagination { pub async fn view(State(ctx): State) -> Result, StatusCode> { Ok(Json( serde_json::Value::new_object() - .set_actor_type(Some(ActorType::Application)) .set_id(Some(&url!(ctx, ""))) + .set_actor_type(Some(ActorType::Application)) .set_name(Some("μpub")) .set_summary(Some("micro social network, federated")) - // .set_inbox(Node::link(url!(ctx, "/inbox"))) - // .set_outbox(Node::link(url!(ctx, "/outbox"))) + .set_published(Some(ctx.app().created)) + .set_public_key(Node::object( + serde_json::Value::new_object() + .set_id(Some(&url!(ctx, "#main-key"))) + .set_owner(Some(ctx.base())) + .set_public_key_pem(&ctx.app().public_key) + )) .ld_context() )) } diff --git a/src/migrations/m20240325_000002_add_system_key.rs b/src/migrations/m20240325_000002_add_system_key.rs index eacfa5d3..dbd1954b 100644 --- a/src/migrations/m20240325_000002_add_system_key.rs +++ b/src/migrations/m20240325_000002_add_system_key.rs @@ -19,6 +19,7 @@ impl MigrationTrait for Migration { ) .col(ColumnDef::new(Application::PrivateKey).string().not_null()) .col(ColumnDef::new(Application::PublicKey).string().not_null()) + .col(ColumnDef::new(Application::Created).date_time().not_null()) .to_owned() ) .await?; @@ -41,4 +42,5 @@ enum Application { Id, PrivateKey, PublicKey, + Created, } diff --git a/src/model/application.rs b/src/model/application.rs index ecb1c42e..cde98aac 100644 --- a/src/model/application.rs +++ b/src/model/application.rs @@ -8,6 +8,8 @@ pub struct Model { pub private_key: String, pub public_key: String, + + pub created: ChronoDateTimeUtc, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/server.rs b/src/server.rs index d19f637d..11b31574 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,7 +1,7 @@ use std::{str::Utf8Error, sync::Arc}; use openssl::rsa::Rsa; -use sea_orm::{DatabaseConnection, DbErr, EntityTrait, QuerySelect, SelectColumns}; +use sea_orm::{DatabaseConnection, DbErr, EntityTrait}; use crate::{dispatcher::Dispatcher, fetcher::Fetcher, model}; @@ -13,8 +13,7 @@ struct ContextInner { protocol: String, fetcher: Fetcher, // TODO keep these pre-parsed - public_key: String, - private_key: String, + app: model::application::Model, } #[macro_export] @@ -49,14 +48,8 @@ impl Context { for _ in 0..1 { // TODO customize delivery workers amount Dispatcher::spawn(db.clone(), domain.clone(), 30); // TODO ew don't do it this deep and secretly!! } - let (public_key, private_key) = match model::application::Entity::find() - .select_only() - .select_column(model::application::Column::PublicKey) - .select_column(model::application::Column::PrivateKey) - .one(&db) - .await? - { - Some(model) => (model.public_key, model.private_key), + let app = match model::application::Entity::find().one(&db).await? { + Some(model) => model, None => { tracing::info!("generating application keys"); let rsa = Rsa::generate(2048)?; @@ -66,19 +59,25 @@ impl Context { id: sea_orm::ActiveValue::NotSet, private_key: sea_orm::ActiveValue::Set(privk.clone()), public_key: sea_orm::ActiveValue::Set(pubk.clone()), + created: sea_orm::ActiveValue::Set(chrono::Utc::now()), }; model::application::Entity::insert(system).exec(&db).await?; - (pubk, privk) + // sqlite doesn't resurn last inserted id so we're better off just querying again, it's just one time + model::application::Entity::find().one(&db).await?.expect("could not find app config just inserted") } }; - let fetcher = Fetcher::new(db.clone(), domain.clone(), private_key.clone()); + let fetcher = Fetcher::new(db.clone(), domain.clone(), app.private_key.clone()); Ok(Context(Arc::new(ContextInner { - db, domain, protocol, private_key, public_key, fetcher, + db, domain, protocol, app, fetcher, }))) } + pub fn app(&self) -> &model::application::Model { + &self.0.app + } + pub fn db(&self) -> &DatabaseConnection { &self.0.db }