def from_db(cls, db, id=None, name=None): """Search db for user entry by id or name (in that priorty) and return constructed object. Returns None if id is not found. """ user = super().from_db(db=db, id=id, name=name) if not user: return None id = user.id # Constructing allergies set needle = (id, ) db.c.execute( 'SELECT allergy_id as id FROM user_allergies WHERE user_id = ?', needle) rows = db.c.fetchall() allergies = {Allergy.from_db(db, row["id"]) for row in rows} # Constructing meals set needle = (id, ) db.c.execute( 'SELECT recipe_id as id FROM user_meals WHERE user_id = ?', needle) rows = db.c.fetchall() meals = {Recipe.from_db(db, row["id"]) for row in rows} user.allergies = allergies user.meals = meals return user
def account(form): """Show account settings for GET. Write new user settings to DB for POST. """ user = User.from_db(db=db, id=session.get("user_id")) # User reached "/account" route via GET (as by clicking a link or via redirect) if request.method == "GET" and not form: allergies = db.get_rows("allergies", order_by="name ASC") user_allergies = {x.id for x in user.allergies} return render_template("account.html", allergies=allergies, user_allergies=user_allergies) # User reached "/account/<form>" route via POST (as by submitting a form via POST) if form == "allergies": allergy_ids = request.form.getlist("allergies") allergies = {Allergy.from_db(db, id) for id in allergy_ids} user.allergies = allergies elif form == "password": current_password = request.form.get("current_password") new_password = request.form.get("new_password") confirmation = request.form.get("confirmation") if not current_password: flash("Must provide valid current password", category="danger") return redirect("account") if not all([new_password, confirmation]): flash("Must provide new password and repeat it", category="danger") return redirect("account") if not new_password == confirmation: flash("New passwords don't match", category="danger") return redirect("account") if not check_password_hash(user.password_hash, current_password): flash("Incorrect current password", category="danger") return redirect("account") user.password_hash = generate_password_hash(new_password) # Commit the user changes to DB try: result = user.write_to_db() except: result = False if result: flash("Changes saved successfully!") else: flash("Something went wrong :(", category="danger") return redirect("/account")
def get_JSON(): """Get JSON repr of an object""" if request.method == "POST" and request.form: obj_type = request.form.get("obj_type") id = request.form.get("id") if request.method == "GET" and request.args: obj_type = request.args.get("obj_type").lower() id = request.args.get("id") try: id = int(id) except: id = None if obj_type in ["user", "valid_meals"]: if not session.get("is_admin") or not id: id = session.get("user_id") elif not id: return("Missing or invalid params") # Users can access only their own user obj and valid_meals user_id = session.get("user_id") d = { "allergy" : lambda db, id: Allergy.from_db(db, id), "ingredient_category": lambda db, id: IngredientCategory.from_db(db, id), "ingredient" : lambda db, id: Ingredient.from_db(db, id), "recipe" : lambda db, id: Recipe.from_db(db, id), "user" : lambda db, id: User.from_db(db, id), "valid_meals" : lambda db, id: User.from_db(db, id).get_valid_recipes_id(), } try: obj = d[obj_type](db, id) except KeyError: return("Missing or invalid params") response = app.response_class( response=enc.encode(obj), mimetype='application/json' ) return response
def admin_display(obj_type): """Show admin page for selected object type""" template = obj_type + ".html" if obj_type else "admin.html" if obj_type == "allergies": kwargs = {"rows":Allergy.get_summary(db)} elif obj_type == "ingredient_categories": kwargs = {"rows":IngredientCategory.get_summary(db)} elif obj_type == "ingredients": kwargs = {"rows" : Ingredient.get_summary(db), "categories": db.get_rows("ingredient_categories"), "allergies" : db.get_rows("allergies")} elif obj_type == "recipes": kwargs = {"rows" : Recipe.get_summary(db), "ingredients": db.get_rows("ingredients")} elif obj_type == "users": kwargs = {"rows" : User.get_summary(db), "allergies" : db.get_rows("allergies")} else: kwargs = {} return render_template(template, **kwargs)
def from_db(cls, db, id=None, name=None): """Search db for ingredient entry by id or name (in that priorty) and return constructed object. Returns None if id is not found. """ db_attrs = cls.get_db_attrs(db, id, name) if not db_attrs: return None id = db_attrs["id"] # Constructing category category_id = db_attrs["category_id"] del db_attrs["category_id"] category = IngredientCategory.from_db(db, category_id) # Constructing allergies set needle = (id,) db.c.execute('SELECT allergy_id as id FROM ingredient_allergies WHERE ingredient_id = ?', needle) rows = db.c.fetchall() allergies = {Allergy.from_db(db, row["id"]) for row in rows} return cls(db=db, category=category, allergies=allergies, **db_attrs)
def admin_remove(obj_type): """Remove an object from DB""" if request.method == "POST" and request.form: id = request.form.get("id") if request.method == "GET" and request.args: id = request.args.get("id") try: id = int(id) except: id = None if not id: return("Missing or invalid params") d = { "allergies" : lambda db, id: Allergy.from_db(db, id).remove_from_db(), "ingredient_categories": lambda db, id: IngredientCategory.from_db(db, id).remove_from_db(), "ingredients" : lambda db, id: Ingredient.from_db(db, id).remove_from_db(), "recipes" : lambda db, id: Recipe.from_db(db, id).remove_from_db(), "users" : lambda db, id: User.from_db(db, id).remove_from_db(), } try: d[obj_type](db, id) # If a recipe was removed remove its image if obj_type == "recipes": filename = str(id) + ".jpg" try: os.remove(os.path.join(app.config["RECIPE_IMG_PATH"], filename)) except FileNotFoundError: pass flash("Entry deleted successfully!") except KeyError: return ("Object type not found") except DBError: flash("Cannot delete entry with dependents (referenced by other entries)!", category="danger") except: flash("Something went wrong :(", category="danger") return redirect("admin/" + obj_type)
def admin_write(obj_type): """Write new object to DB or edit an existing one based on submitted form""" # Set basic values present for all object types name = request.form.get("name") try: id = int(request.form.get("id")) if not id: id = None except ValueError: id = None # Construct object to be written if obj_type == "allergies": obj = Allergy(name, db, id) elif obj_type == "ingredient_categories": obj = IngredientCategory(name, db, id) elif obj_type == "ingredients": category_id = request.form.get("category_id") category = IngredientCategory.from_db(db=db, id=category_id) allergy_ids = request.form.getlist("allergies") allergies = {Allergy.from_db(db=db, id=id) for id in allergy_ids} obj = Ingredient(name, category, allergies, db, id) elif obj_type == "recipes": instructions = request.form.get("instructions") contents = set() try: form_contents = json.loads(request.form.get("contents")) except: form_contents = None for fc in form_contents: ingredient = Ingredient.from_db(db=db, id=fc["ingredient_id"]) try: amount = float(fc["amount"]) except KeyError: amount = 0 units = fc["units"] if fc["units"] != "" else None contents.add(Content(ingredient, amount, units)) obj = Recipe(name, instructions, contents, db, id) # Define function to be called only if object is written to DB successfully def if_written(): # Apply image changes to the filesystem filename = str(obj.id) + ".jpg" if request.form.get("image-delete"): # Current image is to be deleted if exists try: os.remove(os.path.join(app.config["RECIPE_IMG_PATH"], filename)) except FileNotFoundError: pass else: # New image is to be saved image = request.files.get("image") if image: extension = image.filename.split(".").pop() if extension in ALLOWED_IMG_EXTENSIONS: image.save(os.path.join(app.config["RECIPE_IMG_PATH"], filename)) else: flash("Only .jpg, .jpeg images allowed", category=danger) elif obj_type == "users": obj = User.from_db(db, id) obj.is_admin = request.form.get("is_admin") obj.name = request.form.get("name") else: return ("Object type not found") try: result = obj.write_to_db() except: result = False if result: flash("Changes saved successfully!") try: if_written() except UnboundLocalError: pass else: flash("Something went wrong :(", category="danger") return redirect("admin/" + obj_type)