Exemplo n.º 1
0
def crt_meal(username: str, data: RequestBodyType) -> Meal:
    """Create a meal

    :param username: Username of the user owner of the meal
    :param data: The data of the new meal
    :return: The newly created meal
    """
    user = _get_user(username)

    new_meal = _parse_meal(data)
    if not new_meal.calories:
        new_meal.calories = calories_from_nutritionix(new_meal.name)

    calories = get_daily_calories(user, new_meal.date)

    user.meals.append(new_meal)

    if user.daily_calories <= calories + new_meal.calories:
        new_meal.under_daily_total = False
        if calories < user.daily_calories:
            _update_meals(user, new_meal.date, False)
    else:
        new_meal.under_daily_total = True

    db.session.commit()

    return meal_schema.dump(new_meal)
Exemplo n.º 2
0
def updt_meal(username: str, meal_id: int, data: RequestBodyType) -> Meal:
    """Update a meal

    :param username: Username of the user whose meal is going to be updated
    :param meal_id: Id of the meal
    :param data: New data for the meal
    :return: The updated meal
    """
    old_meal = _get_meal(username, meal_id)
    user = _get_user(username)

    new_meal = _parse_meal(data)
    new_meal.user_id = old_meal.user_id
    new_meal.id = old_meal.id

    # Get calories from nutrtionix if the meal has changed but the user didn't provide its calories
    if new_meal.name and new_meal.name != old_meal.name and not new_meal.calories:
        new_meal.calories = calories_from_nutritionix(new_meal.name)

    if new_meal.date:
        # Meal has changed date so we need to update under_daily_total for both dates

        # Update under_daily_limit for old date
        calories = get_daily_calories(user, old_meal.date)
        if calories >= user.daily_calories > calories - old_meal.calories:
            _update_meals(user, old_meal.date, True)

        # Update under_daily_limit for new date
        new_calories = new_meal.calories or old_meal.calories
        calories_new_date = get_daily_calories(user, new_meal.date)
        if user.daily_calories <= calories_new_date + new_calories:
            # New date is over daily limit
            new_meal.under_daily_total = False
            if calories < user.daily_calories:  # New date was under daily limit before
                _update_meals(user, new_meal.date, False)
        else:  # New date will be still under daily limit
            new_meal.under_daily_total = True
    elif new_meal.calories and new_meal.calories != old_meal.calories:
        # Calories have changed but its the same date
        difference = new_meal.calories - old_meal.calories
        calories = get_daily_calories(user, old_meal.date)
        # Change in calories made a difference
        if (user.daily_calories > calories) != (
                user.daily_calories > calories + difference
        ):
            _update_meals(
                user, new_meal.date, user.daily_calories > calories + difference
            )
            new_meal.under_daily_total = user.daily_calories > calories + difference

    db.session.merge(new_meal)
    db.session.commit()

    return meal_schema.dump(old_meal)
Exemplo n.º 3
0
def dlt_meals(username: str, meal_id: int) -> None:
    """Delete the selected meal from the database

    :param username: Username whose meal is going to be deleted
    :param meal_id: Id of the meal that is going to be deleted
    """
    d_user = _get_user(username)
    meal = _get_meal(username, meal_id)

    # Update under_daily_total for the day if necessary
    calories = get_daily_calories(d_user, meal.date)
    if calories >= d_user.daily_calories > calories - meal.calories:
        _update_meals(d_user, meal.date, True)

    db.session.delete(meal)
    db.session.commit()
Exemplo n.º 4
0
        def wrapped(*args, **kwargs):
            nonlocal roles_allowed
            if roles_allowed is None:
                roles_allowed = []

            user = _get_user(kwargs["user"])

            # Admin can do everything
            if user.role == Role.ADMIN:
                logger.info(
                    f"User '{user.username}' with role '{user.role}' succesfully "
                    f"called '{func.__name__}' with args='{args}' and kwargs="
                    f"'{kwargs}'")
                return func(*args, **kwargs)

            if only_allow_self:
                if user.role not in roles_allowed:
                    abort(
                        403,
                        f"User '{kwargs['user']}' belongs to the role '{user.role}' "
                        f"and is not allowed to perform the action",
                    )
                if user.username != kwargs.get("username", user.username):
                    abort(
                        403,
                        f"User '{kwargs['user']}' cannot perform the action for other"
                        f" user",
                    )
                logger.info(
                    f"User '{user.username}' with role '{user.role}' succesfully "
                    f"called '{func.__name__}' with args='{args}' and kwargs="
                    f"'{kwargs}'")
                return func(*args, **kwargs)

            if user.role in roles_allowed or (allow_self and user.username
                                              == kwargs.get("username", None)):
                logger.info(
                    f"User '{user.username}' with role '{user.role}' succesfully "
                    f"called '{func.__name__}' with args='{args}' and "
                    f"kwargs='{kwargs}'")
                return func(*args, **kwargs)
            else:
                abort(
                    403,
                    f"User '{kwargs['user']}' belongs to the role '{user.role}' and"
                    f" is not allowed to perform the action",
                )
Exemplo n.º 5
0
def get_token(username: str, password: str) -> str:
    """Create a token

    :param username: Username of the user that requests the token
    :type username: str
    :param password: Password  of the user that requests the token
    :type password: str
    :return: The token
    :rtype: str
    :raises Unauthorized: If the password is wrong
    """
    try:
        user = _get_user(username)
        if not check_password_hash(user.password, password):
            raise Unauthorized(f"Invalid username/password")
    except RequestError:
        raise Unauthorized(f"Invalid username/password")

    return encode_token(user.username)
Exemplo n.º 6
0
def _get_meal(username: str, meal_id: int) -> Meal:
    """Get the specified meal from the database or abort with a 404 error if either the user or the meal don't exist

    :param username: Username that the meal belongs to
    :param meal_id: Meal id
    :return: The database object for the meal
    :raises NotFound: If the user is not on the database
    """
    user = _get_user(username)
    meal = (
        Meal.query.join(User, User.id == Meal.user_id)
            .filter(User.username == user.username, Meal.id == meal_id)
            .one_or_none()
    )

    if meal is None:
        raise NotFound(f"Meal '{meal_id}' not found")

    return meal
Exemplo n.º 7
0
def get_meals(
        username: str, filter_str: str, items_per_page: int, page_number: int
) -> ...:
    """Get the list of meals for the specified user from the database

    :param username: Username of the user whose meals we need to get
    :param filter_str: Filter string for the result
    :param items_per_page: Number of items per page
    :param page_number: Page requested
    :return: The list of the users filtered and paginated
    """
    r_user = _get_user(username)

    meals = Meal.query.join(User, User.id == Meal.user_id).filter(
        User.username == r_user.username
    )
    meals, pagination = apply_filter(meals, filter_str, items_per_page, page_number)
    data = meals_schema.dump(meals)

    return data, pagination