proxy downloads
This commit is contained in:
@@ -136,10 +136,17 @@ pub struct TestApp {
|
||||
|
||||
impl TestApp {
|
||||
pub async fn new() -> Result<Self> {
|
||||
Self::with_config(|_| {}).await
|
||||
}
|
||||
|
||||
pub async fn with_config<F>(configure: F) -> Result<Self>
|
||||
where
|
||||
F: FnOnce(&mut AppConfig),
|
||||
{
|
||||
let database_url = env::var("TEST_DATABASE_URL")
|
||||
.context("TEST_DATABASE_URL must be set for integration tests")?;
|
||||
|
||||
let config = AppConfig {
|
||||
let mut config = AppConfig {
|
||||
database_url: database_url.clone(),
|
||||
database_max_pool_size: db::DEFAULT_MAX_POOL_SIZE,
|
||||
server_host: "127.0.0.1".to_string(),
|
||||
@@ -156,6 +163,7 @@ impl TestApp {
|
||||
refresh_cookie_secure: false,
|
||||
refresh_cookie_domain: None,
|
||||
cors_allowed_origin: None,
|
||||
proxy_downloads: false,
|
||||
aws_endpoint_url: None,
|
||||
aws_access_key_id: None,
|
||||
aws_secret_access_key: None,
|
||||
@@ -170,6 +178,8 @@ impl TestApp {
|
||||
webauthn_rp_name: "Papercrate".to_string(),
|
||||
};
|
||||
|
||||
configure(&mut config);
|
||||
|
||||
let pool = db::init_pool_with_size(&config.database_url, config.database_max_pool_size)?;
|
||||
prepare_database(&pool).await?;
|
||||
|
||||
@@ -206,6 +216,11 @@ impl TestApp {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn tenant_id(&self) -> Result<Uuid> {
|
||||
self.ensure_default_tenant().await
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn storage(&self) -> Arc<FakeStorage> {
|
||||
self.storage.clone()
|
||||
|
||||
@@ -3,12 +3,14 @@ mod common;
|
||||
use anyhow::{anyhow, Result};
|
||||
use axum::http::StatusCode;
|
||||
use common::{acquire_db_lock, body_to_vec, TestApp, UploadExtras};
|
||||
use diesel::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use uuid::Uuid;
|
||||
|
||||
use papercrate::jobs::{mark_job_succeeded, JOB_PURGE_DOCUMENT};
|
||||
use papercrate::models::Job;
|
||||
use papercrate::models::{Job, NewDocumentAsset, NewDocumentAssetObject};
|
||||
use papercrate::schema::{document_asset_objects, document_assets};
|
||||
use papercrate::workers::{purge::PurgeDocumentJob, JobExecution, JobHandler};
|
||||
use std::sync::Arc;
|
||||
#[derive(Deserialize)]
|
||||
@@ -64,6 +66,19 @@ struct DocumentAssetInfo {
|
||||
asset_type: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AssetProxyDetail {
|
||||
id: Uuid,
|
||||
objects: Vec<AssetProxyObject>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AssetProxyObject {
|
||||
id: Uuid,
|
||||
url: Option<String>,
|
||||
expires_at: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DocumentListItem {
|
||||
id: Uuid,
|
||||
@@ -277,6 +292,90 @@ async fn upload_document_with_custom_title_sets_filename() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn asset_detail_uses_proxy_urls_when_configured() -> Result<()> {
|
||||
let _lock = acquire_db_lock().await;
|
||||
let app = TestApp::with_config(|config| config.proxy_downloads = true).await?;
|
||||
let tenant_id = app.tenant_id().await?;
|
||||
|
||||
let username = "proxy-assets";
|
||||
let password = "secret";
|
||||
app.insert_user(username, password, "admin").await?;
|
||||
let token = app.login_token(username, password).await?;
|
||||
|
||||
let upload = app
|
||||
.upload_document(
|
||||
"/api/documents",
|
||||
"proxy.pdf",
|
||||
"application/pdf",
|
||||
b"dummy",
|
||||
None,
|
||||
&token,
|
||||
)
|
||||
.await?;
|
||||
assert_eq!(upload.status(), StatusCode::CREATED);
|
||||
let body = body_to_vec(upload.into_body()).await?;
|
||||
let detail: DocumentDetail = serde_json::from_slice(&body)?;
|
||||
let document = detail.document;
|
||||
let version = document
|
||||
.current_version
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("current version missing"))?;
|
||||
|
||||
let mut conn = app
|
||||
.state
|
||||
.db_for_tenant(tenant_id)
|
||||
.map_err(|err| anyhow!("tenant connection: {err:?}"))?;
|
||||
|
||||
let asset_id = Uuid::new_v4();
|
||||
let object_id = Uuid::new_v4();
|
||||
|
||||
diesel::insert_into(document_assets::table)
|
||||
.values(&NewDocumentAsset {
|
||||
id: asset_id,
|
||||
document_version_id: version.id,
|
||||
asset_type: "preview".to_string(),
|
||||
mime_type: "image/png".to_string(),
|
||||
metadata: json!({}),
|
||||
cardinality: Some(1),
|
||||
tenant_id,
|
||||
})
|
||||
.execute(&mut conn)?;
|
||||
|
||||
diesel::insert_into(document_asset_objects::table)
|
||||
.values(&NewDocumentAssetObject {
|
||||
id: object_id,
|
||||
asset_id,
|
||||
ordinal: 1,
|
||||
s3_key: "objects/preview.png".to_string(),
|
||||
metadata: json!({}),
|
||||
tenant_id,
|
||||
})
|
||||
.execute(&mut conn)?;
|
||||
|
||||
drop(conn);
|
||||
|
||||
let response = app
|
||||
.get(&format!("/api/assets/{asset_id}"), Some(&token))
|
||||
.await?;
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = body_to_vec(response.into_body()).await?;
|
||||
let asset_detail: AssetProxyDetail = serde_json::from_slice(&body)?;
|
||||
assert_eq!(asset_detail.id, asset_id);
|
||||
assert_eq!(asset_detail.objects.len(), 1);
|
||||
let object = &asset_detail.objects[0];
|
||||
assert_eq!(object.id, object_id);
|
||||
let url = object
|
||||
.url
|
||||
.as_deref()
|
||||
.ok_or_else(|| anyhow!("missing url"))?;
|
||||
assert!(url.starts_with("/download/"));
|
||||
assert!(object.expires_at.is_none());
|
||||
|
||||
app.cleanup().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_list_sorting_controls() -> Result<()> {
|
||||
let _lock = acquire_db_lock().await;
|
||||
|
||||
Reference in New Issue
Block a user