diff --git a/login/.app.py.swp b/login/.app.py.swp
new file mode 100644
index 0000000..28cf93c
Binary files /dev/null and b/login/.app.py.swp differ
diff --git a/login/app.py b/login/app.py
new file mode 100644
index 0000000..30f6928
--- /dev/null
+++ b/login/app.py
@@ -0,0 +1,274 @@
+# Python standard libraries
+import json
+import os
+import sqlite3
+
+# Third-party libraries
+import flask
+from flask import Flask, redirect, request, url_for
+from flask_login import (
+ LoginManager,
+ current_user,
+ login_required,
+ login_user,
+ logout_user,
+)
+from oauthlib.oauth2 import WebApplicationClient
+import requests
+
+# Internal imports
+from db import init_db_command
+from user import User
+
+
+import google.oauth2.credentials
+import google_auth_oauthlib.flow
+import googleapiclient.discovery
+
+# Configuration
+
+CLIENT_SECRETS_FILE = "client_secret.json"
+
+# This OAuth 2.0 access scope allows for full read/write access to the
+# authenticated user's account and requires requests to use an SSL connection.
+SCOPES = ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/calendar.readonly", "openid"]
+API_SERVICE_NAME = 'calendar'
+API_VERSION = 'v3'
+
+GOOGLE_CLIENT_ID ="377787187748-shuvi4iq5bi4gdet6q3ioataimobs4lh.apps.googleusercontent.com"
+GOOGLE_CLIENT_SECRET = "Hu_YWmKsVKUcLwyeINYzdKfZ"
+GOOGLE_DISCOVERY_URL = (
+ "https://accounts.google.com/.well-known/openid-configuration"
+)
+
+API_SERVICE_NAME = 'calendar'
+API_VERSION = 'v3'
+
+# Flask app setup
+app = Flask(__name__)
+app.secret_key = os.environ.get("SECRET_KEY") or os.urandom(24)
+
+# User session management setup
+# https://flask-login.readthedocs.io/en/latest
+login_manager = LoginManager()
+login_manager.init_app(app)
+
+# Naive database setup
+try:
+ init_db_command()
+except sqlite3.OperationalError:
+ # Assume it's already been created
+ pass
+
+# 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_id):
+ return User.get(user_id)
+
+@app.route("/")
+def index():
+ if current_user.is_authenticated:
+ return (
+ "
Hello, {}! You're logged in! Email: {}
"
+ "Google Profile Picture:
"
+ '
'
+ 'Logout'
+ 'test API'.format(
+ current_user.name, current_user.email, current_user.profile_pic
+ )
+ )
+ else:
+ return 'Google Login'
+
+def get_google_provider_cfg():
+ return requests.get(GOOGLE_DISCOVERY_URL).json()
+
+@app.route('/test')
+def test_api_request():
+ if 'credentials' not in flask.session:
+ return flask.redirect('login')
+
+ # Load credentials from the session.
+ credentials = google.oauth2.credentials.Credentials(
+ **flask.session['credentials'])
+
+ service = googleapiclient.discovery.build(
+ API_SERVICE_NAME, API_VERSION, credentials=credentials)
+
+
+ # Save credentials back to session in case access token was refreshed.
+ # ACTION ITEM: In a production app, you likely want to save these
+ # credentials in a persistent database instead.
+ flask.session['credentials'] = credentials_to_dict(credentials)
+
+ return flask.jsonify("{}")
+
+@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/calendar.readonly"],
+ )
+ return redirect(request_uri)
+ '''
+
+ # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
+ flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
+ CLIENT_SECRETS_FILE, scopes=SCOPES)
+
+ # The URI created here must exactly match one of the authorized redirect URIs
+ # for the OAuth 2.0 client, which you configured in the API Console. If this
+ # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch'
+ # error.
+ flow.redirect_uri = request.base_url + "/callback"
+
+ authorization_url, state = flow.authorization_url(
+ # Enable offline access so that you can refresh an access token without
+ # re-prompting the user for permission. Recommended for web server apps.
+ access_type='offline',
+ # Enable incremental authorization. Recommended as a best practice.
+ include_granted_scopes='true')
+
+ # Store the state so the callback can verify the auth server response.
+ flask.session['state'] = state
+
+ print("auth_url: " + authorization_url)
+ print("state: " + state)
+
+ return flask.redirect(authorization_url)
+
+@app.route("/login/callback")
+def callback():
+ print("in callback")
+
+ # Specify the state when creating the flow in the callback so that it can
+ # verified in the authorization server response.
+ state = flask.session['state']
+
+ flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
+ CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
+ flow.redirect_uri = request.base_url
+
+ # Use the authorization server's response to fetch the OAuth 2.0 tokens.
+ authorization_response = flask.request.url
+ flow.fetch_token(authorization_response=authorization_response)
+
+ # Store credentials in the session.
+ # ACTION ITEM: In a production app, you likely want to save these
+ # credentials in a persistent database instead.
+ credentials = flow.credentials
+ flask.session['credentials'] = credentials_to_dict(credentials)
+
+ session = flow.authorized_session()
+ print(session.get('https://www.googleapis.com/userinfo/v2/me').json())
+
+ # Create a user in your db with the information provided
+ # by Google
+ user = User(
+ id_=unique_id, name=users_name, email=users_email, profile_pic=picture
+ )
+
+ # Doesn't exist? Add it to the database.
+ if not User.get(unique_id):
+ User.create(unique_id, users_name, users_email, picture)
+
+ # Begin user session by logging the user in
+ login_user(user)
+ return flask.redirect(flask.url_for('index'))
+
+ '''
+ # Get authorization code Google sent back to you
+ code = request.args.get("code")
+ # Find out what URL to hit to get tokens that allow you to ask for
+ # things on behalf of a user
+ google_provider_cfg = get_google_provider_cfg()
+ token_endpoint = google_provider_cfg["token_endpoint"]
+
+ # 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
+ )
+
+ print("asking for tokens")
+
+ 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)
+ print(userinfo_response.json())
+
+ # You want to make sure their email is verified.
+ # The user authenticated with Google, authorized your
+ # app, and now you've verified their email through Google!
+ 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(
+ id_=unique_id, name=users_name, email=users_email, profile_pic=picture
+ )
+
+ # Doesn't exist? Add it to the database.
+ if not User.get(unique_id):
+ User.create(unique_id, 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()
+ return redirect(url_for("index"))
+
+def credentials_to_dict(credentials):
+ return {'token': credentials.token,
+ 'refresh_token': credentials.refresh_token,
+ 'token_uri': credentials.token_uri,
+ 'client_id': credentials.client_id,
+ 'client_secret': credentials.client_secret,
+ 'scopes': credentials.scopes}
+
+if __name__ == "__main__":
+ app.run('192.168.68.103.xip.io', 1234, ssl_context="adhoc", debug=True)
+
+
+
diff --git a/client_secret.json b/login/client_secret.json
similarity index 100%
rename from client_secret.json
rename to login/client_secret.json
diff --git a/login/db.py b/login/db.py
new file mode 100644
index 0000000..60e4af5
--- /dev/null
+++ b/login/db.py
@@ -0,0 +1,38 @@
+# http://flask.pocoo.org/docs/1.0/tutorial/database/
+import sqlite3
+
+import click
+from flask import current_app, g
+from flask.cli import with_appcontext
+
+def get_db():
+ if "db" not in g:
+ g.db = sqlite3.connect(
+ "sqlite_db", detect_types=sqlite3.PARSE_DECLTYPES
+ )
+ g.db.row_factory = sqlite3.Row
+
+ return g.db
+
+def close_db(e=None):
+ db = g.pop("db", None)
+
+ if db is not None:
+ db.close()
+
+def init_db():
+ db = get_db()
+
+ with current_app.open_resource("schema.sql") as f:
+ db.executescript(f.read().decode("utf8"))
+
+@click.command("init-db")
+@with_appcontext
+def init_db_command():
+ """Clear the existing data and create new tables."""
+ init_db()
+ click.echo("Initialized the database.")
+
+def init_app(app):
+ app.teardown_appcontext(close_db)
+ app.cli.add_command(init_db_command)
diff --git a/login/schema.sql b/login/schema.sql
new file mode 100644
index 0000000..5c71573
--- /dev/null
+++ b/login/schema.sql
@@ -0,0 +1,6 @@
+CREATE TABLE user (
+ id TEXT PRIMARY KEY,
+ name TEXT NOT NULL,
+ email TEXT UNIQUE NOT NULL,
+ profile_pic TEXT NOT NULL
+);
diff --git a/login/sqlite_db b/login/sqlite_db
new file mode 100644
index 0000000..42d1c94
Binary files /dev/null and b/login/sqlite_db differ
diff --git a/login/user.py b/login/user.py
new file mode 100644
index 0000000..e8165a5
--- /dev/null
+++ b/login/user.py
@@ -0,0 +1,34 @@
+from flask_login import UserMixin
+
+from db import get_db
+
+class User(UserMixin):
+ def __init__(self, id_, name, email, profile_pic):
+ self.id = id_
+ self.name = name
+ self.email = email
+ self.profile_pic = profile_pic
+
+ @staticmethod
+ def get(user_id):
+ db = get_db()
+ user = db.execute(
+ "SELECT * FROM user WHERE id = ?", (user_id,)
+ ).fetchone()
+ if not user:
+ return None
+
+ user = User(
+ id_=user[0], name=user[1], email=user[2], profile_pic=user[3]
+ )
+ return user
+
+ @staticmethod
+ def create(id_, name, email, profile_pic):
+ db = get_db()
+ db.execute(
+ "INSERT INTO user (id, name, email, profile_pic) "
+ "VALUES (?, ?, ?, ?)",
+ (id_, name, email, profile_pic),
+ )
+ db.commit()
diff --git a/test1/client_secret.json b/test1/client_secret.json
new file mode 100644
index 0000000..2104b71
--- /dev/null
+++ b/test1/client_secret.json
@@ -0,0 +1 @@
+{"web":{"client_id":"377787187748-shuvi4iq5bi4gdet6q3ioataimobs4lh.apps.googleusercontent.com","project_id":"calendarwatch-1584185874753","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"Hu_YWmKsVKUcLwyeINYzdKfZ","redirect_uris":["http://localhost:1234"],"javascript_origins":["http://raphael.maenle.net","https://raphael.maenle.net"]}}
diff --git a/index.html b/test1/index.html
similarity index 100%
rename from index.html
rename to test1/index.html
diff --git a/index.js b/test1/index.js
similarity index 100%
rename from index.js
rename to test1/index.js
diff --git a/server.py b/test1/server.py
similarity index 84%
rename from server.py
rename to test1/server.py
index 75f47f4..e43f9ed 100644
--- a/server.py
+++ b/test1/server.py
@@ -14,17 +14,23 @@ CLIENT_SECRETS_FILE = "client_secret.json"
# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
-SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
-API_SERVICE_NAME = 'drive'
-API_VERSION = 'v2'
+SCOPES = ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/calendar.readonly", "openid"]
+API_SERVICE_NAME = 'calendar'
+API_VERSION = 'v3'
app = flask.Flask(__name__)
# Note: A secret key is included in the sample so that it works.
# If you use this code in your application, replace this with a truly secret
# key. See https://flask.palletsprojects.com/quickstart/#sessions.
-app.secret_key = 'REPLACE ME - this value is here as a placeholder.'
+app.secret_key = 'N\x0cOZO\xca\x96b\xf0\\\xc7\x11\xbd(\x95\xe3'
+class Calendar:
+ def __init__(self, summary_, calendarId_, color_):
+ self.summary = summary_
+ self.calendarId = calendarId_
+ self.color = color_
+
@app.route('/')
def index():
return print_index_table()
@@ -39,17 +45,17 @@ def test_api_request():
credentials = google.oauth2.credentials.Credentials(
**flask.session['credentials'])
- drive = googleapiclient.discovery.build(
+ service = googleapiclient.discovery.build(
API_SERVICE_NAME, API_VERSION, credentials=credentials)
- files = drive.files().list().execute()
+ getCalendars(service)
# Save credentials back to session in case access token was refreshed.
# ACTION ITEM: In a production app, you likely want to save these
# credentials in a persistent database instead.
flask.session['credentials'] = credentials_to_dict(credentials)
- return flask.jsonify(**files)
+ return flask.jsonify("{}")
@app.route('/authorize')
@@ -74,6 +80,9 @@ def authorize():
# Store the state so the callback can verify the auth server response.
flask.session['state'] = state
+ print("auth_url: " + authorization_url)
+ print("state: " + state)
+
return flask.redirect(authorization_url)
@@ -96,6 +105,8 @@ def oauth2callback():
# credentials in a persistent database instead.
credentials = flow.credentials
flask.session['credentials'] = credentials_to_dict(credentials)
+ print("credentials: ")
+ print(credentials_to_dict(credentials))
return flask.redirect(flask.url_for('test_api_request'))
@@ -157,6 +168,19 @@ def print_index_table():
' API request again, you should go back to the auth flow.' +
'')
+def getCalendars(service):
+ page_token = None
+ calendars = []
+ while True:
+ calendar_list = service.calendarList().list(pageToken=page_token).execute()
+ for calendar in calendar_list['items']:
+ calendars.append(Calendar(calendar['summary'], calendar['id'], calendar['colorId']))
+ page_token = calendar_list.get('nextPageToken')
+ if not page_token:
+ break
+
+ print(calendars)
+
if __name__ == '__main__':
# When running locally, disable OAuthlib's HTTPs verification.
diff --git a/website.py b/test1/website.py
similarity index 100%
rename from website.py
rename to test1/website.py