mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-22 12:01:08 +00:00
Simplify code so that unapproved articles can be viewed directly (but not included in listings)
This commit is contained in:
parent
733abdef96
commit
18d46d22bf
8 changed files with 20 additions and 48 deletions
|
@ -1,4 +1,4 @@
|
||||||
use super::{check_is_admin, is_admin_opt};
|
use super::check_is_admin;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
database::{
|
database::{
|
||||||
|
@ -42,7 +42,7 @@ use diffy::create_patch;
|
||||||
/// Create a new article with empty text, and federate it to followers.
|
/// Create a new article with empty text, and federate it to followers.
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
pub(in crate::backend::api) async fn create_article(
|
pub(in crate::backend::api) async fn create_article(
|
||||||
Extension(mut user): Extension<LocalUserView>,
|
user: Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
data: Data<IbisData>,
|
||||||
Form(create_article): Form<CreateArticleForm>,
|
Form(create_article): Form<CreateArticleForm>,
|
||||||
) -> MyResult<Json<ArticleView>> {
|
) -> MyResult<Json<ArticleView>> {
|
||||||
|
@ -80,12 +80,10 @@ pub(in crate::backend::api) async fn create_article(
|
||||||
resolve_conflict_id: None,
|
resolve_conflict_id: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// workaround so the edit goes through
|
let _ = edit_article(user, data.reset_request_count(), Form(edit_data)).await?;
|
||||||
user.local_user.admin = true;
|
|
||||||
let _ = edit_article(Extension(user), data.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, true, &data)?;
|
let article_view = DbArticle::read_view(article.id, &data)?;
|
||||||
CreateArticle::send_to_followers(article_view.article.clone(), &data).await?;
|
CreateArticle::send_to_followers(article_view.article.clone(), &data).await?;
|
||||||
|
|
||||||
Ok(Json(article_view))
|
Ok(Json(article_view))
|
||||||
|
@ -106,12 +104,11 @@ pub(in crate::backend::api) async fn edit_article(
|
||||||
data: Data<IbisData>,
|
data: Data<IbisData>,
|
||||||
Form(mut edit_form): Form<EditArticleForm>,
|
Form(mut edit_form): Form<EditArticleForm>,
|
||||||
) -> MyResult<Json<Option<ApiConflict>>> {
|
) -> MyResult<Json<Option<ApiConflict>>> {
|
||||||
let is_admin = check_is_admin(&user).is_ok();
|
|
||||||
// resolve conflict if any
|
// resolve conflict if any
|
||||||
if let Some(resolve_conflict_id) = edit_form.resolve_conflict_id {
|
if let Some(resolve_conflict_id) = edit_form.resolve_conflict_id {
|
||||||
DbConflict::delete(resolve_conflict_id, &data)?;
|
DbConflict::delete(resolve_conflict_id, &data)?;
|
||||||
}
|
}
|
||||||
let original_article = DbArticle::read_view(edit_form.article_id, is_admin, &data)?;
|
let original_article = DbArticle::read_view(edit_form.article_id, &data)?;
|
||||||
if edit_form.new_text == original_article.article.text {
|
if edit_form.new_text == original_article.article.text {
|
||||||
return Err(anyhow!("Edit contains no changes").into());
|
return Err(anyhow!("Edit contains no changes").into());
|
||||||
}
|
}
|
||||||
|
@ -153,7 +150,7 @@ pub(in crate::backend::api) async fn edit_article(
|
||||||
previous_version_id: previous_version.hash,
|
previous_version_id: previous_version.hash,
|
||||||
};
|
};
|
||||||
let conflict = DbConflict::create(&form, &data)?;
|
let conflict = DbConflict::create(&form, &data)?;
|
||||||
Ok(Json(conflict.to_api_conflict(is_admin, &data).await?))
|
Ok(Json(conflict.to_api_conflict(&data).await?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,22 +158,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<GetArticleForm>,
|
Query(query): Query<GetArticleForm>,
|
||||||
user: Option<Extension<LocalUserView>>,
|
|
||||||
data: Data<IbisData>,
|
data: Data<IbisData>,
|
||||||
) -> MyResult<Json<ArticleView>> {
|
) -> MyResult<Json<ArticleView>> {
|
||||||
let is_admin = is_admin_opt(&user);
|
|
||||||
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,
|
||||||
is_admin,
|
|
||||||
&data,
|
&data,
|
||||||
)?)),
|
)?)),
|
||||||
(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, is_admin, &data)?;
|
let article = DbArticle::read_view(id, &data)?;
|
||||||
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()),
|
||||||
|
@ -199,13 +193,12 @@ pub(in crate::backend::api) async fn list_articles(
|
||||||
/// how an article should be edited.
|
/// how an article should be edited.
|
||||||
#[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>,
|
data: Data<IbisData>,
|
||||||
Form(fork_form): Form<ForkArticleForm>,
|
Form(fork_form): Form<ForkArticleForm>,
|
||||||
) -> MyResult<Json<ArticleView>> {
|
) -> MyResult<Json<ArticleView>> {
|
||||||
let is_admin = check_is_admin(&user).is_ok();
|
|
||||||
// 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(fork_form.article_id, is_admin, &data)?;
|
let original_article = DbArticle::read_view(fork_form.article_id, &data)?;
|
||||||
|
|
||||||
let local_instance = DbInstance::read_local_instance(&data)?;
|
let local_instance = DbInstance::read_local_instance(&data)?;
|
||||||
let ap_id = ObjectId::parse(&format!(
|
let ap_id = ObjectId::parse(&format!(
|
||||||
|
@ -249,7 +242,7 @@ pub(in crate::backend::api) async fn fork_article(
|
||||||
|
|
||||||
CreateArticle::send_to_followers(article.clone(), &data).await?;
|
CreateArticle::send_to_followers(article.clone(), &data).await?;
|
||||||
|
|
||||||
Ok(Json(DbArticle::read_view(article.id, is_admin, &data)?))
|
Ok(Json(DbArticle::read_view(article.id, &data)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
|
|
|
@ -36,7 +36,6 @@ use axum::{
|
||||||
middleware::{self, Next},
|
middleware::{self, Next},
|
||||||
response::Response,
|
response::Response,
|
||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Extension,
|
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use axum_extra::extract::CookieJar;
|
use axum_extra::extract::CookieJar;
|
||||||
|
@ -94,11 +93,3 @@ fn check_is_admin(user: &LocalUserView) -> MyResult<()> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_admin_opt(user: &Option<Extension<LocalUserView>>) -> bool {
|
|
||||||
if let Some(user) = user {
|
|
||||||
user.local_user.admin
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -161,11 +161,10 @@ pub(crate) async fn list_notifications(
|
||||||
Extension(user): Extension<LocalUserView>,
|
Extension(user): Extension<LocalUserView>,
|
||||||
data: Data<IbisData>,
|
data: Data<IbisData>,
|
||||||
) -> MyResult<Json<Vec<Notification>>> {
|
) -> MyResult<Json<Vec<Notification>>> {
|
||||||
let is_admin = check_is_admin(&user).is_ok();
|
|
||||||
let conflicts = DbConflict::list(&user.person, &data)?;
|
let conflicts = DbConflict::list(&user.person, &data)?;
|
||||||
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 = data.reset_request_count();
|
||||||
async move { c.to_api_conflict(is_admin, &data).await }
|
async move { c.to_api_conflict(&data).await }
|
||||||
}))
|
}))
|
||||||
.await?;
|
.await?;
|
||||||
let mut notifications: Vec<_> = conflicts
|
let mut notifications: Vec<_> = conflicts
|
||||||
|
|
|
@ -87,12 +87,9 @@ impl DbArticle {
|
||||||
.get_result::<Self>(conn.deref_mut())?)
|
.get_result::<Self>(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_view(id: ArticleId, is_admin: bool, data: &IbisData) -> MyResult<ArticleView> {
|
pub fn read_view(id: ArticleId, data: &IbisData) -> MyResult<ArticleView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = data.db_pool.get()?;
|
||||||
let mut query = article::table.find(id).into_boxed();
|
let query = article::table.find(id).into_boxed();
|
||||||
if !is_admin {
|
|
||||||
query = query.filter(article::dsl::approved.eq(true));
|
|
||||||
}
|
|
||||||
let article: DbArticle = query.get_result(conn.deref_mut())?;
|
let article: DbArticle = query.get_result(conn.deref_mut())?;
|
||||||
let latest_version = article.latest_edit_version(data)?;
|
let latest_version = article.latest_edit_version(data)?;
|
||||||
let edits = DbEdit::read_for_article(&article, data)?;
|
let edits = DbEdit::read_for_article(&article, data)?;
|
||||||
|
@ -106,7 +103,6 @@ impl DbArticle {
|
||||||
pub fn read_view_title(
|
pub fn read_view_title(
|
||||||
title: &str,
|
title: &str,
|
||||||
domain: Option<String>,
|
domain: Option<String>,
|
||||||
admin: bool,
|
|
||||||
data: &IbisData,
|
data: &IbisData,
|
||||||
) -> MyResult<ArticleView> {
|
) -> MyResult<ArticleView> {
|
||||||
let mut conn = data.db_pool.get()?;
|
let mut conn = data.db_pool.get()?;
|
||||||
|
@ -115,14 +111,11 @@ impl DbArticle {
|
||||||
.inner_join(instance::table)
|
.inner_join(instance::table)
|
||||||
.filter(article::dsl::title.eq(title))
|
.filter(article::dsl::title.eq(title))
|
||||||
.into_boxed();
|
.into_boxed();
|
||||||
let mut query = if let Some(domain) = domain {
|
let query = if let Some(domain) = domain {
|
||||||
query.filter(instance::dsl::domain.eq(domain))
|
query.filter(instance::dsl::domain.eq(domain))
|
||||||
} else {
|
} else {
|
||||||
query.filter(article::dsl::local.eq(true))
|
query.filter(article::dsl::local.eq(true))
|
||||||
};
|
};
|
||||||
if !admin {
|
|
||||||
query = query.filter(article::dsl::approved.eq(true));
|
|
||||||
}
|
|
||||||
query
|
query
|
||||||
.select(article::all_columns)
|
.select(article::all_columns)
|
||||||
.get_result(conn.deref_mut())?
|
.get_result(conn.deref_mut())?
|
||||||
|
|
|
@ -78,12 +78,8 @@ impl DbConflict {
|
||||||
Ok(delete(conflict::table.find(id)).get_result(conn.deref_mut())?)
|
Ok(delete(conflict::table.find(id)).get_result(conn.deref_mut())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn to_api_conflict(
|
pub async fn to_api_conflict(&self, data: &Data<IbisData>) -> MyResult<Option<ApiConflict>> {
|
||||||
&self,
|
let article = DbArticle::read_view(self.article_id, data)?;
|
||||||
is_admin: bool,
|
|
||||||
data: &Data<IbisData>,
|
|
||||||
) -> MyResult<Option<ApiConflict>> {
|
|
||||||
let article = DbArticle::read_view(self.article_id, is_admin, data)?;
|
|
||||||
// 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(data).await?;
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl Object for DbEdit {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
let article = DbArticle::read_view(self.article_id, false, data)?;
|
let article = DbArticle::read_view(self.article_id, data)?;
|
||||||
let creator = DbPerson::read(self.creator_id, data)?;
|
let creator = DbPerson::read(self.creator_id, data)?;
|
||||||
Ok(ApubEdit {
|
Ok(ApubEdit {
|
||||||
kind: PatchType::Patch,
|
kind: PatchType::Patch,
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl Collection for DbEditCollection {
|
||||||
owner: &Self::Owner,
|
owner: &Self::Owner,
|
||||||
data: &Data<Self::DataType>,
|
data: &Data<Self::DataType>,
|
||||||
) -> Result<Self::Kind, Self::Error> {
|
) -> Result<Self::Kind, Self::Error> {
|
||||||
let article = DbArticle::read_view(owner.id, false, data)?;
|
let article = DbArticle::read_view(owner.id, data)?;
|
||||||
|
|
||||||
let edits = future::try_join_all(
|
let edits = future::try_join_all(
|
||||||
article
|
article
|
||||||
|
|
|
@ -94,7 +94,7 @@ async fn http_get_article(
|
||||||
Path(title): Path<String>,
|
Path(title): Path<String>,
|
||||||
data: Data<IbisData>,
|
data: Data<IbisData>,
|
||||||
) -> MyResult<FederationJson<WithContext<ApubArticle>>> {
|
) -> MyResult<FederationJson<WithContext<ApubArticle>>> {
|
||||||
let article = DbArticle::read_view_title(&title, None, false, &data)?;
|
let article = DbArticle::read_view_title(&title, None, &data)?;
|
||||||
let json = article.article.into_json(&data).await?;
|
let json = article.article.into_json(&data).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json)))
|
Ok(FederationJson(WithContext::new_default(json)))
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ async fn http_get_article_edits(
|
||||||
Path(title): Path<String>,
|
Path(title): Path<String>,
|
||||||
data: Data<IbisData>,
|
data: Data<IbisData>,
|
||||||
) -> MyResult<FederationJson<WithContext<ApubEditCollection>>> {
|
) -> MyResult<FederationJson<WithContext<ApubEditCollection>>> {
|
||||||
let article = DbArticle::read_view_title(&title, None, false, &data)?;
|
let article = DbArticle::read_view_title(&title, None, &data)?;
|
||||||
let json = DbEditCollection::read_local(&article.article, &data).await?;
|
let json = DbEditCollection::read_local(&article.article, &data).await?;
|
||||||
Ok(FederationJson(WithContext::new_default(json)))
|
Ok(FederationJson(WithContext::new_default(json)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue