Admin-Interface¶
Audience: Admin
You will learn:
- Administrative Funktionen des Web-Interfaces
- Icon-Management und Metadaten-Verwaltung
- Bulk-Operationen und Maintenance-Tools
- Admin-spezifische UI-Komponenten
Pre-requisites: - Administrator-Handbuch verstanden - Frontend Web-Interface Grundlagen - Admin-Rechte auf dem System
Status: Teilweise implementiert¶
Hinweis
Das dedizierte Admin-Interface ist derzeit teilweise implementiert. Die meisten administrativen Funktionen werden über Command-Line-Tools und direkte File-Bearbeitung durchgeführt.
Evidenz: app.py:1-67 (kein /admin Endpunkt), replit.md administrative workflows
Aktuelle Admin-Funktionen¶
1. Web-Interface für Übersicht¶
Das Standard-Web-Interface bietet bereits grundlegende administrative Einblicke:
@app.route('/')
def index():
"""Zeigt komplette Icon-Übersicht - auch für Admins nutzbar"""
icons, categories = get_icon_list()
return render_template('index.html',
icons=icons,
categories=categories,
total_icons=len(icons))
Admin-relevante Informationen: - Gesamtanzahl Icons: Anzeige in Header - Kategorie-Verteilung: Dropdown mit Icon-Anzahl pro Kategorie - Vollständige Icon-Liste: Alle verfügbaren Icons mit Metadaten
Evidenz: app.py:45-49
2. API für administrative Abfragen¶
@app.route('/api/icons')
def api_icons():
"""API-Endpunkt für programmatische Admin-Tools"""
icons, categories = get_icon_list()
return jsonify({
'icons': icons,
'categories': categories,
'metadata': {
'total_icons': len(icons),
'total_categories': len(categories),
'timestamp': time.time()
}
})
Administrative API-Nutzung:
# Icon-Anzahl prüfen
curl -s http://localhost:5000/api/icons | jq '.metadata.total_icons'
# Kategorie-Konsistenz prüfen
curl -s http://localhost:5000/api/icons | jq '.categories | keys[]'
Evidenz: app.py:51-55
Geplante Admin-Interface Features¶
1. Admin Dashboard¶
<!-- Geplant: /admin Route -->
<div class="admin-dashboard">
<div class="stats-grid">
<div class="stat-card">
<h3>{{ total_icons }}</h3>
<p>Total Icons</p>
</div>
<div class="stat-card">
<h3>{{ categories|length }}</h3>
<p>Kategorien</p>
</div>
<div class="stat-card">
<h3>{{ zip_size }}</h3>
<p>ZIP Größe</p>
</div>
</div>
<div class="recent-changes">
<h2>Letzte Änderungen</h2>
<!-- Git commits oder File-Timestamps -->
</div>
<div class="system-health">
<h2>System Status</h2>
<div class="health-checks">
<div class="check {{ 'ok' if icons_dir_exists else 'error' }}">
Icons Directory: {{ 'OK' if icons_dir_exists else 'ERROR' }}
</div>
<div class="check {{ 'ok' if metadata_valid else 'error' }}">
Metadaten: {{ 'Valid' if metadata_valid else 'Invalid' }}
</div>
</div>
</div>
</div>
2. Icon-Upload Interface¶
<!-- Geplant: Icon-Upload Form -->
<div class="icon-upload">
<h2>Neue Icons hinzufügen</h2>
<form id="icon-upload-form" enctype="multipart/form-data">
<div class="upload-area">
<input type="file" id="svg-file" accept=".svg" multiple>
<label for="svg-file">SVG-Dateien auswählen</label>
</div>
<div class="metadata-form">
<select name="category" required>
<option value="">Kategorie wählen</option>
{% for category in categories %}
<option value="{{ category }}">{{ category }}</option>
{% endfor %}
</select>
<input type="text" name="custom-category" placeholder="Neue Kategorie">
<div class="icon-preview">
<!-- Dynamic preview of uploaded SVGs -->
</div>
</div>
<button type="submit">Icons hinzufügen</button>
</form>
</div>
3. Kategorie-Management¶
<!-- Geplant: Kategorie-Editor -->
<div class="category-management">
<h2>Kategorien verwalten</h2>
<div class="category-list">
{% for category, icon_list in categories.items() %}
<div class="category-item">
<div class="category-header">
<h3 contenteditable="true">{{ category }}</h3>
<span class="icon-count">{{ icon_list|length }} Icons</span>
<button class="delete-category">🗑️</button>
</div>
<div class="category-icons">
{% for icon_filename in icon_list %}
<div class="icon-item" data-filename="{{ icon_filename }}">
<img src="/static/icons/{{ icon_filename }}" alt="{{ icon_filename }}">
<span>{{ icon_filename }}</span>
<button class="move-icon">↗️</button>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="add-category">
<input type="text" placeholder="Neue Kategorie" id="new-category">
<button onclick="addCategory()">Hinzufügen</button>
</div>
</div>
Command-Line Admin-Tools¶
1. System-Health-Check¶
#!/bin/bash
# scripts/admin-health-check.sh
echo "=== Icon System Health Check ==="
# Icons Directory Check
if [ -d "static/icons" ]; then
icon_count=$(ls static/icons/*.svg | wc -l)
echo "✓ Icons Directory: $icon_count SVG files"
else
echo "❌ Icons Directory: Missing"
exit 1
fi
# Metadata Check
if [ -f "icons.json" ]; then
if python3 -c "import json; json.load(open('icons.json'))" 2>/dev/null; then
echo "✓ Metadata: Valid JSON"
else
echo "❌ Metadata: Invalid JSON"
exit 1
fi
else
echo "❌ Metadata: icons.json missing"
exit 1
fi
# Consistency Check
python3 -c "
import json, os
with open('icons.json') as f:
categories = json.load(f)
categorized = set()
for cat_icons in categories.values():
categorized.update(cat_icons)
actual = set(os.listdir('static/icons'))
uncategorized = actual - categorized
missing = categorized - actual
if uncategorized:
print(f'⚠️ Uncategorized: {len(uncategorized)} icons')
if missing:
print(f'❌ Missing: {len(missing)} categorized icons not found')
if not uncategorized and not missing:
print('✓ Categorization: Consistent')
"
echo "=== Health Check Complete ==="
Evidenz: Administrative workflows aus replit.md:81-91
2. Bulk-Icon-Operations¶
# scripts/bulk-admin.py
import json
import os
import shutil
from pathlib import Path
class IconAdmin:
def __init__(self):
self.icons_dir = Path('static/icons')
self.metadata_file = Path('icons.json')
def validate_consistency(self):
"""Check consistency between files and metadata"""
with open(self.metadata_file) as f:
categories = json.load(f)
categorized = set()
for cat_icons in categories.values():
categorized.update(cat_icons)
actual = set(f.name for f in self.icons_dir.glob('*.svg'))
return {
'uncategorized': actual - categorized,
'missing': categorized - actual,
'total_files': len(actual),
'total_categorized': len(categorized)
}
def move_icons_to_category(self, icon_files, target_category):
"""Move multiple icons to a new category"""
with open(self.metadata_file, 'r') as f:
categories = json.load(f)
# Remove from old categories
for category in categories.values():
for icon_file in icon_files:
if icon_file in category:
category.remove(icon_file)
# Add to new category
if target_category not in categories:
categories[target_category] = []
categories[target_category].extend(icon_files)
# Save updated metadata
with open(self.metadata_file, 'w') as f:
json.dump(categories, f, indent=2)
def remove_icons(self, icon_files):
"""Remove icons from both filesystem and metadata"""
# Remove files
for icon_file in icon_files:
icon_path = self.icons_dir / icon_file
if icon_path.exists():
icon_path.unlink()
# Remove from metadata
with open(self.metadata_file, 'r') as f:
categories = json.load(f)
for category in categories.values():
for icon_file in icon_files:
if icon_file in category:
category.remove(icon_file)
with open(self.metadata_file, 'w') as f:
json.dump(categories, f, indent=2)
# Usage
admin = IconAdmin()
consistency = admin.validate_consistency()
print(f"Consistency Report: {consistency}")
3. Automated Icon-Updates¶
#!/bin/bash
# scripts/update-fontawesome.sh
echo "Updating FontAwesome dependencies..."
# Update Node.js dependencies
npm update @fortawesome/fontawesome-svg-core
npm update @fortawesome/free-solid-svg-icons
# Backup current icons
backup_dir="backup-$(date +%Y%m%d-%H%M%S)"
mkdir "$backup_dir"
cp -r static/icons "$backup_dir/"
cp icons.json "$backup_dir/"
# Extract new icons
node extract-icons.js
# Validate new extraction
new_count=$(ls static/icons/*.svg | wc -l)
old_count=$(ls "$backup_dir/icons"/*.svg | wc -l)
echo "Icon count: $old_count → $new_count"
if [ "$new_count" -lt "$old_count" ]; then
echo "⚠️ Icon count decreased, manual review recommended"
fi
# Run health check
./scripts/admin-health-check.sh
echo "Update complete. Backup available in $backup_dir"
Admin API-Erweiterungen¶
1. System-Status API¶
# Geplant: Admin-spezifische Endpunkte
@app.route('/api/admin/status')
def admin_status():
"""System status for administrators"""
icons, categories = get_icon_list()
# File system stats
icons_dir = Path('static/icons')
total_size = sum(f.stat().st_size for f in icons_dir.glob('*.svg'))
# Git information (if available)
try:
import subprocess
last_commit = subprocess.check_output(
['git', 'log', '-1', '--format=%h %s'],
universal_newlines=True
).strip()
except:
last_commit = "Unknown"
return jsonify({
'system': {
'total_icons': len(icons),
'total_categories': len(categories),
'total_size_bytes': total_size,
'last_commit': last_commit,
'timestamp': time.time()
},
'health': {
'icons_directory': icons_dir.exists(),
'metadata_file': Path('icons.json').exists(),
'consistency': validate_consistency()
}
})
@app.route('/api/admin/categories', methods=['POST'])
def update_categories():
"""Update category metadata"""
new_categories = request.json
# Validate category structure
if not isinstance(new_categories, dict):
return jsonify({'error': 'Invalid category format'}), 400
# Backup current metadata
backup_metadata()
# Save new categories
with open('icons.json', 'w') as f:
json.dump(new_categories, f, indent=2)
return jsonify({'success': True, 'categories': len(new_categories)})
2. Batch-Upload API¶
@app.route('/api/admin/upload', methods=['POST'])
def upload_icons():
"""Upload new SVG icons"""
if 'icons' not in request.files:
return jsonify({'error': 'No icons provided'}), 400
uploaded_files = request.files.getlist('icons')
category = request.form.get('category', 'Uncategorized')
results = []
for file in uploaded_files:
if file.filename.endswith('.svg'):
# Validate SVG content
if validate_svg(file):
# Save file
file.save(f'static/icons/{file.filename}')
# Update metadata
add_to_category(file.filename, category)
results.append({'filename': file.filename, 'status': 'success'})
else:
results.append({'filename': file.filename, 'status': 'invalid_svg'})
else:
results.append({'filename': file.filename, 'status': 'not_svg'})
return jsonify({'results': results})
Security für Admin-Interface¶
1. Authentifizierung¶
# Geplant: Basic Authentication für Admin-Bereiche
from functools import wraps
from flask import request, Response
def check_auth(username, password):
"""Check if username/password combination is valid"""
# In production: use proper password hashing
return username == 'admin' and password == os.environ.get('ADMIN_PASSWORD', 'changeme')
def authenticate():
"""Send 401 response that enables basic auth"""
return Response(
'Authentication required', 401,
{'WWW-Authenticate': 'Basic realm="Admin Area"'}
)
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
# Protect admin routes
@app.route('/admin')
@requires_auth
def admin_dashboard():
return render_template('admin/dashboard.html')
2. CSRF-Protection¶
# Geplant: CSRF-Token für Admin-Formulare
import secrets
@app.before_request
def csrf_protection():
if request.method == "POST" and request.endpoint and 'admin' in request.endpoint:
token = request.form.get('csrf_token')
if not token or token != session.get('csrf_token'):
abort(403)
@app.route('/admin')
def admin_dashboard():
session['csrf_token'] = secrets.token_hex(16)
return render_template('admin/dashboard.html')
Deployment-Überlegungen¶
1. Admin-Interface aktivieren¶
# Admin-Mode über Environment Variable
ADMIN_ENABLED = os.environ.get('ADMIN_ENABLED', 'false').lower() == 'true'
if ADMIN_ENABLED:
# Register admin blueprints
from admin import admin_bp
app.register_blueprint(admin_bp, url_prefix='/admin')
2. Production-Sicherheit¶
# Environment-Variablen für Production
export ADMIN_ENABLED=true
export ADMIN_PASSWORD=secure_random_password
export FLASK_ENV=production
export SECRET_KEY=your_secret_key
Roadmap¶
Phase 1: Grundlegende Admin-UI (geplant)¶
- [ ] Admin-Dashboard mit System-Status
- [ ] Kategorie-Management Interface
- [ ] Basic Authentication
Phase 2: Erweiterte Features (future)¶
- [ ] Icon-Upload über Web-Interface
- [ ] Bulk-Operations UI
- [ ] Git-Integration für Changes
Phase 3: Enterprise Features (future)¶
- [ ] User-Management
- [ ] Audit-Logs
- [ ] Advanced Analytics
Evidenz: Development roadmap aus replit.md:91
Unknown (not found): Vollständiges Admin-Interface UI. Next step: Implementierung basierend auf Admin-Workflows aus Administrator-Handbuch
Related: - Administrator-Handbuch für Workflow-Details - Backend-Übersicht für API-Erweiterungen - Operations-Runbook für Production-Setup