MyFSIO v0.1.4 Release #5
@@ -185,14 +185,12 @@ def create_ui_app(test_config: Optional[Dict[str, Any]] = None) -> Flask:
|
|||||||
|
|
||||||
def _configure_cors(app: Flask) -> None:
|
def _configure_cors(app: Flask) -> None:
|
||||||
origins = app.config.get("CORS_ORIGINS", ["*"])
|
origins = app.config.get("CORS_ORIGINS", ["*"])
|
||||||
methods = app.config.get("CORS_METHODS", ["GET", "PUT", "POST", "DELETE", "OPTIONS"])
|
methods = app.config.get("CORS_METHODS", ["GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD"])
|
||||||
allow_headers = app.config.get(
|
allow_headers = app.config.get("CORS_ALLOW_HEADERS", ["*"])
|
||||||
"CORS_ALLOW_HEADERS",
|
expose_headers = app.config.get("CORS_EXPOSE_HEADERS", ["*"])
|
||||||
["Content-Type", "X-Access-Key", "X-Secret-Key", "X-Amz-Date", "X-Amz-SignedHeaders"],
|
|
||||||
)
|
|
||||||
CORS(
|
CORS(
|
||||||
app,
|
app,
|
||||||
resources={r"/*": {"origins": origins, "methods": methods, "allow_headers": allow_headers}},
|
resources={r"/*": {"origins": origins, "methods": methods, "allow_headers": allow_headers, "expose_headers": expose_headers}},
|
||||||
supports_credentials=True,
|
supports_credentials=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class AppConfig:
|
|||||||
cors_origins: list[str]
|
cors_origins: list[str]
|
||||||
cors_methods: list[str]
|
cors_methods: list[str]
|
||||||
cors_allow_headers: list[str]
|
cors_allow_headers: list[str]
|
||||||
|
cors_expose_headers: list[str]
|
||||||
session_lifetime_days: int
|
session_lifetime_days: int
|
||||||
auth_max_attempts: int
|
auth_max_attempts: int
|
||||||
auth_lockout_minutes: int
|
auth_lockout_minutes: int
|
||||||
@@ -148,18 +149,9 @@ class AppConfig:
|
|||||||
return parts or default
|
return parts or default
|
||||||
|
|
||||||
cors_origins = _csv(str(_get("CORS_ORIGINS", "*")), ["*"])
|
cors_origins = _csv(str(_get("CORS_ORIGINS", "*")), ["*"])
|
||||||
cors_methods = _csv(str(_get("CORS_METHODS", "GET,PUT,POST,DELETE,OPTIONS")), ["GET", "PUT", "POST", "DELETE", "OPTIONS"])
|
cors_methods = _csv(str(_get("CORS_METHODS", "GET,PUT,POST,DELETE,OPTIONS,HEAD")), ["GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD"])
|
||||||
cors_allow_headers = _csv(str(_get("CORS_ALLOW_HEADERS", "Content-Type,X-Access-Key,X-Secret-Key,X-Amz-Algorithm,X-Amz-Credential,X-Amz-Date,X-Amz-Expires,X-Amz-SignedHeaders,X-Amz-Signature")), [
|
cors_allow_headers = _csv(str(_get("CORS_ALLOW_HEADERS", "*")), ["*"])
|
||||||
"Content-Type",
|
cors_expose_headers = _csv(str(_get("CORS_EXPOSE_HEADERS", "*")), ["*"])
|
||||||
"X-Access-Key",
|
|
||||||
"X-Secret-Key",
|
|
||||||
"X-Amz-Algorithm",
|
|
||||||
"X-Amz-Credential",
|
|
||||||
"X-Amz-Date",
|
|
||||||
"X-Amz-Expires",
|
|
||||||
"X-Amz-SignedHeaders",
|
|
||||||
"X-Amz-Signature",
|
|
||||||
])
|
|
||||||
session_lifetime_days = int(_get("SESSION_LIFETIME_DAYS", 30))
|
session_lifetime_days = int(_get("SESSION_LIFETIME_DAYS", 30))
|
||||||
bucket_stats_cache_ttl = int(_get("BUCKET_STATS_CACHE_TTL", 60)) # Default 60 seconds
|
bucket_stats_cache_ttl = int(_get("BUCKET_STATS_CACHE_TTL", 60)) # Default 60 seconds
|
||||||
|
|
||||||
@@ -191,6 +183,7 @@ class AppConfig:
|
|||||||
cors_origins=cors_origins,
|
cors_origins=cors_origins,
|
||||||
cors_methods=cors_methods,
|
cors_methods=cors_methods,
|
||||||
cors_allow_headers=cors_allow_headers,
|
cors_allow_headers=cors_allow_headers,
|
||||||
|
cors_expose_headers=cors_expose_headers,
|
||||||
session_lifetime_days=session_lifetime_days,
|
session_lifetime_days=session_lifetime_days,
|
||||||
auth_max_attempts=auth_max_attempts,
|
auth_max_attempts=auth_max_attempts,
|
||||||
auth_lockout_minutes=auth_lockout_minutes,
|
auth_lockout_minutes=auth_lockout_minutes,
|
||||||
@@ -234,6 +227,7 @@ class AppConfig:
|
|||||||
"CORS_ORIGINS": self.cors_origins,
|
"CORS_ORIGINS": self.cors_origins,
|
||||||
"CORS_METHODS": self.cors_methods,
|
"CORS_METHODS": self.cors_methods,
|
||||||
"CORS_ALLOW_HEADERS": self.cors_allow_headers,
|
"CORS_ALLOW_HEADERS": self.cors_allow_headers,
|
||||||
|
"CORS_EXPOSE_HEADERS": self.cors_expose_headers,
|
||||||
"SESSION_LIFETIME_DAYS": self.session_lifetime_days,
|
"SESSION_LIFETIME_DAYS": self.session_lifetime_days,
|
||||||
"ENCRYPTION_ENABLED": self.encryption_enabled,
|
"ENCRYPTION_ENABLED": self.encryption_enabled,
|
||||||
"ENCRYPTION_MASTER_KEY_PATH": str(self.encryption_master_key_path),
|
"ENCRYPTION_MASTER_KEY_PATH": str(self.encryption_master_key_path),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""Central location for the application version string."""
|
"""Central location for the application version string."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
APP_VERSION = "0.1.3"
|
APP_VERSION = "0.1.4"
|
||||||
|
|
||||||
|
|
||||||
def get_version() -> str:
|
def get_version() -> str:
|
||||||
|
|||||||
6
docs.md
6
docs.md
@@ -577,9 +577,3 @@ DELETE /bucket-policy/<bucket> # Delete policy
|
|||||||
GET /<bucket>?quota # Get bucket quota
|
GET /<bucket>?quota # Get bucket quota
|
||||||
PUT /<bucket>?quota # Set bucket quota (admin only)
|
PUT /<bucket>?quota # Set bucket quota (admin only)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 14. Next Steps
|
|
||||||
|
|
||||||
- Tailor IAM + policy JSON files for team-ready presets.
|
|
||||||
- Wrap `run_api.py` with gunicorn or another WSGI server for long-running workloads.
|
|
||||||
- Extend `bucket_policies.json` to cover Deny statements that simulate production security controls.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user