diff --git a/api/main.py b/api/main.py index 543bcac..db3050f 100644 --- a/api/main.py +++ b/api/main.py @@ -236,7 +236,7 @@ async def app_startup(**kwargs): oauth_json = script_cred["google"]["oauth"]["tcaoff"], http_client = current_app.http_client, redirect_url = r"https://api.thecaoffice.com/converse/mail/callback/gmail", - debug = True, + debug = enable_debugging, debug_prefix = "GMail (M) | ", debug_only_errors = False ) diff --git a/models/behaviour/mail/sync.py b/models/behaviour/mail/sync.py new file mode 100644 index 0000000..febdce5 --- /dev/null +++ b/models/behaviour/mail/sync.py @@ -0,0 +1,199 @@ +""" + + AUTHOR: + + Khushal P Soonderji + + DATE: + + Wednesday, 27th Nov., 2024 + + OBJECTIVE: + + Here we perform on-time mail syncing activities for our users. + + REFERENCES: + + N/A + + DOWNLOADS: + + N/A + +""" + +# ***************************************************************************************************************** +# ***** **** +# *** IMPORT *** +# ***** **** +# ***************************************************************************************************************** + + +# To make sibling directories accessible for imports: +import sys +sys.path.append(".") +sys.path.append("..") + +# My async utils: +from utils_v2.string import json +from utils_v2.date_time import date_time +from utils_v2.database.async_mongo_v2 import AsyncMongo + +# To work with MongoDB: +from bson import ObjectId + +# To work with datatypes: +from typing import Literal + +# To make deep-copies: +import copy + + +# ***************************************************************************************************************** +# ***** **** +# *** MACROS / ONE-TIME INIT *** +# ***** **** +# ***************************************************************************************************************** + + +# --- Nothing Yet + + +# ***************************************************************************************************************** +# ***** **** +# *** VARIABLES *** +# ***** **** +# ***************************************************************************************************************** + + +# --- Nothing Yet + + +# ***************************************************************************************************************** +# ***** **** +# *** FUNCTIONS *** +# ***** **** +# ***************************************************************************************************************** + + +# --- Nothing Yet + + +# ***************************************************************************************************************** +# ***** **** +# *** CLASSES *** +# ***** **** +# ***************************************************************************************************************** + + +class MailOAuthModel: + + AUTH_COLLECTION = "_authTokens" + + def __init__(self): + pass + + @staticmethod + async def get_id( + db_conn: AsyncMongo, + user_info: dict, + service_type: Literal["email", "chat"], + service_client: Literal["gmail"], + auth_type: Literal["oauth"] + ) -> ObjectId: + + """ + Stores params from the session info and gives an identifier to use in the authorization URL. Use this when the + user requests an authorization URL to link your service to another service (like GMail). + :param db_conn: The database connection to use to perform the action. + :param user_info: The dictionary that has the user's session information. + :param service_type: The type of service being provided. + :param service_client: The name of the company or brand that is providing this service that is being integrated. + :param auth_type: To identify the type of authentication being done here. This could indicate simple password + authentication, more advance OAuth2.0 authentication, etc. + :return: An ObjectId to later store the granted tokens. + """ + + # Note down the timestamp at which this event occurred: + request_ts = date_time.get_current_utc_date_time(as_string = False) + + # Get the identifier from the database: + db_json = await db_conn.find_one_and_update( + collection = MailOAuthModel.AUTH_COLLECTION, + filter = { + "serviceType": service_type, + "client": service_client, + "authType": auth_type, + "user": user_info, + }, + update = { + "$set": { + "lastRequestTs": request_ts + }, + "$setOnInsert": { + "version": "1.0.0", + "serviceType": service_type, + "client": service_client, + "authType": auth_type, + "user": user_info, + "token": None, + "firstRefreshTs": None, + "lastRefreshTs": None, + "firstRequestTs": request_ts, + } + }, + projection = { + "_id": True + }, + upsert = True, + return_updated = True + ) + + # Done here: + return db_json["_id"] if db_json else None + + @staticmethod + async def set_token( + db_conn: AsyncMongo, + user_identifier: ObjectId | str, + token: dict + ) -> bool: + + """ + This method is to be called when the end user authorizes your service to connect to his third-party account. For + example, when the end user allows you to access his GMail account. + :param db_conn: The database connection to use to perform the action. + :param user_identifier: The identifier granted by the 'get_id' method. + :param token: The token granted by the third-party service. + :return: + """ + + # Note down the timestamp at which this event occurred: + request_ts = date_time.get_current_utc_date_time(as_string = False) + + # Save the token to the database: + token_saved = await db_conn.update_one( + collection = MailOAuthModel.AUTH_COLLECTION, + filter = {"_id": ObjectId(user_identifier)}, + update = { + "$set": { + "token": token, + "firstRefreshTs": request_ts, + } + } + ) + + # Done here: + return token_saved + + +# ***************************************************************************************************************** +# ***** **** +# *** MAIN PROGRAM *** +# ***** **** +# ***************************************************************************************************************** + + +if __name__ == "__main__": + + pass