Ejemplo n.º 1
0
def register():
    if not app.config["ALLOW_REGISTER"]:
        abort(404)
    if request.method == "GET":
        return render_template("accounts/register.html", form=RegisterForm())
    form = RegisterForm(request.form)
    if not form.validate():
        return render_template("accounts/register.html", form=form)
    if Account.is_username_taken(form.username.data):
        return render_template(
            "accounts/register.html",
            form=form,
            error="Username is already taken.",
        )
    password_hash = \
        bcrypt.generate_password_hash(form.password.data).decode("utf-8")
    account = Account(
        username=form.username.data,
        password_hash=password_hash,
        role="user",
    )
    db.session().add(account)
    db.session.commit()
    login_user(account)
    return redirect(url_for("index"))
Ejemplo n.º 2
0
def delete_my_account():
    if request.method == "GET":
        return redirect(url_for("my_account"))
    db.session().delete(
        Account.query.filter_by(id=current_user.id).first_or_404())
    logout_user()
    db.session().commit()
    return redirect(url_for("index"))
Ejemplo n.º 3
0
def delete_shopping_list_item(item_id: int):
    if request.method == "GET":
        return redirect(url_for("get_shopping_list"))
    delete_count = ShoppingListItem.query.filter_by(
        id=item_id,
        account_id=current_user.id,
    ).delete()
    db.session().flush()
    Ingredient.delete_unused_ingredients(current_user.id)
    db.session().commit()
    return redirect(url_for("get_shopping_list"))
Ejemplo n.º 4
0
def delete_recipe(recipe_id: int):
    if request.method == "GET":
        return redirect(url_for("get_recipe", recipe_id=recipe_id))
    Recipe.query.filter_by(
        id=recipe_id,
        account_id=current_user.id,
    ).delete()
    db.session().flush()
    Ingredient.delete_unused_ingredients(current_user.id)
    db.session().commit()
    return redirect(url_for("get_recipes"))
Ejemplo n.º 5
0
 def insert_if_missing(name, account_id):
     ingredient = Ingredient.query.filter(
         Ingredient.account_id == account_id,
         func.lower(Ingredient.name) == func.lower(name),
     ).first()
     if ingredient:
         return ingredient
     ingredient = Ingredient(name)
     ingredient.account_id = account_id
     db.session().add(ingredient)
     db.session().flush()
     return ingredient
Ejemplo n.º 6
0
    def delete_unused_ingredients(account_id):
        stmt = text("""
DELETE FROM ingredients
WHERE ingredients.id IN (
    SELECT i.id FROM ingredients i
    LEFT JOIN recipe_ingredient ri ON ri.ingredient_id = i.id
    LEFT JOIN shopping_list_items sli ON sli.ingredient_id = i.id
    WHERE
        i.account_id = :account_id
        AND ri.id IS NULL
        AND sli.id IS NULL
)""").params(account_id=account_id)
        db.session().execute(stmt)
Ejemplo n.º 7
0
def create_shopping_list_item():
    if request.method == "GET":
        return redirect(url_for("get_shopping_list"))
    form = RecipeIngredientForm(request.form)
    if not form.validate():
        return render_shopping_list(form, "new")
    item = ShoppingListItem()
    item.amount, item.amount_unit = form.parse_amount()
    item.account_id = current_user.id
    ingredient = Ingredient.insert_if_missing(form.name.data, current_user.id)
    item.ingredient_id = ingredient.id
    db.session().add(item)
    db.session().commit()
    return redirect(url_for("get_shopping_list"))
Ejemplo n.º 8
0
    def insert_ingredients_from_form(self, form):
        ingredients = []
        missing_ingredients = []
        ingredients_by_name = {}
        for recipe_ingredient_form in form.ingredient_amounts:
            name = recipe_ingredient_form.data["name"].strip()
            lower_name = name.lower()
            existing_ingredient = ingredients_by_name.get(lower_name)
            if not existing_ingredient:
                existing_ingredient = Ingredient.query.filter(
                    Ingredient.account_id == self.account_id,
                    func.lower(Ingredient.name) == lower_name,
                ).first()
                if not existing_ingredient:
                    existing_ingredient = Ingredient(name)
                    existing_ingredient.account_id = self.account_id
                    missing_ingredients.append(existing_ingredient)
                ingredients_by_name[lower_name] = existing_ingredient
            ingredients.append(existing_ingredient)
        db.session().bulk_save_objects(missing_ingredients, return_defaults=True)
        db.session().flush()

        recipe_ingredients = []
        for index, recipe_ingredient_form in enumerate(form.ingredient_amounts):
            amount, unit = recipe_ingredient_form.parse_amount()
            recipe_ingredients.append(RecipeIngredient(
                amount=amount,
                amount_unit=unit,
                ingredient_id=ingredients[index].id,
                recipe_id=self.id,
                group_name=recipe_ingredient_form.group.data,
            ))
        db.session().bulk_save_objects(recipe_ingredients)
        db.session().flush()
Ejemplo n.º 9
0
def change_password():
    if request.method == "GET":
        return redirect(url_for("my_account"))
    form = ChangePasswordForm()
    if not form.validate():
        return jsonify(error_messages=form.errors), 400
    if not bcrypt.check_password_hash(current_user.password_hash,
                                      form.current_password.data):
        return jsonify(error_messages={
            "current_password": ["Current password is incorrect"],
        }), 400
    current_user.password_hash = \
        bcrypt.generate_password_hash(form.new_password.data).decode("utf-8")
    db.session().commit()
    return ""
Ejemplo n.º 10
0
def update_shopping_list_item(item_id: int):
    if request.method == "GET":
        return redirect(url_for("get_shopping_list"))
    form = RecipeIngredientForm(request.form)
    if not form.validate():
        return render_shopping_list(form, item_id)
    item = ShoppingListItem.query.filter_by(
        id=item_id,
        account_id=current_user.id,
    ).first_or_404()
    item.amount, item.amount_unit = form.parse_amount()
    ingredient = Ingredient.insert_if_missing(form.name.data.strip(),
                                              current_user.id)
    item.ingredient_id = ingredient.id
    db.session().flush()
    Ingredient.delete_unused_ingredients(current_user.id)
    db.session().commit()
    return redirect(url_for("get_shopping_list"))
Ejemplo n.º 11
0
def update_account(account_id):
    if request.method == "GET":
        return redirect(url_for("get_accounts"))
    form = EditAccountForm()
    if not form.validate():
        return jsonify(error_messages=form.errors), 400
    account = Account.query.filter_by(id=account_id).first_or_404()
    username_duplicate = \
        Account.query.filter_by(username=form.username.data).first()
    if username_duplicate and username_duplicate.id != account.id:
        return jsonify(error_messages={
            "username": ["Username is already taken"],
        }), 400
    account.username = form.username.data
    account.role = form.role.data
    if form.password.data:
        account.password_hash = bcrypt.generate_password_hash(
            form.password.data, ).decode("utf-8")
    db.session().commit()
    return ""
Ejemplo n.º 12
0
def update_recipe(recipe_id: int):
    form = EditRecipeForm(request.form)
    if not form.validate():
        return render_edit_form(
            url_for("update_recipe", recipe_id=recipe_id),
            url_for('get_recipe', recipe_id=recipe_id),
            form,
        )
    recipe = Recipe.query.filter_by(
        id=recipe_id,
        account_id=current_user.id,
    ).first_or_404()
    recipe.name = form.name.data
    recipe.description = form.description.data
    recipe.steps = form.steps.data
    RecipeIngredient.query.filter_by(recipe_id=recipe.id).delete()
    db.session.flush()
    recipe.insert_ingredients_from_form(form)
    Ingredient.delete_unused_ingredients(current_user.id)
    db.session().commit()
    return redirect(url_for("get_recipe", recipe_id=recipe_id))
Ejemplo n.º 13
0
    def get_top_recipe_collectors(count):
        stmt = text("""
SELECT accounts.username username, COUNT(recipes.id) recipe_count
FROM accounts
LEFT JOIN recipes ON recipes.account_id = accounts.id
GROUP BY accounts.username
ORDER BY COUNT(recipes.id) DESC, accounts.username
LIMIT :count
""").params(count=count)
        rows = db.session().execute(stmt)
        try:
            return rows.fetchall()
        finally:
            rows.close()
Ejemplo n.º 14
0
def create_account():
    if request.method == "GET":
        return redirect(url_for("get_accounts"))
    form = EditAccountForm()
    if not form.validate():
        return jsonify(error_messages=form.errors), 400
    if Account.is_username_taken(form.username.data):
        return jsonify(error_messages={
            "username": ["Username is already taken"],
        }), 400
    if form.password.data:
        password = form.password.data
    else:
        password = secrets.token_urlsafe(64)
    db.session().add(
        Account(
            username=form.username.data,
            role=form.role.data,
            password_hash=bcrypt.generate_password_hash(password).decode(
                "utf-8"),
        ))
    db.session().commit()
    return ""
Ejemplo n.º 15
0
def add_ingredient_to_shopping_list():
    if request.method == "GET":
        return redirect(url_for("get_shopping_list"))
    form = AddIngredientToShoppingListForm()
    if not form.validate():
        abort(400)
    item = ShoppingListItem.query.filter_by(
        account_id=current_user.id,
        ingredient_id=form.ingredient_id.data,
        amount_unit=form.amount_unit.data,
    ).first()
    if item is None:
        db.session().add(
            ShoppingListItem(
                amount=Decimal(clamp_amount(form.amount.data)),
                amount_unit=form.amount_unit.data,
                ingredient_id=form.ingredient_id.data,
                account_id=current_user.id,
            ))
    else:
        item.amount = clamp_amount(item.amount +
                                   Decimal(clamp_amount(form.amount.data)))
    db.session().commit()
    return redirect(url_for("get_recipe", recipe_id=form.recipe_id.data))
Ejemplo n.º 16
0
    def get_ingredients(self):
        stmt = text("""
SELECT
    ri.amount AS amount,
    ri.amount_unit AS amount_unit,
    ri.group_name AS group_name,
    i.id AS id,
    i.name AS name
FROM ingredients i, recipe_ingredient ri
WHERE
    ri.recipe_id = :recipe_id
    AND i.account_id = :account_id
    AND ri.ingredient_id = i.id
ORDER BY ri.id
""").bindparams(recipe_id=self.id, account_id=self.account_id)
        return db.session().execute(stmt)
Ejemplo n.º 17
0
def ingredient_completions():
    query = request.args.get("query", "")
    try:
        count = int(request.args.get("count", "10"))
        if count <= 0:
            raise ValueError()
    except ValueError:
        return jsonify(
            error="Query parameter 'count' must be a natural number."), 400
    completions = db.session().execute(
        select(
            columns=[Ingredient.name],
            from_obj=Ingredient,
            whereclause=(Ingredient.account_id == current_user.id)
            & Ingredient.name.contains(query),
            distinct=True,
        ).limit(count))
    return jsonify(completions=[completion[0] for completion in completions])
Ejemplo n.º 18
0
    def get_shopping_list_amounts(self):
        stmt = text("""
SELECT
    i.id AS id,
    SUM(sli.amount) AS amount,
    sli.amount_unit AS unit
FROM (
    SELECT DISTINCT
        i.id AS id,
        i.name AS name
    FROM ingredients i, recipe_ingredient ri
    WHERE
        i.account_id = :account_id
        AND i.id = ri.ingredient_id
        AND ri.recipe_id = :recipe_id
) i
LEFT JOIN shopping_list_items sli
ON sli.ingredient_id = i.id
WHERE sli.account_id = :account_id
GROUP BY i.id, sli.amount_unit
""").bindparams(recipe_id=self.id, account_id=self.account_id)
        return db.session().execute(stmt)
Ejemplo n.º 19
0
def create_recipe():
    form = EditRecipeForm()
    if request.method == "GET" or not form.validate():
        return render_edit_form(
            url_for("create_recipe"),
            url_for("get_recipes"),
            form,
        )
    recipe = Recipe(
        name=form.name.data,
        description=form.description.data,
        steps=form.steps.data,
    )
    recipe.account_id = current_user.id
    db.session().add(recipe)
    db.session().flush()
    recipe.insert_ingredients_from_form(form)
    db.session().commit()
    return redirect(url_for("get_recipes"))
Ejemplo n.º 20
0
def delete_account(account_id):
    if request.method == "GET":
        return redirect(url_for("get_accounts"))
    Account.query.filter_by(id=account_id).delete()
    db.session().commit()
    return redirect(url_for("get_accounts"))
Ejemplo n.º 21
0
def get_miner_by_name(user, miner_name):
    return db.session(Miner).filter_by(user=user, name=miner_name)
Ejemplo n.º 22
0
 def is_username_taken(username):
     return db.session().query(
         exists().where(Account.username == username)).scalar()