You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							658 lines
						
					
					
						
							29 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							658 lines
						
					
					
						
							29 KiB
						
					
					
				
								package app
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
								    "fmt"
							 | 
						|
								    "github.com/seaweedfs/seaweedfs/weed/admin/dash"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								templ Policies(data dash.PoliciesData) {
							 | 
						|
								    <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
							 | 
						|
								        <h1 class="h2">
							 | 
						|
								            <i class="fas fa-shield-alt me-2"></i>IAM Policies
							 | 
						|
								        </h1>
							 | 
						|
								        <div class="btn-toolbar mb-2 mb-md-0">
							 | 
						|
								            <div class="btn-group me-2">
							 | 
						|
								                <button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#createPolicyModal">
							 | 
						|
								                    <i class="fas fa-plus me-1"></i>Create Policy
							 | 
						|
								                </button>
							 | 
						|
								            </div>
							 | 
						|
								        </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <div id="policies-content">
							 | 
						|
								        <!-- Summary Cards -->
							 | 
						|
								        <div class="row mb-4">
							 | 
						|
								            <div class="col-xl-4 col-md-6 mb-4">
							 | 
						|
								                <div class="card border-left-primary shadow h-100 py-2">
							 | 
						|
								                    <div class="card-body">
							 | 
						|
								                        <div class="row no-gutters align-items-center">
							 | 
						|
								                            <div class="col mr-2">
							 | 
						|
								                                <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
							 | 
						|
								                                    Total Policies
							 | 
						|
								                                </div>
							 | 
						|
								                                <div class="h5 mb-0 font-weight-bold text-gray-800">
							 | 
						|
								                                    {fmt.Sprintf("%d", data.TotalPolicies)}
							 | 
						|
								                                </div>
							 | 
						|
								                            </div>
							 | 
						|
								                            <div class="col-auto">
							 | 
						|
								                                <i class="fas fa-shield-alt fa-2x text-gray-300"></i>
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                    </div>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								
							 | 
						|
								            <div class="col-xl-4 col-md-6 mb-4">
							 | 
						|
								                <div class="card border-left-success shadow h-100 py-2">
							 | 
						|
								                    <div class="card-body">
							 | 
						|
								                        <div class="row no-gutters align-items-center">
							 | 
						|
								                            <div class="col mr-2">
							 | 
						|
								                                <div class="text-xs font-weight-bold text-success text-uppercase mb-1">
							 | 
						|
								                                    Active Policies
							 | 
						|
								                                </div>
							 | 
						|
								                                <div class="h5 mb-0 font-weight-bold text-gray-800">
							 | 
						|
								                                    {fmt.Sprintf("%d", data.TotalPolicies)}
							 | 
						|
								                                </div>
							 | 
						|
								                            </div>
							 | 
						|
								                            <div class="col-auto">
							 | 
						|
								                                <i class="fas fa-check-circle fa-2x text-gray-300"></i>
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                    </div>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								
							 | 
						|
								            <div class="col-xl-4 col-md-6 mb-4">
							 | 
						|
								                <div class="card border-left-info shadow h-100 py-2">
							 | 
						|
								                    <div class="card-body">
							 | 
						|
								                        <div class="row no-gutters align-items-center">
							 | 
						|
								                            <div class="col mr-2">
							 | 
						|
								                                <div class="text-xs font-weight-bold text-info text-uppercase mb-1">
							 | 
						|
								                                    Last Updated
							 | 
						|
								                                </div>
							 | 
						|
								                                <div class="h5 mb-0 font-weight-bold text-gray-800">
							 | 
						|
								                                    {data.LastUpdated.Format("15:04")}
							 | 
						|
								                                </div>
							 | 
						|
								                            </div>
							 | 
						|
								                            <div class="col-auto">
							 | 
						|
								                                <i class="fas fa-clock fa-2x text-gray-300"></i>
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                    </div>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								        </div>
							 | 
						|
								
							 | 
						|
								        <!-- Policies Table -->
							 | 
						|
								        <div class="row">
							 | 
						|
								            <div class="col-12">
							 | 
						|
								                <div class="card shadow mb-4">
							 | 
						|
								                    <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
							 | 
						|
								                        <h6 class="m-0 font-weight-bold text-primary">
							 | 
						|
								                            <i class="fas fa-shield-alt me-2"></i>IAM Policies
							 | 
						|
								                        </h6>
							 | 
						|
								                        <div class="dropdown no-arrow">
							 | 
						|
								                            <a class="dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
							 | 
						|
								                                <i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
							 | 
						|
								                            </a>
							 | 
						|
								                            <div class="dropdown-menu dropdown-menu-right shadow animated--fade-in">
							 | 
						|
								                                <div class="dropdown-header">Actions:</div>
							 | 
						|
								                                <a class="dropdown-item" href="#">
							 | 
						|
								                                    <i class="fas fa-download me-2"></i>Export List
							 | 
						|
								                                </a>
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                    </div>
							 | 
						|
								                    <div class="card-body">
							 | 
						|
								                        <div class="table-responsive">
							 | 
						|
								                            <table class="table table-hover" width="100%" cellspacing="0">
							 | 
						|
								                                <thead>
							 | 
						|
								                                    <tr>
							 | 
						|
								                                        <th>Policy Name</th>
							 | 
						|
								                                        <th>Version</th>
							 | 
						|
								                                        <th>Statements</th>
							 | 
						|
								                                        <th>Created</th>
							 | 
						|
								                                        <th>Updated</th>
							 | 
						|
								                                        <th>Actions</th>
							 | 
						|
								                                    </tr>
							 | 
						|
								                                </thead>
							 | 
						|
								                                <tbody>
							 | 
						|
								                                    for _, policy := range data.Policies {
							 | 
						|
								                                        <tr>
							 | 
						|
								                                            <td>
							 | 
						|
								                                                <strong>{policy.Name}</strong>
							 | 
						|
								                                            </td>
							 | 
						|
								                                            <td>
							 | 
						|
								                                                <span class="badge bg-info">{policy.Document.Version}</span>
							 | 
						|
								                                            </td>
							 | 
						|
								                                            <td>
							 | 
						|
								                                                <span class="badge bg-secondary">{fmt.Sprintf("%d statements", len(policy.Document.Statement))}</span>
							 | 
						|
								                                            </td>
							 | 
						|
								                                            <td>
							 | 
						|
								                                                <small class="text-muted">{policy.CreatedAt.Format("2006-01-02 15:04")}</small>
							 | 
						|
								                                            </td>
							 | 
						|
								                                            <td>
							 | 
						|
								                                                <small class="text-muted">{policy.UpdatedAt.Format("2006-01-02 15:04")}</small>
							 | 
						|
								                                            </td>
							 | 
						|
								                                            <td>
							 | 
						|
								                                                <div class="btn-group btn-group-sm" role="group">
							 | 
						|
								                                                    <button type="button" class="btn btn-outline-info view-policy-btn" title="View Policy" data-policy-name={policy.Name}>
							 | 
						|
								                                                        <i class="fas fa-eye"></i>
							 | 
						|
								                                                    </button>
							 | 
						|
								                                                    <button type="button" class="btn btn-outline-primary edit-policy-btn" title="Edit Policy" data-policy-name={policy.Name}>
							 | 
						|
								                                                        <i class="fas fa-edit"></i>
							 | 
						|
								                                                    </button>
							 | 
						|
								                                                    <button type="button" class="btn btn-outline-danger delete-policy-btn" title="Delete Policy" data-policy-name={policy.Name}>
							 | 
						|
								                                                        <i class="fas fa-trash"></i>
							 | 
						|
								                                                    </button>
							 | 
						|
								                                                </div>
							 | 
						|
								                                            </td>
							 | 
						|
								                                        </tr>
							 | 
						|
								                                    }
							 | 
						|
								                                    if len(data.Policies) == 0 {
							 | 
						|
								                                        <tr>
							 | 
						|
								                                            <td colspan="6" class="text-center text-muted py-4">
							 | 
						|
								                                                <i class="fas fa-shield-alt fa-3x mb-3 text-muted"></i>
							 | 
						|
								                                                <div>
							 | 
						|
								                                                    <h5>No IAM policies found</h5>
							 | 
						|
								                                                    <p>Create your first policy to manage access permissions.</p>
							 | 
						|
								                                                    <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createPolicyModal">
							 | 
						|
								                                                        <i class="fas fa-plus me-1"></i>Create Policy
							 | 
						|
								                                                    </button>
							 | 
						|
								                                                </div>
							 | 
						|
								                                            </td>
							 | 
						|
								                                        </tr>
							 | 
						|
								                                    }
							 | 
						|
								                                </tbody>
							 | 
						|
								                            </table>
							 | 
						|
								                        </div>
							 | 
						|
								                    </div>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								        </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <!-- Create Policy Modal -->
							 | 
						|
								    <div class="modal fade" id="createPolicyModal" tabindex="-1" aria-labelledby="createPolicyModalLabel" aria-hidden="true">
							 | 
						|
								        <div class="modal-dialog modal-lg">
							 | 
						|
								            <div class="modal-content">
							 | 
						|
								                <div class="modal-header">
							 | 
						|
								                    <h5 class="modal-title" id="createPolicyModalLabel">
							 | 
						|
								                        <i class="fas fa-shield-alt me-2"></i>Create IAM Policy
							 | 
						|
								                    </h5>
							 | 
						|
								                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
							 | 
						|
								                </div>
							 | 
						|
								                <div class="modal-body">
							 | 
						|
								                    <form id="createPolicyForm">
							 | 
						|
								                        <div class="mb-3">
							 | 
						|
								                            <label for="policyName" class="form-label">Policy Name</label>
							 | 
						|
								                            <input type="text" class="form-control" id="policyName" name="name" required placeholder="e.g., S3ReadOnlyPolicy">
							 | 
						|
								                            <div class="form-text">Enter a unique name for this policy (alphanumeric and underscores only)</div>
							 | 
						|
								                        </div>
							 | 
						|
								                        
							 | 
						|
								                        <div class="mb-3">
							 | 
						|
								                            <label for="policyDocument" class="form-label">Policy Document</label>
							 | 
						|
								                            <textarea class="form-control" id="policyDocument" name="document" rows="15" required placeholder="Enter IAM policy JSON document..."></textarea>
							 | 
						|
								                            <div class="form-text">Enter the policy document in AWS IAM JSON format</div>
							 | 
						|
								                        </div>
							 | 
						|
								
							 | 
						|
								                        <div class="mb-3">
							 | 
						|
								                            <div class="row">
							 | 
						|
								                                <div class="col-md-6">
							 | 
						|
								                                    <button type="button" class="btn btn-outline-info btn-sm" onclick="insertSamplePolicy()">
							 | 
						|
								                                        <i class="fas fa-file-alt me-1"></i>Use Sample Policy
							 | 
						|
								                                    </button>
							 | 
						|
								                                </div>
							 | 
						|
								                                <div class="col-md-6 text-end">
							 | 
						|
								                                    <button type="button" class="btn btn-outline-secondary btn-sm" onclick="validatePolicyDocument()">
							 | 
						|
								                                        <i class="fas fa-check me-1"></i>Validate JSON
							 | 
						|
								                                    </button>
							 | 
						|
								                                </div>
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                    </form>
							 | 
						|
								                </div>
							 | 
						|
								                <div class="modal-footer">
							 | 
						|
								                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
							 | 
						|
								                    <button type="button" class="btn btn-primary" onclick="createPolicy()">
							 | 
						|
								                        <i class="fas fa-plus me-1"></i>Create Policy
							 | 
						|
								                    </button>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								        </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <!-- View Policy Modal -->
							 | 
						|
								    <div class="modal fade" id="viewPolicyModal" tabindex="-1" aria-labelledby="viewPolicyModalLabel" aria-hidden="true">
							 | 
						|
								        <div class="modal-dialog modal-lg">
							 | 
						|
								            <div class="modal-content">
							 | 
						|
								                <div class="modal-header">
							 | 
						|
								                    <h5 class="modal-title" id="viewPolicyModalLabel">
							 | 
						|
								                        <i class="fas fa-eye me-2"></i>View IAM Policy
							 | 
						|
								                    </h5>
							 | 
						|
								                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
							 | 
						|
								                </div>
							 | 
						|
								                <div class="modal-body">
							 | 
						|
								                    <div id="viewPolicyContent">
							 | 
						|
								                        <div class="text-center">
							 | 
						|
								                            <div class="spinner-border" role="status">
							 | 
						|
								                                <span class="visually-hidden">Loading...</span>
							 | 
						|
								                            </div>
							 | 
						|
								                            <p class="mt-2">Loading policy...</p>
							 | 
						|
								                        </div>
							 | 
						|
								                    </div>
							 | 
						|
								                </div>
							 | 
						|
								                <div class="modal-footer">
							 | 
						|
								                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
							 | 
						|
								                    <button type="button" class="btn btn-primary" id="editFromViewBtn">
							 | 
						|
								                        <i class="fas fa-edit me-1"></i>Edit Policy
							 | 
						|
								                    </button>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								        </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <!-- Edit Policy Modal -->
							 | 
						|
								    <div class="modal fade" id="editPolicyModal" tabindex="-1" aria-labelledby="editPolicyModalLabel" aria-hidden="true">
							 | 
						|
								        <div class="modal-dialog modal-lg">
							 | 
						|
								            <div class="modal-content">
							 | 
						|
								                <div class="modal-header">
							 | 
						|
								                    <h5 class="modal-title" id="editPolicyModalLabel">
							 | 
						|
								                        <i class="fas fa-edit me-2"></i>Edit IAM Policy
							 | 
						|
								                    </h5>
							 | 
						|
								                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
							 | 
						|
								                </div>
							 | 
						|
								                <div class="modal-body">
							 | 
						|
								                    <form id="editPolicyForm">
							 | 
						|
								                        <div class="mb-3">
							 | 
						|
								                            <label for="editPolicyName" class="form-label">Policy Name</label>
							 | 
						|
								                            <input type="text" class="form-control" id="editPolicyName" name="name" readonly>
							 | 
						|
								                            <div class="form-text">Policy name cannot be changed</div>
							 | 
						|
								                        </div>
							 | 
						|
								                        
							 | 
						|
								                        <div class="mb-3">
							 | 
						|
								                            <label for="editPolicyDocument" class="form-label">Policy Document</label>
							 | 
						|
								                            <textarea class="form-control" id="editPolicyDocument" name="document" rows="15" required></textarea>
							 | 
						|
								                            <div class="form-text">Edit the policy document in AWS IAM JSON format</div>
							 | 
						|
								                        </div>
							 | 
						|
								
							 | 
						|
								                        <div class="mb-3">
							 | 
						|
								                            <div class="row">
							 | 
						|
								                                <div class="col-md-6">
							 | 
						|
								                                    <button type="button" class="btn btn-outline-info btn-sm" onclick="insertSamplePolicyEdit()">
							 | 
						|
								                                        <i class="fas fa-file-alt me-1"></i>Reset to Sample
							 | 
						|
								                                    </button>
							 | 
						|
								                                </div>
							 | 
						|
								                                <div class="col-md-6 text-end">
							 | 
						|
								                                    <button type="button" class="btn btn-outline-secondary btn-sm" onclick="validateEditPolicyDocument()">
							 | 
						|
								                                        <i class="fas fa-check me-1"></i>Validate JSON
							 | 
						|
								                                    </button>
							 | 
						|
								                                </div>
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                    </form>
							 | 
						|
								                </div>
							 | 
						|
								                <div class="modal-footer">
							 | 
						|
								                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
							 | 
						|
								                    <button type="button" class="btn btn-primary" onclick="updatePolicy()">
							 | 
						|
								                        <i class="fas fa-save me-1"></i>Save Changes
							 | 
						|
								                    </button>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								        </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <!-- JavaScript for Policy Management -->
							 | 
						|
								    <script>
							 | 
						|
								    // Current policy being viewed/edited
							 | 
						|
								    let currentPolicy = null;
							 | 
						|
								    
							 | 
						|
								    // Event listeners for policy actions
							 | 
						|
								    document.addEventListener('DOMContentLoaded', function() {
							 | 
						|
								        // View policy buttons
							 | 
						|
								        document.querySelectorAll('.view-policy-btn').forEach(button => {
							 | 
						|
								            button.addEventListener('click', function() {
							 | 
						|
								                const policyName = this.getAttribute('data-policy-name');
							 | 
						|
								                viewPolicy(policyName);
							 | 
						|
								            });
							 | 
						|
								        });
							 | 
						|
								        
							 | 
						|
								        // Edit policy buttons
							 | 
						|
								        document.querySelectorAll('.edit-policy-btn').forEach(button => {
							 | 
						|
								            button.addEventListener('click', function() {
							 | 
						|
								                const policyName = this.getAttribute('data-policy-name');
							 | 
						|
								                editPolicy(policyName);
							 | 
						|
								            });
							 | 
						|
								        });
							 | 
						|
								        
							 | 
						|
								        // Delete policy buttons
							 | 
						|
								        document.querySelectorAll('.delete-policy-btn').forEach(button => {
							 | 
						|
								            button.addEventListener('click', function() {
							 | 
						|
								                const policyName = this.getAttribute('data-policy-name');
							 | 
						|
								                deletePolicy(policyName);
							 | 
						|
								            });
							 | 
						|
								        });
							 | 
						|
								        
							 | 
						|
								        // Edit from view button
							 | 
						|
								        document.getElementById('editFromViewBtn').addEventListener('click', function() {
							 | 
						|
								            if (currentPolicy) {
							 | 
						|
								                const viewModal = bootstrap.Modal.getInstance(document.getElementById('viewPolicyModal'));
							 | 
						|
								                if (viewModal) viewModal.hide();
							 | 
						|
								                editPolicy(currentPolicy.name);
							 | 
						|
								            }
							 | 
						|
								        });
							 | 
						|
								    });
							 | 
						|
								    
							 | 
						|
								    function createPolicy() {
							 | 
						|
								        const form = document.getElementById('createPolicyForm');
							 | 
						|
								        const formData = new FormData(form);
							 | 
						|
								        
							 | 
						|
								        const policyName = formData.get('name');
							 | 
						|
								        const policyDocumentText = formData.get('document');
							 | 
						|
								        
							 | 
						|
								        if (!policyName || !policyDocumentText) {
							 | 
						|
								            alert('Please fill in all required fields');
							 | 
						|
								            return;
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        let policyDocument;
							 | 
						|
								        try {
							 | 
						|
								            policyDocument = JSON.parse(policyDocumentText);
							 | 
						|
								        } catch (e) {
							 | 
						|
								            alert('Invalid JSON in policy document: ' + e.message);
							 | 
						|
								            return;
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        const requestData = {
							 | 
						|
								            name: policyName,
							 | 
						|
								            document: policyDocument
							 | 
						|
								        };
							 | 
						|
								        
							 | 
						|
								        fetch('/api/object-store/policies', {
							 | 
						|
								            method: 'POST',
							 | 
						|
								            headers: {
							 | 
						|
								                'Content-Type': 'application/json',
							 | 
						|
								            },
							 | 
						|
								            body: JSON.stringify(requestData)
							 | 
						|
								        })
							 | 
						|
								        .then(response => response.json())
							 | 
						|
								        .then(data => {
							 | 
						|
								            if (data.success) {
							 | 
						|
								                alert('Policy created successfully!');
							 | 
						|
								                const modal = bootstrap.Modal.getInstance(document.getElementById('createPolicyModal'));
							 | 
						|
								                if (modal) modal.hide();
							 | 
						|
								                location.reload(); // Refresh the page to show the new policy
							 | 
						|
								            } else {
							 | 
						|
								                alert('Error creating policy: ' + (data.error || 'Unknown error'));
							 | 
						|
								            }
							 | 
						|
								        })
							 | 
						|
								        .catch(error => {
							 | 
						|
								            console.error('Error:', error);
							 | 
						|
								            alert('Error creating policy: ' + error.message);
							 | 
						|
								        });
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function viewPolicy(policyName) {
							 | 
						|
								        // Show the modal first
							 | 
						|
								        const modal = new bootstrap.Modal(document.getElementById('viewPolicyModal'));
							 | 
						|
								        modal.show();
							 | 
						|
								        
							 | 
						|
								        // Reset content to loading state
							 | 
						|
								        document.getElementById('viewPolicyContent').innerHTML = `
							 | 
						|
								            <div class="text-center">
							 | 
						|
								                <div class="spinner-border" role="status">
							 | 
						|
								                    <span class="visually-hidden">Loading...</span>
							 | 
						|
								                </div>
							 | 
						|
								                <p class="mt-2">Loading policy...</p>
							 | 
						|
								            </div>
							 | 
						|
								        `;
							 | 
						|
								        
							 | 
						|
								        // Fetch policy data
							 | 
						|
								        fetch('/api/object-store/policies/' + encodeURIComponent(policyName))
							 | 
						|
								        .then(response => {
							 | 
						|
								            if (!response.ok) {
							 | 
						|
								                throw new Error('Policy not found');
							 | 
						|
								            }
							 | 
						|
								            return response.json();
							 | 
						|
								        })
							 | 
						|
								        .then(policy => {
							 | 
						|
								            currentPolicy = policy;
							 | 
						|
								            displayPolicyDetails(policy);
							 | 
						|
								        })
							 | 
						|
								        .catch(error => {
							 | 
						|
								            console.error('Error:', error);
							 | 
						|
								            document.getElementById('viewPolicyContent').innerHTML = `
							 | 
						|
								                <div class="alert alert-danger" role="alert">
							 | 
						|
								                    <i class="fas fa-exclamation-triangle me-2"></i>
							 | 
						|
								                    Error loading policy: ${error.message}
							 | 
						|
								                </div>
							 | 
						|
								            `;
							 | 
						|
								        });
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function displayPolicyDetails(policy) {
							 | 
						|
								        const content = document.getElementById('viewPolicyContent');
							 | 
						|
								        
							 | 
						|
								        let statementsHtml = '';
							 | 
						|
								        if (policy.document && policy.document.Statement) {
							 | 
						|
								            statementsHtml = policy.document.Statement.map((stmt, index) => `
							 | 
						|
								                <div class="card mb-2">
							 | 
						|
								                    <div class="card-header py-2">
							 | 
						|
								                        <h6 class="mb-0">Statement ${index + 1}</h6>
							 | 
						|
								                    </div>
							 | 
						|
								                    <div class="card-body py-2">
							 | 
						|
								                        <div class="row">
							 | 
						|
								                            <div class="col-md-6">
							 | 
						|
								                                <strong>Effect:</strong> 
							 | 
						|
								                                <span class="badge ${stmt.Effect === 'Allow' ? 'bg-success' : 'bg-danger'}">${stmt.Effect}</span>
							 | 
						|
								                            </div>
							 | 
						|
								                            <div class="col-md-6">
							 | 
						|
								                                <strong>Actions:</strong> ${Array.isArray(stmt.Action) ? stmt.Action.join(', ') : stmt.Action}
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                        <div class="row mt-2">
							 | 
						|
								                            <div class="col-12">
							 | 
						|
								                                <strong>Resources:</strong> ${Array.isArray(stmt.Resource) ? stmt.Resource.join(', ') : stmt.Resource}
							 | 
						|
								                            </div>
							 | 
						|
								                        </div>
							 | 
						|
								                    </div>
							 | 
						|
								                </div>
							 | 
						|
								            `).join('');
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        content.innerHTML = `
							 | 
						|
								            <div class="row mb-3">
							 | 
						|
								                <div class="col-md-6">
							 | 
						|
								                    <strong>Policy Name:</strong> ${policy.name || 'Unknown'}
							 | 
						|
								                </div>
							 | 
						|
								                <div class="col-md-6">
							 | 
						|
								                    <strong>Version:</strong> <span class="badge bg-info">${policy.document?.Version || 'Unknown'}</span>
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								            
							 | 
						|
								            <div class="mb-3">
							 | 
						|
								                <strong>Statements:</strong>
							 | 
						|
								                <div class="mt-2">
							 | 
						|
								                    ${statementsHtml || '<p class="text-muted">No statements found</p>'}
							 | 
						|
								                </div>
							 | 
						|
								            </div>
							 | 
						|
								            
							 | 
						|
								            <div class="mb-3">
							 | 
						|
								                <strong>Raw Policy Document:</strong>
							 | 
						|
								                <pre class="bg-light p-3 border rounded mt-2"><code>${JSON.stringify(policy.document, null, 2)}</code></pre>
							 | 
						|
								            </div>
							 | 
						|
								        `;
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function editPolicy(policyName) {
							 | 
						|
								        // Show the modal first
							 | 
						|
								        const modal = new bootstrap.Modal(document.getElementById('editPolicyModal'));
							 | 
						|
								        modal.show();
							 | 
						|
								        
							 | 
						|
								        // Set policy name
							 | 
						|
								        document.getElementById('editPolicyName').value = policyName;
							 | 
						|
								        document.getElementById('editPolicyDocument').value = 'Loading...';
							 | 
						|
								        
							 | 
						|
								        // Fetch policy data
							 | 
						|
								        fetch('/api/object-store/policies/' + encodeURIComponent(policyName))
							 | 
						|
								        .then(response => {
							 | 
						|
								            if (!response.ok) {
							 | 
						|
								                throw new Error('Policy not found');
							 | 
						|
								            }
							 | 
						|
								            return response.json();
							 | 
						|
								        })
							 | 
						|
								        .then(policy => {
							 | 
						|
								            currentPolicy = policy;
							 | 
						|
								            document.getElementById('editPolicyDocument').value = JSON.stringify(policy.document, null, 2);
							 | 
						|
								        })
							 | 
						|
								        .catch(error => {
							 | 
						|
								            console.error('Error:', error);
							 | 
						|
								            alert('Error loading policy for editing: ' + error.message);
							 | 
						|
								            const editModal = bootstrap.Modal.getInstance(document.getElementById('editPolicyModal'));
							 | 
						|
								            if (editModal) editModal.hide();
							 | 
						|
								        });
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function updatePolicy() {
							 | 
						|
								        const policyName = document.getElementById('editPolicyName').value;
							 | 
						|
								        const policyDocumentText = document.getElementById('editPolicyDocument').value;
							 | 
						|
								        
							 | 
						|
								        if (!policyName || !policyDocumentText) {
							 | 
						|
								            alert('Please fill in all required fields');
							 | 
						|
								            return;
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        let policyDocument;
							 | 
						|
								        try {
							 | 
						|
								            policyDocument = JSON.parse(policyDocumentText);
							 | 
						|
								        } catch (e) {
							 | 
						|
								            alert('Invalid JSON in policy document: ' + e.message);
							 | 
						|
								            return;
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        const requestData = {
							 | 
						|
								            document: policyDocument
							 | 
						|
								        };
							 | 
						|
								        
							 | 
						|
								        fetch('/api/object-store/policies/' + encodeURIComponent(policyName), {
							 | 
						|
								            method: 'PUT',
							 | 
						|
								            headers: {
							 | 
						|
								                'Content-Type': 'application/json',
							 | 
						|
								            },
							 | 
						|
								            body: JSON.stringify(requestData)
							 | 
						|
								        })
							 | 
						|
								        .then(response => response.json())
							 | 
						|
								        .then(data => {
							 | 
						|
								            if (data.success) {
							 | 
						|
								                alert('Policy updated successfully!');
							 | 
						|
								                const modal = bootstrap.Modal.getInstance(document.getElementById('editPolicyModal'));
							 | 
						|
								                if (modal) modal.hide();
							 | 
						|
								                location.reload(); // Refresh the page to show the updated policy
							 | 
						|
								            } else {
							 | 
						|
								                alert('Error updating policy: ' + (data.error || 'Unknown error'));
							 | 
						|
								            }
							 | 
						|
								        })
							 | 
						|
								        .catch(error => {
							 | 
						|
								            console.error('Error:', error);
							 | 
						|
								            alert('Error updating policy: ' + error.message);
							 | 
						|
								        });
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function insertSamplePolicy() {
							 | 
						|
								        const samplePolicy = {
							 | 
						|
								            "Version": "2012-10-17",
							 | 
						|
								            "Statement": [
							 | 
						|
								                {
							 | 
						|
								                    "Effect": "Allow",
							 | 
						|
								                    "Action": [
							 | 
						|
								                        "s3:GetObject",
							 | 
						|
								                        "s3:PutObject"
							 | 
						|
								                    ],
							 | 
						|
								                    "Resource": [
							 | 
						|
								                        "arn:aws:s3:::my-bucket/*"
							 | 
						|
								                    ]
							 | 
						|
								                }
							 | 
						|
								            ]
							 | 
						|
								        };
							 | 
						|
								        
							 | 
						|
								        document.getElementById('policyDocument').value = JSON.stringify(samplePolicy, null, 2);
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function insertSamplePolicyEdit() {
							 | 
						|
								        const samplePolicy = {
							 | 
						|
								            "Version": "2012-10-17",
							 | 
						|
								            "Statement": [
							 | 
						|
								                {
							 | 
						|
								                    "Effect": "Allow",
							 | 
						|
								                    "Action": [
							 | 
						|
								                        "s3:GetObject",
							 | 
						|
								                        "s3:PutObject"
							 | 
						|
								                    ],
							 | 
						|
								                    "Resource": [
							 | 
						|
								                        "arn:aws:s3:::my-bucket/*"
							 | 
						|
								                    ]
							 | 
						|
								                }
							 | 
						|
								            ]
							 | 
						|
								        };
							 | 
						|
								        
							 | 
						|
								        document.getElementById('editPolicyDocument').value = JSON.stringify(samplePolicy, null, 2);
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function validatePolicyDocument() {
							 | 
						|
								        const policyText = document.getElementById('policyDocument').value;
							 | 
						|
								        validatePolicyJSON(policyText);
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function validateEditPolicyDocument() {
							 | 
						|
								        const policyText = document.getElementById('editPolicyDocument').value;
							 | 
						|
								        validatePolicyJSON(policyText);
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function validatePolicyJSON(policyText) {
							 | 
						|
								        if (!policyText) {
							 | 
						|
								            alert('Please enter a policy document first');
							 | 
						|
								            return;
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        try {
							 | 
						|
								            const policy = JSON.parse(policyText);
							 | 
						|
								            
							 | 
						|
								            // Basic validation
							 | 
						|
								            if (!policy.Version) {
							 | 
						|
								                alert('Policy must have a Version field');
							 | 
						|
								                return;
							 | 
						|
								            }
							 | 
						|
								            
							 | 
						|
								            if (!policy.Statement || !Array.isArray(policy.Statement)) {
							 | 
						|
								                alert('Policy must have a Statement array');
							 | 
						|
								                return;
							 | 
						|
								            }
							 | 
						|
								            
							 | 
						|
								            alert('Policy document is valid JSON!');
							 | 
						|
								        } catch (e) {
							 | 
						|
								            alert('Invalid JSON: ' + e.message);
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    function deletePolicy(policyName) {
							 | 
						|
								        if (confirm('Are you sure you want to delete policy "' + policyName + '"?')) {
							 | 
						|
								            fetch('/api/object-store/policies/' + encodeURIComponent(policyName), {
							 | 
						|
								                method: 'DELETE'
							 | 
						|
								            })
							 | 
						|
								            .then(response => response.json())
							 | 
						|
								            .then(data => {
							 | 
						|
								                if (data.success) {
							 | 
						|
								                    alert('Policy deleted successfully!');
							 | 
						|
								                    location.reload(); // Refresh the page
							 | 
						|
								                } else {
							 | 
						|
								                    alert('Error deleting policy: ' + (data.error || 'Unknown error'));
							 | 
						|
								                }
							 | 
						|
								            })
							 | 
						|
								            .catch(error => {
							 | 
						|
								                console.error('Error:', error);
							 | 
						|
								                alert('Error deleting policy: ' + error.message);
							 | 
						|
								            });
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    </script>
							 | 
						|
								} 
							 |