(20241213) Return code is not the HTTP Status Code.

This commit is contained in:
2024-12-13 14:13:47 +05:30
parent e9a106dd91
commit a702e5ca20
13 changed files with 197 additions and 122 deletions
+190
View File
@@ -0,0 +1,190 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Tuesday, 3rd Dec., 2024
OBJECTIVE:
To get one full mail for any given user for any given account.
REFERENCES:
N/A
DOWNLOADS:
N/A
NOTES:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
# To make sibling directories accessible for imports:
import sys
sys.path.append(".")
sys.path.append("..")
# For using Quart:
from quart import Blueprint, current_app, g, request
# My utils:
from utils_v2.string import json
from utils_v2.database.async_mongo_v2 import AsyncMongo
from utils_v2.api.codes import StatusCodes, HttpCodes
from utils_v2.api.response import ResponseModel
from utils_v2.api.async_quart import (
make_ordered_json,
set_api_version,
read_input,
get_session_info,
log_request_to_mongo,
log_chain_to_mongo,
should_not_be_under_maintenance,
only_whitelisted_ips,
limit_rate,
validate_input,
handle_cancelled_request
)
# GMail-related utils:
from utils_v2.goog.gmail.gmail_client import SCOPES_GMAIL_MAIL_MANAGEMENT
from utils_v2.goog.models.data.auth_tokens import GoogleAuthTokens
# Common:
from shared import constants
# Data Models:
from models.api.mail.get import MailGetRequestHeaders, MailGetRequestData
# To work with datatypes:
from typing import Literal
# For asynchronous activities:
import asyncio
# To work with date and time:
import datetime
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
# Related to Quart:
mail_get_bp = Blueprint("mail_get", __name__)
# *****************************************************************************************************************
# ***** ****
# *** VARIABLES ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** FUNCTIONS ***
# ***** ****
# *****************************************************************************************************************
@mail_get_bp.record_once
def init(blueprint_setup_state):
# This gets called when the blueprint is registered.
# Consider this to be a one-time setup for the whole blueprint:
pass
# ---------------------------------------------------------------------------------------------------------------------
@mail_get_bp.route("", methods = ["GET"])
@set_api_version(api_version = "1.0.0")
@read_input(sanitize_headers = False, sanitize_data = False)
@get_session_info(key = "X-Session-Token", session_coro = "get_session")
@log_request_to_mongo(
attr_name = "logs_mongo",
project = constants.PROJECT_NAME,
log_type = constants.MODULE_NAME,
operation = "mailGetApi",
log_input = True,
log_output = True,
sensitive_keys = ["sessionToken", "X-Session-Token"]
)
@log_chain_to_mongo(attr_name = "logs_mongo")
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
@validate_input(
header_validator = lambda x: MailGetRequestHeaders(**x).model_dump(),
data_validator = lambda x: MailGetRequestData(**x)
)
@handle_cancelled_request()
async def get_one_mail(
inbound_headers: dict | MailGetRequestHeaders = None,
inbound_data: dict | MailGetRequestData = None,
inbound_files: dict = None,
**kwargs
):
"""
Use this endpoint when the user wants to fetch one mail's full payload.
:param inbound_headers: auto-extracted by the decorators.
:param inbound_data: auto-extracted by the decorators.
:param inbound_files: auto-extracted by the decorators.
:param kwargs: Any number of extra inputs supplied by the decorators.
:return: A standard response structure.
"""
# If the session token is invalid/expired:
if kwargs.get("session_info") is None:
return ResponseModel(
status_code = StatusCodes.FAILED,
http_code = HttpCodes.UNAUTHORIZED
)
# Get the mail:
message = await current_app.mail_controller.get_one_mail(
mongo_conn = current_app.data_mongo,
token_id = inbound_data.tokenId,
message_id = inbound_data.messageId
)
# Done here:
return ResponseModel(
status_code = StatusCodes.OK if message else StatusCodes.FAILED,
http_code = HttpCodes.SUCCESS if message else HttpCodes.NOT_FOUND,
data = message.full
)
# *****************************************************************************************************************
# ***** ****
# *** MAIN PROGRAM ***
# ***** ****
# *****************************************************************************************************************
if __name__ == "__main__":
pass
+203
View File
@@ -0,0 +1,203 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Tuesday, 3rd Dec., 2024
OBJECTIVE:
To list e-mails by their token identifier. Remember that the 'token identifier' is the '_id' of the document in
MongoDB that holds the tokens to authorize the e-mail id whose mails are being accessed.
REFERENCES:
N/A
DOWNLOADS:
N/A
NOTES:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
# To make sibling directories accessible for imports:
import sys
sys.path.append(".")
sys.path.append("..")
# For using Quart:
from quart import Blueprint, current_app, g, request
# My utils:
from utils_v2.string import json
from utils_v2.database.async_mongo_v2 import AsyncMongo
from utils_v2.api.codes import StatusCodes, HttpCodes
from utils_v2.api.response import ResponseModel
from utils_v2.api.async_quart import (
make_ordered_json,
set_api_version,
read_input,
get_session_info,
log_request_to_mongo,
log_chain_to_mongo,
should_not_be_under_maintenance,
only_whitelisted_ips,
limit_rate,
validate_input,
handle_cancelled_request
)
# GMail-related utils:
from utils_v2.goog.gmail.gmail_client import SCOPES_GMAIL_MAIL_MANAGEMENT
from utils_v2.goog.models.data.auth_tokens import GoogleAuthTokens
# Common:
from shared import constants
# Data Models:
from models.api.mail.list import MailListRequestHeaders, MailListRequestData
# To work with datatypes:
from typing import Literal
# For asynchronous activities:
import asyncio
# To work with date and time:
import datetime
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
# Related to Quart:
mail_list_bp = Blueprint("mail_list", __name__)
# *****************************************************************************************************************
# ***** ****
# *** VARIABLES ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** FUNCTIONS ***
# ***** ****
# *****************************************************************************************************************
@mail_list_bp.record_once
def init(blueprint_setup_state):
# This gets called when the blueprint is registered.
# Consider this to be a one-time setup for the whole blueprint:
pass
# ---------------------------------------------------------------------------------------------------------------------
@mail_list_bp.route("/list", methods = ["GET"])
@mail_list_bp.route("/list/id/token", methods = ["GET", "POST"])
@mail_list_bp.route("/list/tags", methods = ["GET", "POST"])
@set_api_version(api_version = "1.0.0")
@read_input(sanitize_headers = False, sanitize_data = False)
@get_session_info(key = "X-Session-Token", session_coro = "get_session")
@log_request_to_mongo(
attr_name = "logs_mongo",
project = constants.PROJECT_NAME,
log_type = constants.MODULE_NAME,
operation = "mailListByTokIdApi",
log_input = True,
log_output = 1,
sensitive_keys = ["sessionToken", "X-Session-Token"]
)
@log_chain_to_mongo(attr_name = "logs_mongo")
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
@validate_input(
header_validator = lambda x: MailListRequestHeaders(**x).model_dump(),
data_validator = lambda x: MailListRequestData(**x)
)
@handle_cancelled_request()
async def list_mails(
inbound_headers: dict | MailListRequestHeaders = None,
inbound_data: dict | MailListRequestData = None,
inbound_files: dict = None,
**kwargs
):
"""
Use this endpoint when the user wants to fetch the list of mails. The shortlisting here will be done by way of the
token identifier. Any no. of 'tokenId' objects will be given by the client.
:param inbound_headers: auto-extracted by the decorators.
:param inbound_data: auto-extracted by the decorators.
:param inbound_files: auto-extracted by the decorators.
:param kwargs: Any number of extra inputs supplied by the decorators.
:return: A standard response structure.
"""
# If the session token is invalid/expired:
if kwargs.get("session_info") is None:
return ResponseModel(
status_code = StatusCodes.FAILED,
http_code = HttpCodes.UNAUTHORIZED
)
# Build the additional filter:
additional_filter = {}
if inbound_data.tags: additional_filter["tags"] = {"$in": inbound_data.tags}
additional_filter = additional_filter or None
print("AddFil:", additional_filter)
# Get the mails:
mails_list = await current_app.mail_controller.list_mails(
mongo_conn = current_app.data_mongo,
token_ids = inbound_data.tokenIds,
limit = inbound_data.count,
skip = inbound_data.fromCount,
additional_filter = additional_filter
)
# Done here:
return ResponseModel(
status_code = StatusCodes.OK if mails_list else StatusCodes.FAILED,
http_code = HttpCodes.SUCCESS if mails_list else HttpCodes.NOT_FOUND,
data = [mail.preview for mail in mails_list],
message = f"{len(mails_list) if mails_list else 0} mail(s) found"
)
# *****************************************************************************************************************
# ***** ****
# *** MAIN PROGRAM ***
# ***** ****
# *****************************************************************************************************************
if __name__ == "__main__":
pass