Add presigned URL management
This commit is contained in:
@@ -577,6 +577,59 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Presigned URLs Section -->
|
||||
<div x-show="activeSection === 'presigned'" x-cloak class="fade-in">
|
||||
<div class="header">
|
||||
<h2><i class="fas fa-link"></i> Presigned URLs</h2>
|
||||
<button @click="showCreatePresignedModal = true; loadBuckets(); loadCredentials()" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> Create URL
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div x-show="message" x-text="message" :class="messageType === 'error' ? 'error' : 'success'"></div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div x-show="loading" class="loading">Loading URLs...</div>
|
||||
|
||||
<template x-if="!loading && presignedUrls.length === 0">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-link"></i>
|
||||
<h3>No presigned URLs found</h3>
|
||||
<p>Create a presigned URL to share temporary access.</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template x-if="!loading && presignedUrls.length > 0">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Bucket</th>
|
||||
<th>Object</th>
|
||||
<th>Method</th>
|
||||
<th>Expires</th>
|
||||
<th>URL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template x-for="p in presignedUrls" :key="p.url">
|
||||
<tr>
|
||||
<td x-text="p.bucket_name"></td>
|
||||
<td x-text="p.object_key"></td>
|
||||
<td x-text="p.method"></td>
|
||||
<td x-text="p.expires_at"></td>
|
||||
<td>
|
||||
<input class="form-input" :value="p.url" readonly style="font-size: 0.8rem;">
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create Credential Modal -->
|
||||
<div x-show="showCreateCredentialModal" x-cloak class="modal" @click.self="showCreateCredentialModal = false">
|
||||
<div class="modal-content">
|
||||
@@ -646,6 +699,58 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create Presigned URL Modal -->
|
||||
<div x-show="showCreatePresignedModal" x-cloak class="modal" @click.self="showCreatePresignedModal = false">
|
||||
<div class="modal-content">
|
||||
<h3 style="margin-bottom: 1rem;">Create Presigned URL</h3>
|
||||
<form @submit.prevent="createPresigned()">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Bucket Name</label>
|
||||
<select x-model="newPresigned.bucket_name" class="form-select" required>
|
||||
<option value="">Select bucket...</option>
|
||||
<template x-for="bucket in buckets" :key="bucket.name">
|
||||
<option :value="bucket.name" x-text="bucket.name"></option>
|
||||
</template>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Object Key</label>
|
||||
<input x-model="newPresigned.object_key" type="text" class="form-input" placeholder="path/to/file.txt" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Method</label>
|
||||
<select x-model="newPresigned.method" class="form-select">
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="POST">POST</option>
|
||||
<option value="DELETE">DELETE</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Expires In (seconds)</label>
|
||||
<input x-model="newPresigned.expires_in" type="number" class="form-input" min="1" max="604800" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Access Key</label>
|
||||
<select x-model="newPresigned.access_key" class="form-select" required>
|
||||
<option value="">Select credential...</option>
|
||||
<template x-for="credential in credentials" :key="credential.id">
|
||||
<option :value="credential.access_key" x-text="credential.user_name || credential.access_key"></option>
|
||||
</template>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; gap: 1rem; justify-content: flex-end;">
|
||||
<button type="button" @click="showCreatePresignedModal = false" class="btn btn-secondary">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -664,10 +769,12 @@
|
||||
selectedBucket: null,
|
||||
filteredObjects: [],
|
||||
objectSearch: '',
|
||||
presignedUrls: [],
|
||||
|
||||
// Modals
|
||||
showCreateCredentialModal: false,
|
||||
showCreateBucketModal: false,
|
||||
showCreatePresignedModal: false,
|
||||
|
||||
// Forms
|
||||
newCredential: {
|
||||
@@ -680,6 +787,13 @@
|
||||
owner_id: '',
|
||||
region: 'us-east-1'
|
||||
},
|
||||
newPresigned: {
|
||||
bucket_name: '',
|
||||
object_key: '',
|
||||
method: 'GET',
|
||||
expires_in: 3600,
|
||||
access_key: ''
|
||||
},
|
||||
|
||||
init() {
|
||||
this.loadStats();
|
||||
@@ -699,6 +813,9 @@
|
||||
case 'buckets':
|
||||
this.loadBuckets();
|
||||
break;
|
||||
case 'presigned':
|
||||
this.loadPresignedUrls();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -795,6 +912,39 @@
|
||||
}
|
||||
},
|
||||
|
||||
async loadPresignedUrls() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await this.apiCall('/presigned-urls');
|
||||
this.presignedUrls = response.urls;
|
||||
} catch (error) {
|
||||
console.error('Failed to load presigned URLs:', error);
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
async createPresigned() {
|
||||
try {
|
||||
const payload = { ...this.newPresigned };
|
||||
const urlData = await this.apiCall('/presigned-urls', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
this.showMessage('Presigned URL created');
|
||||
this.showCreatePresignedModal = false;
|
||||
this.newPresigned = { bucket_name: '', object_key: '', method: 'GET', expires_in: 3600, access_key: '' };
|
||||
this.presignedUrls.unshift({
|
||||
bucket_name: payload.bucket_name,
|
||||
object_key: payload.object_key,
|
||||
method: payload.method,
|
||||
expires_at: new Date(Date.now() + payload.expires_in * 1000).toISOString().slice(0,19).replace('T',' '),
|
||||
url: urlData.url
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to create presigned URL:', error);
|
||||
}
|
||||
},
|
||||
|
||||
async deleteCredential(id) {
|
||||
if (!confirm('Are you sure you want to delete this credential?')) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user