Bienvenido a un nuevo capítulo del proyecto Login y Registro de usuarios en python; en la que se añadirá validaciones importantes a los datos ingresados al usuario. En el capítulo anterior se avanzó en la captura de los datos para el registro y login de usuarios. Estos datos (si el usuario desea registrarse) se agregan en listas creadas para almacenarlos; pero antes de guardarlos se valida si el username o email de ese nuevo usuario se encuentran ya registrados, así como también se verifica que el ingreso del password y la repetición del mismo fuesen iguales.
Mas hacen falta mejores validaciones, sobre todo en el dato del email o para el password. Por ejemplo, para el email no se valida el formato, por lo que el usuario podría escribir user_test y se guarda igualmente, cuando realmente debería ser algo como user_test@example.com. Con el password no hay mayor validaciones, sin embargo podemos obligar al usuario que escriba un password que tenga al menos 8 caracteres, 1 número, 1 caracter especial, entre otros. Pues bien, justamente esto es lo que haremos hoy. El código de este capítulo lo encontrarán acá.
Comencemos instalando el paquete password_strength que nos ayudará con las validaciones del password.
# pip install password-strength
ACTUALIZACIÓN DE LA ESTRUCTURA DE LA APP
app # paquete app |-> main.py # archivo principal del app |-> menu.py # funciones para los menús del app |-> validators.py # funciones para validar el email y password
En el directorio principal debemos agregar un nuevo archivo llamado validators.py . Acá nos encargaremos de validar el formato del email y la fortaleza y características del password.
DESARROLLANDO EL VALIDATOR
En el archivo validator.py se crea un clase para el manejo de las excepciones y dos funciones para validar el email y password.
En el archivo validator.py se crea un clase para el manejo de las excepciones y dos funciones para validar el email y password.
# -*- coding: utf-8 -*- import re from password_strength import PasswordStats PASSWORD_STRENGTH = 0.3 PASSWORD_LENGTH = 8 PASSWORD_NUMBERS = 1 PASSWORD_UPPERCASE = 1 PASSWORD_SPECIAL = 1 class ValidationError(Exception): message = "Ha ocurrido un error en la validación" def __init__(self, message=None): Exception.__init__(self) if message is not None: self.message = message self.error_response() def error_response(self): return {"message": self.message} def validar_email(email): if not re.match('^[(a-z0-9\_\-\.)]+@[(a-z0-9\_\-\.)]+\.[(a-z)]{2,15}$', email.lower()): raise ValidationError("email: El formato del email no es válido") return email def validar_password(password1, password2): if not password1 == password2: raise ValidationError("password: Las contraseñas no coinciden") errors = [] # password strength. Value range [0 : 1] if PasswordStats(password1).strength() < PASSWORD_STRENGTH: errors.append('Fortaleza: La contraseña es muy simple.') # Min length: 8 if PasswordStats(password1).length < PASSWORD_LENGTH: errors.append(f'Tamaño: La contraseña debe tener al menos {PASSWORD_LENGTH} caracteres.') # Need min. 1 number if PasswordStats(password1).numbers < PASSWORD_NUMBERS: errors.append(f'Numeros: La contraseña debe tener al menos {PASSWORD_NUMBERS} número.') # Need min. 1 uppercase letters if PasswordStats(password1).letters_uppercase < PASSWORD_UPPERCASE: errors.append(f'Mayúscula: La contraseña debe tener al menos {PASSWORD_UPPERCASE} mayúscula.') # Need min. 1 special characters if PasswordStats(password1).special_characters < PASSWORD_SPECIAL: errors.append(f'Especial: La contraseña debe tener al menos {PASSWORD_SPECIAL} caracater especial.') if errors: raise ValidationError(errors)
Acá se puede observar:
- Al inicio se hacen dos importaciones import re y el módulo PasswordStats del paquete password_strength. El primer se utiliza para explorar una variedad de caracteres dentro de una cadena de caracter; es muy útil cuando se busca coincidencias de una palabra o letra dentro de un texto. El segundo se usa para verificar ciertas características de un string, en este caso el password.
- Posteriormente se crean una variables que inicia con el prefijo PASSWORD. Estas son las condiciones que queremos darle a nuestro password, por ejemplo su fortaleza, tamaño, si debe llevar números, letra en mayúscula, caracter especial y cuantos de cada uno de ellos. La fortaleza debe ser un valor entre 0 a 1; para esta ocasión he colocado 0.3.
- Mas abajo se encuentra la clase ValidationError para manejar la excepciones que se generarán de las validaciones. Esta clase hereda las propiedades y métodos de la clase Exception. Esta clase al ser invocada recibe como argumento el texto que explica el error ocurrido.
- Luego encontramos la función validar_email la cual recibe como argumento el email ingresado por el usuario. Esa información es pasado por el método re.match la cual verifica si el email contiene el arroba (@) y el punto (.) en él. Esta validación es simple, en la web se pueden conseguir otras formas de validar correos electrónicos, sin embargo con esta verificación es suficiente para nosotros. Si el email no cumple con el formato se lanza la excepción y se le pasa el mensaje a mostrar.
- Finalmente tenemos la función validar_password que recibe las dos contraseña ingresadas por el usuario. En esta función se verifica que las contraseñas coincida (anteriormente estaba en el main.py), así como también las características de fortaleza, tamaño cantidad de números, mayúsculas y caracteres especiales. Para mostrar los errores de estas características se crea una lista y se van agregando cada error en él si lo hubiese, de esta forma se muestran todos los errores que se cometieron al ingresar el password.
ACTUALIZACIÓN DEL MENU Y MAIN
Para integrar la validación al sistema es necesario actualizar los archivos menu.py y main.py. Veamos primero el main:
if opcion == "1": ''' Sección para el registro de usuario ''' data = menu.register() if "username" in data: if data["username"] in username: print(f'Este username: <{data["username"]}> ya se encuentra registrado.') elif data["email"] in email: print(f'Este Email: <{data["email"]}> ya se encuentra registrado.') else: password_hashed = bcrypt.hashpw( data["password1"].encode('utf8'), bcrypt.gensalt() ) username.append(data["username"]) email.append(data["email"]) password.append(password_hashed) print ("Se ha registrado en el sistema.") else: print(f"\n{data}") input("\nPresione una tecla para continuar...") main()
Del main solo fue modificado la sección donde se procesa el registro. En ella se eliminó la verificación de coincidencia de password1 y password2 (ver codigo del capítulo anterior) ya que ahora ésto se hace en la función de validar_password en el archivo validators.py. Ademas se agregó un nivel en el condifcional, noten que antes de verificar si data["username"] esta en la lista username hay un if que pregunta si el string username se encuentra en el diccionario data. Se hace esto debido que si se retorna un error desde el método register no procese ese código sino el que se encuentra en else el cual imprime el error ocurrido.
El archivo menu.py sufre varias modificaciones. Para verlos sólo mostraré las secciones que cambian.
# -*- coding: utf-8 -*- import os from validators import ValidationError, validar_email, validar_password
Lo primero que se agrega es la importación de las funciones para validar el email y passowrd y la clase de la excepción. Esto es necesario para poder usarlos dentro del archivo menu.py. El otro cambio se hace en el método register de la clase MenuTemplate. Veámoslo:
def register(self): self.clean_screen() self.head() try: username = input("Ingrese username: ") email = validar_email(input("Ingrese email: ")) password1 = input("Ingrese password: ") password2 = input("Repita el password: ") validar_password(password1, password2) except ValidationError as e: return e.message return { "username": username, "email": email, "password1": password1, "password2": password2, }
En esta sección se agrega un bloque try - exception en el ingreso de los datos, con el propósito de capturar la excepción s se encuentra un error en la validaciones. La validaciones las encontramos:
- Cuando se solicita el email se coloca email = validar_email(input("Ingrese email: ")). Pues resulta que con esto se verifica el formato del email, si es correcto se guarda en la variable el dato ingresado, sino se levanta la excepción.
- Después que se ingresan las dos contraseñas se valida el password, la que, de igual forma, valida la información y si hay un error se dispara la excepción.
Si ocurre un error de validación entramos en el bloque se exception en la que retornamos el error en cuestión.
Con esto hemos concluido este capítulo y con la Parte 1 del Proyecto. Ahora iniciaremos la Parte 2 la cual permitirá almacenar la información en una base de datos.
0 comentarios:
Publicar un comentario