mirror of
https://github.com/Nutomic/ibis.git
synced 2025-02-04 02:41:36 +00:00
Also split up files in src/common.rs
This commit is contained in:
parent
95ee090275
commit
0194ddf663
51 changed files with 504 additions and 448 deletions
|
@ -11,25 +11,27 @@ use crate::{
|
||||||
utils::{error::MyResult, generate_article_version},
|
utils::{error::MyResult, generate_article_version},
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
article::{
|
||||||
|
ApiConflict,
|
||||||
|
ApproveArticleForm,
|
||||||
|
ArticleView,
|
||||||
|
CreateArticleForm,
|
||||||
|
DbArticle,
|
||||||
|
DbEdit,
|
||||||
|
DeleteConflictForm,
|
||||||
|
EditArticleForm,
|
||||||
|
EditVersion,
|
||||||
|
ForkArticleForm,
|
||||||
|
GetArticleForm,
|
||||||
|
ListArticlesForm,
|
||||||
|
ProtectArticleForm,
|
||||||
|
SearchArticleForm,
|
||||||
|
},
|
||||||
|
instance::DbInstance,
|
||||||
|
user::LocalUserView,
|
||||||
utils::{extract_domain, http_protocol_str},
|
utils::{extract_domain, http_protocol_str},
|
||||||
validation::can_edit_article,
|
validation::can_edit_article,
|
||||||
ApiConflict,
|
|
||||||
ApproveArticleForm,
|
|
||||||
ArticleView,
|
|
||||||
CreateArticleForm,
|
|
||||||
DbArticle,
|
|
||||||
DbEdit,
|
|
||||||
DbInstance,
|
|
||||||
DeleteConflictForm,
|
|
||||||
EditArticleForm,
|
|
||||||
EditVersion,
|
|
||||||
ForkArticleForm,
|
|
||||||
GetArticleForm,
|
|
||||||
ListArticlesForm,
|
|
||||||
LocalUserView,
|
|
||||||
ProtectArticleForm,
|
|
||||||
ResolveObject,
|
ResolveObject,
|
||||||
SearchArticleForm,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
|
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{database::IbisData, federation::activities::follow::Follow, utils::error::MyResult},
|
backend::{database::IbisData, federation::activities::follow::Follow, utils::error::MyResult},
|
||||||
common::{
|
common::{
|
||||||
DbInstance,
|
instance::{DbInstance, FollowInstance, GetInstance, InstanceView},
|
||||||
FollowInstance,
|
user::LocalUserView,
|
||||||
GetInstance,
|
|
||||||
InstanceView,
|
|
||||||
LocalUserView,
|
|
||||||
ResolveObject,
|
ResolveObject,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,7 +18,11 @@ use crate::{
|
||||||
database::IbisData,
|
database::IbisData,
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
},
|
},
|
||||||
common::{DbEdit, EditView, GetEditList, LocalUserView, SiteView},
|
common::{
|
||||||
|
article::{DbEdit, EditView, GetEditList},
|
||||||
|
instance::SiteView,
|
||||||
|
user::LocalUserView,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
|
|
@ -5,15 +5,17 @@ use crate::{
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
DbArticle,
|
article::DbArticle,
|
||||||
DbPerson,
|
user::{
|
||||||
GetUserForm,
|
DbPerson,
|
||||||
LocalUserView,
|
GetUserForm,
|
||||||
LoginUserForm,
|
LocalUserView,
|
||||||
|
LoginUserForm,
|
||||||
|
RegisterUserForm,
|
||||||
|
UpdateUserForm,
|
||||||
|
},
|
||||||
Notification,
|
Notification,
|
||||||
RegisterUserForm,
|
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
UpdateUserForm,
|
|
||||||
AUTH_COOKIE,
|
AUTH_COOKIE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{backend::utils::error::MyResult, common::Options};
|
use crate::{backend::utils::error::MyResult, common::instance::Options};
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use doku::Document;
|
use doku::Document;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
|
@ -8,11 +8,9 @@ use crate::{
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
article::{ArticleView, DbArticle, EditVersion},
|
||||||
|
instance::DbInstance,
|
||||||
newtypes::{ArticleId, InstanceId},
|
newtypes::{ArticleId, InstanceId},
|
||||||
ArticleView,
|
|
||||||
DbArticle,
|
|
||||||
DbInstance,
|
|
||||||
EditVersion,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId};
|
use activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId};
|
||||||
|
|
|
@ -5,12 +5,9 @@ use crate::{
|
||||||
utils::{error::MyResult, generate_article_version},
|
utils::{error::MyResult, generate_article_version},
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
article::{ApiConflict, DbArticle, DbEdit, EditVersion},
|
||||||
newtypes::{ArticleId, ConflictId, PersonId},
|
newtypes::{ArticleId, ConflictId, PersonId},
|
||||||
ApiConflict,
|
user::DbPerson,
|
||||||
DbArticle,
|
|
||||||
DbEdit,
|
|
||||||
DbPerson,
|
|
||||||
EditVersion,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
|
|
|
@ -5,11 +5,8 @@ use crate::{
|
||||||
IbisData,
|
IbisData,
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
article::{DbArticle, DbEdit, EditVersion, EditView},
|
||||||
newtypes::{ArticleId, PersonId},
|
newtypes::{ArticleId, PersonId},
|
||||||
DbArticle,
|
|
||||||
DbEdit,
|
|
||||||
EditVersion,
|
|
||||||
EditView,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::fetch::object_id::ObjectId;
|
use activitypub_federation::fetch::object_id::ObjectId;
|
||||||
|
|
|
@ -10,7 +10,11 @@ use crate::{
|
||||||
},
|
},
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
},
|
},
|
||||||
common::{newtypes::InstanceId, DbInstance, DbPerson, InstanceView},
|
common::{
|
||||||
|
instance::{DbInstance, InstanceView},
|
||||||
|
newtypes::InstanceId,
|
||||||
|
user::DbPerson,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -7,13 +7,10 @@ use crate::{
|
||||||
utils::{error::MyResult, generate_keypair},
|
utils::{error::MyResult, generate_keypair},
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
instance::DbInstance,
|
||||||
newtypes::PersonId,
|
newtypes::PersonId,
|
||||||
|
user::{DbLocalUser, DbPerson, LocalUserView, UpdateUserForm},
|
||||||
utils::http_protocol_str,
|
utils::http_protocol_str,
|
||||||
DbInstance,
|
|
||||||
DbLocalUser,
|
|
||||||
DbPerson,
|
|
||||||
LocalUserView,
|
|
||||||
UpdateUserForm,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
|
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
common::DbInstance,
|
common::instance::DbInstance,
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
common::{DbArticle, DbInstance},
|
common::{article::DbArticle, instance::DbInstance},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
common::{DbInstance, DbPerson},
|
common::{instance::DbInstance, user::DbPerson},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -8,11 +8,9 @@ use crate::{
|
||||||
utils::error::Error,
|
utils::error::Error,
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
article::{DbArticle, DbEdit, EditVersion},
|
||||||
|
instance::DbInstance,
|
||||||
newtypes::{EditId, PersonId},
|
newtypes::{EditId, PersonId},
|
||||||
DbArticle,
|
|
||||||
DbEdit,
|
|
||||||
DbInstance,
|
|
||||||
EditVersion,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
common::{DbInstance, EditVersion},
|
common::{article::EditVersion, instance::DbInstance},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
common::{DbArticle, DbInstance},
|
common::{article::DbArticle, instance::DbInstance},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -11,7 +11,11 @@ use crate::{
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
common::{validation::can_edit_article, DbArticle, DbEdit, DbInstance},
|
common::{
|
||||||
|
article::{DbArticle, DbEdit},
|
||||||
|
instance::DbInstance,
|
||||||
|
validation::can_edit_article,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -4,7 +4,10 @@ use crate::{
|
||||||
federation::objects::edits_collection::DbEditCollection,
|
federation::objects::edits_collection::DbEditCollection,
|
||||||
utils::error::Error,
|
utils::error::Error,
|
||||||
},
|
},
|
||||||
common::{DbArticle, DbInstance, EditVersion},
|
common::{
|
||||||
|
article::{DbArticle, EditVersion},
|
||||||
|
instance::DbInstance,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
federation::objects::article::ApubArticle,
|
federation::objects::article::ApubArticle,
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
common::{utils::http_protocol_str, DbArticle},
|
common::{article::DbArticle, utils::http_protocol_str},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -3,7 +3,10 @@ use crate::{
|
||||||
database::{edit::DbEditForm, IbisData},
|
database::{edit::DbEditForm, IbisData},
|
||||||
utils::error::Error,
|
utils::error::Error,
|
||||||
},
|
},
|
||||||
common::{DbArticle, DbEdit, DbPerson, EditVersion},
|
common::{
|
||||||
|
article::{DbArticle, DbEdit, EditVersion},
|
||||||
|
user::DbPerson,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{database::IbisData, federation::objects::edit::ApubEdit, utils::error::Error},
|
backend::{database::IbisData, federation::objects::edit::ApubEdit, utils::error::Error},
|
||||||
common::{DbArticle, DbEdit},
|
common::article::{DbArticle, DbEdit},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
federation::{objects::articles_collection::DbArticleCollection, send_activity},
|
federation::{objects::articles_collection::DbArticleCollection, send_activity},
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
common::{utils::extract_domain, DbInstance},
|
common::{instance::DbInstance, utils::extract_domain},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
database::IbisData,
|
database::IbisData,
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
common::{utils::http_protocol_str, DbInstance},
|
common::{instance::DbInstance, utils::http_protocol_str},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
database::{user::DbPersonForm, IbisData},
|
database::{user::DbPersonForm, IbisData},
|
||||||
utils::error::Error,
|
utils::error::Error,
|
||||||
},
|
},
|
||||||
common::DbPerson,
|
common::user::DbPerson,
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
common::{DbArticle, DbInstance, DbPerson},
|
common::{article::DbArticle, instance::DbInstance, user::DbPerson},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
axum::{
|
axum::{
|
||||||
|
|
|
@ -9,11 +9,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
article::{DbArticle, EditVersion},
|
||||||
|
instance::DbInstance,
|
||||||
|
user::DbPerson,
|
||||||
utils::http_protocol_str,
|
utils::http_protocol_str,
|
||||||
DbArticle,
|
|
||||||
DbInstance,
|
|
||||||
DbPerson,
|
|
||||||
EditVersion,
|
|
||||||
MAIN_PAGE_NAME,
|
MAIN_PAGE_NAME,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{database::IbisData, utils::error::MyResult},
|
backend::{database::IbisData, utils::error::MyResult},
|
||||||
common::{utils, DbEdit, EditVersion},
|
common::{
|
||||||
|
article::{DbEdit, EditVersion},
|
||||||
|
utils,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
|
@ -57,8 +60,8 @@ pub(super) fn generate_article_version(
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
|
article::DbEdit,
|
||||||
newtypes::{ArticleId, EditId, PersonId},
|
newtypes::{ArticleId, EditId, PersonId},
|
||||||
DbEdit,
|
|
||||||
};
|
};
|
||||||
use activitypub_federation::fetch::object_id::ObjectId;
|
use activitypub_federation::fetch::object_id::ObjectId;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
|
193
src/common/article.rs
Normal file
193
src/common/article.rs
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
use super::{
|
||||||
|
instance::DbInstance,
|
||||||
|
newtypes::{ArticleId, ConflictId, EditId, InstanceId, PersonId},
|
||||||
|
user::DbPerson,
|
||||||
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
use uuid::Uuid;
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
use {
|
||||||
|
crate::backend::database::schema::{article, edit},
|
||||||
|
activitypub_federation::fetch::object_id::ObjectId,
|
||||||
|
diesel::{Identifiable, Queryable, Selectable},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Should be an enum Title/Id but fails due to https://github.com/nox/serde_urlencoded/issues/66
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
||||||
|
pub struct GetArticleForm {
|
||||||
|
pub title: Option<String>,
|
||||||
|
pub domain: Option<String>,
|
||||||
|
pub id: Option<ArticleId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Default, Debug)]
|
||||||
|
pub struct ListArticlesForm {
|
||||||
|
pub only_local: Option<bool>,
|
||||||
|
pub instance_id: Option<InstanceId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 ArticleView {
|
||||||
|
pub article: DbArticle,
|
||||||
|
pub instance: DbInstance,
|
||||||
|
pub latest_version: EditVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg), belongs_to(DbInstance, foreign_key = instance_id)))]
|
||||||
|
pub struct DbArticle {
|
||||||
|
pub id: ArticleId,
|
||||||
|
pub title: String,
|
||||||
|
pub text: String,
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub ap_id: ObjectId<DbArticle>,
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
pub ap_id: String,
|
||||||
|
pub instance_id: InstanceId,
|
||||||
|
pub local: bool,
|
||||||
|
pub protected: bool,
|
||||||
|
pub approved: bool,
|
||||||
|
pub published: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct CreateArticleForm {
|
||||||
|
pub title: String,
|
||||||
|
pub text: String,
|
||||||
|
pub summary: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct EditArticleForm {
|
||||||
|
/// Id of the article to edit
|
||||||
|
pub article_id: ArticleId,
|
||||||
|
/// Full, new text of the article. A diff against `previous_version` is generated on the backend
|
||||||
|
/// side to handle conflicts.
|
||||||
|
pub new_text: String,
|
||||||
|
/// What was changed
|
||||||
|
pub summary: 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<ConflictId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct ProtectArticleForm {
|
||||||
|
pub article_id: ArticleId,
|
||||||
|
pub protected: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct ForkArticleForm {
|
||||||
|
pub article_id: ArticleId,
|
||||||
|
pub new_title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct ApproveArticleForm {
|
||||||
|
pub article_id: ArticleId,
|
||||||
|
pub approve: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||||
|
pub struct SearchArticleForm {
|
||||||
|
pub query: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a single change to the article.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(table_name = edit, check_for_backend(diesel::pg::Pg)))]
|
||||||
|
pub struct DbEdit {
|
||||||
|
// TODO: we could use hash as primary key, but that gives errors on forking because
|
||||||
|
// the same edit is used for multiple articles
|
||||||
|
pub id: EditId,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub creator_id: PersonId,
|
||||||
|
/// UUID built from sha224 hash of diff
|
||||||
|
pub hash: EditVersion,
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub ap_id: ObjectId<DbEdit>,
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
pub ap_id: String,
|
||||||
|
pub diff: String,
|
||||||
|
pub summary: String,
|
||||||
|
pub article_id: ArticleId,
|
||||||
|
/// First edit of an article always has `EditVersion::default()` here
|
||||||
|
pub previous_version_id: EditVersion,
|
||||||
|
pub published: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
||||||
|
pub struct GetEditList {
|
||||||
|
pub article_id: Option<ArticleId>,
|
||||||
|
pub person_id: Option<PersonId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
pub struct EditView {
|
||||||
|
pub edit: DbEdit,
|
||||||
|
pub article: DbArticle,
|
||||||
|
pub creator: DbPerson,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The version hash of a specific edit. Generated by taking an SHA256 hash of the diff
|
||||||
|
/// and using the first 16 bytes so that it fits into UUID.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(diesel_derive_newtype::DieselNewType))]
|
||||||
|
pub struct EditVersion(pub(crate) Uuid);
|
||||||
|
|
||||||
|
impl EditVersion {
|
||||||
|
pub fn new(diff: &str) -> Self {
|
||||||
|
let mut sha256 = Sha256::new();
|
||||||
|
sha256.update(diff);
|
||||||
|
let hash_bytes = sha256.finalize();
|
||||||
|
let uuid =
|
||||||
|
Uuid::from_slice(&hash_bytes.as_slice()[..16]).expect("hash is correct size for uuid");
|
||||||
|
EditVersion(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash(&self) -> String {
|
||||||
|
hex::encode(self.0.into_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EditVersion {
|
||||||
|
fn default() -> Self {
|
||||||
|
EditVersion::new("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct DeleteConflictForm {
|
||||||
|
pub conflict_id: ConflictId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub struct ApiConflict {
|
||||||
|
pub id: ConflictId,
|
||||||
|
pub hash: EditVersion,
|
||||||
|
pub three_way_merge: String,
|
||||||
|
pub summary: String,
|
||||||
|
pub article: DbArticle,
|
||||||
|
pub previous_version_id: EditVersion,
|
||||||
|
pub published: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_edit_versions() {
|
||||||
|
let default = EditVersion::default();
|
||||||
|
assert_eq!("e3b0c44298fc1c149afbf4c8996fb924", default.hash());
|
||||||
|
|
||||||
|
let version = EditVersion::new("test");
|
||||||
|
assert_eq!("9f86d081884c7d659a2feaa0c55ad015", version.hash());
|
||||||
|
}
|
93
src/common/instance.rs
Normal file
93
src/common/instance.rs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
use super::{
|
||||||
|
newtypes::InstanceId,
|
||||||
|
user::{DbPerson, LocalUserView},
|
||||||
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use smart_default::SmartDefault;
|
||||||
|
use url::Url;
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
use {
|
||||||
|
crate::backend::{
|
||||||
|
database::schema::instance,
|
||||||
|
federation::objects::articles_collection::DbArticleCollection,
|
||||||
|
federation::objects::instance_collection::DbInstanceCollection,
|
||||||
|
},
|
||||||
|
activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId},
|
||||||
|
diesel::{Identifiable, Queryable, Selectable},
|
||||||
|
doku::Document,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[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: InstanceId,
|
||||||
|
pub domain: String,
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub ap_id: ObjectId<DbInstance>,
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
pub ap_id: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub articles_url: Option<CollectionId<DbArticleCollection>>,
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
pub articles_url: String,
|
||||||
|
pub inbox_url: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub public_key: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub private_key: Option<String>,
|
||||||
|
pub last_refreshed_at: DateTime<Utc>,
|
||||||
|
pub local: bool,
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub instances_url: Option<CollectionId<DbInstanceCollection>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DbInstance {
|
||||||
|
pub fn inbox_url(&self) -> Url {
|
||||||
|
Url::parse(&self.inbox_url).expect("can parse inbox url")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<DbPerson>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
|
||||||
|
#[serde(default)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable, Document))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
pub struct Options {
|
||||||
|
/// Whether users can create new accounts
|
||||||
|
#[default = true]
|
||||||
|
#[cfg_attr(feature = "ssr", doku(example = "true"))]
|
||||||
|
pub registration_open: bool,
|
||||||
|
/// Whether admins need to approve new articles
|
||||||
|
#[default = false]
|
||||||
|
#[cfg_attr(feature = "ssr", doku(example = "false"))]
|
||||||
|
pub article_approval: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
pub struct SiteView {
|
||||||
|
pub my_profile: Option<LocalUserView>,
|
||||||
|
pub config: Options,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct GetInstance {
|
||||||
|
pub id: Option<InstanceId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct FollowInstance {
|
||||||
|
pub id: InstanceId,
|
||||||
|
}
|
|
@ -1,25 +1,14 @@
|
||||||
|
pub mod article;
|
||||||
|
pub mod instance;
|
||||||
pub mod newtypes;
|
pub mod newtypes;
|
||||||
|
pub mod user;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod validation;
|
pub mod validation;
|
||||||
|
|
||||||
|
use article::{ApiConflict, DbArticle};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use newtypes::{ArticleId, ConflictId, EditId, InstanceId, PersonId};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
|
||||||
use smart_default::SmartDefault;
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uuid::Uuid;
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
use {
|
|
||||||
crate::backend::{
|
|
||||||
database::schema::{article, edit, instance, local_user, person},
|
|
||||||
federation::objects::articles_collection::DbArticleCollection,
|
|
||||||
federation::objects::instance_collection::DbInstanceCollection,
|
|
||||||
},
|
|
||||||
activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId},
|
|
||||||
diesel::{Identifiable, Queryable, Selectable},
|
|
||||||
doku::Document,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MAIN_PAGE_NAME: &str = "Main_Page";
|
pub const MAIN_PAGE_NAME: &str = "Main_Page";
|
||||||
|
|
||||||
|
@ -28,231 +17,6 @@ pub static AUTH_COOKIE: &str = "auth";
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Auth(pub Option<String>);
|
pub struct Auth(pub Option<String>);
|
||||||
|
|
||||||
/// Should be an enum Title/Id but fails due to https://github.com/nox/serde_urlencoded/issues/66
|
|
||||||
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
||||||
pub struct GetArticleForm {
|
|
||||||
pub title: Option<String>,
|
|
||||||
pub domain: Option<String>,
|
|
||||||
pub id: Option<ArticleId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone, Default, Debug)]
|
|
||||||
pub struct ListArticlesForm {
|
|
||||||
pub only_local: Option<bool>,
|
|
||||||
pub instance_id: Option<InstanceId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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 ArticleView {
|
|
||||||
pub article: DbArticle,
|
|
||||||
pub instance: DbInstance,
|
|
||||||
pub latest_version: EditVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg), belongs_to(DbInstance, foreign_key = instance_id)))]
|
|
||||||
pub struct DbArticle {
|
|
||||||
pub id: ArticleId,
|
|
||||||
pub title: String,
|
|
||||||
pub text: String,
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
pub ap_id: ObjectId<DbArticle>,
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
|
||||||
pub ap_id: String,
|
|
||||||
pub instance_id: InstanceId,
|
|
||||||
pub local: bool,
|
|
||||||
pub protected: bool,
|
|
||||||
pub approved: bool,
|
|
||||||
pub published: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a single change to the article.
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(table_name = edit, check_for_backend(diesel::pg::Pg)))]
|
|
||||||
pub struct DbEdit {
|
|
||||||
// TODO: we could use hash as primary key, but that gives errors on forking because
|
|
||||||
// the same edit is used for multiple articles
|
|
||||||
pub id: EditId,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub creator_id: PersonId,
|
|
||||||
/// UUID built from sha224 hash of diff
|
|
||||||
pub hash: EditVersion,
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
pub ap_id: ObjectId<DbEdit>,
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
|
||||||
pub ap_id: String,
|
|
||||||
pub diff: String,
|
|
||||||
pub summary: String,
|
|
||||||
pub article_id: ArticleId,
|
|
||||||
/// First edit of an article always has `EditVersion::default()` here
|
|
||||||
pub previous_version_id: EditVersion,
|
|
||||||
pub published: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
||||||
pub struct GetEditList {
|
|
||||||
pub article_id: Option<ArticleId>,
|
|
||||||
pub person_id: Option<PersonId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
pub struct EditView {
|
|
||||||
pub edit: DbEdit,
|
|
||||||
pub article: DbArticle,
|
|
||||||
pub creator: DbPerson,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The version hash of a specific edit. Generated by taking an SHA256 hash of the diff
|
|
||||||
/// and using the first 16 bytes so that it fits into UUID.
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(diesel_derive_newtype::DieselNewType))]
|
|
||||||
pub struct EditVersion(pub(crate) Uuid);
|
|
||||||
|
|
||||||
impl EditVersion {
|
|
||||||
pub fn new(diff: &str) -> Self {
|
|
||||||
let mut sha256 = Sha256::new();
|
|
||||||
sha256.update(diff);
|
|
||||||
let hash_bytes = sha256.finalize();
|
|
||||||
let uuid =
|
|
||||||
Uuid::from_slice(&hash_bytes.as_slice()[..16]).expect("hash is correct size for uuid");
|
|
||||||
EditVersion(uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hash(&self) -> String {
|
|
||||||
hex::encode(self.0.into_bytes())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for EditVersion {
|
|
||||||
fn default() -> Self {
|
|
||||||
EditVersion::new("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
||||||
pub struct RegisterUserForm {
|
|
||||||
pub username: String,
|
|
||||||
pub password: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct LoginUserForm {
|
|
||||||
pub username: String,
|
|
||||||
pub password: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
pub struct LocalUserView {
|
|
||||||
pub person: DbPerson,
|
|
||||||
pub local_user: DbLocalUser,
|
|
||||||
pub following: Vec<DbInstance>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A user with account registered on local instance.
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(table_name = local_user, check_for_backend(diesel::pg::Pg)))]
|
|
||||||
pub struct DbLocalUser {
|
|
||||||
pub id: InstanceId,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub password_encrypted: String,
|
|
||||||
pub person_id: PersonId,
|
|
||||||
pub admin: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Federation related data from a local or remote user.
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(table_name = person, check_for_backend(diesel::pg::Pg)))]
|
|
||||||
pub struct DbPerson {
|
|
||||||
pub id: PersonId,
|
|
||||||
pub username: String,
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
pub ap_id: ObjectId<DbPerson>,
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
|
||||||
pub ap_id: String,
|
|
||||||
pub inbox_url: String,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub public_key: String,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub private_key: Option<String>,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub last_refreshed_at: DateTime<Utc>,
|
|
||||||
pub local: bool,
|
|
||||||
pub display_name: Option<String>,
|
|
||||||
pub bio: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DbPerson {
|
|
||||||
pub fn inbox_url(&self) -> Url {
|
|
||||||
Url::parse(&self.inbox_url).expect("can parse inbox url")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct CreateArticleForm {
|
|
||||||
pub title: String,
|
|
||||||
pub text: String,
|
|
||||||
pub summary: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct EditArticleForm {
|
|
||||||
/// Id of the article to edit
|
|
||||||
pub article_id: ArticleId,
|
|
||||||
/// Full, new text of the article. A diff against `previous_version` is generated on the backend
|
|
||||||
/// side to handle conflicts.
|
|
||||||
pub new_text: String,
|
|
||||||
/// What was changed
|
|
||||||
pub summary: 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<ConflictId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct ProtectArticleForm {
|
|
||||||
pub article_id: ArticleId,
|
|
||||||
pub protected: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct ForkArticleForm {
|
|
||||||
pub article_id: ArticleId,
|
|
||||||
pub new_title: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct ApproveArticleForm {
|
|
||||||
pub article_id: ArticleId,
|
|
||||||
pub approve: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct DeleteConflictForm {
|
|
||||||
pub conflict_id: ConflictId,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct GetInstance {
|
|
||||||
pub id: Option<InstanceId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct FollowInstance {
|
|
||||||
pub id: InstanceId,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub struct SuccessResponse {
|
pub struct SuccessResponse {
|
||||||
success: bool,
|
success: bool,
|
||||||
|
@ -264,27 +28,11 @@ impl Default for SuccessResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
||||||
pub struct SearchArticleForm {
|
|
||||||
pub query: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub struct ResolveObject {
|
pub struct ResolveObject {
|
||||||
pub id: Url,
|
pub id: Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct ApiConflict {
|
|
||||||
pub id: ConflictId,
|
|
||||||
pub hash: EditVersion,
|
|
||||||
pub three_way_merge: String,
|
|
||||||
pub summary: String,
|
|
||||||
pub article: DbArticle,
|
|
||||||
pub previous_version_id: EditVersion,
|
|
||||||
pub published: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum Notification {
|
pub enum Notification {
|
||||||
EditConflict(ApiConflict),
|
EditConflict(ApiConflict),
|
||||||
|
@ -299,89 +47,3 @@ impl Notification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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: InstanceId,
|
|
||||||
pub domain: String,
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
pub ap_id: ObjectId<DbInstance>,
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
|
||||||
pub ap_id: String,
|
|
||||||
pub description: Option<String>,
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
pub articles_url: Option<CollectionId<DbArticleCollection>>,
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
|
||||||
pub articles_url: String,
|
|
||||||
pub inbox_url: String,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub public_key: String,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub private_key: Option<String>,
|
|
||||||
pub last_refreshed_at: DateTime<Utc>,
|
|
||||||
pub local: bool,
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
pub instances_url: Option<CollectionId<DbInstanceCollection>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DbInstance {
|
|
||||||
pub fn inbox_url(&self) -> Url {
|
|
||||||
Url::parse(&self.inbox_url).expect("can parse inbox url")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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<DbPerson>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
||||||
pub struct GetUserForm {
|
|
||||||
pub name: String,
|
|
||||||
pub domain: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
||||||
pub struct UpdateUserForm {
|
|
||||||
pub person_id: PersonId,
|
|
||||||
pub display_name: Option<String>,
|
|
||||||
pub bio: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable, Document))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
pub struct Options {
|
|
||||||
/// Whether users can create new accounts
|
|
||||||
#[default = true]
|
|
||||||
#[cfg_attr(feature = "ssr", doku(example = "true"))]
|
|
||||||
pub registration_open: bool,
|
|
||||||
/// Whether admins need to approve new articles
|
|
||||||
#[default = false]
|
|
||||||
#[cfg_attr(feature = "ssr", doku(example = "false"))]
|
|
||||||
pub article_approval: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)]
|
|
||||||
#[cfg_attr(feature = "ssr", derive(Queryable))]
|
|
||||||
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
pub struct SiteView {
|
|
||||||
pub my_profile: Option<LocalUserView>,
|
|
||||||
pub config: Options,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_edit_versions() {
|
|
||||||
let default = EditVersion::default();
|
|
||||||
assert_eq!("e3b0c44298fc1c149afbf4c8996fb924", default.hash());
|
|
||||||
|
|
||||||
let version = EditVersion::new("test");
|
|
||||||
assert_eq!("9f86d081884c7d659a2feaa0c55ad015", version.hash());
|
|
||||||
}
|
|
||||||
|
|
88
src/common/user.rs
Normal file
88
src/common/user.rs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
use super::{
|
||||||
|
instance::DbInstance,
|
||||||
|
newtypes::{InstanceId, PersonId},
|
||||||
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
use {
|
||||||
|
crate::backend::database::schema::{local_user, person},
|
||||||
|
activitypub_federation::fetch::object_id::ObjectId,
|
||||||
|
diesel::{Identifiable, Queryable, Selectable},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||||
|
pub struct RegisterUserForm {
|
||||||
|
pub username: String,
|
||||||
|
pub password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct LoginUserForm {
|
||||||
|
pub username: String,
|
||||||
|
pub password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
pub struct LocalUserView {
|
||||||
|
pub person: DbPerson,
|
||||||
|
pub local_user: DbLocalUser,
|
||||||
|
pub following: Vec<DbInstance>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A user with account registered on local instance.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(table_name = local_user, check_for_backend(diesel::pg::Pg)))]
|
||||||
|
pub struct DbLocalUser {
|
||||||
|
pub id: InstanceId,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub password_encrypted: String,
|
||||||
|
pub person_id: PersonId,
|
||||||
|
pub admin: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Federation related data from a local or remote user.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
|
||||||
|
#[cfg_attr(feature = "ssr", diesel(table_name = person, check_for_backend(diesel::pg::Pg)))]
|
||||||
|
pub struct DbPerson {
|
||||||
|
pub id: PersonId,
|
||||||
|
pub username: String,
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub ap_id: ObjectId<DbPerson>,
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
pub ap_id: String,
|
||||||
|
pub inbox_url: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub public_key: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub private_key: Option<String>,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub last_refreshed_at: DateTime<Utc>,
|
||||||
|
pub local: bool,
|
||||||
|
pub display_name: Option<String>,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DbPerson {
|
||||||
|
pub fn inbox_url(&self) -> Url {
|
||||||
|
Url::parse(&self.inbox_url).expect("can parse inbox url")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||||
|
pub struct GetUserForm {
|
||||||
|
pub name: String,
|
||||||
|
pub domain: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||||
|
pub struct UpdateUserForm {
|
||||||
|
pub person_id: PersonId,
|
||||||
|
pub display_name: Option<String>,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::common::DbArticle;
|
use crate::common::article::DbArticle;
|
||||||
use leptos::server_fn::error::ServerFnErrorErr;
|
use leptos::server_fn::error::ServerFnErrorErr;
|
||||||
|
|
||||||
pub fn can_edit_article(article: &DbArticle, is_admin: bool) -> Result<(), ServerFnErrorErr> {
|
pub fn can_edit_article(article: &DbArticle, is_admin: bool) -> Result<(), ServerFnErrorErr> {
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
newtypes::{ArticleId, ConflictId},
|
article::*,
|
||||||
|
instance::*,
|
||||||
|
newtypes::{ArticleId, ConflictId, PersonId},
|
||||||
|
user::*,
|
||||||
utils::http_protocol_str,
|
utils::http_protocol_str,
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
use http::{Method, StatusCode};
|
use http::{Method, StatusCode};
|
||||||
use leptos::{prelude::ServerFnError, server_fn::error::NoCustomError};
|
use leptos::{prelude::ServerFnError, server_fn::error::NoCustomError};
|
||||||
use log::error;
|
use log::error;
|
||||||
use newtypes::PersonId;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{fmt::Debug, sync::LazyLock};
|
use std::{fmt::Debug, sync::LazyLock};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::SiteView,
|
common::instance::SiteView,
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
components::{nav::Nav, protected_route::IbisProtectedRoute},
|
components::{nav::Nav, protected_route::IbisProtectedRoute},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{validation::can_edit_article, ArticleView},
|
common::{article::ArticleView, validation::can_edit_article},
|
||||||
frontend::{
|
frontend::{
|
||||||
app::{is_admin, is_logged_in},
|
app::{is_admin, is_logged_in},
|
||||||
article_path,
|
article_path,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{utils::extract_domain, EditView},
|
common::{article::EditView, utils::extract_domain},
|
||||||
frontend::{article_link, render_date_time, user_link},
|
frontend::{article_link, render_date_time, user_link},
|
||||||
};
|
};
|
||||||
use leptos::{either::Either, prelude::*};
|
use leptos::{either::Either, prelude::*};
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{newtypes::InstanceId, DbInstance, FollowInstance},
|
common::{
|
||||||
|
instance::{DbInstance, FollowInstance},
|
||||||
|
newtypes::InstanceId,
|
||||||
|
},
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
app::{site, DefaultResource},
|
app::{site, DefaultResource},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::common::{utils::extract_domain, DbArticle, DbPerson};
|
use crate::common::{article::DbArticle, user::DbPerson, utils::extract_domain};
|
||||||
use chrono::{DateTime, Duration, Local, Utc};
|
use chrono::{DateTime, Duration, Local, Utc};
|
||||||
use codee::string::FromToStringCodec;
|
use codee::string::FromToStringCodec;
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{newtypes::ArticleId, ForkArticleForm, ProtectArticleForm},
|
common::{
|
||||||
|
article::{ForkArticleForm, ProtectArticleForm},
|
||||||
|
newtypes::ArticleId,
|
||||||
|
},
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
app::is_admin,
|
app::is_admin,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::CreateArticleForm,
|
common::article::CreateArticleForm,
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
app::{is_admin, site, DefaultResource},
|
app::{is_admin, site, DefaultResource},
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{
|
common::{
|
||||||
|
article::{ApiConflict, ArticleView, EditArticleForm},
|
||||||
newtypes::ConflictId,
|
newtypes::ConflictId,
|
||||||
ApiConflict,
|
|
||||||
ArticleView,
|
|
||||||
EditArticleForm,
|
|
||||||
Notification,
|
Notification,
|
||||||
MAIN_PAGE_NAME,
|
MAIN_PAGE_NAME,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::ListArticlesForm,
|
common::article::ListArticlesForm,
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
app::DefaultResource,
|
app::DefaultResource,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{utils::http_protocol_str, DbInstance, ListArticlesForm},
|
common::{article::ListArticlesForm, instance::DbInstance, utils::http_protocol_str},
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
article_path,
|
article_path,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::LoginUserForm,
|
common::user::LoginUserForm,
|
||||||
frontend::{api::CLIENT, app::site, components::credentials::*},
|
frontend::{api::CLIENT, app::site, components::credentials::*},
|
||||||
};
|
};
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{ArticleView, EditView, GetArticleForm, MAIN_PAGE_NAME},
|
common::{
|
||||||
|
article::{ArticleView, EditView, GetArticleForm},
|
||||||
|
MAIN_PAGE_NAME,
|
||||||
|
},
|
||||||
frontend::api::CLIENT,
|
frontend::api::CLIENT,
|
||||||
};
|
};
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::RegisterUserForm,
|
common::user::RegisterUserForm,
|
||||||
frontend::{api::CLIENT, app::site, components::credentials::*},
|
frontend::{api::CLIENT, app::site, components::credentials::*},
|
||||||
};
|
};
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{DbArticle, DbInstance, SearchArticleForm},
|
common::{
|
||||||
|
article::{DbArticle, SearchArticleForm},
|
||||||
|
instance::DbInstance,
|
||||||
|
},
|
||||||
frontend::{api::CLIENT, article_path, article_title},
|
frontend::{api::CLIENT, article_path, article_title},
|
||||||
};
|
};
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::UpdateUserForm,
|
common::user::UpdateUserForm,
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
app::{site, DefaultResource},
|
app::{site, DefaultResource},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
common::GetUserForm,
|
common::user::GetUserForm,
|
||||||
frontend::{
|
frontend::{
|
||||||
api::CLIENT,
|
api::CLIENT,
|
||||||
components::edit_list::EditList,
|
components::edit_list::EditList,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use ibis::{
|
||||||
config::{IbisConfig, IbisConfigDatabase, IbisConfigFederation},
|
config::{IbisConfig, IbisConfigDatabase, IbisConfigFederation},
|
||||||
start,
|
start,
|
||||||
},
|
},
|
||||||
common::{Options, RegisterUserForm},
|
common::{instance::Options, user::RegisterUserForm},
|
||||||
frontend::api::ApiClient,
|
frontend::api::ApiClient,
|
||||||
};
|
};
|
||||||
use reqwest::ClientBuilder;
|
use reqwest::ClientBuilder;
|
||||||
|
|
|
@ -5,19 +5,19 @@ mod common;
|
||||||
use crate::common::{TestData, TEST_ARTICLE_DEFAULT_TEXT};
|
use crate::common::{TestData, TEST_ARTICLE_DEFAULT_TEXT};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use ibis::common::{
|
use ibis::common::{
|
||||||
|
article::{
|
||||||
|
ArticleView,
|
||||||
|
CreateArticleForm,
|
||||||
|
EditArticleForm,
|
||||||
|
ForkArticleForm,
|
||||||
|
GetArticleForm,
|
||||||
|
ListArticlesForm,
|
||||||
|
ProtectArticleForm,
|
||||||
|
SearchArticleForm,
|
||||||
|
},
|
||||||
|
user::{GetUserForm, LoginUserForm, RegisterUserForm},
|
||||||
utils::extract_domain,
|
utils::extract_domain,
|
||||||
ArticleView,
|
|
||||||
CreateArticleForm,
|
|
||||||
EditArticleForm,
|
|
||||||
ForkArticleForm,
|
|
||||||
GetArticleForm,
|
|
||||||
GetUserForm,
|
|
||||||
ListArticlesForm,
|
|
||||||
LoginUserForm,
|
|
||||||
Notification,
|
Notification,
|
||||||
ProtectArticleForm,
|
|
||||||
RegisterUserForm,
|
|
||||||
SearchArticleForm,
|
|
||||||
};
|
};
|
||||||
use pretty_assertions::{assert_eq, assert_ne};
|
use pretty_assertions::{assert_eq, assert_ne};
|
||||||
use retry_future::{LinearRetryStrategy, RetryFuture, RetryPolicy};
|
use retry_future::{LinearRetryStrategy, RetryFuture, RetryPolicy};
|
||||||
|
|
Loading…
Reference in a new issue