mirror of
https://github.com/KeymonSoft/jRDC-Multi.git
synced 2026-04-19 21:59:23 +00:00
- VERSION 5.09.14
``` feat: Implement hot-swap for DB config reload and JSON POST support **Cambios Principales:** 1. **Hot-Swap para recarga de configuraciones de DB sin reiniciar servidor** 2. **Migración a ReentrantLock para sincronización por incompatibilidad con Sync** 3. **Soporte para peticiones POST con Content-Type: application/json** 4. **Mejoras en inicialización del pool de conexiones y soporte multi-DB** **Problemas Resueltos:** - Falta de "Hot-Swap" en `reload`: El comando no permitía recarga dinámica de configuraciones sin reinicio - Ausencia de mecanismo de cierre de pools en RDCConnector para liberación ordenada de conexiones - Incompatibilidad con `Sync` en entorno B4X - Procesamiento incorrecto de peticiones POST con Content-Type: application/json - Inicialización incorrecta de pools C3P0 con TotalConnections: 0 - Configuración inconsistente de parámetros críticos de C3P0 - jdbcUrl truncada/vacía en logs por shadowing de variables **Cambios Implementados:** **Manager.bas:** - Reemplazo completo de lógica para comando "reload" - Creación de nuevos conectores antes de reemplazar los antiguos - Sincronización con ReentrantLock para acceso thread-safe - Patrón seguro de bloqueo sin `Finally` usando bandera booleana - Cierre explícito de oldConnectors después del reemplazo - Validación de inicialización y control de errores robusto - Registro detallado en log HTML del proceso **RDCConnector.bas:** - Implementación de método `Public Sub Close()` para liberar pools C3P0 - Corrección de shadowing de variable `config` en LoadConfigMap - Reordenamiento de Initialize - Configuración completa de C3P0 antes de adquirir conexiones - Forzar reportes de errores con acquireRetryAttempts y breakAfterAcquireFailure - Activación forzada del pool con conexión temporal **Main.bas:** - Declaración de `MainConnectorsLock As JavaObject` (ReentrantLock) - Inicialización del lock en AppStart - Declaración separada de conectores (con1, con2, con3, con4) **DBHandlerJSON.bas:** - Detección de peticiones POST con Content-Type: application/json - Lectura de JSON desde InputStream en lugar de parámetro URL - Cierre explícito del InputStream para liberación de recursos - Corrección de nombres de variables para evitar conflictos - Mensajes de error mejorados para ambos métodos (legacy y nuevo) **Beneficios:** - Recarga en caliente de configuraciones DB sin interrupción de servicio - Mayor disponibilidad y mantenibilidad del servidor - Prevención de fugas de recursos con cierre ordenado de pools - Compatibilidad con estándares APIs web (POST application/json) - Inicialización robusta y confiable de pools de conexiones - Mejor reporting de errores y diagnóstico de problemas - Soporte multi-DB más estable y confiable ```
This commit is contained in:
310
jRDC_Multi.b4j
310
jRDC_Multi.b4j
@@ -30,40 +30,54 @@ Library6=jshell
|
||||
Library7=json
|
||||
Library8=jsql
|
||||
Library9=bcrypt
|
||||
Module1=ChangePassHandler
|
||||
Module10=ping
|
||||
Module11=RDCConnector
|
||||
Module12=TestHandler
|
||||
Module2=DBHandlerB4X
|
||||
Module3=DBHandlerJSON
|
||||
Module4=DoLoginHandler
|
||||
Module5=faviconHandler
|
||||
Module6=GlobalParameters
|
||||
Module7=LoginHandler
|
||||
Module8=LogoutHandler
|
||||
Module9=Manager
|
||||
Module1=Cambios
|
||||
Module10=Manager
|
||||
Module11=ping
|
||||
Module12=RDCConnector
|
||||
Module13=TestHandler
|
||||
Module2=ChangePassHandler
|
||||
Module3=DBHandlerB4X
|
||||
Module4=DBHandlerJSON
|
||||
Module5=DoLoginHandler
|
||||
Module6=faviconHandler
|
||||
Module7=GlobalParameters
|
||||
Module8=LoginHandler
|
||||
Module9=LogoutHandler
|
||||
NumberOfFiles=10
|
||||
NumberOfLibraries=9
|
||||
NumberOfModules=12
|
||||
NumberOfModules=13
|
||||
Version=10.3
|
||||
@EndOfDesignText@
|
||||
'Non-UI application (console / server application)
|
||||
#Region Project Attributes
|
||||
#CommandLineArgs:
|
||||
#MergeLibraries: True
|
||||
' VERSION 5.09.08
|
||||
'###########################################################################################################
|
||||
'###################### PULL #############################################################
|
||||
'Ctrl + click ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=git&Args=pull
|
||||
'###########################################################################################################
|
||||
'###################### PUSH #############################################################
|
||||
'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=github&Args=..\..\
|
||||
'###########################################################################################################
|
||||
'###################### PUSH TORTOISE GIT #########################################################
|
||||
'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=TortoiseGitProc&Args=/command:commit&Args=/path:"../"&Args=/closeonend:2
|
||||
'###########################################################################################################
|
||||
|
||||
#Region Project Attributes
|
||||
#CommandLineArgs:
|
||||
#MergeLibraries: True
|
||||
' VERSION 5.09.014
|
||||
'###########################################################################################################
|
||||
'###################### PULL #############################################################
|
||||
'Ctrl + click ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=git&Args=pull
|
||||
'###########################################################################################################
|
||||
'###################### PUSH #############################################################
|
||||
'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=github&Args=..\..\
|
||||
'###########################################################################################################
|
||||
'###################### PUSH TORTOISE GIT #########################################################
|
||||
'Ctrl + click ide://run?file=%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe&Args=TortoiseGitProc&Args=/command:commit&Args=/path:"../"&Args=/closeonend:2
|
||||
'###########################################################################################################
|
||||
#End Region
|
||||
|
||||
'- VERSION 5.09.08
|
||||
'- Se agregó que se puedan configurar en el config.properties los siguientes parametros:
|
||||
'
|
||||
' - setInitialPoolSize = 3
|
||||
' - setMinPoolSize = 2
|
||||
' - setMaxPoolSize = 5
|
||||
'
|
||||
'- Se agregaron en duro a RDConnector los siguientes parametros:
|
||||
'
|
||||
' - setMaxIdleTime <-- Tiempo máximo de inactividad de la conexión.
|
||||
' - setMaxConnectionAge <-- Tiempo de vida máximo de una conexión.
|
||||
' - setCheckoutTimeout <-- Tiempo máximo de espera por una conexión.
|
||||
'change based on the jdbc jar file
|
||||
'#AdditionalJar: mysql-connector-java-5.1.27-bin
|
||||
'#AdditionalJar: postgresql-42.7.0
|
||||
@@ -72,104 +86,164 @@ Version=10.3
|
||||
#AdditionalJar: sqlite-jdbc-3.7.2
|
||||
|
||||
Sub Process_Globals
|
||||
Public srvr As Server
|
||||
Public const VERSION As Float = 2.23
|
||||
Type DBCommand (Name As String, Parameters() As Object)
|
||||
Type DBResult (Tag As Object, Columns As Map, Rows As List)
|
||||
Dim listaDeCP As List
|
||||
Dim cpFiles As List
|
||||
Public Connectors, commandsMap As Map
|
||||
Public SQL1 As SQL ' Objeto SQL para la base de datos de usuarios
|
||||
Private bc As BCrypt
|
||||
' --- Variables globales accesibles desde cualquier parte del proyecto ---
|
||||
Public srvr As Server ' El objeto principal del servidor HTTP de B4J.
|
||||
Public const VERSION As Float = 2.23 ' La versión actual de este servidor jRDC modificado.
|
||||
|
||||
' Tipos personalizados para la serialización y deserialización de datos
|
||||
' entre el cliente B4X (DBRequestManager) y el servidor jRDC2.
|
||||
Type DBCommand (Name As String, Parameters() As Object) ' Define un comando SQL.
|
||||
Type DBResult (Tag As Object, Columns As Map, Rows As List) ' Define la estructura de un resultado de consulta.
|
||||
|
||||
Public listaDeCP As List ' Contiene una lista de los identificadores de bases de datos configuradas (ej. "DB1", "DB2").
|
||||
Private cpFiles As List ' Una lista temporal para almacenar los nombres de archivos encontrados en el directorio.
|
||||
|
||||
' Mapas globales para gestionar los conectores de base de datos y los comandos SQL.
|
||||
Public Connectors, commandsMap As Map ' Connectors: Almacena las instancias de RDCConnector por DB.
|
||||
' commandsMap: Almacena los comandos SQL cargados para cada DB.
|
||||
|
||||
Public SQL1 As SQL ' Objeto SQL para interactuar con la base de datos de usuarios (SQLite).
|
||||
Private bc As BCrypt ' Objeto para realizar operaciones de hashing de contraseñas de forma segura (para autenticación).
|
||||
Public MainConnectorsLock As JavaObject ' Objeto de bloqueo para proteger Main.Connectors
|
||||
End Sub
|
||||
|
||||
Sub AppStart (Args() As String)
|
||||
' --- INICIO DE CAMBIOS ---
|
||||
' Inicializamos la base de datos. Se creará si no existe.
|
||||
' --- Subrutina principal que se ejecuta al iniciar la aplicación ---
|
||||
|
||||
' 1. Inicializa la base de datos local de usuarios (SQLite).
|
||||
' Esta base de datos se crea automáticamente si no existe y contiene los usuarios para el panel de administración.
|
||||
InitializeSQLiteDatabase
|
||||
' --- FIN DE CAMBIOS ---
|
||||
listaDeCP.Initialize
|
||||
srvr.Initialize("")
|
||||
Dim con As RDCConnector
|
||||
Connectors = srvr.CreateThreadSafeMap
|
||||
commandsMap.Initialize
|
||||
con.Initialize("DB1") 'Inicializamos el default de config.properties
|
||||
Connectors.Put("DB1", con)
|
||||
srvr.Port = con.serverPort
|
||||
listaDeCP.Add("DB1")
|
||||
|
||||
' 2. Inicializa los mapas globales definidos en GlobalParameters.bas.
|
||||
' Estos mapas se usan para monitorear el servidor y gestionar configuraciones dinámicas.
|
||||
GlobalParameters.mpLogs.Initialize ' Mapa para almacenar logs de actividad.
|
||||
GlobalParameters.mpTotalRequests.Initialize ' Mapa para contar peticiones por endpoint/DB.
|
||||
GlobalParameters.mpTotalConnections.Initialize ' Mapa para almacenar el estado de los pools de conexión por DB.
|
||||
GlobalParameters.mpBlockConnection.Initialize ' Mapa para gestionar IPs bloqueadas (si la funcionalidad está activa).
|
||||
|
||||
' 3. Inicializa las estructuras principales del servidor HTTP.
|
||||
listaDeCP.Initialize ' Inicializa la lista que contendrá los IDs de las bases de datos.
|
||||
srvr.Initialize("") ' Inicializa el objeto servidor HTTP.
|
||||
Connectors = srvr.CreateThreadSafeMap ' Crea un mapa seguro para almacenar instancias de RDCConnector (un conector por DB).
|
||||
commandsMap.Initialize ' Inicializa el mapa que almacenará los comandos SQL cargados de los archivos de configuración.
|
||||
|
||||
' <<<< NUEVA INICIALIZACIÓN: Creamos una instancia de ReentrantLock para proteger Main.Connectors >>>>
|
||||
MainConnectorsLock.InitializeNewInstance("java.util.concurrent.locks.ReentrantLock", Null)
|
||||
' <<<< HASTA AQUÍ LA NUEVA INICIALIZACIÓN >>>>
|
||||
|
||||
' === 4. INICIALIZACIÓN DEL CONECTOR PARA LA BASE DE DATOS PRINCIPAL (DB1) ===
|
||||
' DB1 siempre usa el archivo 'config.properties' por defecto.
|
||||
Dim con1 As RDCConnector ' Declara una variable específica y única para el conector de DB1.
|
||||
con1.Initialize("DB1") ' Inicializa la instancia del conector para "DB1".
|
||||
Connectors.Put("DB1", con1) ' Asocia el identificador "DB1" con su instancia de RDCConnector.
|
||||
srvr.Port = con1.serverPort ' El puerto del servidor HTTP se obtiene del config.properties de DB1.
|
||||
listaDeCP.Add("DB1") ' Añade "DB1" a la lista de bases de datos gestionadas.]
|
||||
Log($"Main.AppStart: Conector 'DB1' inicializado exitosamente en puerto: ${srvr.Port}"$)
|
||||
|
||||
' === 5. DETECCIÓN E INICIALIZACIÓN DE BASES DE DATOS ADICIONALES (DB2, DB3, DB4) ===
|
||||
' El servidor busca archivos de configuración adicionales (ej. config.DB2.properties)
|
||||
' en el mismo directorio donde se ejecuta el JAR.
|
||||
cpFiles = File.ListFiles("./")
|
||||
If cpFiles.Size > 0 Then
|
||||
Log(cpFiles)
|
||||
For i = 0 To cpFiles.Size - 1
|
||||
If cpFiles.Get(i) = "config.DB2.properties" Then ' Si existe el archivo DB2, lo usamos.
|
||||
Dim con As RDCConnector
|
||||
con.Initialize("DB2")
|
||||
Connectors.Put("DB2", con)
|
||||
listaDeCP.Add("DB2")
|
||||
End If
|
||||
If cpFiles.Get(i) = "config.DB3.properties" Then ' Si existe el archivo DB3, lo usamos.
|
||||
Dim con As RDCConnector
|
||||
con.Initialize("DB3")
|
||||
Connectors.Put("DB3", con)
|
||||
listaDeCP.Add("DB3")
|
||||
End If
|
||||
If cpFiles.Get(i) = "config.DB4.properties" Then ' Si existe el archivo DB4, lo usamos.
|
||||
con.Initialize("DB4")
|
||||
Connectors.Put("DB4", con)
|
||||
listaDeCP.Add("DB4")
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
srvr.AddHandler("/ping", "ping", True) ' Agrega un manejador a la ruta "/test", asignando las solicitudes a la clase TestHandler, el último parámetro indica si el manejador debe ejecutar en un nuevo hilo (False en este caso)
|
||||
srvr.AddHandler("/test", "TestHandler", True) ' Agrega un manejador a la ruta "/test", asignando las solicitudes a la clase TestHandler, el último parámetro indica si el manejador debe ejecutar en un nuevo hilo (False en este caso)
|
||||
|
||||
' --- INICIO DE CAMBIOS ---
|
||||
' 1. Rutas para el sistema de Login
|
||||
srvr.AddHandler("/login", "LoginHandler", True) ' Sirve la página de login
|
||||
srvr.AddHandler("/dologin", "DoLoginHandler", True) ' Procesa el intento de login
|
||||
srvr.AddHandler("/logout", "LogoutHandler", True) ' Cierra la sesión
|
||||
srvr.AddHandler("/changepass", "ChangePassHandler", True)
|
||||
' 2. El handler del manager se queda igual, pero ahora estará protegido
|
||||
srvr.AddHandler("/manager", "Manager", True)
|
||||
' --- FIN DE CAMBIOS ---
|
||||
|
||||
srvr.AddHandler("/DBJ", "DBHandlerJSON", True)
|
||||
srvr.AddHandler("/dbrquery", "DBHandlerJSON", True)
|
||||
srvr.AddHandler("/favicon.ico", "faviconHandler", True)
|
||||
' srvr.AddHandler("/*", "DB1Handler", False) ' Si no se especifica una base de datos, entonces asignamos la solicitud a la DB1.
|
||||
|
||||
srvr.AddHandler("/*", "DBHandlerB4X", True)
|
||||
|
||||
srvr.Start
|
||||
Log("===========================================================")
|
||||
Log($"-=== jRDC is running on port: ${srvr.port} (version = $1.2{VERSION}) ===-"$)
|
||||
Log("===========================================================")
|
||||
StartMessageLoop
|
||||
For i = 0 To cpFiles.Size - 1
|
||||
' Procesa 'config.DB2.properties'
|
||||
If cpFiles.Get(i) = "config.DB2.properties" Then
|
||||
Dim con2 As RDCConnector ' Declara una variable específica y única para el conector de DB2.
|
||||
con2.Initialize("DB2") ' Inicializa la instancia del conector para "DB2".
|
||||
Connectors.Put("DB2", con2) ' Asocia "DB2" con su instancia de RDCConnector.
|
||||
listaDeCP.Add("DB2") ' Añade "DB2" a la lista de bases de datos.
|
||||
Log("Main.AppStart: Conector 'DB2' inicializado exitosamente.")
|
||||
End If
|
||||
|
||||
' Procesa 'config.DB3.properties'
|
||||
If cpFiles.Get(i) = "config.DB3.properties" Then
|
||||
Dim con3 As RDCConnector ' Declara una variable específica y única para el conector de DB3.
|
||||
con3.Initialize("DB3") ' Inicializa la instancia del conector para "DB3".
|
||||
Connectors.Put("DB3", con3) ' Asocia "DB3" con su instancia de RDCConnector.
|
||||
listaDeCP.Add("DB3") ' Añade "DB3" a la lista de bases de datos.
|
||||
Log("Main.AppStart: Conector 'DB3' inicializado exitosamente.")
|
||||
End If
|
||||
|
||||
' Procesa 'config.DB4.properties'
|
||||
If cpFiles.Get(i) = "config.DB4.properties" Then
|
||||
Dim con4 As RDCConnector ' Declara una variable específica y única para el conector de DB4.
|
||||
con4.Initialize("DB4") ' Inicializa la instancia del conector para "DB4".
|
||||
Connectors.Put("DB4", con4) ' Asocia "DB4" con su instancia de RDCConnector.
|
||||
listaDeCP.Add("DB4") ' Añade "DB4" a la lista de bases de datos.
|
||||
Log("Main.AppStart: Conector 'DB4' inicializado exitosamente.")
|
||||
End If
|
||||
Next
|
||||
Else
|
||||
Log("Main.AppStart: No se encontraron archivos de configuración adicionales (config.DBx.properties).")
|
||||
End If
|
||||
|
||||
' Log final de las bases de datos que el servidor está gestionando.
|
||||
Dim sbListaDeCP_Log As StringBuilder
|
||||
sbListaDeCP_Log.Initialize
|
||||
For Each item As String In listaDeCP
|
||||
sbListaDeCP_Log.Append(item).Append(", ")
|
||||
Next
|
||||
If sbListaDeCP_Log.Length > 0 Then
|
||||
sbListaDeCP_Log.Remove(sbListaDeCP_Log.Length - 2, sbListaDeCP_Log.Length) ' Elimina la última ", "
|
||||
End If
|
||||
Log($"Main.AppStart: Bases de datos configuradas y listas: [${sbListaDeCP_Log.ToString}]"$)
|
||||
|
||||
' === 6. REGISTRO DE HANDLERS HTTP PARA EL SERVIDOR ===
|
||||
' Asocia rutas URL específicas con clases que manejarán las peticiones correspondientes.
|
||||
' El último parámetro (True) indica que el handler se ejecutará en un nuevo hilo,
|
||||
' lo que es recomendable para la mayoría de los casos para evitar bloqueos.
|
||||
srvr.AddHandler("/ping", "ping", True) ' Endpoint simple para verificar si el servidor está activo.
|
||||
srvr.AddHandler("/test", "TestHandler", True) ' Endpoint para pruebas de conexión y estado del servidor.
|
||||
srvr.AddHandler("/login", "LoginHandler", True) ' Muestra la página HTML de login.
|
||||
srvr.AddHandler("/dologin", "DoLoginHandler", True) ' Procesa el intento de inicio de sesión.
|
||||
srvr.AddHandler("/logout", "LogoutHandler", True) ' Cierra la sesión del usuario.
|
||||
srvr.AddHandler("/changepass", "ChangePassHandler", True) ' Permite a los usuarios cambiar su contraseña.
|
||||
srvr.AddHandler("/manager", "Manager", True) ' Panel de administración del servidor (requiere autenticación).
|
||||
srvr.AddHandler("/DBJ", "DBHandlerJSON", True) ' Handler para clientes web (ej. JavaScript, Node.js) que usan JSON.
|
||||
srvr.AddHandler("/dbrquery", "DBHandlerJSON", True) ' Un alias para el handler JSON, por si se usa en clientes específicos.
|
||||
srvr.AddHandler("/favicon.ico", "faviconHandler", True) ' Sirve el icono de la página (favicon).
|
||||
srvr.AddHandler("/*", "DBHandlerB4X", True) ' Handler por defecto para clientes B4X (DBRequestManager),
|
||||
' procesa peticiones dinámicamente según la URL.
|
||||
|
||||
' 7. Inicia el servidor HTTP.
|
||||
srvr.Start
|
||||
Log("===========================================================")
|
||||
Log($"-=== jRDC está funcionando en el puerto: ${srvr.Port} (versión = $1.2{VERSION}) ===-"$)
|
||||
Log("===========================================================")
|
||||
|
||||
' 8. Inicia el bucle de mensajes de B4J. Es esencial para que la aplicación
|
||||
' de servidor continúe ejecutándose y procesando eventos.
|
||||
StartMessageLoop
|
||||
|
||||
End Sub
|
||||
|
||||
' Nueva subrutina para crear y configurar la base de datos de usuarios
|
||||
' --- Subrutina para inicializar la base de datos de usuarios local (SQLite) ---
|
||||
' Esta base de datos se utiliza para almacenar credenciales de usuarios que pueden
|
||||
' acceder al panel de administración del servidor jRDC.
|
||||
Sub InitializeSQLiteDatabase
|
||||
Dim dbFileName As String = "users.db"
|
||||
' Si la base de datos no existe en la carpeta del .jar, la creamos
|
||||
If File.Exists(File.DirApp, dbFileName) = False Then
|
||||
Log("Creando nueva base de datos de usuarios: " & dbFileName)
|
||||
' Inicializamos la conexión
|
||||
SQL1.InitializeSQLite(File.DirApp, dbFileName, True)
|
||||
' Creamos la tabla de usuarios
|
||||
Dim createUserTable As String = "CREATE TABLE users (username TEXT PRIMARY KEY, password_hash TEXT NOT NULL)"
|
||||
SQL1.ExecNonQuery(createUserTable)
|
||||
|
||||
' Creamos un usuario por defecto para el primer inicio
|
||||
Dim defaultUser As String = "admin"
|
||||
Dim defaultPass As String = "12345"
|
||||
Dim hashedPass As String = bc.hashpw(defaultPass, bc.gensalt) ' bc.HashPassword(defaultPass)
|
||||
|
||||
SQL1.ExecNonQuery2("INSERT INTO users (username, password_hash) VALUES (?, ?)", Array As Object(defaultUser, hashedPass))
|
||||
Log($"Usuario por defecto creado -> user: ${defaultUser}, pass: ${defaultPass}"$)
|
||||
Else
|
||||
' Si ya existe, solo la abrimos
|
||||
SQL1.InitializeSQLite(File.DirApp, dbFileName, True)
|
||||
Log("Base de datos de usuarios cargada.")
|
||||
End If
|
||||
Dim dbFileName As String = "users.db" ' Nombre del archivo de la base de datos SQLite.
|
||||
|
||||
' Verifica si el archivo de la base de datos ya existe en el directorio de la aplicación.
|
||||
If File.Exists(File.DirApp, dbFileName) = False Then
|
||||
Log("Creando nueva base de datos de usuarios: " & dbFileName)
|
||||
' Inicializa la conexión a la base de datos SQLite, creándola si no existe (último parámetro en True).
|
||||
SQL1.InitializeSQLite(File.DirApp, dbFileName, True)
|
||||
|
||||
' Define y ejecuta la sentencia SQL para crear la tabla 'users'.
|
||||
Dim createUserTable As String = "CREATE TABLE users (username TEXT PRIMARY KEY, password_hash TEXT NOT NULL)"
|
||||
SQL1.ExecNonQuery(createUserTable)
|
||||
|
||||
' Crea un usuario por defecto para facilitar el primer acceso al panel de administración.
|
||||
Dim defaultUser As String = "admin"
|
||||
Dim defaultPass As String = "12345"
|
||||
' Genera un hash seguro de la contraseña usando BCrypt, lo cual es crucial para la seguridad.
|
||||
Dim hashedPass As String = bc.hashpw(defaultPass, bc.gensalt)
|
||||
' Inserta el usuario por defecto en la tabla 'users'.
|
||||
SQL1.ExecNonQuery2("INSERT INTO users (username, password_hash) VALUES (?, ?)", Array As Object(defaultUser, hashedPass))
|
||||
Log($"Usuario por defecto creado -> user: ${defaultUser}, pass: ${defaultPass}"$)
|
||||
Else
|
||||
' Si el archivo de la base de datos ya existe, simplemente se abre.
|
||||
SQL1.InitializeSQLite(File.DirApp, dbFileName, True)
|
||||
Log("Base de datos de usuarios cargada.")
|
||||
End If
|
||||
End Sub
|
||||
' --- FIN DE CAMBIOS ---
|
||||
Reference in New Issue
Block a user