(20241217) payment reference will now be the same as the payment id.

This commit is contained in:
2024-12-17 15:57:13 +05:30
parent d24d9cc248
commit 2e0c0224d4
15 changed files with 93 additions and 69 deletions
@@ -166,7 +166,7 @@ async def payment_list(
# ┗┛┛┗┗┗┛┗ ┛ ┗┗┻┗┗┛ # ┗┛┛┗┗┗┛┗ ┛ ┗┗┻┗┗┛
# Get the token ids from the token keys: # Get the token ids from the token keys:
auth_tokens = await current_app.payment_controller.get_tokens( auth_tokens = await current_app.payment_controller.get_tokens_from_keys(
mongo_conn = current_app.data_mongo, mongo_conn = current_app.data_mongo,
token_keys = inbound_data.tokenKeys token_keys = inbound_data.tokenKeys
) )
@@ -167,7 +167,7 @@ async def request_payment(
# ┗ ┛ # ┗ ┛
# Get the token from the token key: # Get the token from the token key:
auth_token = await current_app.payment_controller.get_token( auth_token = await current_app.payment_controller.get_token_from_key(
mongo_conn = current_app.data_mongo, mongo_conn = current_app.data_mongo,
token_key = inbound_data.tokenKey token_key = inbound_data.tokenKey
) )
+1 -1
View File
@@ -159,7 +159,7 @@ async def handle_gmail_callback() -> render_template:
# 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:
auth_token = await current_app.mail_controller.get_token( auth_token = await current_app.mail_controller.get_token_from_key(
mongo_conn = current_app.data_mongo, mongo_conn = current_app.data_mongo,
token_key = g.inbound_data["state"] token_key = g.inbound_data["state"]
) )
+26 -20
View File
@@ -70,6 +70,7 @@ from shared import constants
# Data Models: # Data Models:
from models.api.mail.get import MailGetRequestHeaders, MailGetRequestData from models.api.mail.get import MailGetRequestHeaders, MailGetRequestData
from models.core.user import CoreUserInfoModel
# To work with datatypes: # To work with datatypes:
from typing import Literal from typing import Literal
@@ -80,6 +81,9 @@ import asyncio
# To work with date and time: # To work with date and time:
import datetime import datetime
# Helpers:
from api.helpers.user import token_check
# ***************************************************************************************************************** # *****************************************************************************************************************
# ***** **** # ***** ****
@@ -165,25 +169,7 @@ async def get_one_mail(
return ResponseModel( return ResponseModel(
status_code = StatusCodes.FAILED, status_code = StatusCodes.FAILED,
http_code = HttpCodes.UNAUTHORIZED, http_code = HttpCodes.UNAUTHORIZED,
messge = "invalid session" message = "Invalid session."
)
# ┏┓ ┓ ┏┳┓ ┓
# ┣ ┏┓╋┏┣┓ ┃ ┏┓┃┏┏┓┏┓┏
# ┻ ┗ ┗┗┛┗ ┻ ┗┛┛┗┗ ┛┗┛
# We first load the authorization tokens:
auth_token = await current_app.mail_controller.get_token(
mongo_conn = current_app.data_mongo,
token_key = inbound_data.tokenKey,
)
# If we failed to load the authorization tokens:
if not auth_token:
return ResponseModel(
status_code = StatusCodes.FAILED,
http_code = HttpCodes.UNAUTHORIZED,
message = f"no such token key '{inbound_data.tokenKey}'"
) )
# ┏┓ ┓ ┳┳┓ •┓ # ┏┓ ┓ ┳┳┓ •┓
@@ -193,10 +179,30 @@ async def get_one_mail(
# Get the mail: # Get the mail:
message = await current_app.mail_controller.get_one_mail( message = await current_app.mail_controller.get_one_mail(
mongo_conn = current_app.data_mongo, mongo_conn = current_app.data_mongo,
token_id = auth_token.authTokenId,
message_id = inbound_data.messageId message_id = inbound_data.messageId
) )
# ┏┓ ┓ • ┏┓┓ ┓
# ┃┃┓┏┏┏┓┏┓┏┓┏┣┓┓┏┓ ┃ ┣┓┏┓┏┃┏
# ┗┛┗┻┛┛┗┗ ┛ ┛┛┗┗┣┛ ┗┛┛┗┗ ┗┛┗
# ┛
# We check if the token that was used to fetch the mail is owned by this user:
if not await token_check.is_authorized(
mongo_conn = current_app.data_mongo,
user_info = CoreUserInfoModel(**kwargs["session_info"]),
token_ids = [message.tokenId]
): return ResponseModel(
status_code = StatusCodes.FAILED,
http_code = HttpCodes.UNAUTHORIZED,
message = "The message does not belong to this user."
)
# ┳┓
# ┣┫┏┓┏┏┓┏┓┏┓┏┏┓
# ┛┗┗ ┛┣┛┗┛┛┗┛┗
# ┛
# Done here: # Done here:
return ResponseModel( return ResponseModel(
status_code = StatusCodes.OK if message else StatusCodes.FAILED, status_code = StatusCodes.OK if message else StatusCodes.FAILED,
+1 -1
View File
@@ -180,7 +180,7 @@ async def list_mails(
# ┗┛┛┗┗┗┛┗ ┛ ┗┗┻┗┗┛ # ┗┛┛┗┗┗┛┗ ┛ ┗┗┻┗┗┛
# Get the token ids from the token keys: # Get the token ids from the token keys:
auth_tokens = await current_app.mail_controller.get_tokens( auth_tokens = await current_app.mail_controller.get_tokens_from_keys(
mongo_conn = current_app.data_mongo, mongo_conn = current_app.data_mongo,
token_keys = inbound_data.tokenKeys token_keys = inbound_data.tokenKeys
) )
-6
View File
@@ -172,12 +172,6 @@ async def update_mail_tags(
# ┗┛┣┛┗┻┗┻┗┗ ┛ ┗┗┻┗┗ # ┗┛┣┛┗┻┗┻┗┗ ┛ ┗┗┻┗┗
# ┛ # ┛
# get the token id from the token key:
auth_token = await current_app.mail_controller.get_token(
mongo_conn = current_app.data_mongo,
token_key = inbound_data.tokenKey
)
# Update the mail: # Update the mail:
success = await current_app.mail_controller.update_tags( success = await current_app.mail_controller.update_tags(
mongo_conn = current_app.data_mongo, mongo_conn = current_app.data_mongo,
+1 -1
View File
@@ -162,7 +162,7 @@ async def send_sms(
# ┗┛┗ ┛┗┗┻ ┻ ┛┗┗ ┗┛┛ ┗┗┛ # ┗┛┗ ┛┗┗┻ ┻ ┛┗┗ ┗┛┛ ┗┗┛
# Get the token from the token key: # Get the token from the token key:
auth_token = await current_app.mail_controller.get_token( auth_token = await current_app.mail_controller.get_token_from_key(
mongo_conn = current_app.data_mongo, mongo_conn = current_app.data_mongo,
token_key = inbound_data.tokenKey token_key = inbound_data.tokenKey
) )
+1 -1
View File
@@ -112,7 +112,7 @@ async def is_authorized(
# Fetch the auth tokens from the database: # Fetch the auth tokens from the database:
# Retrieve the document of the token id: # Retrieve the document of the token id:
auth_tokens = await current_app.core_auth_token_controller.get_tokens( auth_tokens = await current_app.core_auth_token_controller.get_tokens_from_ids(
mongo_conn = mongo_conn, mongo_conn = mongo_conn,
token_ids = [ObjectId(t) for t in token_ids] token_ids = [ObjectId(t) for t in token_ids]
) )
+2 -4
View File
@@ -286,7 +286,7 @@ class MailController:
) -> CoreAuthTokenModel | None: ) -> CoreAuthTokenModel | None:
# Simply call the core model: # Simply call the core model:
return await current_app.core_auth_token_controller.get_token( return await current_app.core_auth_token_controller.get_token_from_key(
mongo_conn = mongo_conn, mongo_conn = mongo_conn,
token_key = token_key token_key = token_key
) )
@@ -298,7 +298,7 @@ class MailController:
) -> List[CoreAuthTokenModel] | None: ) -> List[CoreAuthTokenModel] | None:
# Simply call the core model: # Simply call the core model:
return await current_app.core_auth_token_controller.get_tokens( return await current_app.core_auth_token_controller.get_tokens_from_keys(
mongo_conn = mongo_conn, mongo_conn = mongo_conn,
token_keys = token_keys token_keys = token_keys
) )
@@ -611,14 +611,12 @@ class MailController:
@staticmethod @staticmethod
async def get_one_mail( async def get_one_mail(
mongo_conn: AsyncMongo, mongo_conn: AsyncMongo,
token_id: ObjectId | str,
message_id: ObjectId | str message_id: ObjectId | str
) -> CoreMessageModel | None: ) -> CoreMessageModel | None:
# Simply call the core model: # Simply call the core model:
return await current_app.core_message_controller.get_message( return await current_app.core_message_controller.get_message(
mongo_conn = mongo_conn, mongo_conn = mongo_conn,
token_id = token_id,
message_id = message_id message_id = message_id
) )
+5 -5
View File
@@ -162,25 +162,25 @@ class PaymentController:
return success return success
@staticmethod @staticmethod
async def get_token( async def get_token_from_key(
mongo_conn: AsyncMongo, mongo_conn: AsyncMongo,
token_key: ObjectId | str = None, token_key: ObjectId | str = None,
) -> CoreAuthTokenModel | None: ) -> CoreAuthTokenModel | None:
# Simply call the core model: # Simply call the core model:
return await current_app.core_auth_token_controller.get_token( return await current_app.core_auth_token_controller.get_token_from_key(
mongo_conn = mongo_conn, mongo_conn = mongo_conn,
token_key = token_key token_key = token_key
) )
@staticmethod @staticmethod
async def get_tokens( async def get_tokens_from_keys(
mongo_conn: AsyncMongo, mongo_conn: AsyncMongo,
token_keys: ObjectId | str = None, token_keys: ObjectId | str = None,
) -> List[CoreAuthTokenModel] | None: ) -> List[CoreAuthTokenModel] | None:
# Simply call the core model: # Simply call the core model:
return await current_app.core_auth_token_controller.get_tokens( return await current_app.core_auth_token_controller.get_tokens_from_keys(
mongo_conn = mongo_conn, mongo_conn = mongo_conn,
token_keys = token_keys token_keys = token_keys
) )
@@ -223,7 +223,7 @@ class PaymentController:
substitute_text = "" substitute_text = ""
) if isinstance(payment_request.customerNo, str) else payment_request.customerNo, ) if isinstance(payment_request.customerNo, str) else payment_request.customerNo,
type = "CustomerPayBillOnline", type = "CustomerPayBillOnline",
reference = payment_request.reference, reference = str(payment_id),
description = payment_request.description, description = payment_request.description,
callback_url = callback_url, callback_url = callback_url,
payer_no = regex.replace( payer_no = regex.replace(
+1 -1
View File
@@ -173,7 +173,7 @@ class SMSController:
) -> CoreAuthTokenModel | None: ) -> CoreAuthTokenModel | None:
# Simply call the core model: # Simply call the core model:
return await current_app.core_auth_token_controller.get_token( return await current_app.core_auth_token_controller.get_token_from_key(
mongo_conn = mongo_conn, mongo_conn = mongo_conn,
token_key = token_key token_key = token_key
) )
+50 -4
View File
@@ -270,10 +270,33 @@ class CoreAuthTokenController(BaseModel):
# Done here: # Done here:
return token_saved return token_saved
async def get_token( async def get_token_from_id(
self, self,
mongo_conn: AsyncMongo, mongo_conn: AsyncMongo,
token_key: ObjectId | str = None, token_id: ObjectId | str = None,
) -> CoreAuthTokenModel | None:
"""
To retrieve stored tokens from the database. One token at a time.
:param mongo_conn: The database connection (MongoDB) to use to perform the action.
:param token_id: The identifier of the document that holds the token's details.
:return: The retrieved record that has the token, and information about the service and client if found, else
None when there is no matching record.
"""
# If there is some filtering possible, we fetch the token:
token = await mongo_conn.find_one(
collection = self.AUTH_COLLECTION,
filter = {"_id": ObjectId(token_id)}
)
# Done here:
return CoreAuthTokenModel(**token) if token else None
async def get_token_from_key(
self,
mongo_conn: AsyncMongo,
token_key: ObjectId | str = None
) -> CoreAuthTokenModel | None: ) -> CoreAuthTokenModel | None:
""" """
@@ -287,13 +310,36 @@ class CoreAuthTokenController(BaseModel):
# If there is some filtering possible, we fetch the token: # If there is some filtering possible, we fetch the token:
token = await mongo_conn.find_one( token = await mongo_conn.find_one(
collection = self.AUTH_COLLECTION, collection = self.AUTH_COLLECTION,
filter = {"key": ObjectId(token_key)}, filter = {"key": ObjectId(token_key)}
) )
# Done here: # Done here:
return CoreAuthTokenModel(**token) if token else None return CoreAuthTokenModel(**token) if token else None
async def get_tokens( async def get_tokens_from_ids(
self,
mongo_conn: AsyncMongo,
token_ids: List[ObjectId | str] = None,
) -> List[CoreAuthTokenModel]:
"""
To retrieve stored tokens from the database. Multiple tokens at a time.
:param mongo_conn: The database connection (MongoDB) to use to perform the action.
:param token_ids: The identifier of the document that holds the token's details.
:return: The retrieved record that has the token, and information about the service and client if found, else
None when there is no matching record.
"""
# If there is some filtering possible, we fetch the token:
tokens = await mongo_conn.find_many(
collection = self.AUTH_COLLECTION,
filter = {"_id": {"$in": [ObjectId(k) for k in token_ids]}}
)
# Done here:
return [CoreAuthTokenModel(**token) for token in tokens]
async def get_tokens_from_keys(
self, self,
mongo_conn: AsyncMongo, mongo_conn: AsyncMongo,
token_keys: List[ObjectId | str] = None, token_keys: List[ObjectId | str] = None,
+2 -12
View File
@@ -302,14 +302,12 @@ class CoreMessageController(BaseModel):
async def get_message( async def get_message(
self, self,
mongo_conn: AsyncMongo, mongo_conn: AsyncMongo,
token_id: ObjectId | str,
message_id: ObjectId | str, message_id: ObjectId | str,
) -> CoreMessageModel | None: ) -> CoreMessageModel | None:
""" """
Gets one message if you know its message id. Gets one message if you know its message id.
:param mongo_conn: The instance of the database connector to use for the operation. :param mongo_conn: The instance of the database connector to use for the operation.
:param token_id: The id of the auth-token associated with the message. Needed for security.
:param message_id: The id of the message that needs to be read. :param message_id: The id of the message that needs to be read.
:return: The contents of that one message in a structured format. :return: The contents of that one message in a structured format.
""" """
@@ -317,10 +315,7 @@ class CoreMessageController(BaseModel):
# We fetch the whole payload of that one message: # We fetch the whole payload of that one message:
record = await mongo_conn.find_one( record = await mongo_conn.find_one(
collection = self.MESSAGES_COLLECTION, collection = self.MESSAGES_COLLECTION,
filter = { filter = {"_id": ObjectId(message_id)},
"_id": ObjectId(message_id),
"tokenId": ObjectId(token_id)
},
raise_exception = True raise_exception = True
) )
@@ -342,7 +337,6 @@ class CoreMessageController(BaseModel):
async def update_tags( async def update_tags(
self, self,
mongo_conn: AsyncMongo, mongo_conn: AsyncMongo,
token_id: ObjectId | str,
message_id: ObjectId | str, message_id: ObjectId | str,
unset_tags: List[str] = None, unset_tags: List[str] = None,
set_tags: List[str] = None set_tags: List[str] = None
@@ -351,7 +345,6 @@ class CoreMessageController(BaseModel):
""" """
Updates the tags on one message. The tags to remove are processed first, the ones to add are processed later. Updates the tags on one message. The tags to remove are processed first, the ones to add are processed later.
:param mongo_conn: The instance of the database connector to use for the operation. :param mongo_conn: The instance of the database connector to use for the operation.
:param token_id: The id of the auth-token associated with the message. Needed for security.
:param message_id: The id of the message that needs to be read. :param message_id: The id of the message that needs to be read.
:param unset_tags: The tags to remove from the message. :param unset_tags: The tags to remove from the message.
:param set_tags: The tags to add to the message. :param set_tags: The tags to add to the message.
@@ -361,10 +354,7 @@ class CoreMessageController(BaseModel):
# Update the tags: # Update the tags:
return await mongo_conn.update_one( return await mongo_conn.update_one(
collection = self.MESSAGES_COLLECTION, collection = self.MESSAGES_COLLECTION,
filter = { filter = {"_id": ObjectId(message_id)},
"_id": ObjectId(message_id),
"tokenId": ObjectId(token_id)
},
update = [{ update = [{
"$set": { "$set": {
"tags": { "tags": {
+1 -6
View File
@@ -168,7 +168,7 @@ class PGPaymentRequestData(BaseModel):
amount: float | int = Field( amount: float | int = Field(
description = "the amount of money to be requested", description = "the amount of money to be requested",
ge = 0, ge = 0.0,
frozen = True frozen = True
) )
@@ -178,11 +178,6 @@ class PGPaymentRequestData(BaseModel):
examples = ["INR", "USD", "KES"] examples = ["INR", "USD", "KES"]
) )
reference: str | None = Field(
description = "some reference against which the payment was made",
frozen = True
)
description: str | None = Field( description: str | None = Field(
description = "a short, human-readable description of the payment", description = "a short, human-readable description of the payment",
frozen = True frozen = True
-5
View File
@@ -101,11 +101,6 @@ class MailGetRequestHeaders(BaseModel):
class MailGetRequestData(BaseModel): class MailGetRequestData(BaseModel):
tokenKey: str = Field(
description = "the id of the token associated with the mail; needed for security",
frozen = True
)
messageId: str = Field( messageId: str = Field(
description = "the mail identifier (Mongo ObjectId) of the document that holds the mail", description = "the mail identifier (Mongo ObjectId) of the document that holds the mail",
frozen = True frozen = True