diff --git a/weed/admin/dash/s3tables_management.go b/weed/admin/dash/s3tables_management.go index f9492d7da..21aca5aed 100644 --- a/weed/admin/dash/s3tables_management.go +++ b/weed/admin/dash/s3tables_management.go @@ -1061,7 +1061,7 @@ func s3TablesErrorStatus(err error) int { return http.StatusNotFound case s3tables.ErrCodeAccessDenied: return http.StatusForbidden - case s3tables.ErrCodeBucketAlreadyExists, s3tables.ErrCodeNamespaceAlreadyExists, s3tables.ErrCodeTableAlreadyExists, s3tables.ErrCodeConflict: + case s3tables.ErrCodeBucketAlreadyExists, s3tables.ErrCodeNamespaceAlreadyExists, s3tables.ErrCodeTableAlreadyExists, s3tables.ErrCodeBucketNotEmpty, s3tables.ErrCodeNamespaceNotEmpty, s3tables.ErrCodeConflict: return http.StatusConflict } } diff --git a/weed/admin/static/js/s3tables.js b/weed/admin/static/js/s3tables.js index 8dfba286f..1c7bc8c4d 100644 --- a/weed/admin/static/js/s3tables.js +++ b/weed/admin/static/js/s3tables.js @@ -23,6 +23,15 @@ function getCSRFToken() { return tokenMeta.getAttribute('content') || ''; } +function s3tWriteHeaders(extra) { + const headers = Object.assign({}, extra || {}); + const csrfToken = getCSRFToken(); + if (csrfToken) { + headers['X-CSRF-Token'] = csrfToken; + } + return headers; +} + /** * Initialize S3 Tables Buckets Page */ @@ -104,7 +113,7 @@ function initS3TablesBuckets() { try { const response = await fetch(s3tBasePath('/api/s3tables/buckets'), { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify(payload) }); const data = await response.json(); @@ -133,7 +142,7 @@ function initS3TablesBuckets() { try { const response = await fetch(s3tBasePath('/api/s3tables/bucket-policy'), { method: 'PUT', - headers: { 'Content-Type': 'application/json' }, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify({ bucket_arn: bucketArn, policy: policy }) }); const data = await response.json(); @@ -239,7 +248,7 @@ function initS3TablesTables() { try { const response = await fetch(s3tBasePath('/api/s3tables/tables'), { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify(payload) }); const data = await response.json(); @@ -267,7 +276,7 @@ function initS3TablesTables() { try { const response = await fetch(s3tBasePath('/api/s3tables/table-policy'), { method: 'PUT', - headers: { 'Content-Type': 'application/json' }, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify({ bucket_arn: dataBucketArn, namespace: dataNamespace, name: document.getElementById('s3tablesTablePolicyName').value, policy: policy }) }); const data = await response.json(); @@ -306,10 +315,6 @@ function initIcebergNamespaces() { if (!container) return; const bucketArn = container.dataset.bucketArn || ''; const catalogName = container.dataset.catalogName || ''; - const csrfTokenInput = document.getElementById('icebergNamespaceCsrfToken'); - if (csrfTokenInput) { - csrfTokenInput.value = getCSRFToken(); - } const namespaceInput = document.getElementById('icebergNamespaceName'); if (namespaceInput) { @@ -330,14 +335,9 @@ function initIcebergNamespaces() { return; } try { - const csrfToken = csrfTokenInput ? csrfTokenInput.value : getCSRFToken(); - const headers = { 'Content-Type': 'application/json' }; - if (csrfToken) { - headers['X-CSRF-Token'] = csrfToken; - } const response = await fetch(s3tBasePath('/api/s3tables/namespaces'), { method: 'POST', - headers: headers, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify({ bucket_arn: bucketArn, name: name }) }); const data = await response.json(); @@ -433,10 +433,6 @@ function initIcebergTables() { if (!container) return; const bucketArn = container.dataset.bucketArn || ''; const namespace = container.dataset.namespace || ''; - const csrfTokenInput = document.getElementById('icebergTableCsrfToken'); - if (csrfTokenInput) { - csrfTokenInput.value = getCSRFToken(); - } initIcebergDeleteModal(); @@ -476,14 +472,9 @@ function initIcebergTables() { payload.metadata = metadata; } try { - const csrfToken = csrfTokenInput ? csrfTokenInput.value : getCSRFToken(); - const headers = { 'Content-Type': 'application/json' }; - if (csrfToken) { - headers['X-CSRF-Token'] = csrfToken; - } const response = await fetch(s3tBasePath('/api/s3tables/tables'), { method: 'POST', - headers: headers, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify(payload) }); const data = await response.json(); @@ -530,7 +521,7 @@ async function deleteS3TablesBucket() { const bucketArn = document.getElementById('deleteS3TablesBucketModal').dataset.bucketArn; if (!bucketArn) return; try { - const response = await fetch(s3tBasePath(`/api/s3tables/buckets?bucket=${encodeURIComponent(bucketArn)}`), { method: 'DELETE' }); + const response = await fetch(s3tBasePath(`/api/s3tables/buckets?bucket=${encodeURIComponent(bucketArn)}`), { method: 'DELETE', headers: s3tWriteHeaders() }); const data = await response.json(); if (!response.ok) { alert(data.error || 'Failed to delete bucket'); @@ -561,7 +552,7 @@ async function deleteS3TablesBucketPolicy() { const bucketArn = document.getElementById('s3tablesBucketPolicyArn').value; if (!bucketArn) return; try { - const response = await fetch(s3tBasePath(`/api/s3tables/bucket-policy?bucket=${encodeURIComponent(bucketArn)}`), { method: 'DELETE' }); + const response = await fetch(s3tBasePath(`/api/s3tables/bucket-policy?bucket=${encodeURIComponent(bucketArn)}`), { method: 'DELETE', headers: s3tWriteHeaders() }); const data = await response.json(); if (!response.ok) { alert(data.error || 'Failed to delete policy'); @@ -590,7 +581,7 @@ async function deleteS3TablesTable() { query.set('version', versionToken); } try { - const response = await fetch(s3tBasePath(`/api/s3tables/tables?${query.toString()}`), { method: 'DELETE' }); + const response = await fetch(s3tBasePath(`/api/s3tables/tables?${query.toString()}`), { method: 'DELETE', headers: s3tWriteHeaders() }); const data = await response.json(); if (!response.ok) { alert(data.error || 'Failed to delete table'); @@ -621,12 +612,7 @@ async function deleteIcebergTable() { query.set('version', versionToken); } try { - const csrfToken = getCSRFToken(); - const requestOptions = { method: 'DELETE' }; - if (csrfToken) { - requestOptions.headers = { 'X-CSRF-Token': csrfToken }; - } - const response = await fetch(s3tBasePath(`/api/s3tables/tables?${query.toString()}`), requestOptions); + const response = await fetch(s3tBasePath(`/api/s3tables/tables?${query.toString()}`), { method: 'DELETE', headers: s3tWriteHeaders() }); const data = await response.json(); if (!response.ok) { alert(data.error || 'Failed to drop table'); @@ -665,7 +651,7 @@ async function deleteS3TablesTablePolicy() { const dataNamespace = dataContainer.dataset.namespace || ''; const query = new URLSearchParams({ bucket: dataBucketArn, namespace: dataNamespace, name: document.getElementById('s3tablesTablePolicyName').value }); try { - const response = await fetch(s3tBasePath(`/api/s3tables/table-policy?${query.toString()}`), { method: 'DELETE' }); + const response = await fetch(s3tBasePath(`/api/s3tables/table-policy?${query.toString()}`), { method: 'DELETE', headers: s3tWriteHeaders() }); const data = await response.json(); if (!response.ok) { alert(data.error || 'Failed to delete policy'); @@ -872,7 +858,7 @@ async function updateS3TablesTags(resourceArn, tags) { try { const response = await fetch(s3tBasePath('/api/s3tables/tags'), { method: 'PUT', - headers: { 'Content-Type': 'application/json' }, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify({ resource_arn: resourceArn, tags: tags }) }); const data = await response.json(); @@ -899,7 +885,7 @@ async function deleteS3TablesTags() { try { const response = await fetch(s3tBasePath('/api/s3tables/tags'), { method: 'DELETE', - headers: { 'Content-Type': 'application/json' }, + headers: s3tWriteHeaders({ 'Content-Type': 'application/json' }), body: JSON.stringify({ resource_arn: resourceArn, tag_keys: tagKeys }) }); const data = await response.json();