I'm trying to create a Flask app that can browse to the user's Google Drive to select a file to convert to CSV format.
I found online a code to add Google Login (see below), but I don't understand how to print all files from the logged user. I figured out I need to add https://www.googleapis.com/auth/drive.file to the scope but I can't understand how to list all files from an authorized user (current_user.paying==True) in index. I know that this could be done with the following code, but I'm not sure how to defined the credentials.
In callback an access token is already generated, so I tried to access the Google Drive API to just search for the user's Google sheets:
from httplib2 import Http
from apiclient import discovery
from oauth2client import file
with open("./credentials.json", 'w') as outfile:
json.dump(token_response.json(), outfile)
store = file.Storage("./credentials.json")
credentials = store.get()
drive = discovery.build("drive", "v3", http=credentials.authorize(Http()))
files = drive.files().list(q="mimeType='application/vnd.google-apps.spreadsheet'").execute()
But this gives me an "KeyError: '_module'" error that's not very informative.
This is the entire Flask code with Google Login
import os
import requests
import json
from httplib2 import Http
from apiclient import discovery
from oauthlib.oauth2 import WebApplicationClient
from flask import Flask, redirect, request, url_for
from flask_login import LoginManager, current_user, login_required, login_user, logout_user
from flask_login import UserMixin
authorized_users = ["[email protected]"]
class User(UserMixin):
def __init__(self, id_, paying):
self.id = id_
self.paying = paying
@staticmethod
def get(user_email):
if user_email not in authorized_users:
user = User(user_email, False)
else:
user = User(user_email, True)
return user
# Configuration
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", None)
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", None)
GOOGLE_DISCOVERY_URL = ("https://accounts.google.com/.well-known/openid-configuration")
# Flask app setup
app = Flask(__name__)
app.secret_key = os.environ.get("SECRET_KEY") or os.urandom(24)
# User session management setup
login_manager = LoginManager()
login_manager.init_app(app)
# OAuth 2 client setup
client = WebApplicationClient(GOOGLE_CLIENT_ID)
# Flask-Login helper to retrieve a user from our db
@login_manager.user_loader
def load_user(user_email):
return User.get(user_email)
def get_google_provider_cfg():
return requests.get(GOOGLE_DISCOVERY_URL).json()
google_provider_cfg = get_google_provider_cfg()
token_endpoint = google_provider_cfg["token_endpoint"]
print("Google provider cfg", google_provider_cfg)
ACCESS_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token'
@app.route("/")
def index():
if current_user.is_authenticated:
if current_user.paying:
return f"<p>Hello, {current_user.id}! You're logged in!</p><br/><a class='button' href='/logout'>Logout</a>"
else:
return "Not authorized!<br/><a class='button' href='/logout'>Logout</a>"
else:
return f"<a class='button' href='/login'>Google Login</a>"
@app.route("/login")
def login():
# Find out what URL to hit for Google login
google_provider_cfg = get_google_provider_cfg()
authorization_endpoint = google_provider_cfg["authorization_endpoint"]
# Use library to construct the request for Google login and provide
# scopes that let you retrieve user's profile from Google
request_uri = client.prepare_request_uri(
authorization_endpoint,
redirect_uri=request.base_url + "/callback",
scope=["openid", "email", "profile", "https://www.googleapis.com/auth/drive.file"],
)
return redirect(request_uri)
@app.route("/login/callback")
def callback():
# Get authorization code Google sent back to you
code = request.args.get("code")
# Prepare and send a request to get tokens! Yay tokens!
token_url, headers, body = client.prepare_token_request(
token_endpoint,
authorization_response=request.url,
redirect_url=request.base_url,
code=code
)
token_response = requests.post(
token_url,
headers=headers,
data=body,
auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
)
# Parse the tokens!
client.parse_request_body_response(json.dumps(token_response.json()))
# Now that you have tokens (yay) let's find and hit the URL
# from Google that gives you the user's profile information,
# including their Google profile image and email
userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
uri, headers, body = client.add_token(userinfo_endpoint)
userinfo_response = requests.get(uri, headers=headers, data=body)
if userinfo_response.json().get("email_verified"):
# unique_id = userinfo_response.json()["sub"]
users_email = userinfo_response.json()["email"]
picture = userinfo_response.json()["picture"]
users_name = userinfo_response.json()["given_name"]
else:
return "User email not available or not verified by Google.", 400
# Create a user in your db with the information provided
# by Google
user = User(users_email, False)
#
# # Doesn't exist? Add it to the database.
# if not User.get(unique_id):
# User.create(unique_id, users_name, users_email, picture)
print("Logging", users_name, users_email, picture)
# Begin user session by logging the user in
login_user(user)
# Send user back to homepage
return redirect(url_for("index"))
@app.route("/logout")
@login_required
def logout():
logout_user()
print("Logging out")
return redirect(url_for("index"))
if __name__ == "__main__":
app.run(ssl_context="adhoc", debug=True)