diff --git a/src/backend/api/article.rs b/src/backend/api/article.rs index b203ed1..e36403c 100644 --- a/src/backend/api/article.rs +++ b/src/backend/api/article.rs @@ -1,17 +1,17 @@ -use crate::backend::api::ResolveObject; use crate::backend::database::article::DbArticleForm; -use crate::backend::database::conflict::{ApiConflict, DbConflict, DbConflictForm}; +use crate::backend::database::conflict::{DbConflict, DbConflictForm}; use crate::backend::database::edit::DbEditForm; -use crate::backend::database::instance::DbInstance; use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; use crate::backend::federation::activities::create_article::CreateArticle; use crate::backend::federation::activities::submit_article_update; use crate::backend::utils::generate_article_version; -use crate::common::EditVersion; +use crate::common::DbInstance; use crate::common::GetArticleData; use crate::common::LocalUserView; +use crate::common::{ApiConflict, ResolveObject}; use crate::common::{ArticleView, DbArticle, DbEdit}; +use crate::common::{CreateArticleData, EditArticleData, EditVersion, ForkArticleData}; use activitypub_federation::config::Data; use activitypub_federation::fetch::object_id::ObjectId; use anyhow::anyhow; @@ -21,12 +21,6 @@ use axum::Form; use axum::Json; use axum_macros::debug_handler; use diffy::create_patch; -use serde::{Deserialize, Serialize}; - -#[derive(Deserialize, Serialize)] -pub struct CreateArticleData { - pub title: String, -} /// Create a new article with empty text, and federate it to followers. #[debug_handler] @@ -56,20 +50,6 @@ pub(in crate::backend::api) async fn create_article( Ok(Json(DbArticle::read_view(article.id, &data.db_connection)?)) } -#[derive(Deserialize, Serialize, Debug)] -pub struct EditArticleData { - /// Id of the article to edit - pub article_id: i32, - /// Full, new text of the article. A diff against `previous_version` is generated on the backend - /// side to handle conflicts. - pub new_text: String, - /// The version that this edit is based on, ie [DbArticle.latest_version] or - /// [ApiConflict.previous_version] - pub previous_version_id: EditVersion, - /// If you are resolving a conflict, pass the id to delete conflict from the database - pub resolve_conflict_id: Option, -} - /// Edit an existing article (local or remote). /// /// It gracefully handles the case where multiple users edit an article at the same time, by @@ -144,14 +124,6 @@ pub(in crate::backend::api) async fn get_article( } } -#[derive(Deserialize, Serialize)] -pub struct ForkArticleData { - // TODO: could add optional param new_title so there is no problem with title collision - // in case local article with same title exists. however that makes it harder to discover - // variants of same article. - pub article_id: i32, -} - /// Fork a remote article to local instance. This is useful if there are disagreements about /// how an article should be edited. #[debug_handler] diff --git a/src/backend/api/instance.rs b/src/backend/api/instance.rs index 7e7f688..c8ba0bc 100644 --- a/src/backend/api/instance.rs +++ b/src/backend/api/instance.rs @@ -1,16 +1,14 @@ -use crate::backend::api::ResolveObject; -use crate::backend::database::instance::{DbInstance, InstanceView}; use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; use crate::backend::federation::activities::follow::Follow; -use crate::common::LocalUserView; +use crate::common::{DbInstance, InstanceView, ResolveObject}; +use crate::common::{FollowInstance, LocalUserView}; use activitypub_federation::config::Data; use activitypub_federation::fetch::object_id::ObjectId; use axum::extract::Query; use axum::Extension; use axum::{Form, Json}; use axum_macros::debug_handler; -use serde::{Deserialize, Serialize}; /// Retrieve the local instance info. #[debug_handler] @@ -21,11 +19,6 @@ pub(in crate::backend::api) async fn get_local_instance( Ok(Json(local_instance)) } -#[derive(Deserialize, Serialize, Debug)] -pub struct FollowInstance { - pub id: i32, -} - /// Make the local instance follow a given remote instance, to receive activities about new and /// updated articles. #[debug_handler] diff --git a/src/backend/api/mod.rs b/src/backend/api/mod.rs index 0dd5ced..192831c 100644 --- a/src/backend/api/mod.rs +++ b/src/backend/api/mod.rs @@ -6,11 +6,11 @@ use crate::backend::api::user::register_user; use crate::backend::api::user::validate; use crate::backend::api::user::{login_user, logout_user}; use crate::backend::api::user::{my_profile, AUTH_COOKIE}; -use crate::backend::database::conflict::{ApiConflict, DbConflict}; +use crate::backend::database::conflict::DbConflict; use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; -use crate::common::DbArticle; use crate::common::LocalUserView; +use crate::common::{ApiConflict, DbArticle, SearchArticleData}; use activitypub_federation::config::Data; use axum::extract::Query; use axum::routing::{get, post}; @@ -26,8 +26,6 @@ use axum_extra::extract::CookieJar; use axum_macros::debug_handler; use futures::future::try_join_all; use log::warn; -use serde::{Deserialize, Serialize}; -use url::Url; pub mod article; pub mod instance; @@ -70,11 +68,6 @@ async fn auth( Ok(response) } -#[derive(Deserialize, Serialize)] -pub struct ResolveObject { - pub id: Url, -} - /// Get a list of all unresolved edit conflicts. #[debug_handler] async fn edit_conflicts( @@ -93,11 +86,6 @@ async fn edit_conflicts( Ok(Json(conflicts)) } -#[derive(Deserialize, Serialize, Clone)] -pub struct SearchArticleData { - pub query: String, -} - /// Search articles for matching title or body text. #[debug_handler] async fn search_article( diff --git a/src/backend/database/conflict.rs b/src/backend/database/conflict.rs index 2f6f2d5..fc61b14 100644 --- a/src/backend/database/conflict.rs +++ b/src/backend/database/conflict.rs @@ -3,10 +3,10 @@ use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; use crate::backend::federation::activities::submit_article_update; use crate::backend::utils::generate_article_version; -use crate::common::DbArticle; use crate::common::DbEdit; use crate::common::DbLocalUser; use crate::common::EditVersion; +use crate::common::{ApiConflict, DbArticle}; use activitypub_federation::config::Data; use diesel::ExpressionMethods; use diesel::{ @@ -30,14 +30,6 @@ pub struct DbConflict { pub previous_version_id: EditVersion, } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] -pub struct ApiConflict { - pub id: EditVersion, - pub three_way_merge: String, - pub article_id: i32, - pub previous_version_id: EditVersion, -} - #[derive(Debug, Clone, Insertable)] #[diesel(table_name = conflict, check_for_backend(diesel::pg::Pg))] pub struct DbConflictForm { diff --git a/src/backend/database/instance.rs b/src/backend/database/instance.rs index a805fd2..f0439b6 100644 --- a/src/backend/database/instance.rs +++ b/src/backend/database/instance.rs @@ -2,37 +2,19 @@ use crate::backend::database::schema::{instance, instance_follow}; use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; use crate::backend::federation::objects::articles_collection::DbArticleCollection; -use crate::common::DbPerson; +use crate::common::{DbInstance, DbPerson, InstanceView}; use activitypub_federation::config::Data; use activitypub_federation::fetch::collection_id::CollectionId; use activitypub_federation::fetch::object_id::ObjectId; use chrono::{DateTime, Utc}; use diesel::ExpressionMethods; use diesel::{ - insert_into, AsChangeset, Identifiable, Insertable, JoinOnDsl, PgConnection, QueryDsl, - Queryable, RunQueryDsl, Selectable, + insert_into, AsChangeset, Insertable, JoinOnDsl, PgConnection, QueryDsl, RunQueryDsl, }; -use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::ops::DerefMut; use std::sync::Mutex; -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable, Selectable, Identifiable)] -#[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))] -pub struct DbInstance { - pub id: i32, - pub ap_id: ObjectId, - pub articles_url: CollectionId, - pub inbox_url: String, - #[serde(skip)] - pub public_key: String, - #[serde(skip)] - pub private_key: Option, - #[serde(skip)] - pub last_refreshed_at: DateTime, - pub local: bool, -} - #[derive(Debug, Clone, Insertable, AsChangeset)] #[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))] pub struct DbInstanceForm { @@ -45,14 +27,6 @@ pub struct DbInstanceForm { pub local: bool, } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable)] -#[diesel(table_name = article, check_for_backend(diesel::pg::Pg))] -pub struct InstanceView { - pub instance: DbInstance, - pub followers: Vec, - pub following: Vec, -} - impl DbInstance { pub fn create(form: &DbInstanceForm, conn: &Mutex) -> MyResult { let mut conn = conn.lock().unwrap(); diff --git a/src/backend/federation/activities/accept.rs b/src/backend/federation/activities/accept.rs index 4b628a0..65fad0e 100644 --- a/src/backend/federation/activities/accept.rs +++ b/src/backend/federation/activities/accept.rs @@ -1,8 +1,8 @@ -use crate::backend::database::instance::DbInstance; use crate::backend::error::MyResult; use crate::backend::federation::send_activity; use crate::backend::utils::generate_activity_id; use crate::backend::{database::MyDataHandle, federation::activities::follow::Follow}; +use crate::common::DbInstance; use activitypub_federation::traits::Actor; use activitypub_federation::{ config::Data, fetch::object_id::ObjectId, kinds::activity::AcceptType, traits::ActivityHandler, diff --git a/src/backend/federation/activities/create_article.rs b/src/backend/federation/activities/create_article.rs index bb286ea..2ef32e8 100644 --- a/src/backend/federation/activities/create_article.rs +++ b/src/backend/federation/activities/create_article.rs @@ -1,9 +1,9 @@ -use crate::backend::database::instance::DbInstance; use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; use crate::backend::federation::objects::article::ApubArticle; use crate::backend::utils::generate_activity_id; use crate::common::DbArticle; +use crate::common::DbInstance; use activitypub_federation::kinds::activity::CreateType; use activitypub_federation::{ config::Data, diff --git a/src/backend/federation/activities/follow.rs b/src/backend/federation/activities/follow.rs index 9397593..522acdb 100644 --- a/src/backend/federation/activities/follow.rs +++ b/src/backend/federation/activities/follow.rs @@ -1,9 +1,9 @@ -use crate::backend::database::instance::DbInstance; use crate::backend::error::MyResult; use crate::backend::federation::send_activity; use crate::backend::{ database::MyDataHandle, federation::activities::accept::Accept, generate_activity_id, }; +use crate::common::DbInstance; use crate::common::DbPerson; use activitypub_federation::{ config::Data, diff --git a/src/backend/federation/activities/mod.rs b/src/backend/federation/activities/mod.rs index d30f69b..c3b68b8 100644 --- a/src/backend/federation/activities/mod.rs +++ b/src/backend/federation/activities/mod.rs @@ -1,9 +1,9 @@ use crate::backend::database::edit::DbEditForm; -use crate::backend::database::instance::DbInstance; use crate::backend::database::MyDataHandle; use crate::backend::error::Error; use crate::backend::federation::activities::update_local_article::UpdateLocalArticle; use crate::backend::federation::activities::update_remote_article::UpdateRemoteArticle; +use crate::common::DbInstance; use crate::common::EditVersion; use crate::common::{DbArticle, DbEdit}; use activitypub_federation::config::Data; diff --git a/src/backend/federation/activities/reject.rs b/src/backend/federation/activities/reject.rs index 068eae7..a8a41b1 100644 --- a/src/backend/federation/activities/reject.rs +++ b/src/backend/federation/activities/reject.rs @@ -1,9 +1,9 @@ use crate::backend::database::conflict::{DbConflict, DbConflictForm}; -use crate::backend::database::instance::DbInstance; use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; use crate::backend::federation::objects::edit::ApubEdit; use crate::backend::utils::generate_activity_id; +use crate::common::DbInstance; use crate::common::EditVersion; use activitypub_federation::kinds::activity::RejectType; use activitypub_federation::{ diff --git a/src/backend/federation/activities/update_local_article.rs b/src/backend/federation/activities/update_local_article.rs index 2c4d2c0..a14162d 100644 --- a/src/backend/federation/activities/update_local_article.rs +++ b/src/backend/federation/activities/update_local_article.rs @@ -2,8 +2,8 @@ use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; use crate::backend::federation::objects::article::ApubArticle; -use crate::backend::database::instance::DbInstance; use crate::backend::utils::generate_activity_id; +use crate::common::DbInstance; use activitypub_federation::kinds::activity::UpdateType; use activitypub_federation::{ config::Data, diff --git a/src/backend/federation/activities/update_remote_article.rs b/src/backend/federation/activities/update_remote_article.rs index 9e2d9fc..33897b7 100644 --- a/src/backend/federation/activities/update_remote_article.rs +++ b/src/backend/federation/activities/update_remote_article.rs @@ -1,7 +1,6 @@ use crate::backend::database::MyDataHandle; use crate::backend::error::MyResult; -use crate::backend::database::instance::DbInstance; use crate::backend::federation::activities::reject::RejectEdit; use crate::backend::federation::activities::update_local_article::UpdateLocalArticle; use crate::backend::federation::objects::edit::ApubEdit; @@ -9,6 +8,7 @@ use crate::backend::federation::send_activity; use crate::backend::utils::generate_activity_id; use crate::common::DbArticle; use crate::common::DbEdit; +use crate::common::DbInstance; use activitypub_federation::kinds::activity::UpdateType; use activitypub_federation::{ config::Data, diff --git a/src/backend/federation/objects/article.rs b/src/backend/federation/objects/article.rs index 0e45de6..faafb26 100644 --- a/src/backend/federation/objects/article.rs +++ b/src/backend/federation/objects/article.rs @@ -1,9 +1,9 @@ use crate::backend::database::article::DbArticleForm; -use crate::backend::database::instance::DbInstance; use crate::backend::database::MyDataHandle; use crate::backend::error::Error; use crate::backend::federation::objects::edits_collection::DbEditCollection; use crate::common::DbArticle; +use crate::common::DbInstance; use crate::common::EditVersion; use activitypub_federation::config::Data; use activitypub_federation::fetch::collection_id::CollectionId; diff --git a/src/backend/federation/objects/articles_collection.rs b/src/backend/federation/objects/articles_collection.rs index 1463ddf..f3e4780 100644 --- a/src/backend/federation/objects/articles_collection.rs +++ b/src/backend/federation/objects/articles_collection.rs @@ -1,7 +1,7 @@ -use crate::backend::database::instance::DbInstance; use crate::backend::database::MyDataHandle; use crate::backend::error::Error; use crate::backend::federation::objects::article::ApubArticle; +use crate::common::DbInstance; use crate::common::DbArticle; use activitypub_federation::kinds::collection::CollectionType; diff --git a/src/backend/federation/objects/edits_collection.rs b/src/backend/federation/objects/edits_collection.rs index 3336213..8a8789b 100644 --- a/src/backend/federation/objects/edits_collection.rs +++ b/src/backend/federation/objects/edits_collection.rs @@ -3,8 +3,8 @@ use crate::backend::error::Error; use crate::backend::federation::objects::edit::ApubEdit; use crate::common::DbArticle; -use crate::backend::database::instance::DbInstance; use crate::common::DbEdit; +use crate::common::DbInstance; use activitypub_federation::kinds::collection::OrderedCollectionType; use activitypub_federation::{ config::Data, diff --git a/src/backend/federation/objects/instance.rs b/src/backend/federation/objects/instance.rs index a5ee0ef..48bee38 100644 --- a/src/backend/federation/objects/instance.rs +++ b/src/backend/federation/objects/instance.rs @@ -1,4 +1,4 @@ -use crate::backend::database::instance::{DbInstance, DbInstanceForm}; +use crate::backend::database::instance::DbInstanceForm; use crate::backend::database::MyDataHandle; use crate::backend::error::Error; use crate::backend::federation::objects::articles_collection::DbArticleCollection; @@ -8,6 +8,7 @@ use activitypub_federation::fetch::collection_id::CollectionId; use activitypub_federation::kinds::actor::ServiceType; use crate::backend::error::MyResult; +use crate::common::DbInstance; use activitypub_federation::traits::ActivityHandler; use activitypub_federation::{ config::Data, diff --git a/src/backend/federation/routes.rs b/src/backend/federation/routes.rs index 390073a..f30f6ab 100644 --- a/src/backend/federation/routes.rs +++ b/src/backend/federation/routes.rs @@ -1,4 +1,3 @@ -use crate::backend::database::instance::DbInstance; use crate::backend::database::MyDataHandle; use crate::backend::error::Error; use crate::backend::error::MyResult; @@ -16,6 +15,7 @@ use crate::backend::federation::objects::edits_collection::{ApubEditCollection, use crate::backend::federation::objects::instance::ApubInstance; use crate::backend::federation::objects::user::ApubUser; use crate::common::DbArticle; +use crate::common::DbInstance; use crate::common::DbPerson; use activitypub_federation::axum::inbox::{receive_activity, ActivityData}; use activitypub_federation::axum::json::FederationJson; diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 0912133..1986cfa 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,10 +1,10 @@ use crate::backend::database::article::DbArticleForm; -use crate::backend::database::instance::{DbInstance, DbInstanceForm}; +use crate::backend::database::instance::DbInstanceForm; use crate::backend::database::MyData; use crate::backend::error::MyResult; use crate::backend::federation::routes::federation_routes; use crate::backend::utils::generate_activity_id; -use crate::common::DbArticle; +use crate::common::{DbArticle, DbInstance}; use crate::frontend::app::App; use activitypub_federation::config::{FederationConfig, FederationMiddleware}; use activitypub_federation::fetch::collection_id::CollectionId; diff --git a/src/common/mod.rs b/src/common/mod.rs index 2cc101c..8d176a1 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,10 +1,14 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use url::Url; use uuid::Uuid; #[cfg(feature = "ssr")] use { - crate::backend::database::schema::{article, edit, local_user, person}, - activitypub_federation::fetch::object_id::ObjectId, + crate::backend::{ + database::schema::{article, edit, instance, local_user, person}, + federation::objects::articles_collection::DbArticleCollection, + }, + activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId}, diesel::{Identifiable, Queryable, Selectable}, }; @@ -117,3 +121,85 @@ pub struct DbPerson { pub last_refreshed_at: DateTime, pub local: bool, } + +#[derive(Deserialize, Serialize)] +pub struct CreateArticleData { + pub title: String, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct EditArticleData { + /// Id of the article to edit + pub article_id: i32, + /// Full, new text of the article. A diff against `previous_version` is generated on the backend + /// side to handle conflicts. + pub new_text: String, + /// The version that this edit is based on, ie [DbArticle.latest_version] or + /// [ApiConflict.previous_version] + pub previous_version_id: EditVersion, + /// If you are resolving a conflict, pass the id to delete conflict from the database + pub resolve_conflict_id: Option, +} + +#[derive(Deserialize, Serialize)] +pub struct ForkArticleData { + // TODO: could add optional param new_title so there is no problem with title collision + // in case local article with same title exists. however that makes it harder to discover + // variants of same article. + pub article_id: i32, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct FollowInstance { + pub id: i32, +} + +#[derive(Deserialize, Serialize, Clone)] +pub struct SearchArticleData { + pub query: String, +} + +#[derive(Deserialize, Serialize)] +pub struct ResolveObject { + pub id: Url, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct ApiConflict { + pub id: EditVersion, + pub three_way_merge: String, + pub article_id: i32, + pub previous_version_id: EditVersion, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))] +#[cfg_attr(feature = "ssr", diesel(table_name = instance, check_for_backend(diesel::pg::Pg)))] +pub struct DbInstance { + pub id: i32, + #[cfg(feature = "ssr")] + pub ap_id: ObjectId, + #[cfg(not(feature = "ssr"))] + pub ap_id: String, + #[cfg(feature = "ssr")] + pub articles_url: CollectionId, + #[cfg(not(feature = "ssr"))] + pub articles_url: String, + pub inbox_url: String, + #[serde(skip)] + pub public_key: String, + #[serde(skip)] + pub private_key: Option, + #[serde(skip)] + pub last_refreshed_at: DateTime, + pub local: bool, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[cfg_attr(feature = "ssr", derive(Queryable))] +#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg)))] +pub struct InstanceView { + pub instance: DbInstance, + pub followers: Vec, + pub following: Vec, +} diff --git a/src/frontend/api.rs b/src/frontend/api.rs index d251529..f8d2363 100644 --- a/src/frontend/api.rs +++ b/src/frontend/api.rs @@ -1,11 +1,9 @@ -use crate::backend::api::article::{CreateArticleData, EditArticleData, ForkArticleData}; -use crate::backend::api::instance::FollowInstance; -use crate::backend::api::{ResolveObject, SearchArticleData}; -use crate::backend::database::conflict::ApiConflict; -use crate::backend::database::instance::{DbInstance, InstanceView}; -use crate::common::LocalUserView; +use crate::common::ApiConflict; +use crate::common::ResolveObject; use crate::common::{ArticleView, LoginUserData, RegisterUserData}; +use crate::common::{CreateArticleData, EditArticleData, ForkArticleData, LocalUserView}; use crate::common::{DbArticle, GetArticleData}; +use crate::common::{DbInstance, FollowInstance, InstanceView, SearchArticleData}; use crate::frontend::error::MyResult; use anyhow::anyhow; use once_cell::sync::Lazy; diff --git a/tests/common.rs b/tests/common.rs index 83e17f3..d192609 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -3,10 +3,8 @@ use ibis_lib::backend::start; use ibis_lib::common::RegisterUserData; use ibis_lib::frontend::api::ApiClient; use ibis_lib::frontend::error::MyResult; - use reqwest::cookie::Jar; use reqwest::ClientBuilder; - use std::env::current_dir; use std::fs::create_dir_all; use std::ops::Deref; diff --git a/tests/test.rs b/tests/test.rs index b5cdaff..89b7583 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -3,9 +3,8 @@ extern crate ibis_lib; mod common; use crate::common::{TestData, TEST_ARTICLE_DEFAULT_TEXT}; -use ibis_lib::backend::api::article::{EditArticleData, ForkArticleData}; -use ibis_lib::backend::api::SearchArticleData; -use ibis_lib::common::{ArticleView, GetArticleData}; +use ibis_lib::common::SearchArticleData; +use ibis_lib::common::{ArticleView, EditArticleData, ForkArticleData, GetArticleData}; use ibis_lib::common::{LoginUserData, RegisterUserData}; use ibis_lib::frontend::error::MyResult; use pretty_assertions::{assert_eq, assert_ne};