Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so

# ignore all vagrant files
**/.vagrant

# ignore all .json files
*.json

# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip

# Logs and databases #
######################
*.log
*.sql
*.sqlite
Binary file added DeepinScreenshot_select-area_20190511121248.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# OAuth2.0
Starter Code for Auth&Auth course
# Making the Code work with latest OAuth2.0 googleApi changes with Javascript

This changed Codework has changes required to remove Jquery and Ajax completely and do all the Login and Logout requests using Javascript on python 2.7

No New libraries are required

The code is tested on the legacy vagrant environment

This code also has new features as *"signOut"* & *"Login"* links addeed to the restaurant page

![Restaurant main Page](https://github.com/sananand007/OAuth2.0/blob/master/DeepinScreenshot_select-area_20190511121248.png)


# Installing the Vagrant VM for ud330 - Authentication & Authorization

**Note: If you already have a vagrant machine installed from previous Udacity courses skip to the 'Fetch the Source Code and VM Configuration' section**
Expand Down
Binary file added database_setup.pyc
Binary file not shown.
166 changes: 162 additions & 4 deletions project.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
from flask import Flask, render_template, request, redirect,jsonify, url_for, flash
app = Flask(__name__)

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
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:///restaurantmenu.db')
Expand All @@ -14,6 +26,141 @@
session = DBSession()


@app.route('/login')
def showLogin():
state = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in xrange(32))
login_session['state'] = state
# Render the login template
return render_template('logingoogle.html', state = state, GOOGLE_CLIENT_ID=CLIENT_ID)

@app.route('/gconnect', methods=['POST'])
def gconnect():
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'
return response

# 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_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

# Store the access token in the session for later use.
login_session['access_token'] = credentials.access_token
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 = answer.json()
login_session['logged_in'] = True
login_session['provider'] = 'google'
login_session['username'] = data['name']
login_session['picture'] = data['picture']
login_session['email'] = data['email']

output = ''
output += '<h1>Welcome, '
output += login_session['username']
output += '!</h1>'
output += '<img src="'
output += login_session['picture']
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
# DISCONNECT - Revoke a current user's token and reset their login_session

@app.route('/sign-out')
def signOut():
access_token = None
if 'access_token' in login_session:
access_token = login_session['access_token']
print("access token", access_token)
if access_token is None:
print 'Access Token is None'
response = make_response(json.dumps(
'Current user not connected.'), 401)
response.headers['Content-Type'] = 'application/json'
return response
print 'In gdisconnect access token is %s', access_token
print 'Login session: '
print login_session.keys()
url = 'https://accounts.google.com/o/oauth2/revoke?token={}'.format(access_token)
h = httplib2.Http()
result = h.request(url, 'GET')[0]
print 'result is '
print result
if result['status'] == '200':
del login_session['logged_in']
del login_session['access_token']
del login_session['gplus_id']
del login_session['username']
del login_session['email']
del login_session['picture']
del login_session['provider']
flash("You have been logged out")
return render_template('signout.html', GOOGLE_CLIENT_ID=CLIENT_ID)
else:
response = make_response(json.dumps('Failed to revoke token for given user.', 400))
response.headers['Content-Type'] = 'application/json'
del login_session['logged_in']
del login_session['access_token']
del login_session['gplus_id']
del login_session['username']
del login_session['email']
del login_session['picture']
del login_session['provider']
flash("You have been logged out")
return render_template('signout.html', GOOGLE_CLIENT_ID=CLIENT_ID)
#return response

#JSON APIs to view Restaurant Information
@app.route('/restaurant/<int:restaurant_id>/menu/JSON')
def restaurantMenuJSON(restaurant_id):
Expand Down Expand Up @@ -43,6 +190,8 @@ def showRestaurants():
#Create a new restaurant
@app.route('/restaurant/new/', methods=['GET','POST'])
def newRestaurant():
if 'username' not in login_session:
return redirect('/login')
if request.method == 'POST':
newRestaurant = Restaurant(name = request.form['name'])
session.add(newRestaurant)
Expand All @@ -55,6 +204,8 @@ def newRestaurant():
#Edit a restaurant
@app.route('/restaurant/<int:restaurant_id>/edit/', methods = ['GET', 'POST'])
def editRestaurant(restaurant_id):
if 'username' not in login_session:
return redirect('/login')
editedRestaurant = session.query(Restaurant).filter_by(id = restaurant_id).one()
if request.method == 'POST':
if request.form['name']:
Expand All @@ -68,6 +219,8 @@ def editRestaurant(restaurant_id):
#Delete a restaurant
@app.route('/restaurant/<int:restaurant_id>/delete/', methods = ['GET','POST'])
def deleteRestaurant(restaurant_id):
if 'username' not in login_session:
return redirect('/login')
restaurantToDelete = session.query(Restaurant).filter_by(id = restaurant_id).one()
if request.method == 'POST':
session.delete(restaurantToDelete)
Expand All @@ -90,6 +243,8 @@ def showMenu(restaurant_id):
#Create a new menu item
@app.route('/restaurant/<int:restaurant_id>/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()
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)
Expand All @@ -103,7 +258,8 @@ def newMenuItem(restaurant_id):
#Edit a menu item
@app.route('/restaurant/<int:restaurant_id>/menu/<int:menu_id>/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()
if request.method == 'POST':
Expand All @@ -126,6 +282,8 @@ def editMenuItem(restaurant_id, menu_id):
#Delete a menu item
@app.route('/restaurant/<int:restaurant_id>/menu/<int:menu_id>/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()
if request.method == 'POST':
Expand Down
Binary file added restaurantmenu.db
Binary file not shown.
4 changes: 2 additions & 2 deletions templates/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<a href="{{url_for('showRestaurants')}}">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>Show All Restaurants
</a>
<a href="{{url_for('signOut')}}"><b>sign Out</b></a>
</div>
<div class="col-md-6 text-right">
<p>Login Link will go Here </p>

<a href="{{url_for('showLogin')}}"><b>Login</b></a>
</div>
</div>
Loading