window.IAMManagement = (function() { 'use strict'; var users = []; var currentUserKey = null; var endpoints = {}; var csrfToken = ''; var iamLocked = false; var policyModal = null; var editUserModal = null; var deleteUserModal = null; var rotateSecretModal = null; var currentRotateKey = null; var currentEditKey = null; var currentDeleteKey = null; var policyTemplates = { full: [{ bucket: '*', actions: ['list', 'read', 'write', 'delete', 'share', 'policy', 'replication', 'iam:list_users', 'iam:*'] }], readonly: [{ bucket: '*', actions: ['list', 'read'] }], writer: [{ bucket: '*', actions: ['list', 'read', 'write'] }] }; function init(config) { users = config.users || []; currentUserKey = config.currentUserKey || null; endpoints = config.endpoints || {}; csrfToken = config.csrfToken || ''; iamLocked = config.iamLocked || false; if (iamLocked) return; initModals(); setupJsonAutoIndent(); setupCopyButtons(); setupPolicyEditor(); setupCreateUserModal(); setupEditUserModal(); setupDeleteUserModal(); setupRotateSecretModal(); setupFormHandlers(); } function initModals() { var policyModalEl = document.getElementById('policyEditorModal'); var editModalEl = document.getElementById('editUserModal'); var deleteModalEl = document.getElementById('deleteUserModal'); var rotateModalEl = document.getElementById('rotateSecretModal'); if (policyModalEl) policyModal = new bootstrap.Modal(policyModalEl); if (editModalEl) editUserModal = new bootstrap.Modal(editModalEl); if (deleteModalEl) deleteUserModal = new bootstrap.Modal(deleteModalEl); if (rotateModalEl) rotateSecretModal = new bootstrap.Modal(rotateModalEl); } function setupJsonAutoIndent() { window.UICore.setupJsonAutoIndent(document.getElementById('policyEditorDocument')); window.UICore.setupJsonAutoIndent(document.getElementById('createUserPolicies')); } function setupCopyButtons() { document.querySelectorAll('.config-copy').forEach(function(button) { button.addEventListener('click', async function() { var targetId = button.dataset.copyTarget; var target = document.getElementById(targetId); if (!target) return; await window.UICore.copyToClipboard(target.innerText, button, 'Copy JSON'); }); }); var secretCopyButton = document.querySelector('[data-secret-copy]'); if (secretCopyButton) { secretCopyButton.addEventListener('click', async function() { var secretInput = document.getElementById('disclosedSecretValue'); if (!secretInput) return; await window.UICore.copyToClipboard(secretInput.value, secretCopyButton, 'Copy'); }); } } function getUserPolicies(accessKey) { var user = users.find(function(u) { return u.access_key === accessKey; }); return user ? JSON.stringify(user.policies, null, 2) : ''; } function applyPolicyTemplate(name, textareaEl) { if (policyTemplates[name] && textareaEl) { textareaEl.value = JSON.stringify(policyTemplates[name], null, 2); } } function setupPolicyEditor() { var userLabelEl = document.getElementById('policyEditorUserLabel'); var userInputEl = document.getElementById('policyEditorUser'); var textareaEl = document.getElementById('policyEditorDocument'); document.querySelectorAll('[data-policy-template]').forEach(function(button) { button.addEventListener('click', function() { applyPolicyTemplate(button.dataset.policyTemplate, textareaEl); }); }); document.querySelectorAll('[data-policy-editor]').forEach(function(button) { button.addEventListener('click', function() { var key = button.getAttribute('data-access-key'); if (!key) return; userLabelEl.textContent = key; userInputEl.value = key; textareaEl.value = getUserPolicies(key); policyModal.show(); }); }); } function setupCreateUserModal() { var createUserPoliciesEl = document.getElementById('createUserPolicies'); document.querySelectorAll('[data-create-policy-template]').forEach(function(button) { button.addEventListener('click', function() { applyPolicyTemplate(button.dataset.createPolicyTemplate, createUserPoliciesEl); }); }); } function setupEditUserModal() { var editUserForm = document.getElementById('editUserForm'); var editUserDisplayName = document.getElementById('editUserDisplayName'); document.querySelectorAll('[data-edit-user]').forEach(function(btn) { btn.addEventListener('click', function() { var key = btn.dataset.editUser; var name = btn.dataset.displayName; currentEditKey = key; editUserDisplayName.value = name; editUserForm.action = endpoints.updateUser.replace('ACCESS_KEY', key); editUserModal.show(); }); }); } function setupDeleteUserModal() { var deleteUserForm = document.getElementById('deleteUserForm'); var deleteUserLabel = document.getElementById('deleteUserLabel'); var deleteSelfWarning = document.getElementById('deleteSelfWarning'); document.querySelectorAll('[data-delete-user]').forEach(function(btn) { btn.addEventListener('click', function() { var key = btn.dataset.deleteUser; currentDeleteKey = key; deleteUserLabel.textContent = key; deleteUserForm.action = endpoints.deleteUser.replace('ACCESS_KEY', key); if (key === currentUserKey) { deleteSelfWarning.classList.remove('d-none'); } else { deleteSelfWarning.classList.add('d-none'); } deleteUserModal.show(); }); }); } function setupRotateSecretModal() { var rotateUserLabel = document.getElementById('rotateUserLabel'); var confirmRotateBtn = document.getElementById('confirmRotateBtn'); var rotateCancelBtn = document.getElementById('rotateCancelBtn'); var rotateDoneBtn = document.getElementById('rotateDoneBtn'); var rotateSecretConfirm = document.getElementById('rotateSecretConfirm'); var rotateSecretResult = document.getElementById('rotateSecretResult'); var newSecretKeyInput = document.getElementById('newSecretKey'); var copyNewSecretBtn = document.getElementById('copyNewSecret'); document.querySelectorAll('[data-rotate-user]').forEach(function(btn) { btn.addEventListener('click', function() { currentRotateKey = btn.dataset.rotateUser; rotateUserLabel.textContent = currentRotateKey; rotateSecretConfirm.classList.remove('d-none'); rotateSecretResult.classList.add('d-none'); confirmRotateBtn.classList.remove('d-none'); rotateCancelBtn.classList.remove('d-none'); rotateDoneBtn.classList.add('d-none'); rotateSecretModal.show(); }); }); if (confirmRotateBtn) { confirmRotateBtn.addEventListener('click', async function() { if (!currentRotateKey) return; window.UICore.setButtonLoading(confirmRotateBtn, true, 'Rotating...'); try { var url = endpoints.rotateSecret.replace('ACCESS_KEY', currentRotateKey); var response = await fetch(url, { method: 'POST', headers: { 'Accept': 'application/json', 'X-CSRFToken': csrfToken } }); if (!response.ok) { var data = await response.json(); throw new Error(data.error || 'Failed to rotate secret'); } var data = await response.json(); newSecretKeyInput.value = data.secret_key; rotateSecretConfirm.classList.add('d-none'); rotateSecretResult.classList.remove('d-none'); confirmRotateBtn.classList.add('d-none'); rotateCancelBtn.classList.add('d-none'); rotateDoneBtn.classList.remove('d-none'); } catch (err) { if (window.showToast) { window.showToast(err.message, 'Error', 'danger'); } rotateSecretModal.hide(); } finally { window.UICore.setButtonLoading(confirmRotateBtn, false); } }); } if (copyNewSecretBtn) { copyNewSecretBtn.addEventListener('click', async function() { await window.UICore.copyToClipboard(newSecretKeyInput.value, copyNewSecretBtn, 'Copy'); }); } if (rotateDoneBtn) { rotateDoneBtn.addEventListener('click', function() { window.location.reload(); }); } } function createUserCardHtml(accessKey, displayName, policies) { var policyBadges = ''; if (policies && policies.length > 0) { policyBadges = policies.map(function(p) { var actionText = p.actions && p.actions.includes('*') ? 'full' : (p.actions ? p.actions.length : 0); return '' + '' + window.UICore.escapeHtml(p.bucket) + '(' + actionText + ')'; }).join(''); } else { policyBadges = 'No policies'; } return '
' + window.UICore.escapeHtml(accessKey) + '' +
'' + window.UICore.escapeHtml(data.access_key) + 'This secret is only shown once. Copy it now and store it securely.
' + '