(20241209) Standardizing the data models for the database. Started with mail authentication.

This commit is contained in:
2024-12-09 12:05:12 +05:30
parent 30088dcea4
commit e2c9200941
11 changed files with 262 additions and 244 deletions
+24 -17
View File
@@ -138,36 +138,38 @@ async def handle_gmail_callback() -> render_template:
# Generate the tokens from the callback. Google sends all the needed params in the callback as the URL's query
# params. We can simply use the exact URL that was hit to generate the tokens. In Quart (and Flask) this can be
# achieved by 'request.url' like this:
tokens = await current_app.gmail_client.get_authorization_tokens(
google_tokens = await current_app.gmail_client.get_authorization_tokens(
redirect_url = request.url,
# scopes = g.inbound_data["scope"].split(" ")
scopes = None
)
if tokens:
if google_tokens:
# Get the e-mail id that granted authorization. We will be comparing this to the e-mail id that had been given
# to us when the authorization was initiated. We don't mind any e-mail id being used, but we need them to be the
# same at both ends:
user_profile = await current_app.gmail_client.get_user_profile(tokens = tokens)
user_profile = await current_app.gmail_client.get_user_profile(tokens = google_tokens)
if user_profile.success:
tokens.email = user_profile.data["emailAddress"]
tokens.displayName = user_profile.data["displayName"]
tokens.displayPictureUrl = user_profile.data["displayPictureUrl"]
google_tokens.email = user_profile.data["emailAddress"]
google_tokens.displayName = user_profile.data["displayName"]
google_tokens.displayPictureUrl = user_profile.data["displayPictureUrl"]
# Here's where we do the checking of the e-mails,
# if they don't match, we reject the authorization:
placeholder_token = await current_app.mail_oauth_model.get_token(
auth_token = await current_app.mail_oauth_model.get_token(
mongo_conn = current_app.data_mongo,
token_id = g.inbound_data["state"]
)
if (
(not placeholder_token) or
placeholder_token["clientUserId"]["email"] != str(tokens.email)
(not auth_token) or
auth_token.clientUserId["email"] != str(google_tokens.email)
): return await render_template(
"/mail/oauth/oauth_failure_v2.html",
mail_client = g.mail_client.title(),
failure_hint = f"We were expecting authorization from '{placeholder_token['clientUserId']['email']}' but got authorization from '{tokens.email}' instead."
failure_hint = (
f"We were expecting authorization from '{auth_token.clientUserId['email']}', "
f"but got authorization from '{google_tokens.email}' instead."
)
)
# We create standard labels that we will use:
@@ -190,7 +192,7 @@ async def handle_gmail_callback() -> render_template:
]
tasks = [
current_app.gmail_client.create_label(
tokens = tokens,
tokens = google_tokens,
label_name = label["name"],
label_visibility = "labelShow",
message_visibility = "show",
@@ -201,18 +203,20 @@ async def handle_gmail_callback() -> render_template:
client_responses = await asyncio.gather(*tasks)
# Add the labels to the tokens data:
client_response = await current_app.gmail_client.list_labels(tokens = tokens)
tokens.labels = client_response.data if client_response.success else None
client_response = await current_app.gmail_client.list_labels(tokens = google_tokens)
google_tokens.labels = client_response.data if client_response.success else None
# Now that we have passed the check,
# we save the tokens to the database:
auth_token.clientUserId = google_tokens.client_user_id
auth_token.token = google_tokens.model_dump()
auth_token.status = "active"
tokens_saved = await current_app.mail_oauth_model.set_token(
db_conn = current_app.sql_writer,
mongo_conn = current_app.data_mongo,
session_token = g.inbound_headers.get("X-Session-Token"),
token_id = g.inbound_data["state"],
client_user_id = tokens.client_user_id,
token = tokens.model_dump()
auth_token = auth_token
)
# Return an HTML response for success:
@@ -294,7 +298,10 @@ async def mail_auth_callback(
return await render_template(
"/mail/oauth/oauth_failure_v2.html",
mail_client = mail_client.title(),
failure_hint = f"Invalid client '{mail_client}' selected. Please use log-id '{g.log_id}' to check with the support team."
failure_hint = (
f"Invalid client '{mail_client}' selected. "
"Please use log-id '{g.log_id}' to check with the support team."
)
)
+14 -11
View File
@@ -71,6 +71,7 @@ from models.data.api.mail.oauth import (
OAuthMailAuthorizationRequestHeaders,
OAuthMailAuthorizationRequestData
)
from models.data.core.auth_token import CoreAuthTokenModel
# For asynchronous activities:
import asyncio
@@ -169,22 +170,24 @@ async def request_oauth_authorization_url(
# Start by assuming failure:
auth_url = None
# ┳ •┏
# ┃┏┫┏┓┏┓┓╋┓┏ ┃┃┏┏┓┏┓
# ┻┗┻┗ ┛┗┗┗┛┗┫ ┗┛┛┗ ┛
# ┛
# ┏┓ ┏┳┓
# ┃┓┏┓┏┓┏┓┏┓┓╋┏┓ ┃ ┏┓┃┏┏┓┏┓ ┃┏┫
# ┗┛┗ ┛┗┗ ┛ ┗┻┗┗ ┻ ┗┛┛┗┗ ┻┗┻
# Make a user identifier from the session info:
token_id = await current_app.mail_oauth_model.get_token_id(
db_conn = current_app.sql_writer,
mongo_conn = current_app.data_mongo,
session_token = inbound_headers["X-Session-Token"],
user_info = kwargs["session_info"],
client_user_id = {"email": inbound_data.mailId},
auth = None,
service_client = inbound_data.mailClient,
auth_type = "oauth",
sync_freq = inbound_data.syncFreq
auth_token = CoreAuthTokenModel(
serviceType = "email",
client = inbound_data.mailClient,
authType = "oauth",
user = kwargs["session_info"],
clientUserId = {"email": inbound_data.mailId},
status = "pending",
syncFreq = inbound_data.syncFreq,
),
session_token = inbound_headers["X-Session-Token"]
)
if token_id is None:
return ResponseModel(