Example #1
0
def put_meals(list_id):
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if not isinstance(req, list):
        raise APIError("A list of meals is required")
    list_ = List.query.filter_by(id=list_id).first()
    meals = Meal.query.filter_by(list_id=list_.id).all()
    # verify integrity of received list
    verify_meals(req, meals)
    for meal in meals:
        if meal.id not in [i["id"] for i in req if "id" in i]:
            db.session.delete(meal)
    db.session.commit()
    meals = Meal.query.filter_by(list_id=list_.id).all()
    for index, req_meal in enumerate(req):
        if "id" in req_meal and req_meal["id"] in [i.id for i in meals]:
            meals_index = [i.id for i in meals].index(req_meal["id"])
            meals[meals_index].order = index
            meals[meals_index].name = req_meal["name"]
        else:
            new_meal = Meal(
                list_id=list_.id, name=req_meal["name"], order=index
            )
            db.session.add(new_meal)
    db.session.commit()
    json_obj = [meal.to_dict() for meal in list_.get_or_create_meals()]
    return jsonify(json_obj)
Example #2
0
def register():
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    verify_mandatory_user_fields(req)
    if "password" not in req:
        raise APIError("password is required")
    if User.query.filter_by(username=req["username"]).first():
        raise APIError("Username already taken")
    if User.query.filter_by(email=req["email"]).first():
        raise APIError("Email already taken")
    if len(req["password"]) < 8:
        raise APIError(
            "Password is too short, please use 8 characters or more")
    u = User(
        username=req["username"],
        email=req["email"],
        firstname=req["firstname"],
        lastname=req["lastname"],
        is_confirmed=False,
    )
    u.set_password(req["password"])
    db.session.add(u)
    db.session.commit()
    # TODO confirm email
    # token = generate_confirmation_token(u.email)
    # confirm_url = url_for('auth.confirm_email', token=token, _external=True)
    # send_user_confirmation_email(u, confirm_url)
    login_user(u)
    return jsonify({"msg": "Registered successfully", **u.to_dict()}), 201
Example #3
0
 def decorated_function(*args, **kwargs):
     list_id = kwargs["list_id"]
     list_ = List.query.filter_by(id=list_id).first()
     if not list_:
         raise APIError(f"No list with id {list_id}", 404)
     if current_user not in list_.get_users_with_access():
         raise APIError("You don't have access to this page", 403)
     return func(*args, **kwargs)
Example #4
0
 def decorated_function(*args, **kwargs):
     list_id = kwargs["list_id"]
     list_ = List.query.filter_by(id=list_id).first()
     if not list_:
         raise APIError(f"No list with id {list_id}", 404)
     if current_user not in list_.get_owners():
         raise APIError("Only the list owner can perform this action", 403)
     return func(*args, **kwargs)
Example #5
0
 def decorated_function(*args, **kwargs):
     entry_id = kwargs["entry_id"]
     entry = Entry.query.filter_by(id=entry_id).first()
     if not entry:
         raise APIError(f"No entry with id {entry_id}", 404)
     list_ = entry.day.list_
     if current_user not in list_.get_users_with_access():
         raise APIError("You don't have access to this page", 403)
     return func(*args, **kwargs)
Example #6
0
def verify_meals(req, meals):
    for meal in req:
        if "id" in meal:
            if meal["id"] not in [i.id for i in meals]:
                raise APIError(
                    "ID assignment not allowed, only include pre-existing IDs"
                )
            if "name" not in meal:
                raise APIError(f"No name received in {meal}")
Example #7
0
def verify_mandatory_user_fields(req):
    if "username" not in req:
        raise APIError("username is required")
    if "email" not in req:
        raise APIError("email is required")
    if "firstname" not in req:
        raise APIError("firstname is required")
    if "lastname" not in req:
        raise APIError("lastname is required")
Example #8
0
def delete_user(user_id):
    user_ = User.query.filter_by(id=user_id).first()
    if not user_:
        raise APIError(f"No user with id {user_id}", 404)
    if user_ != current_user:
        raise APIError("You cannot delete another user", 403)
    db.session.delete(user_)
    db.session.commit()
    logout_user()
    return jsonify({"msg": "User deleted"}), 401
Example #9
0
def extract_args(args):
    offset = int(args.get("offset")) if "offset" in args else 0
    if (offset and offset > 5000) or (offset and offset < -5000):
        raise APIError("Offset needs to be within -5000 and 5000")
    limit = int(args.get("limit")) if "limit" in args else None
    if limit and limit > 25:
        raise APIError("Limit cannot be over 25")
    start_today = (
        bool(args.get("start_today")) if "start_today" in args else False
    )
    return dict(offset=offset, limit=limit, start_today=start_today)
Example #10
0
def login():
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "username" not in req:
        raise APIError("username is required")
    if "password" not in req:
        raise APIError("password is required")
    u = User.query.filter_by(username=req["username"]).first()
    if u is None or not u.check_password(req["password"]):
        raise APIError("Invalid username or password!", 401)
    login_user(u)
    return jsonify({"msg": "Logged in successfully", **u.to_dict()}), 200
Example #11
0
def post_foods(list_id):
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "name" not in req:
        raise APIError("name is required")
    list_ = List.query.filter_by(id=list_id).first()
    if Food.query.filter_by(name=req["name"], list_id=list_.id).first():
        raise APIError(f'Food {req["name"]} already exists')
    food = Food(list_id=list_.id, name=req["name"])
    db.session.add(food)
    db.session.commit()
    json_obj = [food.to_dict() for food in list_.foods]
    return jsonify(json_obj), 201
Example #12
0
def post_categories(list_id):
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "name" not in req:
        raise APIError("name is required")
    list_ = List.query.filter_by(id=list_id).first()
    if req["name"] in [i.name for i in list_.categories]:
        raise APIError(f'FoodCategory {req["name"]} already exists')
    foodcategory = FoodCategory(name=req["name"], list_id=list_id)
    db.session.add(foodcategory)
    db.session.commit()
    json_obj = [category.to_dict() for category in list_.categories]
    return jsonify(json_obj), 201
Example #13
0
def patch_meals(list_id, meal_id):
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "name" not in req:
        raise APIError("name is required")
    list_ = List.query.filter_by(id=list_id).first()
    meal = Meal.query.filter_by(list_id=list_.id, id=meal_id).first()
    if not meal:
        raise APIError(f"No meal with id {meal_id} exists", 404)
    meal.name = req["name"]
    db.session.commit()
    json_obj = [meal.to_dict() for meal in list_.get_or_create_meals()]
    return jsonify(json_obj), 200
Example #14
0
def delete_category(food_id, category_id):
    food = Food.query.filter_by(id=food_id).first()
    if not food:
        raise APIError(f"No food with id {food_id} exists", 404)
    category = FoodCategory.query.filter_by(id=category_id).first()
    if not category:
        raise APIError(f"No category with id {category_id} exists", 404)
    if category.id not in [i.category.id for i in food.categories]:
        raise APIError(
            f"Category {category_id} does not belong to Food {food_id}")
    category_association = FoodCategoryAssociation.query.filter_by(
        food_id=food.id, category_id=category.id).first()
    db.session.delete(category_association)
    db.session.commit()
    json_obj = [category.category.to_dict() for category in food.categories]
    return jsonify(json_obj)
Example #15
0
def user():
    if current_user.is_authenticated:
        return (
            jsonify({"msg": "Session still valid", **current_user.to_dict()}),
            200,
        )
    raise APIError("Please log in", 401)
Example #16
0
def post_category_association(food_id, category_id):
    food = Food.query.filter_by(id=food_id).first()
    if not food:
        raise APIError(f"No food with id {food_id} exists", 404)
    category = FoodCategory.query.filter_by(id=category_id).first()
    if not category:
        raise APIError(f"No food with id {category_id} exists", 404)
    if category.id in [i.category.id for i in food.categories]:
        raise APIError(
            f"Category {category_id} is already linked to food {food_id}")
    foodcategoryassociation = FoodCategoryAssociation(food_id=food.id,
                                                      category_id=category.id)
    db.session.add(foodcategoryassociation)
    db.session.commit()
    json_obj = [category.category.to_dict() for category in food.categories]
    return jsonify(json_obj)
Example #17
0
def delete_category_by_list(list_id, category_id):
    list_ = List.query.filter_by(id=list_id).first()
    category = FoodCategory.query.filter_by(id=category_id).first()
    if not category:
        raise APIError(f"No category with id {category_id} exists", 404)
    db.session.delete(category)
    db.session.commit()
    json_obj = [category.to_dict() for category in list_.categories]
    return jsonify(json_obj), 200
Example #18
0
def patch_entry(entry_id):
    # TODO functionize -> get_json -> check that there is content (or raise)
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    entry = Entry.query.filter_by(id=entry_id).first_or_404()
    entry.value = req["value"]
    db.session.commit()
    return jsonify(entry.to_dict()), 200
Example #19
0
def delete_share(list_id, share_id):
    list_ = List.query.filter_by(id=list_id).first()
    share = ListPermission.query.filter_by(id=share_id,
                                           list_id=list_id).first()
    if not share:
        raise APIError(f"Share with id {share_id} not found", 404)
    db.session.delete(share)
    db.session.commit()
    return jsonify([i.to_dict() for i in list_.users]), 200
Example #20
0
def delete_meal(list_id, meal_id):
    list_ = List.query.filter_by(id=list_id).first()
    meal = Meal.query.filter_by(list_id=list_.id, id=meal_id).first()
    if not meal:
        raise APIError(f"No meal with id {meal_id} exists", 404)
    db.session.delete(meal)
    db.session.commit()
    json_obj = [meal.to_dict() for meal in list_.get_or_create_meals()]
    return jsonify(json_obj), 200
Example #21
0
def post_list():
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "listname" not in req:
        raise APIError("listname is required")
    if req["listname"] == "":
        raise APIError("Listname cannot be empty")
    list_ = List(name=req["listname"])
    list_.generate_api_key()
    db.session.add(list_)
    db.session.commit()
    perm = ListPermission(list_id=list_.id,
                          user_id=current_user.id,
                          permission_level="owner")
    db.session.add(perm)
    db.session.commit()
    return jsonify(list_.to_dict()), 201
Example #22
0
def delete_food(list_id, food_id):
    list_ = List.query.filter_by(id=list_id).first()
    food = Food.query.filter_by(list_id=list_.id, id=food_id).first()
    if not food:
        raise APIError(f"No meal with id {food_id} exists", 404)
    db.session.delete(food)
    db.session.commit()
    json_obj = [food.to_dict() for food in list_.foods]
    return jsonify(json_obj), 200
Example #23
0
def put_food(list_id, food_id):
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "name" not in req:
        raise APIError("name is required")
    if "categories" not in req:
        raise APIError("categories is required")
    list_ = List.query.filter_by(id=list_id).first()
    food = Food.query.filter_by(list_id=list_.id, id=food_id).first()
    if not food:
        raise APIError(f"No food with id {food_id} exists", 404)
    food.name = req["name"]
    categories_to_associate = [
        i for i in list_.categories if i.name in req["categories"]
    ]
    categories_to_disassociate = [
        i for i in list_.categories if i.name not in req["categories"]
    ]
    categories_to_add = [
        i for i in req["categories"]
        if i not in [i.name for i in categories_to_associate]
    ]
    for category in categories_to_add:
        fc = FoodCategory(list_id=list_.id, name=category)
        db.session.add(fc)
        db.session.commit()
        fca = FoodCategoryAssociation(category_id=fc.id, food_id=food.id)
        db.session.add(fca)
        db.session.commit()
    for category in categories_to_associate:
        if category.id not in [i.category.id for i in food.categories]:
            fca = FoodCategoryAssociation(category_id=category.id,
                                          food_id=food.id)
            db.session.add(fca)
    for category in categories_to_disassociate:
        if category in [i.category for i in food.categories]:
            fca = FoodCategoryAssociation.query.filter_by(
                category_id=category.id, food_id=food.id).first()
            db.session.delete(fca)
    db.session.commit()
    json_obj = [food.to_dict() for food in list_.foods]
    return jsonify(json_obj)
Example #24
0
def post_list_shares(list_id):
    list_ = List.query.filter_by(id=list_id).first()
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "username" not in req:
        raise APIError("Username is required")
    user_ = User.query.filter_by(username=req["username"]).first()
    if not user_:
        raise APIError(f"User {req['username']} does not exist", 404)
    if user_ in list_.get_users_with_access():
        raise APIError(
            f"User {req['username']} already has access to this list")
    new_perm = ListPermission(user_id=user_.id,
                              list_id=list_.id,
                              permission_level="member")
    db.session.add(new_perm)
    db.session.commit()
    return jsonify([i.to_dict() for i in list_.users]), 201
Example #25
0
def post_meals(list_id):
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    if "name" not in req:
        raise APIError("name is required")
    list_ = List.query.filter_by(id=list_id).first()
    if Meal.query.filter_by(name=req["name"], list_id=list_.id).first():
        raise APIError(f'Meal {req["name"]} already exists')
    try:
        order = 1 + max(
            [i.order for i in Meal.query.filter_by(list_id=list_.id).all()]
        )
    except ValueError:
        order = 1
    meal = Meal(list_id=list_.id, name=req["name"], order=order)
    db.session.add(meal)
    db.session.commit()
    json_obj = [meal.to_dict() for meal in list_.get_or_create_meals()]
    return jsonify(json_obj), 201
Example #26
0
def put_list_settings(list_id):
    args = extract_args(request.args)

    req = request.get_json()
    if not req:
        raise APIError("application/json is required")

    list_ = List.query.filter_by(id=list_id).first()
    settings = list_.get_settings_for_user(current_user)

    if "start_day_of_week" not in req:
        raise APIError("start_day_of_week is required")
    if "days_to_display" not in req:
        raise APIError("days_to_display is required")

    # handle days_to_display
    days_to_display = int(req["days_to_display"])
    if days_to_display < 5 or days_to_display > 21:
        raise APIError("days_to_display needs to be a number between 5-21")

    # handle start_day_of_week
    allowed_days = list(calendar.day_name)
    allowed_days.append("Today")
    start_day_of_week = req["start_day_of_week"]
    if start_day_of_week not in allowed_days:
        raise APIError(
            f'start_day_of_week needs to be one of:  {" ".join(allowed_days)}')
    if start_day_of_week == "Today":
        start_day_of_week = -1
    else:
        start_day_of_week = allowed_days.index(start_day_of_week)

    # set and commit
    settings.start_day_of_week = start_day_of_week
    settings.days_to_display = days_to_display
    db.session.commit()

    return jsonify(
        [list_.to_dict(args["offset"], args["limit"], args["start_today"])])
Example #27
0
def patch_list(list_id):
    args = extract_args(request.args)
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    list_ = List.query.filter_by(id=list_id).first()
    if "listname" in req:
        list_.name = req["listname"]
    db.session.commit()
    return (
        jsonify([
            list_.to_dict(args["offset"], args["limit"], args["start_today"])
        ]),
        200,
    )
Example #28
0
def put_users(user_id):
    req = request.get_json()
    if not req:
        raise APIError("application/json is required")
    user_ = User.query.filter_by(id=user_id).first()
    if not user_:
        raise APIError(f"User with id {user_id} not found", 404)
    if not user_ == current_user:
        raise APIError("Insufficient permissions", 403)
    verify_mandatory_user_fields(req)
    if "password" in req and req["password"] != "":
        if len(req["password"]) < 8:
            raise APIError(
                "Password is too short, please use 8 characters or more")
        else:
            current_user.set_password(req["password"])
    if req["username"] != current_user.username:
        if User.query.filter_by(username=req["username"]).first():
            raise APIError("Username already taken")
        current_user.username = req["username"]
    if req["email"] != current_user.email:
        if User.query.filter_by(email=req["email"]).first():
            raise APIError("Email already taken")
        current_user.email = req["email"]
    # TODO confirm email
    # token = generate_confirmation_token(u.email)
    # confirm_url = url_for('auth.confirm_email', token=token, _external=True)
    # send_user_confirmation_email(u, confirm_url)
    current_user.firstname = req["firstname"]
    current_user.lastname = req["lastname"]
    db.session.commit()
    return (
        jsonify({
            "msg": "User updated successfully",
            **current_user.to_dict()
        }),
        200,
    )
Example #29
0
 def decorated_function(*args, **kwargs):
     if not current_user.is_authenticated:
         raise APIError("Please log in", 401)
     return func(*args, **kwargs)
Example #30
0
def get_categories_by_food(food_id):
    food = Food.query.filter_by(id=food_id).first()
    if not food:
        raise APIError(f"No food with id {food_id} exists", 404)
    json_obj = [category.category.to_dict() for category in food.categories]
    return jsonify(json_obj)