diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..9575d51 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.6.1 diff --git a/Lesson4/step2/.env.example b/Lesson4/step2/.env.example new file mode 100644 index 0000000..0a37f4f --- /dev/null +++ b/Lesson4/step2/.env.example @@ -0,0 +1,7 @@ +google_client_id= +google_project_id= +google_client_secret= +facebook_app_id= +facebook_app_secret= +app_secret_key= +debug= \ No newline at end of file diff --git a/Lesson4/step2/.gitignore b/Lesson4/step2/.gitignore new file mode 100644 index 0000000..40723b0 --- /dev/null +++ b/Lesson4/step2/.gitignore @@ -0,0 +1,5 @@ +*.idea/ +__pycache__/ +pyrepo/ +*.pyc +.env \ No newline at end of file diff --git a/Lesson4/step2/.python-version b/Lesson4/step2/.python-version new file mode 100644 index 0000000..9575d51 --- /dev/null +++ b/Lesson4/step2/.python-version @@ -0,0 +1 @@ +3.6.1 diff --git a/Lesson4/step2/README.md b/Lesson4/step2/README.md new file mode 100644 index 0000000..2e7a9d2 --- /dev/null +++ b/Lesson4/step2/README.md @@ -0,0 +1,39 @@ +# Restaurants and Menus + +The first step is to setup the `.env` file to hold all of the environment variables that are needed to connect to the APIs. To do so, run `cp .env.example .env`, which will copy the example file to the .env file. This file is not committed to the Git repo. + +The version of Python is `3.6.1`, which is shown in the `.python-version` file. + +After signing up for an app on facebook and google, fill in the values in their appropriate places in the `.env` file. These will automatically cascade to the rest of the app. + +The database used by default is restaurantmenuwithusers.db. To change to another database engine, look in the `database_setup.py` file and change the engine to whatever is appropriate for your use case. + +To start using the program, run: +```shell +pip install -r requirements.txt +``` + +This will install all of the dependencies. + +To re-run the base seeds, run `python lotsofmenus.py`. + +To start up the app, run either: + +```shell +export FLASK_APP=project.py +flask run +``` + +Or +```shell +python project.py +``` + +All dependencies are kept in the .env file. To create the .env file, run + +```shell +cp .env.example .env +``` + +Then fill in the environment values with their required settings. + diff --git a/Lesson4/step2/client_secrets.json b/Lesson4/step2/client_secrets.json deleted file mode 100644 index f6bbfb7..0000000 --- a/Lesson4/step2/client_secrets.json +++ /dev/null @@ -1 +0,0 @@ -{"web":{"auth_uri":"https://accounts.google.com/o/oauth2/auth","client_secret":"YOUR_CLIENT_SECRET_GOES_HERE","token_uri":"https://accounts.google.com/o/oauth2/token","client_email":"13140951618-15nik769cellkubaqnjk5facdib2dh4d@developer.gserviceaccount.com","redirect_uris":["https://localhost:5000/callback","http://localhost:5000/callback"],"client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/13140951618-15nik769cellkubaqnjk5facdib2dh4d@developer.gserviceaccount.com","client_id":"YOUR_CLIENT_ID_GOES_HERE.apps.googleusercontent.com","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","javascript_origins":["http://localhost","https://udacity-oauth.herokuapp.com","http://udacity-oauth.herokuapp.com","http://localhost:5000"]}} diff --git a/Lesson4/step2/database_setup.py b/Lesson4/step2/database_setup.py index f49c971..4abe0c7 100644 --- a/Lesson4/step2/database_setup.py +++ b/Lesson4/step2/database_setup.py @@ -1,7 +1,9 @@ +#! /usr/bin/env python3 + from sqlalchemy import Column, ForeignKey, Integer, String +from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship -from sqlalchemy import create_engine Base = declarative_base() @@ -59,5 +61,4 @@ def serialize(self): engine = create_engine('sqlite:///restaurantmenuwithusers.db') - Base.metadata.create_all(engine) diff --git a/Lesson4/step2/fb_client_secrets.json b/Lesson4/step2/fb_client_secrets.json deleted file mode 100644 index bff14f0..0000000 --- a/Lesson4/step2/fb_client_secrets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "web": { - "app_id": "PASTE_YOUR_APP_ID_HERE", - "app_secret": "PASTE_YOUR_CLIENT_SECRET_HERE" - } -} diff --git a/Lesson4/step2/lotsofmenus.py b/Lesson4/step2/lotsofmenus.py index 3e4460a..8c96e69 100644 --- a/Lesson4/step2/lotsofmenus.py +++ b/Lesson4/step2/lotsofmenus.py @@ -1,9 +1,11 @@ -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker +#! /usr/bin/env python3 -from database_setup import Restaurant, Base, MenuItem, User +import locale +import random +from faker import Faker +from sqlalchemy.orm import sessionmaker +from database_setup import Restaurant, Base, MenuItem, User, engine -engine = create_engine('sqlite:///restaurantmenuwithusers.db') # Bind the engine to the metadata of the Base class so that the # declaratives can be accessed through a DBSession instance Base.metadata.bind = engine @@ -17,370 +19,44 @@ # revert all of them back to the last commit by calling # session.rollback() session = DBSession() +locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') +fake = Faker() - -# Create dummy user -User1 = User(name="Robo Barista", email="tinnyTim@udacity.com", - picture='https://pbs.twimg.com/profile_images/2671170543/18debd694829ed78203a5a36dd364160_400x400.png') -session.add(User1) -session.commit() - -# Menu for UrbanBurger -restaurant1 = Restaurant(user_id=1, name="Urban Burger") - -session.add(restaurant1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Veggie Burger", description="Juicy grilled veggie patty with tomato mayo and lettuce", - price="$7.50", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="French Fries", description="with garlic and parmesan", - price="$2.99", course="Appetizer", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Chicken Burger", description="Juicy grilled chicken patty with tomato mayo and lettuce", - price="$5.50", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - -menuItem3 = MenuItem(user_id=1, name="Chocolate Cake", description="fresh baked and served with ice cream", - price="$3.99", course="Dessert", restaurant=restaurant1) - -session.add(menuItem3) -session.commit() - -menuItem4 = MenuItem(user_id=1, name="Sirloin Burger", description="Made with grade A beef", - price="$7.99", course="Entree", restaurant=restaurant1) - -session.add(menuItem4) -session.commit() - -menuItem5 = MenuItem(user_id=1, name="Root Beer", description="16oz of refreshing goodness", - price="$1.99", course="Beverage", restaurant=restaurant1) - -session.add(menuItem5) -session.commit() - -menuItem6 = MenuItem(user_id=1, name="Iced Tea", description="with Lemon", - price="$.99", course="Beverage", restaurant=restaurant1) - -session.add(menuItem6) -session.commit() - -menuItem7 = MenuItem(user_id=1, name="Grilled Cheese Sandwich", - description="On texas toast with American Cheese", price="$3.49", course="Entree", restaurant=restaurant1) - -session.add(menuItem7) -session.commit() - -menuItem8 = MenuItem(user_id=1, name="Veggie Burger", description="Made with freshest of ingredients and home grown spices", - price="$5.99", course="Entree", restaurant=restaurant1) - -session.add(menuItem8) -session.commit() - - -# Menu for Super Stir Fry -restaurant2 = Restaurant(user_id=1, name="Super Stir Fry") - -session.add(restaurant2) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="Chicken Stir Fry", description="With your choice of noodles vegetables and sauces", - price="$7.99", course="Entree", restaurant=restaurant2) - -session.add(menuItem1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Peking Duck", - description=" A famous duck dish from Beijing[1] that has been prepared since the imperial era. The meat is prized for its thin, crisp skin, with authentic versions of the dish serving mostly the skin and little meat, sliced in front of the diners by the cook", price="$25", course="Entree", restaurant=restaurant2) - -session.add(menuItem2) -session.commit() - -menuItem3 = MenuItem(user_id=1, name="Spicy Tuna Roll", description="Seared rare ahi, avocado, edamame, cucumber with wasabi soy sauce ", - price="15", course="Entree", restaurant=restaurant2) - -session.add(menuItem3) -session.commit() - -menuItem4 = MenuItem(user_id=1, name="Nepali Momo ", description="Steamed dumplings made with vegetables, spices and meat. ", - price="12", course="Entree", restaurant=restaurant2) - -session.add(menuItem4) -session.commit() - -menuItem5 = MenuItem(user_id=1, name="Beef Noodle Soup", description="A Chinese noodle soup made of stewed or red braised beef, beef broth, vegetables and Chinese noodles.", - price="14", course="Entree", restaurant=restaurant2) - -session.add(menuItem5) -session.commit() - -menuItem6 = MenuItem(user_id=1, name="Ramen", description="a Japanese noodle soup dish. It consists of Chinese-style wheat noodles served in a meat- or (occasionally) fish-based broth, often flavored with soy sauce or miso, and uses toppings such as sliced pork, dried seaweed, kamaboko, and green onions.", - price="12", course="Entree", restaurant=restaurant2) - -session.add(menuItem6) -session.commit() - - -# Menu for Panda Garden -restaurant1 = Restaurant(user_id=1, name="Panda Garden") - -session.add(restaurant1) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="Pho", description="a Vietnamese noodle soup consisting of broth, linguine-shaped rice noodles called banh pho, a few herbs, and meat.", - price="$8.99", course="Entree", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Chinese Dumplings", description="a common Chinese dumpling which generally consists of minced meat and finely chopped vegetables wrapped into a piece of dough skin. The skin can be either thin and elastic or thicker.", - price="$6.99", course="Appetizer", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - -menuItem3 = MenuItem(user_id=1, name="Gyoza", description="light seasoning of Japanese gyoza with salt and soy sauce, and in a thin gyoza wrapper", - price="$9.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem3) -session.commit() - -menuItem4 = MenuItem(user_id=1, name="Stinky Tofu", description="Taiwanese dish, deep fried fermented tofu served with pickled cabbage.", - price="$6.99", course="Entree", restaurant=restaurant1) - -session.add(menuItem4) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Veggie Burger", description="Juicy grilled veggie patty with tomato mayo and lettuce", - price="$9.50", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) +for i in range(0, 10): + user = User( + name=fake.name(), + email=fake.email(), + picture='https://pbs.twimg.com/profile_images/2671170543/' + '18debd694829ed78203a5a36dd364160_400x400.png' + ) + session.add(user) session.commit() - -# Menu for Thyme for that -restaurant1 = Restaurant(user_id=1, name="Thyme for That Vegetarian Cuisine ") - -session.add(restaurant1) +for i in range(0, 10): + restaurant = Restaurant( + user_id=i + 1, + name=fake.text() + ) + session.add(restaurant) session.commit() +course_elements = ["Entree", "Dessert", "Beverage", "Appetizer"] -menuItem1 = MenuItem(user_id=1, name="Tres Leches Cake", description="Rich, luscious sponge cake soaked in sweet milk and topped with vanilla bean whipped cream and strawberries.", - price="$2.99", course="Dessert", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() +for i in range(0, 1000): + restaurant = session.query(Restaurant).filter_by( + id=random.randint(1, 10) + ).first() -menuItem2 = MenuItem(user_id=1, name="Mushroom risotto", description="Portabello mushrooms in a creamy risotto", - price="$5.99", course="Entree", restaurant=restaurant1) + menuItem = MenuItem( + user_id=restaurant.user_id, + name=fake.lexify("???????? ??????"), + description=fake.text(), + price=locale.currency(round(random.randint(100, 10000) / 100, 2)), + course=fake.random_element(course_elements), + restaurant=restaurant + ) + session.add(menuItem) -session.add(menuItem2) session.commit() -menuItem3 = MenuItem(user_id=1, name="Honey Boba Shaved Snow", - description="Milk snow layered with honey boba, jasmine tea jelly, grass jelly, caramel, cream, and freshly made mochi", price="$4.50", course="Dessert", restaurant=restaurant1) - -session.add(menuItem3) -session.commit() - -menuItem4 = MenuItem(user_id=1, name="Cauliflower Manchurian", description="Golden fried cauliflower florets in a midly spiced soya,garlic sauce cooked with fresh cilantro, celery, chilies,ginger & green onions", - price="$6.95", course="Appetizer", restaurant=restaurant1) - -session.add(menuItem4) -session.commit() - -menuItem5 = MenuItem(user_id=1, name="Aloo Gobi Burrito", description="Vegan goodness. Burrito filled with rice, garbanzo beans, curry sauce, potatoes (aloo), fried cauliflower (gobi) and chutney. Nom Nom", - price="$7.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem5) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Veggie Burger", description="Juicy grilled veggie patty with tomato mayo and lettuce", - price="$6.80", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - - -# Menu for Tony's Bistro -restaurant1 = Restaurant(user_id=1, name="Tony\'s Bistro ") - -session.add(restaurant1) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="Shellfish Tower", description="Lobster, shrimp, sea snails, crawfish, stacked into a delicious tower", - price="$13.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Chicken and Rice", description="Chicken... and rice", - price="$4.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - -menuItem3 = MenuItem(user_id=1, name="Mom's Spaghetti", description="Spaghetti with some incredible tomato sauce made by mom", - price="$6.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem3) -session.commit() - -menuItem4 = MenuItem(user_id=1, name="Choc Full O\' Mint (Smitten\'s Fresh Mint Chip ice cream)", - description="Milk, cream, salt, ..., Liquid nitrogen magic", price="$3.95", course="Dessert", restaurant=restaurant1) - -session.add(menuItem4) -session.commit() - -menuItem5 = MenuItem(user_id=1, name="Tonkatsu Ramen", description="Noodles in a delicious pork-based broth with a soft-boiled egg", - price="$7.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem5) -session.commit() - - -# Menu for Andala's -restaurant1 = Restaurant(user_id=1, name="Andala\'s") - -session.add(restaurant1) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="Lamb Curry", description="Slow cook that thang in a pool of tomatoes, onions and alllll those tasty Indian spices. Mmmm.", - price="$9.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Chicken Marsala", description="Chicken cooked in Marsala wine sauce with mushrooms", - price="$7.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - -menuItem3 = MenuItem(user_id=1, name="Potstickers", description="Delicious chicken and veggies encapsulated in fried dough.", - price="$6.50", course="Appetizer", restaurant=restaurant1) - -session.add(menuItem3) -session.commit() - -menuItem4 = MenuItem(user_id=1, name="Nigiri Sampler", description="Maguro, Sake, Hamachi, Unagi, Uni, TORO!", - price="$6.75", course="Appetizer", restaurant=restaurant1) - -session.add(menuItem4) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Veggie Burger", description="Juicy grilled veggie patty with tomato mayo and lettuce", - price="$7.00", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - - -# Menu for Auntie Ann's -restaurant1 = Restaurant(user_id=1, name="Auntie Ann\'s Diner' ") - -session.add(restaurant1) -session.commit() - -menuItem9 = MenuItem(user_id=1, name="Chicken Fried Steak", - description="Fresh battered sirloin steak fried and smothered with cream gravy", price="$8.99", course="Entree", restaurant=restaurant1) - -session.add(menuItem9) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="Boysenberry Sorbet", description="An unsettlingly huge amount of ripe berries turned into frozen (and seedless) awesomeness", - price="$2.99", course="Dessert", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Broiled salmon", description="Salmon fillet marinated with fresh herbs and broiled hot & fast", - price="$10.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - -menuItem3 = MenuItem(user_id=1, name="Morels on toast (seasonal)", - description="Wild morel mushrooms fried in butter, served on herbed toast slices", price="$7.50", course="Appetizer", restaurant=restaurant1) - -session.add(menuItem3) -session.commit() - -menuItem4 = MenuItem(user_id=1, name="Tandoori Chicken", description="Chicken marinated in yoghurt and seasoned with a spicy mix(chilli, tamarind among others) and slow cooked in a cylindrical clay or metal oven which gets its heat from burning charcoal.", - price="$8.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem4) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Veggie Burger", description="Juicy grilled veggie patty with tomato mayo and lettuce", - price="$9.50", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - -menuItem10 = MenuItem(user_id=1, name="Spinach Ice Cream", description="vanilla ice cream made with organic spinach leaves", - price="$1.99", course="Dessert", restaurant=restaurant1) - -session.add(menuItem10) -session.commit() - - -# Menu for Cocina Y Amor -restaurant1 = Restaurant(user_id=1, name="Cocina Y Amor ") - -session.add(restaurant1) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="Super Burrito Al Pastor", - description="Marinated Pork, Rice, Beans, Avocado, Cilantro, Salsa, Tortilla", price="$5.95", course="Entree", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - -menuItem2 = MenuItem(user_id=1, name="Cachapa", description="Golden brown, corn-based Venezuelan pancake; usually stuffed with queso telita or queso de mano, and possibly lechon. ", - price="$7.99", course="Entree", restaurant=restaurant1) - -session.add(menuItem2) -session.commit() - - -restaurant1 = Restaurant(user_id=1, name="State Bird Provisions") -session.add(restaurant1) -session.commit() - -menuItem1 = MenuItem(user_id=1, name="Chantrelle Toast", description="Crispy Toast with Sesame Seeds slathered with buttery chantrelle mushrooms", - price="$5.95", course="Appetizer", restaurant=restaurant1) - -session.add(menuItem1) -session.commit - -menuItem1 = MenuItem(user_id=1, name="Guanciale Chawanmushi", - description="Japanese egg custard served hot with spicey Italian Pork Jowl (guanciale)", price="$6.95", course="Dessert", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - - -menuItem1 = MenuItem(user_id=1, name="Lemon Curd Ice Cream Sandwich", - description="Lemon Curd Ice Cream Sandwich on a chocolate macaron with cardamom meringue and cashews", price="$4.25", course="Dessert", restaurant=restaurant1) - -session.add(menuItem1) -session.commit() - - -print "added menu items!" +print("added all the items items!") diff --git a/Lesson4/step2/project.py b/Lesson4/step2/project.py index 529ff42..6bcf186 100644 --- a/Lesson4/step2/project.py +++ b/Lesson4/step2/project.py @@ -1,40 +1,67 @@ -from flask import Flask, render_template, request, redirect, jsonify, url_for, flash -from sqlalchemy import create_engine, asc -from sqlalchemy.orm import sessionmaker -from database_setup import Base, Restaurant, MenuItem, User -from flask import session as login_session +#! /usr/bin/env python3 + +import json import random import string -from oauth2client.client import flow_from_clientsecrets -from oauth2client.client import FlowExchangeError +from functools import wraps + import httplib2 -import json -from flask import make_response import requests +from flask import Flask, render_template, request, \ + redirect, jsonify, url_for, flash, make_response, \ + session as login_session +from oauth2client.client import FlowExchangeError, OAuth2WebServerFlow +from sqlalchemy import asc +from sqlalchemy.orm import sessionmaker + +from database_setup import Base, Restaurant, MenuItem, User, engine +from variables import facebook_web, google_web, main_app + +state = ''.join(random.choice(string.ascii_uppercase + string.digits) + for x in range(32)) app = Flask(__name__) +app.secret_key = state -CLIENT_ID = json.loads( - open('client_secrets.json', 'r').read())['web']['client_id'] +GOOGLE_CLIENT_ID = google_web.get('client_id') APPLICATION_NAME = "Restaurant Menu Application" - # Connect to Database and create database session -engine = create_engine('sqlite:///restaurantmenuwithusers.db') Base.metadata.bind = engine DBSession = sessionmaker(bind=engine) session = DBSession() -# Create anti-forgery state token +def login_required(f): + """ + If a user is logged in, perform the normal action. + Otherwise, send them to the login. + """ + + @wraps(f) + def decorated_function(*args, **kwargs): + print(request.url) + if 'username' not in login_session: + flash( + "The url %s is not available " + "unless you are logged in!" % request.url + ) + return redirect('/login') + return f(*args, **kwargs) + + return decorated_function + + @app.route('/login') -def showLogin(): - state = ''.join(random.choice(string.ascii_uppercase + string.digits) - for x in xrange(32)) +def show_login(): login_session['state'] = state - # return "The current session state is %s" % login_session['state'] - return render_template('login.html', STATE=state) + return render_template( + 'login.html', + STATE=login_session['state'], + google_web=google_web, + facebook_web=facebook_web + ) @app.route('/fbconnect', methods=['POST']) @@ -44,35 +71,37 @@ def fbconnect(): response.headers['Content-Type'] = 'application/json' return response access_token = request.data - print "access token received %s " % access_token - - app_id = json.loads(open('fb_client_secrets.json', 'r').read())[ - 'web']['app_id'] - app_secret = json.loads( - open('fb_client_secrets.json', 'r').read())['web']['app_secret'] - url = 'https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id=%s&client_secret=%s&fb_exchange_token=%s' % ( - app_id, app_secret, access_token) + app_id = facebook_web.get('app_id') + app_secret = facebook_web.get('app_secret') + url = 'https://graph.facebook.com/oauth/access_token?' \ + 'grant_type=fb_exchange_token&client_id=%s&client_secret=%s' \ + '&fb_exchange_token=%s' % ( + app_id, app_secret, str(access_token).split("'")[1]) h = httplib2.Http() result = h.request(url, 'GET')[1] - # Use token to get user info from API - userinfo_url = "https://graph.facebook.com/v2.8/me" ''' - Due to the formatting for the result from the server token exchange we have to - split the token first on commas and select the first index which gives us the key : value - for the server access token then we split it on colons to pull out the actual token value - and replace the remaining quotes with nothing so that it can be used directly in the graph + Due to the formatting for the result + from the server token + exchange we have to + split the token first on commas and select the first + index which gives us the key : value + for the server access token then we split it + on colons to pull out the actual token value + and replace the remaining quotes with nothing + so that it can be used directly in the graph api calls ''' - token = result.split(',')[0].split(':')[1].replace('"', '') + str_result = str(result) + token = str_result.split(',')[0].split(':')[1].replace('"', '') - url = 'https://graph.facebook.com/v2.8/me?access_token=%s&fields=name,id,email' % token + url = 'https://graph.facebook.com/v2.8/me?access_token' \ + '=%s&fields=name,id,email' % token h = httplib2.Http() result = h.request(url, 'GET')[1] - # print "url sent for API access:%s"% url - # print "API JSON result: %s" % result + data = json.loads(result) login_session['provider'] = 'facebook' login_session['username'] = data["name"] @@ -83,7 +112,9 @@ def fbconnect(): login_session['access_token'] = token # Get user picture - url = 'https://graph.facebook.com/v2.8/me/picture?access_token=%s&redirect=0&height=200&width=200' % token + url = 'https://graph.facebook.com/v2.8/me/picture?' \ + 'access_token=%s&redirect=0&height=200&width=200' \ + % token h = httplib2.Http() result = h.request(url, 'GET')[1] data = json.loads(result) @@ -91,9 +122,9 @@ def fbconnect(): login_session['picture'] = data["data"]["url"] # see if user exists - user_id = getUserID(login_session['email']) + user_id = get_user_id(login_session['email']) if not user_id: - user_id = createUser(login_session) + user_id = create_user(login_session) login_session['user_id'] = user_id output = '' @@ -103,7 +134,9 @@ def fbconnect(): output += '!' output += ' ' + output += ' " style = "width: 300px; height: 300px;border-radius: ' \ + '150px;-webkit-border-radius: ' \ + '150px;-moz-border-radius: 150px;"> ' flash("Now logged in as %s" % login_session['username']) return output @@ -114,9 +147,10 @@ def fbdisconnect(): facebook_id = login_session['facebook_id'] # The access token must me included to successfully logout access_token = login_session['access_token'] - url = 'https://graph.facebook.com/%s/permissions?access_token=%s' % (facebook_id,access_token) + url = 'https://graph.facebook.com/%s/permissions?' \ + 'access_token=%s' % (facebook_id, access_token) h = httplib2.Http() - result = h.request(url, 'DELETE')[1] + h.request(url, 'DELETE') return "you have been logged out" @@ -132,8 +166,10 @@ def gconnect(): try: # Upgrade the authorization code into a credentials object - oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='') - oauth_flow.redirect_uri = 'postmessage' + oauth_flow = OAuth2WebServerFlow( + redirect_uri='postmessage', + **google_web + ) credentials = oauth_flow.step2_exchange(code) except FlowExchangeError: response = make_response( @@ -162,18 +198,9 @@ def gconnect(): return response # Verify that the access token is valid for this app. - if result['issued_to'] != CLIENT_ID: + if result['issued_to'] != GOOGLE_CLIENT_ID: response = make_response( json.dumps("Token's client ID does not match app's."), 401) - print "Token's client ID does not match app's." - response.headers['Content-Type'] = 'application/json' - return response - - stored_access_token = login_session.get('access_token') - stored_gplus_id = login_session.get('gplus_id') - if stored_access_token is not None and gplus_id == stored_gplus_id: - response = make_response(json.dumps('Current user is already connected.'), - 200) response.headers['Content-Type'] = 'application/json' return response @@ -195,9 +222,9 @@ def gconnect(): login_session['provider'] = 'google' # see if user exists, if it doesn't make a new one - user_id = getUserID(data["email"]) + user_id = get_user_id(data["email"]) if not user_id: - user_id = createUser(login_session) + user_id = create_user(login_session) login_session['user_id'] = user_id output = '' @@ -206,35 +233,42 @@ def gconnect(): output += '!' output += ' ' + output += ' " style = "width: 300px; height: 300px;border-radius: 150px;' \ + '-webkit-border-radius: 150px;-moz-border-radius: 150px;"> ' flash("you are now logged in as %s" % login_session['username']) - print "done!" return output + # User Helper Functions -def createUser(login_session): - newUser = User(name=login_session['username'], email=login_session[ - 'email'], picture=login_session['picture']) - session.add(newUser) +def create_user(login_session_dict): + new_user = User( + name=login_session_dict['username'], + email=login_session_dict['email'], + picture=login_session_dict['picture'] + ) + session.add(new_user) session.commit() - user = session.query(User).filter_by(email=login_session['email']).one() + user = session.query(User).filter_by( + email=login_session_dict['email'] + ).one() return user.id -def getUserInfo(user_id): +def get_user_info(user_id): user = session.query(User).filter_by(id=user_id).one() return user -def getUserID(email): +def get_user_id(email): try: user = session.query(User).filter_by(email=email).one() return user.id except: return None + # DISCONNECT - Revoke a current user's token and reset their login_session @@ -251,37 +285,48 @@ def gdisconnect(): h = httplib2.Http() result = h.request(url, 'GET')[0] if result['status'] == '200': - del login_session['access_token'] - del login_session['gplus_id'] - del login_session['username'] - del login_session['email'] - del login_session['picture'] - response = make_response(json.dumps('Successfully disconnected.'), 200) + remove_session() + response = make_response(json.dumps('Successfully disconnected.')) response.headers['Content-Type'] = 'application/json' return response else: - response = make_response(json.dumps('Failed to revoke token for given user.', 400)) + response = make_response( + json.dumps('Failed to revoke token for given user.') + ) response.headers['Content-Type'] = 'application/json' return response +def remove_session(): + # the dictionary needs to be copied to avoid a runtime error + sess = login_session.copy() + for (key, value) in sess.items(): + del login_session[key] + + # JSON APIs to view Restaurant Information @app.route('/restaurant//menu/JSON') -def restaurantMenuJSON(restaurant_id): - restaurant = session.query(Restaurant).filter_by(id=restaurant_id).one() +def restaurant_menu_json(restaurant_id): items = session.query(MenuItem).filter_by( restaurant_id=restaurant_id).all() + if not items: + return jsonify("No such restaurant exists") return jsonify(MenuItems=[i.serialize for i in items]) @app.route('/restaurant//menu//JSON') -def menuItemJSON(restaurant_id, menu_id): - Menu_Item = session.query(MenuItem).filter_by(id=menu_id).one() - return jsonify(Menu_Item=Menu_Item.serialize) +def menu_item_json(restaurant_id, menu_id): + try: + menu_item = session.query(MenuItem).filter_by( + id=menu_id, restaurant_id=restaurant_id + ).one() + except: + return jsonify("No such menu exists") + return jsonify(Menu_Item=menu_item.serialize) @app.route('/restaurant/JSON') -def restaurantsJSON(): +def restaurants_json(): restaurants = session.query(Restaurant).all() return jsonify(restaurants=[r.serialize for r in restaurants]) @@ -289,171 +334,261 @@ def restaurantsJSON(): # Show all restaurants @app.route('/') @app.route('/restaurant/') -def showRestaurants(): +def show_restaurants(): restaurants = session.query(Restaurant).order_by(asc(Restaurant.name)) - if 'username' not in login_session: - return render_template('publicrestaurants.html', restaurants=restaurants) - else: - return render_template('restaurants.html', restaurants=restaurants) + return render_template( + 'restaurants.html', + restaurants=restaurants, + login_session=login_session + ) + # Create a new restaurant @app.route('/restaurant/new/', methods=['GET', 'POST']) -def newRestaurant(): - if 'username' not in login_session: - return redirect('/login') +@login_required +def new_restaurant(): if request.method == 'POST': - newRestaurant = Restaurant( - name=request.form['name'], user_id=login_session['user_id']) - session.add(newRestaurant) - flash('New Restaurant %s Successfully Created' % newRestaurant.name) + new_restaurant_obj = Restaurant( + name=request.form['name'], + user_id=login_session['user_id'] + ) + session.add(new_restaurant_obj) + flash( + 'New Restaurant %s Successfully Created' % + new_restaurant_obj.name + ) session.commit() - return redirect(url_for('showRestaurants')) + return redirect(url_for('show_restaurants')) else: return render_template('newRestaurant.html') + # Edit a restaurant @app.route('/restaurant//edit/', methods=['GET', 'POST']) -def editRestaurant(restaurant_id): - editedRestaurant = session.query( - Restaurant).filter_by(id=restaurant_id).one() - if 'username' not in login_session: - return redirect('/login') - if editedRestaurant.user_id != login_session['user_id']: - return "" +@login_required +def edit_restaurant(restaurant_id): + try: + edited_restaurant = session.query( + Restaurant).filter_by( + id=restaurant_id + ).one() + except: + return "No such restaurant exists." + if edited_restaurant.user_id != login_session['user_id']: + return "" if request.method == 'POST': - if request.form['name']: - editedRestaurant.name = request.form['name'] - flash('Restaurant Successfully Edited %s' % editedRestaurant.name) - return redirect(url_for('showRestaurants')) + if request.form['name'] != edited_restaurant.name: + edited_restaurant.name = request.form['name'] + flash('Restaurant Successfully Edited %s' % edited_restaurant.name) + return redirect(url_for('show_restaurants')) else: - return render_template('editRestaurant.html', restaurant=editedRestaurant) + return render_template( + 'editRestaurant.html', + restaurant=edited_restaurant + ) # Delete a restaurant @app.route('/restaurant//delete/', methods=['GET', 'POST']) -def deleteRestaurant(restaurant_id): - restaurantToDelete = session.query( - Restaurant).filter_by(id=restaurant_id).one() - if 'username' not in login_session: - return redirect('/login') - if restaurantToDelete.user_id != login_session['user_id']: - return "" +@login_required +def delete_restaurant(restaurant_id): + try: + restaurant_to_delete = session.query( + Restaurant).filter_by(id=restaurant_id).one() + except: + return "No such restaurant to delete" + if restaurant_to_delete.user_id != login_session['user_id']: + return "" if request.method == 'POST': - session.delete(restaurantToDelete) - flash('%s Successfully Deleted' % restaurantToDelete.name) + session.delete(restaurant_to_delete) + menu_items_to_delete = session.query(MenuItem).filter_by( + restaurant_id=restaurant_id + ).all() + for del_menu in menu_items_to_delete: + session.delete(del_menu) + flash('%s Successfully Deleted' % restaurant_to_delete.name) session.commit() - return redirect(url_for('showRestaurants', restaurant_id=restaurant_id)) + return redirect( + url_for( + 'show_restaurants', + restaurant_id=restaurant_id + ) + ) else: - return render_template('deleteRestaurant.html', restaurant=restaurantToDelete) + return render_template( + 'deleteRestaurant.html', + restaurant=restaurant_to_delete + ) + # Show a restaurant menu @app.route('/restaurant//') @app.route('/restaurant//menu/') -def showMenu(restaurant_id): - restaurant = session.query(Restaurant).filter_by(id=restaurant_id).one() - creator = getUserInfo(restaurant.user_id) +def show_menu(restaurant_id): + try: + restaurant = session.query(Restaurant).filter_by( + id=restaurant_id + ).one() + except: + return "No such restaurant" + creator = get_user_info(restaurant.user_id) + if creator is None: + return "The owner has shut down the restaurant" items = session.query(MenuItem).filter_by( restaurant_id=restaurant_id).all() - if 'username' not in login_session or creator.id != login_session['user_id']: - return render_template('publicmenu.html', items=items, restaurant=restaurant, creator=creator) - else: - return render_template('menu.html', items=items, restaurant=restaurant, creator=creator) + return render_template( + 'menu.html', + items=items, + restaurant=restaurant, + creator=creator, + login_session=login_session + ) # Create a new menu item -@app.route('/restaurant//menu/new/', methods=['GET', 'POST']) -def newMenuItem(restaurant_id): - if 'username' not in login_session: - return redirect('/login') - restaurant = session.query(Restaurant).filter_by(id=restaurant_id).one() +@app.route( + '/restaurant//menu/new/', + methods=['GET', 'POST'] +) +@login_required +def new_menu_item(restaurant_id): + try: + restaurant = session.query(Restaurant).filter_by( + id=restaurant_id + ).one() + except: + return "No such restaurant" if login_session['user_id'] != restaurant.user_id: - return "" - if request.method == 'POST': - newItem = MenuItem(name=request.form['name'], description=request.form['description'], price=request.form[ - 'price'], course=request.form['course'], restaurant_id=restaurant_id, user_id=restaurant.user_id) - session.add(newItem) - session.commit() - flash('New Menu %s Item Successfully Created' % (newItem.name)) - return redirect(url_for('showMenu', restaurant_id=restaurant_id)) + return "" + if request.method == 'POST': + new_item = MenuItem( + name=request.form['name'], + description=request.form['description'], + price=request.form['price'], + course=request.form['course'], + restaurant_id=restaurant_id, + user_id=restaurant.user_id + ) + session.add(new_item) + session.commit() + flash('New Menu %s Item Successfully Created' % new_item.name) + return redirect(url_for('show_menu', restaurant_id=restaurant_id)) else: return render_template('newmenuitem.html', restaurant_id=restaurant_id) + # Edit a menu item -@app.route('/restaurant//menu//edit', methods=['GET', 'POST']) -def editMenuItem(restaurant_id, menu_id): - if 'username' not in login_session: - return redirect('/login') - editedItem = session.query(MenuItem).filter_by(id=menu_id).one() - restaurant = session.query(Restaurant).filter_by(id=restaurant_id).one() +@app.route( + '/restaurant//menu//edit', + methods=['GET', 'POST'] +) +@login_required +def edit_menu_item(restaurant_id, menu_id): + try: + edited_item = session.query(MenuItem).filter_by( + id=menu_id + ).one() + except: + return "No such item" + try: + restaurant = session.query(Restaurant).filter_by( + id=restaurant_id + ).one() + except: + return "No such restaurant" if login_session['user_id'] != restaurant.user_id: - return "" + return "" if request.method == 'POST': - if request.form['name']: - editedItem.name = request.form['name'] - if request.form['description']: - editedItem.description = request.form['description'] - if request.form['price']: - editedItem.price = request.form['price'] - if request.form['course']: - editedItem.course = request.form['course'] - session.add(editedItem) + for (key, value) in request.form.items(): + setattr(edited_item, key, value) + session.add(edited_item) session.commit() flash('Menu Item Successfully Edited') - return redirect(url_for('showMenu', restaurant_id=restaurant_id)) + return redirect(url_for('show_menu', restaurant_id=restaurant_id)) else: - return render_template('editmenuitem.html', restaurant_id=restaurant_id, menu_id=menu_id, item=editedItem) + return render_template( + 'editmenuitem.html', + restaurant_id=restaurant_id, + menu_id=menu_id, + item=edited_item + ) # Delete a menu item -@app.route('/restaurant//menu//delete', methods=['GET', 'POST']) -def deleteMenuItem(restaurant_id, menu_id): - if 'username' not in login_session: - return redirect('/login') - restaurant = session.query(Restaurant).filter_by(id=restaurant_id).one() - itemToDelete = session.query(MenuItem).filter_by(id=menu_id).one() +@app.route( + '/restaurant//menu//delete', + methods=['GET', 'POST'] +) +@login_required +def delete_menu_item(restaurant_id, menu_id): + try: + restaurant = session.query(Restaurant).filter_by( + id=restaurant_id + ).one() + except: + return "No such restaurant" + try: + item_to_delete = session.query(MenuItem).filter_by( + id=menu_id + ).one() + except: + return "No such item" if login_session['user_id'] != restaurant.user_id: - return "" + return "" if request.method == 'POST': - session.delete(itemToDelete) + session.delete(item_to_delete) session.commit() flash('Menu Item Successfully Deleted') - return redirect(url_for('showMenu', restaurant_id=restaurant_id)) + return redirect(url_for('show_menu', restaurant_id=restaurant_id)) else: - return render_template('deleteMenuItem.html', item=itemToDelete) + return render_template('deleteMenuItem.html', item=item_to_delete) # Disconnect based on provider @app.route('/disconnect') def disconnect(): if 'provider' in login_session: - if login_session['provider'] == 'google': - gdisconnect() - del login_session['gplus_id'] - del login_session['credentials'] - if login_session['provider'] == 'facebook': - fbdisconnect() - del login_session['facebook_id'] - del login_session['username'] - del login_session['email'] - del login_session['picture'] - del login_session['user_id'] - del login_session['provider'] + remove_session() flash("You have successfully been logged out.") - return redirect(url_for('showRestaurants')) + return redirect(url_for('show_restaurants')) else: flash("You were not logged in") - return redirect(url_for('showRestaurants')) + return redirect(url_for('show_restaurants')) if __name__ == '__main__': - app.secret_key = 'super_secret_key' - app.debug = True - app.run(host='0.0.0.0', port=5000) + app.secret_key = main_app.get('secret_key', 'super_secret_key') + app.debug = main_app.get('debug', True) + app.config['SESSION_TYPE'] = main_app.get('session_type', 'filesystem') + app.run( + host=main_app.get('host', '0.0.0.0'), + port=main_app.get('port', 5000) + ) diff --git a/Lesson4/step2/requirements.txt b/Lesson4/step2/requirements.txt new file mode 100644 index 0000000..3bf07bd --- /dev/null +++ b/Lesson4/step2/requirements.txt @@ -0,0 +1,19 @@ +certifi==2017.7.27.1 +chardet==3.0.4 +click==6.7 +Flask==0.12.2 +httplib2==0.10.3 +idna==2.6 +itsdangerous==0.24 +Jinja2==2.9.6 +MarkupSafe==1.0 +oauth2client==4.1.2 +pyasn1==0.3.2 +pyasn1-modules==0.0.11 +python-dotenv==0.6.5 +requests==2.18.4 +rsa==3.4.2 +six==1.10.0 +SQLAlchemy==1.1.13 +urllib3==1.22 +Werkzeug==0.12.2 diff --git a/Lesson4/step2/restaurantmenu.db b/Lesson4/step2/restaurantmenu.db deleted file mode 100644 index e69de29..0000000 diff --git a/Lesson4/step2/restaurantmenuwithusers.db b/Lesson4/step2/restaurantmenuwithusers.db index 7bfdd06..0417312 100644 Binary files a/Lesson4/step2/restaurantmenuwithusers.db and b/Lesson4/step2/restaurantmenuwithusers.db differ diff --git a/Lesson4/step2/static/styles.css b/Lesson4/step2/static/styles.css index df225bb..72bab5a 100644 --- a/Lesson4/step2/static/styles.css +++ b/Lesson4/step2/static/styles.css @@ -1,163 +1,193 @@ * { - font-family: "Helvetica Neue Bold", Roboto, Helvetica, Arial, sans-serif; - font-weight: 700; + font-family: "Helvetica Neue Bold", Roboto, Helvetica, Arial, sans-serif; + font-weight: 700; } h1 { - font-family: "Helvetica Neue Light", Roboto, Helvetica, Arial, sans-serif; - font-size: 50px; - color: #51453B; - line-height: 60px; - font-weight: 300; + font-family: "Helvetica Neue Light", Roboto, Helvetica, Arial, sans-serif; + font-size: 50px; + color: #51453B; + line-height: 60px; + font-weight: 300; } h2 { - font-size: 24px; - color: #42C3C9; - line-height: 29px; + font-size: 24px; + color: #42C3C9; + line-height: 29px; } h3 { - font-size: 18px; - color: #4A4A4A; - line-height: 23px; -} - p { - font-family: "Helvetica Neue", Roboto, Helvetica, Arial, sans-serif; - font-size: 16px; - color: #7B7573; - line-height: 24px; - font-weight: 400; - } - - strong { - font-size: 16px; - color: #7B7573; - line-height: 24px; - } - - a { - font-size: 14px; - color: #0093B9; - line-height: 17px; - } + font-size: 18px; + color: #4A4A4A; + line-height: 23px; +} + +p { + font-family: "Helvetica Neue", Roboto, Helvetica, Arial, sans-serif; + font-size: 16px; + color: #7B7573; + line-height: 24px; + font-weight: 400; +} + +strong { + font-size: 16px; + color: #7B7573; + line-height: 24px; +} + +a { + font-size: 14px; + color: #0093B9; + line-height: 17px; +} + .padding-top { - padding-top: 30px; + padding-top: 30px; } + .padding-bottom { - padding-bottom: 30px; + padding-bottom: 30px; } + .margin-right { - margin-right: 30px; + margin-right: 30px; } + .padding-none { - padding: 0; + padding: 0; } + .btn { - padding: 20px; - margin: 0; - border-color: #9FB80A; - border-width: 2px; - color: #9FB80A;; + padding: 20px; + margin: 0; + border-color: #9FB80A; + border-width: 2px; + color: #9FB80A;; } + .btn:hover { - border-color: #9FB80A; + border-color: #9FB80A; } + .btn.delete { - border-color: #aaaaaa; - color: #aaaaaa; + border-color: #aaaaaa; + color: #aaaaaa; } + .btn.delete:hover { - border-color: #aaaaaa; - color: red; + border-color: #aaaaaa; + color: red; } + .glyphicon { - margin-right: 10px; + margin-right: 10px; } + .top-menu { - padding-top: 30px; - padding-bottom: 30px; + padding-top: 30px; + padding-bottom: 30px; } + .top-menu p { - margin-bottom: 0; - line-height: 16px; + margin-bottom: 0; + line-height: 16px; } + .top-menu a { - margin-bottom: 0; - line-height: 16px; - font-size: 16px; - color: #7B7573; - font-weight: 400; + margin-bottom: 0; + line-height: 16px; + font-size: 16px; + color: #7B7573; + font-weight: 400; } + .divider { - height: 15px; + height: 15px; } + .divider.blue { - background-color: #42C3C9; + background-color: #42C3C9; } + .divider.green { - background-color: #9FB80A; + background-color: #9FB80A; } + .banner.main { - height: 150px; - background: url("/static/top-banner.jpg"); - background-position: right; - background-repeat: no-repeat; - background-size: cover; + height: 150px; + background: url("/static/top-banner.jpg"); + background-position: right; + background-repeat: no-repeat; + background-size: cover; + border-bottom: solid 15px #42c3c9; + margin-bottom: 15px; } + .banner.menu { - height: 150px; - background-color: #E1E17F; + background-color: #E1E17F; } + .banner.profile { - height: 150px; - background-color: #A6E8EB; + height: 150px; + background-color: #A6E8EB; } + .banner h1 { - margin: 45px 0; + margin: 45px 0; + font-size: 14px; } - .restaurant-list { - background-color: #F0F0F0; - padding: 20px; -u } - .restaurant-list:hover { - background-color: #e1e17f; - padding: 20px; + +.restaurant-list { + background-color: #F0F0F0; + padding: 20px; } + +.restaurant-list:hover { + background-color: #e1e17f; + padding: 20px; +} + .menu-item { - background: #F0F0F0; - padding: 20px; - margin: 20px; - margin-left: -20px; + background: #F0F0F0; + padding: 20px; + margin: 20px; + margin-left: -20px; } + .menu-price { - font-weight: 700; + font-weight: 700; } + .creator { - padding-right: 20px; - margin-top: -20px; - text-align: right; - float:right; + padding-right: 20px; + margin-top: -20px; + text-align: right; + float: right; } + .creator img { - width: 100px; - border-radius: 50%; + width: 100px; + border-radius: 50%; } + .creator figcaption { - font-size: 14px; - color: #7B7573; - font-weight: 400; - margin-top: -20px; + font-size: 14px; + color: #7B7573; + font-weight: 400; + margin-top: -20px; } + .flash { - background-color: #98FB98; - width:100%; - text-decoration: none; + background-color: #98FB98; + width: 100%; + text-decoration: none; } .flash li { - list-style-type: none; - text-align: center; + list-style-type: none; + text-align: center; } \ No newline at end of file diff --git a/Lesson4/step2/templates/deleteRestaurant.html b/Lesson4/step2/templates/deleteRestaurant.html index f71b37a..20eb995 100644 --- a/Lesson4/step2/templates/deleteRestaurant.html +++ b/Lesson4/step2/templates/deleteRestaurant.html @@ -1,17 +1,19 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -

Are you sure you want to delete {{restaurant.name}}?

+ {% include "header.html" %} +

Are you sure you want to delete {{ restaurant.name }}?

-
+ - - - - + + + + -
+ {% endblock %} \ No newline at end of file diff --git a/Lesson4/step2/templates/deletemenuitem.html b/Lesson4/step2/templates/deletemenuitem.html index e49fd4a..bcef025 100644 --- a/Lesson4/step2/templates/deletemenuitem.html +++ b/Lesson4/step2/templates/deletemenuitem.html @@ -1,17 +1,19 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -

Are you sure you want to delete {{item.name}}?

+ {% include "header.html" %} +

Are you sure you want to delete {{ item.name }}?

-
+ - - - - + + + + -
+ {% endblock %} diff --git a/Lesson4/step2/templates/editRestaurant.html b/Lesson4/step2/templates/editRestaurant.html index 5ce142f..cd6cc37 100644 --- a/Lesson4/step2/templates/editRestaurant.html +++ b/Lesson4/step2/templates/editRestaurant.html @@ -1,29 +1,31 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -
-
-
- -
-
-
-
- - -
- - - - -
-
-
-
+ {% include "header.html" %} +
+
+
+ +
+
+
+
+ + +
+ + + + +
+
+
+
{% endblock %} \ No newline at end of file diff --git a/Lesson4/step2/templates/editmenuitem.html b/Lesson4/step2/templates/editmenuitem.html index e92fee7..41e0e02 100644 --- a/Lesson4/step2/templates/editmenuitem.html +++ b/Lesson4/step2/templates/editmenuitem.html @@ -1,58 +1,65 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -
-
-
- -
-
-
-
- - + {% include "header.html" %} +
+
+
+ +
+
+ +
+ + - - + + - -
-
$
- -
- -
- -
-
- -
-
- -
-
- -
- - - - -
- -
-
+ +
+
$
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ + + + +
+ +
+
{% endblock %} \ No newline at end of file diff --git a/Lesson4/step2/templates/header.html b/Lesson4/step2/templates/header.html index e706801..1f7f1bb 100644 --- a/Lesson4/step2/templates/header.html +++ b/Lesson4/step2/templates/header.html @@ -1,15 +1,15 @@
- -
- {%if 'username' not in session %} - Click Here to Login - {% else %} - Logout - {% endif %} - -
+ +
+ {% if 'username' not in session %} + Click Here to Login + {% else %} + Logout + {% endif %} + +
\ No newline at end of file diff --git a/Lesson4/step2/templates/login.html b/Lesson4/step2/templates/login.html index ba2472a..ab7c7bc 100644 --- a/Lesson4/step2/templates/login.html +++ b/Lesson4/step2/templates/login.html @@ -1,147 +1,128 @@ - +{% extends "main.html" %} +{% block content %} - - - - - - - - - - - - - - - - - -
- +
+ +
+ + + + + +{% endblock %} + +{% block scripts %} + + + + + +{% endblock %} diff --git a/Lesson4/step2/templates/main.html b/Lesson4/step2/templates/main.html index 75de0c9..da8af1a 100644 --- a/Lesson4/step2/templates/main.html +++ b/Lesson4/step2/templates/main.html @@ -1,14 +1,21 @@ - - - - - - -
- {% block content %} - {% endblock %} -
- + + + + + {% block css %} + {% endblock %} + + +
+ {% block content %} + {% endblock %} +
+{% block scripts %} +{% endblock %} + \ No newline at end of file diff --git a/Lesson4/step2/templates/menu.html b/Lesson4/step2/templates/menu.html index b56a5f1..2b7c576 100644 --- a/Lesson4/step2/templates/menu.html +++ b/Lesson4/step2/templates/menu.html @@ -1,114 +1,133 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -
-
-
- -
- {% with messages = get_flashed_messages() %} - {% if messages %} - -
    - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} - {% endwith %} +
+ {% with messages = get_flashed_messages() %} + {% if messages %} -
- - - {% if items !=[] %} -
-
-
-

Appetizers

- {% for i in items %} - {% if i.course == 'Appetizer' %} - - {% endif %} - {% endfor %} -
-
-

Entrees

- {% for i in items %} - {% if i.course == 'Entree' %} - - {% endif %} - {% endfor %} -
-
-

Desserts

- {% for i in items %} - {% if i.course == 'Dessert' %} - - {% endif %} - {% endfor %} -

Beverages

- {% for i in items %} - {% if i.course == 'Beverage' %} - - {% endif %} - {% endfor %} -
-
-
- {% endif %} +
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} + {% endwith %} + +
+ {% if login_session.user_id == restaurant.user_id %} + + {% endif %} + + {% if items !=[] %} +
+
+
+

Appetizers

+ {% for i in items %} + {% if i.course == 'Appetizer' %} + + {% endif %} + {% endfor %} +
+
+

Entrees

+ {% for i in items %} + {% if i.course == 'Entree' %} + + {% endif %} + {% endfor %} +
+
+

Desserts

+ {% for i in items %} + {% if i.course == 'Dessert' %} + + {% endif %} + {% endfor %} +

Beverages

+ {% for i in items %} + {% if i.course == 'Beverage' %} + + {% endif %} + {% endfor %} +
+
+
+ {% endif %} {% endblock %} diff --git a/Lesson4/step2/templates/newRestaurant.html b/Lesson4/step2/templates/newRestaurant.html index 978cfd4..e98e1ff 100644 --- a/Lesson4/step2/templates/newRestaurant.html +++ b/Lesson4/step2/templates/newRestaurant.html @@ -1,25 +1,26 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -
-
-
- -
-
-
-
- - -
- -
-
-
-
+ {% include "header.html" %} +
+
+
+ +
+
+
+
+ + +
+ +
+
+
+
{% endblock %} diff --git a/Lesson4/step2/templates/newmenuitem.html b/Lesson4/step2/templates/newmenuitem.html index 88a1d51..25b6c67 100644 --- a/Lesson4/step2/templates/newmenuitem.html +++ b/Lesson4/step2/templates/newmenuitem.html @@ -1,55 +1,57 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -
-
-
- -
-
-
-
- - + {% include "header.html" %} +
+
+
+ +
+
+ +
+ + - - + + - -
-
$
- -
- -
- -
-
- -
-
- -
-
- -
- -
- -
-
+ +
+
$
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
{% endblock %} diff --git a/Lesson4/step2/templates/publicmenu.html b/Lesson4/step2/templates/publicmenu.html deleted file mode 100644 index ac6dc5d..0000000 --- a/Lesson4/step2/templates/publicmenu.html +++ /dev/null @@ -1,95 +0,0 @@ -{% extends "main.html" %} -{% block content %} -{% include "header.html" %} - -
-
-
- -
-
-
- -
-
-
-
-
- {% with messages = get_flashed_messages() %} - {% if messages %} -
    - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} - {% endwith %} -
-
- {% if items !=[] %} -
-
-
-

Appetizers

- {% for i in items %} - {% if i.course == 'Appetizer' %} - - {% endif %} - {% endfor %} -
-
-

Entrees

- {% for i in items %} - {% if i.course == 'Entree' %} - - {% endif %} - {% endfor %} -
-
-

Desserts

- {% for i in items %} - {% if i.course == 'Dessert' %} - - {% endif %} - {% endfor %} -

Beverages

- {% for i in items %} - {% if i.course == 'Beverage' %} - - {% endif %} - {% endfor %} -
-
-
- {% endif %} -{% endblock %} diff --git a/Lesson4/step2/templates/publicrestaurants.html b/Lesson4/step2/templates/publicrestaurants.html deleted file mode 100644 index 63c4ec7..0000000 --- a/Lesson4/step2/templates/publicrestaurants.html +++ /dev/null @@ -1,53 +0,0 @@ -{% extends "main.html" %} -{% block content %} - -
-
-
- - -
- {% with messages = get_flashed_messages() %} - {% if messages %} - -
    - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} - {% endwith %} - -
- - - -
-
-
- -
-
-
- {% for restaurant in restaurants %} - -
-
-
-

{{restaurant.name}}

-
-
-
-
- {% endfor %} -{% endblock %} diff --git a/Lesson4/step2/templates/restaurants.html b/Lesson4/step2/templates/restaurants.html index 33de351..12d7193 100644 --- a/Lesson4/step2/templates/restaurants.html +++ b/Lesson4/step2/templates/restaurants.html @@ -1,55 +1,62 @@ {% extends "main.html" %} {% block content %} -{% include "header.html" %} -
-
-
-
-
-
-
-
- + {% include "header.html" %} +
+
+
+
+
+
+
+
+ -
- {% with messages = get_flashed_messages() %} - {% if messages %} - -
    - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} - {% endwith %} +
+ {% with messages = get_flashed_messages() %} + {% if messages %} -
- - - {% for restaurant in restaurants %} - -
-
-
-

{{restaurant.name}}

-
-
-
-
- {% endfor %} +
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} + {% endwith %} + +
+ {% if login_session.user_id %} + + {% endif %} + {% for restaurant in restaurants %} + +
+
+
+

+ {% if login_session.user_id == restaurant.user_id %} +   + {% endif %} + {{ restaurant.name }} +

+ +
+
+
+
+ {% endfor %} {% endblock %} diff --git a/Lesson4/step2/variables.py b/Lesson4/step2/variables.py new file mode 100644 index 0000000..b7c6fdd --- /dev/null +++ b/Lesson4/step2/variables.py @@ -0,0 +1,47 @@ +from os import environ + +from dotenv import load_dotenv, find_dotenv + +load_dotenv(find_dotenv()) + +google_web = dict( + client_id=environ.get("google_client_id", "google_client_id_here"), + project_id=environ.get("google_project_id", "google_project_id_here"), + auth_uri=environ.get( + "google_auth_uri", + "https://accounts.google.com/o/oauth2/auth" + ), + token_uri=environ.get( + "google_token_uri", + "https://accounts.google.com/o/oauth2/token" + ), + auth_provider_x509_cert_url=environ.get( + "google_x509", + "https://www.googleapis.com/oauth2/v1/certs" + ), + client_secret=environ.get( + "google_client_secret", + "google_client_secret_here" + ), + javascript_origins=[ + "http://localhost:5000" + ], + scope='', + redirect_uris=[ + "https://localhost:5000/callback", + "http://localhost:5000/callback" + ] +) + +facebook_web = dict( + app_id=environ.get('facebook_app_id', 'facebook_app_id_goes_here'), + app_secret=environ.get( + 'facebook_app_secret', + 'facebook_app_secret_goes_here' + ) +) + +main_app = dict( + secret_key=environ.get('app_secret_key', 'super secret key'), + debug=environ.get('debug', True) +)