""" AUTHOR: Khushal P Soonderji DATE: Monday, 10th Feb., 2025. OBJECTIVE: To handle all MikroTik configuration from one place. REFERENCES: N/A DOWNLOADS: N/A """ import datetime # ***************************************************************************************************************** # ***** **** # *** IMPORT *** # ***** **** # ***************************************************************************************************************** # To make sibling directories accessible for imports: import sys sys.path.append(".") sys.path.append("..") # My async utils: from utils_v2.string import json from utils_v2.date_time import date_time from utils_v2.mikrotik.controllers.async_mikrotik import AsyncMikroTik from utils_v2.database.async_mysql_v2 import AsyncMySQL from utils_v2.database.async_mongo_v2 import AsyncMongo from utils_v2.cache.async_redis_cache_v2 import AsyncRedisCache # Controllers: from controllers_v2.core.software import CoreSoftwareController # To make very controlled API calls: from utils_v2.rest.controllers.async_base import AsyncREST from utils_v2.rest.models.api_call import ApiResponse # Models: from models.software.mikrotik.auth import ( MikroTikPPPoE1000Auth, MikroTikHotspot1000Auth, MikroTikAuthResponse ) from models.software.mikrotik.configure import ( MikroTikConfigAttemptResponse, MikroTikRollBackAttemptResponse ) # To work with IP Addresses: import ipaddress # To work with datatypes: from typing import List, Any # To make HTTP requests: import httpx # to work with MongoDB: from bson.objectid import ObjectId # To make abstract classes: from abc import ABC, abstractmethod # Misc: import math # ***************************************************************************************************************** # ***** **** # *** MACROS / ONE-TIME INIT *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** VARIABLES *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** FUNCTIONS *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** CLASSES *** # ***** **** # ***************************************************************************************************************** class MikroTikController(CoreSoftwareController, ABC): # ┏┓┓ ┓┏ # ┃ ┃┏┓┏┏ ┃┃┏┓┏┓┏ # ┗┛┗┗┻┛┛ ┗┛┗┻┛ ┛ SERVICE_TYPE = "mikrotik" # ┏┓ # ┃ ┏┓┏┓┏╋┏┓┓┏┏╋┏┓┏┓ # ┗┛┗┛┛┗┛┗┛ ┗┻┗┗┗┛┛ def __init__( self, cache: AsyncRedisCache = None, http_client: httpx.AsyncClient = None, alert_url: str = None, base_filter: dict = None, debug: bool = True, debug_prefix: str = "MikroTik (C) | ", debug_only_errors: bool = True ): """ This is the foundational controller for all MikroTik services. This is built on top of the core message controller, and, in turn, all individual MikroTik client controllers must be built on top of this. :param cache: The object to use for caching results from database calls. :param http_client: The HTTP client to use to make REST-ful API calls. :param base_filter: The basic filter that will be applied to all fetching/updating queries. WARNING: THE BASE FILTER WILL ALWAYS BE APPLIED AUTOMATICALLY. SET THIS UP WISELY. :param debug: Whether, or not, you would like to print debugging messages: :param debug_prefix: The prefix to print with the debugging messages. :param debug_only_errors: Whether you would like to print only error messages or all messages. :return: None. """ # Prepare the combined base filter: mikrotik_filter = {} for k, v in (base_filter or {}).items(): mikrotik_filter[k] = v mikrotik_filter["serviceType"] = self.SERVICE_TYPE # Invoke the parent's constructor: CoreSoftwareController.__init__( self, cache = cache, alert_url = alert_url, http_client = http_client, base_filter = mikrotik_filter, debug = debug, debug_prefix = debug_prefix, debug_only_errors = debug_only_errors ) # Init a variable in a parent: self._service_type = self.SERVICE_TYPE # For controlled REST-ful calls: self._rest = AsyncREST( http_client = http_client, debug = debug, debug_prefix = debug_prefix, debug_only_errors = debug_only_errors ) # ┏┓ ┓ # ┣┫┓┏╋┣┓ # ┛┗┗┻┗┛┗ @abstractmethod async def save_auth( self, sql_conn: AsyncMySQL, mongo_data_conn: AsyncMongo, mikrotik_auth: MikroTikPPPoE1000Auth | MikroTikHotspot1000Auth ) -> MikroTikAuthResponse: """ Checks if a particular set of incoming credentials give access to a valid server and then stores the credentials. :param sql_conn: The database connection to use to perform this task. :param mongo_data_conn: The database connection to use to perform this task. :param mikrotik_auth: The set of credentials as received from the UI/API. :return: A structured response to indicate what happened during authorization. """ pass # ┏┓ ┏• # ┃ ┏┓┏┓╋┓┏┓ # ┗┛┗┛┛┗┛┗┗┫ # ┛ @abstractmethod async def roll_back( self, mikrotik_client: AsyncMikroTik, mikrotik_auth: MikroTikPPPoE1000Auth | MikroTikHotspot1000Auth ) -> MikroTikRollBackAttemptResponse: """ The rolling-back to the original state (as best as possible) in case the configurations fails midway after completing some no. of steps. :param mikrotik_client: The client to use. :param mikrotik_auth: The set of credentials as received from the UI/API. :return: A structured response to indicate what happened during the configuration attempt. """ pass @abstractmethod async def configure( self, mikrotik_client: AsyncMikroTik, mikrotik_auth: MikroTikPPPoE1000Auth | MikroTikHotspot1000Auth ) -> MikroTikConfigAttemptResponse: """ Run the configuration steps for the system. :param mikrotik_client: The client to use. :param mikrotik_auth: The set of credentials as received from the UI/API. :return: A structured response to indicate what happened during the configuration attempt. """ pass # ***************************************************************************************************************** # ***** **** # *** MAIN PROGRAM *** # ***** **** # ***************************************************************************************************************** if __name__ == "__main__": pass