Unnötige Reddis und Rabbit MQ entfernt

Dieser Commit ist enthalten in:
2025-06-21 18:34:48 +02:00
Ursprung e6799c698e
Commit 1e6012a1e6
11 geänderte Dateien mit 186 neuen und 88 gelöschten Zeilen

Datei anzeigen

@@ -0,0 +1,72 @@
-- Add constraint to ensure licenses always inherit is_fake from their customer
-- This migration adds a trigger to automatically sync is_fake status
-- Function to sync is_fake status
CREATE OR REPLACE FUNCTION sync_license_fake_status()
RETURNS TRIGGER AS $$
BEGIN
-- When inserting or updating a license, get is_fake from customer
IF TG_OP = 'INSERT' OR (TG_OP = 'UPDATE' AND NEW.customer_id != OLD.customer_id) THEN
SELECT is_fake INTO NEW.is_fake
FROM customers
WHERE id = NEW.customer_id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger for licenses table
DROP TRIGGER IF EXISTS sync_license_fake_before_insert_update ON licenses;
CREATE TRIGGER sync_license_fake_before_insert_update
BEFORE INSERT OR UPDATE ON licenses
FOR EACH ROW
EXECUTE FUNCTION sync_license_fake_status();
-- Function to update licenses when customer is_fake changes
CREATE OR REPLACE FUNCTION sync_customer_fake_to_licenses()
RETURNS TRIGGER AS $$
BEGIN
-- When customer is_fake changes, update all their licenses
IF TG_OP = 'UPDATE' AND NEW.is_fake != OLD.is_fake THEN
UPDATE licenses
SET is_fake = NEW.is_fake
WHERE customer_id = NEW.id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger for customers table
DROP TRIGGER IF EXISTS sync_customer_fake_after_update ON customers;
CREATE TRIGGER sync_customer_fake_after_update
AFTER UPDATE ON customers
FOR EACH ROW
EXECUTE FUNCTION sync_customer_fake_to_licenses();
-- Verify current data is consistent (should return 0)
DO $$
DECLARE
mismatch_count INTEGER;
BEGIN
SELECT COUNT(*) INTO mismatch_count
FROM licenses l
JOIN customers c ON l.customer_id = c.id
WHERE l.is_fake != c.is_fake;
IF mismatch_count > 0 THEN
RAISE NOTICE 'Found % mismatches. Fixing...', mismatch_count;
-- Fix any existing mismatches
UPDATE licenses l
SET is_fake = c.is_fake
FROM customers c
WHERE l.customer_id = c.id
AND l.is_fake != c.is_fake;
RAISE NOTICE 'Fixed all mismatches.';
ELSE
RAISE NOTICE 'No mismatches found. Data is consistent.';
END IF;
END $$;

Datei anzeigen

@@ -37,7 +37,8 @@ def api_customers():
for customer in paginated_customers:
results.append({
'id': customer['id'],
'text': f"{customer['name']} ({customer['email'] or 'keine E-Mail'})"
'text': f"{customer['name']} ({customer['email'] or 'keine E-Mail'})",
'is_fake': customer.get('is_fake', False) # Include the is_fake field
})
return jsonify({
@@ -913,7 +914,7 @@ def global_search():
# Suche in Kunden
cur.execute("""
SELECT id, name, email
SELECT id, name, email, is_fake
FROM customers
WHERE name ILIKE %s OR email ILIKE %s
LIMIT 10
@@ -923,7 +924,8 @@ def global_search():
results['customers'].append({
'id': row[0],
'name': row[1],
'email': row[2]
'email': row[2],
'is_fake': row[3]
})
# Suche in Ressourcen

Datei anzeigen

@@ -42,20 +42,21 @@ def batch_create():
valid_from = request.form['valid_from']
valid_until = request.form['valid_until']
device_limit = int(request.form['device_limit'])
is_fake = 'is_fake' in request.form
# Validierung
if count < 1 or count > 100:
flash('Anzahl muss zwischen 1 und 100 liegen!', 'error')
return redirect(url_for('batch.batch_create'))
# Hole Kundendaten
cur.execute("SELECT name, email FROM customers WHERE id = %s", (customer_id,))
# Hole Kundendaten inkl. is_fake Status
cur.execute("SELECT name, email, is_fake FROM customers WHERE id = %s", (customer_id,))
customer = cur.fetchone()
if not customer:
flash('Kunde nicht gefunden!', 'error')
return redirect(url_for('batch.batch_create'))
# Lizenz erbt immer den is_fake Status vom Kunden
is_fake = customer[2]
created_licenses = []
# Erstelle Lizenzen
@@ -315,21 +316,27 @@ def batch_import():
if not customer:
# Erstelle neuen Kunden
name = row.get('customer_name', email.split('@')[0])
# Neue Kunden werden immer als Fake erstellt in der Testphase
# TODO: Nach Testphase muss hier die Business-Logik angepasst werden
is_fake = True
cur.execute("""
INSERT INTO customers (name, email, created_at)
VALUES (%s, %s, %s)
INSERT INTO customers (name, email, is_fake, created_at)
VALUES (%s, %s, %s, %s)
RETURNING id
""", (name, email, datetime.now()))
""", (name, email, is_fake, datetime.now()))
customer_id = cur.fetchone()[0]
customer_name = name
else:
customer_id = customer[0]
customer_name = customer[1]
# Hole is_fake Status vom existierenden Kunden
cur.execute("SELECT is_fake FROM customers WHERE id = %s", (customer_id,))
is_fake = cur.fetchone()[0]
# Generiere Lizenzschlüssel
license_key = row.get('license_key', generate_license_key())
# Erstelle Lizenz
# Erstelle Lizenz - is_fake wird vom Kunden geerbt
cur.execute("""
INSERT INTO licenses (
license_key, customer_id,
@@ -340,7 +347,7 @@ def batch_import():
""", (
license_key, customer_id,
row['license_type'], row['valid_from'], row['valid_until'],
int(row['device_limit']), row.get('is_fake', False),
int(row['device_limit']), is_fake,
datetime.now()
))

Datei anzeigen

@@ -415,7 +415,8 @@ def api_customer_licenses(customer_id):
'customer': {
'id': customer['id'],
'name': customer['name'],
'email': customer['email']
'email': customer['email'],
'is_fake': customer.get('is_fake', False) # Include the is_fake field
},
'licenses': licenses
})

Datei anzeigen

@@ -117,14 +117,13 @@ def edit_license(license_id):
'valid_from': request.form['valid_from'],
'valid_until': request.form['valid_until'],
'is_active': 'is_active' in request.form,
'is_fake': 'is_fake' in request.form,
'device_limit': int(request.form.get('device_limit', 3))
}
cur.execute("""
UPDATE licenses
SET license_key = %s, license_type = %s, valid_from = %s,
valid_until = %s, is_active = %s, is_fake = %s, device_limit = %s
valid_until = %s, is_active = %s, device_limit = %s
WHERE id = %s
""", (
new_values['license_key'],
@@ -132,7 +131,6 @@ def edit_license(license_id):
new_values['valid_from'],
new_values['valid_until'],
new_values['is_active'],
new_values['is_fake'],
new_values['device_limit'],
license_id
))
@@ -147,7 +145,6 @@ def edit_license(license_id):
'valid_from': str(current_license.get('valid_from', '')),
'valid_until': str(current_license.get('valid_until', '')),
'is_active': current_license.get('is_active'),
'is_fake': current_license.get('is_fake'),
'device_limit': current_license.get('device_limit', 3)
},
new_values=new_values)
@@ -286,7 +283,7 @@ def create_license():
license_key = request.form["license_key"].upper() # Immer Großbuchstaben
license_type = request.form["license_type"]
valid_from = request.form["valid_from"]
is_fake = request.form.get("is_fake") == "on" # Checkbox value
# is_fake wird später vom Kunden geerbt
# Berechne valid_until basierend auf Laufzeit
duration = int(request.form.get("duration", 1))
@@ -338,7 +335,9 @@ def create_license():
flash(f'E-Mail bereits vergeben für Kunde: {existing[1]}', 'error')
return redirect(url_for('licenses.create_license'))
# Kunde einfügen (erbt Test-Status von Lizenz)
# Neuer Kunde wird immer als Fake erstellt, da wir in der Testphase sind
# TODO: Nach Testphase muss hier die Business-Logik angepasst werden
is_fake = True
cur.execute("""
INSERT INTO customers (name, email, is_fake, created_at)
VALUES (%s, %s, %s, NOW())
@@ -359,9 +358,8 @@ def create_license():
return redirect(url_for('licenses.create_license'))
customer_info = {'name': customer_data[0], 'email': customer_data[1]}
# Wenn Kunde Test-Kunde ist, Lizenz auch als Test markieren
if customer_data[2]: # is_fake des Kunden
is_fake = True
# Lizenz erbt immer den is_fake Status vom Kunden
is_fake = customer_data[2]
# Lizenz hinzufügen
cur.execute("""

Datei anzeigen

@@ -191,11 +191,7 @@ def system_status():
# Check each service
service_checks = [
{'name': 'License Server', 'url': 'http://license-server:8443/health', 'port': 8443},
{'name': 'Auth Service', 'url': 'http://auth-service:5001/health', 'port': 5001},
{'name': 'Analytics Service', 'url': 'http://analytics-service:5003/health', 'port': 5003},
{'name': 'Admin API Service', 'url': 'http://admin-api-service:5004/health', 'port': 5004},
{'name': 'PostgreSQL', 'check': 'database'},
{'name': 'Redis', 'url': 'http://redis:6379', 'check': 'redis'},
]
for service in service_checks:

Datei anzeigen

@@ -26,6 +26,11 @@
{% endif %}
{% endwith %}
<!-- Customer Type Indicator -->
<div id="customerTypeIndicator" class="alert d-none mb-3" role="alert">
<i class="fas fa-info-circle"></i> <span id="customerTypeMessage"></span>
</div>
<form method="post" action="{{ url_for('batch.batch_create') }}" accept-charset="UTF-8">
<div class="row g-3">
<div class="col-md-12">
@@ -173,14 +178,6 @@
</div>
</div>
<!-- Test Data Checkbox -->
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="isFake" name="is_fake">
<label class="form-check-label" for="isFake">
<i class="fas fa-flask"></i> Als Fake-Daten markieren
<small class="text-muted">(wird von der Software ignoriert)</small>
</label>
</div>
<div class="mt-4 d-flex gap-2">
<button type="submit" class="btn btn-primary btn-lg">
@@ -316,6 +313,9 @@ document.addEventListener('DOMContentLoaded', function() {
emailDiv.style.display = 'block';
nameInput.required = true;
emailInput.required = true;
// Zeige Indikator für neuen Kunden
showCustomerTypeIndicator('new');
} else {
// Verstecke Eingabefelder bei bestehendem Kunden
nameDiv.style.display = 'none';
@@ -324,6 +324,11 @@ document.addEventListener('DOMContentLoaded', function() {
emailInput.required = false;
nameInput.value = '';
emailInput.value = '';
// Zeige Indikator basierend auf Kundendaten
if (e.params.data.is_fake !== undefined) {
showCustomerTypeIndicator(e.params.data.is_fake ? 'fake' : 'real');
}
}
});
@@ -333,6 +338,7 @@ document.addEventListener('DOMContentLoaded', function() {
document.getElementById('emailDiv').style.display = 'none';
document.getElementById('customerName').required = false;
document.getElementById('email').required = false;
hideCustomerTypeIndicator();
});
// Resource Availability Check
@@ -460,5 +466,28 @@ function updateBatchResourceStatus(data, totalDomains, totalIpv4, totalPhones, q
submitButton.classList.remove('btn-secondary');
}
}
// Funktion zur Anzeige des Kundentyp-Indikators
function showCustomerTypeIndicator(type) {
const indicator = document.getElementById('customerTypeIndicator');
const message = document.getElementById('customerTypeMessage');
indicator.classList.remove('d-none', 'alert-info', 'alert-warning', 'alert-success');
if (type === 'new') {
indicator.classList.add('alert-info');
message.textContent = 'Neue Kunden werden in der Testphase als TEST-Kunden erstellt. Alle Batch-Lizenzen werden automatisch als TEST-Lizenzen markiert.';
} else if (type === 'fake') {
indicator.classList.add('alert-warning');
message.textContent = 'Dies ist ein TEST-Kunde. Alle Batch-Lizenzen werden automatisch als TEST-Lizenzen markiert und von der Software ignoriert.';
} else if (type === 'real') {
indicator.classList.add('alert-success');
message.textContent = 'Dies ist ein PRODUKTIV-Kunde. Alle Batch-Lizenzen werden als produktive Lizenzen erstellt.';
}
}
function hideCustomerTypeIndicator() {
document.getElementById('customerTypeIndicator').classList.add('d-none');
}
</script>
{% endblock %}

Datei anzeigen

@@ -65,12 +65,16 @@
</div>
</div>
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="isTest" name="is_fake" {% if license.is_fake %}checked{% endif %}>
<label class="form-check-label" for="isTest">
<i class="fas fa-flask"></i> Als Fake-Daten markieren
<small class="text-muted">(wird von der Software ignoriert)</small>
</label>
<div class="alert {% if license.is_fake %}alert-warning{% else %}alert-success{% endif %} mt-3" role="alert">
<i class="fas fa-info-circle"></i>
<strong>Status:</strong>
{% if license.is_fake %}
TEST-Lizenz (wird von der Software ignoriert)
{% else %}
PRODUKTIV-Lizenz
{% endif %}
<br>
<small class="text-muted">Der Status wird vom Kunden geerbt und kann nicht direkt geändert werden.</small>
</div>
<div class="mt-4">

Datei anzeigen

@@ -9,6 +9,11 @@
<a href="{{ url_for('customers.customers_licenses') }}" class="btn btn-secondary">← Zurück zur Übersicht</a>
</div>
<!-- Customer Type Indicator -->
<div id="customerTypeIndicator" class="alert d-none mb-3" role="alert">
<i class="fas fa-info-circle"></i> <span id="customerTypeMessage"></span>
</div>
<form method="post" action="{{ url_for('licenses.create_license') }}" accept-charset="UTF-8">
<div class="row g-3">
<div class="col-md-12">
@@ -152,14 +157,6 @@
</div>
</div>
<!-- Test Data Checkbox -->
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="isTest" name="is_fake">
<label class="form-check-label" for="isTest">
<i class="fas fa-flask"></i> Als Fake-Daten markieren
<small class="text-muted">(wird von der Software ignoriert)</small>
</label>
</div>
<div class="mt-4">
<button type="submit" class="btn btn-primary"> Lizenz erstellen</button>
@@ -368,6 +365,9 @@ document.addEventListener('DOMContentLoaded', function() {
emailDiv.style.display = 'block';
nameInput.required = true;
emailInput.required = true;
// Zeige Indikator für neuen Kunden
showCustomerTypeIndicator('new');
} else {
// Verstecke Eingabefelder bei bestehendem Kunden
nameDiv.style.display = 'none';
@@ -376,6 +376,11 @@ document.addEventListener('DOMContentLoaded', function() {
emailInput.required = false;
nameInput.value = '';
emailInput.value = '';
// Zeige Indikator basierend auf Kundendaten
if (e.params.data.is_fake !== undefined) {
showCustomerTypeIndicator(e.params.data.is_fake ? 'fake' : 'real');
}
}
});
@@ -385,6 +390,7 @@ document.addEventListener('DOMContentLoaded', function() {
document.getElementById('emailDiv').style.display = 'none';
document.getElementById('customerName').required = false;
document.getElementById('email').required = false;
hideCustomerTypeIndicator();
});
// Resource Availability Check
@@ -529,5 +535,28 @@ function updateResourceStatus(data, domainCount, ipv4Count, phoneCount) {
statusElement.textContent = message;
statusElement.className = hasIssue ? 'text-danger' : 'text-success';
}
// Funktion zur Anzeige des Kundentyp-Indikators
function showCustomerTypeIndicator(type) {
const indicator = document.getElementById('customerTypeIndicator');
const message = document.getElementById('customerTypeMessage');
indicator.classList.remove('d-none', 'alert-info', 'alert-warning', 'alert-success');
if (type === 'new') {
indicator.classList.add('alert-info');
message.textContent = 'Neue Kunden werden in der Testphase als TEST-Kunden erstellt. Die Lizenz wird automatisch als TEST-Lizenz markiert.';
} else if (type === 'fake') {
indicator.classList.add('alert-warning');
message.textContent = 'Dies ist ein TEST-Kunde. Die Lizenz wird automatisch als TEST-Lizenz markiert und von der Software ignoriert.';
} else if (type === 'real') {
indicator.classList.add('alert-success');
message.textContent = 'Dies ist ein PRODUKTIV-Kunde. Die Lizenz wird als produktive Lizenz erstellt.';
}
}
function hideCustomerTypeIndicator() {
document.getElementById('customerTypeIndicator').classList.add('d-none');
}
</script>
{% endblock %}