(20241209) Standardizing the data models for the database. Started with mail authentication.
This commit is contained in:
@@ -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
|
# 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
|
# 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:
|
# 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,
|
redirect_url = request.url,
|
||||||
# scopes = g.inbound_data["scope"].split(" ")
|
|
||||||
scopes = None
|
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
|
# 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
|
# 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:
|
# 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:
|
if user_profile.success:
|
||||||
tokens.email = user_profile.data["emailAddress"]
|
google_tokens.email = user_profile.data["emailAddress"]
|
||||||
tokens.displayName = user_profile.data["displayName"]
|
google_tokens.displayName = user_profile.data["displayName"]
|
||||||
tokens.displayPictureUrl = user_profile.data["displayPictureUrl"]
|
google_tokens.displayPictureUrl = user_profile.data["displayPictureUrl"]
|
||||||
|
|
||||||
# Here's where we do the checking of the e-mails,
|
# Here's where we do the checking of the e-mails,
|
||||||
# if they don't match, we reject the authorization:
|
# 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,
|
mongo_conn = current_app.data_mongo,
|
||||||
token_id = g.inbound_data["state"]
|
token_id = g.inbound_data["state"]
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
(not placeholder_token) or
|
(not auth_token) or
|
||||||
placeholder_token["clientUserId"]["email"] != str(tokens.email)
|
auth_token.clientUserId["email"] != str(google_tokens.email)
|
||||||
): return await render_template(
|
): return await render_template(
|
||||||
"/mail/oauth/oauth_failure_v2.html",
|
"/mail/oauth/oauth_failure_v2.html",
|
||||||
mail_client = g.mail_client.title(),
|
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:
|
# We create standard labels that we will use:
|
||||||
@@ -190,7 +192,7 @@ async def handle_gmail_callback() -> render_template:
|
|||||||
]
|
]
|
||||||
tasks = [
|
tasks = [
|
||||||
current_app.gmail_client.create_label(
|
current_app.gmail_client.create_label(
|
||||||
tokens = tokens,
|
tokens = google_tokens,
|
||||||
label_name = label["name"],
|
label_name = label["name"],
|
||||||
label_visibility = "labelShow",
|
label_visibility = "labelShow",
|
||||||
message_visibility = "show",
|
message_visibility = "show",
|
||||||
@@ -201,18 +203,20 @@ async def handle_gmail_callback() -> render_template:
|
|||||||
client_responses = await asyncio.gather(*tasks)
|
client_responses = await asyncio.gather(*tasks)
|
||||||
|
|
||||||
# Add the labels to the tokens data:
|
# Add the labels to the tokens data:
|
||||||
client_response = await current_app.gmail_client.list_labels(tokens = tokens)
|
client_response = await current_app.gmail_client.list_labels(tokens = google_tokens)
|
||||||
tokens.labels = client_response.data if client_response.success else None
|
google_tokens.labels = client_response.data if client_response.success else None
|
||||||
|
|
||||||
# Now that we have passed the check,
|
# Now that we have passed the check,
|
||||||
# we save the tokens to the database:
|
# 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(
|
tokens_saved = await current_app.mail_oauth_model.set_token(
|
||||||
db_conn = current_app.sql_writer,
|
db_conn = current_app.sql_writer,
|
||||||
mongo_conn = current_app.data_mongo,
|
mongo_conn = current_app.data_mongo,
|
||||||
session_token = g.inbound_headers.get("X-Session-Token"),
|
session_token = g.inbound_headers.get("X-Session-Token"),
|
||||||
token_id = g.inbound_data["state"],
|
token_id = g.inbound_data["state"],
|
||||||
client_user_id = tokens.client_user_id,
|
auth_token = auth_token
|
||||||
token = tokens.model_dump()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Return an HTML response for success:
|
# Return an HTML response for success:
|
||||||
@@ -294,7 +298,10 @@ async def mail_auth_callback(
|
|||||||
return await render_template(
|
return await render_template(
|
||||||
"/mail/oauth/oauth_failure_v2.html",
|
"/mail/oauth/oauth_failure_v2.html",
|
||||||
mail_client = mail_client.title(),
|
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."
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ from models.data.api.mail.oauth import (
|
|||||||
OAuthMailAuthorizationRequestHeaders,
|
OAuthMailAuthorizationRequestHeaders,
|
||||||
OAuthMailAuthorizationRequestData
|
OAuthMailAuthorizationRequestData
|
||||||
)
|
)
|
||||||
|
from models.data.core.auth_token import CoreAuthTokenModel
|
||||||
|
|
||||||
# For asynchronous activities:
|
# For asynchronous activities:
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -169,22 +170,24 @@ async def request_oauth_authorization_url(
|
|||||||
# Start by assuming failure:
|
# Start by assuming failure:
|
||||||
auth_url = None
|
auth_url = None
|
||||||
|
|
||||||
# ┳ ┓ •┏ ┳┳
|
# ┏┓ ┏┳┓ ┓ ┳ ┓
|
||||||
# ┃┏┫┏┓┏┓╋┓╋┓┏ ┃┃┏┏┓┏┓
|
# ┃┓┏┓┏┓┏┓┏┓┏┓╋┏┓ ┃ ┏┓┃┏┏┓┏┓ ┃┏┫
|
||||||
# ┻┗┻┗ ┛┗┗┗┛┗┫ ┗┛┛┗ ┛
|
# ┗┛┗ ┛┗┗ ┛ ┗┻┗┗ ┻ ┗┛┛┗┗ ┛┗ ┻┗┻
|
||||||
# ┛
|
|
||||||
|
|
||||||
# Make a user identifier from the session info:
|
# Make a user identifier from the session info:
|
||||||
token_id = await current_app.mail_oauth_model.get_token_id(
|
token_id = await current_app.mail_oauth_model.get_token_id(
|
||||||
db_conn = current_app.sql_writer,
|
db_conn = current_app.sql_writer,
|
||||||
mongo_conn = current_app.data_mongo,
|
mongo_conn = current_app.data_mongo,
|
||||||
session_token = inbound_headers["X-Session-Token"],
|
auth_token = CoreAuthTokenModel(
|
||||||
user_info = kwargs["session_info"],
|
serviceType = "email",
|
||||||
client_user_id = {"email": inbound_data.mailId},
|
client = inbound_data.mailClient,
|
||||||
auth = None,
|
authType = "oauth",
|
||||||
service_client = inbound_data.mailClient,
|
user = kwargs["session_info"],
|
||||||
auth_type = "oauth",
|
clientUserId = {"email": inbound_data.mailId},
|
||||||
sync_freq = inbound_data.syncFreq
|
status = "pending",
|
||||||
|
syncFreq = inbound_data.syncFreq,
|
||||||
|
),
|
||||||
|
session_token = inbound_headers["X-Session-Token"]
|
||||||
)
|
)
|
||||||
if token_id is None:
|
if token_id is None:
|
||||||
return ResponseModel(
|
return ResponseModel(
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ def init(blueprint_setup_state):
|
|||||||
@test_callback_bp.route("/callback", methods = ["POST", "GET"])
|
@test_callback_bp.route("/callback", methods = ["POST", "GET"])
|
||||||
@set_api_version(api_version = "1.0.0")
|
@set_api_version(api_version = "1.0.0")
|
||||||
@read_input(sanitize_headers = False, sanitize_data = False)
|
@read_input(sanitize_headers = False, sanitize_data = False)
|
||||||
|
@get_session_info(key = "X-Session-Token", session_coro = "get_session")
|
||||||
@log_request_to_mongo(
|
@log_request_to_mongo(
|
||||||
attr_name = "logs_mongo",
|
attr_name = "logs_mongo",
|
||||||
project = constants.PROJECT_NAME,
|
project = constants.PROJECT_NAME,
|
||||||
@@ -118,7 +119,7 @@ def init(blueprint_setup_state):
|
|||||||
operation = "testCllBckApi",
|
operation = "testCllBckApi",
|
||||||
log_input = True,
|
log_input = True,
|
||||||
log_output = True,
|
log_output = True,
|
||||||
sensitive_keys = None
|
sensitive_keys = ["sessionToken", "X-Session-Token"]
|
||||||
)
|
)
|
||||||
@log_chain_to_mongo(attr_name = "logs_mongo")
|
@log_chain_to_mongo(attr_name = "logs_mongo")
|
||||||
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
|
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
|
||||||
@@ -130,6 +131,8 @@ async def callback_test(
|
|||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
|
|
||||||
|
print("SESSION INFO:", kwargs.get("session_info"))
|
||||||
|
|
||||||
# Return a random page:
|
# Return a random page:
|
||||||
return await render_template(
|
return await render_template(
|
||||||
random.choice([
|
random.choice([
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ sys.path.append("..")
|
|||||||
# To use Quart:
|
# To use Quart:
|
||||||
from quart import current_app
|
from quart import current_app
|
||||||
|
|
||||||
|
# The data model:
|
||||||
|
from models.data.core.user_info import CoreUserInfoModel
|
||||||
|
|
||||||
|
|
||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
# ***** ****
|
# ***** ****
|
||||||
@@ -84,18 +87,27 @@ async def get_session(session_token):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
|
# Fetch the raw info from cache:
|
||||||
raw_info = await current_app.module_cache.get(key = session_token)
|
raw_info = await current_app.module_cache.get(key = session_token)
|
||||||
session_info = {
|
|
||||||
"fullName": raw_info["value"]["full_name"],
|
# Feed needed field into the core model:
|
||||||
"userId": raw_info["value"]["user_id"],
|
session_info = CoreUserInfoModel(
|
||||||
"entityId": raw_info["value"]["entity_id"],
|
fullName = raw_info["value"]["full_name"],
|
||||||
"billingAccountId": raw_info["value"]["billing_account_id"],
|
userId = raw_info["value"]["user_id"],
|
||||||
"departmentId": raw_info["value"]["department_id"],
|
entityId = raw_info["value"]["entity_id"],
|
||||||
"branchId": raw_info["value"]["branch_id"],
|
billingAccountId = raw_info["value"]["billing_account_id"],
|
||||||
"industry": raw_info["value"]["industry"]
|
departmentId = raw_info["value"]["department_id"],
|
||||||
}
|
branchId = raw_info["value"]["branch_id"],
|
||||||
|
industry = raw_info["value"]["industry"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Done here:
|
||||||
return session_info
|
return session_info
|
||||||
|
|
||||||
|
# In case something goes wrong:
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
|
current_app.printer(exception)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -71,7 +71,7 @@ from utils_v2.api.async_quart import (
|
|||||||
from utils_v2.goog.gmail.gmail_client import AsyncGMailClient
|
from utils_v2.goog.gmail.gmail_client import AsyncGMailClient
|
||||||
|
|
||||||
# Behaviour Models:
|
# Behaviour Models:
|
||||||
from models.behaviour.mail.oauth_v2 import MailOAuthModel
|
from models.behaviour.mail.oauth_v3 import MailOAuthModel
|
||||||
from models.behaviour.mail.sync_v2 import MailSyncModel
|
from models.behaviour.mail.sync_v2 import MailSyncModel
|
||||||
from models.behaviour.mail.retrieve import MailRetrieveModel
|
from models.behaviour.mail.retrieve import MailRetrieveModel
|
||||||
from models.behaviour.sms.auth import SMSAuthModel
|
from models.behaviour.sms.auth import SMSAuthModel
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
DATE:
|
DATE:
|
||||||
|
|
||||||
Monday, 2nd Dec., 2024
|
ORIGINAL: Monday, 2nd Dec., 2024
|
||||||
|
UPGRADE: Monday, 9th Dec., 2024
|
||||||
|
|
||||||
OBJECTIVE:
|
OBJECTIVE:
|
||||||
|
|
||||||
@@ -44,6 +45,9 @@ from utils_v2.database.async_mongo_v2 import AsyncMongo
|
|||||||
# Base model:
|
# Base model:
|
||||||
from models.behaviour.base import BaseModel
|
from models.behaviour.base import BaseModel
|
||||||
|
|
||||||
|
# Data models:
|
||||||
|
from models.data.core.auth_token import CoreAuthTokenModel
|
||||||
|
|
||||||
# To work with MongoDB:
|
# To work with MongoDB:
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
|
|
||||||
@@ -99,12 +103,7 @@ class MailOAuthModel(BaseModel):
|
|||||||
self,
|
self,
|
||||||
db_conn: AsyncMySQL,
|
db_conn: AsyncMySQL,
|
||||||
mongo_conn: AsyncMongo,
|
mongo_conn: AsyncMongo,
|
||||||
user_info: dict,
|
auth_token: CoreAuthTokenModel,
|
||||||
client_user_id: dict,
|
|
||||||
auth: dict,
|
|
||||||
service_client: Literal["gmail"],
|
|
||||||
auth_type: Literal["oauth"],
|
|
||||||
sync_freq: Literal[60, 300, 900] = 300,
|
|
||||||
session_token: str = None
|
session_token: str = None
|
||||||
) -> ObjectId:
|
) -> ObjectId:
|
||||||
|
|
||||||
@@ -113,13 +112,7 @@ class MailOAuthModel(BaseModel):
|
|||||||
user requests an authorization URL to link your service to another service (like GMail).
|
user requests an authorization URL to link your service to another service (like GMail).
|
||||||
:param db_conn: The database connection (MariaDB) to use to perform the action.
|
:param db_conn: The database connection (MariaDB) to use to perform the action.
|
||||||
:param mongo_conn: The database connection (MongoDB) to use to perform the action.
|
:param mongo_conn: The database connection (MongoDB) to use to perform the action.
|
||||||
:param user_info: The dictionary that has the user's session information.
|
:param auth_token: An instance of the core auth-token model that holds data in the database.
|
||||||
:param client_user_id: The way the third-party client recognizes your user.
|
|
||||||
:param auth: The authentication details of the account.
|
|
||||||
: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.
|
|
||||||
:param sync_freq: The time interval in which mails need to be sync'd. Specify this in seconds.
|
|
||||||
:param session_token: The session token of the user who requested this service.
|
:param session_token: The session token of the user who requested this service.
|
||||||
:return: An ObjectId to later store the granted tokens.
|
:return: An ObjectId to later store the granted tokens.
|
||||||
"""
|
"""
|
||||||
@@ -127,35 +120,36 @@ class MailOAuthModel(BaseModel):
|
|||||||
# Note down the timestamp at which this event occurred:
|
# Note down the timestamp at which this event occurred:
|
||||||
request_ts = date_time.get_current_utc_date_time(as_string = False)
|
request_ts = date_time.get_current_utc_date_time(as_string = False)
|
||||||
|
|
||||||
# Get the identifier from the database:
|
# Get the identifier from the database.
|
||||||
|
# BE CAREFUL WITH THE KEYS HERE, THEY SHOULD MATCH THE FIELDS OF THE CORE AUTH-TOKEN MODEL:
|
||||||
mongo_json = await mongo_conn.find_one_and_update(
|
mongo_json = await mongo_conn.find_one_and_update(
|
||||||
collection = MailOAuthModel.AUTH_COLLECTION,
|
collection = MailOAuthModel.AUTH_COLLECTION,
|
||||||
filter = mongo_conn.dict_to_dot_notation({
|
filter = mongo_conn.dict_to_dot_notation({
|
||||||
"serviceType": "email",
|
"serviceType": "email",
|
||||||
"user": {
|
"user": {
|
||||||
"entityId": user_info["entityId"],
|
"entityId": auth_token.user.entityId,
|
||||||
"billingAccountId": user_info["billingAccountId"]
|
"billingAccountId": auth_token.user.billingAccountId
|
||||||
},
|
},
|
||||||
"clientUserId": client_user_id
|
"clientUserId": auth_token.clientUserId
|
||||||
}),
|
}),
|
||||||
update = {
|
update = {
|
||||||
"$set": {
|
"$set": {
|
||||||
"lastRequestTs": request_ts,
|
"lastRequestTs": request_ts,
|
||||||
"status": "active",
|
"status": auth_token.status,
|
||||||
"syncFreq": max(sync_freq, 60)
|
"syncFreq": max(auth_token.syncFreq, 60)
|
||||||
},
|
},
|
||||||
"$setOnInsert": {
|
"$setOnInsert": {
|
||||||
"version": "1.1.1",
|
"version": auth_token.version,
|
||||||
"serviceType": "email",
|
"serviceType": auth_token.serviceType,
|
||||||
"client": service_client,
|
"client": auth_token.client,
|
||||||
"authType": auth_type,
|
"authType": auth_token.authType,
|
||||||
"user": user_info,
|
"user": auth_token.user.model_dump(),
|
||||||
"clientUserId": client_user_id,
|
"clientUserId": auth_token.clientUserId,
|
||||||
"auth": auth,
|
"auth": auth_token.auth,
|
||||||
"token": None,
|
"token": auth_token.token,
|
||||||
"firstRefreshTs": None,
|
"firstRefreshTs": auth_token.firstRefreshTs,
|
||||||
"lastRefreshTs": None,
|
"lastRefreshTs": auth_token.lastRefreshTs,
|
||||||
"firstRequestTs": request_ts,
|
"firstRequestTs": auth_token.firstRequestTs,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
projection = {
|
projection = {
|
||||||
@@ -172,15 +166,15 @@ class MailOAuthModel(BaseModel):
|
|||||||
db_conn = db_conn,
|
db_conn = db_conn,
|
||||||
proc_name = "entity_integration_save",
|
proc_name = "entity_integration_save",
|
||||||
proc_args = (
|
proc_args = (
|
||||||
user_info["entityId"], # ............................................ 'p_entity_id'
|
auth_token.user.entityId, # ......................................... 'p_entity_id'
|
||||||
service_client, # ................................................... 'p_provider'
|
auth_token.client, # ................................................ 'p_provider'
|
||||||
"Pending", # ........................................................ 'p_current_status'
|
"Pending", # ........................................................ 'p_current_status'
|
||||||
"Auth Requested", # ................................................. 'p_last_action'
|
"Auth Requested", # ................................................. 'p_last_action'
|
||||||
None, # ............................................................. 'p_display_name'
|
None, # ............................................................. 'p_display_name'
|
||||||
None, # ............................................................. 'p_display_picture'
|
None, # ............................................................. 'p_display_picture'
|
||||||
str(mongo_json["_id"]), # ........................................... 'p_token_id'
|
str(mongo_json["_id"]), # ........................................... 'p_token_id'
|
||||||
json.to_string(python_data = {"email": None}, no_space = True), # ... 'p_notes'
|
json.to_string(python_data = {"email": None}, no_space = True), # ... 'p_notes'
|
||||||
user_info["userId"] # ............................................... 'p_created_by'
|
auth_token.user.userId # ............................................ 'p_created_by'
|
||||||
),
|
),
|
||||||
session_token = session_token
|
session_token = session_token
|
||||||
)
|
)
|
||||||
@@ -193,8 +187,7 @@ class MailOAuthModel(BaseModel):
|
|||||||
db_conn: AsyncMySQL,
|
db_conn: AsyncMySQL,
|
||||||
mongo_conn: AsyncMongo,
|
mongo_conn: AsyncMongo,
|
||||||
token_id: ObjectId | str,
|
token_id: ObjectId | str,
|
||||||
client_user_id: dict,
|
auth_token: CoreAuthTokenModel,
|
||||||
token: dict,
|
|
||||||
session_token: str = None
|
session_token: str = None
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
@@ -205,9 +198,7 @@ class MailOAuthModel(BaseModel):
|
|||||||
:param db_conn: The database connection (MariaDB) to use to perform the action.
|
:param db_conn: The database connection (MariaDB) to use to perform the action.
|
||||||
:param mongo_conn: The database connection (MongoDB) to use to perform the action.
|
:param mongo_conn: The database connection (MongoDB) to use to perform the action.
|
||||||
:param token_id: The identifier granted by the 'get_token_id' method.
|
:param token_id: The identifier granted by the 'get_token_id' method.
|
||||||
:param client_user_id: The way the third-party client recognizes your user. These details should match the
|
:param auth_token: The actual auth/token data to be saved to the database.
|
||||||
details furnished while requesting the authorization through 'get_token_id' method.
|
|
||||||
:param token: The token granted by the third-party service.
|
|
||||||
:param session_token: The session token of the user who requested this service.
|
:param session_token: The session token of the user who requested this service.
|
||||||
:return: True if saved, False if failed.
|
:return: True if saved, False if failed.
|
||||||
"""
|
"""
|
||||||
@@ -218,17 +209,18 @@ class MailOAuthModel(BaseModel):
|
|||||||
# Note down the timestamp at which this event occurred:
|
# Note down the timestamp at which this event occurred:
|
||||||
request_ts = date_time.get_current_utc_date_time(as_string = False)
|
request_ts = date_time.get_current_utc_date_time(as_string = False)
|
||||||
|
|
||||||
# Save the token to MongoDB:
|
# Save the token to MongoDB.
|
||||||
|
# BE CAREFUL WITH THE KEYS HERE, THEY SHOULD MATCH THE FIELDS OF THE CORE AUTH-TOKEN MODEL:
|
||||||
mongo_json = await mongo_conn.find_one_and_update(
|
mongo_json = await mongo_conn.find_one_and_update(
|
||||||
collection = MailOAuthModel.AUTH_COLLECTION,
|
collection = MailOAuthModel.AUTH_COLLECTION,
|
||||||
filter = mongo_conn.dict_to_dot_notation({
|
filter = mongo_conn.dict_to_dot_notation({
|
||||||
"_id": ObjectId(token_id),
|
"_id": ObjectId(token_id),
|
||||||
"clientUserId": client_user_id
|
"clientUserId": auth_token.clientUserId
|
||||||
}),
|
}),
|
||||||
update = [{
|
update = [{
|
||||||
"$set": {
|
"$set": {
|
||||||
"token": token,
|
"token": auth_token.token,
|
||||||
"status": "active",
|
"status": auth_token.status,
|
||||||
"lastRefreshTs": request_ts,
|
"lastRefreshTs": request_ts,
|
||||||
"firstRefreshTs": {
|
"firstRefreshTs": {
|
||||||
"$cond": {
|
"$cond": {
|
||||||
@@ -252,9 +244,9 @@ class MailOAuthModel(BaseModel):
|
|||||||
# Tell MariaDB that the token was saved:
|
# Tell MariaDB that the token was saved:
|
||||||
if mongo_json is not None:
|
if mongo_json is not None:
|
||||||
token_notes = {
|
token_notes = {
|
||||||
"email": token["email"],
|
"email": auth_token.token["email"],
|
||||||
"displayName": token.get("displayName"),
|
"displayName": auth_token.token.get("displayName"),
|
||||||
"displayPictureUrl": token.get("displayPictureUrl"),
|
"displayPictureUrl": auth_token.token.get("displayPictureUrl"),
|
||||||
}
|
}
|
||||||
db_json = await self.call_procedure(
|
db_json = await self.call_procedure(
|
||||||
db_conn = db_conn,
|
db_conn = db_conn,
|
||||||
@@ -264,11 +256,11 @@ class MailOAuthModel(BaseModel):
|
|||||||
mongo_json["client"], # ......................................... 'p_provider'
|
mongo_json["client"], # ......................................... 'p_provider'
|
||||||
"Active", # ..................................................... 'p_current_status'
|
"Active", # ..................................................... 'p_current_status'
|
||||||
"Auth Granted", # ............................................... 'p_last_action'
|
"Auth Granted", # ............................................... 'p_last_action'
|
||||||
token["displayName"], # ......................................... 'p_display_name'
|
auth_token.token.get("displayName"), # .......................... 'p_display_name'
|
||||||
token["displayPictureUrl"], # ................................... 'p_display_picture'
|
auth_token.token.get("displayPictureUrl"), # .................... 'p_display_picture'
|
||||||
token_id, # ..................................................... 'p_token_id'
|
token_id, # ..................................................... 'p_token_id'
|
||||||
json.to_string(python_data = token_notes, no_space = True), # ... 'p_notes'
|
json.to_string(python_data = token_notes, no_space = True), # ... 'p_notes'
|
||||||
mongo_json["user"]["userId"] # .................................. 'p_created_by'
|
auth_token.user.userId # ........................................ 'p_created_by'
|
||||||
),
|
),
|
||||||
session_token = session_token
|
session_token = session_token
|
||||||
)
|
)
|
||||||
@@ -282,7 +274,7 @@ class MailOAuthModel(BaseModel):
|
|||||||
mongo_conn: AsyncMongo,
|
mongo_conn: AsyncMongo,
|
||||||
token_id: ObjectId | str = None,
|
token_id: ObjectId | str = None,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> dict | None:
|
) -> CoreAuthTokenModel | None:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
To retrieve stored tokens from the database.
|
To retrieve stored tokens from the database.
|
||||||
@@ -301,21 +293,15 @@ class MailOAuthModel(BaseModel):
|
|||||||
# If there is no search criteria, we exit with failure:
|
# If there is no search criteria, we exit with failure:
|
||||||
if not filter_json: return None
|
if not filter_json: return None
|
||||||
|
|
||||||
# If there is some filtering possible,
|
# If there is some filtering possible, we fetch the token:
|
||||||
# we fetch and return the token:
|
token = await mongo_conn.find_one(
|
||||||
return await mongo_conn.find_one(
|
|
||||||
collection = self.AUTH_COLLECTION,
|
collection = self.AUTH_COLLECTION,
|
||||||
filter = filter_json,
|
filter = filter_json,
|
||||||
projection = {
|
|
||||||
"_id": True,
|
|
||||||
"serviceType": True,
|
|
||||||
"authType": True,
|
|
||||||
"client": True,
|
|
||||||
"clientUserId": True,
|
|
||||||
"token": True
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return CoreAuthTokenModel(**token) if token else None
|
||||||
|
|
||||||
|
|
||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
# ***** ****
|
# ***** ****
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ from typing import Optional, Literal, Union
|
|||||||
from utils_v2.string import regex
|
from utils_v2.string import regex
|
||||||
from utils_v2.date_time import date_time
|
from utils_v2.date_time import date_time
|
||||||
|
|
||||||
|
# Other core models:
|
||||||
|
from models.data.core.user_info import CoreUserInfoModel
|
||||||
|
|
||||||
# To work with MongoDB:
|
# To work with MongoDB:
|
||||||
from bson.objectid import ObjectId
|
from bson.objectid import ObjectId
|
||||||
|
|
||||||
@@ -108,31 +111,41 @@ class CoreAuthTokenModel(BaseModel):
|
|||||||
|
|
||||||
firstRequestTs: AwareDatetime = Field(
|
firstRequestTs: AwareDatetime = Field(
|
||||||
description = "the time (utc) at which authorization was first requested",
|
description = "the time (utc) at which authorization was first requested",
|
||||||
frozen = True
|
frozen = True,
|
||||||
|
default_factory = lambda: date_time.get_current_utc_date_time(as_string = False)
|
||||||
)
|
)
|
||||||
|
|
||||||
lastRequestTs: AwareDatetime = Field(
|
lastRequestTs: AwareDatetime = Field(
|
||||||
description = "the time (utc) at which authorization was last requested",
|
description = "the time (utc) at which authorization was last requested",
|
||||||
frozen = False
|
frozen = False,
|
||||||
|
default = None
|
||||||
)
|
)
|
||||||
|
|
||||||
firstRefreshTs: AwareDatetime = Field(
|
firstRefreshTs: AwareDatetime = Field(
|
||||||
description = "the time (utc) at which the tokens were first refreshed",
|
description = "the time (utc) at which the tokens were first refreshed",
|
||||||
frozen = False
|
frozen = False,
|
||||||
|
default = None
|
||||||
)
|
)
|
||||||
|
|
||||||
lastRefreshTs: AwareDatetime = Field(
|
lastRefreshTs: AwareDatetime = Field(
|
||||||
description = "the time (utc) at which the tokens were last refreshed",
|
description = "the time (utc) at which the tokens were last refreshed",
|
||||||
frozen = False
|
frozen = False,
|
||||||
|
default = None
|
||||||
|
)
|
||||||
|
|
||||||
|
auth: dict | None = Field(
|
||||||
|
description = "any direct auth details like api keys or passwords; will differ for each client",
|
||||||
|
frozen = True,
|
||||||
|
default = None
|
||||||
)
|
)
|
||||||
|
|
||||||
token: dict | None = Field(
|
token: dict | None = Field(
|
||||||
description = "the actual auth tokens of that client; will differ for each client",
|
description = "the actual auth tokens of that client; will differ for each client",
|
||||||
frozen = True,
|
frozen = True,
|
||||||
default_factory = lambda: date_time.get_current_utc_date_time(as_string = False)
|
default = None
|
||||||
)
|
)
|
||||||
|
|
||||||
user: dict = Field(
|
user: CoreUserInfoModel = Field(
|
||||||
description = "how you identify your user",
|
description = "how you identify your user",
|
||||||
frozen = True
|
frozen = True
|
||||||
)
|
)
|
||||||
@@ -142,6 +155,18 @@ class CoreAuthTokenModel(BaseModel):
|
|||||||
frozen = True
|
frozen = True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
status: Literal["pending", "active", "disabled"] = Field(
|
||||||
|
description = "to indicate the status of this account",
|
||||||
|
frozen = False,
|
||||||
|
default = "pending"
|
||||||
|
)
|
||||||
|
|
||||||
|
syncFreq: Literal[60, 300, 1500] = Field(
|
||||||
|
description = "the no. of seconds after which to poll for updates from the client (if applicable)",
|
||||||
|
frozen = False,
|
||||||
|
default = 300
|
||||||
|
)
|
||||||
|
|
||||||
# ┏┓ ┏•
|
# ┏┓ ┏•
|
||||||
# ┃ ┏┓┏┓╋┓┏┓
|
# ┃ ┏┓┏┓╋┓┏┓
|
||||||
# ┗┛┗┛┛┗┛┗┗┫
|
# ┗┛┗┛┛┗┛┗┗┫
|
||||||
@@ -37,7 +37,7 @@ sys.path.append("..")
|
|||||||
|
|
||||||
# For making data behaviour_models:
|
# For making data behaviour_models:
|
||||||
from pydantic import BaseModel, Field, field_validator, PastDatetime, AwareDatetime
|
from pydantic import BaseModel, Field, field_validator, PastDatetime, AwareDatetime
|
||||||
from typing import Optional, Literal, Union
|
from typing import Optional, Literal, Union, List
|
||||||
|
|
||||||
# My utils:
|
# My utils:
|
||||||
from utils_v2.string import regex
|
from utils_v2.string import regex
|
||||||
@@ -80,6 +80,50 @@ import pycountry
|
|||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentEvent(BaseModel):
|
||||||
|
|
||||||
|
eventTs: AwareDatetime = Field(
|
||||||
|
description = "to know the date and time (utc) of this update",
|
||||||
|
frozen = True
|
||||||
|
)
|
||||||
|
|
||||||
|
initByPG: bool = Field(
|
||||||
|
description = "to figure out whether the payment gateway initiated this event or we did",
|
||||||
|
frozen = True
|
||||||
|
)
|
||||||
|
|
||||||
|
httpCode: int | None = Field(
|
||||||
|
description = "the http code generated by the event",
|
||||||
|
frozen = True,
|
||||||
|
examples = [200, 400, 401]
|
||||||
|
)
|
||||||
|
|
||||||
|
payload: dict = Field(
|
||||||
|
description = "the json payload or set of query params received from an event from the payment gateway",
|
||||||
|
frozen = True
|
||||||
|
)
|
||||||
|
|
||||||
|
# ┏┓ ┏•
|
||||||
|
# ┃ ┏┓┏┓╋┓┏┓
|
||||||
|
# ┗┛┗┛┛┗┛┗┗┫
|
||||||
|
# ┛
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
extra = "allow"
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
# ┓┏ ┓• ┓ •
|
||||||
|
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
||||||
|
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
||||||
|
|
||||||
|
@field_validator("eventTs", mode = "before")
|
||||||
|
def parse_date_time(cls, value):
|
||||||
|
return date_time.parse_date_time(input_value = value, timezone = date_time.TIMEZONE_UTC)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class CorePaymentModel(BaseModel):
|
class CorePaymentModel(BaseModel):
|
||||||
|
|
||||||
version: str = Field(
|
version: str = Field(
|
||||||
@@ -89,22 +133,22 @@ class CorePaymentModel(BaseModel):
|
|||||||
default = "1.0.0"
|
default = "1.0.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
paymentStatus: Literal["requested", "paid", "rejected"] = Field(
|
paymentStatus: Literal[
|
||||||
|
"initFailed", # ... When we tried to initiate the request, but the payment gateway (PG) rejected it.
|
||||||
|
"initiated", # .... When we made a successful payment request, or the customer initiated one from the PG.
|
||||||
|
"failed", # ....... When the customer tried paying, but it failed (e.g.: because of an incorrect pin).
|
||||||
|
"rejected", # ..... When the customer explicitly rejected the payment.
|
||||||
|
"authorized", # ... When the customer made the payment (but it hasn't been settled in your account yet).
|
||||||
|
"settled", # ...... When the PG sends the money to your account.
|
||||||
|
"refunded", # ..... When the money was refunded to the client.
|
||||||
|
] = Field(
|
||||||
description = "the status of the payment request to see what stage of the process we are in",
|
description = "the status of the payment request to see what stage of the process we are in",
|
||||||
frozen = False,
|
frozen = False
|
||||||
default = "requested"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
requestTs: AwareDatetime = Field(
|
lastEventTs: AwareDatetime = Field(
|
||||||
description = "the time (utc) at which the payment request was initiated",
|
description = "the time (utc) at which the latest payment event occurred",
|
||||||
frozen = True,
|
frozen = True
|
||||||
default_factory = lambda: date_time.get_current_utc_date_time(as_string = False)
|
|
||||||
)
|
|
||||||
|
|
||||||
responseTs: AwareDatetime | None = Field(
|
|
||||||
description = "the time (utc) at which the payer responded to the payment request",
|
|
||||||
frozen = False,
|
|
||||||
default = None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
tokenId: ObjectId = Field(
|
tokenId: ObjectId = Field(
|
||||||
@@ -122,7 +166,7 @@ class CorePaymentModel(BaseModel):
|
|||||||
examples = ["INR", "USD", "KES"]
|
examples = ["INR", "USD", "KES"]
|
||||||
)
|
)
|
||||||
|
|
||||||
metadata: dict = Field(
|
metadata: dict | None = Field(
|
||||||
description = "any arbitrary amount of data to identify the user and payment details",
|
description = "any arbitrary amount of data to identify the user and payment details",
|
||||||
frozen = True
|
frozen = True
|
||||||
)
|
)
|
||||||
@@ -138,28 +182,9 @@ class CorePaymentModel(BaseModel):
|
|||||||
default = None
|
default = None
|
||||||
)
|
)
|
||||||
|
|
||||||
clientPaymentRequestHttpCode: int | str = Field(
|
events: List[PaymentEvent] = Field(
|
||||||
description = "the http code the third-party client returned when you requested the payment",
|
description = "an array of all the events that happened in the process of this payment",
|
||||||
frozen = False,
|
frozen = False
|
||||||
default = None
|
|
||||||
)
|
|
||||||
|
|
||||||
clientPaymentRequestJSON: str | int = Field(
|
|
||||||
description = "how the third-party client responded when you requested the payment",
|
|
||||||
frozen = False,
|
|
||||||
default = None
|
|
||||||
)
|
|
||||||
|
|
||||||
clientPaymentResponseHttpCode: int | str = Field(
|
|
||||||
description = "the http code the third-party client returned when your user responded to the payment request",
|
|
||||||
frozen = False,
|
|
||||||
default = None
|
|
||||||
)
|
|
||||||
|
|
||||||
clientPaymentResponseJSON: str | int | None = Field(
|
|
||||||
description = "how the third-party client responded when your user responded to the payment request",
|
|
||||||
frozen = False,
|
|
||||||
default = None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# ┏┓ ┏•
|
# ┏┓ ┏•
|
||||||
@@ -175,7 +200,7 @@ class CorePaymentModel(BaseModel):
|
|||||||
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
||||||
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
||||||
|
|
||||||
@field_validator("requestTs", "responseTs", mode = "before")
|
@field_validator("lastEventTs", mode = "before")
|
||||||
def parse_date_time(cls, value):
|
def parse_date_time(cls, value):
|
||||||
return date_time.parse_date_time(input_value = value, timezone = date_time.TIMEZONE_UTC)
|
return date_time.parse_date_time(input_value = value, timezone = date_time.TIMEZONE_UTC)
|
||||||
|
|
||||||
@@ -203,16 +228,42 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
from utils_v2.string import json
|
from utils_v2.string import json
|
||||||
|
|
||||||
|
now = date_time.get_current_utc_date_time(as_string = False)
|
||||||
|
|
||||||
payment = CorePaymentModel(
|
payment = CorePaymentModel(
|
||||||
paymentStatus = "requested",
|
paymentStatus = "authorized",
|
||||||
tokenId = "67519cf3a7804fcbc6f12452",
|
tokenId = "67519cf3a7804fcbc6f12452",
|
||||||
amount = 1.00,
|
amount = 1.00,
|
||||||
currencyCode = "INR",
|
currencyCode = "INR",
|
||||||
metadata = {
|
metadata = {
|
||||||
"userId": 1,
|
"userId": 1,
|
||||||
"name": "My Test"
|
"name": "Bhopli"
|
||||||
},
|
},
|
||||||
client = "safaricomMPesaExpress"
|
client = "razorpay",
|
||||||
|
clientPaymentReferenceId = "txn_123_abc",
|
||||||
|
lastEventTs = now,
|
||||||
|
events = [
|
||||||
|
PaymentEvent(
|
||||||
|
eventTs = now - datetime.timedelta(minutes = 1, seconds = 12),
|
||||||
|
initByPG = True,
|
||||||
|
httpCode = None,
|
||||||
|
payload = {
|
||||||
|
"status": "captured",
|
||||||
|
"from": "Barfi",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
PaymentEvent(
|
||||||
|
eventTs = now,
|
||||||
|
initByPG = True,
|
||||||
|
httpCode = None,
|
||||||
|
payload = {
|
||||||
|
"status": "authorized",
|
||||||
|
"from": "Barfi",
|
||||||
|
"amount": -100.00,
|
||||||
|
"description": "meow"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
print("PAYMENT TXN. MODEL:", json.to_string(payment.model_dump(), default = str))
|
print("PAYMENT TXN. MODEL:", json.to_string(payment.model_dump(), default = str))
|
||||||
@@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
DATE:
|
DATE:
|
||||||
|
|
||||||
Saturday, 7th Dec., 2024.
|
Monday, 9th Dec., 2024.
|
||||||
|
|
||||||
OBJECTIVE:
|
OBJECTIVE:
|
||||||
|
|
||||||
To define how auth tokens will be stored in the database.
|
To define how user info will be stored in the database.
|
||||||
|
|
||||||
REFERENCES:
|
REFERENCES:
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ import datetime
|
|||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
class CoreAuthTokenModel(BaseModel):
|
class CoreUserInfoModel(BaseModel):
|
||||||
|
|
||||||
version: str = Field(
|
version: str = Field(
|
||||||
description = "a hint about the version no. of this message",
|
description = "a hint about the version no. of this message",
|
||||||
@@ -86,72 +86,40 @@ class CoreAuthTokenModel(BaseModel):
|
|||||||
default = "1.0.0"
|
default = "1.0.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
serviceType: Literal["email", "sms", "chat"] = Field(
|
fullName: str | None = Field(
|
||||||
description = "the kind of service this message was sent/received from",
|
description = "the full name of the user as found in the database",
|
||||||
frozen = True
|
|
||||||
)
|
|
||||||
|
|
||||||
client: Literal[
|
|
||||||
"gmail", "outlook", # ...................... Mail Clients
|
|
||||||
"telegram", "whatsapp", # .................. Chat Clients
|
|
||||||
"nimbusSmsIndia", "savvyBulkSmsKenya", # ... SMS Clients
|
|
||||||
"razorpay", "safaricomMPesaExpress" # ...... Payment Gateways
|
|
||||||
] = Field(
|
|
||||||
description = "the third-part client that was used",
|
|
||||||
frozen = True
|
|
||||||
)
|
|
||||||
|
|
||||||
authType: Literal["oauth", "auth"] = Field(
|
|
||||||
description = "the type of authentication procedure used",
|
|
||||||
frozen = True
|
|
||||||
)
|
|
||||||
|
|
||||||
firstRequestTs: AwareDatetime = Field(
|
|
||||||
description = "the time (utc) at which authorization was first requested",
|
|
||||||
frozen = True
|
|
||||||
)
|
|
||||||
|
|
||||||
lastRequestTs: AwareDatetime = Field(
|
|
||||||
description = "the time (utc) at which authorization was last requested",
|
|
||||||
frozen = False
|
|
||||||
)
|
|
||||||
|
|
||||||
firstRefreshTs: AwareDatetime = Field(
|
|
||||||
description = "the time (utc) at which the tokens were first refreshed",
|
|
||||||
frozen = False
|
|
||||||
)
|
|
||||||
|
|
||||||
lastRefreshTs: AwareDatetime = Field(
|
|
||||||
description = "the time (utc) at which the tokens were last refreshed",
|
|
||||||
frozen = False
|
|
||||||
)
|
|
||||||
|
|
||||||
token: dict | None = Field(
|
|
||||||
description = "the actual auth tokens of that client; will differ for each client",
|
|
||||||
frozen = True,
|
frozen = True,
|
||||||
default_factory = lambda: date_time.get_current_utc_date_time(as_string = False)
|
examples = ["Bhopli Narangi"]
|
||||||
)
|
)
|
||||||
|
|
||||||
user: dict = Field(
|
userId: int | str | None = Field(
|
||||||
description = "how you identify your user",
|
description = "the id of the user as found in the database",
|
||||||
frozen = True
|
frozen = True
|
||||||
)
|
)
|
||||||
|
|
||||||
clientUserId: dict = Field(
|
entityId: int | str | None = Field(
|
||||||
description = "how third-party client identifies the same user",
|
description = "the id of the entity with which this user is associated",
|
||||||
frozen = True
|
frozen = True
|
||||||
)
|
)
|
||||||
|
|
||||||
status: Literal["active", "disabled"] = Field(
|
billingAccountId: int | str | None = Field(
|
||||||
description = "to indicate the status of this account",
|
description = "the id of the billing account with which this user is associated",
|
||||||
frozen = False,
|
frozen = True
|
||||||
default = "active"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
syncFreq: Literal[60, 300, 1500] = Field(
|
departmentId: int | str | None = Field(
|
||||||
description = "the no. of seconds after which to poll for updates from the client (if applicable)",
|
description = "the id of the dept. in which this user is working",
|
||||||
frozen = False,
|
frozen = True
|
||||||
default = 300
|
)
|
||||||
|
|
||||||
|
branchId: int | str | None = Field(
|
||||||
|
description = "the id of the branch in which this user is working",
|
||||||
|
frozen = True
|
||||||
|
)
|
||||||
|
|
||||||
|
industry: str | None = Field(
|
||||||
|
description = "the name of the industry this user is working in",
|
||||||
|
frozen = True
|
||||||
)
|
)
|
||||||
|
|
||||||
# ┏┓ ┏•
|
# ┏┓ ┏•
|
||||||
@@ -160,21 +128,9 @@ class CoreAuthTokenModel(BaseModel):
|
|||||||
# ┛
|
# ┛
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
extra = "allow"
|
extra = "ignore"
|
||||||
arbitrary_types_allowed = True
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
# ┓┏ ┓• ┓ •
|
|
||||||
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
|
||||||
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
|
||||||
|
|
||||||
@field_validator(
|
|
||||||
"firstRequestTs",
|
|
||||||
"lastRequestTs", "firstRefreshTs", "lastRefreshTs",
|
|
||||||
mode = "before"
|
|
||||||
)
|
|
||||||
def parse_date_time(cls, value):
|
|
||||||
return date_time.parse_date_time(input_value = value, timezone = date_time.TIMEZONE_UTC)
|
|
||||||
|
|
||||||
|
|
||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
# ***** ****
|
# ***** ****
|
||||||
@@ -184,29 +140,4 @@ class CoreAuthTokenModel(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from utils_v2.string import json
|
pass
|
||||||
|
|
||||||
auth_token = CoreAuthTokenModel(
|
|
||||||
serviceType = "email",
|
|
||||||
client = "gmail",
|
|
||||||
authType = "oauth",
|
|
||||||
firstRequestTs = date_time.get_current_utc_date_time(as_string = False),
|
|
||||||
lastRequestTs = date_time.get_current_utc_date_time(as_string = False),
|
|
||||||
firstRefreshTs = date_time.get_current_utc_date_time(as_string = False),
|
|
||||||
lastRefreshTs = date_time.get_current_utc_date_time(as_string = False),
|
|
||||||
token = {
|
|
||||||
"username": "testing123",
|
|
||||||
"password": "abcdefgh"
|
|
||||||
},
|
|
||||||
user = {
|
|
||||||
"userId": 0,
|
|
||||||
"entityId": 1,
|
|
||||||
"billingAccountId": 2,
|
|
||||||
"fullName": "Bhopli"
|
|
||||||
},
|
|
||||||
clientUserId = {
|
|
||||||
"email": "bhopli@gmail.com"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
print("AUTH-TOKEN MODEL:", json.to_string(auth_token.model_dump(), default = str))
|
|
||||||
|
|||||||
Reference in New Issue
Block a user