diff --git a/client_secrets.json b/client_secrets.json new file mode 100644 index 0000000..705db88 --- /dev/null +++ b/client_secrets.json @@ -0,0 +1 @@ +{"web":{"client_id":"572235577549-tfbi0cfuv710lnbiddopr0ol0lu7ussp.apps.googleusercontent.com","project_id":"restaurant-menu-app-163714","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"4uwv69qFZ7_Ui70Lum1wxL-K","redirect_uris":"http://localhost:5000"}} \ No newline at end of file diff --git a/database_setup.py b/database_setup.py new file mode 100644 index 0000000..c02f525 --- /dev/null +++ b/database_setup.py @@ -0,0 +1,63 @@ +from sqlalchemy import Column, ForeignKey, Integer, String +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship +from sqlalchemy import create_engine + +Base = declarative_base() + + +class User(Base): + __tablename__ = 'user' + + id = Column(Integer, primary_key=True) + name = Column(String(250), nullable=False) + email = Column(String(250), nullable=False) + picture = Column(String(250)) + + +class Restaurant(Base): + __tablename__ = 'restaurant' + + id = Column(Integer, primary_key=True) + name = Column(String(250), nullable=False) + user_id = Column(Integer, ForeignKey('user.id')) + user = relationship(User) + + @property + def serialize(self): + """Return object data in easily serializeable format""" + return { + 'name': self.name, + 'id': self.id, + } + + +class MenuItem(Base): + __tablename__ = 'menu_item' + + name = Column(String(80), nullable=False) + id = Column(Integer, primary_key=True) + description = Column(String(250)) + price = Column(String(8)) + course = Column(String(250)) + restaurant_id = Column(Integer, ForeignKey('restaurant.id')) + restaurant = relationship(Restaurant) + user_id = Column(Integer, ForeignKey('user.id')) + user = relationship(User) + + @property + def serialize(self): + """Return object data in easily serializeable format""" + return { + 'name': self.name, + 'description': self.description, + 'id': self.id, + 'price': self.price, + 'course': self.course, + } + + +engine = create_engine('sqlite:///restaurantmenuwithusers.db') + + +Base.metadata.create_all(engine) \ No newline at end of file diff --git a/database_setup.pyc b/database_setup.pyc new file mode 100644 index 0000000..4d6aa4f Binary files /dev/null and b/database_setup.pyc differ diff --git a/lotsofmenus.py b/lotsofmenus.py new file mode 100644 index 0000000..2b7eaac --- /dev/null +++ b/lotsofmenus.py @@ -0,0 +1,386 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +from database_setup import Restaurant, Base, MenuItem, User + +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 + +DBSession = sessionmaker(bind=engine) +# A DBSession() instance establishes all conversations with the database +# and represents a "staging zone" for all the objects loaded into the +# database session object. Any change made against the objects in the +# session won't be persisted into the database until you call +# session.commit(). If you're not happy about the changes, you can +# revert all of them back to the last commit by calling +# session.rollback() +session = DBSession() + + +# 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) +session.commit() + + +# Menu for Thyme for that +restaurant1 = Restaurant(user_id=1, name="Thyme for That Vegetarian Cuisine ") + +session.add(restaurant1) +session.commit() + + +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() + +menuItem2 = MenuItem(user_id=1, name="Mushroom risotto", description="Portabello mushrooms in a creamy risotto", + price="$5.99", course="Entree", restaurant=restaurant1) + +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!" \ No newline at end of file diff --git a/pg_config.sh b/pg_config.sh new file mode 100644 index 0000000..e68f3c4 --- /dev/null +++ b/pg_config.sh @@ -0,0 +1,10 @@ +apt-get -qqy update +apt-get -qqy install postgresql python-psycopg2 +apt-get -qqy install python-sqlalchemy +apt-get -qqy install python-pip +pip install werkzeug==0.8.3 +pip install flask==0.9 +pip install Flask-Login==0.1.3 +pip install oauth2client +pip install requests +pip install httplib2 diff --git a/project.py b/project.py new file mode 100644 index 0000000..d4158b2 --- /dev/null +++ b/project.py @@ -0,0 +1,378 @@ +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 +import random +import string +from oauth2client.client import flow_from_clientsecrets +from oauth2client.client import FlowExchangeError +import httplib2 +import json +from flask import make_response +import requests + +app = Flask(__name__) + +CLIENT_ID = json.loads( + open('client_secrets.json', 'r').read())['web']['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 +@app.route('/login') +def showLogin(): + state = ''.join( + random.choice(string.ascii_uppercase + string.digits) for x in xrange(32)) + login_session['state'] = state + # return "The current session state is %s" % login_session['state'] + return render_template('login.html', STATE=state) + + + +@app.route('/gconnect', methods=['POST']) +def gconnect(): + # Validate state token + if request.args.get('state') != login_session['state']: + response = make_response(json.dumps('Invalid state parameter.'), 401) + response.headers['Content-Type'] = 'application/json' + return response + + + # Obtain authorization code + code = request.data + + try: + # Upgrade the authorization code into a credentials object + oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='') + oauth_flow.redirect_uri = 'postmessage' + credentials = oauth_flow.step2_exchange(code) + except FlowExchangeError: + response = make_response( + json.dumps('Failed to upgrade the authorization code.'), 401) + response.headers['Content-Type'] = 'application/json' + return response + + # Check that the access token is valid. + access_token = credentials.access_token + url = ('https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s' + % access_token) + h = httplib2.Http() + result = json.loads(h.request(url, 'GET')[1]) + # If there was an error in the access token info, abort. + if result.get('error') is not None: + response = make_response(json.dumps(result.get('error')), 500) + response.headers['Content-Type'] = 'application/json' + + # Verify that the access token is used for the intended user. + gplus_id = credentials.id_token['sub'] + if result['user_id'] != gplus_id: + response = make_response( + json.dumps("Token's user ID doesn't match given user ID."), 401) + response.headers['Content-Type'] = 'application/json' + return response + + # Verify that the access token is valid for this app. + if result['issued_to'] != 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_credentials = login_session.get('credentials') + stored_gplus_id = login_session.get('gplus_id') + if stored_credentials 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 + + # Store the access token in the session for later use. + login_session['credentials'] = credentials.to_json() + login_session['gplus_id'] = gplus_id + + # Get user info + userinfo_url = "https://www.googleapis.com/oauth2/v1/userinfo" + params = {'access_token': credentials.access_token, 'alt': 'json'} + answer = requests.get(userinfo_url, params=params) + + data = json.loads(answer.text) + + login_session['username'] = data['name'] + login_session['picture'] = data['picture'] + login_session['email'] = data['email'] + # ADD PROVIDER TO LOGIN SESSION + login_session['provider'] = 'google' + + # see if user exists, if it doesn't make a new one + user_id = getUserID(login_session["email"]) + if not user_id: + user_id = createUser(login_session) + login_session['user_id'] = user_id + + + output = '' + output += '