1
0
Fork 0
mirror of https://github.com/Nutomic/ibis.git synced 2024-11-22 12:31:08 +00:00

Simplify code so that unapproved articles can be viewed directly (but not included in listings)

This commit is contained in:
Felix Ableitner 2024-11-13 11:07:28 +01:00
parent 733abdef96
commit 18d46d22bf
8 changed files with 20 additions and 48 deletions

View file

@ -1,4 +1,4 @@
use super::{check_is_admin, is_admin_opt};
use super::check_is_admin;
use crate::{
backend::{
database::{
@ -42,7 +42,7 @@ use diffy::create_patch;
/// Create a new article with empty text, and federate it to followers.
#[debug_handler]
pub(in crate::backend::api) async fn create_article(
Extension(mut user): Extension<LocalUserView>,
user: Extension<LocalUserView>,
data: Data<IbisData>,
Form(create_article): Form<CreateArticleForm>,
) -> MyResult<Json<ArticleView>> {
@ -80,12 +80,10 @@ pub(in crate::backend::api) async fn create_article(
resolve_conflict_id: None,
};
// workaround so the edit goes through
user.local_user.admin = true;
let _ = edit_article(Extension(user), data.reset_request_count(), Form(edit_data)).await?;
let _ = edit_article(user, data.reset_request_count(), Form(edit_data)).await?;
// 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?;
Ok(Json(article_view))
@ -106,12 +104,11 @@ pub(in crate::backend::api) async fn edit_article(
data: Data<IbisData>,
Form(mut edit_form): Form<EditArticleForm>,
) -> MyResult<Json<Option<ApiConflict>>> {
let is_admin = check_is_admin(&user).is_ok();
// resolve conflict if any
if let Some(resolve_conflict_id) = edit_form.resolve_conflict_id {
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 {
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,
};
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]
pub(in crate::backend::api) async fn get_article(
Query(query): Query<GetArticleForm>,
user: Option<Extension<LocalUserView>>,
data: Data<IbisData>,
) -> MyResult<Json<ArticleView>> {
let is_admin = is_admin_opt(&user);
match (query.title, query.id) {
(Some(title), None) => Ok(Json(DbArticle::read_view_title(
&title,
query.domain,
is_admin,
&data,
)?)),
(None, Some(id)) => {
if query.domain.is_some() {
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))
}
_ => 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.
#[debug_handler]
pub(in crate::backend::api) async fn fork_article(
Extension(user): Extension<LocalUserView>,
Extension(_user): Extension<LocalUserView>,
data: Data<IbisData>,
Form(fork_form): Form<ForkArticleForm>,
) -> 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
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 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?;
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

View file

@ -36,7 +36,6 @@ use axum::{
middleware::{self, Next},
response::Response,
routing::{get, post},
Extension,
Router,
};
use axum_extra::extract::CookieJar;
@ -94,11 +93,3 @@ fn check_is_admin(user: &LocalUserView) -> MyResult<()> {
}
Ok(())
}
fn is_admin_opt(user: &Option<Extension<LocalUserView>>) -> bool {
if let Some(user) = user {
user.local_user.admin
} else {
false
}
}

View file

@ -161,11 +161,10 @@ pub(crate) async fn list_notifications(
Extension(user): Extension<LocalUserView>,
data: Data<IbisData>,
) -> MyResult<Json<Vec<Notification>>> {
let is_admin = check_is_admin(&user).is_ok();
let conflicts = DbConflict::list(&user.person, &data)?;
let conflicts: Vec<_> = try_join_all(conflicts.into_iter().map(|c| {
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?;
let mut notifications: Vec<_> = conflicts

View file

@ -87,12 +87,9 @@ impl DbArticle {
.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 query = article::table.find(id).into_boxed();
if !is_admin {
query = query.filter(article::dsl::approved.eq(true));
}
let query = article::table.find(id).into_boxed();
let article: DbArticle = query.get_result(conn.deref_mut())?;
let latest_version = article.latest_edit_version(data)?;
let edits = DbEdit::read_for_article(&article, data)?;
@ -106,7 +103,6 @@ impl DbArticle {
pub fn read_view_title(
title: &str,
domain: Option<String>,
admin: bool,
data: &IbisData,
) -> MyResult<ArticleView> {
let mut conn = data.db_pool.get()?;
@ -115,14 +111,11 @@ impl DbArticle {
.inner_join(instance::table)
.filter(article::dsl::title.eq(title))
.into_boxed();
let mut query = if let Some(domain) = domain {
let query = if let Some(domain) = domain {
query.filter(instance::dsl::domain.eq(domain))
} else {
query.filter(article::dsl::local.eq(true))
};
if !admin {
query = query.filter(article::dsl::approved.eq(true));
}
query
.select(article::all_columns)
.get_result(conn.deref_mut())?

View file

@ -78,12 +78,8 @@ impl DbConflict {
Ok(delete(conflict::table.find(id)).get_result(conn.deref_mut())?)
}
pub async fn to_api_conflict(
&self,
is_admin: bool,
data: &Data<IbisData>,
) -> MyResult<Option<ApiConflict>> {
let article = DbArticle::read_view(self.article_id, is_admin, data)?;
pub async fn to_api_conflict(&self, data: &Data<IbisData>) -> MyResult<Option<ApiConflict>> {
let article = DbArticle::read_view(self.article_id, data)?;
// 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?;

View file

@ -52,7 +52,7 @@ impl Object for DbEdit {
}
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)?;
Ok(ApubEdit {
kind: PatchType::Patch,

View file

@ -35,7 +35,7 @@ impl Collection for DbEditCollection {
owner: &Self::Owner,
data: &Data<Self::DataType>,
) -> 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(
article

View file

@ -94,7 +94,7 @@ async fn http_get_article(
Path(title): Path<String>,
data: Data<IbisData>,
) -> 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?;
Ok(FederationJson(WithContext::new_default(json)))
}
@ -104,7 +104,7 @@ async fn http_get_article_edits(
Path(title): Path<String>,
data: Data<IbisData>,
) -> 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?;
Ok(FederationJson(WithContext::new_default(json)))
}