# """ # Module that control the authentication app. The authetication flow is as follow: # 1.- A HTTP post is made to MG/authenticate/drive (goes to POST examples). # 2.- Follow the url returned by this method. Logging with the google account wanted # and allow all the permissions. # 3.- The authentication flow is completed. # # Behind the scene: # 1.- When step one is received the google library are used to make the registration # url. Then this url is sent to the user. # 2.- When user finish the login process an HTTP GET is received in MG/authentication/drive. # This request has the information needed to finished the OAuth process and get the # authorization token to access the client's google drive. # 3.- The parameters of the authorization is saved to disk. # # Warnings # -------- # - The credentials are removed when the server is restarted, so the authentication flow must be # relaunched. # # Notes # ----- # - The credentials are saved in a sqlite3 file with the following structure: # * Tables: # - users: # +----------+--------------+ # | name | GDriveID | # +----------+--------------+ # - name (TEXT PRIMARY KEY): Name of the authenticated user. # - GDriveID (TEXT): Unique identification for a gdrive element. # - gdrive # +----------+--------------+-----------+----------+ # | id | user_email | user_id | cred | # +----------+--------------+-----------+----------+ # - id (TEXT PRIMARY KEY): Id of the authentication parameters. Must be the same as # GDriveID. # - user_email (TEXT): Email of the user # - user_id (TEXT): Google identification string of user. # - cred (TEXT): Encrypted credentials in a json string format. # """ # from __future__ import print_function # import json # import os.path # import uuid # import sqlite3 # from django.conf import settings # from django.http import HttpRequest, HttpResponse # from cryptography.fernet import Fernet # from google_auth_oauthlib.flow import Flow # from google.oauth2.credentials import Credentials # from googleapiclient.discovery import build # # from tools.service.http_loaders import invisible_out, invisible_in # from tools.parser import NoneParser # # # AUTH_PATH = os.path.join(settings.BASE_DIR, 'MG', 'authenticate', 'certs') # SCOPES = ['https://www.googleapis.com/auth/drive.file', # 'https://www.googleapis.com/auth/drive.install', # 'https://www.googleapis.com/auth/userinfo.email', # 'openid'] # # # def post(task, user=None, request=None): # """ # Trigger the authentication flow. After do the post follow the url returned. # Parameters # ---------- # user: str # User to register # request: HttpRequest # Django request # # Returns # ------- # str: # Url to complete the authentication flow. # # Examples # -------- # >>> import requests # >>> parameters={'user':'test'} # >>> response = requests.post(':/MG/authenticate/drive', # ... json=parameters) # >>> response.json() # "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=763575270216-c # 9pmt2o1npa6md49keck7jtptfjmds79.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0. # 0.1%3A1114%2FMG%2Fauthenticate%2Fdrive%2Ftest2&scope=https%3A%2F%2Fwww.googleapis.com # %2Fauth%2Fdrive.file+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.install+https%3A%2F%2F # www.googleapis.com%2Fauth%2Fuserinfo.email+openid&state=oVF6TpVKEGVzcgEG8CRs3TvdPfUSRb& # access_type=offline" # # """ # user = json.loads(request.body.decode('utf8'))["user"] # host = request.get_host() # # flow = Flow.from_client_secrets_file(settings.GDRIVE_API_CREDENTIALS_PATH, SCOPES) # http_protoc = request.scheme # flow.redirect_uri = "{}://{}/MG/authenticate/drive/{}".format(http_protoc, host, user) # auth_url, _ = flow.authorization_url() # return auth_url # # # POST_REQUEST = { # 'function': post, # 'http_p': invisible_in, # 'parser': NoneParser # } # # # def get(_, user: str = None, request: HttpRequest = None): # """ # This functionality is only internal. This method would be called from the google # consent screen. # """ # host = request.get_host() # flow = Flow.from_client_secrets_file(settings.GDRIVE_API_CREDENTIALS_PATH, SCOPES) # flow.redirect_uri = "{}://{}/MG/authenticate/drive/{}".format(request.scheme, host, user) # # authorization_response = "https://{}{}".format(host, # request.get_full_path().replace('http', 'https')) # flow.fetch_token(authorization_response=authorization_response) # # # Check user # cred = Credentials.from_authorized_user_info(json.loads(flow.credentials.to_json()), SCOPES) # user_info_service = build('oauth2', 'v2', credentials=cred) # user_info = user_info_service.userinfo().get().execute() # # # Encrypt file # with open(settings.CIPHER_KEY, 'rb') as key_file: # key = key_file.read() # fernet = Fernet(key) # # # checking user credentials # conn = sqlite3.connect(settings.CERTS_DB_PATH) # res = list(conn.execute('SELECT GDriveID FROM users where name=\'{}\''.format(user))) # if res: # gdriveid = res[0][0] # conn.execute('REPLACE INTO gdrive (id, email, user_id, cred) VALUES ' # '("{drive_id}", "{email}", "{user_id}", "{cred}");' # .format(drive_id=gdriveid, email=user_info['email'], # user_id=user_info['id'], # cred=fernet.encrypt(flow.credentials.to_json().encode()).decode())) # else: # gdriveid = uuid.uuid4().hex # conn.execute('INSERT INTO gdrive (id, email, user_id, cred) VALUES ' # '("{drive_id}", "{email}", "{user_id}", "{cred}");' # .format(drive_id=gdriveid, email=user_info['email'], # user_id=user_info['id'], # cred=fernet.encrypt(flow.credentials.to_json().encode()).decode())) # conn.execute('INSERT INTO users (name, GDriveID) VALUES ' # '("{name}", "{drive_id}");' # .format(drive_id=gdriveid, name=user)) # conn.commit() # conn.close() # # return HttpResponse('Created') # # # GET_REQUEST = { # 'function': get, # 'http_p': invisible_in, # 'http_rm': invisible_out, # 'parser': NoneParser # }