milestonexprotectrestpython.xprrestservicebase

Module: xprrestservicebase.py

Revision History

Date Version Description
2023/07/11 1.0.0.0 Initial Version.

@export
class XPRRestServiceBase:

The XPRRestServiceBase class provides properties common to all XProtect REST services.

Threadsafety:

This class is fully thread-safe.

XPRRestServiceBase()

Initializes a new instance of the class.

Raises:
  • TypeError: The loginInfo argument is not of type XPRLoginInfo.
  • Exception: The method fails for any other reason.
ApiGatewayUrlPrefix: str

URL prefix of the XProtect REST API Gateway server.

Returns:

The ApiGatewayUrlPrefix property value.

This url prefix is used to call various REST API services that are hosted by the XProtect API Gateway.

It should only contain the server name (and port number if required) portion of the API Gateway server (e.g. "https://xprotectapigateway.example.com", or "https://xprotectapigateway.example.com:443") url prefix.

It should NOT contain any of the API Gateway REST version information (e.g. "/api/rest/v1/") details.

IsAutoTokenRenewalEnabled: bool

Enables / disables the automatic token renewal check logic check that is made prior to making a call to the XProtect REST service.

Returns:

The IsAutoTokenRenewalEnabled property value.

If True, the LoginInfo.ExpireTime value is checked to see if the XProtect token is within 1 minute of expiring PRIOR to processing the desired API method (e.g. GetCameras, etc). If the token is about to expire, then it will be automatically renewed via a call to the XProtect REST Login method (e.g. LoginBasicUser, LoginBasicWindows) that was previously used to login and establish the authentication token. The desired API method (e.g. GetCameras, etc) is then processed as requested.

If False, the desired API method (e.g. GetCameras, etc) is processed normally, though it will probably fail with a XPRLoginTokenExpiredException due to an expired token!

IsSslVerifyEnabled: bool

SSL Verify flag used on all request GET / POST method calls. Default Value is True.

Returns:

The IsSslVerifyEnabled property value.

This setting will be added to all request GET / POST calls made to the XProtect REST services.

If False, it will ignore SSL Certificate warnings (e.g. certificate expired, self-signed certificate, etc). It also makes a call to "urllib3.disable_warnings(category=InsecureRequestWarning)" to suppress terminal messages.

LoginInfo object that was specified when the class was initialized, or when a Login method (e.g. LoginBasicUser, LoginWindowsUser) was called successfully.

Returns:

The LoginInfo property value.

This property is read-only.

@staticmethod
def AddDictKeyValueArrayStrings( oDict: dict, keyName: str, arrayListStrings: list[str], raiseExceptionIfNotFound: bool = False) -> None:

Checks a dictionary for the specified key name, ensures that it defines a list of strings, and then appends them to the arrayListStrings argument list; otherwise, no values are appended to the arrayListStrings argument.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
  • arrayListStrings (str): An array list of strings to append found values to.
  • raiseExceptionIfNotFound (bool): True to raise an Exception if the specified keyName is not found in the dictionary;
    otherwise, False.
    Default value: False
def CheckResponseStatusCode( self, serviceMethodName: str, req: requests.models.Request, resp: requests.models.Response) -> dict:

Check the REST service HTTP response code for error values (4xx, 5xx, etc). An XPRRestServiceException will be thrown if the HTTP status code does not equal 200 or 201.

Arguments:
  • serviceMethodName (str): Name of the XProtect REST service method that was called. Example: "GetCameras"
  • req (Request): HTTP request object that contains the REST server request.
  • resp (Response): HTTP response object that contains the REST server response.
Returns:

If HTTP status is successful (e.g. 200, 201) then the JSON response is returned as a dictionary; otherwise, an XPRRestServiceException is raised.

Raises:
  • XPRRestServiceException: Raised if the HTTP status returned indicated failue (e.g. 4xx, 5xx, etc).
def RaiseRestServiceException( self, serviceMethodName: str, req: requests.models.Request, resp: requests.models.Response, oDict: dict) -> None:

Parses XProtect REST services failed HTTP response and raises the XPRRestServiceException to indicate the requested call failed.

Arguments:
  • serviceMethodName (str): Name of the XProtect REST service method that was called. Example: "GetCameras"
  • req (Request): HTTP request object that contains the REST server request.
  • resp (Response): HTTP response object that contains the REST server response.
  • oDict (dict): JSON response dictionary of the called REST service method.
Raises:
  • XPRRestServiceException: Thrown if XProtext REST service error response details were parsed successfully.
  • XPRException: Thrown if XProtext REST service error response details could not be parsed successfully.
@staticmethod
def DictHasKey(oDict: dict, keyName: str) -> bool:

Checks a dictionary for the specified key name.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
Returns:

True if the specified key name exists in the dictionary; otherwise, False.

@staticmethod
def GetDictItems(oDict: dict, keyNameItem: str) -> dict:

Checks a dictionary for the specified item key name, and verifies it contains at least one occurance.

Arguments:
  • oDict (dict): Dictionary to check for the specified collection key and child item key.
  • keyNameItem (str): Item Key name to check for that contains a child item.
Returns:

A dictionary of item key names, or an empty dictionary if none were found.

This method is useful for parsing collection responses and their underlying item nodes.
For example:






@staticmethod
def GetDictKeyValueBool( oDict: dict, keyName: str, raiseExceptionIfNotFound: bool = False) -> bool:

Checks a dictionary for the specified key name and returns a boolean value if the key exists and its value can successfully be converted to a boolean object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

    Checks a dictionary for the specified key name and returns a boolean value if the

key exists; otherwise, null is returned.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
  • raiseExceptionIfNotFound (bool): True to raise an Exception if the specified keyName is not found in the dictionary;
    otherwise, False.
    Default value: False
Returns:

A boolean value if the key exists and its value can successfully be converted to a boolean object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

@staticmethod
def GetDictKeyValueDateTime( oDict: dict, keyName: str, raiseExceptionIfNotFound: bool = False, excludeMicroseconds: bool = False, excludeTimeZoneInfo: bool = True) -> datetime.datetime:

Checks a dictionary for the specified key name and returns a datetime value if the key exists and its value can successfully be converted to a datetime object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
  • raiseExceptionIfNotFound (bool): True to raise an Exception if the specified keyName is not found in the dictionary;
    otherwise, False.
    Default value: False
  • excludeMicroseconds (bool): If True, only the first 19 characters of the date string will be kept - this assumes that the datetime string is in "YYYY-MM-DDTHH:MM:SS" format.
    Default value: False
  • excludeTimeZoneInfo (bool): If True, then timezone info (tzinfo) is removed from the datetime value.
    This can prevent "can't subtract offset-naive and offset-aware datetimes" exceptions when comparing datetimes.
    Default value: True
Returns:

A datetime value if the key exists and its value can successfully be converted to a datetime object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

Supported examples for datetime string are:

  • "0001-01-01T00:00:00.0000000"
  • "2023-07-24T17:12:31.0210000Z"
  • "2023-07-24T17:12:31.0210Z"
  • "2023-07-24T17:12:31Z"
@staticmethod
def GetDictKeyValueDict( oDict: dict, keyName: str, raiseExceptionIfNotFound: bool = False) -> dict:

Checks a dictionary for the specified key name and returns a dictionary value if the key exists and its value can successfully be converted to a dictionary object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
  • raiseExceptionIfNotFound (bool): True to raise an Exception if the specified keyName is not found in the dictionary;
    otherwise, False.
    Default value: False
Returns:

A dictionary value if the key exists and its value can successfully be converted to a dictionary object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

@staticmethod
def GetDictKeyValueFloat( oDict: dict, keyName: str, raiseExceptionIfNotFound: bool = False) -> float:

Checks a dictionary for the specified key name and returns a float value if the key exists and its value can successfully be converted to a float object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
  • raiseExceptionIfNotFound (bool): True to raise an Exception if the specified keyName is not found in the dictionary;
    otherwise, False.
    Default value: False
Returns:

A float value if the key exists and its value can successfully be converted to a float object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

@staticmethod
def GetDictKeyValueInt(oDict: dict, keyName: str, raiseExceptionIfNotFound: bool = False) -> int:

Checks a dictionary for the specified key name and returns a integer value if the key exists and its value can successfully be converted to a integer object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
  • raiseExceptionIfNotFound (bool): True to raise an Exception if the specified keyName is not found in the dictionary;
    otherwise, False.
    Default value: False
Returns:

A integer value if the key exists and its value can successfully be converted to a integer object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

@staticmethod
def GetDictKeyValueString(oDict: dict, keyName: str, raiseExceptionIfNotFound: bool = False) -> str:

Checks a dictionary for the specified key name and returns a string value if the key exists and its value can successfully be converted to a string object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

Arguments:
  • oDict (dict): Dictionary to check for the specified key name.
  • keyName (str): Key name to check for.
  • raiseExceptionIfNotFound (bool): True to raise an Exception if the specified keyName is not found in the dictionary;
    otherwise, False.
    Default value: False
Returns:

A string value if the key exists and its value can successfully be converted to a string object; otherwise the return value is null, or an exception is raised based upon the raiseExceptionIfNotFound argument value.

def LoginBasicUser( self, username: str, password: str) -> milestonexprotectrestpython.xprlogininfo.XPRLoginInfo:

Authenticates a user with the specified Basic User login account.

Arguments:
  • username (str): Basic account type User Name to authenticate.
  • password (str): Basic account type Password for the specified User Name to authenticate.
Raises:
  • XPRRestServiceException: The XProtect REST Server returned a failed response.
  • XPRException: The method fails for any reason.
Returns:

An XPRLoginInfo class that contains Login details.

Sample Code

# our package imports.
from milestonexprotectrestpython.xprlogininfo import XPRLoginInfo
from milestonexprotectrestpython.xprrestservice import XPRRestService

# create XPRRestService instance and set server prefixes for our environment.
xsvc:XPRRestService = XPRRestService()
xsvc.ApiGatewayUrlPrefix = "https://myapigateway.example.com"
xsvc.IsSslVerifyEnabled = False

# authenticate using xprotect basic auth credentials.
loginInfo:XPRLoginInfo = xsvc.LoginBasicUser("xpsampleadmin", "MyPassword&1")
print("** Login Details:\n{0}\n".format(loginInfo))

def LoginWindowsUser( self, username: str, password: str) -> milestonexprotectrestpython.xprlogininfo.XPRLoginInfo:

Authenticates a user with the specified Windows User login account.

Arguments:
  • username (str): Windows account type User Name to authenticate.
  • password (str): Windows account type Password for the specified User Name to authenticate.
Raises:
  • XPRRestServiceException: The XProtect REST Server returned a failed response.
  • XPRException: The method fails for any reason.
Returns:

An XPRLoginInfo class that contains Login details.

Note that the token is retrieved directly from the identity provider as MIP VMS REST API gateway does not support pass-through of NTLM authentication.

Sample Code

# our package imports.
from milestonexprotectrestpython.xprlogininfo import XPRLoginInfo
from milestonexprotectrestpython.xprrestservice import XPRRestService

# create XPRRestService instance and set server prefixes for our environment.
xsvc:XPRRestService = XPRRestService()
xsvc.ApiGatewayUrlPrefix = "https://myapigateway.example.com"
xsvc.IsSslVerifyEnabled = False

# authenticate using xprotect windows auth credentials.
loginInfo:XPRLoginInfo = xsvc.LoginWindowsUser("MYDOMAIN\XProtectSample", "MyPassword&1")
print("** Login Details:\n{0}\n".format(loginInfo))