From 0c247a8959ac5cafd8648fdf046a156547915438 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 9 Feb 2024 14:46:33 +0100 Subject: [PATCH] correctly link remote articles --- scripts/federation.sh | 19 ++++++------- src/backend/api/article.rs | 6 ++--- src/backend/config.rs | 14 ++++++++++ src/backend/database/article.rs | 23 +++++++++++----- src/common/mod.rs | 10 ++----- src/frontend/api.rs | 2 +- src/frontend/app.rs | 7 +++-- src/frontend/components/article_nav.rs | 9 ++++--- src/frontend/mod.rs | 37 ++++++++++++++++++++++++++ src/frontend/pages/article/edit.rs | 3 ++- src/frontend/pages/article/history.rs | 3 ++- src/frontend/pages/article/list.rs | 3 ++- src/frontend/pages/article/read.rs | 3 ++- src/frontend/pages/mod.rs | 9 +++++-- src/frontend/pages/search.rs | 3 ++- src/main.rs | 10 +------ tests/test.rs | 18 ++++++++----- 17 files changed, 122 insertions(+), 57 deletions(-) diff --git a/scripts/federation.sh b/scripts/federation.sh index a68dc0a..2ed1120 100755 --- a/scripts/federation.sh +++ b/scripts/federation.sh @@ -6,12 +6,12 @@ set -e # 127.0.0.1 ibis-alpha # 127.0.0.1 ibis-beta # -# Then run this script and open http://ibis-alpha:8070/, http://ibis-beta:8080/ in your browser. +# Then run this script and open http://ibis-alpha:8090/, http://ibis-beta:8091/ in your browser. function cleanup { echo "stop postgres" - ./scripts/stop_dev_db.sh $ALPHA_DB_PATH - ./scripts/stop_dev_db.sh $BETA_DB_PATH + ./scripts/stop_dev_db.sh $ALPHA_DB_PATH >/dev/null + ./scripts/stop_dev_db.sh $BETA_DB_PATH >/dev/null } trap cleanup EXIT @@ -22,18 +22,19 @@ BETA_DB_PATH="$DB_FOLDER/beta" # create db folders if they dont exist if [ ! -d $ALPHA_DB_PATH ]; then - ./scripts/start_dev_db.sh $ALPHA_DB_PATH + ./scripts/start_dev_db.sh $ALPHA_DB_PATH >/dev/null else - pg_ctl start --options="-c listen_addresses= -c unix_socket_directories=$ALPHA_DB_PATH" -D "$ALPHA_DB_PATH/dev_pgdata" + pg_ctl start --options="-c listen_addresses= -c unix_socket_directories=$ALPHA_DB_PATH" -D "$ALPHA_DB_PATH/dev_pgdata" >/dev/null fi if [ ! -d $BETA_DB_PATH ]; then - ./scripts/start_dev_db.sh $BETA_DB_PATH + ./scripts/start_dev_db.sh $BETA_DB_PATH >/dev/null else - pg_ctl start --options="-c listen_addresses= -c unix_socket_directories=$BETA_DB_PATH" -D "$BETA_DB_PATH/dev_pgdata" + pg_ctl start --options="-c listen_addresses= -c unix_socket_directories=$BETA_DB_PATH" -D "$BETA_DB_PATH/dev_pgdata" >/dev/null fi ALPHA_DB_URL="postgresql://ibis:password@/ibis?host=$ALPHA_DB_PATH" BETA_DB_URL="postgresql://ibis:password@/ibis?host=$BETA_DB_PATH" +echo $ALPHA_DB_URL # get rid of processes leftover from previous runs killall ibis || true @@ -41,9 +42,9 @@ killall ibis || true CARGO_TARGET_DIR=target/frontend trunk build # launch a couple of local instances to test federation, then wait for processes to finish -IBIS__BIND=127.0.0.1:8070 IBIS__FEDERATION__DOMAIN=ibis-alpha:8070 IBIS__DATABASE_URL=$ALPHA_DB_URL cargo run & +IBIS__BIND=127.0.0.1:8090 IBIS__FEDERATION__DOMAIN=ibis-alpha:8090 IBIS__DATABASE_URL=$ALPHA_DB_URL cargo run & PID_ALPHA=($!) -IBIS__BIND=127.0.0.1:8080 IBIS__FEDERATION__DOMAIN=ibis-beta:8080 IBIS__DATABASE_URL=$BETA_DB_URL cargo run & +IBIS__BIND=127.0.0.1:8091 IBIS__FEDERATION__DOMAIN=ibis-beta:8091 IBIS__DATABASE_URL=$BETA_DB_URL cargo run & PID_BETA=($!) wait $PID_ALPHA diff --git a/src/backend/api/article.rs b/src/backend/api/article.rs index dff542c..65083e4 100644 --- a/src/backend/api/article.rs +++ b/src/backend/api/article.rs @@ -140,12 +140,12 @@ pub(in crate::backend::api) async fn get_article( match (query.title, query.id) { (Some(title), None) => Ok(Json(DbArticle::read_view_title( &title, - &query.instance_id, + query.instance_domain, &data.db_connection, )?)), (None, Some(id)) => { - if query.instance_id.is_some() { - return Err(anyhow!("Cant combine id and instance_id").into()); + if query.instance_domain.is_some() { + return Err(anyhow!("Cant combine id and instance_domain").into()); } Ok(Json(DbArticle::read_view(id, &data.db_connection)?)) } diff --git a/src/backend/config.rs b/src/backend/config.rs index 50e863e..36d73b7 100644 --- a/src/backend/config.rs +++ b/src/backend/config.rs @@ -1,3 +1,4 @@ +use config::Config; use doku::Document; use serde::Deserialize; use smart_default::SmartDefault; @@ -23,6 +24,19 @@ pub struct IbisConfig { pub federation: IbisConfigFederation, } +impl IbisConfig { + pub fn read() -> Self { + let config = Config::builder() + .add_source(config::File::with_name("config/config.toml")) + // Cant use _ as separator due to https://github.com/mehcode/config-rs/issues/391 + .add_source(config::Environment::with_prefix("IBIS").separator("__")) + .build() + .unwrap(); + + config.try_deserialize().unwrap() + } +} + #[derive(Debug, Deserialize, PartialEq, Eq, Clone, Document, SmartDefault)] #[serde(default)] pub struct IbisConfigSetup { diff --git a/src/backend/database/article.rs b/src/backend/database/article.rs index d3aa27d..3e47879 100644 --- a/src/backend/database/article.rs +++ b/src/backend/database/article.rs @@ -1,4 +1,4 @@ -use crate::backend::database::schema::{article, edit}; +use crate::backend::database::schema::{article, edit, instance}; use crate::backend::error::MyResult; use crate::backend::federation::objects::edits_collection::DbEditCollection; use crate::common::DbEdit; @@ -77,20 +77,29 @@ impl DbArticle { pub fn read_view_title( title: &str, - instance_id: &Option, + instance_domain: Option, conn: &Mutex, ) -> MyResult { let article: DbArticle = { let mut conn = conn.lock().unwrap(); let query = article::table - .into_boxed() - .filter(article::dsl::title.eq(title)); - let query = if let Some(instance_id) = instance_id { - query.filter(article::dsl::instance_id.eq(instance_id)) + .inner_join(instance::table) + .filter(article::dsl::title.eq(title)) + .into_boxed(); + let query = if let Some(mut instance_domain) = instance_domain { + // TODO: fragile + if !instance_domain.starts_with("http") { + instance_domain = format!("http://{instance_domain}/"); + } + query + .filter(instance::dsl::ap_id.eq(instance_domain)) + .filter(instance::dsl::local.eq(false)) } else { query.filter(article::dsl::local.eq(true)) }; - query.get_result(conn.deref_mut())? + query + .select(article::all_columns) + .get_result(conn.deref_mut())? }; let latest_version = article.latest_edit_version(conn)?; let edits = DbEdit::read_for_article(&article, conn)?; diff --git a/src/common/mod.rs b/src/common/mod.rs index 7575ae2..c79825a 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -18,10 +18,10 @@ use { pub const MAIN_PAGE_NAME: &str = "Main_Page"; /// Should be an enum Title/Id but fails due to https://github.com/nox/serde_urlencoded/issues/66 -#[derive(Deserialize, Serialize, Clone)] +#[derive(Deserialize, Serialize, Clone, Debug)] pub struct GetArticleData { pub title: Option, - pub instance_id: Option, + pub instance_domain: Option, pub id: Option, } @@ -54,12 +54,6 @@ pub struct DbArticle { pub local: bool, } -impl DbArticle { - pub fn title(&self) -> String { - self.title.replace('_', " ") - } -} - /// Represents a single change to the article. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[cfg_attr(feature = "ssr", derive(Queryable, Selectable))] diff --git a/src/frontend/api.rs b/src/frontend/api.rs index 0f0ad15..3fe8907 100644 --- a/src/frontend/api.rs +++ b/src/frontend/api.rs @@ -84,7 +84,7 @@ impl ApiClient { self.get_article(GetArticleData { title: None, - instance_id: None, + instance_domain: None, id: Some(edit_form.article_id), }) .await diff --git a/src/frontend/app.rs b/src/frontend/app.rs index 10c9222..47e7595 100644 --- a/src/frontend/app.rs +++ b/src/frontend/app.rs @@ -62,12 +62,15 @@ impl GlobalState { #[component] pub fn App() -> impl IntoView { - #[allow(unused_mut, unused_assignments)] - let mut backend_hostname = "127.0.0.1:8080".to_string(); + let backend_hostname; #[cfg(not(feature = "ssr"))] { backend_hostname = web_sys::window().unwrap().location().host().unwrap(); } + #[cfg(feature = "ssr")] + { + backend_hostname = crate::backend::config::IbisConfig::read().bind.to_string(); + } provide_meta_context(); let backend_hostname = GlobalState { diff --git a/src/frontend/components/article_nav.rs b/src/frontend/components/article_nav.rs index 898063c..8a6325a 100644 --- a/src/frontend/components/article_nav.rs +++ b/src/frontend/components/article_nav.rs @@ -1,6 +1,7 @@ use crate::common::validation::can_edit_article; use crate::common::ArticleView; use crate::frontend::app::GlobalState; +use crate::frontend::article_link; use leptos::*; use leptos_router::*; @@ -10,16 +11,16 @@ pub fn ArticleNav(article: Resource, ArticleView>) -> impl IntoVi view! { {move || article.get().map(|article| { - let title = article.article.title.clone(); + let article_link = article_link(&article.article); view!{ }})} diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 07bdcb9..2685bdb 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -1,3 +1,6 @@ +use crate::common::DbArticle; +use url::Url; + pub mod api; pub mod app; mod components; @@ -7,3 +10,37 @@ pub mod pages; #[cfg(feature = "hydrate")] #[wasm_bindgen::prelude::wasm_bindgen] pub fn hydrate() {} + +fn extract_hostname(article: &DbArticle) -> String { + let ap_id: Url; + #[cfg(not(feature = "ssr"))] + { + ap_id = article.ap_id.parse().unwrap(); + } + #[cfg(feature = "ssr")] + { + ap_id = article.ap_id.inner().clone(); + } + let mut port = String::new(); + if let Some(port_) = ap_id.port() { + port = format!(":{port_}"); + } + format!("{}{port}", ap_id.host_str().unwrap()) +} + +fn article_link(article: &DbArticle) -> String { + if article.local { + format!("/article/{}", article.title) + } else { + format!("/article/{}@{}", article.title, extract_hostname(article)) + } +} + +fn article_title(article: &DbArticle) -> String { + let title = article.title.replace('_', " "); + if article.local { + title + } else { + format!("{}@{}", title, extract_hostname(article)) + } +} diff --git a/src/frontend/pages/article/edit.rs b/src/frontend/pages/article/edit.rs index 185d709..2803a8f 100644 --- a/src/frontend/pages/article/edit.rs +++ b/src/frontend/pages/article/edit.rs @@ -1,5 +1,6 @@ use crate::common::{ArticleView, EditArticleData}; use crate::frontend::app::GlobalState; +use crate::frontend::article_title; use crate::frontend::components::article_nav::ArticleNav; use crate::frontend::pages::article_resource; use leptos::*; @@ -61,7 +62,7 @@ pub fn EditArticle() -> impl IntoView { set_text.set(article.article.text.clone()); view! {
-

{article.article.title()}

+

{article_title(&article.article)}