mirror of
https://github.com/Nutomic/ibis.git
synced 2025-02-02 22:41:35 +00:00
Rename IbisData to IbisContext
This commit is contained in:
parent
696ba19a2f
commit
3d1beefe14
40 changed files with 598 additions and 550 deletions
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
article::DbArticleForm,
|
article::DbArticleForm,
|
||||||
conflict::{DbConflict, DbConflictForm},
|
conflict::{DbConflict, DbConflictForm},
|
||||||
edit::DbEditForm,
|
edit::DbEditForm,
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
federation::activities::{create_article::CreateArticle, submit_article_update},
|
federation::activities::{create_article::CreateArticle, submit_article_update},
|
||||||
utils::{
|
utils::{
|
||||||
|
@ -50,13 +50,13 @@ use diffy::create_patch;
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn create_article(
|
pub(in crate::backend::api) async fn create_article(
|
||||||
user: Extension<LocalUserView>,
|
user: Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(mut params): Form<CreateArticleParams>,
|
Form(mut params): Form<CreateArticleParams>,
|
||||||
) -> MyResult<Json<DbArticleView>> {
|
) -> MyResult<Json<DbArticleView>> {
|
||||||
params.title = validate_article_title(¶ms.title)?;
|
params.title = validate_article_title(¶ms.title)?;
|
||||||
validate_not_empty(¶ms.text)?;
|
validate_not_empty(¶ms.text)?;
|
||||||
|
|
||||||
let local_instance = DbInstance::read_local(&data)?;
|
let local_instance = DbInstance::read_local(&context)?;
|
||||||
let ap_id = ObjectId::parse(&format!(
|
let ap_id = ObjectId::parse(&format!(
|
||||||
"{}://{}/article/{}",
|
"{}://{}/article/{}",
|
||||||
http_protocol_str(),
|
http_protocol_str(),
|
||||||
|
@ -70,23 +70,23 @@ pub(in crate::backend::api) async fn create_article(
|
||||||
instance_id: local_instance.id,
|
instance_id: local_instance.id,
|
||||||
local: true,
|
local: true,
|
||||||
protected: false,
|
protected: false,
|
||||||
approved: !data.config.options.article_approval,
|
approved: !context.config.options.article_approval,
|
||||||
};
|
};
|
||||||
let article = DbArticle::create(form, &data)?;
|
let article = DbArticle::create(form, &context)?;
|
||||||
|
|
||||||
let edit_data = EditArticleParams {
|
let edit_data = EditArticleParams {
|
||||||
article_id: article.id,
|
article_id: article.id,
|
||||||
new_text: params.text,
|
new_text: params.text,
|
||||||
summary: params.summary,
|
summary: params.summary,
|
||||||
previous_version_id: article.latest_edit_version(&data)?,
|
previous_version_id: article.latest_edit_version(&context)?,
|
||||||
resolve_conflict_id: None,
|
resolve_conflict_id: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = edit_article(user, data.reset_request_count(), Form(edit_data)).await?;
|
let _ = edit_article(user, context.reset_request_count(), Form(edit_data)).await?;
|
||||||
|
|
||||||
// allow reading unapproved article here
|
// allow reading unapproved article here
|
||||||
let article_view = DbArticle::read_view(article.id, &data)?;
|
let article_view = DbArticle::read_view(article.id, &context)?;
|
||||||
CreateArticle::send_to_followers(article_view.article.clone(), &data).await?;
|
CreateArticle::send_to_followers(article_view.article.clone(), &context).await?;
|
||||||
|
|
||||||
Ok(Json(article_view))
|
Ok(Json(article_view))
|
||||||
}
|
}
|
||||||
|
@ -103,15 +103,15 @@ pub(in crate::backend::api) async fn create_article(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn edit_article(
|
pub(in crate::backend::api) async fn edit_article(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(mut params): Form<EditArticleParams>,
|
Form(mut params): Form<EditArticleParams>,
|
||||||
) -> MyResult<Json<Option<ApiConflict>>> {
|
) -> MyResult<Json<Option<ApiConflict>>> {
|
||||||
validate_not_empty(¶ms.new_text)?;
|
validate_not_empty(¶ms.new_text)?;
|
||||||
// resolve conflict if any
|
// resolve conflict if any
|
||||||
if let Some(resolve_conflict_id) = params.resolve_conflict_id {
|
if let Some(resolve_conflict_id) = params.resolve_conflict_id {
|
||||||
DbConflict::delete(resolve_conflict_id, user.person.id, &data)?;
|
DbConflict::delete(resolve_conflict_id, user.person.id, &context)?;
|
||||||
}
|
}
|
||||||
let original_article = DbArticle::read_view(params.article_id, &data)?;
|
let original_article = DbArticle::read_view(params.article_id, &context)?;
|
||||||
if params.new_text == original_article.article.text {
|
if params.new_text == original_article.article.text {
|
||||||
return Err(anyhow!("Edit contains no changes").into());
|
return Err(anyhow!("Edit contains no changes").into());
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ pub(in crate::backend::api) async fn edit_article(
|
||||||
if !params.new_text.ends_with('\n') {
|
if !params.new_text.ends_with('\n') {
|
||||||
params.new_text.push('\n');
|
params.new_text.push('\n');
|
||||||
}
|
}
|
||||||
let local_link = format!("](https://{}", data.config.federation.domain);
|
let local_link = format!("](https://{}", context.config.federation.domain);
|
||||||
if params.new_text.contains(&local_link) {
|
if params.new_text.contains(&local_link) {
|
||||||
return Err(anyhow!("Links to local instance don't work over federation").into());
|
return Err(anyhow!("Links to local instance don't work over federation").into());
|
||||||
}
|
}
|
||||||
|
@ -139,18 +139,18 @@ pub(in crate::backend::api) async fn edit_article(
|
||||||
params.previous_version_id,
|
params.previous_version_id,
|
||||||
&original_article.article,
|
&original_article.article,
|
||||||
user.person.id,
|
user.person.id,
|
||||||
&data,
|
&context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(Json(None))
|
Ok(Json(None))
|
||||||
} else {
|
} else {
|
||||||
// There have been other changes since this edit was initiated. Get the common ancestor
|
// There have been other changes since this edit was initiated. Get the common ancestor
|
||||||
// version and generate a diff to find out what exactly has changed.
|
// version and generate a diff to find out what exactly has changed.
|
||||||
let edits = DbEdit::list_for_article(original_article.article.id, &data)?;
|
let edits = DbEdit::list_for_article(original_article.article.id, &context)?;
|
||||||
let ancestor = generate_article_version(&edits, ¶ms.previous_version_id)?;
|
let ancestor = generate_article_version(&edits, ¶ms.previous_version_id)?;
|
||||||
let patch = create_patch(&ancestor, &new_text);
|
let patch = create_patch(&ancestor, &new_text);
|
||||||
|
|
||||||
let previous_version = DbEdit::read(¶ms.previous_version_id, &data)?;
|
let previous_version = DbEdit::read(¶ms.previous_version_id, &context)?;
|
||||||
let form = DbConflictForm {
|
let form = DbConflictForm {
|
||||||
hash: EditVersion::new(&patch.to_string()),
|
hash: EditVersion::new(&patch.to_string()),
|
||||||
diff: patch.to_string(),
|
diff: patch.to_string(),
|
||||||
|
@ -159,8 +159,8 @@ pub(in crate::backend::api) async fn edit_article(
|
||||||
article_id: original_article.article.id,
|
article_id: original_article.article.id,
|
||||||
previous_version_id: previous_version.hash,
|
previous_version_id: previous_version.hash,
|
||||||
};
|
};
|
||||||
let conflict = DbConflict::create(&form, &data)?;
|
let conflict = DbConflict::create(&form, &context)?;
|
||||||
Ok(Json(conflict.to_api_conflict(&data).await?))
|
Ok(Json(conflict.to_api_conflict(&context).await?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,19 +168,19 @@ pub(in crate::backend::api) async fn edit_article(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn get_article(
|
pub(in crate::backend::api) async fn get_article(
|
||||||
Query(query): Query<GetArticleParams>,
|
Query(query): Query<GetArticleParams>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<DbArticleView>> {
|
) -> MyResult<Json<DbArticleView>> {
|
||||||
match (query.title, query.id) {
|
match (query.title, query.id) {
|
||||||
(Some(title), None) => Ok(Json(DbArticle::read_view_title(
|
(Some(title), None) => Ok(Json(DbArticle::read_view_title(
|
||||||
&title,
|
&title,
|
||||||
query.domain,
|
query.domain,
|
||||||
&data,
|
&context,
|
||||||
)?)),
|
)?)),
|
||||||
(None, Some(id)) => {
|
(None, Some(id)) => {
|
||||||
if query.domain.is_some() {
|
if query.domain.is_some() {
|
||||||
return Err(anyhow!("Cant combine id and instance_domain").into());
|
return Err(anyhow!("Cant combine id and instance_domain").into());
|
||||||
}
|
}
|
||||||
let article = DbArticle::read_view(id, &data)?;
|
let article = DbArticle::read_view(id, &context)?;
|
||||||
Ok(Json(article))
|
Ok(Json(article))
|
||||||
}
|
}
|
||||||
_ => Err(anyhow!("Must pass exactly one of title, id").into()),
|
_ => Err(anyhow!("Must pass exactly one of title, id").into()),
|
||||||
|
@ -190,12 +190,12 @@ pub(in crate::backend::api) async fn get_article(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn list_articles(
|
pub(in crate::backend::api) async fn list_articles(
|
||||||
Query(query): Query<ListArticlesParams>,
|
Query(query): Query<ListArticlesParams>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<Vec<DbArticle>>> {
|
) -> MyResult<Json<Vec<DbArticle>>> {
|
||||||
Ok(Json(DbArticle::read_all(
|
Ok(Json(DbArticle::read_all(
|
||||||
query.only_local,
|
query.only_local,
|
||||||
query.instance_id,
|
query.instance_id,
|
||||||
&data,
|
&context,
|
||||||
)?))
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,14 +204,14 @@ pub(in crate::backend::api) async fn list_articles(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn fork_article(
|
pub(in crate::backend::api) async fn fork_article(
|
||||||
Extension(_user): Extension<LocalUserView>,
|
Extension(_user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(mut params): Form<ForkArticleParams>,
|
Form(mut params): Form<ForkArticleParams>,
|
||||||
) -> MyResult<Json<DbArticleView>> {
|
) -> MyResult<Json<DbArticleView>> {
|
||||||
// TODO: lots of code duplicated from create_article(), can move it into helper
|
// TODO: lots of code duplicated from create_article(), can move it into helper
|
||||||
let original_article = DbArticle::read_view(params.article_id, &data)?;
|
let original_article = DbArticle::read_view(params.article_id, &context)?;
|
||||||
params.new_title = validate_article_title(¶ms.new_title)?;
|
params.new_title = validate_article_title(¶ms.new_title)?;
|
||||||
|
|
||||||
let local_instance = DbInstance::read_local(&data)?;
|
let local_instance = DbInstance::read_local(&context)?;
|
||||||
let ap_id = ObjectId::parse(&format!(
|
let ap_id = ObjectId::parse(&format!(
|
||||||
"{}://{}/article/{}",
|
"{}://{}/article/{}",
|
||||||
http_protocol_str(),
|
http_protocol_str(),
|
||||||
|
@ -225,14 +225,14 @@ pub(in crate::backend::api) async fn fork_article(
|
||||||
instance_id: local_instance.id,
|
instance_id: local_instance.id,
|
||||||
local: true,
|
local: true,
|
||||||
protected: false,
|
protected: false,
|
||||||
approved: !data.config.options.article_approval,
|
approved: !context.config.options.article_approval,
|
||||||
};
|
};
|
||||||
let article = DbArticle::create(form, &data)?;
|
let article = DbArticle::create(form, &context)?;
|
||||||
|
|
||||||
// copy edits to new article
|
// copy edits to new article
|
||||||
// this could also be done in sql
|
// this could also be done in sql
|
||||||
|
|
||||||
let edits = DbEdit::list_for_article(original_article.article.id, &data)?;
|
let edits = DbEdit::list_for_article(original_article.article.id, &context)?;
|
||||||
for e in edits {
|
for e in edits {
|
||||||
let ap_id = DbEditForm::generate_ap_id(&article, &e.hash)?;
|
let ap_id = DbEditForm::generate_ap_id(&article, &e.hash)?;
|
||||||
let form = DbEditForm {
|
let form = DbEditForm {
|
||||||
|
@ -246,12 +246,12 @@ pub(in crate::backend::api) async fn fork_article(
|
||||||
published: Utc::now(),
|
published: Utc::now(),
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
DbEdit::create(&form, &data)?;
|
DbEdit::create(&form, &context)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateArticle::send_to_followers(article.clone(), &data).await?;
|
CreateArticle::send_to_followers(article.clone(), &context).await?;
|
||||||
|
|
||||||
Ok(Json(DbArticle::read_view(article.id, &data)?))
|
Ok(Json(DbArticle::read_view(article.id, &context)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch a remote article, including edits collection. Allows viewing and editing. Note that new
|
/// Fetch a remote article, including edits collection. Allows viewing and editing. Note that new
|
||||||
|
@ -259,12 +259,12 @@ pub(in crate::backend::api) async fn fork_article(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(super) async fn resolve_article(
|
pub(super) async fn resolve_article(
|
||||||
Query(query): Query<ResolveObjectParams>,
|
Query(query): Query<ResolveObjectParams>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<DbArticleView>> {
|
) -> MyResult<Json<DbArticleView>> {
|
||||||
let article: DbArticle = ObjectId::from(query.id).dereference(&data).await?;
|
let article: DbArticle = ObjectId::from(query.id).dereference(&context).await?;
|
||||||
let instance = DbInstance::read(article.instance_id, &data)?;
|
let instance = DbInstance::read(article.instance_id, &context)?;
|
||||||
let comments = DbComment::read_for_article(article.id, &data)?;
|
let comments = DbComment::read_for_article(article.id, &context)?;
|
||||||
let latest_version = article.latest_edit_version(&data)?;
|
let latest_version = article.latest_edit_version(&context)?;
|
||||||
Ok(Json(DbArticleView {
|
Ok(Json(DbArticleView {
|
||||||
article,
|
article,
|
||||||
instance,
|
instance,
|
||||||
|
@ -277,23 +277,23 @@ pub(super) async fn resolve_article(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(super) async fn search_article(
|
pub(super) async fn search_article(
|
||||||
Query(query): Query<SearchArticleParams>,
|
Query(query): Query<SearchArticleParams>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<Vec<DbArticle>>> {
|
) -> MyResult<Json<Vec<DbArticle>>> {
|
||||||
if query.query.is_empty() {
|
if query.query.is_empty() {
|
||||||
return Err(anyhow!("Query is empty").into());
|
return Err(anyhow!("Query is empty").into());
|
||||||
}
|
}
|
||||||
let article = DbArticle::search(&query.query, &data)?;
|
let article = DbArticle::search(&query.query, &context)?;
|
||||||
Ok(Json(article))
|
Ok(Json(article))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn protect_article(
|
pub(in crate::backend::api) async fn protect_article(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(params): Form<ProtectArticleParams>,
|
Form(params): Form<ProtectArticleParams>,
|
||||||
) -> MyResult<Json<DbArticle>> {
|
) -> MyResult<Json<DbArticle>> {
|
||||||
check_is_admin(&user)?;
|
check_is_admin(&user)?;
|
||||||
let article = DbArticle::update_protected(params.article_id, params.protected, &data)?;
|
let article = DbArticle::update_protected(params.article_id, params.protected, &context)?;
|
||||||
Ok(Json(article))
|
Ok(Json(article))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,14 +301,14 @@ pub(in crate::backend::api) async fn protect_article(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub async fn approve_article(
|
pub async fn approve_article(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(params): Form<ApproveArticleParams>,
|
Form(params): Form<ApproveArticleParams>,
|
||||||
) -> MyResult<Json<()>> {
|
) -> MyResult<Json<()>> {
|
||||||
check_is_admin(&user)?;
|
check_is_admin(&user)?;
|
||||||
if params.approve {
|
if params.approve {
|
||||||
DbArticle::update_approved(params.article_id, true, &data)?;
|
DbArticle::update_approved(params.article_id, true, &context)?;
|
||||||
} else {
|
} else {
|
||||||
DbArticle::delete(params.article_id, &data)?;
|
DbArticle::delete(params.article_id, &context)?;
|
||||||
}
|
}
|
||||||
Ok(Json(()))
|
Ok(Json(()))
|
||||||
}
|
}
|
||||||
|
@ -317,9 +317,9 @@ pub async fn approve_article(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub async fn delete_conflict(
|
pub async fn delete_conflict(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(params): Form<DeleteConflictParams>,
|
Form(params): Form<DeleteConflictParams>,
|
||||||
) -> MyResult<Json<()>> {
|
) -> MyResult<Json<()>> {
|
||||||
DbConflict::delete(params.conflict_id, user.person.id, &data)?;
|
DbConflict::delete(params.conflict_id, user.person.id, &context)?;
|
||||||
Ok(Json(()))
|
Ok(Json(()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{
|
database::{
|
||||||
comment::{DbCommentInsertForm, DbCommentUpdateForm},
|
comment::{DbCommentInsertForm, DbCommentUpdateForm},
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
federation::activities::comment::{
|
federation::activities::comment::{
|
||||||
create_or_update_comment::CreateOrUpdateComment,
|
create_or_update_comment::CreateOrUpdateComment,
|
||||||
|
@ -29,13 +29,13 @@ use chrono::Utc;
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn create_comment(
|
pub(in crate::backend::api) async fn create_comment(
|
||||||
user: Extension<LocalUserView>,
|
user: Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(params): Form<CreateCommentParams>,
|
Form(params): Form<CreateCommentParams>,
|
||||||
) -> MyResult<Json<DbCommentView>> {
|
) -> MyResult<Json<DbCommentView>> {
|
||||||
validate_not_empty(¶ms.content)?;
|
validate_not_empty(¶ms.content)?;
|
||||||
let mut depth = 0;
|
let mut depth = 0;
|
||||||
if let Some(parent_id) = params.parent_id {
|
if let Some(parent_id) = params.parent_id {
|
||||||
let parent = DbComment::read(parent_id, &data)?;
|
let parent = DbComment::read(parent_id, &context)?;
|
||||||
if parent.deleted {
|
if parent.deleted {
|
||||||
return Err(anyhow!("Cant reply to deleted comment").into());
|
return Err(anyhow!("Cant reply to deleted comment").into());
|
||||||
}
|
}
|
||||||
|
@ -57,18 +57,18 @@ pub(in crate::backend::api) async fn create_comment(
|
||||||
published: Utc::now(),
|
published: Utc::now(),
|
||||||
updated: None,
|
updated: None,
|
||||||
};
|
};
|
||||||
let comment = DbComment::create(form, &data)?;
|
let comment = DbComment::create(form, &context)?;
|
||||||
|
|
||||||
// Set the ap_id which contains db id (so it is not know before inserting)
|
// Set the ap_id which contains db id (so it is not know before inserting)
|
||||||
let proto = http_protocol_str();
|
let proto = http_protocol_str();
|
||||||
let ap_id = format!("{}://{}/comment/{}", proto, data.domain(), comment.id.0).parse()?;
|
let ap_id = format!("{}://{}/comment/{}", proto, context.domain(), comment.id.0).parse()?;
|
||||||
let form = DbCommentUpdateForm {
|
let form = DbCommentUpdateForm {
|
||||||
ap_id: Some(ap_id),
|
ap_id: Some(ap_id),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let comment = DbComment::update(form, comment.id, &data)?;
|
let comment = DbComment::update(form, comment.id, &context)?;
|
||||||
|
|
||||||
CreateOrUpdateComment::send(&comment.comment, &data).await?;
|
CreateOrUpdateComment::send(&comment.comment, &context).await?;
|
||||||
|
|
||||||
Ok(Json(comment))
|
Ok(Json(comment))
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ pub(in crate::backend::api) async fn create_comment(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn edit_comment(
|
pub(in crate::backend::api) async fn edit_comment(
|
||||||
user: Extension<LocalUserView>,
|
user: Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(params): Form<EditCommentParams>,
|
Form(params): Form<EditCommentParams>,
|
||||||
) -> MyResult<Json<DbCommentView>> {
|
) -> MyResult<Json<DbCommentView>> {
|
||||||
if let Some(content) = ¶ms.content {
|
if let Some(content) = ¶ms.content {
|
||||||
|
@ -85,7 +85,7 @@ pub(in crate::backend::api) async fn edit_comment(
|
||||||
if params.content.is_none() && params.deleted.is_none() {
|
if params.content.is_none() && params.deleted.is_none() {
|
||||||
return Err(anyhow!("Edit has no parameters").into());
|
return Err(anyhow!("Edit has no parameters").into());
|
||||||
}
|
}
|
||||||
let orig_comment = DbComment::read(params.id, &data)?;
|
let orig_comment = DbComment::read(params.id, &context)?;
|
||||||
if orig_comment.creator_id != user.person.id {
|
if orig_comment.creator_id != user.person.id {
|
||||||
return Err(anyhow!("Cannot edit comment created by another user").into());
|
return Err(anyhow!("Cannot edit comment created by another user").into());
|
||||||
}
|
}
|
||||||
|
@ -95,17 +95,17 @@ pub(in crate::backend::api) async fn edit_comment(
|
||||||
updated: Some(Utc::now()),
|
updated: Some(Utc::now()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let comment = DbComment::update(form, params.id, &data)?;
|
let comment = DbComment::update(form, params.id, &context)?;
|
||||||
|
|
||||||
// federate
|
// federate
|
||||||
if orig_comment.content != comment.comment.content {
|
if orig_comment.content != comment.comment.content {
|
||||||
CreateOrUpdateComment::send(&comment.comment, &data).await?;
|
CreateOrUpdateComment::send(&comment.comment, &context).await?;
|
||||||
}
|
}
|
||||||
if !orig_comment.deleted && comment.comment.deleted {
|
if !orig_comment.deleted && comment.comment.deleted {
|
||||||
DeleteComment::send(&comment.comment, &data).await?;
|
DeleteComment::send(&comment.comment, &context).await?;
|
||||||
}
|
}
|
||||||
if orig_comment.deleted && !comment.comment.deleted {
|
if orig_comment.deleted && !comment.comment.deleted {
|
||||||
UndoDeleteComment::send(&comment.comment, &data).await?;
|
UndoDeleteComment::send(&comment.comment, &context).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Json(comment))
|
Ok(Json(comment))
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{database::IbisData, federation::activities::follow::Follow, utils::error::MyResult},
|
backend::{
|
||||||
|
database::IbisContext,
|
||||||
|
federation::activities::follow::Follow,
|
||||||
|
utils::error::MyResult,
|
||||||
|
},
|
||||||
common::{
|
common::{
|
||||||
instance::{DbInstance, FollowInstanceParams, GetInstanceParams, InstanceView},
|
instance::{DbInstance, FollowInstanceParams, GetInstanceParams, InstanceView},
|
||||||
user::LocalUserView,
|
user::LocalUserView,
|
||||||
|
@ -14,10 +18,10 @@ use axum_macros::debug_handler;
|
||||||
/// Retrieve details about an instance. If no id is provided, return local instance.
|
/// Retrieve details about an instance. If no id is provided, return local instance.
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn get_instance(
|
pub(in crate::backend::api) async fn get_instance(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(params): Form<GetInstanceParams>,
|
Form(params): Form<GetInstanceParams>,
|
||||||
) -> MyResult<Json<InstanceView>> {
|
) -> MyResult<Json<InstanceView>> {
|
||||||
let local_instance = DbInstance::read_view(params.id, &data)?;
|
let local_instance = DbInstance::read_view(params.id, &context)?;
|
||||||
Ok(Json(local_instance))
|
Ok(Json(local_instance))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,14 +30,14 @@ pub(in crate::backend::api) async fn get_instance(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn follow_instance(
|
pub(in crate::backend::api) async fn follow_instance(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(params): Form<FollowInstanceParams>,
|
Form(params): Form<FollowInstanceParams>,
|
||||||
) -> MyResult<Json<SuccessResponse>> {
|
) -> MyResult<Json<SuccessResponse>> {
|
||||||
let target = DbInstance::read(params.id, &data)?;
|
let target = DbInstance::read(params.id, &context)?;
|
||||||
let pending = !target.local;
|
let pending = !target.local;
|
||||||
DbInstance::follow(&user.person, &target, pending, &data)?;
|
DbInstance::follow(&user.person, &target, pending, &context)?;
|
||||||
let instance = DbInstance::read(params.id, &data)?;
|
let instance = DbInstance::read(params.id, &context)?;
|
||||||
Follow::send(user.person, &instance, &data).await?;
|
Follow::send(user.person, &instance, &context).await?;
|
||||||
Ok(Json(SuccessResponse::default()))
|
Ok(Json(SuccessResponse::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,16 +46,16 @@ pub(in crate::backend::api) async fn follow_instance(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(super) async fn resolve_instance(
|
pub(super) async fn resolve_instance(
|
||||||
Query(params): Query<ResolveObjectParams>,
|
Query(params): Query<ResolveObjectParams>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<DbInstance>> {
|
) -> MyResult<Json<DbInstance>> {
|
||||||
let instance: DbInstance = ObjectId::from(params.id).dereference(&data).await?;
|
let instance: DbInstance = ObjectId::from(params.id).dereference(&context).await?;
|
||||||
Ok(Json(instance))
|
Ok(Json(instance))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn list_remote_instances(
|
pub(in crate::backend::api) async fn list_remote_instances(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<Vec<DbInstance>>> {
|
) -> MyResult<Json<Vec<DbInstance>>> {
|
||||||
let instances = DbInstance::read_remote(&data)?;
|
let instances = DbInstance::read_remote(&context)?;
|
||||||
Ok(Json(instances))
|
Ok(Json(instances))
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
instance::{follow_instance, get_instance, resolve_instance},
|
instance::{follow_instance, get_instance, resolve_instance},
|
||||||
user::{get_user, login_user, logout_user, register_user},
|
user::{get_user, login_user, logout_user, register_user},
|
||||||
},
|
},
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
@ -83,12 +83,12 @@ fn check_is_admin(user: &LocalUserView) -> MyResult<()> {
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn site_view(
|
pub(in crate::backend::api) async fn site_view(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
user: Option<Extension<LocalUserView>>,
|
user: Option<Extension<LocalUserView>>,
|
||||||
) -> MyResult<Json<SiteView>> {
|
) -> MyResult<Json<SiteView>> {
|
||||||
Ok(Json(SiteView {
|
Ok(Json(SiteView {
|
||||||
my_profile: user.map(|u| u.0),
|
my_profile: user.map(|u| u.0),
|
||||||
config: data.config.options.clone(),
|
config: context.config.options.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ pub(in crate::backend::api) async fn site_view(
|
||||||
pub async fn edit_list(
|
pub async fn edit_list(
|
||||||
Query(query): Query<GetEditList>,
|
Query(query): Query<GetEditList>,
|
||||||
user: Option<Extension<LocalUserView>>,
|
user: Option<Extension<LocalUserView>>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<Vec<EditView>>> {
|
) -> MyResult<Json<Vec<EditView>>> {
|
||||||
let params = if let Some(article_id) = query.article_id {
|
let params = if let Some(article_id) = query.article_id {
|
||||||
ViewEditParams::ArticleId(article_id)
|
ViewEditParams::ArticleId(article_id)
|
||||||
|
@ -106,7 +106,7 @@ pub async fn edit_list(
|
||||||
} else {
|
} else {
|
||||||
return Err(anyhow!("Must provide article_id or person_id").into());
|
return Err(anyhow!("Must provide article_id or person_id").into());
|
||||||
};
|
};
|
||||||
Ok(Json(DbEdit::view(params, &user.map(|u| u.0), &data)?))
|
Ok(Json(DbEdit::view(params, &user.map(|u| u.0), &context)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trims the string param, and converts to None if it is empty
|
/// Trims the string param, and converts to None if it is empty
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{check_is_admin, empty_to_none};
|
use super::{check_is_admin, empty_to_none};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{conflict::DbConflict, read_jwt_secret, IbisData},
|
database::{conflict::DbConflict, read_jwt_secret, IbisContext},
|
||||||
utils::{
|
utils::{
|
||||||
error::MyResult,
|
error::MyResult,
|
||||||
validate::{validate_display_name, validate_user_name},
|
validate::{validate_display_name, validate_user_name},
|
||||||
|
@ -54,8 +54,8 @@ struct Claims {
|
||||||
pub exp: u64,
|
pub exp: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_login_token(person: &DbPerson, data: &Data<IbisData>) -> MyResult<String> {
|
fn generate_login_token(person: &DbPerson, context: &Data<IbisContext>) -> MyResult<String> {
|
||||||
let hostname = data.domain().to_string();
|
let hostname = context.domain().to_string();
|
||||||
let claims = Claims {
|
let claims = Claims {
|
||||||
sub: person.username.clone(),
|
sub: person.username.clone(),
|
||||||
iss: hostname,
|
iss: hostname,
|
||||||
|
@ -63,58 +63,58 @@ fn generate_login_token(person: &DbPerson, data: &Data<IbisData>) -> MyResult<St
|
||||||
exp: get_current_timestamp() + 60 * 60 * 24 * 365,
|
exp: get_current_timestamp() + 60 * 60 * 24 * 365,
|
||||||
};
|
};
|
||||||
|
|
||||||
let secret = read_jwt_secret(data)?;
|
let secret = read_jwt_secret(context)?;
|
||||||
let key = EncodingKey::from_secret(secret.as_bytes());
|
let key = EncodingKey::from_secret(secret.as_bytes());
|
||||||
let jwt = encode(&Header::default(), &claims, &key)?;
|
let jwt = encode(&Header::default(), &claims, &key)?;
|
||||||
Ok(jwt)
|
Ok(jwt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn validate(jwt: &str, data: &IbisData) -> MyResult<LocalUserView> {
|
pub async fn validate(jwt: &str, context: &IbisContext) -> MyResult<LocalUserView> {
|
||||||
let validation = Validation::default();
|
let validation = Validation::default();
|
||||||
let secret = read_jwt_secret(data)?;
|
let secret = read_jwt_secret(context)?;
|
||||||
let key = DecodingKey::from_secret(secret.as_bytes());
|
let key = DecodingKey::from_secret(secret.as_bytes());
|
||||||
let claims = decode::<Claims>(jwt, &key, &validation)?;
|
let claims = decode::<Claims>(jwt, &key, &validation)?;
|
||||||
DbPerson::read_local_from_name(&claims.claims.sub, data)
|
DbPerson::read_local_from_name(&claims.claims.sub, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn register_user(
|
pub(in crate::backend::api) async fn register_user(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
jar: CookieJar,
|
jar: CookieJar,
|
||||||
Form(params): Form<RegisterUserParams>,
|
Form(params): Form<RegisterUserParams>,
|
||||||
) -> MyResult<(CookieJar, Json<LocalUserView>)> {
|
) -> MyResult<(CookieJar, Json<LocalUserView>)> {
|
||||||
if !data.config.options.registration_open {
|
if !context.config.options.registration_open {
|
||||||
return Err(anyhow!("Registration is closed").into());
|
return Err(anyhow!("Registration is closed").into());
|
||||||
}
|
}
|
||||||
validate_user_name(¶ms.username)?;
|
validate_user_name(¶ms.username)?;
|
||||||
let user = DbPerson::create_local(params.username, params.password, false, &data)?;
|
let user = DbPerson::create_local(params.username, params.password, false, &context)?;
|
||||||
let token = generate_login_token(&user.person, &data)?;
|
let token = generate_login_token(&user.person, &context)?;
|
||||||
let jar = jar.add(create_cookie(token, &data));
|
let jar = jar.add(create_cookie(token, &context));
|
||||||
Ok((jar, Json(user)))
|
Ok((jar, Json(user)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn login_user(
|
pub(in crate::backend::api) async fn login_user(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
jar: CookieJar,
|
jar: CookieJar,
|
||||||
Form(params): Form<LoginUserParams>,
|
Form(params): Form<LoginUserParams>,
|
||||||
) -> MyResult<(CookieJar, Json<LocalUserView>)> {
|
) -> MyResult<(CookieJar, Json<LocalUserView>)> {
|
||||||
let user = DbPerson::read_local_from_name(¶ms.username, &data)?;
|
let user = DbPerson::read_local_from_name(¶ms.username, &context)?;
|
||||||
let valid = verify(¶ms.password, &user.local_user.password_encrypted)?;
|
let valid = verify(¶ms.password, &user.local_user.password_encrypted)?;
|
||||||
if !valid {
|
if !valid {
|
||||||
return Err(anyhow!("Invalid login").into());
|
return Err(anyhow!("Invalid login").into());
|
||||||
}
|
}
|
||||||
let token = generate_login_token(&user.person, &data)?;
|
let token = generate_login_token(&user.person, &context)?;
|
||||||
let jar = jar.add(create_cookie(token, &data));
|
let jar = jar.add(create_cookie(token, &context));
|
||||||
Ok((jar, Json(user)))
|
Ok((jar, Json(user)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_cookie(jwt: String, data: &Data<IbisData>) -> Cookie<'static> {
|
fn create_cookie(jwt: String, context: &Data<IbisContext>) -> Cookie<'static> {
|
||||||
let mut cookie = Cookie::build((AUTH_COOKIE, jwt));
|
let mut cookie = Cookie::build((AUTH_COOKIE, jwt));
|
||||||
|
|
||||||
// Must not set cookie domain on localhost
|
// Must not set cookie domain on localhost
|
||||||
// https://stackoverflow.com/a/1188145
|
// https://stackoverflow.com/a/1188145
|
||||||
let domain = data.domain().to_string();
|
let domain = context.domain().to_string();
|
||||||
if !domain.starts_with("localhost") && !domain.starts_with("127.0.0.1") {
|
if !domain.starts_with("localhost") && !domain.starts_with("127.0.0.1") {
|
||||||
cookie = cookie.domain(domain);
|
cookie = cookie.domain(domain);
|
||||||
}
|
}
|
||||||
|
@ -131,45 +131,45 @@ fn create_cookie(jwt: String, data: &Data<IbisData>) -> Cookie<'static> {
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn logout_user(
|
pub(in crate::backend::api) async fn logout_user(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
jar: CookieJar,
|
jar: CookieJar,
|
||||||
) -> MyResult<(CookieJar, Json<SuccessResponse>)> {
|
) -> MyResult<(CookieJar, Json<SuccessResponse>)> {
|
||||||
let jar = jar.remove(create_cookie(String::new(), &data));
|
let jar = jar.remove(create_cookie(String::new(), &context));
|
||||||
Ok((jar, Json(SuccessResponse::default())))
|
Ok((jar, Json(SuccessResponse::default())))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn get_user(
|
pub(in crate::backend::api) async fn get_user(
|
||||||
params: Query<GetUserParams>,
|
params: Query<GetUserParams>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<DbPerson>> {
|
) -> MyResult<Json<DbPerson>> {
|
||||||
Ok(Json(DbPerson::read_from_name(
|
Ok(Json(DbPerson::read_from_name(
|
||||||
¶ms.name,
|
¶ms.name,
|
||||||
¶ms.domain,
|
¶ms.domain,
|
||||||
&data,
|
&context,
|
||||||
)?))
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn update_user_profile(
|
pub(in crate::backend::api) async fn update_user_profile(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
Form(mut params): Form<UpdateUserParams>,
|
Form(mut params): Form<UpdateUserParams>,
|
||||||
) -> MyResult<Json<SuccessResponse>> {
|
) -> MyResult<Json<SuccessResponse>> {
|
||||||
empty_to_none(&mut params.display_name);
|
empty_to_none(&mut params.display_name);
|
||||||
empty_to_none(&mut params.bio);
|
empty_to_none(&mut params.bio);
|
||||||
validate_display_name(¶ms.display_name)?;
|
validate_display_name(¶ms.display_name)?;
|
||||||
DbPerson::update_profile(¶ms, &data)?;
|
DbPerson::update_profile(¶ms, &context)?;
|
||||||
Ok(Json(SuccessResponse::default()))
|
Ok(Json(SuccessResponse::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(crate) async fn list_notifications(
|
pub(crate) async fn list_notifications(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<Vec<Notification>>> {
|
) -> MyResult<Json<Vec<Notification>>> {
|
||||||
let conflicts = DbConflict::list(&user.person, &data)?;
|
let conflicts = DbConflict::list(&user.person, &context)?;
|
||||||
let conflicts: Vec<_> = try_join_all(conflicts.into_iter().map(|c| {
|
let conflicts: Vec<_> = try_join_all(conflicts.into_iter().map(|c| {
|
||||||
let data = data.reset_request_count();
|
let data = context.reset_request_count();
|
||||||
async move { c.to_api_conflict(&data).await }
|
async move { c.to_api_conflict(&data).await }
|
||||||
}))
|
}))
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -180,7 +180,7 @@ pub(crate) async fn list_notifications(
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if check_is_admin(&user).is_ok() {
|
if check_is_admin(&user).is_ok() {
|
||||||
let articles = DbArticle::list_approval_required(&data)?;
|
let articles = DbArticle::list_approval_required(&context)?;
|
||||||
notifications.extend(
|
notifications.extend(
|
||||||
articles
|
articles
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -195,13 +195,13 @@ pub(crate) async fn list_notifications(
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(crate) async fn count_notifications(
|
pub(crate) async fn count_notifications(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<Json<usize>> {
|
) -> MyResult<Json<usize>> {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let conflicts = DbConflict::list(&user.person, &data)?;
|
let conflicts = DbConflict::list(&user.person, &context)?;
|
||||||
count += conflicts.len();
|
count += conflicts.len();
|
||||||
if check_is_admin(&user).is_ok() {
|
if check_is_admin(&user).is_ok() {
|
||||||
let articles = DbArticle::list_approval_required(&data)?;
|
let articles = DbArticle::list_approval_required(&context)?;
|
||||||
count += articles.len();
|
count += articles.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{
|
database::{
|
||||||
schema::{article, edit, instance},
|
schema::{article, edit, instance},
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
federation::objects::edits_collection::DbEditCollection,
|
federation::objects::edits_collection::DbEditCollection,
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
|
@ -46,15 +46,15 @@ impl DbArticle {
|
||||||
Ok(CollectionId::parse(&format!("{}/edits", self.ap_id))?)
|
Ok(CollectionId::parse(&format!("{}/edits", self.ap_id))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(form: DbArticleForm, data: &IbisData) -> MyResult<Self> {
|
pub fn create(form: DbArticleForm, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(article::table)
|
Ok(insert_into(article::table)
|
||||||
.values(form)
|
.values(form)
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_or_update(form: DbArticleForm, data: &IbisData) -> MyResult<Self> {
|
pub fn create_or_update(form: DbArticleForm, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(article::table)
|
Ok(insert_into(article::table)
|
||||||
.values(&form)
|
.values(&form)
|
||||||
.on_conflict(article::dsl::ap_id)
|
.on_conflict(article::dsl::ap_id)
|
||||||
|
@ -63,48 +63,48 @@ impl DbArticle {
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_text(id: ArticleId, text: &str, data: &IbisData) -> MyResult<Self> {
|
pub fn update_text(id: ArticleId, text: &str, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(diesel::update(article::dsl::article.find(id))
|
Ok(diesel::update(article::dsl::article.find(id))
|
||||||
.set(article::dsl::text.eq(text))
|
.set(article::dsl::text.eq(text))
|
||||||
.get_result::<Self>(conn.deref_mut())?)
|
.get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_protected(id: ArticleId, locked: bool, data: &IbisData) -> MyResult<Self> {
|
pub fn update_protected(id: ArticleId, locked: bool, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(diesel::update(article::dsl::article.find(id))
|
Ok(diesel::update(article::dsl::article.find(id))
|
||||||
.set(article::dsl::protected.eq(locked))
|
.set(article::dsl::protected.eq(locked))
|
||||||
.get_result::<Self>(conn.deref_mut())?)
|
.get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_approved(id: ArticleId, approved: bool, data: &IbisData) -> MyResult<Self> {
|
pub fn update_approved(id: ArticleId, approved: bool, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(diesel::update(article::dsl::article.find(id))
|
Ok(diesel::update(article::dsl::article.find(id))
|
||||||
.set(article::dsl::approved.eq(approved))
|
.set(article::dsl::approved.eq(approved))
|
||||||
.get_result::<Self>(conn.deref_mut())?)
|
.get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(id: ArticleId, data: &IbisData) -> MyResult<Self> {
|
pub fn delete(id: ArticleId, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(diesel::delete(article::dsl::article.find(id)).get_result::<Self>(conn.deref_mut())?)
|
Ok(diesel::delete(article::dsl::article.find(id)).get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(id: ArticleId, data: &IbisData) -> MyResult<Self> {
|
pub fn read(id: ArticleId, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(article::table
|
Ok(article::table
|
||||||
.find(id)
|
.find(id)
|
||||||
.get_result::<Self>(conn.deref_mut())?)
|
.get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_view(id: ArticleId, data: &IbisData) -> MyResult<DbArticleView> {
|
pub fn read_view(id: ArticleId, context: &IbisContext) -> MyResult<DbArticleView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let query = article::table
|
let query = article::table
|
||||||
.find(id)
|
.find(id)
|
||||||
.inner_join(instance::table)
|
.inner_join(instance::table)
|
||||||
.into_boxed();
|
.into_boxed();
|
||||||
let (article, instance): (DbArticle, DbInstance) = query.get_result(conn.deref_mut())?;
|
let (article, instance): (DbArticle, DbInstance) = query.get_result(conn.deref_mut())?;
|
||||||
let comments = DbComment::read_for_article(article.id, data)?;
|
let comments = DbComment::read_for_article(article.id, context)?;
|
||||||
let latest_version = article.latest_edit_version(data)?;
|
let latest_version = article.latest_edit_version(context)?;
|
||||||
Ok(DbArticleView {
|
Ok(DbArticleView {
|
||||||
article,
|
article,
|
||||||
instance,
|
instance,
|
||||||
|
@ -116,9 +116,9 @@ impl DbArticle {
|
||||||
pub fn read_view_title(
|
pub fn read_view_title(
|
||||||
title: &str,
|
title: &str,
|
||||||
domain: Option<String>,
|
domain: Option<String>,
|
||||||
data: &IbisData,
|
context: &IbisContext,
|
||||||
) -> MyResult<DbArticleView> {
|
) -> MyResult<DbArticleView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let (article, instance): (DbArticle, DbInstance) = {
|
let (article, instance): (DbArticle, DbInstance) = {
|
||||||
let query = article::table
|
let query = article::table
|
||||||
.inner_join(instance::table)
|
.inner_join(instance::table)
|
||||||
|
@ -131,8 +131,8 @@ impl DbArticle {
|
||||||
};
|
};
|
||||||
query.get_result(conn.deref_mut())?
|
query.get_result(conn.deref_mut())?
|
||||||
};
|
};
|
||||||
let comments = DbComment::read_for_article(article.id, data)?;
|
let comments = DbComment::read_for_article(article.id, context)?;
|
||||||
let latest_version = article.latest_edit_version(data)?;
|
let latest_version = article.latest_edit_version(context)?;
|
||||||
Ok(DbArticleView {
|
Ok(DbArticleView {
|
||||||
article,
|
article,
|
||||||
instance,
|
instance,
|
||||||
|
@ -141,8 +141,8 @@ impl DbArticle {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_from_ap_id(ap_id: &ObjectId<DbArticle>, data: &IbisData) -> MyResult<Self> {
|
pub fn read_from_ap_id(ap_id: &ObjectId<DbArticle>, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(article::table
|
Ok(article::table
|
||||||
.filter(article::dsl::ap_id.eq(ap_id))
|
.filter(article::dsl::ap_id.eq(ap_id))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
|
@ -154,9 +154,9 @@ impl DbArticle {
|
||||||
pub fn read_all(
|
pub fn read_all(
|
||||||
only_local: Option<bool>,
|
only_local: Option<bool>,
|
||||||
instance_id: Option<InstanceId>,
|
instance_id: Option<InstanceId>,
|
||||||
data: &IbisData,
|
context: &IbisContext,
|
||||||
) -> MyResult<Vec<Self>> {
|
) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let mut query = article::table
|
let mut query = article::table
|
||||||
.inner_join(edit::table)
|
.inner_join(edit::table)
|
||||||
.inner_join(instance::table)
|
.inner_join(instance::table)
|
||||||
|
@ -175,8 +175,8 @@ impl DbArticle {
|
||||||
Ok(query.get_results(&mut conn)?)
|
Ok(query.get_results(&mut conn)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search(query: &str, data: &IbisData) -> MyResult<Vec<Self>> {
|
pub fn search(query: &str, context: &IbisContext) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let replaced = query
|
let replaced = query
|
||||||
.replace('%', "\\%")
|
.replace('%', "\\%")
|
||||||
.replace('_', "\\_")
|
.replace('_', "\\_")
|
||||||
|
@ -191,8 +191,8 @@ impl DbArticle {
|
||||||
.get_results(conn.deref_mut())?)
|
.get_results(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn latest_edit_version(&self, data: &IbisData) -> MyResult<EditVersion> {
|
pub fn latest_edit_version(&self, context: &IbisContext) -> MyResult<EditVersion> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let latest_version: Option<EditVersion> = edit::table
|
let latest_version: Option<EditVersion> = edit::table
|
||||||
.filter(edit::dsl::article_id.eq(self.id))
|
.filter(edit::dsl::article_id.eq(self.id))
|
||||||
.order_by(edit::dsl::id.desc())
|
.order_by(edit::dsl::id.desc())
|
||||||
|
@ -206,8 +206,8 @@ impl DbArticle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_approval_required(data: &IbisData) -> MyResult<Vec<Self>> {
|
pub fn list_approval_required(context: &IbisContext) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let query = article::table
|
let query = article::table
|
||||||
.group_by(article::dsl::id)
|
.group_by(article::dsl::id)
|
||||||
.filter(article::dsl::approved.eq(false))
|
.filter(article::dsl::approved.eq(false))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{
|
use super::{
|
||||||
schema::{comment, person},
|
schema::{comment, person},
|
||||||
IbisData,
|
IbisContext,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::utils::error::MyResult,
|
backend::utils::error::MyResult,
|
||||||
|
@ -48,8 +48,8 @@ pub struct DbCommentUpdateForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbComment {
|
impl DbComment {
|
||||||
pub fn create(form: DbCommentInsertForm, data: &IbisData) -> MyResult<Self> {
|
pub fn create(form: DbCommentInsertForm, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(comment::table)
|
Ok(insert_into(comment::table)
|
||||||
.values(form)
|
.values(form)
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
|
@ -58,18 +58,18 @@ impl DbComment {
|
||||||
pub fn update(
|
pub fn update(
|
||||||
form: DbCommentUpdateForm,
|
form: DbCommentUpdateForm,
|
||||||
id: CommentId,
|
id: CommentId,
|
||||||
data: &IbisData,
|
context: &IbisContext,
|
||||||
) -> MyResult<DbCommentView> {
|
) -> MyResult<DbCommentView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let comment: DbComment = update(comment::table.find(id))
|
let comment: DbComment = update(comment::table.find(id))
|
||||||
.set(form)
|
.set(form)
|
||||||
.get_result(conn.deref_mut())?;
|
.get_result(conn.deref_mut())?;
|
||||||
let creator = DbPerson::read(comment.creator_id, data)?;
|
let creator = DbPerson::read(comment.creator_id, context)?;
|
||||||
Ok(DbCommentView { comment, creator })
|
Ok(DbCommentView { comment, creator })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_or_update(form: DbCommentInsertForm, data: &IbisData) -> MyResult<Self> {
|
pub fn create_or_update(form: DbCommentInsertForm, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(comment::table)
|
Ok(insert_into(comment::table)
|
||||||
.values(&form)
|
.values(&form)
|
||||||
.on_conflict(comment::dsl::ap_id)
|
.on_conflict(comment::dsl::ap_id)
|
||||||
|
@ -78,24 +78,24 @@ impl DbComment {
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(id: CommentId, data: &IbisData) -> MyResult<Self> {
|
pub fn read(id: CommentId, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(comment::table
|
Ok(comment::table
|
||||||
.find(id)
|
.find(id)
|
||||||
.get_result::<Self>(conn.deref_mut())?)
|
.get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_view(id: CommentId, data: &IbisData) -> MyResult<DbCommentView> {
|
pub fn read_view(id: CommentId, context: &IbisContext) -> MyResult<DbCommentView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let comment = comment::table
|
let comment = comment::table
|
||||||
.find(id)
|
.find(id)
|
||||||
.get_result::<Self>(conn.deref_mut())?;
|
.get_result::<Self>(conn.deref_mut())?;
|
||||||
let creator = DbPerson::read(comment.creator_id, data)?;
|
let creator = DbPerson::read(comment.creator_id, context)?;
|
||||||
Ok(DbCommentView { comment, creator })
|
Ok(DbCommentView { comment, creator })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_from_ap_id(ap_id: &ObjectId<DbComment>, data: &IbisData) -> MyResult<Self> {
|
pub fn read_from_ap_id(ap_id: &ObjectId<DbComment>, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(comment::table
|
Ok(comment::table
|
||||||
.filter(comment::dsl::ap_id.eq(ap_id))
|
.filter(comment::dsl::ap_id.eq(ap_id))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
|
@ -103,9 +103,9 @@ impl DbComment {
|
||||||
|
|
||||||
pub fn read_for_article(
|
pub fn read_for_article(
|
||||||
article_id: ArticleId,
|
article_id: ArticleId,
|
||||||
data: &IbisData,
|
context: &IbisContext,
|
||||||
) -> MyResult<Vec<DbCommentView>> {
|
) -> MyResult<Vec<DbCommentView>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let comments = comment::table
|
let comments = comment::table
|
||||||
.inner_join(person::table)
|
.inner_join(person::table)
|
||||||
.filter(comment::article_id.eq(article_id))
|
.filter(comment::article_id.eq(article_id))
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{
|
database::{
|
||||||
schema::{conflict, edit},
|
schema::{conflict, edit},
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
federation::activities::submit_article_update,
|
federation::activities::submit_article_update,
|
||||||
utils::{error::MyResult, generate_article_version},
|
utils::{error::MyResult, generate_article_version},
|
||||||
|
@ -57,23 +57,23 @@ pub struct DbConflictForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbConflict {
|
impl DbConflict {
|
||||||
pub fn create(form: &DbConflictForm, data: &IbisData) -> MyResult<Self> {
|
pub fn create(form: &DbConflictForm, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(conflict::table)
|
Ok(insert_into(conflict::table)
|
||||||
.values(form)
|
.values(form)
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list(person: &DbPerson, data: &IbisData) -> MyResult<Vec<Self>> {
|
pub fn list(person: &DbPerson, context: &IbisContext) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(conflict::table
|
Ok(conflict::table
|
||||||
.filter(conflict::dsl::creator_id.eq(person.id))
|
.filter(conflict::dsl::creator_id.eq(person.id))
|
||||||
.get_results(conn.deref_mut())?)
|
.get_results(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete merge conflict which was created by specific user
|
/// Delete merge conflict which was created by specific user
|
||||||
pub fn delete(id: ConflictId, creator_id: PersonId, data: &IbisData) -> MyResult<()> {
|
pub fn delete(id: ConflictId, creator_id: PersonId, context: &IbisContext) -> MyResult<()> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let conflict: Self = delete(
|
let conflict: Self = delete(
|
||||||
conflict::table
|
conflict::table
|
||||||
.filter(conflict::dsl::creator_id.eq(creator_id))
|
.filter(conflict::dsl::creator_id.eq(creator_id))
|
||||||
|
@ -89,13 +89,16 @@ impl DbConflict {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn to_api_conflict(&self, data: &Data<IbisData>) -> MyResult<Option<ApiConflict>> {
|
pub async fn to_api_conflict(
|
||||||
let article = DbArticle::read_view(self.article_id, data)?;
|
&self,
|
||||||
|
context: &Data<IbisContext>,
|
||||||
|
) -> MyResult<Option<ApiConflict>> {
|
||||||
|
let article = DbArticle::read_view(self.article_id, context)?;
|
||||||
// Make sure to get latest version from origin so that all conflicts can be resolved
|
// Make sure to get latest version from origin so that all conflicts can be resolved
|
||||||
let original_article = article.article.ap_id.dereference_forced(data).await?;
|
let original_article = article.article.ap_id.dereference_forced(context).await?;
|
||||||
|
|
||||||
// create common ancestor version
|
// create common ancestor version
|
||||||
let edits = DbEdit::list_for_article(original_article.id, data)?;
|
let edits = DbEdit::list_for_article(original_article.id, context)?;
|
||||||
let ancestor = generate_article_version(&edits, &self.previous_version_id)?;
|
let ancestor = generate_article_version(&edits, &self.previous_version_id)?;
|
||||||
|
|
||||||
let patch = Patch::from_str(&self.diff)?;
|
let patch = Patch::from_str(&self.diff)?;
|
||||||
|
@ -111,10 +114,10 @@ impl DbConflict {
|
||||||
self.previous_version_id.clone(),
|
self.previous_version_id.clone(),
|
||||||
&original_article,
|
&original_article,
|
||||||
self.creator_id,
|
self.creator_id,
|
||||||
data,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
DbConflict::delete(self.id, self.creator_id, data)?;
|
DbConflict::delete(self.id, self.creator_id, context)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Err(three_way_merge) => {
|
Err(three_way_merge) => {
|
||||||
|
@ -125,7 +128,7 @@ impl DbConflict {
|
||||||
three_way_merge,
|
three_way_merge,
|
||||||
summary: self.summary.clone(),
|
summary: self.summary.clone(),
|
||||||
article: original_article.clone(),
|
article: original_article.clone(),
|
||||||
previous_version_id: original_article.latest_edit_version(data)?,
|
previous_version_id: original_article.latest_edit_version(context)?,
|
||||||
published: self.published,
|
published: self.published,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::schema::{article, edit, person},
|
database::schema::{article, edit, person},
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
article::{DbArticle, DbEdit, EditVersion, EditView},
|
article::{DbArticle, DbEdit, EditVersion, EditView},
|
||||||
|
@ -77,8 +77,8 @@ impl DbEditForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbEdit {
|
impl DbEdit {
|
||||||
pub fn create(form: &DbEditForm, data: &IbisData) -> MyResult<Self> {
|
pub fn create(form: &DbEditForm, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(edit::table)
|
Ok(insert_into(edit::table)
|
||||||
.values(form)
|
.values(form)
|
||||||
.on_conflict(edit::dsl::ap_id)
|
.on_conflict(edit::dsl::ap_id)
|
||||||
|
@ -87,22 +87,22 @@ impl DbEdit {
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(version: &EditVersion, data: &IbisData) -> MyResult<Self> {
|
pub fn read(version: &EditVersion, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(edit::table
|
Ok(edit::table
|
||||||
.filter(edit::dsl::hash.eq(version))
|
.filter(edit::dsl::hash.eq(version))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_from_ap_id(ap_id: &ObjectId<DbEdit>, data: &IbisData) -> MyResult<Self> {
|
pub fn read_from_ap_id(ap_id: &ObjectId<DbEdit>, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(edit::table
|
Ok(edit::table
|
||||||
.filter(edit::dsl::ap_id.eq(ap_id))
|
.filter(edit::dsl::ap_id.eq(ap_id))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_for_article(id: ArticleId, data: &IbisData) -> MyResult<Vec<Self>> {
|
pub fn list_for_article(id: ArticleId, context: &IbisContext) -> MyResult<Vec<Self>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(edit::table
|
Ok(edit::table
|
||||||
.filter(edit::article_id.eq(id))
|
.filter(edit::article_id.eq(id))
|
||||||
.order(edit::published)
|
.order(edit::published)
|
||||||
|
@ -112,9 +112,9 @@ impl DbEdit {
|
||||||
pub fn view(
|
pub fn view(
|
||||||
params: ViewEditParams,
|
params: ViewEditParams,
|
||||||
user: &Option<LocalUserView>,
|
user: &Option<LocalUserView>,
|
||||||
data: &IbisData,
|
context: &IbisContext,
|
||||||
) -> MyResult<Vec<EditView>> {
|
) -> MyResult<Vec<EditView>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let person_id = user.as_ref().map(|u| u.person.id).unwrap_or(PersonId(-1));
|
let person_id = user.as_ref().map(|u| u.person.id).unwrap_or(PersonId(-1));
|
||||||
let query = edit::table
|
let query = edit::table
|
||||||
.inner_join(article::table)
|
.inner_join(article::table)
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{
|
database::{
|
||||||
schema::{article, comment, instance, instance_follow},
|
schema::{article, comment, instance, instance_follow},
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
federation::objects::{
|
federation::objects::{
|
||||||
articles_collection::DbArticleCollection,
|
articles_collection::DbArticleCollection,
|
||||||
|
@ -48,8 +48,8 @@ pub struct DbInstanceForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbInstance {
|
impl DbInstance {
|
||||||
pub fn create(form: &DbInstanceForm, data: &IbisData) -> MyResult<Self> {
|
pub fn create(form: &DbInstanceForm, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(instance::table)
|
Ok(insert_into(instance::table)
|
||||||
.values(form)
|
.values(form)
|
||||||
.on_conflict(instance::ap_id)
|
.on_conflict(instance::ap_id)
|
||||||
|
@ -58,34 +58,37 @@ impl DbInstance {
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(id: InstanceId, data: &IbisData) -> MyResult<Self> {
|
pub fn read(id: InstanceId, context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance::table.find(id).get_result(conn.deref_mut())?)
|
Ok(instance::table.find(id).get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_from_ap_id(
|
pub fn read_from_ap_id(
|
||||||
ap_id: &ObjectId<DbInstance>,
|
ap_id: &ObjectId<DbInstance>,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<DbInstance> {
|
) -> MyResult<DbInstance> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance::table
|
Ok(instance::table
|
||||||
.filter(instance::ap_id.eq(ap_id))
|
.filter(instance::ap_id.eq(ap_id))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_local(data: &IbisData) -> MyResult<Self> {
|
pub fn read_local(context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance::table
|
Ok(instance::table
|
||||||
.filter(instance::local.eq(true))
|
.filter(instance::local.eq(true))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_view(id: Option<InstanceId>, data: &Data<IbisData>) -> MyResult<InstanceView> {
|
pub fn read_view(
|
||||||
|
id: Option<InstanceId>,
|
||||||
|
context: &Data<IbisContext>,
|
||||||
|
) -> MyResult<InstanceView> {
|
||||||
let instance = match id {
|
let instance = match id {
|
||||||
Some(id) => DbInstance::read(id, data),
|
Some(id) => DbInstance::read(id, context),
|
||||||
None => DbInstance::read_local(data),
|
None => DbInstance::read_local(context),
|
||||||
}?;
|
}?;
|
||||||
let followers = DbInstance::read_followers(instance.id, data)?;
|
let followers = DbInstance::read_followers(instance.id, context)?;
|
||||||
|
|
||||||
Ok(InstanceView {
|
Ok(InstanceView {
|
||||||
instance,
|
instance,
|
||||||
|
@ -97,10 +100,10 @@ impl DbInstance {
|
||||||
follower: &DbPerson,
|
follower: &DbPerson,
|
||||||
instance: &DbInstance,
|
instance: &DbInstance,
|
||||||
pending_: bool,
|
pending_: bool,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
use instance_follow::dsl::{follower_id, instance_id, pending};
|
use instance_follow::dsl::{follower_id, instance_id, pending};
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let form = (
|
let form = (
|
||||||
instance_id.eq(instance.id),
|
instance_id.eq(instance.id),
|
||||||
follower_id.eq(follower.id),
|
follower_id.eq(follower.id),
|
||||||
|
@ -116,10 +119,10 @@ impl DbInstance {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_followers(id_: InstanceId, data: &IbisData) -> MyResult<Vec<DbPerson>> {
|
pub fn read_followers(id_: InstanceId, context: &IbisContext) -> MyResult<Vec<DbPerson>> {
|
||||||
use crate::backend::database::schema::person;
|
use crate::backend::database::schema::person;
|
||||||
use instance_follow::dsl::{follower_id, instance_id};
|
use instance_follow::dsl::{follower_id, instance_id};
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance_follow::table
|
Ok(instance_follow::table
|
||||||
.inner_join(person::table.on(follower_id.eq(person::id)))
|
.inner_join(person::table.on(follower_id.eq(person::id)))
|
||||||
.filter(instance_id.eq(id_))
|
.filter(instance_id.eq(id_))
|
||||||
|
@ -127,8 +130,8 @@ impl DbInstance {
|
||||||
.get_results(conn.deref_mut())?)
|
.get_results(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_remote(data: &Data<IbisData>) -> MyResult<Vec<DbInstance>> {
|
pub fn read_remote(context: &Data<IbisContext>) -> MyResult<Vec<DbInstance>> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance::table
|
Ok(instance::table
|
||||||
.filter(instance::local.eq(false))
|
.filter(instance::local.eq(false))
|
||||||
.get_results(conn.deref_mut())?)
|
.get_results(conn.deref_mut())?)
|
||||||
|
@ -136,8 +139,11 @@ impl DbInstance {
|
||||||
|
|
||||||
/// Read the instance where an article is hosted, based on a comment id.
|
/// Read the instance where an article is hosted, based on a comment id.
|
||||||
/// Note this may be different from the instance where the comment is hosted.
|
/// Note this may be different from the instance where the comment is hosted.
|
||||||
pub fn read_for_comment(comment_id: CommentId, data: &Data<IbisData>) -> MyResult<DbInstance> {
|
pub fn read_for_comment(
|
||||||
let mut conn = data.db_pool.get()?;
|
comment_id: CommentId,
|
||||||
|
context: &Data<IbisContext>,
|
||||||
|
) -> MyResult<DbInstance> {
|
||||||
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance::table
|
Ok(instance::table
|
||||||
.inner_join(article::table)
|
.inner_join(article::table)
|
||||||
.inner_join(comment::table.on(comment::article_id.eq(article::id)))
|
.inner_join(comment::table.on(comment::article_id.eq(article::id)))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::schema::instance_stats;
|
use super::schema::instance_stats;
|
||||||
use crate::backend::{IbisData, MyResult};
|
use crate::backend::{IbisContext, MyResult};
|
||||||
use diesel::{query_dsl::methods::FindDsl, Queryable, RunQueryDsl, Selectable};
|
use diesel::{query_dsl::methods::FindDsl, Queryable, RunQueryDsl, Selectable};
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ pub struct InstanceStats {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstanceStats {
|
impl InstanceStats {
|
||||||
pub fn read(data: &IbisData) -> MyResult<Self> {
|
pub fn read(context: &IbisContext) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance_stats::table.find(1).get_result(conn.deref_mut())?)
|
Ok(instance_stats::table.find(1).get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,13 @@ pub mod user;
|
||||||
pub type DbPool = Pool<ConnectionManager<PgConnection>>;
|
pub type DbPool = Pool<ConnectionManager<PgConnection>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct IbisData {
|
pub struct IbisContext {
|
||||||
pub db_pool: DbPool,
|
pub db_pool: DbPool,
|
||||||
pub config: IbisConfig,
|
pub config: IbisConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_jwt_secret(data: &IbisData) -> MyResult<String> {
|
pub fn read_jwt_secret(context: &IbisContext) -> MyResult<String> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(jwt_secret::table
|
Ok(jwt_secret::table
|
||||||
.select(jwt_secret::dsl::secret)
|
.select(jwt_secret::dsl::secret)
|
||||||
.first(conn.deref_mut())?)
|
.first(conn.deref_mut())?)
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{
|
database::{
|
||||||
schema::{instance, instance_follow, local_user, person},
|
schema::{instance, instance_follow, local_user, person},
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
utils::{error::MyResult, generate_keypair},
|
utils::{error::MyResult, generate_keypair},
|
||||||
},
|
},
|
||||||
|
@ -51,8 +51,8 @@ pub struct DbPersonForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DbPerson {
|
impl DbPerson {
|
||||||
pub fn create(person_form: &DbPersonForm, data: &Data<IbisData>) -> MyResult<Self> {
|
pub fn create(person_form: &DbPersonForm, context: &Data<IbisContext>) -> MyResult<Self> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(insert_into(person::table)
|
Ok(insert_into(person::table)
|
||||||
.values(person_form)
|
.values(person_form)
|
||||||
.on_conflict(person::dsl::ap_id)
|
.on_conflict(person::dsl::ap_id)
|
||||||
|
@ -61,8 +61,8 @@ impl DbPerson {
|
||||||
.get_result::<DbPerson>(conn.deref_mut())?)
|
.get_result::<DbPerson>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(id: PersonId, data: &IbisData) -> MyResult<DbPerson> {
|
pub fn read(id: PersonId, context: &IbisContext) -> MyResult<DbPerson> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(person::table.find(id).get_result(conn.deref_mut())?)
|
Ok(person::table.find(id).get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +70,10 @@ impl DbPerson {
|
||||||
username: String,
|
username: String,
|
||||||
password: String,
|
password: String,
|
||||||
admin: bool,
|
admin: bool,
|
||||||
data: &IbisData,
|
context: &IbisContext,
|
||||||
) -> MyResult<LocalUserView> {
|
) -> MyResult<LocalUserView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let domain = &data.config.federation.domain;
|
let domain = &context.config.federation.domain;
|
||||||
let ap_id = ObjectId::parse(&format!(
|
let ap_id = ObjectId::parse(&format!(
|
||||||
"{}://{domain}/user/{username}",
|
"{}://{domain}/user/{username}",
|
||||||
http_protocol_str()
|
http_protocol_str()
|
||||||
|
@ -115,9 +115,9 @@ impl DbPerson {
|
||||||
|
|
||||||
pub fn read_from_ap_id(
|
pub fn read_from_ap_id(
|
||||||
ap_id: &ObjectId<DbPerson>,
|
ap_id: &ObjectId<DbPerson>,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<DbPerson> {
|
) -> MyResult<DbPerson> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(person::table
|
Ok(person::table
|
||||||
.filter(person::dsl::ap_id.eq(ap_id))
|
.filter(person::dsl::ap_id.eq(ap_id))
|
||||||
.get_result(conn.deref_mut())?)
|
.get_result(conn.deref_mut())?)
|
||||||
|
@ -126,9 +126,9 @@ impl DbPerson {
|
||||||
pub fn read_from_name(
|
pub fn read_from_name(
|
||||||
username: &str,
|
username: &str,
|
||||||
domain: &Option<String>,
|
domain: &Option<String>,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<DbPerson> {
|
) -> MyResult<DbPerson> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let mut query = person::table
|
let mut query = person::table
|
||||||
.filter(person::username.eq(username))
|
.filter(person::username.eq(username))
|
||||||
.select(person::all_columns)
|
.select(person::all_columns)
|
||||||
|
@ -144,8 +144,8 @@ impl DbPerson {
|
||||||
Ok(query.get_result(conn.deref_mut())?)
|
Ok(query.get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_profile(params: &UpdateUserParams, data: &Data<IbisData>) -> MyResult<()> {
|
pub fn update_profile(params: &UpdateUserParams, context: &Data<IbisContext>) -> MyResult<()> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
diesel::update(person::table.find(params.person_id))
|
diesel::update(person::table.find(params.person_id))
|
||||||
.set((
|
.set((
|
||||||
person::dsl::display_name.eq(¶ms.display_name),
|
person::dsl::display_name.eq(¶ms.display_name),
|
||||||
|
@ -155,15 +155,15 @@ impl DbPerson {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_local_from_name(username: &str, data: &IbisData) -> MyResult<LocalUserView> {
|
pub fn read_local_from_name(username: &str, context: &IbisContext) -> MyResult<LocalUserView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
let (person, local_user) = person::table
|
let (person, local_user) = person::table
|
||||||
.inner_join(local_user::table)
|
.inner_join(local_user::table)
|
||||||
.filter(person::dsl::local)
|
.filter(person::dsl::local)
|
||||||
.filter(person::dsl::username.eq(username))
|
.filter(person::dsl::username.eq(username))
|
||||||
.get_result::<(DbPerson, DbLocalUser)>(conn.deref_mut())?;
|
.get_result::<(DbPerson, DbLocalUser)>(conn.deref_mut())?;
|
||||||
// TODO: handle this in single query
|
// TODO: handle this in single query
|
||||||
let following = Self::read_following(person.id, data)?;
|
let following = Self::read_following(person.id, context)?;
|
||||||
Ok(LocalUserView {
|
Ok(LocalUserView {
|
||||||
person,
|
person,
|
||||||
local_user,
|
local_user,
|
||||||
|
@ -171,9 +171,9 @@ impl DbPerson {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_following(id_: PersonId, data: &IbisData) -> MyResult<Vec<DbInstance>> {
|
fn read_following(id_: PersonId, context: &IbisContext) -> MyResult<Vec<DbInstance>> {
|
||||||
use instance_follow::dsl::{follower_id, instance_id};
|
use instance_follow::dsl::{follower_id, instance_id};
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = context.db_pool.get()?;
|
||||||
Ok(instance_follow::table
|
Ok(instance_follow::table
|
||||||
.inner_join(instance::table.on(instance_id.eq(instance::dsl::id)))
|
.inner_join(instance::table.on(instance_id.eq(instance::dsl::id)))
|
||||||
.filter(follower_id.eq(id_))
|
.filter(follower_id.eq(id_))
|
||||||
|
@ -182,13 +182,13 @@ impl DbPerson {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ghost user serves as placeholder for deleted accounts
|
/// Ghost user serves as placeholder for deleted accounts
|
||||||
pub fn ghost(data: &Data<IbisData>) -> MyResult<DbPerson> {
|
pub fn ghost(context: &Data<IbisContext>) -> MyResult<DbPerson> {
|
||||||
let username = "ghost";
|
let username = "ghost";
|
||||||
let read = DbPerson::read_from_name(username, &None, data);
|
let read = DbPerson::read_from_name(username, &None, context);
|
||||||
if read.is_ok() {
|
if read.is_ok() {
|
||||||
read
|
read
|
||||||
} else {
|
} else {
|
||||||
let domain = &data.config.federation.domain;
|
let domain = &context.config.federation.domain;
|
||||||
let ap_id = ObjectId::parse(&format!(
|
let ap_id = ObjectId::parse(&format!(
|
||||||
"{}://{domain}/user/{username}",
|
"{}://{domain}/user/{username}",
|
||||||
http_protocol_str()
|
http_protocol_str()
|
||||||
|
@ -206,7 +206,7 @@ impl DbPerson {
|
||||||
display_name: None,
|
display_name: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
};
|
};
|
||||||
DbPerson::create(&person_form, data)
|
DbPerson::create(&person_form, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::{activities::follow::Follow, send_activity},
|
federation::{activities::follow::Follow, send_activity},
|
||||||
utils::{
|
utils::{
|
||||||
error::{Error, MyResult},
|
error::{Error, MyResult},
|
||||||
|
@ -32,10 +32,10 @@ impl Accept {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
local_instance: DbInstance,
|
local_instance: DbInstance,
|
||||||
object: Follow,
|
object: Follow,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
let id = generate_activity_id(data)?;
|
let id = generate_activity_id(context)?;
|
||||||
let follower = object.actor.dereference(data).await?;
|
let follower = object.actor.dereference(context).await?;
|
||||||
let accept = Accept {
|
let accept = Accept {
|
||||||
actor: local_instance.ap_id.clone(),
|
actor: local_instance.ap_id.clone(),
|
||||||
object,
|
object,
|
||||||
|
@ -46,7 +46,7 @@ impl Accept {
|
||||||
&local_instance,
|
&local_instance,
|
||||||
accept,
|
accept,
|
||||||
vec![follower.shared_inbox_or_inbox()],
|
vec![follower.shared_inbox_or_inbox()],
|
||||||
data,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -55,7 +55,7 @@ impl Accept {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for Accept {
|
impl ActivityHandler for Accept {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -66,15 +66,15 @@ impl ActivityHandler for Accept {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
// add to follows
|
// add to follows
|
||||||
let person = self.object.actor.dereference_local(data).await?;
|
let person = self.object.actor.dereference_local(context).await?;
|
||||||
let instance = self.actor.dereference(data).await?;
|
let instance = self.actor.dereference(context).await?;
|
||||||
DbInstance::follow(&person, &instance, false, data)?;
|
DbInstance::follow(&person, &instance, false, context)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::{routes::AnnouncableActivities, send_activity},
|
federation::{routes::AnnouncableActivities, send_activity},
|
||||||
utils::{
|
utils::{
|
||||||
error::{Error, MyResult},
|
error::{Error, MyResult},
|
||||||
|
@ -32,7 +32,7 @@ pub struct AnnounceActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnnounceActivity {
|
impl AnnounceActivity {
|
||||||
pub async fn send(object: AnnouncableActivities, context: &Data<IbisData>) -> MyResult<()> {
|
pub async fn send(object: AnnouncableActivities, context: &Data<IbisContext>) -> MyResult<()> {
|
||||||
let id = generate_activity_id(context)?;
|
let id = generate_activity_id(context)?;
|
||||||
let instance = DbInstance::read_local(context)?;
|
let instance = DbInstance::read_local(context)?;
|
||||||
let announce = AnnounceActivity {
|
let announce = AnnounceActivity {
|
||||||
|
@ -56,7 +56,7 @@ impl AnnounceActivity {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for AnnounceActivity {
|
impl ActivityHandler for AnnounceActivity {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::generate_comment_activity_to;
|
use super::generate_comment_activity_to;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::{
|
federation::{
|
||||||
objects::comment::ApubComment,
|
objects::comment::ApubComment,
|
||||||
routes::AnnouncableActivities,
|
routes::AnnouncableActivities,
|
||||||
|
@ -40,16 +40,16 @@ pub struct CreateOrUpdateComment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateOrUpdateComment {
|
impl CreateOrUpdateComment {
|
||||||
pub async fn send(comment: &DbComment, data: &Data<IbisData>) -> MyResult<()> {
|
pub async fn send(comment: &DbComment, context: &Data<IbisContext>) -> MyResult<()> {
|
||||||
let instance = DbInstance::read_for_comment(comment.id, data)?;
|
let instance = DbInstance::read_for_comment(comment.id, context)?;
|
||||||
|
|
||||||
let kind = if comment.updated.is_none() {
|
let kind = if comment.updated.is_none() {
|
||||||
CreateOrUpdateType::Create
|
CreateOrUpdateType::Create
|
||||||
} else {
|
} else {
|
||||||
CreateOrUpdateType::Update
|
CreateOrUpdateType::Update
|
||||||
};
|
};
|
||||||
let object = comment.clone().into_json(data).await?;
|
let object = comment.clone().into_json(context).await?;
|
||||||
let id = generate_activity_id(data)?;
|
let id = generate_activity_id(context)?;
|
||||||
let activity = Self {
|
let activity = Self {
|
||||||
actor: object.attributed_to.clone(),
|
actor: object.attributed_to.clone(),
|
||||||
object,
|
object,
|
||||||
|
@ -58,15 +58,15 @@ impl CreateOrUpdateComment {
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
let activity = AnnouncableActivities::CreateOrUpdateComment(activity);
|
let activity = AnnouncableActivities::CreateOrUpdateComment(activity);
|
||||||
let creator = DbPerson::read(comment.creator_id, data)?;
|
let creator = DbPerson::read(comment.creator_id, context)?;
|
||||||
send_activity_to_instance(&creator, activity, &instance, data).await?;
|
send_activity_to_instance(&creator, activity, &instance, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for CreateOrUpdateComment {
|
impl ActivityHandler for CreateOrUpdateComment {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -77,18 +77,18 @@ impl ActivityHandler for CreateOrUpdateComment {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(&self.id, self.object.id.inner())?;
|
verify_domains_match(&self.id, self.object.id.inner())?;
|
||||||
verify_domains_match(&self.id, self.actor.inner())?;
|
verify_domains_match(&self.id, self.actor.inner())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
let comment = DbComment::from_json(self.object, data).await?;
|
let comment = DbComment::from_json(self.object, context).await?;
|
||||||
|
|
||||||
let instance = DbInstance::read_for_comment(comment.id, data)?;
|
let instance = DbInstance::read_for_comment(comment.id, context)?;
|
||||||
if instance.local {
|
if instance.local {
|
||||||
Self::send(&comment, data).await?;
|
Self::send(&comment, context).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::generate_comment_activity_to;
|
use super::generate_comment_activity_to;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{comment::DbCommentUpdateForm, IbisData},
|
database::{comment::DbCommentUpdateForm, IbisContext},
|
||||||
federation::{routes::AnnouncableActivities, send_activity_to_instance},
|
federation::{routes::AnnouncableActivities, send_activity_to_instance},
|
||||||
utils::{
|
utils::{
|
||||||
error::{Error, MyResult},
|
error::{Error, MyResult},
|
||||||
|
@ -38,9 +38,9 @@ impl DeleteComment {
|
||||||
comment: &DbComment,
|
comment: &DbComment,
|
||||||
creator: &DbPerson,
|
creator: &DbPerson,
|
||||||
instance: &DbInstance,
|
instance: &DbInstance,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<Self> {
|
) -> MyResult<Self> {
|
||||||
let id = generate_activity_id(data)?;
|
let id = generate_activity_id(context)?;
|
||||||
Ok(DeleteComment {
|
Ok(DeleteComment {
|
||||||
actor: creator.ap_id.clone(),
|
actor: creator.ap_id.clone(),
|
||||||
object: comment.ap_id.clone(),
|
object: comment.ap_id.clone(),
|
||||||
|
@ -49,19 +49,19 @@ impl DeleteComment {
|
||||||
id,
|
id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub async fn send(comment: &DbComment, data: &Data<IbisData>) -> MyResult<()> {
|
pub async fn send(comment: &DbComment, context: &Data<IbisContext>) -> MyResult<()> {
|
||||||
let instance = DbInstance::read_for_comment(comment.id, data)?;
|
let instance = DbInstance::read_for_comment(comment.id, context)?;
|
||||||
let creator = DbPerson::read(comment.creator_id, data)?;
|
let creator = DbPerson::read(comment.creator_id, context)?;
|
||||||
let activity = Self::new(comment, &creator, &instance, data)?;
|
let activity = Self::new(comment, &creator, &instance, context)?;
|
||||||
let activity = AnnouncableActivities::DeleteComment(activity);
|
let activity = AnnouncableActivities::DeleteComment(activity);
|
||||||
send_activity_to_instance(&creator, activity, &instance, data).await?;
|
send_activity_to_instance(&creator, activity, &instance, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for DeleteComment {
|
impl ActivityHandler for DeleteComment {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -72,24 +72,24 @@ impl ActivityHandler for DeleteComment {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(self.actor.inner(), &self.id)?;
|
verify_domains_match(self.actor.inner(), &self.id)?;
|
||||||
verify_domains_match(self.actor.inner(), self.object.inner())?;
|
verify_domains_match(self.actor.inner(), self.object.inner())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
let form = DbCommentUpdateForm {
|
let form = DbCommentUpdateForm {
|
||||||
deleted: Some(true),
|
deleted: Some(true),
|
||||||
updated: Some(Utc::now()),
|
updated: Some(Utc::now()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let comment = self.object.dereference(data).await?;
|
let comment = self.object.dereference(context).await?;
|
||||||
DbComment::update(form, comment.id, data)?;
|
DbComment::update(form, comment.id, context)?;
|
||||||
|
|
||||||
let instance = DbInstance::read_for_comment(comment.id, data)?;
|
let instance = DbInstance::read_for_comment(comment.id, context)?;
|
||||||
if instance.local {
|
if instance.local {
|
||||||
Self::send(&comment, data).await?;
|
Self::send(&comment, context).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{delete_comment::DeleteComment, generate_comment_activity_to};
|
use super::{delete_comment::DeleteComment, generate_comment_activity_to};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{comment::DbCommentUpdateForm, IbisData},
|
database::{comment::DbCommentUpdateForm, IbisContext},
|
||||||
federation::{routes::AnnouncableActivities, send_activity_to_instance},
|
federation::{routes::AnnouncableActivities, send_activity_to_instance},
|
||||||
utils::{
|
utils::{
|
||||||
error::{Error, MyResult},
|
error::{Error, MyResult},
|
||||||
|
@ -37,11 +37,11 @@ pub struct UndoDeleteComment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UndoDeleteComment {
|
impl UndoDeleteComment {
|
||||||
pub async fn send(comment: &DbComment, data: &Data<IbisData>) -> MyResult<()> {
|
pub async fn send(comment: &DbComment, context: &Data<IbisContext>) -> MyResult<()> {
|
||||||
let instance = DbInstance::read_for_comment(comment.id, data)?;
|
let instance = DbInstance::read_for_comment(comment.id, context)?;
|
||||||
let id = generate_activity_id(data)?;
|
let id = generate_activity_id(context)?;
|
||||||
let creator = DbPerson::read(comment.creator_id, data)?;
|
let creator = DbPerson::read(comment.creator_id, context)?;
|
||||||
let object = DeleteComment::new(comment, &creator, &instance, data)?;
|
let object = DeleteComment::new(comment, &creator, &instance, context)?;
|
||||||
let activity = UndoDeleteComment {
|
let activity = UndoDeleteComment {
|
||||||
actor: creator.ap_id.clone(),
|
actor: creator.ap_id.clone(),
|
||||||
object,
|
object,
|
||||||
|
@ -50,14 +50,14 @@ impl UndoDeleteComment {
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
let activity = AnnouncableActivities::UndoDeleteComment(activity);
|
let activity = AnnouncableActivities::UndoDeleteComment(activity);
|
||||||
send_activity_to_instance(&creator, activity, &instance, data).await?;
|
send_activity_to_instance(&creator, activity, &instance, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for UndoDeleteComment {
|
impl ActivityHandler for UndoDeleteComment {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -68,24 +68,24 @@ impl ActivityHandler for UndoDeleteComment {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
|
verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
|
||||||
verify_domains_match(self.actor.inner(), &self.id)?;
|
verify_domains_match(self.actor.inner(), &self.id)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
let form = DbCommentUpdateForm {
|
let form = DbCommentUpdateForm {
|
||||||
deleted: Some(false),
|
deleted: Some(false),
|
||||||
updated: Some(Utc::now()),
|
updated: Some(Utc::now()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let comment = self.object.object.dereference(data).await?;
|
let comment = self.object.object.dereference(context).await?;
|
||||||
DbComment::update(form, comment.id, data)?;
|
DbComment::update(form, comment.id, context)?;
|
||||||
|
|
||||||
let instance = DbInstance::read_for_comment(comment.id, data)?;
|
let instance = DbInstance::read_for_comment(comment.id, context)?;
|
||||||
if instance.local {
|
if instance.local {
|
||||||
Self::send(&comment, data).await?;
|
Self::send(&comment, context).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::objects::article::ApubArticle,
|
federation::objects::article::ApubArticle,
|
||||||
utils::{
|
utils::{
|
||||||
error::{Error, MyResult},
|
error::{Error, MyResult},
|
||||||
|
@ -32,11 +32,14 @@ pub struct CreateArticle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateArticle {
|
impl CreateArticle {
|
||||||
pub async fn send_to_followers(article: DbArticle, data: &Data<IbisData>) -> MyResult<()> {
|
pub async fn send_to_followers(
|
||||||
let local_instance = DbInstance::read_local(data)?;
|
article: DbArticle,
|
||||||
let object = article.clone().into_json(data).await?;
|
context: &Data<IbisContext>,
|
||||||
let id = generate_activity_id(data)?;
|
) -> MyResult<()> {
|
||||||
let to = local_instance.follower_ids(data)?;
|
let local_instance = DbInstance::read_local(context)?;
|
||||||
|
let object = article.clone().into_json(context).await?;
|
||||||
|
let id = generate_activity_id(context)?;
|
||||||
|
let to = local_instance.follower_ids(context)?;
|
||||||
let create = CreateArticle {
|
let create = CreateArticle {
|
||||||
actor: local_instance.ap_id.clone(),
|
actor: local_instance.ap_id.clone(),
|
||||||
to,
|
to,
|
||||||
|
@ -45,14 +48,14 @@ impl CreateArticle {
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
local_instance
|
local_instance
|
||||||
.send_to_followers(create, vec![], data)
|
.send_to_followers(create, vec![], context)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for CreateArticle {
|
impl ActivityHandler for CreateArticle {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -63,15 +66,17 @@ impl ActivityHandler for CreateArticle {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
let article = DbArticle::from_json(self.object.clone(), data).await?;
|
let article = DbArticle::from_json(self.object.clone(), context).await?;
|
||||||
if article.local {
|
if article.local {
|
||||||
let local_instance = DbInstance::read_local(data)?;
|
let local_instance = DbInstance::read_local(context)?;
|
||||||
local_instance.send_to_followers(self, vec![], data).await?;
|
local_instance
|
||||||
|
.send_to_followers(self, vec![], context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::{activities::accept::Accept, send_activity},
|
federation::{activities::accept::Accept, send_activity},
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
|
@ -28,22 +28,26 @@ pub struct Follow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Follow {
|
impl Follow {
|
||||||
pub async fn send(actor: DbPerson, to: &DbInstance, data: &Data<IbisData>) -> MyResult<()> {
|
pub async fn send(
|
||||||
let id = generate_activity_id(data)?;
|
actor: DbPerson,
|
||||||
|
to: &DbInstance,
|
||||||
|
context: &Data<IbisContext>,
|
||||||
|
) -> MyResult<()> {
|
||||||
|
let id = generate_activity_id(context)?;
|
||||||
let follow = Follow {
|
let follow = Follow {
|
||||||
actor: actor.ap_id.clone(),
|
actor: actor.ap_id.clone(),
|
||||||
object: to.ap_id.clone(),
|
object: to.ap_id.clone(),
|
||||||
kind: Default::default(),
|
kind: Default::default(),
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
send_activity(&actor, follow, vec![to.shared_inbox_or_inbox()], data).await?;
|
send_activity(&actor, follow, vec![to.shared_inbox_or_inbox()], context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for Follow {
|
impl ActivityHandler for Follow {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -54,18 +58,18 @@ impl ActivityHandler for Follow {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
let actor = self.actor.dereference(data).await?;
|
let actor = self.actor.dereference(context).await?;
|
||||||
let local_instance = DbInstance::read_local(data)?;
|
let local_instance = DbInstance::read_local(context)?;
|
||||||
verify_urls_match(self.object.inner(), local_instance.ap_id.inner())?;
|
verify_urls_match(self.object.inner(), local_instance.ap_id.inner())?;
|
||||||
DbInstance::follow(&actor, &local_instance, false, data)?;
|
DbInstance::follow(&actor, &local_instance, false, context)?;
|
||||||
|
|
||||||
// send back an accept
|
// send back an accept
|
||||||
Accept::send(local_instance, self, data).await?;
|
Accept::send(local_instance, self, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{edit::DbEditForm, IbisData},
|
database::{edit::DbEditForm, IbisContext},
|
||||||
federation::activities::{
|
federation::activities::{
|
||||||
update_local_article::UpdateLocalArticle,
|
update_local_article::UpdateLocalArticle,
|
||||||
update_remote_article::UpdateRemoteArticle,
|
update_remote_article::UpdateRemoteArticle,
|
||||||
|
@ -30,7 +30,7 @@ pub async fn submit_article_update(
|
||||||
previous_version: EditVersion,
|
previous_version: EditVersion,
|
||||||
original_article: &DbArticle,
|
original_article: &DbArticle,
|
||||||
creator_id: PersonId,
|
creator_id: PersonId,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut form = DbEditForm::new(
|
let mut form = DbEditForm::new(
|
||||||
original_article,
|
original_article,
|
||||||
|
@ -41,16 +41,16 @@ pub async fn submit_article_update(
|
||||||
false,
|
false,
|
||||||
)?;
|
)?;
|
||||||
if original_article.local {
|
if original_article.local {
|
||||||
let edit = DbEdit::create(&form, data)?;
|
let edit = DbEdit::create(&form, context)?;
|
||||||
let updated_article = DbArticle::update_text(edit.article_id, &new_text, data)?;
|
let updated_article = DbArticle::update_text(edit.article_id, &new_text, context)?;
|
||||||
|
|
||||||
UpdateLocalArticle::send(updated_article, vec![], data).await?;
|
UpdateLocalArticle::send(updated_article, vec![], context).await?;
|
||||||
} else {
|
} else {
|
||||||
// insert edit as pending, so only the creator can see it
|
// insert edit as pending, so only the creator can see it
|
||||||
form.pending = true;
|
form.pending = true;
|
||||||
let edit = DbEdit::create(&form, data)?;
|
let edit = DbEdit::create(&form, context)?;
|
||||||
let instance = DbInstance::read(original_article.instance_id, data)?;
|
let instance = DbInstance::read(original_article.instance_id, context)?;
|
||||||
UpdateRemoteArticle::send(edit, instance, data).await?;
|
UpdateRemoteArticle::send(edit, instance, context).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{
|
database::{
|
||||||
conflict::{DbConflict, DbConflictForm},
|
conflict::{DbConflict, DbConflictForm},
|
||||||
IbisData,
|
IbisContext,
|
||||||
},
|
},
|
||||||
federation::{objects::edit::ApubEdit, send_activity},
|
federation::{objects::edit::ApubEdit, send_activity},
|
||||||
utils::{
|
utils::{
|
||||||
|
@ -38,10 +38,10 @@ impl RejectEdit {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
edit: ApubEdit,
|
edit: ApubEdit,
|
||||||
user_instance: DbInstance,
|
user_instance: DbInstance,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
let local_instance = DbInstance::read_local(data)?;
|
let local_instance = DbInstance::read_local(context)?;
|
||||||
let id = generate_activity_id(data)?;
|
let id = generate_activity_id(context)?;
|
||||||
let reject = RejectEdit {
|
let reject = RejectEdit {
|
||||||
actor: local_instance.ap_id.clone(),
|
actor: local_instance.ap_id.clone(),
|
||||||
to: vec![user_instance.ap_id.into_inner()],
|
to: vec![user_instance.ap_id.into_inner()],
|
||||||
|
@ -53,7 +53,7 @@ impl RejectEdit {
|
||||||
&local_instance,
|
&local_instance,
|
||||||
reject,
|
reject,
|
||||||
vec![Url::parse(&user_instance.inbox_url)?],
|
vec![Url::parse(&user_instance.inbox_url)?],
|
||||||
data,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -62,7 +62,7 @@ impl RejectEdit {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for RejectEdit {
|
impl ActivityHandler for RejectEdit {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -73,14 +73,14 @@ impl ActivityHandler for RejectEdit {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
// cant convert this to DbEdit as it tries to apply patch and fails
|
// cant convert this to DbEdit as it tries to apply patch and fails
|
||||||
let article = self.object.object.dereference(data).await?;
|
let article = self.object.object.dereference(context).await?;
|
||||||
let creator = self.object.attributed_to.dereference(data).await?;
|
let creator = self.object.attributed_to.dereference(context).await?;
|
||||||
let form = DbConflictForm {
|
let form = DbConflictForm {
|
||||||
hash: EditVersion::new(&self.object.content),
|
hash: EditVersion::new(&self.object.content),
|
||||||
diff: self.object.content,
|
diff: self.object.content,
|
||||||
|
@ -89,7 +89,7 @@ impl ActivityHandler for RejectEdit {
|
||||||
article_id: article.id,
|
article_id: article.id,
|
||||||
previous_version_id: self.object.previous_version,
|
previous_version_id: self.object.previous_version,
|
||||||
};
|
};
|
||||||
DbConflict::create(&form, data)?;
|
DbConflict::create(&form, context)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::objects::article::ApubArticle,
|
federation::objects::article::ApubArticle,
|
||||||
utils::{
|
utils::{
|
||||||
error::{Error, MyResult},
|
error::{Error, MyResult},
|
||||||
|
@ -36,22 +36,22 @@ impl UpdateLocalArticle {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
article: DbArticle,
|
article: DbArticle,
|
||||||
extra_recipients: Vec<DbInstance>,
|
extra_recipients: Vec<DbInstance>,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
debug_assert!(article.local);
|
debug_assert!(article.local);
|
||||||
let local_instance = DbInstance::read_local(data)?;
|
let local_instance = DbInstance::read_local(context)?;
|
||||||
let id = generate_activity_id(data)?;
|
let id = generate_activity_id(context)?;
|
||||||
let mut to = local_instance.follower_ids(data)?;
|
let mut to = local_instance.follower_ids(context)?;
|
||||||
to.extend(extra_recipients.iter().map(|i| i.ap_id.inner().clone()));
|
to.extend(extra_recipients.iter().map(|i| i.ap_id.inner().clone()));
|
||||||
let update = UpdateLocalArticle {
|
let update = UpdateLocalArticle {
|
||||||
actor: local_instance.ap_id.clone(),
|
actor: local_instance.ap_id.clone(),
|
||||||
to,
|
to,
|
||||||
object: article.into_json(data).await?,
|
object: article.into_json(context).await?,
|
||||||
kind: Default::default(),
|
kind: Default::default(),
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
local_instance
|
local_instance
|
||||||
.send_to_followers(update, extra_recipients, data)
|
.send_to_followers(update, extra_recipients, context)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ impl UpdateLocalArticle {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for UpdateLocalArticle {
|
impl ActivityHandler for UpdateLocalArticle {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -70,13 +70,13 @@ impl ActivityHandler for UpdateLocalArticle {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, _data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, _context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Received on article follower instances (where article is always remote)
|
/// Received on article follower instances (where article is always remote)
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
DbArticle::from_json(self.object, data).await?;
|
DbArticle::from_json(self.object, context).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::{
|
federation::{
|
||||||
activities::{reject::RejectEdit, update_local_article::UpdateLocalArticle},
|
activities::{reject::RejectEdit, update_local_article::UpdateLocalArticle},
|
||||||
objects::edit::ApubEdit,
|
objects::edit::ApubEdit,
|
||||||
|
@ -45,14 +45,14 @@ impl UpdateRemoteArticle {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
edit: DbEdit,
|
edit: DbEdit,
|
||||||
article_instance: DbInstance,
|
article_instance: DbInstance,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
let local_instance = DbInstance::read_local(data)?;
|
let local_instance = DbInstance::read_local(context)?;
|
||||||
let id = generate_activity_id(data)?;
|
let id = generate_activity_id(context)?;
|
||||||
let update = UpdateRemoteArticle {
|
let update = UpdateRemoteArticle {
|
||||||
actor: local_instance.ap_id.clone(),
|
actor: local_instance.ap_id.clone(),
|
||||||
to: vec![article_instance.ap_id.into_inner()],
|
to: vec![article_instance.ap_id.into_inner()],
|
||||||
object: edit.into_json(data).await?,
|
object: edit.into_json(context).await?,
|
||||||
kind: Default::default(),
|
kind: Default::default(),
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
|
@ -60,7 +60,7 @@ impl UpdateRemoteArticle {
|
||||||
&local_instance,
|
&local_instance,
|
||||||
update,
|
update,
|
||||||
vec![Url::parse(&article_instance.inbox_url)?],
|
vec![Url::parse(&article_instance.inbox_url)?],
|
||||||
data,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -69,7 +69,7 @@ impl UpdateRemoteArticle {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for UpdateRemoteArticle {
|
impl ActivityHandler for UpdateRemoteArticle {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
|
@ -80,27 +80,31 @@ impl ActivityHandler for UpdateRemoteArticle {
|
||||||
self.actor.inner()
|
self.actor.inner()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(&self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
let article = DbArticle::read_from_ap_id(&self.object.object, data)?;
|
let article = DbArticle::read_from_ap_id(&self.object.object, context)?;
|
||||||
can_edit_article(&article, false)?;
|
can_edit_article(&article, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Received on article origin instance
|
/// Received on article origin instance
|
||||||
async fn receive(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||||
let local_article = DbArticle::read_from_ap_id(&self.object.object, data)?;
|
let local_article = DbArticle::read_from_ap_id(&self.object.object, context)?;
|
||||||
let patch = Patch::from_str(&self.object.content)?;
|
let patch = Patch::from_str(&self.object.content)?;
|
||||||
|
|
||||||
match apply(&local_article.text, &patch) {
|
match apply(&local_article.text, &patch) {
|
||||||
Ok(applied) => {
|
Ok(applied) => {
|
||||||
let edit = DbEdit::from_json(self.object.clone(), data).await?;
|
let edit = DbEdit::from_json(self.object.clone(), context).await?;
|
||||||
let article = DbArticle::update_text(edit.article_id, &applied, data)?;
|
let article = DbArticle::update_text(edit.article_id, &applied, context)?;
|
||||||
UpdateLocalArticle::send(article, vec![self.actor.dereference(data).await?], data)
|
UpdateLocalArticle::send(
|
||||||
.await?;
|
article,
|
||||||
|
vec![self.actor.dereference(context).await?],
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
let user_instance = self.actor.dereference(data).await?;
|
let user_instance = self.actor.dereference(context).await?;
|
||||||
RejectEdit::send(self.object.clone(), user_instance, data).await?;
|
RejectEdit::send(self.object.clone(), user_instance, context).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::utils::error::MyResult;
|
use super::utils::error::MyResult;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{config::IbisConfig, database::IbisData},
|
backend::{config::IbisConfig, database::IbisContext},
|
||||||
common::{instance::DbInstance, user::DbPerson},
|
common::{instance::DbInstance, user::DbPerson},
|
||||||
};
|
};
|
||||||
use activities::announce::AnnounceActivity;
|
use activities::announce::AnnounceActivity;
|
||||||
|
@ -25,14 +25,14 @@ pub async fn send_activity<Activity, ActorType: Actor>(
|
||||||
actor: &ActorType,
|
actor: &ActorType,
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
recipients: Vec<Url>,
|
recipients: Vec<Url>,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> Result<(), <Activity as ActivityHandler>::Error>
|
) -> Result<(), <Activity as ActivityHandler>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
||||||
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
||||||
{
|
{
|
||||||
let activity = WithContext::new_default(activity);
|
let activity = WithContext::new_default(activity);
|
||||||
queue_activity(&activity, actor, recipients, data).await?;
|
queue_activity(&activity, actor, recipients, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,13 @@ pub async fn send_activity_to_instance(
|
||||||
actor: &DbPerson,
|
actor: &DbPerson,
|
||||||
activity: AnnouncableActivities,
|
activity: AnnouncableActivities,
|
||||||
instance: &DbInstance,
|
instance: &DbInstance,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
if instance.local {
|
if instance.local {
|
||||||
AnnounceActivity::send(activity, data).await?;
|
AnnounceActivity::send(activity, context).await?;
|
||||||
} else {
|
} else {
|
||||||
let inbox_url = instance.inbox_url.parse()?;
|
let inbox_url = instance.inbox_url.parse()?;
|
||||||
send_activity(actor, activity, vec![inbox_url], data).await?;
|
send_activity(actor, activity, vec![inbox_url], context).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{article::DbArticleForm, IbisData},
|
database::{article::DbArticleForm, IbisContext},
|
||||||
federation::objects::edits_collection::DbEditCollection,
|
federation::objects::edits_collection::DbEditCollection,
|
||||||
utils::{error::Error, validate::validate_article_title},
|
utils::{error::Error, validate::validate_article_title},
|
||||||
},
|
},
|
||||||
|
@ -40,27 +40,27 @@ pub struct ApubArticle {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for DbArticle {
|
impl Object for DbArticle {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ApubArticle;
|
type Kind = ApubArticle;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_from_id(
|
async fn read_from_id(
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Option<Self>, Self::Error> {
|
) -> Result<Option<Self>, Self::Error> {
|
||||||
let article = DbArticle::read_from_ap_id(&object_id.into(), data).ok();
|
let article = DbArticle::read_from_ap_id(&object_id.into(), context).ok();
|
||||||
Ok(article)
|
Ok(article)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, context: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
let local_instance = DbInstance::read_local(data)?;
|
let local_instance = DbInstance::read_local(context)?;
|
||||||
Ok(ApubArticle {
|
Ok(ApubArticle {
|
||||||
kind: Default::default(),
|
kind: Default::default(),
|
||||||
id: self.ap_id.clone(),
|
id: self.ap_id.clone(),
|
||||||
attributed_to: local_instance.ap_id.clone(),
|
attributed_to: local_instance.ap_id.clone(),
|
||||||
to: vec![public(), local_instance.followers_url()?],
|
to: vec![public(), local_instance.followers_url()?],
|
||||||
edits: self.edits_id()?,
|
edits: self.edits_id()?,
|
||||||
latest_version: self.latest_edit_version(data)?,
|
latest_version: self.latest_edit_version(context)?,
|
||||||
content: self.text,
|
content: self.text,
|
||||||
name: self.title,
|
name: self.title,
|
||||||
protected: self.protected,
|
protected: self.protected,
|
||||||
|
@ -70,15 +70,18 @@ impl Object for DbArticle {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(json.id.inner(), expected_domain)?;
|
verify_domains_match(json.id.inner(), expected_domain)?;
|
||||||
verify_is_remote_object(&json.id, data)?;
|
verify_is_remote_object(&json.id, context)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
async fn from_json(
|
||||||
let instance = json.attributed_to.dereference(data).await?;
|
json: Self::Kind,
|
||||||
|
context: &Data<Self::DataType>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let instance = json.attributed_to.dereference(context).await?;
|
||||||
let mut form = DbArticleForm {
|
let mut form = DbArticleForm {
|
||||||
title: json.name,
|
title: json.name,
|
||||||
text: json.content,
|
text: json.content,
|
||||||
|
@ -89,9 +92,9 @@ impl Object for DbArticle {
|
||||||
approved: true,
|
approved: true,
|
||||||
};
|
};
|
||||||
form.title = validate_article_title(&form.title)?;
|
form.title = validate_article_title(&form.title)?;
|
||||||
let article = DbArticle::create_or_update(form, data)?;
|
let article = DbArticle::create_or_update(form, context)?;
|
||||||
|
|
||||||
json.edits.dereference(&article, data).await?;
|
json.edits.dereference(&article, context).await?;
|
||||||
|
|
||||||
Ok(article)
|
Ok(article)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{article::ApubArticle, comment::ApubComment};
|
use super::{article::ApubArticle, comment::ApubComment};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
common::{article::DbArticle, comment::DbComment},
|
common::{article::DbArticle, comment::DbComment},
|
||||||
|
@ -26,7 +26,7 @@ pub enum ApubArticleOrComment {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for DbArticleOrComment {
|
impl Object for DbArticleOrComment {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ApubArticleOrComment;
|
type Kind = ApubArticleOrComment;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
@ -34,38 +34,41 @@ impl Object for DbArticleOrComment {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_from_id(object_id: Url, data: &Data<Self::DataType>) -> MyResult<Option<Self>> {
|
async fn read_from_id(
|
||||||
let post = DbArticle::read_from_id(object_id.clone(), data).await?;
|
object_id: Url,
|
||||||
|
context: &Data<Self::DataType>,
|
||||||
|
) -> MyResult<Option<Self>> {
|
||||||
|
let post = DbArticle::read_from_id(object_id.clone(), context).await?;
|
||||||
Ok(match post {
|
Ok(match post {
|
||||||
Some(o) => Some(Self::Article(o)),
|
Some(o) => Some(Self::Article(o)),
|
||||||
None => DbComment::read_from_id(object_id, data)
|
None => DbComment::read_from_id(object_id, context)
|
||||||
.await?
|
.await?
|
||||||
.map(Self::Comment),
|
.map(Self::Comment),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete(self, data: &Data<Self::DataType>) -> MyResult<()> {
|
async fn delete(self, context: &Data<Self::DataType>) -> MyResult<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::Article(p) => p.delete(data).await,
|
Self::Article(p) => p.delete(context).await,
|
||||||
Self::Comment(c) => c.delete(data).await,
|
Self::Comment(c) => c.delete(context).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> MyResult<Self::Kind> {
|
async fn into_json(self, context: &Data<Self::DataType>) -> MyResult<Self::Kind> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Self::Article(p) => Self::Kind::Article(Box::new(p.into_json(data).await?)),
|
Self::Article(p) => Self::Kind::Article(Box::new(p.into_json(context).await?)),
|
||||||
Self::Comment(c) => Self::Kind::Comment(Box::new(c.into_json(data).await?)),
|
Self::Comment(c) => Self::Kind::Comment(Box::new(c.into_json(context).await?)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify(
|
async fn verify(
|
||||||
apub: &Self::Kind,
|
apub: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
match apub {
|
match apub {
|
||||||
Self::Kind::Article(a) => DbArticle::verify(a, expected_domain, data).await,
|
Self::Kind::Article(a) => DbArticle::verify(a, expected_domain, context).await,
|
||||||
Self::Kind::Comment(a) => DbComment::verify(a, expected_domain, data).await,
|
Self::Kind::Comment(a) => DbComment::verify(a, expected_domain, context).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::objects::article::ApubArticle,
|
federation::objects::article::ApubArticle,
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
|
@ -40,25 +40,25 @@ pub fn local_articles_url(domain: &str) -> MyResult<CollectionId<DbArticleCollec
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Collection for DbArticleCollection {
|
impl Collection for DbArticleCollection {
|
||||||
type Owner = ();
|
type Owner = ();
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ArticleCollection;
|
type Kind = ArticleCollection;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_local(
|
async fn read_local(
|
||||||
_owner: &Self::Owner,
|
_owner: &Self::Owner,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Self::Kind, Self::Error> {
|
) -> Result<Self::Kind, Self::Error> {
|
||||||
let local_articles = DbArticle::read_all(Some(true), None, data)?;
|
let local_articles = DbArticle::read_all(Some(true), None, context)?;
|
||||||
let articles = try_join_all(
|
let articles = try_join_all(
|
||||||
local_articles
|
local_articles
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|a| a.into_json(data))
|
.map(|a| a.into_json(context))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let collection = ArticleCollection {
|
let collection = ArticleCollection {
|
||||||
r#type: Default::default(),
|
r#type: Default::default(),
|
||||||
id: local_articles_url(&data.config.federation.domain)?.into(),
|
id: local_articles_url(&context.config.federation.domain)?.into(),
|
||||||
total_items: articles.len() as i32,
|
total_items: articles.len() as i32,
|
||||||
items: articles,
|
items: articles,
|
||||||
};
|
};
|
||||||
|
@ -68,7 +68,7 @@ impl Collection for DbArticleCollection {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
_data: &Data<Self::DataType>,
|
_context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(&json.id, expected_domain)?;
|
verify_domains_match(&json.id, expected_domain)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -77,20 +77,20 @@ impl Collection for DbArticleCollection {
|
||||||
async fn from_json(
|
async fn from_json(
|
||||||
apub: Self::Kind,
|
apub: Self::Kind,
|
||||||
_owner: &Self::Owner,
|
_owner: &Self::Owner,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let articles =
|
let articles = apub
|
||||||
apub.items
|
.items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|i| !i.id.is_local(data))
|
.filter(|i| !i.id.is_local(context))
|
||||||
.map(|article| async {
|
.map(|article| async {
|
||||||
let id = article.id.clone();
|
let id = article.id.clone();
|
||||||
let res = DbArticle::from_json(article, data).await;
|
let res = DbArticle::from_json(article, context).await;
|
||||||
if let Err(e) = &res {
|
if let Err(e) = &res {
|
||||||
warn!("Failed to synchronize article {id}: {e}");
|
warn!("Failed to synchronize article {id}: {e}");
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
});
|
});
|
||||||
join_all(articles).await;
|
join_all(articles).await;
|
||||||
|
|
||||||
Ok(DbArticleCollection(()))
|
Ok(DbArticleCollection(()))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::article_or_comment::DbArticleOrComment;
|
use super::article_or_comment::DbArticleOrComment;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{comment::DbCommentInsertForm, IbisData},
|
database::{comment::DbCommentInsertForm, IbisContext},
|
||||||
utils::{error::Error, validate::validate_comment_max_depth},
|
utils::{error::Error, validate::validate_comment_max_depth},
|
||||||
},
|
},
|
||||||
common::{article::DbArticle, comment::DbComment, user::DbPerson},
|
common::{article::DbArticle, comment::DbComment, user::DbPerson},
|
||||||
|
@ -37,24 +37,24 @@ pub struct ApubComment {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for DbComment {
|
impl Object for DbComment {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ApubComment;
|
type Kind = ApubComment;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_from_id(
|
async fn read_from_id(
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Option<Self>, Self::Error> {
|
) -> Result<Option<Self>, Self::Error> {
|
||||||
Ok(DbComment::read_from_ap_id(&object_id.into(), data).ok())
|
Ok(DbComment::read_from_ap_id(&object_id.into(), context).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, context: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
let creator = DbPerson::read(self.creator_id, data)?;
|
let creator = DbPerson::read(self.creator_id, context)?;
|
||||||
let in_reply_to = if let Some(parent_comment_id) = self.parent_id {
|
let in_reply_to = if let Some(parent_comment_id) = self.parent_id {
|
||||||
let comment = DbComment::read(parent_comment_id, data)?;
|
let comment = DbComment::read(parent_comment_id, context)?;
|
||||||
comment.ap_id.into_inner().into()
|
comment.ap_id.into_inner().into()
|
||||||
} else {
|
} else {
|
||||||
let article = DbArticle::read(self.article_id, data)?;
|
let article = DbArticle::read(self.article_id, context)?;
|
||||||
article.ap_id.into_inner().into()
|
article.ap_id.into_inner().into()
|
||||||
};
|
};
|
||||||
Ok(ApubComment {
|
Ok(ApubComment {
|
||||||
|
@ -72,15 +72,18 @@ impl Object for DbComment {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(json.id.inner(), expected_domain)?;
|
verify_domains_match(json.id.inner(), expected_domain)?;
|
||||||
verify_is_remote_object(&json.id, data)?;
|
verify_is_remote_object(&json.id, context)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
async fn from_json(
|
||||||
let parent = json.in_reply_to.dereference(data).await?;
|
json: Self::Kind,
|
||||||
|
context: &Data<Self::DataType>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let parent = json.in_reply_to.dereference(context).await?;
|
||||||
let (article_id, parent_id, depth) = match parent {
|
let (article_id, parent_id, depth) = match parent {
|
||||||
DbArticleOrComment::Article(db_article) => (db_article.id, None, 0),
|
DbArticleOrComment::Article(db_article) => (db_article.id, None, 0),
|
||||||
DbArticleOrComment::Comment(db_comment) => (
|
DbArticleOrComment::Comment(db_comment) => (
|
||||||
|
@ -89,7 +92,7 @@ impl Object for DbComment {
|
||||||
db_comment.depth + 1,
|
db_comment.depth + 1,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let creator = json.attributed_to.dereference(data).await?;
|
let creator = json.attributed_to.dereference(context).await?;
|
||||||
validate_comment_max_depth(depth)?;
|
validate_comment_max_depth(depth)?;
|
||||||
|
|
||||||
let form = DbCommentInsertForm {
|
let form = DbCommentInsertForm {
|
||||||
|
@ -105,6 +108,6 @@ impl Object for DbComment {
|
||||||
depth,
|
depth,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(DbComment::create_or_update(form, data)?)
|
Ok(DbComment::create_or_update(form, context)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{edit::DbEditForm, IbisData},
|
database::{edit::DbEditForm, IbisContext},
|
||||||
utils::error::Error,
|
utils::error::Error,
|
||||||
},
|
},
|
||||||
common::{
|
common::{
|
||||||
|
@ -43,20 +43,20 @@ pub struct ApubEdit {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for DbEdit {
|
impl Object for DbEdit {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ApubEdit;
|
type Kind = ApubEdit;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_from_id(
|
async fn read_from_id(
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Option<Self>, Self::Error> {
|
) -> Result<Option<Self>, Self::Error> {
|
||||||
Ok(DbEdit::read_from_ap_id(&object_id.into(), data).ok())
|
Ok(DbEdit::read_from_ap_id(&object_id.into(), context).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, context: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
let article = DbArticle::read_view(self.article_id, data)?;
|
let article = DbArticle::read_view(self.article_id, context)?;
|
||||||
let creator = DbPerson::read(self.creator_id, data)?;
|
let creator = DbPerson::read(self.creator_id, context)?;
|
||||||
Ok(ApubEdit {
|
Ok(ApubEdit {
|
||||||
kind: PatchType::Patch,
|
kind: PatchType::Patch,
|
||||||
id: self.ap_id,
|
id: self.ap_id,
|
||||||
|
@ -73,21 +73,24 @@ impl Object for DbEdit {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(json.id.inner(), expected_domain)?;
|
verify_domains_match(json.id.inner(), expected_domain)?;
|
||||||
verify_is_remote_object(&json.id, data)?;
|
verify_is_remote_object(&json.id, context)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
async fn from_json(
|
||||||
let article = json.object.dereference(data).await?;
|
json: Self::Kind,
|
||||||
let creator = match json.attributed_to.dereference(data).await {
|
context: &Data<Self::DataType>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let article = json.object.dereference(context).await?;
|
||||||
|
let creator = match json.attributed_to.dereference(context).await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// If actor couldnt be fetched, use ghost as placeholder
|
// If actor couldnt be fetched, use ghost as placeholder
|
||||||
warn!("Failed to fetch user {}: {e}", json.attributed_to);
|
warn!("Failed to fetch user {}: {e}", json.attributed_to);
|
||||||
DbPerson::ghost(data)?
|
DbPerson::ghost(context)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let form = DbEditForm {
|
let form = DbEditForm {
|
||||||
|
@ -101,7 +104,7 @@ impl Object for DbEdit {
|
||||||
published: json.published,
|
published: json.published,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
let edit = DbEdit::create(&form, data)?;
|
let edit = DbEdit::create(&form, context)?;
|
||||||
Ok(edit)
|
Ok(edit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{database::IbisData, federation::objects::edit::ApubEdit, utils::error::Error},
|
backend::{database::IbisContext, federation::objects::edit::ApubEdit, utils::error::Error},
|
||||||
common::article::{DbArticle, DbEdit},
|
common::article::{DbArticle, DbEdit},
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
|
@ -28,20 +28,20 @@ pub struct DbEditCollection();
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Collection for DbEditCollection {
|
impl Collection for DbEditCollection {
|
||||||
type Owner = DbArticle;
|
type Owner = DbArticle;
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ApubEditCollection;
|
type Kind = ApubEditCollection;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_local(
|
async fn read_local(
|
||||||
article: &Self::Owner,
|
article: &Self::Owner,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Self::Kind, Self::Error> {
|
) -> Result<Self::Kind, Self::Error> {
|
||||||
let article = DbArticle::read(article.id, data)?;
|
let article = DbArticle::read(article.id, context)?;
|
||||||
let edits = DbEdit::list_for_article(article.id, data)?;
|
let edits = DbEdit::list_for_article(article.id, context)?;
|
||||||
let edits = future::try_join_all(
|
let edits = future::try_join_all(
|
||||||
edits
|
edits
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| e.into_json(data))
|
.map(|e| e.into_json(context))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -57,7 +57,7 @@ impl Collection for DbEditCollection {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
_data: &Data<Self::DataType>,
|
_context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(&json.id, expected_domain)?;
|
verify_domains_match(&json.id, expected_domain)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -66,12 +66,16 @@ impl Collection for DbEditCollection {
|
||||||
async fn from_json(
|
async fn from_json(
|
||||||
apub: Self::Kind,
|
apub: Self::Kind,
|
||||||
owner: &Self::Owner,
|
owner: &Self::Owner,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
try_join_all(apub.items.into_iter().map(|i| DbEdit::from_json(i, data)))
|
try_join_all(
|
||||||
.await
|
apub.items
|
||||||
.map_err(|e| warn!("Failed to synchronize edits for {}: {e}", owner.ap_id))
|
.into_iter()
|
||||||
.ok();
|
.map(|i| DbEdit::from_json(i, context)),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| warn!("Failed to synchronize edits for {}: {e}", owner.ap_id))
|
||||||
|
.ok();
|
||||||
Ok(DbEditCollection())
|
Ok(DbEditCollection())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::instance_collection::DbInstanceCollection;
|
use super::instance_collection::DbInstanceCollection;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{instance::DbInstanceForm, IbisData},
|
database::{instance::DbInstanceForm, IbisContext},
|
||||||
federation::{objects::articles_collection::DbArticleCollection, send_activity},
|
federation::{objects::articles_collection::DbArticleCollection, send_activity},
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
|
@ -40,8 +40,8 @@ impl DbInstance {
|
||||||
Ok(Url::parse(&format!("{}/followers", self.ap_id.inner()))?)
|
Ok(Url::parse(&format!("{}/followers", self.ap_id.inner()))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn follower_ids(&self, data: &Data<IbisData>) -> MyResult<Vec<Url>> {
|
pub fn follower_ids(&self, context: &Data<IbisContext>) -> MyResult<Vec<Url>> {
|
||||||
Ok(DbInstance::read_followers(self.id, data)?
|
Ok(DbInstance::read_followers(self.id, context)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| f.ap_id.into())
|
.map(|f| f.ap_id.into())
|
||||||
.collect())
|
.collect())
|
||||||
|
@ -51,26 +51,26 @@ impl DbInstance {
|
||||||
&self,
|
&self,
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
extra_recipients: Vec<DbInstance>,
|
extra_recipients: Vec<DbInstance>,
|
||||||
data: &Data<IbisData>,
|
context: &Data<IbisContext>,
|
||||||
) -> Result<(), <Activity as ActivityHandler>::Error>
|
) -> Result<(), <Activity as ActivityHandler>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
||||||
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
<Activity as ActivityHandler>::Error: From<activitypub_federation::error::Error>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error>,
|
<Activity as ActivityHandler>::Error: From<Error>,
|
||||||
{
|
{
|
||||||
let mut inboxes: Vec<_> = DbInstance::read_followers(self.id, data)?
|
let mut inboxes: Vec<_> = DbInstance::read_followers(self.id, context)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| f.inbox_url())
|
.map(|f| f.inbox_url())
|
||||||
.collect();
|
.collect();
|
||||||
inboxes.extend(extra_recipients.into_iter().map(|i| i.inbox_url()));
|
inboxes.extend(extra_recipients.into_iter().map(|i| i.inbox_url()));
|
||||||
send_activity(self, activity, inboxes, data).await?;
|
send_activity(self, activity, inboxes, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for DbInstance {
|
impl Object for DbInstance {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ApubInstance;
|
type Kind = ApubInstance;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
@ -80,12 +80,12 @@ impl Object for DbInstance {
|
||||||
|
|
||||||
async fn read_from_id(
|
async fn read_from_id(
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Option<Self>, Self::Error> {
|
) -> Result<Option<Self>, Self::Error> {
|
||||||
Ok(DbInstance::read_from_ap_id(&object_id.into(), data).ok())
|
Ok(DbInstance::read_from_ap_id(&object_id.into(), context).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, _data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, _context: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
Ok(ApubInstance {
|
Ok(ApubInstance {
|
||||||
kind: Default::default(),
|
kind: Default::default(),
|
||||||
id: self.ap_id.clone(),
|
id: self.ap_id.clone(),
|
||||||
|
@ -100,14 +100,17 @@ impl Object for DbInstance {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(json.id.inner(), expected_domain)?;
|
verify_domains_match(json.id.inner(), expected_domain)?;
|
||||||
verify_is_remote_object(&json.id, data)?;
|
verify_is_remote_object(&json.id, context)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
async fn from_json(
|
||||||
|
json: Self::Kind,
|
||||||
|
context: &Data<Self::DataType>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
let domain = extract_domain(&json.id);
|
let domain = extract_domain(&json.id);
|
||||||
let form = DbInstanceForm {
|
let form = DbInstanceForm {
|
||||||
domain,
|
domain,
|
||||||
|
@ -121,20 +124,20 @@ impl Object for DbInstance {
|
||||||
last_refreshed_at: Utc::now(),
|
last_refreshed_at: Utc::now(),
|
||||||
local: false,
|
local: false,
|
||||||
};
|
};
|
||||||
let instance = DbInstance::create(&form, data)?;
|
let instance = DbInstance::create(&form, context)?;
|
||||||
|
|
||||||
// TODO: very inefficient to sync all articles every time
|
// TODO: very inefficient to sync all articles every time
|
||||||
let instance_ = instance.clone();
|
let instance_ = instance.clone();
|
||||||
let data_ = data.reset_request_count();
|
let context_ = context.reset_request_count();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Some(articles_url) = &instance_.articles_url {
|
if let Some(articles_url) = &instance_.articles_url {
|
||||||
let res = articles_url.dereference(&(), &data_).await;
|
let res = articles_url.dereference(&(), &context_).await;
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
tracing::warn!("error in spawn: {e}");
|
tracing::warn!("error in spawn: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(instances_url) = &instance_.instances_url {
|
if let Some(instances_url) = &instance_.instances_url {
|
||||||
let res = instances_url.dereference(&(), &data_).await;
|
let res = instances_url.dereference(&(), &context_).await;
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
tracing::warn!("error in spawn: {e}");
|
tracing::warn!("error in spawn: {e}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::instance::ApubInstance;
|
use super::instance::ApubInstance;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
utils::error::{Error, MyResult},
|
utils::error::{Error, MyResult},
|
||||||
},
|
},
|
||||||
common::{instance::DbInstance, utils::http_protocol_str},
|
common::{instance::DbInstance, utils::http_protocol_str},
|
||||||
|
@ -40,25 +40,25 @@ pub fn linked_instances_url(domain: &str) -> MyResult<CollectionId<DbInstanceCol
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Collection for DbInstanceCollection {
|
impl Collection for DbInstanceCollection {
|
||||||
type Owner = ();
|
type Owner = ();
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = InstanceCollection;
|
type Kind = InstanceCollection;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn read_local(
|
async fn read_local(
|
||||||
_owner: &Self::Owner,
|
_owner: &Self::Owner,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Self::Kind, Self::Error> {
|
) -> Result<Self::Kind, Self::Error> {
|
||||||
let instances = DbInstance::read_remote(data)?;
|
let instances = DbInstance::read_remote(context)?;
|
||||||
let instances = future::try_join_all(
|
let instances = future::try_join_all(
|
||||||
instances
|
instances
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|i| i.into_json(data))
|
.map(|i| i.into_json(context))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let collection = InstanceCollection {
|
let collection = InstanceCollection {
|
||||||
r#type: Default::default(),
|
r#type: Default::default(),
|
||||||
id: linked_instances_url(&data.config.federation.domain)?.into(),
|
id: linked_instances_url(&context.config.federation.domain)?.into(),
|
||||||
total_items: instances.len() as i32,
|
total_items: instances.len() as i32,
|
||||||
items: instances,
|
items: instances,
|
||||||
};
|
};
|
||||||
|
@ -68,7 +68,7 @@ impl Collection for DbInstanceCollection {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
_data: &Data<Self::DataType>,
|
_context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(&json.id, expected_domain)?;
|
verify_domains_match(&json.id, expected_domain)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -77,20 +77,20 @@ impl Collection for DbInstanceCollection {
|
||||||
async fn from_json(
|
async fn from_json(
|
||||||
apub: Self::Kind,
|
apub: Self::Kind,
|
||||||
_owner: &Self::Owner,
|
_owner: &Self::Owner,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let instances =
|
let instances = apub
|
||||||
apub.items
|
.items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|i| !i.id.is_local(data))
|
.filter(|i| !i.id.is_local(context))
|
||||||
.map(|instance| async {
|
.map(|instance| async {
|
||||||
let id = instance.id.clone();
|
let id = instance.id.clone();
|
||||||
let res = DbInstance::from_json(instance, data).await;
|
let res = DbInstance::from_json(instance, context).await;
|
||||||
if let Err(e) = &res {
|
if let Err(e) = &res {
|
||||||
warn!("Failed to synchronize article {id}: {e}");
|
warn!("Failed to synchronize article {id}: {e}");
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
});
|
});
|
||||||
join_all(instances).await;
|
join_all(instances).await;
|
||||||
|
|
||||||
Ok(DbInstanceCollection(()))
|
Ok(DbInstanceCollection(()))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{user::DbPersonForm, IbisData},
|
database::{user::DbPersonForm, IbisContext},
|
||||||
utils::error::Error,
|
utils::error::Error,
|
||||||
},
|
},
|
||||||
common::user::DbPerson,
|
common::user::DbPerson,
|
||||||
|
@ -33,7 +33,7 @@ pub struct ApubUser {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for DbPerson {
|
impl Object for DbPerson {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = ApubUser;
|
type Kind = ApubUser;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
@ -43,12 +43,12 @@ impl Object for DbPerson {
|
||||||
|
|
||||||
async fn read_from_id(
|
async fn read_from_id(
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
data: &Data<Self::DataType>,
|
context: &Data<Self::DataType>,
|
||||||
) -> Result<Option<Self>, Self::Error> {
|
) -> Result<Option<Self>, Self::Error> {
|
||||||
Ok(DbPerson::read_from_ap_id(&object_id.into(), data).ok())
|
Ok(DbPerson::read_from_ap_id(&object_id.into(), context).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, _data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, _context: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
Ok(ApubUser {
|
Ok(ApubUser {
|
||||||
kind: Default::default(),
|
kind: Default::default(),
|
||||||
id: __self.ap_id.clone(),
|
id: __self.ap_id.clone(),
|
||||||
|
@ -63,13 +63,16 @@ impl Object for DbPerson {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
json: &Self::Kind,
|
json: &Self::Kind,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
_data: &Data<Self::DataType>,
|
_context: &Data<Self::DataType>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
verify_domains_match(json.id.inner(), expected_domain)?;
|
verify_domains_match(json.id.inner(), expected_domain)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
async fn from_json(
|
||||||
|
json: Self::Kind,
|
||||||
|
context: &Data<Self::DataType>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
let form = DbPersonForm {
|
let form = DbPersonForm {
|
||||||
username: json.preferred_username,
|
username: json.preferred_username,
|
||||||
ap_id: json.id,
|
ap_id: json.id,
|
||||||
|
@ -81,7 +84,7 @@ impl Object for DbPerson {
|
||||||
display_name: json.name,
|
display_name: json.name,
|
||||||
bio: json.summary,
|
bio: json.summary,
|
||||||
};
|
};
|
||||||
DbPerson::create(&form, data)
|
DbPerson::create(&form, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use super::{
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::IbisData,
|
database::IbisContext,
|
||||||
federation::{
|
federation::{
|
||||||
activities::{
|
activities::{
|
||||||
accept::Accept,
|
accept::Accept,
|
||||||
|
@ -74,66 +74,66 @@ pub fn federation_routes() -> Router<()> {
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_instance(
|
async fn http_get_instance(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<FederationJson<WithContext<ApubInstance>>> {
|
) -> MyResult<FederationJson<WithContext<ApubInstance>>> {
|
||||||
let local_instance = DbInstance::read_local(&data)?;
|
let local_instance = DbInstance::read_local(&context)?;
|
||||||
let json_instance = local_instance.into_json(&data).await?;
|
let json_instance = local_instance.into_json(&context).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json_instance)))
|
Ok(FederationJson(WithContext::new_default(json_instance)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_person(
|
async fn http_get_person(
|
||||||
Path(name): Path<String>,
|
Path(name): Path<String>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<FederationJson<WithContext<ApubUser>>> {
|
) -> MyResult<FederationJson<WithContext<ApubUser>>> {
|
||||||
let person = DbPerson::read_local_from_name(&name, &data)?.person;
|
let person = DbPerson::read_local_from_name(&name, &context)?.person;
|
||||||
let json_person = person.into_json(&data).await?;
|
let json_person = person.into_json(&context).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json_person)))
|
Ok(FederationJson(WithContext::new_default(json_person)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_all_articles(
|
async fn http_get_all_articles(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<FederationJson<WithContext<ArticleCollection>>> {
|
) -> MyResult<FederationJson<WithContext<ArticleCollection>>> {
|
||||||
let collection = DbArticleCollection::read_local(&(), &data).await?;
|
let collection = DbArticleCollection::read_local(&(), &context).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(collection)))
|
Ok(FederationJson(WithContext::new_default(collection)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_linked_instances(
|
async fn http_get_linked_instances(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<FederationJson<WithContext<InstanceCollection>>> {
|
) -> MyResult<FederationJson<WithContext<InstanceCollection>>> {
|
||||||
let collection = DbInstanceCollection::read_local(&(), &data).await?;
|
let collection = DbInstanceCollection::read_local(&(), &context).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(collection)))
|
Ok(FederationJson(WithContext::new_default(collection)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_article(
|
async fn http_get_article(
|
||||||
Path(title): Path<String>,
|
Path(title): Path<String>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<FederationJson<WithContext<ApubArticle>>> {
|
) -> MyResult<FederationJson<WithContext<ApubArticle>>> {
|
||||||
let article = DbArticle::read_view_title(&title, None, &data)?;
|
let article = DbArticle::read_view_title(&title, None, &context)?;
|
||||||
let json = article.article.into_json(&data).await?;
|
let json = article.article.into_json(&context).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json)))
|
Ok(FederationJson(WithContext::new_default(json)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_article_edits(
|
async fn http_get_article_edits(
|
||||||
Path(title): Path<String>,
|
Path(title): Path<String>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<FederationJson<WithContext<ApubEditCollection>>> {
|
) -> MyResult<FederationJson<WithContext<ApubEditCollection>>> {
|
||||||
let article = DbArticle::read_view_title(&title, None, &data)?;
|
let article = DbArticle::read_view_title(&title, None, &context)?;
|
||||||
let json = DbEditCollection::read_local(&article.article, &data).await?;
|
let json = DbEditCollection::read_local(&article.article, &context).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json)))
|
Ok(FederationJson(WithContext::new_default(json)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn http_get_comment(
|
async fn http_get_comment(
|
||||||
Path(id): Path<i32>,
|
Path(id): Path<i32>,
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
) -> MyResult<FederationJson<WithContext<ApubComment>>> {
|
) -> MyResult<FederationJson<WithContext<ApubComment>>> {
|
||||||
let comment = DbComment::read(CommentId(id), &data)?;
|
let comment = DbComment::read(CommentId(id), &context)?;
|
||||||
let json = comment.into_json(&data).await?;
|
let json = comment.into_json(&context).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json)))
|
Ok(FederationJson(WithContext::new_default(json)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,10 +163,10 @@ pub enum AnnouncableActivities {
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub async fn http_post_inbox(
|
pub async fn http_post_inbox(
|
||||||
data: Data<IbisData>,
|
context: Data<IbisContext>,
|
||||||
activity_data: ActivityData,
|
activity_data: ActivityData,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
receive_activity::<WithContext<InboxActivities>, UserOrInstance, IbisData>(activity_data, &data)
|
receive_activity::<WithContext<InboxActivities>, UserOrInstance, _>(activity_data, &context)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ pub enum PersonOrInstanceType {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Object for UserOrInstance {
|
impl Object for UserOrInstance {
|
||||||
type DataType = IbisData;
|
type DataType = IbisContext;
|
||||||
type Kind = PersonOrInstance;
|
type Kind = PersonOrInstance;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
config::IbisConfig,
|
config::IbisConfig,
|
||||||
database::{article::DbArticleForm, instance::DbInstanceForm, IbisData},
|
database::{article::DbArticleForm, instance::DbInstanceForm, IbisContext},
|
||||||
federation::{activities::submit_article_update, VerifyUrlData},
|
federation::{activities::submit_article_update, VerifyUrlData},
|
||||||
utils::{
|
utils::{
|
||||||
error::{Error, MyResult},
|
error::{Error, MyResult},
|
||||||
|
@ -59,11 +59,11 @@ pub async fn start(
|
||||||
.get()?
|
.get()?
|
||||||
.run_pending_migrations(MIGRATIONS)
|
.run_pending_migrations(MIGRATIONS)
|
||||||
.expect("run migrations");
|
.expect("run migrations");
|
||||||
let ibis_data = IbisData { db_pool, config };
|
let context = IbisContext { db_pool, config };
|
||||||
let data = FederationConfig::builder()
|
let data = FederationConfig::builder()
|
||||||
.domain(ibis_data.config.federation.domain.clone())
|
.domain(context.config.federation.domain.clone())
|
||||||
.url_verifier(Box::new(VerifyUrlData(ibis_data.config.clone())))
|
.url_verifier(Box::new(VerifyUrlData(context.config.clone())))
|
||||||
.app_data(ibis_data)
|
.app_data(context)
|
||||||
.http_fetch_limit(1000)
|
.http_fetch_limit(1000)
|
||||||
.debug(cfg!(debug_assertions))
|
.debug(cfg!(debug_assertions))
|
||||||
.build()
|
.build()
|
||||||
|
@ -89,8 +89,8 @@ const MAIN_PAGE_DEFAULT_TEXT: &str = "Welcome to Ibis, the federated Wikipedia a
|
||||||
This main page can only be edited by the admin. Use it as an introduction for new users, \
|
This main page can only be edited by the admin. Use it as an introduction for new users, \
|
||||||
and to list interesting articles.";
|
and to list interesting articles.";
|
||||||
|
|
||||||
async fn setup(data: &Data<IbisData>) -> Result<(), Error> {
|
async fn setup(context: &Data<IbisContext>) -> Result<(), Error> {
|
||||||
let domain = &data.config.federation.domain;
|
let domain = &context.config.federation.domain;
|
||||||
let ap_id = ObjectId::parse(&format!("{}://{domain}", http_protocol_str()))?;
|
let ap_id = ObjectId::parse(&format!("{}://{domain}", http_protocol_str()))?;
|
||||||
let inbox_url = format!("{}://{domain}/inbox", http_protocol_str());
|
let inbox_url = format!("{}://{domain}/inbox", http_protocol_str());
|
||||||
let keypair = generate_keypair()?;
|
let keypair = generate_keypair()?;
|
||||||
|
@ -106,13 +106,13 @@ async fn setup(data: &Data<IbisData>) -> Result<(), Error> {
|
||||||
last_refreshed_at: Utc::now(),
|
last_refreshed_at: Utc::now(),
|
||||||
local: true,
|
local: true,
|
||||||
};
|
};
|
||||||
let instance = DbInstance::create(&form, data)?;
|
let instance = DbInstance::create(&form, context)?;
|
||||||
|
|
||||||
let person = DbPerson::create_local(
|
let person = DbPerson::create_local(
|
||||||
data.config.setup.admin_username.clone(),
|
context.config.setup.admin_username.clone(),
|
||||||
data.config.setup.admin_password.clone(),
|
context.config.setup.admin_password.clone(),
|
||||||
true,
|
true,
|
||||||
data,
|
context,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Create the main page which is shown by default
|
// Create the main page which is shown by default
|
||||||
|
@ -128,7 +128,7 @@ async fn setup(data: &Data<IbisData>) -> Result<(), Error> {
|
||||||
protected: true,
|
protected: true,
|
||||||
approved: true,
|
approved: true,
|
||||||
};
|
};
|
||||||
let article = DbArticle::create(form, data)?;
|
let article = DbArticle::create(form, context)?;
|
||||||
// also create an article so its included in most recently edited list
|
// also create an article so its included in most recently edited list
|
||||||
submit_article_update(
|
submit_article_update(
|
||||||
MAIN_PAGE_DEFAULT_TEXT.to_string(),
|
MAIN_PAGE_DEFAULT_TEXT.to_string(),
|
||||||
|
@ -136,12 +136,12 @@ async fn setup(data: &Data<IbisData>) -> Result<(), Error> {
|
||||||
EditVersion::default(),
|
EditVersion::default(),
|
||||||
&article,
|
&article,
|
||||||
person.person.id,
|
person.person.id,
|
||||||
data,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// create ghost user
|
// create ghost user
|
||||||
DbPerson::ghost(data)?;
|
DbPerson::ghost(context)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{api::user::validate, database::IbisData},
|
backend::{api::user::validate, database::IbisContext},
|
||||||
common::{Auth, AUTH_COOKIE},
|
common::{Auth, AUTH_COOKIE},
|
||||||
};
|
};
|
||||||
use axum::{body::Body, extract::State, http::Request, middleware::Next, response::Response};
|
use axum::{body::Body, extract::State, http::Request, middleware::Next, response::Response};
|
||||||
|
@ -14,7 +14,7 @@ pub(super) const FEDERATION_ROUTES_PREFIX: &str = "/federation_routes";
|
||||||
/// If user is authenticated sets extensions `Auth` and `LocalUserView`.
|
/// If user is authenticated sets extensions `Auth` and `LocalUserView`.
|
||||||
#[debug_middleware]
|
#[debug_middleware]
|
||||||
pub(super) async fn auth_middleware(
|
pub(super) async fn auth_middleware(
|
||||||
State(data): State<Arc<IbisData>>,
|
State(context): State<Arc<IbisContext>>,
|
||||||
mut request: Request<Body>,
|
mut request: Request<Body>,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
|
@ -34,7 +34,7 @@ pub(super) async fn auth_middleware(
|
||||||
let auth: HashSet<_> = headers.chain(cookies).map(|s| s.to_string()).collect();
|
let auth: HashSet<_> = headers.chain(cookies).map(|s| s.to_string()).collect();
|
||||||
|
|
||||||
for auth in auth {
|
for auth in auth {
|
||||||
if let Ok(local_user) = validate(&auth, &data).await {
|
if let Ok(local_user) = validate(&auth, &context).await {
|
||||||
request.extensions_mut().insert(Auth(Some(auth)));
|
request.extensions_mut().insert(Auth(Some(auth)));
|
||||||
request.extensions_mut().insert(local_user);
|
request.extensions_mut().insert(local_user);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{database::IbisData, utils::error::MyResult};
|
use super::{database::IbisContext, utils::error::MyResult};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{api::api_routes, federation::routes::federation_routes},
|
backend::{api::api_routes, federation::routes::federation_routes},
|
||||||
common::Auth,
|
common::Auth,
|
||||||
|
@ -31,7 +31,7 @@ mod middleware;
|
||||||
mod nodeinfo;
|
mod nodeinfo;
|
||||||
|
|
||||||
pub(super) async fn start_server(
|
pub(super) async fn start_server(
|
||||||
data: FederationConfig<IbisData>,
|
context: FederationConfig<IbisContext>,
|
||||||
override_hostname: Option<SocketAddr>,
|
override_hostname: Option<SocketAddr>,
|
||||||
notify_start: Option<oneshot::Sender<()>>,
|
notify_start: Option<oneshot::Sender<()>>,
|
||||||
) -> MyResult<()> {
|
) -> MyResult<()> {
|
||||||
|
@ -42,7 +42,7 @@ pub(super) async fn start_server(
|
||||||
}
|
}
|
||||||
let routes = generate_route_list(App);
|
let routes = generate_route_list(App);
|
||||||
|
|
||||||
let arc_data = Arc::new(data.deref().clone());
|
let arc_data = Arc::new(context.deref().clone());
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.leptos_routes_with_handler(routes, get(leptos_routes_handler))
|
.leptos_routes_with_handler(routes, get(leptos_routes_handler))
|
||||||
.fallback(file_and_error_handler)
|
.fallback(file_and_error_handler)
|
||||||
|
@ -50,7 +50,7 @@ pub(super) async fn start_server(
|
||||||
.nest(FEDERATION_ROUTES_PREFIX, federation_routes())
|
.nest(FEDERATION_ROUTES_PREFIX, federation_routes())
|
||||||
.nest("/api/v1", api_routes())
|
.nest("/api/v1", api_routes())
|
||||||
.nest("", nodeinfo::config())
|
.nest("", nodeinfo::config())
|
||||||
.layer(FederationMiddleware::new(data))
|
.layer(FederationMiddleware::new(context))
|
||||||
.layer(CorsLayer::permissive())
|
.layer(CorsLayer::permissive())
|
||||||
.layer(CompressionLayer::new())
|
.layer(CompressionLayer::new())
|
||||||
.route_layer(from_fn_with_state(arc_data, auth_middleware));
|
.route_layer(from_fn_with_state(arc_data, auth_middleware));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{instance_stats::InstanceStats, IbisData},
|
database::{instance_stats::InstanceStats, IbisContext},
|
||||||
utils::error::MyResult,
|
utils::error::MyResult,
|
||||||
},
|
},
|
||||||
common::utils::http_protocol_str,
|
common::utils::http_protocol_str,
|
||||||
|
@ -16,21 +16,21 @@ pub fn config() -> Router<()> {
|
||||||
.route("/.well-known/nodeinfo", get(node_info_well_known))
|
.route("/.well-known/nodeinfo", get(node_info_well_known))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn node_info_well_known(data: Data<IbisData>) -> MyResult<Json<NodeInfoWellKnown>> {
|
async fn node_info_well_known(context: Data<IbisContext>) -> MyResult<Json<NodeInfoWellKnown>> {
|
||||||
Ok(Json(NodeInfoWellKnown {
|
Ok(Json(NodeInfoWellKnown {
|
||||||
links: vec![NodeInfoWellKnownLinks {
|
links: vec![NodeInfoWellKnownLinks {
|
||||||
rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.1")?,
|
rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.1")?,
|
||||||
href: Url::parse(&format!(
|
href: Url::parse(&format!(
|
||||||
"{}://{}/nodeinfo/2.1.json",
|
"{}://{}/nodeinfo/2.1.json",
|
||||||
http_protocol_str(),
|
http_protocol_str(),
|
||||||
data.domain()
|
context.domain()
|
||||||
))?,
|
))?,
|
||||||
}],
|
}],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn node_info(data: Data<IbisData>) -> MyResult<Json<NodeInfo>> {
|
async fn node_info(context: Data<IbisContext>) -> MyResult<Json<NodeInfo>> {
|
||||||
let stats = InstanceStats::read(&data)?;
|
let stats = InstanceStats::read(&context)?;
|
||||||
Ok(Json(NodeInfo {
|
Ok(Json(NodeInfo {
|
||||||
version: "2.1".to_string(),
|
version: "2.1".to_string(),
|
||||||
software: NodeInfoSoftware {
|
software: NodeInfoSoftware {
|
||||||
|
@ -49,7 +49,7 @@ async fn node_info(data: Data<IbisData>) -> MyResult<Json<NodeInfo>> {
|
||||||
local_posts: stats.articles,
|
local_posts: stats.articles,
|
||||||
local_comments: stats.comments,
|
local_comments: stats.comments,
|
||||||
},
|
},
|
||||||
open_registrations: data.config.options.registration_open,
|
open_registrations: context.config.options.registration_open,
|
||||||
services: Default::default(),
|
services: Default::default(),
|
||||||
metadata: vec![],
|
metadata: vec![],
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{database::IbisData, utils::error::MyResult},
|
backend::{database::IbisContext, utils::error::MyResult},
|
||||||
common::{
|
common::{
|
||||||
article::{DbEdit, EditVersion},
|
article::{DbEdit, EditVersion},
|
||||||
utils,
|
utils,
|
||||||
|
@ -19,8 +19,8 @@ pub mod error;
|
||||||
pub(super) mod scheduled_tasks;
|
pub(super) mod scheduled_tasks;
|
||||||
pub(super) mod validate;
|
pub(super) mod validate;
|
||||||
|
|
||||||
pub(super) fn generate_activity_id(data: &Data<IbisData>) -> Result<Url, ParseError> {
|
pub(super) fn generate_activity_id(context: &Data<IbisContext>) -> Result<Url, ParseError> {
|
||||||
let domain = &data.config.federation.domain;
|
let domain = &context.config.federation.domain;
|
||||||
let id: String = thread_rng()
|
let id: String = thread_rng()
|
||||||
.sample_iter(&Alphanumeric)
|
.sample_iter(&Alphanumeric)
|
||||||
.take(7)
|
.take(7)
|
||||||
|
|
Loading…
Reference in a new issue