예제 #1
0
def login(data):
    """
    Endpoint para iniciar la sesión con las credenciales de un usuario ya
    registrado. Debe cumplir los requisitos de :ref:`error_validacion`.

    :param email: Dirección de correo electrónico
    :type email: ``str``
    :param password: Contraseña
    :type password: ``str``

    :return: Un token de acceso en el campo ``access_token``, o un error de
        validación.
    """

    email = data.get("email")
    password = data.get("password")

    # Comprobamos si existe un usuario con ese email
    user = db.session.query(User).get(email)
    db.session.commit()
    if user is None:
        return msg_err("El usuario no existe")

    # Comprobamos si los hashes coinciden
    if not user.check_password(password):
        return msg_err("Contraseña incorrecta")

    access_token = create_access_token(identity=email)
    logger.info(f"User {user.name} has logged in")
    return {"access_token": access_token}
예제 #2
0
def signup(data):
    """
    Endpoint de registro de un usuario. Los parámetros deben cumplir las reglas
    de validación establecidas en :meth:`gatovid.models.User`.

    :param email: Dirección de correo electrónico
    :type email: ``str``
    :param name: Nombre del usuario
    :type name: ``str``
    :param password: Contraseña del usuario
    :type password: ``str``

    :return: Un objeto JSON con el nombre y correo del usuario registrado, como
        forma de verificación de la operación, o un error de validación.
    """

    try:
        user = User(
            email=data.get("email"),
            name=data.get("name"),
            password=data.get("password"),
        )
        initial_stats = Stats(user_id=user.email)
        initial_purchases = [
            Purchase(user_id=user.email, item_id=0,
                     type=PurchasableType.BOARD),
            Purchase(user_id=user.email,
                     item_id=0,
                     type=PurchasableType.PROFILE_PIC),
        ]
    except InvalidModelException as e:
        return msg_err(e)

    try:
        db.session.add(user)
        db.session.commit()
    except IntegrityError as e:
        if isinstance(e.orig, UniqueViolation):
            db.session.rollback()
            return msg_err("Email o nombre ya en uso")
        else:
            raise

    # Cuando el usuario ya existe se le puede añadir la tabla de estadísticas y
    # demás relaciones.
    db.session.add(initial_stats)
    for purchase in initial_purchases:
        db.session.add(purchase)
    db.session.commit()

    logger.info(f"User {user.name} has signed up")

    return {
        "user": {
            "email": user.email,
            "name": user.name,
        },
    }
예제 #3
0
def modify_user(data):
    """
    Endpoint autenticado de modificación del usuario, al cual se le pasan
    aquellos campos a cambiar, todos siendo opcionales. Los parámetros deben
    cumplir las reglas de validación establecidas en
    :meth:`gatovid.models.User`.

    No hace falta pasar el email porque al estar protegido se puede obtener a
    partir del token. De esta forma se asegura que no se modifican los perfiles
    de otros usuarios.

    :param name: Nombre nuevo del usuario
    :type name: ``Optional[str]``
    :param password: Contraseña nueva del usuario
    :type password: ``Optional[str]``
    :param board: El identificador del nuevo tapete del usuario
    :type board: ``Optional[int]``
    :param picture: El identificador de la nueva foto del usuario
    :type picture: ``Optional[int]``

    :return: Un mensaje descriptivo de la operación realizada correctamente, o
        un mensaje de error interno en caso contrario. Se considera un error el no
        indicar ninguno de los parámetros opcionales anteriores.
    """

    email = get_jwt_identity()
    user = db.session.query(User).get(email)

    modified = False
    for field in ("name", "password", "board", "picture"):
        new_val = data.get(field)
        if new_val is None:
            continue

        try:
            setattr(user, field, new_val)
        except InvalidModelException as e:
            return msg_err(e)

        modified = True

    if not modified:
        return msg_err("Ningún campo a modificar")

    try:
        db.session.commit()
    except IntegrityError as e:
        if isinstance(e.orig, UniqueViolation):
            db.session.rollback()
            return msg_err("Nombre ya en uso")

    logger.info(f"User {user.name} has modified their profile")
    return msg_ok("Usuario modificado con éxito")
예제 #4
0
def user_stats(data):
    """
    Endpoint para acceder a las estadísticas de un usuario, dado su nombre.

    :param name: Nombre del usuario
    :type name: ``str``

    :return: Un objeto JSON con los campos ``games``, ``losses``, ``wins`` y
        ``playtime_mins``, todos enteros.
    """

    name = data.get("name")
    user = db.session.query(User).filter_by(name=name).first()
    db.session.commit()
    if user is None:
        return msg_err("El usuario no existe")

    stats = user.stats

    logger.info(f"User {name} has been accessed to their stats")
    return {
        "games": stats.games,
        "losses": stats.losses,
        "wins": stats.wins,
        "playtime_mins": stats.playtime_mins,
    }
예제 #5
0
def shop_buy(data):
    """
    Endpoint para comprar un objeto en la tienda.

    :param id: Identificador del objeto
    :type id: ``int``
    :param type: Tipo del objeto ("board" | "profile_pic")
    :type type: ``str``

    :return: Un mensaje descriptivo de la operación realizada correctamente, o
        un mensaje de error interno en caso contrario.
    """

    email = get_jwt_identity()
    user = db.session.query(User).get(email)

    item_id = data.get("id")
    item_type = data.get("type")

    try:
        purchase = Purchase(user_id=email, item_id=item_id, type=item_type)
    except InvalidModelException as e:
        return msg_err(e)

    price = purchase.get_price()
    if user.coins < price:
        return msg_err("No tienes suficientes patitas")

    user.coins -= price
    try:
        db.session.add(purchase)
        db.session.commit()
    except IntegrityError as e:
        if isinstance(e.orig, UniqueViolation):
            db.session.rollback()
            return msg_err("Objeto ya comprado")
        else:
            raise

    logger.info(f"User {user.name} has bought a shop item")
    return msg_ok("Objeto comprado con éxito")
예제 #6
0
def logout(data):
    """
    Endpoint autenticado para cerrar la sesión.

    :return: Un mensaje descriptivo de la operación realizada correctamente, o
        un mensaje de error interno en caso contrario.
    """

    logger.info(f"User {get_jwt_identity()} is logging out")
    if _revoke_token():
        return msg_ok("Sesión cerrada con éxito")
    else:
        return msg_err("No se pudo cerrar sesión", code=500)
예제 #7
0
def remove_user(data):
    """
    Endpoint autenticado de borrado de cuenta.

    Al borrar una cuenta se cierra también la sesión, garantizando que solo se
    podrá borrar una vez.

    :return: Un mensaje descriptivo de la operación realizada correctamente, o
        un mensaje de error interno en caso contrario.
    """

    email = get_jwt_identity()
    if not _revoke_token():
        return msg_err("No se pudo cerrar sesión")

    user = db.session.query(User).get(email)
    db.session.delete(user)
    db.session.commit()

    logger.info(f"User {user.name} has been removed")

    return msg_ok("Usuario eliminado con éxito")
예제 #8
0
 def revoked_token_callback(jwt_header, jwt_payload):
     return msg_err("Token de sesión revocado", code=401)
예제 #9
0
 def invalid_token_callback(reason):
     return msg_err("Token de sesión inválido", code=401)
예제 #10
0
 def expired_token_callback(jwt_header, jwt_payload):
     return msg_err("Token de sesión expirado", code=401)