modified: .gitignore

modified:   app.py
	new file:   command_storage/.gitignore
This commit is contained in:
SimolZimol
2026-01-07 04:24:59 +01:00
parent 6d38651305
commit 404b2ac77f
3 changed files with 42 additions and 24 deletions

3
.gitignore vendored
View File

@@ -3,6 +3,9 @@ __pycache__/
*.py[cod] *.py[cod]
*$py.class *$py.class
# Command storage (temporary files)
command_storage/*.json
# Virtual environments # Virtual environments
.venv/ .venv/
venv/ venv/

48
app.py
View File

@@ -8,18 +8,22 @@ from flask import Flask, render_template, jsonify, send_from_directory, request
app = Flask(__name__) app = Flask(__name__)
# In-memory storage for commands (thread-safe) # File-based storage for commands (works across multiple workers)
command_storage = {} STORAGE_DIR = Path(__file__).parent / 'command_storage'
STORAGE_DIR.mkdir(exist_ok=True)
storage_lock = Lock() storage_lock = Lock()
def cleanup_expired_commands(): def cleanup_expired_commands():
"""Remove expired commands from storage""" """Remove expired command files"""
with storage_lock:
now = datetime.now(timezone.utc) now = datetime.now(timezone.utc)
expired_keys = [key for key, value in command_storage.items() for file_path in STORAGE_DIR.glob('*.json'):
if datetime.fromisoformat(value['expires_at']) < now] try:
for key in expired_keys: with open(file_path, 'r') as f:
del command_storage[key] data = json.load(f)
if datetime.fromisoformat(data['expires_at']) < now:
file_path.unlink()
except:
pass # Ignore corrupted files
# Load projects from version.json # Load projects from version.json
def load_projects(): def load_projects():
@@ -272,14 +276,19 @@ def store_command():
created_at = datetime.now(timezone.utc) created_at = datetime.now(timezone.utc)
expires_at = created_at + timedelta(minutes=30) expires_at = created_at + timedelta(minutes=30)
# Store command # Prepare data
with storage_lock: command_data = {
command_storage[command_uuid] = {
'command': command, 'command': command,
'created_at': created_at.isoformat(), 'created_at': created_at.isoformat(),
'expires_at': expires_at.isoformat() 'expires_at': expires_at.isoformat()
} }
# Store to file
storage_file = STORAGE_DIR / f'{command_uuid}.json'
with storage_lock:
with open(storage_file, 'w', encoding='utf-8') as f:
json.dump(command_data, f)
# Generate URL - use HTTPS if behind proxy # Generate URL - use HTTPS if behind proxy
scheme = request.headers.get('X-Forwarded-Proto', 'https' if request.is_secure else 'http') scheme = request.headers.get('X-Forwarded-Proto', 'https' if request.is_secure else 'http')
host = request.headers.get('X-Forwarded-Host', request.host) host = request.headers.get('X-Forwarded-Host', request.host)
@@ -300,20 +309,23 @@ def retrieve_command(command_uuid):
"""Retrieve stored command by UUID (JSON response for plugin)""" """Retrieve stored command by UUID (JSON response for plugin)"""
cleanup_expired_commands() cleanup_expired_commands()
# Keep lock for entire operation to prevent race conditions storage_file = STORAGE_DIR / f'{command_uuid}.json'
with storage_lock:
command_data = command_storage.get(command_uuid)
if not command_data: if not storage_file.exists():
return jsonify({'error': 'Command not found or expired'}), 404 return jsonify({'error': 'Command not found or expired'}), 404
try:
with open(storage_file, 'r', encoding='utf-8') as f:
command_data = json.load(f)
# Check if expired # Check if expired
if datetime.fromisoformat(command_data['expires_at']) < datetime.now(timezone.utc): if datetime.fromisoformat(command_data['expires_at']) < datetime.now(timezone.utc):
del command_storage[command_uuid] storage_file.unlink()
return jsonify({'error': 'Command expired'}), 410 return jsonify({'error': 'Command expired'}), 410
# Return a copy to avoid modification outside lock return jsonify(command_data), 200
return jsonify(dict(command_data)), 200 except Exception as e:
return jsonify({'error': 'Failed to read command'}), 500
# Serve /versions as JSON # Serve /versions as JSON
@app.route('/versions') @app.route('/versions')

3
command_storage/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
# This directory stores temporary command data
# Files are automatically deleted after 30 minutes
*.json