def create_meal(user: str, username: str, body: RequestBodyType) -> ResponseType: """Create a meal :param user: User that requests the action :param username: User whose meal is going to be created :param body: Information about the new meal :return: A success message if the meal was found or a 400 error if any parameter was wrong """ try: data = crt_meal(username, body) except RequestError as e: data = None logger.warning(e.message) abort(e.code, e.message) logger.info( f"User: '******' created meal: '{data.get('id')}' for user: '******'" ) return ( { "status": 201, "title": "Success", "detail": f"Meal: '{data.get('id')}' of user: '******' " f"succesfully created", "data": data, }, 201, )
def read_meal(user: str, username: str, meal_id: int) -> ResponseType: """Read a meal that belongs to a user :param user: The user that requests the action :param username: Username to read his meal :param meal_id: Id of the meal """ try: data = get_meal(username, meal_id) except RequestError as e: data = None logger.warning(e.message) abort(e.code, e.message) logger.info( f"User: '******' read meal: '{meal_id}' of user: '******'") return ( { "status": 200, "title": "Success", "detail": f"Meal: '{meal_id}' of user: '******' succesfully read", "data": data, }, 200, )
def delete_meal(user: str, username: str, meal_id: int) -> ResponseType: """Delete a meal :param user: User that requests the action :param username: User whose meal is going to be deleted :param meal_id: Meal id to delete :return: A success message if the meal was found or a 404 error if either the user or the meal does not exist """ try: dlt_meals(username, meal_id) except RequestError as e: logger.warning(e.message) abort(e.code, e.message) logger.info( f"User: '******' deleted meal: '{meal_id}' for user: '******'") return ( { "status": 200, "title": "Success", "detail": f"Meal: '{meal_id}' of user: '******' succesfully deleted", "data": None, }, 200, )
def update_meal(user: str, username: str, meal_id: int, body: RequestBodyType) -> ResponseType: """Update a meal :param user: User that requests the action :param username: User whose meal is going to be updated :param meal_id: Meal id to update :param body: New body of the updated meal :return: A success message if the meal was found or a 404 error if either the user or the meal does not exist """ try: data = updt_meal(username, meal_id, body) except RequestError as e: data = None logger.warning(e.message) abort(e.code, e.message) logger.info( f"User: '******' updated meal: '{meal_id}' for user: '******'") return ( { "status": 200, "title": "Success", "detail": f"Meal: '{meal_id}' of user: '******' succesfully updated", "data": data, }, 200, )
def calories_from_nutritionix(meal: str) -> int: """Query Nutritionix API to get the calories information of a meal :param meal: Name of the meal :return: The calories of the specified meal """ auth = {"appId": cfg.NTX_APP_ID, "appKey": cfg.NTX_API_KEY} try: food_info = requests.get( "/".join([cfg.NTX_BASE_URL, "search", meal]), params={ **auth, "results": "0:1" }, ).json() except (requests.RequestException, ValueError) as e: logger.warning( f"Exception happened while trying to get calories for '{meal}': {e} " ) return 0 if not food_info.get("total_hits", None): return 0 try: meal_id = food_info["hits"][0]["fields"]["item_id"] except LookupError as e: logger.warning( f"Exception happened while trying to get calories for '{meal}': {e} " ) return 0 try: food_info = requests.get("/".join([cfg.NTX_BASE_URL, "item"]), params={ **auth, "id": meal_id }).json() except (requests.RequestException, ValueError) as e: logger.warning( f"Exception happened while trying to get calories for '{meal}': {e} " ) return 0 logger.info( f"Successfully read calories from Nutrionix API for meal: '{meal}'") return food_info.get("nf_calories", 0)
def read_meals( user: str, username: str, filter_results: str = None, items_per_page: int = 10, page_number: int = 1, ) -> ResponseType: """Read the list of meals for a given user :param user: The user that requests the action :param username: User to return al his meals :param filter_results: Filter string for the results :param items_per_page: Number of items of every page, defaults to 10 :param page_number: Page number of the results defaults to 1 """ try: data, pagination = get_meals(username, filter_results, items_per_page, page_number) except RequestError as e: data = pagination = None logger.warning(e.message) abort(e.code, e.message) logger.info( f"User: '******', read meals for user: '******'," f" filter: '{filter_results}', itemsPerPage: '{items_per_page}'," f" pageNumber: '{page_number}'") return ( { "status": 200, "title": "Success", "detail": f"List of meals succesfully read for user: '******'", "data": data, "num_pages": pagination.num_pages, "total_result": pagination.total_results, }, 200, )
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", )