188 lines
6.8 KiB
Python
188 lines
6.8 KiB
Python
import google.oauth2.credentials
|
|
import google_auth_oauthlib.flow
|
|
import googleapiclient.discovery
|
|
|
|
import backend.caltojson as caltojson
|
|
from oauthlib.oauth2 import WebApplicationClient
|
|
import flask
|
|
|
|
# Python standard libraries
|
|
import json
|
|
import os
|
|
|
|
# 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,
|
|
)
|
|
import requests
|
|
|
|
from database.models import Calendar as dbCalendar
|
|
from server import db
|
|
# Configuration
|
|
class GoogleClient():
|
|
def __init__(self):
|
|
self.CLIENT_SECRETS_FILE = "certificate/client_secret.json"
|
|
|
|
with open("/home/calendarwatch/certificate/google_client.json", encoding='utf-8') as json_file:
|
|
self.google_client = json.load(json_file)
|
|
|
|
self.SCOPES = self.google_client.get('scopes')
|
|
self.API_SERVICE_NAME = 'calendar'
|
|
self.API_VERSION = 'v3'
|
|
|
|
# GOOGLE_CLIENT_ID ="377787187748-shuvi4iq5bi4gdet6q3ioataimobs4lh.apps.googleusercontent.com"
|
|
self.GOOGLE_CLIENT_ID = self.google_client.get('client_id')
|
|
# GOOGLE_CLIENT_SECRET = "Hu_YWmKsVKUcLwyeINYzdKfZ"
|
|
self.GOOGLE_CLIENT_SECRET = self.google_client.get('client_secret')
|
|
self.GOOGLE_DISCOVERY_URL = (
|
|
"https://accounts.google.com/.well-known/openid-configuration"
|
|
)
|
|
|
|
# OAuth 2 client setup
|
|
self.client = WebApplicationClient(self.GOOGLE_CLIENT_ID)
|
|
|
|
|
|
def build_credentials(self, token, refresh_token):
|
|
data = {}
|
|
data['token'] = token
|
|
data['refresh_token'] = refresh_token
|
|
data['token_uri'] = self.google_client.get('token_uri')
|
|
data['client_id'] = self.google_client.get('client_id')
|
|
data['client_secret'] = self.google_client.get('client_secret')
|
|
data['scopes'] = self.google_client.get('scopes')
|
|
return data
|
|
|
|
GC = GoogleClient()
|
|
|
|
def login():
|
|
# Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
|
|
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
|
GC.CLIENT_SECRETS_FILE, scopes=GC.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
|
|
# Flask-Login helper to retrieve a user from our db
|
|
return authorization_url
|
|
|
|
def verifyResponse():
|
|
# 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(
|
|
GC.CLIENT_SECRETS_FILE, scopes=GC.SCOPES, state=state)
|
|
flow.redirect_uri = flask.url_for('callback', _external=True)
|
|
|
|
# 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)
|
|
print(credentials_to_dict(credentials), flush=True)
|
|
session = flow.authorized_session()
|
|
return session, credentials_to_dict(credentials)
|
|
|
|
|
|
def get_google_provider_cfg():
|
|
return requests.get(GC.GOOGLE_DISCOVERY_URL).json()
|
|
|
|
def deleteAccount(user):
|
|
result = requests.post('https://oauth2.googleapis.com/revoke',
|
|
params={'token': user.google_token.token},
|
|
headers = {'content-type': 'applixation/x-www-form-urlencoded'})
|
|
print(result, flush=True)
|
|
return
|
|
|
|
class Calendar:
|
|
def __init__(self, name, calendarId, toggle='False', color="#000000"):
|
|
self.name = name
|
|
self.color = color
|
|
self.toggle=toggle
|
|
self.calendarId = calendarId
|
|
|
|
# TODO move this to databas
|
|
def calendarsFromDb():
|
|
pyCalendars = []
|
|
for calendar in current_user.calendars:
|
|
name = (calendar.name[:16] + '..') if len(calendar.name)> 18 else calendar.name
|
|
calendarId = calendar.calendar_id
|
|
toggle = calendar.toggle
|
|
color = calendar.color
|
|
|
|
pyCalendars.append(Calendar(name, calendarId, toggle, color))
|
|
|
|
return pyCalendars
|
|
|
|
|
|
def updateCalendars():
|
|
if 'credentials' not in flask.session:
|
|
return flask.redirect('login/google')
|
|
|
|
# Load credentials from the session.
|
|
# credentials = google.oauth2.credentials.Credentials(
|
|
# **flask.session['credentials'])
|
|
# a = flask.session['credentials']
|
|
# print(a, flush=True)
|
|
# print(current_user.getGoogleCredentials(), flush=True)
|
|
if current_user.google_token == None:
|
|
print("notok", flush=True)
|
|
return
|
|
|
|
client_token = GC.build_credentials(current_user.google_token.token,
|
|
current_user.google_token.refresh_token)
|
|
credentials = google.oauth2.credentials.Credentials(**client_token)
|
|
calendars = caltojson.getCalendarList(credentials)
|
|
print(calendars, flush=True)
|
|
for calendar in calendars:
|
|
print(calendar, flush=True)
|
|
if not current_user.hasCalendar(calendar.calendarId):
|
|
print("adding", flush=True)
|
|
c = dbCalendar(calendar_id=calendar.calendarId,
|
|
name = calendar.summary,
|
|
toggle = "False",
|
|
color = calendar.color)
|
|
db.session.add(c)
|
|
current_user.calendars.append(c)
|
|
|
|
db.session.commit()
|
|
print("updated Calendars")
|
|
# 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.
|
|
# TODO add save updated token to database here
|
|
flask.session['credentials'] = credentials_to_dict(credentials)
|
|
|
|
|
|
|
|
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}
|
|
|
|
|