def delete(self): if not self.data.filename is None: path = os.path.join(UPLOAD_FOLDER, 'recipes', str(g.user.id), self.data.filename) self.uploader.delete("/" + path) with session_scope() as session: session.delete(self.data)
def get_order(order_id): try: with session_scope() as db_session: order = db_session.query(Order).filter( Order.id == order_id).first() if order is None: return {'code': 404, 'message': 'Order does not exist'}, 404 if order.user_id != g.user.id: return { 'code': 403, 'message': 'Order does not belong to user.' }, 403 return order.to_json(), 200 return {'code': 200, 'message': 'success'}, 200 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400
def save(): # Load json data from json schema to variable user_info.json 'SCHEMA_FOLDER' schemas_direcotry = os.path.join(current_app.root_path, current_app.config['SCHEMA_FOLDER']) schema_filepath = os.path.join(schemas_direcotry, 'save_for_later.schema.json') try: with open(schema_filepath) as schema_file: schema = json.loads(schema_file.read()) validate(instance=request.json, schema=schema, format_checker=draft7_format_checker) except jsonschema.exceptions.ValidationError as validation_error: return {'code': 400, 'message': validation_error.message} try: # Check if cart id exists with cart items with session_scope() as db_session: # get user_id from json # user_id = request.json.get("user_id") product_id = request.json.get("product_id") savedProduct = save_product(user_id=session['user_id'], product_id=product_id, date_saved=date.today()) db_session.add(savedProduct) return {"code": 200, "message": savedProduct.to_json()}, 200 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return {'code': 400, 'message': 'error: ' + db_error.args[0]}, 400
def delete_item_from_mine(product_id): if 'cart_id' not in session: return { 'code': 400, 'message': 'No cart associated with the session' }, 400 try: with session_scope() as db_session: query = db_session.query(CartLine).filter( CartLine.cart_id == session.get('cart_id')).filter( CartLine.product_id == product_id) if query.count() == 1: cart_line = query.one() db_session.delete(cart_line) else: session.pop('cart_id') return {'code': 400, 'message': 'Invalid cart_id'}, 400 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400 return '', 200
def register(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] error = None if os.environ['FLASK_ENV'] == 'production': error = "Sorry, registration is now closed." elif not username: error = 'Username is required.' elif not password: error = 'Password is required.' elif User.query.filter_by(username=username).first() is not None: error = 'Username {} is already registered.'.format(username) if error is None: user = User(username=username, password=generate_password_hash(password)) with session_scope() as sess: sess.add(user) return redirect(url_for('auth.login')) flash(error) return render_template('auth/register.html')
def get_brands(): with session_scope() as db_session: brands = db_session.query(Brand).all() if len(brands) > 0: return {'brands': [brand.to_json() for brand in brands]}, 200 else: return {'brands': []}, 200
def get_sections(): with session_scope() as db_session: query = db_session.query(Section).all() if len(query) > 0: return {'sections': [section.to_json() for section in query]}, 200 else: return {'sections': []}, 200
def view_total_sales(): # Later will add the ability to sort by date and Category """Endpoint use to compute the total number of items sold between two dates. Returns: (str, int) -- Returns a string with the number of sales. """ try: with session_scope() as db_session: orders = db_session.query(Order).all() if len(orders) < 1: return {'code': 404, 'message': 'There are no sales'}, 404 nmbr_itm = 0 for order in orders: for items in order.order_lines: nmbr_itm = nmbr_itm + items.quantity except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400 except NoResultFound: # Returns an error in case of a integrity constraint not being followed. return {'code': 400, 'message': "No sales have been registered"}, 400 return {'numberItems': nmbr_itm}, 200
def view_trending_by_week(): # Later will add the ability to sort by date and Category """Endpoint use to compute the total number of items sold between two dates. Returns: (str, int) -- Returns a string with the number of sales. """ try: with session_scope() as db_session: # Added filters by date result = db_session.execute( 'SELECT product.id, SUM(order_line.quantity) AS sales, AVG(review.score) AS avg_score FROM product JOIN "user" ON "user".id = product.user_id LEFT JOIN review ON review.product_id = product.id JOIN order_line ON order_line.product_id = product.id GROUP BY product.id HAVING AVG(review.score) >= 3.5 OR AVG(review.score) IS NULL ORDER BY avg_score, sales DESC LIMIT 10;' ) products = db_session.query(Product).filter( Product.id.in_((r['id'] for r in result))).all() return { 'products': [product.to_json() for product in products] }, 200 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400
def update(self): with session_scope() as session: recipe = session.query(Recipe).filter_by(id=self.id).first() recipe.type = RecipeType.WEBPAGE.value recipe.title = self.title recipe.description = self.description recipe.url = self.url
def viewreview(username): try: # Check if cart id exists with cart items with session_scope() as db_session: rev_user = db_session.query(User).filter( User.username == username).first() myreview = db_session.query(Review) if rev_user is None: return '', 400 rev_user_id = rev_user.id array = [] score = 0 num_reviews = 0 for item in myreview: if item.product.user_id == rev_user_id: score = score + item.score array.append(item.to_json()) num_reviews = num_reviews + 1 if num_reviews != 0: score = "%.2f" % (score / num_reviews) return {"code": 200, "score": score, "message": array}, 200 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return {'code': 400, 'message': 'error: ' + db_error.args[0]}, 400
def viewreview_product(permalink): try: # Check if cart id exists with cart items with session_scope() as db_session: product = db_session.query(Product).filter( Product.permalink == permalink).first() if product is None: return '', 400 product_id = product.id myreview = db_session.query(Review).filter( Review.product_id == product_id) array = [] score = 0 num_reviews = len(myreview.all()) for item in myreview: score = score + item.score array.append(item.to_json()) if num_reviews != 0: score = "%.2f" % (score / num_reviews) return {"code": 200, "score": score, "message": array}, 200 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return {'code': 400, 'message': 'error: ' + db_error.args[0]}, 400
def admin_remove(permalink): try: with session_scope() as db_session: product = db_session.query(Product).filter( Product.permalink == permalink) if product.count() > 0: db_session.delete(product.one()) db_session.commit() return { 'code': 200, 'message': 'success! the product with permalink: ' + permalink + ' has been removed' }, 200 else: return { 'code': 400, 'message': 'There are no products in the database with the specified id' }, 400 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400
def createProduct(): """Endpoint to add a new product to the system Returns: (str, int) -- Returns a tuple of the JSON object of the newly created product and a http status code. """ # Validate that only the valid Product properties from the JSON schema new_product.schema.json schemas_direcotry = os.path.join(current_app.root_path, current_app.config['SCHEMA_FOLDER']) schema_filepath = os.path.join(schemas_direcotry, 'new_product.schema.json') try: with open(schema_filepath) as schema_file: schema = json.loads(schema_file.read()) validate(instance=request.json, schema=schema, format_checker=draft7_format_checker) except jsonschema.exceptions.ValidationError as validation_error: return {'code': 400, 'message': validation_error.message}, 400 try: photos = convert_and_save(request.json['photos']) except: photos = None try: with session_scope() as db_session: # Create a md5 of the time of insertion to be appended to the permalink md5 = hashlib.md5() md5.update(str(time.time()).encode('utf-8')) new_product = Product( name=request.json['name'], description=request.json['description'], quantity=request.json['stockQuantity'], category_id=request.json['categoryId'], user_id=session.get('user_id'), tax_id=request.json['taxId'], brand_id=request.json['brandId'], condition=request.json['condition'], price=request.json['price'], permalink=request.json['name'].lower().translate( Product.permalink_translation_tab) + '-' + md5.hexdigest()[:5], photos=photos) db_session.add(new_product) # Commit new product to database making sure of the integrity of the relations. db_session.commit() return new_product.to_json(), 200 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400
def update_addresses(): """Endpoint use to update one or more address Returns: (str, int) -- Returns a tuple of the JSON object of the updated addresses and a http status code. """ # Validate that only the valid User properties from the JSON schema update_self.schema.json schemas_direcotry = os.path.join(current_app.root_path, current_app.config['SCHEMA_FOLDER']) schema_filepath = os.path.join(schemas_direcotry, 'update_addresses.schema.json') try: with open(schema_filepath) as schema_file: schema = json.loads(schema_file.read()) validate(instance=request.json, schema=schema, format_checker=draft7_format_checker) except jsonschema.exceptions.ValidationError as validation_error: return { 'code': 400, 'message': validation_error.message }, 400 try: with session_scope() as db_session: user = db_session.merge(g.user) addresses = request.json user_address = user.addresses for x in range(len(addresses)): for k in addresses[x][1]: index = addresses[x][0] new_value = addresses[x][1][k] user_address[index][k] = new_value #Check for conflict #validate new object according to schema # MAX 3 Addresses # NO duplicates schema_filepath = os.path.join(schemas_direcotry, 'add_addresses.schema.json') try: with open(schema_filepath) as schema_file: schema = json.loads(schema_file.read()) validate(instance=user_address, schema=schema, format_checker=draft7_format_checker) except jsonschema.exceptions.ValidationError as validation_error: return { 'code': 400, 'message': validation_error.message }, 400 user.addresses = user_address db_session.add(user) g.user = user db_session.expunge(g.user) # Needed, otherwise changes do not apply to DB db_session.merge(g.user) except DBAPIError as db_error: return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400 return g.user.to_json(), 200
def regist(self): recipe = Recipe(type=RecipeType.WEBPAGE.value, title=self.title, description=self.description, url=self.url, author_id=g.user.id) with session_scope() as session: session.add(recipe)
def get_category_by_permalink(permalink): with session_scope() as db_session: category = db_session.query(Category).filter( Category.permalink == permalink.lower()).first() if category is not None: return category.to_json(), 200 else: return '', 404
def regist(self): hashed_filename = self.upload_image() recipe = Recipe(type=RecipeType.IMAGE.value, title=self.title, description=self.description, filename=hashed_filename, author_id=g.user.id) with session_scope() as session: session.add(recipe)
def update(self): hashed_filename = self.upload_image() with session_scope() as session: recipe = session.query(Recipe).filter_by(id=self.id).first() recipe.type = RecipeType.IMAGE.value recipe.title = self.title recipe.description = self.description if hashed_filename: recipe.filename = hashed_filename
def before_request(): if 'user_id' in session: with session_scope() as db_session: query = db_session.query(User).filter( User.id == session.get('user_id')) if query.count() == 1: user = query.one() g.user = user db_session.expunge(g.user)
def does_category_exist(permalink): with session_scope() as db_session: category = db_session.query(Category).filter( Category.permalink == permalink.lower()).first() status_code = 404 if category is not None: status_code = 200 return '', status_code
def get_categories(): with session_scope() as db_session: categories = db_session.query(Category).all() if len(categories) > 0: return { 'categories': [category.to_json() for category in categories] }, 200 else: return {'categories': []}, 200
def showSelf(): """Endpoint that returns the information of the authenticated user. Returns: str -- Returns a JSON object of the authenticated user. """ with session_scope() as db_session: user = db_session.merge(g.user) return user.to_json(), 200
def view_sales_leaderboard_by_date(start_date, end_date=None): # Later will add the ability to sort by date and Category """Endpoint use to compute the total number of items sold between two dates. Returns: (str, int) -- Returns a string with the number of sales. """ try: with session_scope() as db_session: # Added filters by date users = db_session.query(User).all() leaderboard = [] for user in users: username = user.username sales = 0 products = db_session.query(Product).filter( Product.user_id == user.id).all() for product in products: if end_date is not None: if validate(start_date) and validate(end_date): pass else: return '', 404 order_lines = db_session.query(OrderLine).filter( OrderLine.product_id == product.id, Order.date.between(start_date, end_date)) else: if validate(start_date): pass else: return '', 404 order_lines = db_session.query(OrderLine).filter( OrderLine.product_id == product.id, Order.date == start_date) for order_line in order_lines: sales = sales + order_line.quantity seller = SellerRecord(username, sales) leaderboard.append(seller) # Sort the entries leaderboard.sort(reverse=True) first_ten = [] for i in range(min(10, len(leaderboard))): first_ten.append(leaderboard[i].to_json()) except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400 except NoResultFound: # Returns an error in case of a integrity constraint not being followed. return {'code': 400, 'message': "No sales have been registered"}, 400 return {"top_sellers": first_ten}, 200
def updateSelf(): """"Endpoints to handle updating an authenticate user. Returns: str -- Returns a refreshed instance of user as a JSON or an JSON containing any error encountered. """ # Validate that only the valid User properties from the JSON schema update_self.schema.json schemas_direcotry = os.path.join(current_app.root_path, current_app.config['SCHEMA_FOLDER']) schema_filepath = os.path.join(schemas_direcotry, 'update_self.schema.json') try: with open(schema_filepath) as schema_file: schema = json.loads(schema_file.read()) validate(instance=request.json, schema=schema, format_checker=draft7_format_checker) except jsonschema.exceptions.ValidationError as validation_error: return {'code': 400, 'message': validation_error.message}, 400 try: with session_scope() as db_session: user = db_session.merge(g.user) current_password = request.json.get("current_password") # Current User Password is required before applying any changes if argon2.verify(current_password, user.password) is False: return { 'code': 400, 'message': "Current password is incorrect" }, 400 # Update the values to the current User for k, v in request.json.items(): # if k == password hash password if k == "password": user.__dict__[k] = argon2.hash(v) user.reset_password = False else: user.__dict__[k] = v db_session.add(user) g.user = user db_session.expunge(g.user) db_session.merge(g.user) except DBAPIError as db_error: return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400 return g.user.to_json(), 200
def get_products_category_by_permalink(permalink): with session_scope() as db_session: category = db_session.query(Category).filter( Category.permalink == permalink.lower()).first() if category is not None: return { 'products': [product.to_json() for product in category.products] }, 200 else: return '', 404
def delAddress(): """Endpoint use to add a address to the user. Sends a welcoming Returns: (str, int) -- Returns a tuple of the JSON object of the newly add shipping addresses user and a http status code. """ # Validate that only the valid User properties from the JSON schema update_self.schema.json schemas_direcotry = os.path.join(current_app.root_path, current_app.config['SCHEMA_FOLDER']) schema_filepath = os.path.join(schemas_direcotry, 'del_addresses.schema.json') try: with open(schema_filepath) as schema_file: schema = json.loads(schema_file.read()) validate(instance=request.json, schema=schema, format_checker=draft7_format_checker) except jsonschema.exceptions.ValidationError as validation_error: return { 'code': 400, 'message': validation_error.message }, 400 try: with session_scope() as db_session: user = db_session.merge(g.user) indices = request.json addresses = user.addresses #shift counter -- denotes the number of elements removed from the list counter = 0 for i in indices: if i is not 0: del addresses[max(0, (i - counter))] counter = counter + 1 else: del addresses[i] counter = counter + 1 user.addresses = addresses db_session.add(user) g.user = user db_session.expunge(g.user) # Needed, otherwise changes do not apply to DB db_session.merge(g.user) except DBAPIError as db_error: return { 'code': 400, 'message': re.search('DETAIL: (.*)', db_error.args[0]).group(1) }, 400 except IndexError as index_error: return { 'code': 400, 'message': "No addresses available to be deleted" }, 400 return g.user.to_json(), 200
def review(): # Load json data from json schema to variable user_info.json 'SCHEMA_FOLDER' schemas_direcotry = os.path.join(current_app.root_path, current_app.config['SCHEMA_FOLDER']) schema_filepath = os.path.join(schemas_direcotry, 'review.schema.json') try: with open(schema_filepath) as schema_file: schema = json.loads(schema_file.read()) validate(instance=request.json, schema=schema, format_checker=draft7_format_checker) except jsonschema.exceptions.ValidationError as validation_error: return {'code': 400, 'message': validation_error.message}, 400 try: # Check if cart id exists with cart items with session_scope() as db_session: # check if user has bought this product id queryOrder = db_session.query(Order).filter( Order.user_id == g.user.id) product = None for item in queryOrder: queryOrderLine = db_session.query(OrderLine).filter( OrderLine.order_id == item.id) for lineitem in queryOrderLine: if lineitem.product.permalink == request.json.get( "productPermalink").lower(): product = lineitem.product if product is not None: myreview = Review(user_id=g.user.id, product_id=product.id, comment=request.json.get("comment"), score=request.json.get("score")) db_session.add(myreview) db_session.commit() #db_session.flush() return {"code": 200, "message": myreview.to_json()}, 200 else: return { "code": 400, "message": "User hasn't bought this product" }, 400 except DBAPIError as db_error: # Returns an error in case of a integrity constraint not being followed. return {'code': 400, 'message': 'error: ' + db_error.args[0]}, 400
def can_review_product(permalink): # Check if cart id exists with cart items with session_scope() as db_session: # check if user has bought this product id queryOrder = db_session.query(Order).filter(Order.user_id == g.user.id) for item in queryOrder: queryOrderLine = db_session.query(OrderLine).filter( OrderLine.order_id == item.id) for lineitem in queryOrderLine: if lineitem.product.permalink == permalink.lower(): return '', 200 return '', 400
def get_product_by_permalink(permalink): """Endpoint to get a product by permalink Returns: (str, int) -- Returns a tuple of the JSON object of the found product and a http status code. """ with session_scope() as db_session: product = db_session.query(Product).filter( Product.permalink == permalink.lower()).first() if product is not None: return product.to_json(), 200 else: return '', 404