def add_book(): """ This method lists a book on one of several lists, by a user. It involves the following steps: - add the book to the backend DB to the relevant table - then, reload the page with an updated table """ bsdb = get_bsdb() data = req.get_json() if data.get('request') == 'my-books': # here we list the book as being available for trade # isbn = req.get_json()["isbn"] copyquality = data["quality"] points = data["points"] book_id = data["bookId"] user_num = session["user_num"] # bsdb.user_add_book_by_isbn(isbn, user_num, copyquality) bsdb.user_add_book_by_id(book_id, user_num, copyquality, points) app.logger.info(f"Book {book_id} added by user {user_num}") flash("Book successfully added to your BookSwap library.", "success") return redirect('/my-books') elif data.get('request') == 'my-wishlist': book_id = data["bookId"] user_num = session["user_num"] bsdb.user_add_book_to_wishlist_by_id(book_id, user_num) return redirect('/wishlist')
def change_points(): """ Change_points changes the point value assigned to the UserBooks entry. """ bsdb = get_bsdb() points = req.get_json().get('points') user_num = session['user_num'] book_id = req.get_json().get('id') app.logger.info( f"UserBooks id {book_id} trying to change it to {points} points. " + f"Current user is {session['user_num']}") # Confirm that the requesting user owns the book try: if bsdb.is_user_book_owner(user_num, book_id): app.logger.info(f"Correct user for the book detected.") else: app.logger.warning(f"Incorrect user for the book detected.") flash("Wrong uesr for that book. Log out, log in, and try again?", "warning") return redirect(url_for('my_books')) except Exception: app.logger.error("Error checking user validity.") flash("We had an error trying to verify your identity. " + "Sorry about that. Perhaps try again?", "warning") return redirect(url_for('my_books')) # Change the points try: bsdb.set_book_points(book_id, points) app.logger.info(f"Book points changed.") flash("Book points successfully changed.", "success") except Exception: app.logger.error(f"Error changing book points.") flash("We had an error trying to change your book points. " + "Sorry about that. Perhaps try again?", "warning") return redirect(url_for('my_books'))
def search_book(): """ This method is POSTed a request with the fields 'isbn', 'author', and 'title', and searches for results on the open library API that match these fields. It returns a rendered set of divs to be inserted into the html as appropriate. """ bsdb = get_bsdb() data = req.get_json() if data.get('request') == 'my-books': isbn = data["isbn"] author = data["author"] title = data["title"] # TODO magic number here - number of search results search_results = bsdb.search_books_openlibrary(title=title, author=author, isbn=isbn, num_results=5) copyqualities = bsdb.get_book_qualities() return render_template("snippets/external_search_results.html", search_results=search_results, copyqualities=copyqualities, show_qualities=True, show_points=True) elif data.get('request') == 'my-wishlist': isbn = data["isbn"] author = data["author"] title = data["title"] # TODO magic number here - number of search results search_results = bsdb.search_books_openlibrary(title=title, author=author, isbn=isbn, num_results=5) return render_template("snippets/external_search_results.html", search_results=search_results, show_qualities=False, show_points=False, show_wishlist_results=True)
def requestBook(): bsdb = get_bsdb() book = req.get_json(force=True) app.logger.info('Request incoming for book: %s', book) if (book['userId'] == session['user_num']): flash("You tried to request your own book? It would be easier to just pull it off the shelf and read...", "warning") app.logger.warning( f"User {session['user_num']} attempted to trade with themselves. This leads to night blindness") success = "False" try: points_available = bsdb.get_current_user_points(session["user_num"]) except Exception: points_available = 0 else: try: points_available = bsdb.request_book(book, session['user_num']) success = "True" app.logger.info( f"Successfully placed trade request for user {session['user_num']} on UserBooks number " f"{book['userBooksId']}") except Exception: app.logger.error( f"Unable to place the Trade Request for user {session['user_num']} on UserBooks book number " f"{book['userBooksId']}") success = "False" flash("There was an error in placing the trade request. Feel free to try again", "warning") return { "book": book, "points_available": points_available, "success": success }
def wishlist(): bsdb = get_bsdb() wishlists = Wishlists(session['user_num'], bsdb) data = req.get_json() # User asks to see copies of a book if req.method == "POST" and data.get("request") == "copiesModal": book = eval(data['book']) app.logger.info(f"Request incoming for copies of book {book} from user {session['user_num']}") try: copies = bsdb.get_available_copies(book["bookId"], session["user_num"]) copies_arr = [dict(copy) for copy in copies] app.logger.info(f"Copies available: {copies_arr}") except Exception: app.logger.error(f"Error retrieving copies of {book} for user {session['user_num']}") flash("Error retrieving copies of the book. Maybe try again?", "warning") return redirect('/wishlist') return { "title": copies_arr[0]['title'], "copies": copies_arr, "count": len(copies_arr), "points_available": g.points } # Page load try: books = wishlists.get_all_wishlist_books_for_user() app.logger.info(f"Made wishlists for user {session['user_num']}") except Exception: app.logger.error(f"Error making wishlists for user {session['user_num']}") flash("We had an error fetching your wishlist", "warning") books = [] return render_template('user/wishlist.html', books=books)
def __init__(self, user_num): """ Class initializer. Accepts: user_num (int): User id Returns: None """ self.user_num = user_num self.bsdb = get_bsdb()
def reject_trade(user_books_id): app.logger.info(f"Incoming trade rejection from user {session['user_num']} for book {user_books_id}") bsdb = get_bsdb() try: bsdb.reject_trade(user_books_id) app.logger.info(f"Trade successfully rejected. UserBooks number {user_books_id} is available again.") flash("Trade successfully removed", "success") except Exception: app.logger.error(f"There was an error in rejecting the trade.") flash("There was an error in deleting your trade", "warning") return redirect(url_for('received_requests'))
def accept_trade(user_books_id): app.logger.info(f"Incoming trade acceptance from user {session['user_num']} for book {user_books_id}") bsdb = get_bsdb() try: bsdb.accept_trade(user_books_id) app.logger.info(f"Trade successfully accepted.") flash("Trade successfully accepted", "success") except Exception: app.logger.info(f"There was an error in accepting the trade.") flash("There was an error in accepting your trade", "warning") return redirect(url_for('received_requests'))
def book_not_received(user_books_id): app.logger.info(f"Incoming book NOT received confirmation from {session['user_num']} for book {user_books_id}") bsdb = get_bsdb() book_not_received = BookReceived(session['user_num'], user_books_id, bsdb) try: book_not_received.book_not_received() app.logger.info(f"Trade failure confirmation from user {session['user_num']} for book {user_books_id}") flash("Trade marked as never completed", "success") except Exception: app.logger.error( f"Unsuccessful trade failure confirmation from user {session['user_num']} for book {user_books_id}") return redirect(url_for("my_requests"))
def browse_books(): form = BookSearchForm() bsdb = get_bsdb() recent_books = bsdb.get_recent_additions(8) recent_books_arr = [dict(book) for book in recent_books] local_results = {} external_results = {} if req.method == 'POST': book_search_query = (form.ISBN.data, form.author.data, form.title.data) book_search = BookSearch(book_search_query, bsdb) # TODO magic numbers here # book_results = book_search.local_book_search(10) local_results, external_results = book_search.combined_book_search(10, 10) show_recent = False show_search = False show_results = True else: book_results = {} show_recent = True show_search = True show_results = False # Load current user's points if session.get('user_num'): try: points_available = bsdb.get_current_user_points(session['user_num']) app.logger.info(f"User {session['user_num']} has {points_available} points.") except Exception: app.logger.error( f"APP: Browse_books -- Could not determine number of points for user {session['user_num']}.") points_available = 0 flash( "We could not load your points, so we assume you have 0 points. Feel free to browse for now, " "but we will need to fix this before you can make trade requests.", "warning") else: points_available = 0 app.logger.info(f"\n\t recent_books: {recent_books_arr}" + f"\t local_results: {local_results}" + f"\t external_results: {external_results}" + f"\t form: {form}" + f"\t Visiting user has {points_available} points available.") return render_template('browse-books.html', recent_books=recent_books_arr, local_results=local_results, external_results=external_results, form=form, show_recent=show_recent, show_search=show_search, show_results=show_results, points_available=points_available )
def cancel_request(user_books_id): app.logger.info(f"Incoming trade request cancellation from {session['user_num']} for book {user_books_id}") bsdb = get_bsdb() cancel_trade_request = CancelTradeRequest(session['user_num'], user_books_id, bsdb) try: cancel_trade_request.cancel_request() app.logger.info( f"Successful trade request cancellation from user {session['user_num']} for book {user_books_id}") flash("Trade request canceled", "success") except Exception: app.logger.error( f"Unsuccessful trade request cancellation from user {session['user_num']} for book {user_books_id}") return redirect(url_for("my_requests"))
def my_books(): bsdb = get_bsdb() # Get the data of books currently listed rows = bsdb.get_listed_books(session['user_num']) copyqualities = bsdb.get_book_qualities() # Build the data to be passed to Jinja headers = ["Title", "Author", "Quality", "Points", "ISBN", "ID", "Cover"] table_content = [[row[header] for header in headers] for row in rows] data = {"headers": headers, "rows": table_content, "caption": "", "copyqualities": copyqualities } return render_template('user/my-books.html', data=data)
def received_requests(): bsdb = get_bsdb() user = session['user_num'] num_trade_reqs = bsdb.get_num_trade_requests(user) num_open_trades = bsdb.get_num_open_trades(user) if num_trade_reqs == 0 and num_open_trades == 0: return render_template('user/no-trades.html') else: trade_info = bsdb.get_trade_info(user) trade_info_dicts = [dict(row) for row in trade_info] return render_template('user/received-requests.html', trade_info=trade_info_dicts, num_open_trades=num_open_trades, num_trade_reqs=num_trade_reqs)
def my_requests(): bsdb = get_bsdb() user = session['user_num'] my_request = MyRequests(user, bsdb) try: requests = my_request.get_all_open_requests() requests_dicts = [dict(row) for row in requests] for trade in requests_dicts: print(trade['tradeAge']) except Exception: app.logger.error("Couldn't fill my-requests") requests_dicts = [] if len(requests_dicts) == 0: return render_template('user/no-trades.html', no_sent_requests=True) else: return render_template('user/my-requests.html', requests=requests_dicts)
def populate_g(): bsdb = get_bsdb() user_num = session.get("user_num") if user_num is not None: try: user_info = bsdb.get_account_settings(user_num) g.username = user_info["username"] g.points = user_info["points"] g.num_trade_requests = bsdb.get_num_trade_requests(user_num) g.num_open_trades = bsdb.get_num_open_trades(user_num) app.logger.info(f"Request made. Current user status:" f"\t g.username: {g.username}" + f"\t g.points: {g.points}" f"\t g.num_trade_requests: {g.num_trade_requests}" + f"\t g.num_open_trades: {g.num_open_trades}") except Exception: app.logger.error(f"Error setting up g") session['user_num'] = None
def login(): form = LoginForm() # Checks if input is valid if form.validate_on_submit(): bsdb = get_bsdb() username = form.username.data password = form.password.data error = None app.logger.info(f'Login attempt incoming for user {username}') id = None # Username check try: id = bsdb.get_username_id(username) except Exception: app.logger.error(f"Error checking username ( {username} ).") error = "We had an error checking your username. Please try again." if id is None: app.logger.error(f"Login -- Incorrect username ( {username} ) entered.") error = "Incorrect username. We do not have record of this username." # Password check else: try: if password != bsdb.get_password(id): app.logger.warning(f"Incorrect password entered for {username}.") error = "Incorrect password." except Exception: app.logger.error(f"Error checking password for {username}.") error = "We hada n error checking your password. Please try again." # No errors, login proceeds if error is None: session.clear() session['user_num'] = id app.logger.info(f"User {username} successfully logged in.") return redirect(url_for('home')) flash(error, 'warning') return render_template('login.html', form=form)
def account(): # Get basic database and forms ready to return bsdb = get_bsdb() acct = AccountSettings(session['user_num']) account_settings_change_form = AccountSettingsChangeForm() password_change_form = PasswordChangeForm() account_settings = bsdb.get_account_settings(session["user_num"]) show_account_modal = False show_password_modal = False # Check against requests to change account settings if (req.method == 'POST' and account_settings_change_form.submit_account_change.data): show_account_modal = True app.logger.info(f"request received to change user settings for " + f"user {session['user_num']}") # Check to make sure form was valid, return form if it was not if not account_settings_change_form.validate_on_submit(): app.logger.warning(f"Settings change form failed validation") flash("Your information wouldn't work. Try again?", "warning") return render_template( 'user/user-home.html', account_settings=account_settings, account_settings_change_form=account_settings_change_form, password_change_form=password_change_form, show_account_modal=show_account_modal, show_password_modal=show_password_modal ) # Check that the username isn't changing or is available if acct.is_username_valid(session['user_num'], account_settings_change_form.username.data): app.logger.info("username is valid") try: acct.set_account_information( session['user_num'], account_settings_change_form) flash("Account information updated.", "success") app.logger.info("returning new account info:") account_settings = bsdb.get_account_settings( session["user_num"]) show_account_modal = False account_settings = bsdb.get_account_settings( session["user_num"]) except Exception: flash("Error updating your information. Try again?", "warning") else: flash("Username is already taken", "warning") # Check against request to change password elif req.method == 'POST' and password_change_form.submit.data: show_password_modal = True app.logger.info(f"request received to change password for " + f"user {session['user_num']}") if not password_change_form.validate_on_submit(): app.logger.warning(f"Password change form failed verification") flash("Your infromation wouldn't work. Try again?", "warning") return render_template( 'user/user-home.html', account_settings=account_settings, account_settings_change_form=account_settings_change_form, password_change_form=password_change_form, show_account_modal=show_account_modal, show_password_modal=show_password_modal ) try: correct_password = acct.is_password_correct(session["user_num"], password_change_form) if not correct_password: flash("Original password was not correct. Please try again.", "warning") else: app.logger.info("Original password was entered correctly.") try: acct.set_password(session["user_num"], password_change_form) app.logger.info("New Password set") flash("New Password Sucessfully Set.", "success") show_password_modal = False except Exception: app.logger.error("Error setting new password") flash("Error setting new password. Try again?", "warning") except Exception: flash("Error determining if the original password is correct. Try again?", "warning") app.logger.error("Error checking original password.") # We got here either by being GET or succeeding making changes. # Refill account_setting and account_settings_change_form account_settings_change_form = acct.fill_account_settings_change_form() account_settings = bsdb.get_account_settings(session["user_num"]) return render_template( 'user/user-home.html', account_settings=account_settings, account_settings_change_form=account_settings_change_form, password_change_form=password_change_form, show_account_modal=show_account_modal, show_password_modal=show_password_modal )
def add_to_wish(bookid=None): bsdb = get_bsdb() db = get_db() db.row_factory = sqlite3.Row # Queries used for SELECTing and INSERTing get_books_isbn_query = 'SELECT * FROM Books WHERE ISBN = ?' get_wishlist_books_query = 'SELECT * FROM WishlistsBooks WHERE wishlistId = ? AND bookId = ?' insert_wishlist_query = 'INSERT INTO WishlistsBooks (wishlistId, bookId) VALUES (?, ?)' # Special path for browse-books route if bookid is not None: c = db.cursor() c.execute(get_wishlist_books_query, (session['user_num'], bookid)) # if the book was already in the wishlist, don't add it if c.fetchall(): flash("Book already in your wishlist", "warning") app.logger.warning(f"Book {bookid} already in " + f"user {session['user_num']}'s wishlist") # otherwise, add book to the wishlist else: c.execute(insert_wishlist_query, (session['user_num'], bookid)) flash("Book added to your wishlist", "success") app.logger.info(f"Book {id} successfully added to " + f"user {session['user_num']}'s wishlist") db.commit() db.close() return redirect(url_for('browse_books')) data = req.args.get("isbn") if data == "": return redirect('/wishlist') c = db.cursor() c.execute(get_books_isbn_query, (data,)) bookId = c.fetchall()[0]['id'] # need to get Users Wishlist.id number c.execute(""" SELECT id FROM Wishlists WHERE Wishlists.userId = ? """, (session['user_num'],)) wishlist = c.fetchone()['id'] c.execute(get_wishlist_books_query, (wishlist, bookId)) if not c.fetchall(): flash("Book successfully added to your wishlist", "success") app.logger.info(f"Book {bookId} added to wishlist {wishlist}") c.execute(insert_wishlist_query, (wishlist, bookId)) else: flash("Book already in your wishlist.", "warning") app.logger.warning(f"Book {bookId} attempted to add to wishlist {wishlist}, but it was already in that list.") db.commit() db.close() return redirect('/wishlist')