This commit is contained in:
2025-10-29 10:46:21 +01:00
parent 2de3dc30bf
commit ac27a9ab36
5 changed files with 111 additions and 14 deletions
+2 -2
View File
@@ -40,7 +40,7 @@ struct TenantSelectionResponse {
#[derive(Deserialize)]
struct TenantSummary {
tenant_id: Uuid,
id: Uuid,
slug: String,
}
@@ -225,7 +225,7 @@ async fn login_returns_tenant_selection_when_multiple_memberships() -> Result<()
.tenants
.iter()
.find(|tenant| tenant.slug == secondary_slug)
.map(|t| t.tenant_id)
.map(|t| t.id)
.context("secondary tenant missing from selection")?;
let select_response = app
+2 -2
View File
@@ -322,7 +322,7 @@ impl TestApp {
#[derive(Deserialize)]
struct TenantSummary {
tenant_id: Uuid,
id: Uuid,
_slug: String,
}
@@ -343,7 +343,7 @@ impl TestApp {
tenant_id: Uuid,
}
let target_tenant = selection.tenants[0].tenant_id;
let target_tenant = selection.tenants[0].id;
let select_response = self
.post_json(
"/api/auth/select-tenant",
+98 -9
View File
@@ -620,7 +620,7 @@ async fn bulk_move_documents_to_folder() -> Result<()> {
}
#[tokio::test]
async fn bulk_update_tags_for_selection() -> Result<()> {
async fn bulk_add_tags_for_selection() -> Result<()> {
let _lock = acquire_db_lock().await;
let app = TestApp::new().await?;
@@ -755,6 +755,84 @@ async fn bulk_update_tags_for_selection() -> Result<()> {
assert!(labels.contains(&"Review"));
}
app.cleanup().await?;
Ok(())
}
#[tokio::test]
async fn bulk_remove_tags_from_selection() -> Result<()> {
let _lock = acquire_db_lock().await;
let app = TestApp::new().await?;
let password = "bulktagremove";
app.insert_user("tagrem", password, "admin").await?;
let token = app.login_token("tagrem", password).await?;
let first = app
.upload_document(
"/api/documents",
"meeting-notes.txt",
"text/plain",
b"notes",
None,
&token,
)
.await?;
let first_body = body_to_vec(first.into_body()).await?;
let first_detail: DocumentDetail = serde_json::from_slice(&first_body)?;
let second = app
.upload_document(
"/api/documents",
"draft.txt",
"text/plain",
b"draft",
None,
&token,
)
.await?;
let second_body = body_to_vec(second.into_body()).await?;
let second_detail: DocumentDetail = serde_json::from_slice(&second_body)?;
let urgent_tag = app
.post_json(
"/api/tags",
&CreateTagPayload {
label: "Urgent",
color: None,
},
Some(&token),
)
.await?;
let urgent_body = body_to_vec(urgent_tag.into_body()).await?;
let urgent: TagResponse = serde_json::from_slice(&urgent_body)?;
let review_tag = app
.post_json(
"/api/tags",
&CreateTagPayload {
label: "Review",
color: None,
},
Some(&token),
)
.await?;
let review_body = body_to_vec(review_tag.into_body()).await?;
let review: TagResponse = serde_json::from_slice(&review_body)?;
let seed_resp = app
.post_json(
"/api/documents/bulk/tags",
&BulkTagRequest {
document_ids: &[first_detail.document.id, second_detail.document.id],
tag_ids: &[urgent.id, review.id],
action: "add",
},
Some(&token),
)
.await?;
assert!(seed_resp.status().is_success());
let remove_resp = app
.post_json(
"/api/documents/bulk/tags",
@@ -766,17 +844,11 @@ async fn bulk_update_tags_for_selection() -> Result<()> {
Some(&token),
)
.await?;
{
let status = remove_resp.status();
assert!(
status == StatusCode::OK
|| status == StatusCode::CREATED
|| status == StatusCode::NO_CONTENT
);
}
assert!(remove_resp.status().is_success());
let remove_body = body_to_vec(remove_resp.into_body()).await?;
let remove_result: BulkTagResult = serde_json::from_slice(&remove_body)?;
assert_eq!(remove_result.removed, 2);
assert_eq!(remove_result.added, 0);
for doc_id in [&first_detail.document.id, &second_detail.document.id] {
let refreshed = app
@@ -794,6 +866,23 @@ async fn bulk_update_tags_for_selection() -> Result<()> {
assert!(labels.contains(&"Review"));
}
let idempotent_resp = app
.post_json(
"/api/documents/bulk/tags",
&BulkTagRequest {
document_ids: &[first_detail.document.id, second_detail.document.id],
tag_ids: &[urgent.id],
action: "remove",
},
Some(&token),
)
.await?;
assert!(idempotent_resp.status().is_success());
let idempotent_body = body_to_vec(idempotent_resp.into_body()).await?;
let idempotent_result: BulkTagResult = serde_json::from_slice(&idempotent_body)?;
assert_eq!(idempotent_result.removed, 0);
assert_eq!(idempotent_result.added, 0);
app.cleanup().await?;
Ok(())
}
+8
View File
@@ -27,6 +27,14 @@ cat <<PROXY >> /etc/nginx/conf.d/default.conf
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
location /download/ {
proxy_pass ${API_PROXY_PASS_TRIMMED};
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
PROXY
fi
+1 -1
View File
@@ -48,7 +48,7 @@ module.exports = {
open: true,
proxy: [
{
context: ['/api'],
context: ['/api', '/download'],
target: 'http://127.0.0.1:3000',
changeOrigin: true,
secure: false,