window.BucketDetailOperations = (function() { 'use strict'; let showMessage = function() {}; let escapeHtml = function(s) { return s; }; function init(config) { showMessage = config.showMessage || showMessage; escapeHtml = config.escapeHtml || escapeHtml; } async function loadLifecycleRules(card, endpoint) { if (!card || !endpoint) return; const body = card.querySelector('[data-lifecycle-body]'); if (!body) return; try { const response = await fetch(endpoint); const data = await response.json(); if (!response.ok) { body.innerHTML = `${escapeHtml(data.error || 'Failed to load')}`; return; } const rules = data.rules || []; if (rules.length === 0) { body.innerHTML = 'No lifecycle rules configured'; return; } body.innerHTML = rules.map(rule => { const actions = []; if (rule.expiration_days) actions.push(`Delete after ${rule.expiration_days} days`); if (rule.noncurrent_days) actions.push(`Delete old versions after ${rule.noncurrent_days} days`); if (rule.abort_mpu_days) actions.push(`Abort incomplete MPU after ${rule.abort_mpu_days} days`); return ` ${escapeHtml(rule.id)} ${escapeHtml(rule.prefix || '(all)')} ${actions.map(a => `
${escapeHtml(a)}
`).join('')} ${escapeHtml(rule.status)} `; }).join(''); } catch (err) { body.innerHTML = `${escapeHtml(err.message)}`; } } async function loadCorsRules(card, endpoint) { if (!card || !endpoint) return; const body = document.getElementById('cors-rules-body'); if (!body) return; try { const response = await fetch(endpoint); const data = await response.json(); if (!response.ok) { body.innerHTML = `${escapeHtml(data.error || 'Failed to load')}`; return; } const rules = data.rules || []; if (rules.length === 0) { body.innerHTML = 'No CORS rules configured'; return; } body.innerHTML = rules.map((rule, idx) => ` ${(rule.allowed_origins || []).map(o => `${escapeHtml(o)}`).join('')} ${(rule.allowed_methods || []).map(m => `${escapeHtml(m)}`).join('')} ${(rule.allowed_headers || []).slice(0, 3).join(', ')}${(rule.allowed_headers || []).length > 3 ? '...' : ''} ${rule.max_age_seconds || 0}s `).join(''); } catch (err) { body.innerHTML = `${escapeHtml(err.message)}`; } } async function loadAcl(card, endpoint) { if (!card || !endpoint) return; const body = card.querySelector('[data-acl-body]'); if (!body) return; try { const response = await fetch(endpoint); const data = await response.json(); if (!response.ok) { body.innerHTML = `${escapeHtml(data.error || 'Failed to load')}`; return; } const grants = data.grants || []; if (grants.length === 0) { body.innerHTML = 'No ACL grants configured'; return; } body.innerHTML = grants.map(grant => { const grantee = grant.grantee_type === 'CanonicalUser' ? grant.display_name || grant.grantee_id : grant.grantee_uri || grant.grantee_type; return ` ${escapeHtml(grantee)} ${escapeHtml(grant.permission)} ${escapeHtml(grant.grantee_type)} `; }).join(''); } catch (err) { body.innerHTML = `${escapeHtml(err.message)}`; } } async function deleteLifecycleRule(ruleId) { if (!confirm(`Delete lifecycle rule "${ruleId}"?`)) return; const card = document.getElementById('lifecycle-rules-card'); if (!card) return; const endpoint = card.dataset.lifecycleUrl; const csrfToken = window.getCsrfToken ? window.getCsrfToken() : ''; try { const resp = await fetch(endpoint, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken }, body: JSON.stringify({ rule_id: ruleId }) }); const data = await resp.json(); if (!resp.ok) throw new Error(data.error || 'Failed to delete'); showMessage({ title: 'Rule deleted', body: `Lifecycle rule "${ruleId}" has been deleted.`, variant: 'success' }); loadLifecycleRules(card, endpoint); } catch (err) { showMessage({ title: 'Delete failed', body: err.message, variant: 'danger' }); } } async function deleteCorsRule(index) { if (!confirm('Delete this CORS rule?')) return; const card = document.getElementById('cors-rules-card'); if (!card) return; const endpoint = card.dataset.corsUrl; const csrfToken = window.getCsrfToken ? window.getCsrfToken() : ''; try { const resp = await fetch(endpoint, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken }, body: JSON.stringify({ rule_index: index }) }); const data = await resp.json(); if (!resp.ok) throw new Error(data.error || 'Failed to delete'); showMessage({ title: 'Rule deleted', body: 'CORS rule has been deleted.', variant: 'success' }); loadCorsRules(card, endpoint); } catch (err) { showMessage({ title: 'Delete failed', body: err.message, variant: 'danger' }); } } return { init: init, loadLifecycleRules: loadLifecycleRules, loadCorsRules: loadCorsRules, loadAcl: loadAcl, deleteLifecycleRule: deleteLifecycleRule, deleteCorsRule: deleteCorsRule }; })();