diff --git a/Web/app.py b/Web/app.py index a55270c..c064d90 100755 --- a/Web/app.py +++ b/Web/app.py @@ -68,6 +68,7 @@ import logging from logging.handlers import RotatingFileHandler import secrets import importlib +import atexit try: redis = importlib.import_module('redis') except Exception: @@ -2190,12 +2191,13 @@ def _upload_student_cards_excel(): synonyms = { 'ausweis_id': ['ausweis_id', 'ausweisid', 'ausweis-id', 'karte', 'kartennummer', 'card_id', 'id'], + # NEU: Erkennung für lokales Differenzierungsmerkmal / Ausweis Ident + 'ausweis_ident': ['lokales differenzierungsmerkmal', 'lokales_differenzierungsmerkmal', 'ausweis_ident', 'differenzierungsmerkmal'], 'first_name': ['vorname', 'first_name', 'firstname', 'rufname'], 'last_name': ['nachname', 'last_name', 'lastname'], 'class_name': ['klasse', 'class', 'class_name', 'jahrgang', 'jahrgangsstufe', 'stufe', 'gruppe', 'asv_klasse'], 'notes': ['notizen', 'notes', 'bemerkungen', 'bemerkung', 'hinweis', 'hinweise'], - 'default_borrow_days': ['standard_ausleihdauer', 'ausleihdauer', 'borrow_days', 'tage', 'leihtage', - 'max_borrow_days'], + 'default_borrow_days': ['standard_ausleihdauer', 'ausleihdauer', 'borrow_days', 'tage', 'leihtage', 'max_borrow_days'], } def col_index(key): @@ -2207,6 +2209,7 @@ def _upload_student_cards_excel(): mapped_indices = { 'ausweis_id': col_index('ausweis_id'), + 'ausweis_ident': col_index('ausweis_ident'), # NEU 'first_name': col_index('first_name'), 'last_name': col_index('last_name'), 'class_name': col_index('class_name'), @@ -2225,7 +2228,7 @@ def _upload_student_cards_excel(): client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) try: db = client[cfg.MONGODB_DB] - + student_cards_cursor = db['student_cards'].find({}, {'AusweisId': 1}) existing_ids.update( str(card.get('AusweisId', '')).strip().upper() @@ -2247,29 +2250,40 @@ def _upload_student_cards_excel(): return row_values[idx] ausweis_id = sanitize_form_value(val('ausweis_id')) + ausweis_ident = sanitize_form_value(val('ausweis_ident')) # NEU gelesen class_name = sanitize_form_value(val('class_name')) notes = sanitize_form_value(val('notes')) - + + # Ausleihdauer extrahieren und standardmäßig auf 14 setzen default_borrow_days = _excel_int(val('default_borrow_days')) if not default_borrow_days: default_borrow_days = 14 + # Vor- und Nachname sicher auslesen und zusammensetzen first_name = sanitize_form_value(val('first_name')) or "" last_name = sanitize_form_value(val('last_name')) or "" student_name = f"{first_name} {last_name}".strip() + # Leere Zeilen überspringen if not ausweis_id and not student_name and not class_name: continue row_errors = [] - + if not student_name: row_errors.append('Vorname und Nachname fehlen') + # NEU: Generierung des Ausweis Ident, falls nicht in Excel vorhanden + if not ausweis_ident: + # Erstellt einen Bezeichner wie z.B. LD-A83F9 + random_chars = "".join(random.choices(string.ascii_uppercase + string.digits, k=5)) + ausweis_ident = f"LD-{random_chars}" + + # Logik für die Haupt-AusweisID if not ausweis_id and student_name: - ausweis_id = generate_ausweis_id_excel(existing_ids) + ausweis_id = generate_ausweis_id(existing_ids) validation_warnings.append((row_number, f'Ausweis-ID wurde automatisch erzeugt: {ausweis_id}')) - existing_ids.add(ausweis_id.upper()) + existing_ids.add(ausweis_id.upper()) elif ausweis_id: ausweis_id = str(ausweis_id).strip().upper() if ausweis_id in existing_ids: @@ -2284,6 +2298,7 @@ def _upload_student_cards_excel(): planned_rows.append({ 'row_number': row_number, 'ausweis_id': ausweis_id, + 'ausweis_ident': ausweis_ident, 'student_name': student_name, 'class_name': class_name, 'notes': notes, @@ -2322,6 +2337,7 @@ def _upload_student_cards_excel(): ) student_cards.insert_one({ 'AusweisId': row['ausweis_id'], + 'AusweisIdent': encrypt_text(row['ausweis_ident']), 'StandardAusleihdauer': int(row['default_borrow_days']), 'Erstellt': datetime.datetime.now(), **encrypted_payload, diff --git a/Web/modules/database/user.py b/Web/modules/database/user.py index 3091ed9..2765d5d 100755 --- a/Web/modules/database/user.py +++ b/Web/modules/database/user.py @@ -704,6 +704,41 @@ def get_user_by_student_card(student_card_id): # Do not call dp.decrypt_text() here because found_user is a MongoDB dictionary. return found_user +def get_user_by_student_ident(student_ident): + """Return user dict by student ident by decrypting all cards and matching.""" + if not student_ident: + return None + + # Normalisiere den Suchbegriff, den wir finden wollen + normalized_target = str(student_ident).strip() + if not normalized_target: + return None + + client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) + try: + db = _get_tenant_db(client) + all_student_cards = db['student_cards'].find() + + for user_doc in all_student_cards: + encrypted_ident = user_doc.get('AusweisIdent') + + if encrypted_ident: + try: + decrypted_ident = dp.decrypt_text(encrypted_ident) + + if decrypted_ident and str(decrypted_ident).strip() == normalized_target: + return user_doc + + except Exception as e: + app.logger.error(f"Entschlüsselungsfehler bei ID {user_doc.get('_id')}: {e}") + continue + + except Exception as exc: + app.logger.error(f"Datenbankfehler in get_user_by_student_ident: {exc}") + finally: + client.close() + + return None def make_admin(username): """Grant administrator privileges to a user.""" diff --git a/Web/requirements.txt b/Web/requirements.txt index 2f12fd7..cb6ba3a 100755 --- a/Web/requirements.txt +++ b/Web/requirements.txt @@ -18,4 +18,5 @@ pywebpush py-vapid>=1.9.0 beautifulsoup4 pywebpush -pandas \ No newline at end of file +pandas +atexit \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index da3a2e1..db60e41 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,4 +18,5 @@ pywebpush py-vapid>=1.9.0 beautifulsoup4 pywebpush -pandas \ No newline at end of file +pandas +atexit \ No newline at end of file