5.1.1. Build aws client, constants and configs

Go into the constants folder and create the following files: app.py, regex.py, and __init__.py.

In app.py, add:

import os
from dotenv import load_dotenv

load_dotenv()

APP_CONSTANTS = {
    "HOST": os.getenv("HOST", "localhost"),
    "PORT": int(os.getenv("PORT", "7800")),
}

5.1.1.1

Here you can see the process variable – it holds runtime information. env stores environment variables, which are loaded from the .env file we create based on .env.example.

HOST and PORT are the two environment variables we set up in .env.example earlier.

In regex.py, add some regular expressions:

import re

# Common Regexes
CUSTOMER_ID_PREFIX_PATTERN = r"^CUSTOMER#"
CUSTOMER_ID_PREFIX_REGEX = re.compile(CUSTOMER_ID_PREFIX_PATTERN)

VIETNAMESE_NAME_PATTERN = (
    r"^[AÀẢÃÁẠĂẰẲẴẮẶÂẦẨẪẤẬBCDĐEÈẺẼÉẸÊỀỂỄẾỆFGHIÌỈĨÍỊJKLMNOÒỎÕÓỌÔỒỔỖỐỘƠỜỞỠỚỢPQRSTUÙỦŨÚỤƯỪỬỮỨỰVWXYỲỶỸÝỴZ]"
    r"[aàảãáạăằẳẵắặâầẩẫấậbcdđeèẻẽéẹêềểễếệfghiìỉĩíịjklmnoòỏõóọôồổỗốộơờởỡớợpqrstuùủũúụưừửữứựvwxyỳỷỹýỵz]+ "
    r"[AÀẢÃÁẠĂẰẲẴẮẶÂẦẨẪẤẬBCDĐEÈẺẼÉẸÊỀỂỄẾỆFGHIÌỈĨÍỊJKLMNOÒỎÕÓỌÔỒỔỖỐỘƠỜỞỠỚỢPQRSTUÙỦŨÚỤƯỪỬỮỨỰVWXYỲỶỸÝỴZ]"
    r"[aàảãáạăằẳẵắặâầẩẫấậbcdđeèẻẽéẹêềểễếệfghiìỉĩíịjklmnoòỏõóọôồổỗốộơờởỡớợpqrstuùủũúụưừửữứựvwxyỳỷỹýỵz]+"
    r"(?: [AÀẢÃÁẠĂẰẲẴẮẶÂẦẨẪẤẬBCDĐEÈẺẼÉẸÊỀỂỄẾỆFGHIÌỈĨÍỊJKLMNOÒỎÕÓỌÔỒỔỖỐỘƠỜỞỠỚỢPQRSTUÙỦŨÚỤƯỪỬỮỨỰVWXYỲỶỸÝỴZ]"
    r"[aàảãáạăằẳẵắặâầẩẫấậbcdđeèẻẽéẹêềểễếệfghiìỉĩíịjklmnoòỏõóọôồổỗốộơờởỡớợpqrstuùủũúụưừửữứựvwxyỳỷỹýỵz]*)*"
)
VIETNAMESE_NAME_REGEX = re.compile(VIETNAMESE_NAME_PATTERN)

VIETNAMESE_PHONENUMBER_PATTERN = r"(84|0[3|5|7|8|9])+([0-9]{8})\b"
VIETNAMESE_PHONENUMBER_REGEX = re.compile(VIETNAMESE_PHONENUMBER_PATTERN)

USERNAME_PATTERN = r"^[a-zA-Z0-9._-]{3,30}$"
USERNAME_REGEX = re.compile(USERNAME_PATTERN)

PASSWORD_PATTERN = r"^[A-Za-z0-9!@#$%^&*()\[\]{}:;.,<>?/\\|_~`+=\-]{8,128}$"
PASSWORD_REGEX = re.compile(PASSWORD_PATTERN)

# Date Regex
ISO8601_DATETIME_PATTERN = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$"
ISO8601_DATETIME_REGEX = re.compile(ISO8601_DATETIME_PATTERN)

# Other Regex
SNAKECASE_PATTERN = r"^[a-z]+(_[a-z]+)*$"
SNAKECASE_REGEX = re.compile(SNAKECASE_PATTERN)

5.1.1.2

These regex patterns will be used for data validation inside the core part of the app.

And in __init__.py, export the variables from the two files above:

from .app import *
from .regex import *

5.1.1.3

Configs

Next, add a main.py file to hold the remaining environment variables and constants that are more app- or function-related (just the variables themselves here).

import os

# Import external packages
from dotenv import load_dotenv

# Tải biến môi trường từ file .env
load_dotenv()


class Configs:
    Aws_Profile = os.getenv("AWS_PROFILE")
    Aws_Access_Key_Id = os.getenv("AWS_ACCESS_KEY_ID", "")
    Aws_Secret_Access_Key = os.getenv("AWS_SECRET_ACCESS_KEY", "")
    Aws_Region = os.getenv("AWS_REGION", "ap-southeast-1")
    DynamoDB_Table_Name_PCustomers = os.getenv(
        "DYNAMODB_TABLE_NAME_PCUSTOMERS", "test_table"
    )
    Cognito_User_Pool_Id = os.getenv("COGNITO_USER_POOL_ID", "")
    Cognito_App_Client_Id = os.getenv("COGNITO_APP_CLIENT_ID", "")
    Cognito_App_Client_Secret = os.getenv("COGNITO_APP_CLIENT_SECRET", "")

5.1.1.4

Create an __init__.py file and add the following code:

from .main import *

5.1.1.5

AWS Clients

First, create a main.py file and add the following code snippets:

import boto3

# Import from utils
from utils.configs import Configs

def get_client(
    service_name: str,
    profile_name: str = Configs.Aws_Profile,
    region_name: str = Configs.Aws_Region,
):
    """Hàm nền tảng dùng để tạo bất kì client cho bất kì dịch vụ nào đó.

    Args:
        service_name (str): tên dịch vụ.
        profile_name (str): tên của profile.
        region_name (str): tên của region.

    Returns:
        _: client của service.
    """
    # Create a session using the named profile 'vsl'
    session = boto3.Session(profile_name=profile_name)

    # Create a Service client from the session
    client = session.client(
        service_name=service_name, region_name=region_name
    )  # adjust region as needed
    return client

Write a function to get the DynamoDB client configured according to our standard:

def get_dynamodb_client():
    """Cấu hình và lấy DynamoDB Client.

    Returns:
        boto3 DynamoDB client
    """
    return get_client(service_name="dynamodb")


def get_cognito_idp_client():
    """Cấu hình và lấy Cognito Identity Provider Client.

    Returns:
        boto3 Cognito IDP client
    """
    return get_client(service_name="cognito-idp")

5.1.1.6

Then create an __init__.py file and add the following code:

from .main import *

5.1.1.7

That’s it — we’ve finished adding code for AWS Client, Constants, and Configs. In the next section we’ll build the crypto module, and I’ll explain it in more detail there.