{"cells":[{"cell_type":"code","source":"from django.shortcuts import render, redirect\nfrom django.db import connections, utils as db_utils # Para conexiones dinámicas\nfrom django.contrib import messages # Para mostrar mensajes al usuario\nfrom auth_asesoft.models import AsesoftUser # Modelo para la tabla usuarios en 'asesoft'\nfrom .forms import LoginForm\nimport datetime # Para verificar fin_acceso\n\n# Columnas esperadas en la tabla 'usuarios' de la base de datos del cliente\n# Esto es para construir la tabla en la plantilla de forma más genérica.\n# Si las columnas son fijas y conocidas, puedes hardcodearlas en la plantilla.\nCLIENT_USER_TABLE_COLUMNS = ['id', 'nombre_completo', 'correo_electronico', 'telefono', 'fecha_registro']\n\n\ndef login_view(request):\n    if request.method == 'POST':\n        form = LoginForm(request.POST)\n        if form.is_valid():\n            login_username = form.cleaned_data['login']\n            login_password = form.cleaned_data['userpass']\n\n            try:\n                # Conectar a la base de datos 'default' (asesoft) para verificar el usuario\n                user_record = AsesoftUser.objects.using('default').get(login=login_username)\n\n                # ¡ADVERTENCIA DE SEGURIDAD! Comparación de contraseñas en texto plano.\n                # En producción, debes usar un sistema de hashing seguro.\n                if user_record.userpass == login_password:\n                    # Verificar si el acceso del usuario está vigente\n                    if user_record.fin_acceso >= datetime.date.today():\n                        # Credenciales válidas y acceso vigente\n                        request.session['asesoft_user_id'] = user_record.id\n                        request.session['asesoft_user_login'] = user_record.login\n                        request.session['client_db_config'] = {\n                            'servername': user_record.servername,\n                            'dbname': user_record.dbname,\n                            'username': user_record.username,\n                            'password': user_record.password, # ¡ADVERTENCIA DE SEGURIDAD!\n                        }\n                        messages.success(request, f\"Bienvenido {user_record.login}!\")\n                        return redirect('clientviewer:client_data')\n                    else:\n                        messages.error(request, \"Tu acceso ha expirado. Contacta al administrador.\")\n                else:\n                    messages.error(request, \"Usuario o contraseña incorrectos.\")\n            except AsesoftUser.DoesNotExist:\n                messages.error(request, \"Usuario o contraseña incorrectos.\")\n            except Exception as e:\n                messages.error(request, f\"Error durante el login: {e}\")\n        else:\n            messages.error(request, \"Por favor, corrige los errores en el formulario.\")\n    else:\n        form = LoginForm()\n\n    return render(request, 'clientviewer/login.html', {'form': form})\n\n\ndef client_data_view(request):\n    # Verificar si el usuario está logueado (si hay datos de sesión)\n    if 'asesoft_user_id' not in request.session or 'client_db_config' not in request.session:\n        messages.warning(request, \"Por favor, inicia sesión para ver esta página.\")\n        return redirect('clientviewer:login')\n\n    client_db_config = request.session['client_db_config']\n    asesoft_user_id = request.session['asesoft_user_id']\n    \n    # Crear un alias único para la conexión a la base de datos del cliente\n    # Esto es importante si múltiples usuarios se conectan simultáneamente,\n    # aunque para este ejemplo simple, podríamos reusar un alias si la config es la misma.\n    # Por seguridad y claridad, un alias por sesión/usuario es mejor.\n    db_alias = f\"client_db_{asesoft_user_id}\"\n\n    client_users_data = []\n    column_names = []\n    error_message = None\n\n    try:\n        # Configurar la conexión a la base de datos del cliente dinámicamente\n        # Solo la añade si no existe ya para esta sesión (evita redefiniciones innecesarias)\n        if db_alias not in connections.databases:\n            connections.databases[db_alias] = {\n                'ENGINE': 'django.db.backends.mysql', # Asumiendo MySQL para el cliente\n                'NAME': client_db_config['dbname'],\n                'USER': client_db_config['username'],\n                'PASSWORD': client_db_config['password'],\n                'HOST': client_db_config['servername'],\n                'PORT': '3306', # Puerto estándar de MySQL, ajustar si es diferente\n                'OPTIONS': {\n                    'init_command': \"SET sql_mode='STRICT_TRANS_TABLES'\",\n                },\n            }\n        \n        # Forzar a Django a reconocer la nueva configuración si es la primera vez\n        # connections.ensure_defaults(db_alias) # Esto puede no ser necesario si se accede directamente\n        # connections.prepare_test_settings(db_alias) # Esto puede no ser necesario\n\n        # Usar la conexión dinámicamente\n        with connections[db_alias].cursor() as cursor:\n            # Consulta para obtener los datos de la tabla 'usuarios' de la BD del cliente\n            # Ajusta el nombre de la tabla y las columnas si es necesario.\n            # Es más seguro seleccionar columnas explícitamente que usar SELECT *\n            query = f\"SELECT {', '.join(CLIENT_USER_TABLE_COLUMNS)} FROM usuarios LIMIT 100;\" # Limitar resultados por si acaso\n            cursor.execute(query)\n            \n            # Obtener los nombres de las columnas de la descripción del cursor\n            column_names = [col[0] for col in cursor.description]\n            \n            # Obtener todas las filas como una lista de tuplas/diccionarios\n            # fetchall() devuelve tuplas. Para diccionarios:\n            # client_users_data = [dict(zip(column_names, row)) for row in cursor.fetchall()]\n            client_users_data = cursor.fetchall()\n\n\n    except db_utils.OperationalError as e:\n        error_message = f\"Error de conexión a la base de datos del cliente ({client_db_config['dbname']}): {e}. Verifica la configuración y que el servidor de base deatos esté accesible.\"\n        messages.error(request, error_message)\n        # Limpiar la configuración de la BD del cliente de la sesión si falla la conexión\n        # para evitar reintentos con configuración incorrecta.\n        if db_alias in connections.databases:\n            del connections.databases[db_alias]\n    except Exception as e:\n        error_message = f\"Ocurrió un error inesperado al obtener los datos del cliente: {e}\"\n        messages.error(request, error_message)\n        if db_alias in connections.databases:\n            del connections.databases[db_alias]\n\n\n    context = {\n        'client_users_data': client_users_data,\n        'column_names': column_names, # Nombres de las columnas para la cabecera de la tabla\n        'client_db_name': client_db_config['dbname'],\n        'error_message': error_message,\n        'asesoft_user_login': request.session.get('asesoft_user_login', 'Usuario'),\n    }\n    return render(request, 'clientviewer/client_data.html', context)\n\ndef logout_view(request):\n    # Limpiar la configuración de la base de datos dinámica si existe\n    asesoft_user_id = request.session.get('asesoft_user_id')\n    if asesoft_user_id:\n        db_alias = f\"client_db_{asesoft_user_id}\"\n        if db_alias in connections.databases:\n            del connections.databases[db_alias]\n            print(f\"DEBUG: Conexión {db_alias} eliminada de connections.databases\")\n\n    # Limpiar todas las claves de sesión relevantes\n    keys_to_delete = ['asesoft_user_id', 'asesoft_user_login', 'client_db_config']\n    for key in keys_to_delete:\n        if key in request.session:\n            del request.session[key]\n            \n    messages.info(request, \"Has cerrado sesión.\")\n    return redirect('clientviewer:login')","outputs":[],"execution_count":null,"metadata":{}}],"metadata":{"colab":{"from_bard":true},"kernelspec":{"display_name":"Python 3","name":"python3"}},"nbformat":4,"nbformat_minor":0}