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}
 | 
						|
 | 
						|
 |