Un poco de seguridad

Habíamos quedado en el post anterior con la idea de agregar una mínima seguridad a nuestra base de datos, encriptando las contraseñas para que no puedan ser leídas directamente si alguien abre la base de datos con un gestor externo.

Para ello vamos a usar el componente gb.crypt y el algoritmo de encriptación llamado MD5. Gambas nos proporciona también el algoritmo DES, pero no será este si no el MD5.Debemos agregar este componente desde el menú proyecto–>propiedades , en la pestaña componentes.

 

Vamos a guardar la contraseña encriptada y mediante su método check comparamos la contraseña introducida con la guardada. Pero…¡Atención! En el momento de comparar se pasa la contraseña tal como se escribió, no hay que encriptarla antes ya que el propio método chek se encarga de esto.

Esto nos significa hacer unas modificaciones en Fmain para comparar las contraseñas.

ClaveEncriptada = hres[“password”]

password = txtpass.text

If txtuser.text = Clave3 And txtpass.text = “” Then     ‘comprobamos que escriba la contraseña

Message.Info(“Ingrese su Contraseña “)

txtpass.SetFocus

Else If txtuser.text = Clave3 And If Crypt.Check(password, ClaveEncriptada) = True Then ‘comprobamos si la contraseña coincide o  no

Message.Info(“Contraseña incorrecta”)

txtpass.SetFocus

Si observamos el código atentamente veremos que Clave 4 se ha convertido en ClaveEncriptada( La que nos trae la base de datos) y password es la que escribimos nosotros. Destacado en negrita esta el método que las compara, que nos devuelve true si las contraseñas no coinciden y false cuando si lo hacen.

Pero ,¿Cómo encriptamos las contraseñas al momento de guardarlas?   Es fácil, pero no lo podemos hacer desde el DataBrowser directamente. Los controles enlazados a datos nos permiten realizar muchas cosas con muy poco código, pero también tienen sus limitaciones, ya que no podemos “intervenir” en sus rutinas de manejo de datos. La solución es sencilla, pero nos implica agregar los usuarios desde un formulario externo, para no recargar este de controles. Vamos entonces a crear un nuevo formulario llamado Fusuarios , al que solo podremos acceder siendo administrador del sistema. Veamos su aspecto:

fusuarios

El nuevo formulario

Aquí va a ir la rutina de encriptación de la contraseña. Veamos todo el código del formulario comentado:

Private hconn As Connection    ‘declaramos variables
Private hresul As Result
Private Encriptado As String

‘**************************************************************************************

Public Sub Form_Open()
Me.Center
cbxtipo.Add(“Admin”)       ‘Cargamos el combobox
cbxtipo.add(“Operador”)
hconn = Modcon.ConectarBase()  ‘Nos conectamos a la base de datos

End

‘**************************************************************************************

Public Function encript(password As String) As String

Encriptado = crypt.md5(password)     ‘funcion de encriptado

End

‘**************************************************************************************

Public Sub btnaceptar_Click()
Dim pass As String
Dim sql As String
If Txtnombre.text = “” Or Txtpass.text = “” Then  ‘comprobar campos que no esten vacios
Message(“complete todos los datos”)
txtnombre.SetFocus
btnaceptar.Enabled = True
Else
pass = txtpass.text
encript(pass)                          ‘aqui llamamos a la funcion encript y le pasamos como parametro la contraseña escrita
hconn = Modcon.ConectarBase()

Try hconn.EXEC(“insert into usuarios values(&1, &2, &3, &4)”, cbxtipo.Current.Text, Null, txtnombre.text, Encriptado)
btnaceptar.Enabled = False
Catch
Message.Error(“Imposible introducir los datos solicitados”)

Endif
End

‘**************************************************************************************

Public Sub btncancelar_Click()

txtnombre.text = “”
txtpass.text = “”
btnaceptar.Enabled = True
End

‘**************************************************************************************

Public Sub btnsalir_Click()

Fadmin.Show
Me.Close

End
Todo lo relacionado a la encritación esta resaltado en azul, el resto no cambia con respecto a las rutinas ya usadas antes para insertar datos. La contraseña encriptada si fuera, por ejemplo, eldani en la base de datos se vería de otra manera:

eldani=$1$xxmv2eN8$HGtH4TaTFZltTVopzYmiE1

Como podrás ver, absolutamente diferente e casi imposible de recordar.

En el próximo post veremos los cambios a Fadmin y subiré el código fuente completo del programa. Hasta entonces.

Anuncios
Publicado en programación | Etiquetado , , , | 4 comentarios

El formulario de administración

Nos había quedado pendiente el formulario de administración de usuarios, al que solo se ingresa siendo usuario administrador. A los efectos de mostrar otro tipo de controles, vamos a usar controles asociados a datos para ver y editar  los usuarios. En mi época de VB solía usarlos mucho, ahora soy más amigo del código, del cual estos controles ns ahorran muchísimo, ya que con solo indicarle la tabla a usar y la conexión, por si mismo se rellena la tabla y trae controles que nos permiten agregar, editar y borrar datos sin escribir una sola línea de código.

Veamos su aspecto:

fadminAparte de los ya conocidos botones vamos a insertar un control DataSource y encima de éste un control DataBrowser. Bastará con indicarle en el evento open del formulario la conexión y la tabla a utilizar, para que el control se llene solo. Además, como probablemente vayamos solo a ingresar gastos o ingresos de materiales, vamos a poner el control databrowser con su propiedad enabled a false para que por defecto esté bloqueada al arrancar el form,a través del botón administrar usuarios lo podemos llevar a True para poder editar los usuarios. Veamos su código comentado:

‘ Gambas class file

Private hconn As Connection     ‘variable de conexión

Public Sub Form_Open()
Dim usuario As String
usuario = FMain.txtuser.text                 ‘asignarle un valor
Me.Center
Me.Caption = “Administrador” & ” :  ” & usuario
hconn = Modcon.ConectarBase()                   ‘conectamos a la base

End

Public Sub btningresar_Click()

Fingreso.show
Fingreso.Caption = “Formulario para ingreso de gastos” & “- ” & Me.Caption

End

Public Sub btngastos_Click()
DataBrowser1.Enabled = False    ‘bloqueamos el databrowser
Fgastos.Show

End
Public Sub btnadmin_Click()

DataSource1.Table = “usuarios”                     ‘elegimos la tabla a utilizar
DataBrowser1.Enabled = True     ‘Aquí habilitamos la edición

End
Public Sub btncambiar_Click()

FMain.show
Me.Close

End

Public Sub btnsalir_Click()

Me.close

End

Como pueden ver, el código es muy reducido, ya que el control databrowser ya trae en si mismo los controles para agregar, editar y borrar.

Ahora, podemos utilizar este mismo formulario para editar los materiales, cambiando la propiedad del datasource para elegir otra tabla. El código es muy simple.

Public Sub btnmat_Click()

DataSource1.Table = “materiales”
DataBrowser1.Enabled = True
End

Nos queda pendiente agregar un poco de seguridad extra ya que las contraseñas son visibles si abrimos la base de datos con un gestor externo. Pero eso ya es tema de otro post. Hasta entonces.

Publicado en programación | Etiquetado , | 2 comentarios

Codifiquemos el reporte

Había quedado pendiente a codificación del reporte. Vamos a pasarle la variable valor de Fgastos para que lance el reporte elegido usando el mismo código para todos los reportes, sea por local, por material o por fecha. Voy a subir todo el código y luego comentaré lo más relevante.

Private hRes1 As Result
Private hConn As Connection

Private Function ConectarBase() As Boolean

If hconn <> Null Then Return False

hconn = New Connection
hconn.Host = User.Home &/ “.stock”
hconn.name = “stock”
hconn.type = “sqlite3”
Try hconn.Open()
If Error Then
hconn = Null
Message.Error(“error al conectar con la base”)
Return True
Endif
Return False

End

Public Sub _new()

Dim ReportHBox1 As ReportHBox
Dim ReportVBox1 As ReportVBox
Dim lbfecha, lbagencia, lbmaterial, lbcantidad As ReportLabel
Dim valor As String

valor = Fgastos.valor
Print valor
If hconn = Null Then
ConectarBase()

Else
End If
ReportVBox1 = New ReportVBox(Me)
ReportVBox1.Expand = True

ReportHBox1 = New ReportHBox(ReportVBox1)
ReportHBox1.Height = “8mm”
lbfecha = New ReportLabel(ReportHBox1) As “lbfecha”
lbfecha.Width = “25mm”
lbfecha.Alignment = Align.Center
lbagencia = New ReportLabel(ReportHBox1) As “lbagencia”
lbagencia.Expand = True
lbagencia.Alignment = Align.Center
lbmaterial = New ReportLabel(ReportHBox1) As “lbmaterial”
lbmaterial.Expand = True
lbmaterial.Alignment = Align.Center
lbcantidad = New ReportLabel(ReportHBox1) As “lbcantidad”
lbcantidad.Expand = True
lbcantidad.Alignment = Align.Center

hRes1 = hconn.Exec(valor)

ReportHBox1.DataCount = hRes1.Count

End

Public Sub lbfecha_Data(Index As Integer)

hRes1.MoveTo(Index)
Last.data = hRes1!fecha

End

Public Sub lbagencia_Data(Index As Integer)

hRes1.MoveTo(Index)
Last.data = hRes1!local

End

Public Sub lbmaterial_Data(Index As Integer)

hRes1.MoveTo(Index)
Last.data = hRes1!material

End

Public Sub lbcantidad_Data(Index As Integer)

hRes1.MoveTo(Index)
Last.data = hRes1!cantidad

End

Primero debemos declarar y crear la conexión, ya que la del módulo, por alguna razón que desconozco, no funciona con el reporte. Para ello declaramos las variables al principio del formulario y creamos la conexión como siempre. Luego en el evento new del reporte declaramos las variables locales, nos conectamos y traemos los datos. Luego los recorremos mediante el evento data de losa distintos label. Esto ya lo hemos hecho varias veces en proyectos anteriores, no voy a repetir toda la explicación de vuelta. Si os quedan dudas podéis usar el buscador del blog para encontrar los artículos anteriores.

Publicado en programación | Etiquetado , , | 4 comentarios

Reportes imprimibles con gb.report

Hemos conseguido listar y filtrar los diferentes gastos, pero, no podemos pasear con el programa y la base de datos. La idea entonces es crear reportes que puedan imprimirse a convertirse al formato .pdf para poder visualizarlos en cualquier equipo, independientemente del sistema operativo.

Vamos entonces a modificar el formulario de gastos, agregando algunos botones más. Además de modificar su ubicación. Veamos el aspecto de la “barra” modificada.

barra de botonesHemos agregado5 botones, a saber : Btnreportelugar, btnreportematerial, btncombinado, btnreporteporfecha y nuestro viejo conocido btnsalir. Quizá algunos nombres parezcan innecesariamente largos, pero son 100 % descriptivos.

Para poder crear los reportes debemos activar el componente gb.report. Para ello vamos a la pestaña proyecto->propiedades->componentes y allí activamos la casilla de verificación correspondiente. Vamos ahora al árbol del proyecto, seleccionamos fuentes->nuevo-> reporte y en el cuadro de diálogo que se abre a continuación lo nombramos simplemente Reporte. Vamos a agregarle un ReportVBox y dentro de éste colocamos dos reportlabel, uno para el título y otro para las cabeceras de las columnas. Veamos su aspecto.

En tiempo de diseño

En tiempo de diseño

en tiempo de ejecución

en tiempo de ejecución

Para ver como ajustar sus propiedades podéis visitar el siguiente post :https://gambeando.wordpress.com/2012/09/21/agregando-el-reporte/

Bien, para llamar el reporte debemos hacerlo desde Fgastos, teniendo dos precauciones, declarar las variables “comunes” al principio del formulario

Private reporte As Report    ‘este es nuevo
Private hconn As Connection
Private hresul As Result
Public valor As String        ‘este es nuevo

e instanciarlo cada vez que lo llamamos con la palabra clave new

reportarLo que hacemos aquí es preguntar si la variable valor no es igual(<>)a una cadena vacía, que llama al reporte y me abra la vista previa o preview. En caso contrario mostramos un mensaje advirtiendo la ausencia de datos coincidentes. ¿Pero que es datos?

Datos es una variable, que tomara el valor de la sentencia sql correspondiente. Vamos a mostrar un ejemplo con el código para reportar por material.

sqlPor orden de línea, declaramos la variable local filtro y le asignamos el valor seleccionado en el combobox. Luego ejecutamos la sentencia sql y comprobamos el resultado. Si nos da false, le asignamos a la variable valor una cadena vacía para que al llamar al procedimiento reportar nos muestre el mensaje, en caso contrario asignamos a la variable valor el contenido de la sentencia sql.

Para pedir cada reporte, codificaremos el botón correspondiente llamando primero al procedimiento que genera la variable valor y luego a reportar. ¿Suena complicado? Para nada. Sigamos con el mismo ejemplo.

Public Sub Btnreportelugar_Click()

Por_lugar()
reportar

End

Pero si lanzamos esto ahora probablemente nos de un error, ya que el reporte aún no ha sido codificado. Os dejo a continuación el resto del código agregado a Fgastos y en un próximo post comenzaremos a codificar el reporte.

Public Sub Por_lugar()

Dim filtro As String

filtro = cbxlugar.Current.Text
hresul = hconn.Exec(“Select * from gastos where local like ‘” & filtro & “‘”)
If hresul.Available = False Then
valor = “”
Else
valor = “Select * from gastos where local like ‘” & filtro & “‘”
Endif
//**********************************************************
End

Public Sub Btnreportelugar_Click()

Por_lugar()
reportar

End
//***************************************************************
Public Sub btnreportematerial_Click()
Por_material()

reportar
End
//********************************************************
Public Sub btncombinado_Click()

combinado()
reportar

End
//*******************************************************
Public Sub combinado()

Dim filtro As String
Dim filtrob As String
filtrob = cbxmaterial.Current.Text
filtro = cbxlugar.Current.Text
hresul = hconn.Exec(“Select * from gastos where local like ‘” & filtro & “‘ and material like ‘” & filtrob & “‘ order by fecha desc”)
If hresul.Available = False Then
Valor = “”
Else
valor = “Select * from gastos where local like ‘” & filtro & “‘ and material like ‘” & filtrob & “‘ order by fecha desc”
Endif

End

//***************************************************************
Public Sub porfecha()

Dim Desde As String[]
Dim DesdeSql As String
Dim Hasta As String[]
Dim HastaSql As String

Desde = Split(Dbdesde.value, “/”)
‘ponemos lo guiones en barritas para que el motor sqlite3 lo reconozca
‘———————————————————-
DesdeSql = “‘” & Desde[2] & “-” & Desde[0] & “-” & Desde[1] & ” 00:00:00′”
Hasta = Split(Dbhasta.Value, “/”)
HastaSql = “‘” & Hasta[2] & “-” & Hasta[0] & “-” & Hasta[1] & ” 00:00:00′”

hresul = hconn.Exec(“Select * from gastos where datetime(fecha) between” & DesdeSql & ” and ” & HastaSql & “order by fecha desc “)
If hresul.Available = False Then
Valor = “”
Else
valor = “Select * from gastos where datetime(fecha) between” & DesdeSql & ” and ” & HastaSql & “order by fecha desc ”
Endif
End
//*****************************************************************
Public Sub btnreporteporfecha_Click()

porfecha()
reportar

End

Publicado en programación | Etiquetado , , , | 1 Comentario

Viendo y filtrando gastos(III)

Vamos ahora a agregar a nuestro formulario gastos tres controles nuevos, dos Datebox y otro botón. Llamaremos, como siempre,con un nombre descriptivo a nuestros controles: Dbdesde y Dbhasta a los datebox y btnfecha al botón.Vea la imagen:

fechasLos dos primeros nos permitirán elegir las fechas pulsando en el icono con forma de almanaque en lugar de escribirlas a mano. El botón va a lanzar la búsqueda. Debo reconocer que me resultó bastante complicada esta parte y gracias a la ayuda de los compañeros del foro de gambas-es.org pude sacarla adelante. Porque además exige descomponer la fecha en sus partes mediante la función split y luego rearmarla para que funcione. Veamos el código:

Public Sub Btnfecha_Click()

Dim Desde As String[]                ‘Declaramos las variables
Dim DesdeSql As String
Dim Hasta As String[]  ‘ <—- Atento a los corchetes rectos
Dim HastaSql As String

llenado        ‘llamamos al procedimiento llenado

Desde = Split(Dbdesde.value, “/”)
‘ponemos lo guiones en barritas para que el motor sqlite3 lo reconozca
DesdeSql = “‘” & Desde[2] & “-” & Desde[0] & “-” & Desde[1] & ” 00:00:00′”
Hasta = Split(Dbhasta.Value, “/”)
HastaSql = “‘” & Hasta[2] & “-” & Hasta[0] & “-” & Hasta[1] & ” 00:00:00′”

hresul = hconn.Exec(“Select * from gastos where datetime(fecha) between” & DesdeSql & ” and ” & HastaSql & “order by fecha desc “)  ‘Ejecutamos la consulta

datos   ‘llamamos al procedimiento datos

End

*************************************************************************

Los corchetes rectos en la formación de las variables Desdesql y Hastasql nos indican la posición de las distintas partes de la fecha y es necesario que coincidan con el formato en que están quedando guardadas en la base de datos. Sé que puede resultar confuso. En mi caso está guardando año, mes, día en la base, por eso los números no están en orden en los corchetes.

Con esto ya podemos ver los gastos discriminados por local o material, por local y material o por fecha.

Publicado en programación | Etiquetado , | Deja un comentario

Viendo y filtrando gastos (II)

En el evento open del formulario vamos a llamar al procedimiento llenar_todo() para que nos muestre todos los gastos , sin filtro alguno. Si queramos que aparezcan primero los más recientes usaremos la cláusula order by fecha desc en la sentencia sql . Eso suele ser lo más habitual.

Vamos a empezar ahora a filtrar de acuerdo a tres criterios primarios:

1)Por lugar

2)Por material

3)Por lugar y material (para saber cuánto de cada material usamos en determinado lugar)

¿En que se distingue cada uno de las consultas en cuánto al código? En el filtro y en la sentencia sql. El resto del código es prácticamente igual y ambos van a llamar a dos procedimientos que ya vimos; llenado y datos. En caso de duda sobre esto ver el post anterior. Cómo cada una de estas consultas las vamos a llamar desde su botón específico, vamos a codificarlo directamente en el evento click de los botones.

Public Sub btnlugar_Click()

Dim filtro As String
filtro = cbxlugar.Current.Text

  llenado
hconn = Modcon.ConectarBase()
hresul = hconn.Exec(“Select * from gastos where local like ‘” & filtro & “‘order by fecha desc”)

  datos

End
…………………………………………………………………………………………………………………………………….
Public Sub btnmaterial_Click()

Dim filtro As String
filtro = cbxmaterial.Current.Text

llenado
hconn = Modcon.ConectarBase()
hresul = hconn.Exec(“Select * from gastos where material like ‘” & filtro & “‘ order by fecha desc”)

datos

End

……………………………………………………………………………………………………………………………………..

Public Sub btncombina_Click()

Dim filtro As String
Dim filtrob As String
filtro = cbxlugar.Current.Text
filtrob = cbxmaterial.Current.Text

llenado
hconn = Modcon.ConectarBase()
hresul = hconn.Exec(“Select * from gastos where local like ‘” & filtro & “‘ and material like ‘” & filtrob & “‘ order by fecha desc”)

datos

End

He destacado en rojo el último procedimiento para destacar las diferencias con respecto a los otros, más simples. Primero, vemos que utiliza dos filtros y que ambos son concatenados en la consulta por intermedio del operador lógico and y ordernados  por a través de la claúsula order by. Cabe aclarar que el criterio de ordenamiento es el que me parece mejor, pero puedes ordenar por cualquiera de los campos en forma ascendente o descendente, sea por su valor alfabético o numérico. En el próximo post veremos el complicado tema de las fechas en las búsquedas. Hasta entonces.

Publicado en programación | Etiquetado , , | 3 comentarios

Viendo y filtrando gastos (I)

Hasta ahora sólo hemos ingresado los gastos. Ha llegado el momento de verlos y seleccionar por distintos criterios. Vamos a crear un nuevo formulario al que llamaremos fgastos.

fgastos

Vamos a añadirle por ahora cuatro botones ( btnlugar, btnmaterial, btncombina, btnrefrescar) un columview al que llamamos simplemente tabla y un par de comboboxes cuyos nombres pueden verse en la imagen precedente. Al principio del código agregaremos como siempre las variables a utilizar en todo el formulario

Private hconn As Connection  ‘variable de conexión
Private hresul As Result    ‘variable de consulta

Vamos a crear los procedimientos para cargar los comboboxes y para llenar la tabla con todos los datos, sin ningún filtro.

Public Sub listado(lista As ComboBox)

Dim Clave As String

Modcon.ConectarBase()
hresul = hconn.Exec(“Select * from materiales order by nombre ASC”) ‘consulta sql
Do While hresul.Available
Clave = hresul[“nombre”]
lista.Add(Clave)
hresul.MoveNext()
Loop

End
……………………………………………………………………………………………………………………………….

Public Sub listado1(lista As ComboBox)

Dim Clave As String

Modcon.ConectarBase()
hresul = hconn.Exec(“Select * from locales order by nombre ASC”) ‘consulta sql

Do While hresul.Available
Clave = hresul[“nombre”]
lista.Add(Clave)
hresul.MoveNext()
Loop

End

Estos dos primeros procedimientos ya los hemos usado muchas veces y no precisan mayor explicación. Son los que llenan cada combobox con los datos de las tablas que les corresponden. Esto es necesario para que al filtrar no debemos escribir, con lo cual, además, evitamos errores de tipeado.

Public Sub llenado()

tabla.Clear

tabla.Columns.Count = 5
tabla.Columns[0].text = “id”
tabla.Columns[0].Width = 20
tabla.Columns[0].Alignment = Align.Center
tabla.Columns[1].text = “Fecha”
tabla.Columns[1].Alignment = Align.Center
tabla.Columns[1].Width = 100
tabla.Columns[2].text = “Lugar”
tabla.Columns[2].Alignment = Align.Center
tabla.Columns[2].Width = 180
tabla.Columns[3].text = “Material”
tabla.Columns[3].Alignment = Align.Center
tabla.Columns[3].Width = 200
tabla.Columns[4].text = “Cantidad”
tabla.Columns[4].Alignment = Align.Center
tabla.Columns[4].Width = 20

End

El procedimiento llenado prepara la estructura de la tabla para recibir los datos. Debemos llamarlo en cada consulta, al tenerlo en un procedimiento evitamos repetir todo el código innecesariamente. Con el que viene a continuación, llamado llenar_todo() se encarga de llamar los datos  sin ningún tipo de filtro, y llama a otro denominado datos() , que los muestra por pantalla. Si miras con atención podrás notar como llenar todo llama a otros dos procedimientos.

Public Sub datos()

Dim Clave As String

If hresul.Available = False Then
Message(“No hay datos que coincidan con su búsqueda”)
Endif
Do While hresul.Available

Clave = hresul[“id_gasto”]
tabla.Add(Clave, Clave)

tabla[Clave][1] = hresul[“fecha”]
tabla[Clave][2] = hresul[“local”]
tabla[Clave][3] = hresul[“material”]
tabla[Clave][4] = hresul[“cantidad”]

hresul.MoveNext()

Loop

End

……………………………………………………………………………………………………………………………………
Public Sub llenar_todo()
Dim filtro As String

llenado                             ‘llamada al procedimiento llenado
hconn = Modcon.ConectarBase()
hresul = hconn.Exec(“Select * from gastos”)

datos                          ‘llamada al procedimiento datos
End

Como más adelante veremos, esta forma de hacerlo nos permitirá simplificar las consultas filtradas gracias a la modularización del sistema y la reutilización de código. Con esto ya estamos en condiciones de ver los gastos por pantalla y en general. En el próximo post comenzaremos a aplicar filtros simples y combinados.

Publicado en programación | Etiquetado , , | Deja un comentario