def post(list_id): """Adds an item to a shoppinglist""" user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({ "status": status, "message": message }), status_code shoppinglist, message, status, status_code = get_shoppinglist( user_id, list_id) if shoppinglist: # form fields name = request.form.get("name") price = request.form.get("price") quantity = request.form.get("quantity") status = request.form.get("status") has_been_bought = True if status and status.strip().title() == "True" else False name = name.strip() if name else "" price = price.strip() if price else "" quantity = quantity.strip() if quantity else "" if name and price and quantity: name = name.lower() name_already_exists = Item.query.filter( Item.shoppinglist_id == list_id).filter(Item.name == name).all() if name_already_exists: return jsonify({ "status": "failure", "message": f"an item with name '{name}' already exists" }), 409 item = Item(list_id, name, quantity, price, status=has_been_bought) item.save() return jsonify({ "status": "success", "message": f"'{item.name}' has been added" }), 201 return jsonify({ "status": "failure", "message": "'name', 'price' and 'quantity' of an item must be" " specified whereas 'status' is optional" }), 400 return jsonify({ "status": status, "message": message }), status_code
def post(): """ User can only logout if and only if a user is logged in and has an authentication token. """ user_id, msg, status, status_code, token = parse_auth_header(request) if user_id is None: return jsonify({"status": status, "message": msg}), status_code user = User.query.filter_by(id=user_id).first() blacklist = BlacklistToken(token) if blacklist.save(): # blacklist token return jsonify({ "status": "success", "message": f"Successfully logged out '{user.email}'" }), 200
def post(): user_id, msg, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({"status": status, "message": msg}), status_code password = request.form.get("password") confirm_password = request.form.get("confirm password") if password and confirm_password: if len(password) < 6: return jsonify({ "status": "failure", "message": "password must have a minimum of 6 characters" }), 400 password_hash = Bcrypt().generate_password_hash(password).decode( 'utf8') if Bcrypt().check_password_hash(password_hash, confirm_password): user = User.query.filter_by(id=user_id).first() if user and not user.validate_password(password): # if old password is not similar to the new password user.password = password_hash user.save() return jsonify({ "status": "success", "message": f"password reset successful for '{user.email}'" }), 200 return jsonify({ "status": "failure", "message": "Your new password should not be similar to " "your old password" }), 400 return jsonify({ "status": "failure", "message": "the given passwords don't match" }), 400 return jsonify({ "status": "failure", "message": "the fields 'password' and 'confirm password' are required" }), 400
def delete(list_id): user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({"status": status, "message": message}), status_code shoppinglist, message, status, status_code = get_shoppinglist( user_id, list_id) if shoppinglist and shoppinglist.delete(): return jsonify({ "status": status, "message": f"shopping list with ID {list_id} deleted successfully" }), status_code return jsonify({"status": status, "message": message}), status_code
def post(): """Adds a new shoppinglist to the currently logged in user account""" user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({"status": status, "message": message}), status_code # prevents errors due to empty string names name = request.form.get("name") notify_date = request.form.get("notify_date") name = name.strip() if name else "" notify_date = notify_date.strip() if notify_date else "" if name and notify_date: name = name.lower() name_already_exists = ShoppingList.query.filter( ShoppingList.user_id == user_id).filter( ShoppingList.name == name).all() if name_already_exists: return jsonify({ "status": "failure", "message": f"a shopping list with name '{name}' already exists" }), 409 date_string, message = parse_notify_date(notify_date) if date_string is None: return jsonify({ "status": "failure", "message": message, }), 400 shoppinglist = ShoppingList(user_id, name, date_string) shoppinglist.save() return jsonify({ "status": "success", "message": f"'{shoppinglist.name}' successfully created" }), 201 return jsonify({ "status": "failure", "message": "'name' and 'notify_date' of the shoppinglist are required fields" }), 400
def delete(list_id, item_id): user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({ "status": status, "message": message }), status_code item, message, status, status_code = get_item( user_id, list_id, item_id) if item is not None and item.delete(): return jsonify({ 'status': status, 'message': f'an item with ID {item_id} has been successfully deleted' }), status_code return jsonify({ "status": status, "message": message }), status_code
def get(list_id): user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({"status": status, "message": message}), status_code shoppinglist, message, status, status_code = get_shoppinglist( user_id, list_id) if shoppinglist: return jsonify({ "id": shoppinglist.id, "name": shoppinglist.name, "notify_date": shoppinglist.notify_date.strftime("%Y-%m-%d"), "date_created": shoppinglist.date_created.strftime("%Y-%m-%d %H:%M:%S"), "date_modified": shoppinglist.date_modified.strftime("%Y-%m-%d %H:%M:%S") }), status_code return jsonify({"status": status, "message": message}), status_code
def get(list_id, item_id): user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({ "status": status, "message": message }), status_code item, message, status, status_code = get_item( user_id, list_id, item_id) if item is not None: return jsonify({ "id": item.id, "name": item.name, "price": item.price, "quantity": item.quantity, "has_been_bought": item.has_been_bought, 'date_modified': item.date_modified.strftime("%Y-%m-%d %H:%M:%S") }), 200 return jsonify({ "status": status, "message": message }), status_code
def get(list_id): user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({ "status": status, "message": message }), status_code shoppinglist, message, status, status_code = get_shoppinglist( user_id, list_id) if shoppinglist: # the query parameters for items search_query = request.args.get('q', None, type=str) page = request.args.get('page', 1, type=int) per_page = request.args.get('limit', 20, type=int) if per_page and per_page > 20: # pragma: no cover per_page = 20 if not per_page or per_page < 1: # pragma: no cover per_page = 20 if not page or page < 1: # pragma: no cover page = 1 query_object = Item.query.filter(Item.shoppinglist_id == list_id) if search_query is not None: query_object = query_object.filter( Item.name.like('%' + search_query.strip().lower() + '%')) # pg_object refers to the pagination object obtained pg_object = query_object.paginate( page=page, per_page=per_page, error_out=False) next_page = None if pg_object.has_next: # pragma: no cover next_page = "/api/v1/shoppinglists/{0}/items?page={1}{2}{3}".format( list_id, pg_object.next_num, '' if per_page == 20 else f'&limit={per_page}', '' if search_query is None else f'&q={search_query}') previous_page = None if pg_object.has_prev: # pragma: no cover previous_page = "/api/v1/shoppinglists/{0}/items?page={1}{2}{3}".format( list_id, pg_object.prev_num, '' if per_page == 20 else f'&limit={per_page}', '' if search_query is None else f'&q={search_query}') list_items = [] for item in pg_object.items: list_items.append( { "id": item.id, "name": item.name, "price": item.price, "quantity": item.quantity, "has_been_bought": item.has_been_bought, 'date_modified': item.date_modified.strftime("%Y-%m-%d %H:%M:%S") } ) if list_items: if search_query is not None: return jsonify({ "status": "success", "items": list_items, "previous_page": previous_page, "next_page": next_page }), 200 return jsonify({ "status": "success", "items": list_items, "previous_page": previous_page, "next_page": next_page }), 200 if search_query is not None: return jsonify({ "status": "success", "message": "your query did not match any items" }), 200 return jsonify({ "status": 'success', "message": 'no items on this list' }), 200 return jsonify({ "status": status, "message": message }), status_code
def put(list_id, item_id): user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({ "status": status, "message": message }), status_code item, message, status, status_code = get_item( user_id, list_id, item_id) if item is not None: # query parameters name = request.form.get("name") price = request.form.get("price") quantity = request.form.get("quantity") status = request.form.get("status") has_been_bought = True if status and status.strip().title() == "True" else False name = name.strip() if name else "" price = price.strip() if price else "" quantity = quantity.strip() if quantity else "" if name and price and quantity: name = name.lower() name_already_exists = Item.query.filter( Item.shoppinglist_id == list_id).filter(( (Item.name == name) & (Item.id != item_id))).all() # if no edits were made... if (item.name == name and item.quantity == quantity and item.price == price and item.has_been_bought == has_been_bought): return jsonify({ "status": "failure", "message": "no changes were made to the item" }), 200 if name_already_exists: return jsonify({ "status": 'failure', "message": f"an item with name '{name}' already exists" }), 409 item.name = name item.price = price item.quantity = quantity item.has_been_bought = has_been_bought item.date_modified = datetime.now() item.save() return jsonify({ 'status': 'success', 'data': { 'id': item.id, 'name': item.name, "price": item.price, "quantity": item.quantity, 'date_modified': item.date_modified, 'has_been_bought': item.has_been_bought }, 'message': 'item has been updated successfully' }), 200 return jsonify({ 'status': 'failure', 'message': "'name', 'price' and 'quantity' of an item must be specified whereas 'status' is optional" }), 400 return jsonify({ "status": status, "message": message }), status_code
def get(): """ Returns the shoppinglists that are owned by the logged in user. The lists returned depend on whether there were any specified query parameters. """ user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({"status": status, "message": message}), status_code # the query parameters search_query = request.args.get('q', None, type=str) page = request.args.get('page', 1, type=int) per_page = request.args.get('limit', 20, type=int) if per_page and per_page > 20: # pragma: no cover per_page = 20 if not per_page or per_page < 1: # pragma: no cover per_page = 20 if not page or page < 1: # pragma: no cover page = 1 query_object = ShoppingList.query.filter( ShoppingList.user_id == user_id) if search_query is not None: query_object = query_object.filter( ShoppingList.name.like('%' + search_query.strip().lower() + '%')) # pg_object refers to the pagination object obtained pg_object = query_object.paginate(page=page, per_page=per_page, error_out=False) next_page = None if pg_object.has_next: next_page = "/api/v1/shoppinglists?page={0}{1}{2}".format( pg_object.next_num, '' if per_page == 20 else f'&limit={per_page}', '' if search_query is None else f'&q={search_query}') previous_page = None if pg_object.has_prev: previous_page = "/api/v1/shoppinglists?page={0}{1}{2}".format( pg_object.prev_num, '' if per_page == 20 else f'&limit={per_page}', '' if search_query is None else f'&q={search_query}') shoppinglists = [] for shoppinglist in pg_object.items: shoppinglists.append({ "id": shoppinglist.id, "name": shoppinglist.name, "date_created": shoppinglist.date_created.strftime("%Y-%m-%d %H:%M:%S"), "notify_date": shoppinglist.notify_date.strftime("%Y-%m-%d"), "date_modified": shoppinglist.date_modified.strftime("%Y-%m-%d %H:%M:%S") }) if shoppinglists: if search_query is not None: return jsonify({ "status": "success", "lists": shoppinglists, "next_page": next_page, "previous_page": previous_page }), 200 return jsonify({ "status": "success", "lists": shoppinglists, "next_page": next_page, "previous_page": previous_page }), 200 if search_query is not None: return jsonify({ "status": "success", "message": "your query did not match any shopping lists" }), 200 return jsonify({ "status": "success", "message": "No shoppinglists found!" }), 200
def put(list_id): user_id, message, status, status_code, _ = parse_auth_header(request) if user_id is None: return jsonify({"status": status, "message": message}), status_code shoppinglist, message, status, status_code = get_shoppinglist( user_id, list_id) if shoppinglist: # a shoppinglist with list_id exists in the database name = request.form.get("name") notify_date = request.form.get("notify_date") name = name.strip() if name else "" notify_date = notify_date.strip() if notify_date else "" if name and notify_date: name = name.lower() name_already_exists = ShoppingList.query.filter( ShoppingList.user_id == user_id).filter( ((ShoppingList.name == name) & (ShoppingList.id != list_id))).all() date_string, message = parse_notify_date(notify_date) if date_string is None: return jsonify({ "status": "failure", "message": message, }), 400 stored_date = shoppinglist.notify_date.strftime("%Y-%m-%d") if shoppinglist.name == name and stored_date == date_string: return jsonify({ "status": "failure", "message": "No changes were made to the list" }), 200 if name_already_exists: return jsonify({ "status": "failure", "message": f"a shopping list with name '{name}' already exists" }), 409 shoppinglist.name = name shoppinglist.notify_date = date_string shoppinglist.date_modified = datetime.now() shoppinglist.save() return jsonify({ "status": "success", "data": { "id": shoppinglist.id, "name": shoppinglist.name, "date_modified": shoppinglist.date_modified, "notify_date": shoppinglist.notify_date }, "message": "shoppinglist has been successfully edited!" }), 200 return jsonify({ "status": "failure", "message": "'name' and 'notify_date' of the shoppinglist are required fields" }), 400 return jsonify({"status": status, "message": message}), status_code