1
0

Collections (#688)

* initial draft; unfinished

* images, fixes

* fixes

* println

* revisions

* fixes

* alternate context setup version

* rev

* partial revs

* rev

* clippy ,fmt

* fmt/clippy/prepare

* fixes

* revs
This commit is contained in:
Wyatt Verchere
2023-09-13 22:22:32 -07:00
committed by GitHub
parent 35cd277fcf
commit 9bd2cb3c7e
30 changed files with 2579 additions and 24 deletions

View File

@@ -1,11 +1,16 @@
use crate::auth::{check_is_moderator_from_headers, get_user_from_headers};
use crate::database;
use crate::database::models::image_item;
use crate::database::models::thread_item::{ThreadBuilder, ThreadMessageBuilder};
use crate::models::ids::ImageId;
use crate::models::ids::{base62_impl::parse_base62, ProjectId, UserId, VersionId};
use crate::models::images::{Image, ImageContext};
use crate::models::pats::Scopes;
use crate::models::reports::{ItemType, Report};
use crate::models::threads::{MessageBody, ThreadType};
use crate::queue::session::AuthQueue;
use crate::routes::ApiError;
use crate::util::img;
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
use chrono::Utc;
use futures::StreamExt;
@@ -22,12 +27,16 @@ pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(report_get);
}
#[derive(Deserialize)]
#[derive(Deserialize, Validate)]
pub struct CreateReport {
pub report_type: String,
pub item_id: String,
pub item_type: ItemType,
pub body: String,
// Associations to uploaded images
#[validate(length(max = 10))]
#[serde(default)]
pub uploaded_images: Vec<ImageId>,
}
#[post("report")]
@@ -147,6 +156,42 @@ pub async fn report_create(
}
report.insert(&mut transaction).await?;
for image_id in new_report.uploaded_images {
if let Some(db_image) =
image_item::Image::get(image_id.into(), &mut *transaction, &redis).await?
{
let image: Image = db_image.into();
if !matches!(image.context, ImageContext::Report { .. })
|| image.context.inner_id().is_some()
{
return Err(ApiError::InvalidInput(format!(
"Image {} is not unused and in the 'report' context",
image_id
)));
}
sqlx::query!(
"
UPDATE uploaded_images
SET report_id = $1
WHERE id = $2
",
id.0 as i64,
image_id.0 as i64
)
.execute(&mut *transaction)
.await?;
image_item::Image::clear_cache(image.id.into(), &redis).await?;
} else {
return Err(ApiError::InvalidInput(format!(
"Image {} could not be found",
image_id
)));
}
}
let thread_id = ThreadBuilder {
type_: ThreadType::Report,
members: vec![],
@@ -423,6 +468,17 @@ pub async fn report_edit(
.await?;
}
// delete any images no longer in the body
let checkable_strings: Vec<&str> = vec![&edit_report.body]
.into_iter()
.filter_map(|x: &Option<String>| x.as_ref().map(|y| y.as_str()))
.collect();
let image_context = ImageContext::Report {
report_id: Some(id.into()),
};
img::delete_unused_images(image_context, checkable_strings, &mut transaction, &redis)
.await?;
transaction.commit().await?;
Ok(HttpResponse::NoContent().body(""))
@@ -442,11 +498,20 @@ pub async fn report_delete(
check_is_moderator_from_headers(&req, &**pool, &redis, &session_queue).await?;
let mut transaction = pool.begin().await?;
let result = crate::database::models::report_item::Report::remove_full(
info.into_inner().0.into(),
&mut transaction,
)
.await?;
let id = info.into_inner().0;
let context = ImageContext::Report {
report_id: Some(id),
};
let uploaded_images =
database::models::Image::get_many_contexted(context, &mut transaction).await?;
for image in uploaded_images {
image_item::Image::remove(image.id, &mut transaction, &redis).await?;
}
let result =
crate::database::models::report_item::Report::remove_full(id.into(), &mut transaction)
.await?;
transaction.commit().await?;
if result.is_some() {