Fix UI/UX issues: lifecycle warnings, CORS tooltip, IAM overflow, config validation, JS maintenance

This commit is contained in:
2026-01-09 12:47:37 +08:00
parent a5d19e2982
commit c5d4b2f1cd
9 changed files with 3589 additions and 3508 deletions

View File

@@ -374,6 +374,7 @@ def bucket_detail(bucket_name: str):
kms_keys = kms_manager.list_keys() if kms_manager else []
kms_enabled = current_app.config.get("KMS_ENABLED", False)
encryption_enabled = current_app.config.get("ENCRYPTION_ENABLED", False)
lifecycle_enabled = current_app.config.get("LIFECYCLE_ENABLED", False)
can_manage_encryption = can_manage_versioning
bucket_quota = storage.get_bucket_quota(bucket_name)
@@ -418,6 +419,7 @@ def bucket_detail(bucket_name: str):
kms_keys=kms_keys,
kms_enabled=kms_enabled,
encryption_enabled=encryption_enabled,
lifecycle_enabled=lifecycle_enabled,
bucket_quota=bucket_quota,
bucket_stats=bucket_stats,
can_manage_quota=can_manage_quota,

View File

@@ -1,6 +1,6 @@
from __future__ import annotations
APP_VERSION = "0.2.0"
APP_VERSION = "0.2.1"
def get_version() -> str:

46
docs.md
View File

@@ -189,6 +189,52 @@ All configuration is done via environment variables. The table below lists every
| `KMS_ENABLED` | `false` | Enable KMS key management for encryption. |
| `KMS_KEYS_PATH` | `data/.myfsio.sys/keys/kms_keys.json` | Path to store KMS key metadata. |
## Lifecycle Rules
Lifecycle rules automate object management by scheduling deletions based on object age.
### Enabling Lifecycle Enforcement
By default, lifecycle enforcement is disabled. Enable it by setting the environment variable:
```bash
LIFECYCLE_ENABLED=true python run.py
```
Or in your `myfsio.env` file:
```
LIFECYCLE_ENABLED=true
LIFECYCLE_INTERVAL_SECONDS=3600 # Check interval (default: 1 hour)
```
### Configuring Rules
Once enabled, configure lifecycle rules via:
- **Web UI:** Bucket Details → Lifecycle tab → Add Rule
- **S3 API:** `PUT /<bucket>?lifecycle` with XML configuration
### Available Actions
| Action | Description |
|--------|-------------|
| **Expiration** | Delete current version objects after N days |
| **NoncurrentVersionExpiration** | Delete old versions N days after becoming noncurrent (requires versioning) |
| **AbortIncompleteMultipartUpload** | Clean up incomplete multipart uploads after N days |
### Example Configuration (XML)
```xml
<LifecycleConfiguration>
<Rule>
<ID>DeleteOldLogs</ID>
<Status>Enabled</Status>
<Filter><Prefix>logs/</Prefix></Filter>
<Expiration><Days>30</Days></Expiration>
</Rule>
</LifecycleConfiguration>
```
### Performance Tuning
| Variable | Default | Notes |

View File

@@ -2,6 +2,7 @@ Flask>=3.1.2
Flask-Limiter>=4.1.1
Flask-Cors>=6.0.2
Flask-WTF>=1.2.2
python-dotenv>=1.2.1
pytest>=9.0.2
requests>=2.32.5
boto3>=1.42.14

11
run.py
View File

@@ -6,6 +6,17 @@ import os
import sys
import warnings
from multiprocessing import Process
from pathlib import Path
from dotenv import load_dotenv
for _env_file in [
Path("/opt/myfsio/myfsio.env"),
Path.cwd() / ".env",
Path.cwd() / "myfsio.env",
]:
if _env_file.exists():
load_dotenv(_env_file, override=True)
from app import create_api_app, create_ui_app
from app.config import AppConfig

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -116,8 +116,8 @@
<div class="card h-100 iam-user-card">
<div class="card-body">
<div class="d-flex align-items-start justify-content-between mb-3">
<div class="d-flex align-items-center gap-3">
<div class="user-avatar user-avatar-lg">
<div class="d-flex align-items-center gap-3 min-width-0 overflow-hidden">
<div class="user-avatar user-avatar-lg flex-shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0zm4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10z"/>
</svg>
@@ -127,7 +127,7 @@
<code class="small text-muted d-block text-truncate" title="{{ user.access_key }}">{{ user.access_key }}</code>
</div>
</div>
<div class="dropdown">
<div class="dropdown flex-shrink-0">
<button class="btn btn-sm btn-icon" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>

View File

@@ -184,5 +184,5 @@ class TestPaginatedObjectListing:
assert resp.status_code == 200
html = resp.data.decode("utf-8")
# Should have the JavaScript loading infrastructure
assert "loadObjects" in html or "objectsApiUrl" in html
# Should have the JavaScript loading infrastructure (external JS file)
assert "bucket-detail-main.js" in html