Update IAM controlsd and ad new S3 actions

This commit is contained in:
2025-11-30 23:58:21 +08:00
parent 53326f4e41
commit 590a39ca80
7 changed files with 320 additions and 25 deletions

View File

@@ -59,11 +59,13 @@
Permissions
</button>
</li>
{% if can_manage_replication %}
<li class="nav-item" role="presentation">
<button class="nav-link {{ 'active' if active_tab == 'replication' else '' }}" id="replication-tab" data-bs-toggle="tab" data-bs-target="#replication-pane" type="button" role="tab" aria-controls="replication-pane" aria-selected="{{ 'true' if active_tab == 'replication' else 'false' }}">
Replication
</button>
</li>
{% endif %}
</ul>
<!-- Tab Content -->
@@ -658,6 +660,7 @@
</div>
</div>
{% if can_manage_replication %}
<!-- Replication Tab -->
<div class="tab-pane fade {{ 'show active' if active_tab == 'replication' else '' }}" id="replication-pane" role="tabpanel" aria-labelledby="replication-tab" tabindex="0">
<div class="row g-4">
@@ -671,8 +674,8 @@
<span class="fw-semibold">Replication Configuration</span>
</div>
<div class="card-body">
{% if replication_rule %}
<!-- Replication Enabled State -->
{% if replication_rule and replication_rule.enabled %}
<!-- Replication Active State -->
<div class="alert alert-success d-flex align-items-center mb-4" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-check-circle-fill flex-shrink-0 me-2" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
@@ -830,17 +833,103 @@
</svg>
Refresh
</a>
<!-- Pause button - available to users with replication permission -->
<form method="POST" action="{{ url_for('ui.update_bucket_replication', bucket_name=bucket_name) }}" class="d-inline">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="action" value="pause">
<button type="submit" class="btn btn-outline-warning">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="me-1" viewBox="0 0 16 16">
<path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"/>
</svg>
Pause Replication
</button>
</form>
{% if is_replication_admin %}
<!-- Delete button - admin only -->
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#disableReplicationModal">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="me-1" viewBox="0 0 16 16">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
</svg>
Disable Replication
Remove Configuration
</button>
{% endif %}
</div>
{% elif replication_rule and not replication_rule.enabled %}
<!-- Replication Paused State -->
<div class="alert alert-warning d-flex align-items-center mb-4" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="flex-shrink-0 me-2" viewBox="0 0 16 16">
<path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"/>
</svg>
<div>
<strong>Replication Paused</strong>
Replication is configured but currently paused. New uploads will not be replicated until resumed.
</div>
</div>
<!-- Show target info even when paused -->
<h6 class="text-muted text-uppercase small mb-3">Replication Target</h6>
<div class="card border mb-4">
<div class="card-body">
<div class="row align-items-center">
<div class="col-auto">
<div class="rounded-circle bg-warning bg-opacity-10 d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="text-warning" viewBox="0 0 16 16">
<path d="M4.715 6.542 3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 5.5L8 6.086a1.002 1.002 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4.018 4.018 0 0 1-.128-1.287z"/>
<path d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 3.55a2 2 0 1 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 1 0-4.243-4.243L6.586 4.672z"/>
</svg>
</div>
</div>
<div class="col">
{% set target_conn = connections | selectattr("id", "equalto", replication_rule.target_connection_id) | first %}
<div class="fw-semibold">{{ target_conn.name if target_conn else 'Unknown Connection' }}</div>
<div class="text-muted small">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor" class="me-1" viewBox="0 0 16 16">
<path d="M5 4a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1H5zm-.5 2.5A.5.5 0 0 1 5 6h6a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zM5 8a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1H5zm0 2a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1H5z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z"/>
</svg>
{{ replication_rule.target_bucket }}
</div>
</div>
<div class="col-auto">
<span class="badge bg-warning-subtle text-warning px-3 py-2">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor" class="me-1" viewBox="0 0 16 16">
<path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"/>
</svg>
Paused
</span>
</div>
</div>
</div>
</div>
<div class="d-flex gap-2">
<!-- Resume button -->
<form method="POST" action="{{ url_for('ui.update_bucket_replication', bucket_name=bucket_name) }}" class="d-inline">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="action" value="resume">
<button type="submit" class="btn btn-primary">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="me-1" viewBox="0 0 16 16">
<path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/>
</svg>
Resume Replication
</button>
</form>
{% if is_replication_admin %}
<!-- Delete button - admin only -->
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#disableReplicationModal">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="me-1" viewBox="0 0 16 16">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
</svg>
Remove Configuration
</button>
{% endif %}
</div>
{% else %}
<!-- Replication Setup State -->
<!-- Replication Not Configured State -->
<div class="text-center py-4">
<div class="rounded-circle bg-body-tertiary d-inline-flex align-items-center justify-content-center mb-3" style="width: 64px; height: 64px;">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="text-muted" viewBox="0 0 16 16">
@@ -848,11 +937,16 @@
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/>
</svg>
</div>
{% if is_replication_admin %}
<h5 class="mb-2">Set Up Replication</h5>
<p class="text-muted mb-4">Automatically copy new objects from this bucket to a bucket in another S3-compatible service.</p>
{% else %}
<h5 class="mb-2">Replication Not Configured</h5>
<p class="text-muted mb-4">An administrator needs to configure replication settings for this bucket before you can enable it.</p>
{% endif %}
</div>
{% if connections %}
{% if is_replication_admin and connections %}
<form method="POST" action="{{ url_for('ui.update_bucket_replication', bucket_name=bucket_name) }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="action" value="create">
@@ -904,7 +998,7 @@
Enable Replication
</button>
</form>
{% else %}
{% elif is_replication_admin %}
<div class="alert alert-warning d-flex align-items-start" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="flex-shrink-0 me-2 mt-1" viewBox="0 0 16 16">
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
@@ -969,6 +1063,7 @@
</div>
</div>
</div>
{% endif %}
</div>
</div>