Lizenzkey Generator
Dieser Commit ist enthalten in:
@@ -18,6 +18,9 @@ import logging
|
||||
import random
|
||||
import hashlib
|
||||
import requests
|
||||
import secrets
|
||||
import string
|
||||
import re
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -548,6 +551,50 @@ def verify_recaptcha(response):
|
||||
logging.error(f"Unerwarteter Fehler bei reCAPTCHA: {str(e)}")
|
||||
return False
|
||||
|
||||
def generate_license_key(license_type='full'):
|
||||
"""
|
||||
Generiert einen Lizenzschlüssel im Format: AF-YYYYMMFT-XXXX-YYYY-ZZZZ
|
||||
|
||||
AF = Account Factory (Produktkennung)
|
||||
YYYY = Jahr
|
||||
MM = Monat
|
||||
FT = F für Fullversion, T für Testversion
|
||||
XXXX-YYYY-ZZZZ = Zufällige alphanumerische Zeichen
|
||||
"""
|
||||
# Erlaubte Zeichen (ohne verwirrende wie 0/O, 1/I/l)
|
||||
chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
|
||||
|
||||
# Datum-Teil
|
||||
now = datetime.now()
|
||||
date_part = now.strftime('%Y%m')
|
||||
type_char = 'F' if license_type == 'full' else 'T'
|
||||
|
||||
# Zufällige Teile generieren (3 Blöcke à 4 Zeichen)
|
||||
parts = []
|
||||
for _ in range(3):
|
||||
part = ''.join(secrets.choice(chars) for _ in range(4))
|
||||
parts.append(part)
|
||||
|
||||
# Key zusammensetzen
|
||||
key = f"AF-{date_part}{type_char}-{parts[0]}-{parts[1]}-{parts[2]}"
|
||||
|
||||
return key
|
||||
|
||||
def validate_license_key(key):
|
||||
"""
|
||||
Validiert das License Key Format
|
||||
Erwartet: AF-YYYYMMFT-XXXX-YYYY-ZZZZ
|
||||
"""
|
||||
if not key:
|
||||
return False
|
||||
|
||||
# Pattern für das spezifische Format
|
||||
# AF- (fest) + 6 Ziffern (YYYYMM) + F oder T + - + 4 Zeichen + - + 4 Zeichen + - + 4 Zeichen
|
||||
pattern = r'^AF-\d{6}[FT]-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$'
|
||||
|
||||
# Großbuchstaben für Vergleich
|
||||
return bool(re.match(pattern, key.upper()))
|
||||
|
||||
@app.route("/login", methods=["GET", "POST"])
|
||||
def login():
|
||||
# Timing-Attack Schutz - Start Zeit merken
|
||||
@@ -672,6 +719,51 @@ def heartbeat():
|
||||
'username': session.get('username')
|
||||
})
|
||||
|
||||
@app.route("/api/generate-license-key", methods=['POST'])
|
||||
@login_required
|
||||
def api_generate_key():
|
||||
"""API Endpoint zur Generierung eines neuen Lizenzschlüssels"""
|
||||
try:
|
||||
# Lizenztyp aus Request holen (default: full)
|
||||
data = request.get_json() or {}
|
||||
license_type = data.get('type', 'full')
|
||||
|
||||
# Key generieren
|
||||
key = generate_license_key(license_type)
|
||||
|
||||
# Prüfen ob Key bereits existiert (sehr unwahrscheinlich aber sicher ist sicher)
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
# Wiederhole bis eindeutiger Key gefunden
|
||||
attempts = 0
|
||||
while attempts < 10: # Max 10 Versuche
|
||||
cur.execute("SELECT 1 FROM licenses WHERE license_key = %s", (key,))
|
||||
if not cur.fetchone():
|
||||
break # Key ist eindeutig
|
||||
key = generate_license_key(license_type)
|
||||
attempts += 1
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# Log für Audit
|
||||
log_audit('GENERATE_KEY', 'license',
|
||||
additional_info={'type': license_type, 'key': key})
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'key': key,
|
||||
'type': license_type
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Fehler bei Key-Generierung: {str(e)}")
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': 'Fehler bei der Key-Generierung'
|
||||
}), 500
|
||||
|
||||
@app.route("/")
|
||||
@login_required
|
||||
def dashboard():
|
||||
@@ -841,11 +933,16 @@ def create_license():
|
||||
if request.method == "POST":
|
||||
name = request.form["customer_name"]
|
||||
email = request.form["email"]
|
||||
license_key = request.form["license_key"]
|
||||
license_key = request.form["license_key"].upper() # Immer Großbuchstaben
|
||||
license_type = request.form["license_type"]
|
||||
valid_from = request.form["valid_from"]
|
||||
valid_until = request.form["valid_until"]
|
||||
|
||||
# Validiere License Key Format
|
||||
if not validate_license_key(license_key):
|
||||
flash('Ungültiges License Key Format! Erwartet: AF-YYYYMMFT-XXXX-YYYY-ZZZZ', 'error')
|
||||
return redirect(url_for('create_license'))
|
||||
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren