diff --git a/.claude/settings.local.json b/.claude/settings.local.json index d7fd6ba..7d7237e 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -73,7 +73,8 @@ "Bash(docker compose:*)", "Bash(true)", "Bash(git checkout:*)", - "Bash(touch:*)" + "Bash(touch:*)", + "Bash(wget:*)" ], "deny": [] } diff --git a/v2_adminpanel/init.sql b/v2_adminpanel/init.sql index fd69d0e..d9e6087 100644 --- a/v2_adminpanel/init.sql +++ b/v2_adminpanel/init.sql @@ -8,7 +8,7 @@ CREATE TABLE IF NOT EXISTS customers ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT, - is_test BOOLEAN DEFAULT FALSE, + is_fake BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, CONSTRAINT unique_email UNIQUE (email) ); @@ -21,7 +21,7 @@ CREATE TABLE IF NOT EXISTS licenses ( valid_from DATE NOT NULL, valid_until DATE NOT NULL, is_active BOOLEAN DEFAULT TRUE, - is_test BOOLEAN DEFAULT FALSE, + is_fake BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); @@ -129,7 +129,7 @@ CREATE TABLE IF NOT EXISTS resource_pools ( quarantine_until TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, notes TEXT, - is_test BOOLEAN DEFAULT FALSE, + is_fake BOOLEAN DEFAULT FALSE, UNIQUE(resource_type, resource_value) ); @@ -245,48 +245,48 @@ CREATE TABLE IF NOT EXISTS users ( CREATE INDEX IF NOT EXISTS idx_users_username ON users(username); CREATE INDEX IF NOT EXISTS idx_users_reset_token ON users(password_reset_token) WHERE password_reset_token IS NOT NULL; --- Migration: Add is_test column to licenses if it doesn't exist +-- Migration: Add is_fake column to licenses if it doesn't exist DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'licenses' AND column_name = 'is_test') THEN - ALTER TABLE licenses ADD COLUMN is_test BOOLEAN DEFAULT FALSE; + WHERE table_name = 'licenses' AND column_name = 'is_fake') THEN + ALTER TABLE licenses ADD COLUMN is_fake BOOLEAN DEFAULT FALSE; - -- Mark all existing licenses as test data - UPDATE licenses SET is_test = TRUE; + -- Mark all existing licenses as fake data + UPDATE licenses SET is_fake = TRUE; - -- Add index for better performance when filtering test data - CREATE INDEX idx_licenses_is_test ON licenses(is_test); + -- Add index for better performance when filtering fake data + CREATE INDEX idx_licenses_is_fake ON licenses(is_fake); END IF; END $$; --- Migration: Add is_test column to customers if it doesn't exist +-- Migration: Add is_fake column to customers if it doesn't exist DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'customers' AND column_name = 'is_test') THEN - ALTER TABLE customers ADD COLUMN is_test BOOLEAN DEFAULT FALSE; + WHERE table_name = 'customers' AND column_name = 'is_fake') THEN + ALTER TABLE customers ADD COLUMN is_fake BOOLEAN DEFAULT FALSE; - -- Mark all existing customers as test data - UPDATE customers SET is_test = TRUE; + -- Mark all existing customers as fake data + UPDATE customers SET is_fake = TRUE; -- Add index for better performance - CREATE INDEX idx_customers_is_test ON customers(is_test); + CREATE INDEX idx_customers_is_fake ON customers(is_fake); END IF; END $$; --- Migration: Add is_test column to resource_pools if it doesn't exist +-- Migration: Add is_fake column to resource_pools if it doesn't exist DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'resource_pools' AND column_name = 'is_test') THEN - ALTER TABLE resource_pools ADD COLUMN is_test BOOLEAN DEFAULT FALSE; + WHERE table_name = 'resource_pools' AND column_name = 'is_fake') THEN + ALTER TABLE resource_pools ADD COLUMN is_fake BOOLEAN DEFAULT FALSE; - -- Mark all existing resources as test data - UPDATE resource_pools SET is_test = TRUE; + -- Mark all existing resources as fake data + UPDATE resource_pools SET is_fake = TRUE; -- Add index for better performance - CREATE INDEX idx_resource_pools_is_test ON resource_pools(is_test); + CREATE INDEX idx_resource_pools_is_fake ON resource_pools(is_fake); END IF; END $$; diff --git a/v2_adminpanel/migrations/rename_test_to_fake.sql b/v2_adminpanel/migrations/rename_test_to_fake.sql new file mode 100644 index 0000000..f813a0d --- /dev/null +++ b/v2_adminpanel/migrations/rename_test_to_fake.sql @@ -0,0 +1,48 @@ +-- Migration script to rename is_test columns to is_fake +-- This separates fake/demo data from test licenses + +-- 1. Rename columns in all tables +DO $$ +BEGIN + -- Rename is_test to is_fake in customers table + IF EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name = 'customers' AND column_name = 'is_test') THEN + ALTER TABLE customers RENAME COLUMN is_test TO is_fake; + END IF; + + -- Rename is_test to is_fake in licenses table + IF EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name = 'licenses' AND column_name = 'is_test') THEN + ALTER TABLE licenses RENAME COLUMN is_test TO is_fake; + END IF; + + -- Rename is_test to is_fake in resource_pools table + IF EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name = 'resource_pools' AND column_name = 'is_test') THEN + ALTER TABLE resource_pools RENAME COLUMN is_test TO is_fake; + END IF; +END $$; + +-- 2. Rename indexes +DO $$ +BEGIN + -- Rename index for customers + IF EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'idx_customers_is_test') THEN + ALTER INDEX idx_customers_is_test RENAME TO idx_customers_is_fake; + END IF; + + -- Rename index for licenses + IF EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'idx_licenses_is_test') THEN + ALTER INDEX idx_licenses_is_test RENAME TO idx_licenses_is_fake; + END IF; + + -- Rename index for resource_pools + IF EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'idx_resource_pools_is_test') THEN + ALTER INDEX idx_resource_pools_is_test RENAME TO idx_resource_pools_is_fake; + END IF; +END $$; + +-- 3. Add comments to clarify the purpose +COMMENT ON COLUMN customers.is_fake IS 'Marks fake/demo data, not to be confused with test licenses'; +COMMENT ON COLUMN licenses.is_fake IS 'Marks fake/demo data, not to be confused with test license type'; +COMMENT ON COLUMN resource_pools.is_fake IS 'Marks fake/demo resources'; \ No newline at end of file diff --git a/v2_adminpanel/models.py b/v2_adminpanel/models.py index 2448bc0..264fbc5 100644 --- a/v2_adminpanel/models.py +++ b/v2_adminpanel/models.py @@ -32,12 +32,12 @@ def get_user_by_username(username): return None -def get_licenses(show_test=False): +def get_licenses(show_fake=False): """Get all licenses from database""" try: with get_db_connection() as conn: with get_db_cursor(conn) as cur: - if show_test: + if show_fake: cur.execute(""" SELECT l.*, c.name as customer_name FROM licenses l @@ -49,7 +49,7 @@ def get_licenses(show_test=False): SELECT l.*, c.name as customer_name FROM licenses l LEFT JOIN customers c ON l.customer_id = c.id - WHERE l.is_test = false + WHERE l.is_fake = false ORDER BY l.created_at DESC """) @@ -86,7 +86,7 @@ def get_license_by_id(license_id): return None -def get_customers(show_test=False, search=None): +def get_customers(show_fake=False, search=None): """Get all customers from database""" try: with get_db_connection() as conn: @@ -102,8 +102,8 @@ def get_customers(show_test=False, search=None): where_clauses = [] params = [] - if not show_test: - where_clauses.append("c.is_test = false") + if not show_fake: + where_clauses.append("c.is_fake = false") if search: where_clauses.append("(LOWER(c.name) LIKE LOWER(%s) OR LOWER(c.email) LIKE LOWER(%s))") diff --git a/v2_adminpanel/routes/admin_routes.py b/v2_adminpanel/routes/admin_routes.py index 39b204a..775d277 100644 --- a/v2_adminpanel/routes/admin_routes.py +++ b/v2_adminpanel/routes/admin_routes.py @@ -25,18 +25,18 @@ def dashboard(): try: # Hole Statistiken mit sicheren Defaults # Anzahl aktiver Lizenzen (nur echte Daten, keine Testdaten) - cur.execute("SELECT COUNT(*) FROM licenses WHERE is_active = true AND is_test = false") + cur.execute("SELECT COUNT(*) FROM licenses WHERE is_active = true AND is_fake = false") active_licenses = cur.fetchone()[0] if cur.rowcount > 0 else 0 - # Anzahl Kunden (nur echte Kunden, keine Testkunden) - cur.execute("SELECT COUNT(*) FROM customers WHERE is_test = false") + # Anzahl Kunden (nur echte Kunden, keine Fake-Kunden) + cur.execute("SELECT COUNT(*) FROM customers WHERE is_fake = false") total_customers = cur.fetchone()[0] if cur.rowcount > 0 else 0 # Testdaten separat zählen für optionale Anzeige - cur.execute("SELECT COUNT(*) FROM customers WHERE is_test = true") - test_customers_count = cur.fetchone()[0] if cur.rowcount > 0 else 0 + cur.execute("SELECT COUNT(*) FROM customers WHERE is_fake = true") + fake_customers_count = cur.fetchone()[0] if cur.rowcount > 0 else 0 - cur.execute("SELECT COUNT(*) FROM licenses WHERE is_test = true") + cur.execute("SELECT COUNT(*) FROM licenses WHERE is_fake = true") test_licenses_count = cur.fetchone()[0] if cur.rowcount > 0 else 0 # Anzahl aktiver Sessions (Admin-Panel) @@ -61,7 +61,7 @@ def dashboard(): FROM license_heartbeats lh JOIN licenses l ON l.id = lh.license_id WHERE lh.timestamp > NOW() - INTERVAL '15 minutes' - AND l.is_test = false + AND l.is_fake = false """) active_usage = cur.fetchone()[0] if cur.rowcount > 0 else 0 except Exception as e: @@ -82,7 +82,7 @@ def dashboard(): FROM licenses l LEFT JOIN customers c ON l.customer_id = c.id LEFT JOIN sessions s ON l.id = s.license_id - WHERE l.is_test = false AND c.is_test = false + WHERE l.is_fake = false AND c.is_fake = false GROUP BY l.license_key, c.name ORDER BY session_count DESC LIMIT 10 @@ -109,7 +109,7 @@ def dashboard(): cur.execute(""" SELECT COUNT(*) as full_licenses FROM licenses - WHERE is_test = false + WHERE is_fake = false """) license_count = cur.fetchone() full_licenses = license_count[0] if license_count and license_count[0] else 0 @@ -123,7 +123,7 @@ def dashboard(): COUNT(CASE WHEN valid_until < NOW() THEN 1 END) as expired, COUNT(CASE WHEN is_active = false THEN 1 END) as inactive FROM licenses - WHERE is_test = false + WHERE is_fake = false """) license_status = cur.fetchone() active_licenses_count = license_status[0] if license_status and license_status[0] else 0 @@ -140,8 +140,8 @@ def dashboard(): EXTRACT(DAY FROM (l.valid_until - NOW())) as days_remaining FROM licenses l JOIN customers c ON l.customer_id = c.id - WHERE l.is_test = false - AND c.is_test = false + WHERE l.is_fake = false + AND c.is_fake = false AND l.is_active = true AND l.valid_until IS NOT NULL AND l.valid_until > NOW() @@ -166,8 +166,8 @@ def dashboard(): END as status FROM licenses l JOIN customers c ON l.customer_id = c.id - WHERE l.is_test = false - AND c.is_test = false + WHERE l.is_fake = false + AND c.is_fake = false ORDER BY l.created_at DESC LIMIT 5 """) @@ -176,15 +176,15 @@ def dashboard(): # Stats Objekt für Template erstellen stats = { 'total_customers': total_customers, - 'total_licenses': active_licenses, # This was already filtered for is_test = false + 'total_licenses': active_licenses, # This was already filtered for is_fake = false 'active_sessions': active_sessions, # Admin-Panel Sessions 'active_usage': active_usage, # Aktive Kunden-Nutzung 'active_licenses': active_licenses_count, 'full_licenses': full_licenses, 'test_licenses': test_version_licenses, # Test versions, not test data - 'test_data_count': test_licenses_count, # Actual test data count - 'test_customers_count': test_customers_count, - 'test_resources_count': 0, + 'fake_data_count': test_licenses_count, # Actual test data count + 'fake_customers_count': fake_customers_count, + 'fake_resources_count': 0, 'expired_licenses': expired_licenses, 'inactive_licenses': inactive_licenses, 'last_backup': None, @@ -210,7 +210,7 @@ def dashboard(): COUNT(CASE WHEN status = 'quarantine' THEN 1 END) as quarantine, COUNT(*) as total FROM resource_pool - WHERE type = %s AND is_test = false + WHERE type = %s AND is_fake = false """, (resource_type,)) result = cur.fetchone() @@ -249,9 +249,9 @@ def dashboard(): # Count test resources separately try: - cur.execute("SELECT COUNT(*) FROM resource_pool WHERE is_test = true") - test_resources_count = cur.fetchone()[0] if cur.rowcount > 0 else 0 - stats['test_resources_count'] = test_resources_count + cur.execute("SELECT COUNT(*) FROM resource_pool WHERE is_fake = true") + fake_resources_count = cur.fetchone()[0] if cur.rowcount > 0 else 0 + stats['fake_resources_count'] = fake_resources_count except: pass diff --git a/v2_adminpanel/routes/api_routes.py b/v2_adminpanel/routes/api_routes.py index 5d8de92..3af4783 100644 --- a/v2_adminpanel/routes/api_routes.py +++ b/v2_adminpanel/routes/api_routes.py @@ -25,7 +25,7 @@ def api_customers(): try: # Get all customers (with optional search) - customers = get_customers(show_test=True, search=search) + customers = get_customers(show_fake=True, search=search) # Pagination start = (page - 1) * per_page @@ -396,7 +396,7 @@ def bulk_delete_licenses(): for license_id in license_ids: # Hole vollständige Lizenz-Info cur.execute(""" - SELECT l.id, l.license_key, l.is_active, l.is_test, + SELECT l.id, l.license_key, l.is_active, l.is_fake, c.name as customer_name FROM licenses l LEFT JOIN customers c ON l.customer_id = c.id @@ -407,7 +407,7 @@ def bulk_delete_licenses(): if not result: continue - license_id, license_key, is_active, is_test, customer_name = result + license_id, license_key, is_active, is_fake, customer_name = result # Safety check: Don't delete active licenses unless forced if is_active and not force_delete: @@ -601,7 +601,7 @@ def get_license_resources(license_id): rp.id, rp.resource_type, rp.resource_value, - rp.is_test, + rp.is_fake, rp.status_changed_at, lr.assigned_at, lr.assigned_by @@ -617,7 +617,7 @@ def get_license_resources(license_id): 'id': row[0], 'type': row[1], 'value': row[2], - 'is_test': row[3], + 'is_fake': row[3], 'status_changed_at': row[4].isoformat() if row[4] else None, 'assigned_at': row[5].isoformat() if row[5] else None, 'assigned_by': row[6] @@ -675,7 +675,7 @@ def allocate_resources(): try: # Prüfe ob Ressource verfügbar ist cur.execute(""" - SELECT resource_value, status, is_test + SELECT resource_value, status, is_fake FROM resource_pools WHERE id = %s """, (resource_id,)) @@ -690,8 +690,8 @@ def allocate_resources(): continue # Prüfe Test/Produktion Kompatibilität - if resource[2] != license_data['is_test']: - errors.append(f"Ressource {resource[0]} ist {'Test' if resource[2] else 'Produktion'}, Lizenz ist {'Test' if license_data['is_test'] else 'Produktion'}") + if resource[2] != license_data['is_fake']: + errors.append(f"Ressource {resource[0]} ist {'Test' if resource[2] else 'Produktion'}, Lizenz ist {'Test' if license_data['is_fake'] else 'Produktion'}") continue # Weise Ressource zu @@ -751,32 +751,32 @@ def check_resource_availability(): resource_type = request.args.get('type') if resource_type: count = int(request.args.get('count', 1)) - is_test = request.args.get('is_test', 'false') == 'true' - show_test = request.args.get('show_test', 'false') == 'true' + is_fake = request.args.get('is_fake', 'false') == 'true' + show_fake = request.args.get('show_fake', 'false') == 'true' conn = get_connection() cur = conn.cursor() try: # Hole verfügbare Ressourcen mit Details - if show_test: + if show_fake: # Zeige alle verfügbaren Ressourcen (Test und Produktion) cur.execute(""" - SELECT id, resource_value, is_test + SELECT id, resource_value, is_fake FROM resource_pools WHERE resource_type = %s AND status = 'available' - ORDER BY is_test, resource_value + ORDER BY is_fake, resource_value LIMIT %s """, (resource_type, count)) else: # Zeige nur Produktions-Ressourcen cur.execute(""" - SELECT id, resource_value, is_test + SELECT id, resource_value, is_fake FROM resource_pools WHERE resource_type = %s AND status = 'available' - AND is_test = false + AND is_fake = false ORDER BY resource_value LIMIT %s """, (resource_type, count)) @@ -786,7 +786,7 @@ def check_resource_availability(): available_resources.append({ 'id': row[0], 'value': row[1], - 'is_test': row[2] + 'is_fake': row[2] }) return jsonify({ @@ -794,7 +794,7 @@ def check_resource_availability(): 'requested': count, 'available': available_resources, 'sufficient': len(available_resources) >= count, - 'show_test': show_test + 'show_fake': show_fake }) except Exception as e: @@ -808,7 +808,7 @@ def check_resource_availability(): domain_count = int(request.args.get('domain', 0)) ipv4_count = int(request.args.get('ipv4', 0)) phone_count = int(request.args.get('phone', 0)) - is_test = request.args.get('is_test', 'false') == 'true' + is_fake = request.args.get('is_fake', 'false') == 'true' conn = get_connection() cur = conn.cursor() @@ -823,8 +823,8 @@ def check_resource_availability(): FROM resource_pools WHERE resource_type = 'domain' AND status = 'available' - AND is_test = %s - """, (is_test,)) + AND is_fake = %s + """, (is_fake,)) domain_available = cur.fetchone()[0] # IPv4 @@ -833,8 +833,8 @@ def check_resource_availability(): FROM resource_pools WHERE resource_type = 'ipv4' AND status = 'available' - AND is_test = %s - """, (is_test,)) + AND is_fake = %s + """, (is_fake,)) ipv4_available = cur.fetchone()[0] # Phones @@ -843,8 +843,8 @@ def check_resource_availability(): FROM resource_pools WHERE resource_type = 'phone' AND status = 'available' - AND is_test = %s - """, (is_test,)) + AND is_fake = %s + """, (is_fake,)) phone_available = cur.fetchone()[0] return jsonify({ @@ -862,7 +862,7 @@ def check_resource_availability(): ipv4_available >= ipv4_count and phone_available >= phone_count ), - 'is_test': is_test + 'is_fake': is_fake }) except Exception as e: diff --git a/v2_adminpanel/routes/batch_routes.py b/v2_adminpanel/routes/batch_routes.py index 85d496d..18415a7 100644 --- a/v2_adminpanel/routes/batch_routes.py +++ b/v2_adminpanel/routes/batch_routes.py @@ -42,7 +42,7 @@ def batch_create(): valid_from = request.form['valid_from'] valid_until = request.form['valid_until'] device_limit = int(request.form['device_limit']) - is_test = 'is_test' in request.form + is_fake = 'is_fake' in request.form # Validierung if count < 1 or count > 100: @@ -74,13 +74,13 @@ def batch_create(): INSERT INTO licenses ( license_key, customer_id, license_type, valid_from, valid_until, device_limit, - is_test, created_at + is_fake, created_at ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) RETURNING id """, ( license_key, customer_id, license_type, valid_from, valid_until, device_limit, - is_test, datetime.now() + is_fake, datetime.now() )) license_id = cur.fetchone()[0] @@ -141,7 +141,7 @@ def batch_export(): SELECT l.license_key, c.name, c.email, l.license_type, l.valid_from, l.valid_until, - l.device_limit, l.is_test, l.created_at + l.device_limit, l.is_fake, l.created_at FROM licenses l JOIN customers c ON l.customer_id = c.id WHERE l.id = ANY(%s) @@ -158,7 +158,7 @@ def batch_export(): 'valid_from': row[4], 'valid_until': row[5], 'device_limit': row[6], - 'is_test': row[7], + 'is_fake': row[7], 'created_at': row[8] }) @@ -334,13 +334,13 @@ def batch_import(): INSERT INTO licenses ( license_key, customer_id, license_type, valid_from, valid_until, device_limit, - is_test, created_at + is_fake, created_at ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) RETURNING id """, ( license_key, customer_id, row['license_type'], row['valid_from'], row['valid_until'], - int(row['device_limit']), row.get('is_test', False), + int(row['device_limit']), row.get('is_fake', False), datetime.now() )) diff --git a/v2_adminpanel/routes/customer_routes.py b/v2_adminpanel/routes/customer_routes.py index 9cb58eb..0de180e 100644 --- a/v2_adminpanel/routes/customer_routes.py +++ b/v2_adminpanel/routes/customer_routes.py @@ -22,14 +22,14 @@ def test_customers(): @customer_bp.route("/customers") @login_required def customers(): - show_test = request.args.get('show_test', 'false').lower() == 'true' + show_fake = request.args.get('show_fake', 'false').lower() == 'true' search = request.args.get('search', '').strip() page = request.args.get('page', 1, type=int) per_page = 20 sort = request.args.get('sort', 'name') order = request.args.get('order', 'asc') - customers_list = get_customers(show_test=show_test, search=search) + customers_list = get_customers(show_fake=show_fake, search=search) # Sortierung if sort == 'name': @@ -48,7 +48,7 @@ def customers(): return render_template("customers.html", customers=paginated_customers, - show_test=show_test, + show_fake=show_fake, search=search, page=page, per_page=per_page, @@ -77,17 +77,17 @@ def edit_customer(customer_id): new_values = { 'name': request.form['name'], 'email': request.form['email'], - 'is_test': 'is_test' in request.form + 'is_fake': 'is_fake' in request.form } cur.execute(""" UPDATE customers - SET name = %s, email = %s, is_test = %s + SET name = %s, email = %s, is_fake = %s WHERE id = %s """, ( new_values['name'], new_values['email'], - new_values['is_test'], + new_values['is_fake'], customer_id )) @@ -98,16 +98,16 @@ def edit_customer(customer_id): old_values={ 'name': current_customer['name'], 'email': current_customer['email'], - 'is_test': current_customer.get('is_test', False) + 'is_fake': current_customer.get('is_fake', False) }, new_values=new_values) flash('Kunde erfolgreich aktualisiert!', 'success') - # Redirect mit show_test Parameter wenn nötig + # Redirect mit show_fake Parameter wenn nötig redirect_url = url_for('customers.customers_licenses') - if request.form.get('show_test') == 'true': - redirect_url += '?show_test=true' + if request.form.get('show_fake') == 'true': + redirect_url += '?show_fake=true' return redirect(redirect_url) finally: cur.close() @@ -137,13 +137,13 @@ def create_customer(): # Insert new customer name = request.form['name'] email = request.form['email'] - is_test = 'is_test' in request.form # Checkbox ist nur vorhanden wenn angekreuzt + is_fake = 'is_fake' in request.form # Checkbox ist nur vorhanden wenn angekreuzt cur.execute(""" - INSERT INTO customers (name, email, is_test, created_at) + INSERT INTO customers (name, email, is_fake, created_at) VALUES (%s, %s, %s, %s) RETURNING id - """, (name, email, is_test, datetime.now())) + """, (name, email, is_fake, datetime.now())) customer_id = cur.fetchone()[0] conn.commit() @@ -153,17 +153,17 @@ def create_customer(): new_values={ 'name': name, 'email': email, - 'is_test': is_test + 'is_fake': is_fake }) - if is_test: - flash(f'Testkunde {name} erfolgreich erstellt!', 'success') + if is_fake: + flash(f'Fake-Kunde {name} erfolgreich erstellt!', 'success') else: flash(f'Kunde {name} erfolgreich erstellt!', 'success') - # Redirect mit show_test=true wenn Testkunde erstellt wurde - if is_test: - return redirect(url_for('customers.customers_licenses', show_test='true')) + # Redirect mit show_fake=true wenn Fake-Kunde erstellt wurde + if is_fake: + return redirect(url_for('customers.customers_licenses', show_fake='true')) else: return redirect(url_for('customers.customers_licenses')) @@ -232,9 +232,9 @@ def customers_licenses(): import psycopg2 logging.info("=== CUSTOMERS-LICENSES ROUTE CALLED ===") - # Get show_test parameter from URL - show_test = request.args.get('show_test', 'false').lower() == 'true' - logging.info(f"show_test parameter: {show_test}") + # Get show_fake parameter from URL + show_fake = request.args.get('show_fake', 'false').lower() == 'true' + logging.info(f"show_fake parameter: {show_fake}") try: # Direkte Verbindung ohne Helper-Funktionen @@ -250,7 +250,7 @@ def customers_licenses(): try: # Hole alle Kunden mit ihren Lizenzen - # Wenn show_test=false, zeige nur Nicht-Test-Kunden + # Wenn show_fake=false, zeige nur Nicht-Test-Kunden query = """ SELECT c.id, @@ -259,17 +259,17 @@ def customers_licenses(): c.created_at, COUNT(l.id), COUNT(CASE WHEN l.is_active = true THEN 1 END), - COUNT(CASE WHEN l.is_test = true THEN 1 END), + COUNT(CASE WHEN l.is_fake = true THEN 1 END), MAX(l.created_at), - c.is_test + c.is_fake FROM customers c LEFT JOIN licenses l ON c.id = l.customer_id - WHERE (%s OR c.is_test = false) - GROUP BY c.id, c.name, c.email, c.created_at, c.is_test + WHERE (%s OR c.is_fake = false) + GROUP BY c.id, c.name, c.email, c.created_at, c.is_fake ORDER BY c.name """ - cur.execute(query, (show_test,)) + cur.execute(query, (show_fake,)) customers = [] results = cur.fetchall() @@ -286,12 +286,12 @@ def customers_licenses(): 'active_licenses': row[5], 'test_licenses': row[6], 'last_license_created': row[7], - 'is_test': row[8] + 'is_fake': row[8] }) return render_template("customers_licenses.html", customers=customers, - show_test=show_test) + show_fake=show_fake) finally: cur.close() @@ -325,7 +325,7 @@ def api_customer_licenses(customer_id): l.license_key, l.license_type, l.is_active, - l.is_test, + l.is_fake, l.valid_from, l.valid_until, l.device_limit, @@ -387,7 +387,7 @@ def api_customer_licenses(customer_id): 'license_key': row[1], 'license_type': row[2], 'is_active': row[3], - 'is_test': row[4], + 'is_fake': row[4], 'valid_from': row[5].strftime('%Y-%m-%d') if row[5] else None, 'valid_until': row[6].strftime('%Y-%m-%d') if row[6] else None, 'device_limit': row[7], @@ -442,7 +442,7 @@ def api_customer_quick_stats(customer_id): SELECT COUNT(l.id) as total_licenses, COUNT(CASE WHEN l.is_active = true THEN 1 END) as active_licenses, - COUNT(CASE WHEN l.is_test = true THEN 1 END) as test_licenses, + COUNT(CASE WHEN l.is_fake = true THEN 1 END) as test_licenses, SUM(l.device_limit) as total_device_limit FROM licenses l WHERE l.customer_id = %s diff --git a/v2_adminpanel/routes/export_routes.py b/v2_adminpanel/routes/export_routes.py index 4c1169f..70cc735 100644 --- a/v2_adminpanel/routes/export_routes.py +++ b/v2_adminpanel/routes/export_routes.py @@ -21,10 +21,10 @@ def export_licenses(): try: # Filter aus Request - show_test = request.args.get('show_test', 'false') == 'true' + show_fake = request.args.get('show_fake', 'false') == 'true' # SQL Query mit optionalem Test-Filter - if show_test: + if show_fake: query = """ SELECT l.id, @@ -37,7 +37,7 @@ def export_licenses(): l.is_active, l.device_limit, l.created_at, - l.is_test, + l.is_fake, CASE WHEN l.valid_until < CURRENT_DATE THEN 'Abgelaufen' WHEN l.is_active = false THEN 'Deaktiviert' @@ -62,7 +62,7 @@ def export_licenses(): l.is_active, l.device_limit, l.created_at, - l.is_test, + l.is_fake, CASE WHEN l.valid_until < CURRENT_DATE THEN 'Abgelaufen' WHEN l.is_active = false THEN 'Deaktiviert' @@ -72,7 +72,7 @@ def export_licenses(): (SELECT COUNT(DISTINCT hardware_id) FROM sessions s WHERE s.license_key = l.license_key) as registered_devices FROM licenses l LEFT JOIN customers c ON l.customer_id = c.id - WHERE l.is_test = false + WHERE l.is_fake = false ORDER BY l.created_at DESC """ @@ -81,7 +81,7 @@ def export_licenses(): # Daten für Export vorbereiten data = [] columns = ['ID', 'Lizenzschlüssel', 'Kunde', 'E-Mail', 'Typ', 'Gültig von', - 'Gültig bis', 'Aktiv', 'Gerätelimit', 'Erstellt am', 'Test-Lizenz', + 'Gültig bis', 'Aktiv', 'Gerätelimit', 'Erstellt am', 'Fake-Lizenz', 'Status', 'Aktive Sessions', 'Registrierte Geräte'] for row in cur.fetchall(): @@ -163,13 +163,13 @@ def export_customers(): c.phone, c.address, c.created_at, - c.is_test, + c.is_fake, COUNT(l.id) as license_count, COUNT(CASE WHEN l.is_active = true THEN 1 END) as active_licenses, COUNT(CASE WHEN l.valid_until < CURRENT_DATE THEN 1 END) as expired_licenses FROM customers c LEFT JOIN licenses l ON c.id = l.customer_id - GROUP BY c.id, c.name, c.email, c.phone, c.address, c.created_at, c.is_test + GROUP BY c.id, c.name, c.email, c.phone, c.address, c.created_at, c.is_fake ORDER BY c.name """) @@ -227,7 +227,7 @@ def export_sessions(): s.last_heartbeat, s.is_active, l.license_type, - l.is_test + l.is_fake FROM sessions s LEFT JOIN licenses l ON s.license_key = l.license_key WHERE s.is_active = true @@ -247,7 +247,7 @@ def export_sessions(): s.last_heartbeat, s.is_active, l.license_type, - l.is_test + l.is_fake FROM sessions s LEFT JOIN licenses l ON s.license_key = l.license_key WHERE s.started_at >= CURRENT_TIMESTAMP - INTERVAL '%s days' @@ -259,7 +259,7 @@ def export_sessions(): data = [] columns = ['ID', 'Lizenzschlüssel', 'Kunde', 'Benutzer', 'Geräte-ID', 'Login-Zeit', 'Logout-Zeit', 'Letzte Aktivität', 'Aktiv', - 'Lizenztyp', 'Test-Lizenz'] + 'Lizenztyp', 'Fake-Lizenz'] for row in cur.fetchall(): data.append(list(row)) @@ -295,7 +295,7 @@ def export_resources(): # Filter aus Request resource_type = request.args.get('type', 'all') status_filter = request.args.get('status', 'all') - show_test = request.args.get('show_test', 'false') == 'true' + show_fake = request.args.get('show_fake', 'false') == 'true' # SQL Query aufbauen query = """ @@ -304,7 +304,7 @@ def export_resources(): rp.resource_type, rp.resource_value, rp.status, - rp.is_test, + rp.is_fake, l.license_key, c.name as customer_name, rp.created_at, @@ -328,8 +328,8 @@ def export_resources(): query += " AND rp.status = %s" params.append(status_filter) - if not show_test: - query += " AND rp.is_test = false" + if not show_fake: + query += " AND rp.is_fake = false" query += " ORDER BY rp.resource_type, rp.resource_value" diff --git a/v2_adminpanel/routes/license_routes.py b/v2_adminpanel/routes/license_routes.py index ce7afb8..fadb42b 100644 --- a/v2_adminpanel/routes/license_routes.py +++ b/v2_adminpanel/routes/license_routes.py @@ -24,43 +24,47 @@ def licenses(): # Get filter parameters search = request.args.get('search', '').strip() - filter_type = request.args.get('type', '') - filter_status = request.args.get('status', '') + filter_types = request.args.getlist('types[]') # Multi-select for types + filter_statuses = request.args.getlist('statuses[]') # Multi-select for statuses sort = request.args.get('sort', 'created_at') order = request.args.get('order', 'desc') page = request.args.get('page', 1, type=int) per_page = 50 - # Process type filter to determine show_test - # Default: show only real data unless test_data is explicitly selected - show_test = filter_type == 'test_data' + # Get all licenses (both fake and real data) + licenses_list = get_licenses(show_fake=True) - # Get licenses based on filters - licenses_list = get_licenses(show_test=show_test) + # Type filtering with OR logic + if filter_types: + filtered_by_type = [] + for license in licenses_list: + # Check if license matches any selected type + if 'full' in filter_types and license.get('license_type') == 'full' and not license.get('is_fake'): + filtered_by_type.append(license) + elif 'test' in filter_types and license.get('license_type') == 'test' and not license.get('is_fake'): + filtered_by_type.append(license) + licenses_list = filtered_by_type + else: + # If no types selected, show only real data by default + licenses_list = [l for l in licenses_list if not l.get('is_fake')] - # Additional filtering based on type and status - if filter_type: - if filter_type == 'full': - licenses_list = [l for l in licenses_list if l.get('license_type') == 'full' and not l.get('is_test')] - elif filter_type == 'test': - licenses_list = [l for l in licenses_list if l.get('license_type') == 'test' and not l.get('is_test')] - elif filter_type == 'test_data': - licenses_list = [l for l in licenses_list if l.get('is_test')] - elif filter_type == 'live_data': - licenses_list = [l for l in licenses_list if not l.get('is_test')] - - # Status filtering - if filter_status: + # Status filtering with OR logic + if filter_statuses: now = datetime.now() - if filter_status == 'active': - licenses_list = [l for l in licenses_list if l.get('is_active') and l.get('valid_until') and l.get('valid_until') > now] - elif filter_status == 'expiring': - expiry_threshold = now + timedelta(days=30) - licenses_list = [l for l in licenses_list if l.get('valid_until') and now < l.get('valid_until') <= expiry_threshold] - elif filter_status == 'expired': - licenses_list = [l for l in licenses_list if l.get('valid_until') and l.get('valid_until') <= now] - elif filter_status == 'inactive': - licenses_list = [l for l in licenses_list if not l.get('is_active')] + filtered_by_status = [] + for license in licenses_list: + # Check if license matches any selected status + if 'active' in filter_statuses and license.get('is_active') and license.get('valid_until') and license.get('valid_until') > now: + filtered_by_status.append(license) + elif 'expiring' in filter_statuses: + expiry_threshold = now + timedelta(days=30) + if license.get('valid_until') and now < license.get('valid_until') <= expiry_threshold: + filtered_by_status.append(license) + elif 'expired' in filter_statuses and license.get('valid_until') and license.get('valid_until') <= now: + filtered_by_status.append(license) + elif 'inactive' in filter_statuses and not license.get('is_active'): + filtered_by_status.append(license) + licenses_list = filtered_by_status # Search filtering if search: @@ -79,10 +83,9 @@ def licenses(): return render_template("licenses.html", licenses=licenses_list, - show_test=show_test, search=search, - filter_type=filter_type, - filter_status=filter_status, + filter_types=filter_types, + filter_statuses=filter_statuses, sort=sort, order=order, page=page, @@ -114,14 +117,14 @@ 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_test': 'is_test' 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_test = %s, device_limit = %s + valid_until = %s, is_active = %s, is_fake = %s, device_limit = %s WHERE id = %s """, ( new_values['license_key'], @@ -129,7 +132,7 @@ def edit_license(license_id): new_values['valid_from'], new_values['valid_until'], new_values['is_active'], - new_values['is_test'], + new_values['is_fake'], new_values['device_limit'], license_id )) @@ -144,7 +147,7 @@ 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_test': current_license.get('is_test'), + 'is_fake': current_license.get('is_fake'), 'device_limit': current_license.get('device_limit', 3) }, new_values=new_values) @@ -283,7 +286,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_test = request.form.get("is_test") == "on" # Checkbox value + is_fake = request.form.get("is_fake") == "on" # Checkbox value # Berechne valid_until basierend auf Laufzeit duration = int(request.form.get("duration", 1)) @@ -337,19 +340,19 @@ def create_license(): # Kunde einfügen (erbt Test-Status von Lizenz) cur.execute(""" - INSERT INTO customers (name, email, is_test, created_at) + INSERT INTO customers (name, email, is_fake, created_at) VALUES (%s, %s, %s, NOW()) RETURNING id - """, (name, email, is_test)) + """, (name, email, is_fake)) customer_id = cur.fetchone()[0] - customer_info = {'name': name, 'email': email, 'is_test': is_test} + customer_info = {'name': name, 'email': email, 'is_fake': is_fake} # Audit-Log für neuen Kunden log_audit('CREATE', 'customer', customer_id, - new_values={'name': name, 'email': email, 'is_test': is_test}) + new_values={'name': name, 'email': email, 'is_fake': is_fake}) else: # Bestehender Kunde - hole Infos für Audit-Log - cur.execute("SELECT name, email, is_test FROM customers WHERE id = %s", (customer_id,)) + cur.execute("SELECT name, email, is_fake FROM customers WHERE id = %s", (customer_id,)) customer_data = cur.fetchone() if not customer_data: flash('Kunde nicht gefunden!', 'error') @@ -357,17 +360,17 @@ def 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_test des Kunden - is_test = True + if customer_data[2]: # is_fake des Kunden + is_fake = True # Lizenz hinzufügen cur.execute(""" INSERT INTO licenses (license_key, customer_id, license_type, valid_from, valid_until, is_active, - domain_count, ipv4_count, phone_count, device_limit, is_test) + domain_count, ipv4_count, phone_count, device_limit, is_fake) VALUES (%s, %s, %s, %s, %s, TRUE, %s, %s, %s, %s, %s) RETURNING id """, (license_key, customer_id, license_type, valid_from, valid_until, - domain_count, ipv4_count, phone_count, device_limit, is_test)) + domain_count, ipv4_count, phone_count, device_limit, is_fake)) license_id = cur.fetchone()[0] # Ressourcen zuweisen @@ -375,10 +378,10 @@ def create_license(): # Prüfe Verfügbarkeit cur.execute(""" SELECT - (SELECT COUNT(*) FROM resource_pools WHERE resource_type = 'domain' AND status = 'available' AND is_test = %s) as domains, - (SELECT COUNT(*) FROM resource_pools WHERE resource_type = 'ipv4' AND status = 'available' AND is_test = %s) as ipv4s, - (SELECT COUNT(*) FROM resource_pools WHERE resource_type = 'phone' AND status = 'available' AND is_test = %s) as phones - """, (is_test, is_test, is_test)) + (SELECT COUNT(*) FROM resource_pools WHERE resource_type = 'domain' AND status = 'available' AND is_fake = %s) as domains, + (SELECT COUNT(*) FROM resource_pools WHERE resource_type = 'ipv4' AND status = 'available' AND is_fake = %s) as ipv4s, + (SELECT COUNT(*) FROM resource_pools WHERE resource_type = 'phone' AND status = 'available' AND is_fake = %s) as phones + """, (is_fake, is_fake, is_fake)) available = cur.fetchone() if available[0] < domain_count: @@ -392,9 +395,9 @@ def create_license(): if domain_count > 0: cur.execute(""" SELECT id FROM resource_pools - WHERE resource_type = 'domain' AND status = 'available' AND is_test = %s + WHERE resource_type = 'domain' AND status = 'available' AND is_fake = %s LIMIT %s FOR UPDATE - """, (is_test, domain_count)) + """, (is_fake, domain_count)) for (resource_id,) in cur.fetchall(): cur.execute(""" UPDATE resource_pools @@ -417,9 +420,9 @@ def create_license(): if ipv4_count > 0: cur.execute(""" SELECT id FROM resource_pools - WHERE resource_type = 'ipv4' AND status = 'available' AND is_test = %s + WHERE resource_type = 'ipv4' AND status = 'available' AND is_fake = %s LIMIT %s FOR UPDATE - """, (is_test, ipv4_count)) + """, (is_fake, ipv4_count)) for (resource_id,) in cur.fetchall(): cur.execute(""" UPDATE resource_pools @@ -442,9 +445,9 @@ def create_license(): if phone_count > 0: cur.execute(""" SELECT id FROM resource_pools - WHERE resource_type = 'phone' AND status = 'available' AND is_test = %s + WHERE resource_type = 'phone' AND status = 'available' AND is_fake = %s LIMIT %s FOR UPDATE - """, (is_test, phone_count)) + """, (is_fake, phone_count)) for (resource_id,) in cur.fetchall(): cur.execute(""" UPDATE resource_pools @@ -480,7 +483,7 @@ def create_license(): 'valid_from': valid_from, 'valid_until': valid_until, 'device_limit': device_limit, - 'is_test': is_test + 'is_fake': is_fake }) flash(f'Lizenz {license_key} erfolgreich erstellt!', 'success') diff --git a/v2_adminpanel/routes/resource_routes.py b/v2_adminpanel/routes/resource_routes.py index 1664868..baa70fd 100644 --- a/v2_adminpanel/routes/resource_routes.py +++ b/v2_adminpanel/routes/resource_routes.py @@ -28,9 +28,9 @@ def resources(): resource_type = request.args.get('type', 'all') status_filter = request.args.get('status', 'all') search_query = request.args.get('search', '') - show_test = request.args.get('show_test', 'false') == 'true' + show_fake = request.args.get('show_fake', 'false') == 'true' - logging.info(f"Filters: type={resource_type}, status={status_filter}, search={search_query}, show_test={show_test}") + logging.info(f"Filters: type={resource_type}, status={status_filter}, search={search_query}, show_fake={show_fake}") # Basis-Query query = """ @@ -39,7 +39,7 @@ def resources(): rp.resource_type, rp.resource_value, rp.status, - rp.is_test, + rp.is_fake, rp.allocated_to_license, rp.created_at, rp.status_changed_at, @@ -67,8 +67,8 @@ def resources(): query += " AND (rp.resource_value ILIKE %s OR c.name ILIKE %s)" params.extend([f'%{search_query}%', f'%{search_query}%']) - if not show_test: - query += " AND rp.is_test = false" + if not show_fake: + query += " AND rp.is_fake = false" query += " ORDER BY rp.resource_type, rp.resource_value" @@ -84,7 +84,7 @@ def resources(): 'resource_type': row[1], 'resource_value': row[2], 'status': row[3], - 'is_test': row[4], + 'is_fake': row[4], 'allocated_to_license': row[5], 'created_at': row[6], 'status_changed_at': row[7], @@ -98,16 +98,16 @@ def resources(): SELECT resource_type, status, - is_test, + is_fake, COUNT(*) as count FROM resource_pools """ # Apply test filter to statistics as well - if not show_test: - stats_query += " WHERE is_test = false" + if not show_fake: + stats_query += " WHERE is_fake = false" - stats_query += " GROUP BY resource_type, status, is_test" + stats_query += " GROUP BY resource_type, status, is_fake" cur.execute(stats_query) @@ -115,7 +115,7 @@ def resources(): for row in cur.fetchall(): res_type = row[0] status = row[1] - is_test = row[2] + is_fake = row[2] count = row[3] if res_type not in stats: @@ -131,7 +131,7 @@ def resources(): stats[res_type]['total'] += count stats[res_type][status] = stats[res_type].get(status, 0) + count - if is_test: + if is_fake: stats[res_type]['test'] += count else: stats[res_type]['prod'] += count @@ -160,7 +160,7 @@ def resources(): resource_type=resource_type, status_filter=status_filter, search=search_query, # Changed from search_query to search - show_test=show_test, + show_fake=show_fake, total=total, page=page, total_pages=total_pages, @@ -325,7 +325,7 @@ def resource_history(resource_id): try: # Hole Ressourcen-Info cur.execute(""" - SELECT resource_type, resource_value, status, is_test + SELECT resource_type, resource_value, status, is_fake FROM resource_pools WHERE id = %s """, (resource_id,)) resource = cur.fetchone() @@ -369,7 +369,7 @@ def resource_history(resource_id): 'type': resource[0], 'value': resource[1], 'status': resource[2], - 'is_test': resource[3] + 'is_fake': resource[3] }, history=history) @@ -395,10 +395,10 @@ def resource_metrics(): SELECT resource_type, status, - is_test, + is_fake, COUNT(*) as count FROM resource_pools - GROUP BY resource_type, status, is_test + GROUP BY resource_type, status, is_fake ORDER BY resource_type, status """) @@ -539,8 +539,8 @@ def resources_report(): COUNT(CASE WHEN status = 'available' THEN 1 END) as available, COUNT(CASE WHEN status = 'allocated' THEN 1 END) as allocated, COUNT(CASE WHEN status = 'quarantined' THEN 1 END) as quarantined, - COUNT(CASE WHEN is_test = true THEN 1 END) as test, - COUNT(CASE WHEN is_test = false THEN 1 END) as production + COUNT(CASE WHEN is_fake = true THEN 1 END) as test, + COUNT(CASE WHEN is_fake = false THEN 1 END) as production FROM resource_pools GROUP BY resource_type ORDER BY resource_type @@ -566,7 +566,7 @@ def resources_report(): rp.resource_type, rp.resource_value, rp.status, - rp.is_test, + rp.is_fake, c.name as customer_name, l.license_key, rp.status_changed_at, @@ -628,7 +628,7 @@ def add_resources(): try: resource_type = request.form.get('resource_type') resources_text = request.form.get('resources_text', '') - is_test = request.form.get('is_test', 'false') == 'true' + is_fake = request.form.get('is_fake', 'false') == 'true' if not resource_type or not resources_text.strip(): flash('Bitte Ressourcentyp und Ressourcen angeben!', 'error') @@ -686,9 +686,9 @@ def add_resources(): for resource in new_resources: cur.execute(""" INSERT INTO resource_pools - (resource_type, resource_value, status, is_test, created_by) + (resource_type, resource_value, status, is_fake, created_by) VALUES (%s, %s, 'available', %s, %s) - """, (resource_type, resource, is_test, session['username'])) + """, (resource_type, resource, is_fake, session['username'])) added_count += 1 conn.commit() @@ -706,7 +706,7 @@ def add_resources(): if invalid_resources: flash(f'❌ {len(invalid_resources)} ungültige Ressourcen wurden ignoriert.', 'error') - return redirect(url_for('resources.resources', show_test=request.form.get('show_test', 'false'))) + return redirect(url_for('resources.resources', show_fake=request.form.get('show_fake', 'false'))) except Exception as e: conn.rollback() @@ -717,5 +717,5 @@ def add_resources(): conn.close() # GET request - show form - show_test = request.args.get('show_test', 'false') == 'true' - return render_template('add_resources.html', show_test=show_test) \ No newline at end of file + show_fake = request.args.get('show_fake', 'false') == 'true' + return render_template('add_resources.html', show_fake=show_fake) \ No newline at end of file diff --git a/v2_adminpanel/templates/batch_form.html b/v2_adminpanel/templates/batch_form.html index 744dc31..92ecf50 100644 --- a/v2_adminpanel/templates/batch_form.html +++ b/v2_adminpanel/templates/batch_form.html @@ -175,9 +175,9 @@
- -
diff --git a/v2_adminpanel/templates/create_customer.html b/v2_adminpanel/templates/create_customer.html index f731f02..03a7eff 100644 --- a/v2_adminpanel/templates/create_customer.html +++ b/v2_adminpanel/templates/create_customer.html @@ -30,9 +30,9 @@
- -
diff --git a/v2_adminpanel/templates/customers.html b/v2_adminpanel/templates/customers.html index 87f123b..aaed406 100644 --- a/v2_adminpanel/templates/customers.html +++ b/v2_adminpanel/templates/customers.html @@ -5,10 +5,10 @@ {% macro sortable_header(label, field, current_sort, current_order) %} {% if current_sort == field %} - {% else %} - {% endif %} {{ label }} @@ -41,10 +41,10 @@
- -
@@ -126,31 +126,31 @@

diff --git a/v2_adminpanel/templates/customers_licenses.html b/v2_adminpanel/templates/customers_licenses.html index a88f7d4..d6050bf 100644 --- a/v2_adminpanel/templates/customers_licenses.html +++ b/v2_adminpanel/templates/customers_licenses.html @@ -17,14 +17,14 @@ Export

@@ -47,11 +47,11 @@
- -
@@ -289,7 +289,7 @@ function loadCustomerLicenses(customerId) { }); document.querySelector(`[data-customer-id="${customerId}"]`).classList.add('active'); - // URL aktualisieren ohne Reload (behalte show_test Parameter) + // URL aktualisieren ohne Reload (behalte show_fake Parameter) const currentUrl = new URL(window.location); currentUrl.searchParams.set('customer_id', customerId); window.history.pushState({}, '', currentUrl.toString()); @@ -522,10 +522,10 @@ function copyToClipboard(text) { } // Toggle Testkunden -function toggleTestCustomers() { - const showTest = document.getElementById('showTestCustomers').checked; +function toggleFakeCustomers() { + const showTest = document.getElementById('showFakeCustomers').checked; const currentUrl = new URL(window.location); - currentUrl.searchParams.set('show_test', showTest); + currentUrl.searchParams.set('show_fake', showTest); window.location.href = currentUrl.toString(); } @@ -854,12 +854,12 @@ function quarantineResource(resourceId, resourceValue) { // Lade verfügbare Ressourcen function loadAvailableResources(licenseId) { - // Hole show_test Parameter aus der URL + // Hole show_fake Parameter aus der URL const urlParams = new URLSearchParams(window.location.search); - const showTest = urlParams.get('show_test') === 'true'; + const showTest = urlParams.get('show_fake') === 'true'; // Lade verfügbare Domains - fetch(`/api/resources/check-availability?type=domain&count=200&show_test=${showTest}`) + fetch(`/api/resources/check-availability?type=domain&count=200&show_fake=${showTest}`) .then(response => response.json()) .then(data => { const select = document.getElementById('availableDomains'); @@ -880,7 +880,7 @@ function loadAvailableResources(licenseId) { }); // Lade verfügbare IPv4s - fetch(`/api/resources/check-availability?type=ipv4&count=200&show_test=${showTest}`) + fetch(`/api/resources/check-availability?type=ipv4&count=200&show_fake=${showTest}`) .then(response => response.json()) .then(data => { const select = document.getElementById('availableIpv4s'); @@ -901,7 +901,7 @@ function loadAvailableResources(licenseId) { }); // Lade verfügbare Telefonnummern - fetch(`/api/resources/check-availability?type=phone&count=200&show_test=${showTest}`) + fetch(`/api/resources/check-availability?type=phone&count=200&show_fake=${showTest}`) .then(response => response.json()) .then(data => { const select = document.getElementById('availablePhones'); diff --git a/v2_adminpanel/templates/dashboard.html b/v2_adminpanel/templates/dashboard.html index 2aa9635..764c07b 100644 --- a/v2_adminpanel/templates/dashboard.html +++ b/v2_adminpanel/templates/dashboard.html @@ -116,17 +116,17 @@

Vollversionen

-

{{ stats.test_licenses }}

+

{{ stats.fake_licenses }}

Testversionen

- {% if stats.test_data_count > 0 or stats.test_customers_count > 0 or stats.test_resources_count > 0 %} + {% if stats.fake_data_count > 0 or stats.fake_customers_count > 0 or stats.fake_resources_count > 0 %}
- Testdaten: - {{ stats.test_data_count }} Lizenzen, - {{ stats.test_customers_count }} Kunden, - {{ stats.test_resources_count }} Ressourcen + Fake-Daten: + {{ stats.fake_data_count }} Lizenzen, + {{ stats.fake_customers_count }} Kunden, + {{ stats.fake_resources_count }} Ressourcen
{% endif %} diff --git a/v2_adminpanel/templates/edit_customer.html b/v2_adminpanel/templates/edit_customer.html index 907b0ce..e5db27d 100644 --- a/v2_adminpanel/templates/edit_customer.html +++ b/v2_adminpanel/templates/edit_customer.html @@ -7,15 +7,15 @@

Kunde bearbeiten

- 👥 Zurück zur Übersicht + 👥 Zurück zur Übersicht
- {% if request.args.get('show_test') == 'true' %} - + {% if request.args.get('show_fake') == 'true' %} + {% endif %}
@@ -33,16 +33,16 @@
- +
- Abbrechen + Abbrechen
diff --git a/v2_adminpanel/templates/edit_license.html b/v2_adminpanel/templates/edit_license.html index 5457c91..92f4b2a 100644 --- a/v2_adminpanel/templates/edit_license.html +++ b/v2_adminpanel/templates/edit_license.html @@ -7,15 +7,15 @@
- {% if request.args.get('show_test') == 'true' %} - + {% if request.args.get('show_fake') == 'true' %} + {% endif %}
@@ -66,16 +66,16 @@
- +
- Abbrechen + Abbrechen
diff --git a/v2_adminpanel/templates/index.html b/v2_adminpanel/templates/index.html index 6f2c2ff..4839735 100644 --- a/v2_adminpanel/templates/index.html +++ b/v2_adminpanel/templates/index.html @@ -154,9 +154,9 @@
- +
diff --git a/v2_adminpanel/templates/licenses.html b/v2_adminpanel/templates/licenses.html index b6a1c1e..bf6d9b7 100644 --- a/v2_adminpanel/templates/licenses.html +++ b/v2_adminpanel/templates/licenses.html @@ -4,13 +4,20 @@ {% macro sortable_header(label, field, current_sort, current_order) %} + {% set base_url = url_for('licenses.licenses') %} + {% set params = [] %} + {% if search %}{% set _ = params.append('search=' + search|urlencode) %}{% endif %} + {% for type in filter_types %}{% set _ = params.append('types[]=' + type|urlencode) %}{% endfor %} + {% for status in filter_statuses %}{% set _ = params.append('statuses[]=' + status|urlencode) %}{% endfor %} + {% set _ = params.append('sort=' + field) %} {% if current_sort == field %} - + {% set _ = params.append('order=' + ('desc' if current_order == 'asc' else 'asc')) %} {% else %} - + {% set _ = params.append('order=asc') %} {% endif %} + {% set _ = params.append('page=1') %} + + {{ label }} {% if current_sort == field %} @@ -24,6 +31,46 @@ {% endmacro %} {% block extra_css %} + {% endblock %} {% block content %} @@ -36,46 +83,162 @@
-
-
+ +
+
-
- - -
-
- - -
-
+ + +
+
+ + +
+
+
Lizenztyp
+ ODER +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
Status
+ ODER +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
Schnellfilter
+
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + - {% if search or filter_type or filter_status %} + {% if search or filter_types or filter_statuses %}
- - Gefiltert: {{ total }} Ergebnisse - {% if search %} | Suche: {{ search }}{% endif %} - {% if filter_type %} | Typ: {{ 'Vollversion' if filter_type == 'full' else 'Testversion' }}{% endif %} - {% if filter_status %} | Status: {{ filter_status }}{% endif %} - +
+ + Gefiltert: {{ total }} Ergebnisse + +
+ {% if search %} + + {{ search }} + {% set clear_search_params = [] %} + {% for type in filter_types %}{% set _ = clear_search_params.append('types[]=' + type|urlencode) %}{% endfor %} + {% for status in filter_statuses %}{% set _ = clear_search_params.append('statuses[]=' + status|urlencode) %}{% endfor %} + {% set _ = clear_search_params.append('sort=' + sort) %} + {% set _ = clear_search_params.append('order=' + order) %} + × + + {% endif %} + {% for type in (filter_types or []) %} + + {{ 'Vollversion' if type == 'full' else 'Testversion' }} + × + + {% endfor %} + {% for status in (filter_statuses or []) %} + + {% if status == 'active' %}✅ Aktiv{% elif status == 'expiring' %}⏰ Läuft bald ab{% elif status == 'expired' %}⚠️ Abgelaufen{% else %}❌ Deaktiviert{% endif %} + × + + {% endfor %} +
+
{% endif %}
@@ -119,8 +282,8 @@ {{ license.customer_name }} - {% if license.is_test %} - 🧪 + {% if license.is_fake %} + 🧪 {% endif %} - @@ -182,33 +345,41 @@ {% if total_pages > 1 %}