diff --git a/cryptlex/lexfloatclient/lexfloatclient.py b/cryptlex/lexfloatclient/lexfloatclient.py index d30603e..6c451cc 100644 --- a/cryptlex/lexfloatclient/lexfloatclient.py +++ b/cryptlex/lexfloatclient/lexfloatclient.py @@ -1,11 +1,32 @@ import ctypes import json +import functools +import warnings from cryptlex.lexfloatclient import lexfloatclient_native as LexFloatClientNative from cryptlex.lexfloatclient.lexfloatstatus_codes import LexFloatStatusCodes from cryptlex.lexfloatclient.lexfloatclient_exception import LexFloatClientException callback_list = [] +def deprecated(alternative): + """This is a decorator which can be used to mark functions as deprecated. + It will result in a warning being emitted when the function is used. + + Args: + alternative (str): Name of the alternative function to use + """ + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + warnings.warn( + f"The function {func.__name__}() is deprecated. Use {alternative}() instead.", + category=DeprecationWarning, + stacklevel=2 + ) + return func(*args, **kwargs) + return wrapper + return decorator + class PermissionFlags: LF_USER = 10 LF_ALL_USERS = 11 @@ -23,6 +44,13 @@ def __init__(self, name, enabled, data): self.enabled = enabled self.data = data +class HostFeatureEntitlement(object): + def __init__(self, host_feature_entitlement_dict): + self.feature_name = host_feature_entitlement_dict.get("featureName") + self.feature_display_name = host_feature_entitlement_dict.get("featureDisplayName") + self.value = host_feature_entitlement_dict.get("value") + + class HostConfig(object): def __init__(self, max_offline_lease_duration): self.max_offline_lease_duration = max_offline_lease_duration @@ -176,6 +204,7 @@ def GetHostConfig(): raise LexFloatClientException(status) @staticmethod + @deprecated("GetHostLicenseEntitlementSetName") def GetHostProductVersionName(): """Gets the product version name. @@ -194,6 +223,7 @@ def GetHostProductVersionName(): return LexFloatClientNative.byte_to_string(buffer.value) @staticmethod + @deprecated("GetHostLicenseEntitlementSetDisplayName") def GetHostProductVersionDisplayName(): """Gets the product version display name. @@ -212,6 +242,7 @@ def GetHostProductVersionDisplayName(): return LexFloatClientNative.byte_to_string(buffer.value) @staticmethod + @deprecated("GetHostFeatureEntitlement") def GetHostProductVersionFeatureFlag(name): """Gets the product version feature flag. @@ -234,6 +265,93 @@ def GetHostProductVersionFeatureFlag(name): return HostProductVersionFeatureFlag(name, isEnabled, LexFloatClientNative.byte_to_string(buffer.value)) else: raise LexFloatClientException(status) + + @staticmethod + def GetHostLicenseEntitlementSetName(): + """Gets the name of the entitlement set associated with the LexFloatServer license. + + Raises: + LexFloatClientException + + Returns: + str: host license entitlement set name + """ + buffer_size = 256 + buffer = LexFloatClientNative.get_ctype_string_buffer(buffer_size) + status = LexFloatClientNative.GetHostLicenseEntitlementSetName(buffer, buffer_size) + if status != LexFloatStatusCodes.LF_OK: + raise LexFloatClientException(status) + return LexFloatClientNative.byte_to_string(buffer.value) + + @staticmethod + def GetHostLicenseEntitlementSetDisplayName(): + """Gets the display name of the entitlement set associated with the LexFloatServer license. + + Raises: + LexFloatClientException + + Returns: + str: host license entitlement set display name + """ + buffer_size = 256 + buffer = LexFloatClientNative.get_ctype_string_buffer(buffer_size) + status = LexFloatClientNative.GetHostLicenseEntitlementSetDisplayName(buffer, buffer_size) + if status != LexFloatStatusCodes.LF_OK: + raise LexFloatClientException(status) + return LexFloatClientNative.byte_to_string(buffer.value) + + @staticmethod + def GetHostFeatureEntitlements(): + """Gets the feature entitlements associated with the LexFloatServer license. + + Feature entitlements can be linked directly to a license (license feature entitlements) + or via entitlement sets. If a feature entitlement is defined in both, the value from + the license feature entitlement takes precedence, overriding the entitlement set value. + + Raises: + LexFloatClientException + + Returns: + HostFeatureEntitlements[]: list of host feature entitlements + """ + buffer_size = 4096 + buffer = LexFloatClientNative.get_ctype_string_buffer(buffer_size) + status = LexFloatClientNative.GetHostFeatureEntitlements(buffer, buffer_size) + if status == LexFloatStatusCodes.LF_OK: + host_feature_entitlements_json = LexFloatClientNative.byte_to_string(buffer.value) + if not host_feature_entitlements_json.strip(): + return [] + else: + host_feature_entitlements = json.loads(host_feature_entitlements_json) + host_feature_entitlements_list = [HostFeatureEntitlement(feature_detail) for feature_detail in host_feature_entitlements] + return host_feature_entitlements_list + else: + raise LexFloatClientException(status) + + @staticmethod + def GetHostFeatureEntitlement(feature_name): + """Gets the feature entitlement associated with the LexFloatServer license. + + Feature entitlements can be linked directly to a license (license feature entitlements) + or via entitlement sets. If a feature entitlement is defined in both, the value from + the license feature entitlement takes precedence, overriding the entitlement set value. + + Raises: + LexFloatClientException + + Returns: + HostFeatureEntitlement: host feature entitlement + """ + cstring_feature_name = LexFloatClientNative.get_ctype_string(feature_name) + buffer_size = 1024 + buffer = LexFloatClientNative.get_ctype_string_buffer(buffer_size) + status = LexFloatClientNative.GetHostFeatureEntitlement(cstring_feature_name, buffer, buffer_size) + if status == LexFloatStatusCodes.LF_OK: + host_feature_entitlement_json = LexFloatClientNative.byte_to_string(buffer.value) + host_feature_entitlement = json.loads(host_feature_entitlement_json) + return HostFeatureEntitlement(host_feature_entitlement) + else: + raise LexFloatClientException(status) @staticmethod def GetHostLicenseMetadata(key): diff --git a/cryptlex/lexfloatclient/lexfloatclient_exception.py b/cryptlex/lexfloatclient/lexfloatclient_exception.py index 4c15166..83c7931 100644 --- a/cryptlex/lexfloatclient/lexfloatclient_exception.py +++ b/cryptlex/lexfloatclient/lexfloatclient_exception.py @@ -80,4 +80,8 @@ def get_error_message(code): return 'Machine fingerprint has changed since activation.' if code == LexFloatStatusCodes.LF_E_PROXY_NOT_TRUSTED: return 'Request blocked due to untrusted proxy.' + if code == LexFloatStatusCodes.LF_E_ENTITLEMENT_SET_NOT_LINKED: + return 'No entitlement set is linked to the license.' + if code == LexFloatStatusCodes.LF_E_FEATURE_ENTITLEMENT_NOT_FOUND: + return 'The feature entitlement does not exist.' return 'Unknown error!' diff --git a/cryptlex/lexfloatclient/lexfloatclient_native.py b/cryptlex/lexfloatclient/lexfloatclient_native.py index 920c75e..4ffa915 100644 --- a/cryptlex/lexfloatclient/lexfloatclient_native.py +++ b/cryptlex/lexfloatclient/lexfloatclient_native.py @@ -155,6 +155,22 @@ def byte_to_string(input): GetHostConfig.argtypes = [STRTYPE, c_uint32] GetHostConfig.restype = c_int +GetHostLicenseEntitlementSetName = library.GetHostLicenseEntitlementSetName +GetHostLicenseEntitlementSetName.argtypes = [STRTYPE, c_uint32] +GetHostLicenseEntitlementSetName.restype = c_int + +GetHostLicenseEntitlementSetDisplayName = library.GetHostLicenseEntitlementSetDisplayName +GetHostLicenseEntitlementSetDisplayName.argtypes = [STRTYPE, c_uint32] +GetHostLicenseEntitlementSetDisplayName.restype = c_int + +GetHostFeatureEntitlements = library.GetHostFeatureEntitlementsInternal +GetHostFeatureEntitlements.argtypes = [STRTYPE, c_uint32] +GetHostFeatureEntitlements.restype = c_int + +GetHostFeatureEntitlement = library.GetHostFeatureEntitlementInternal +GetHostFeatureEntitlement.argtypes = [CSTRTYPE, STRTYPE, c_uint32] +GetHostFeatureEntitlement.restype = c_int + GetHostLicenseMetadata = library.GetHostLicenseMetadata GetHostLicenseMetadata.argtypes = [CSTRTYPE, STRTYPE, c_uint32] GetHostLicenseMetadata.restype = c_int diff --git a/cryptlex/lexfloatclient/lexfloatstatus_codes.py b/cryptlex/lexfloatclient/lexfloatstatus_codes.py index a30a4da..3f33b35 100644 --- a/cryptlex/lexfloatclient/lexfloatstatus_codes.py +++ b/cryptlex/lexfloatclient/lexfloatstatus_codes.py @@ -60,6 +60,10 @@ class LexFloatStatusCodes: LF_E_PROXY_NOT_TRUSTED = 67 + LF_E_ENTITLEMENT_SET_NOT_LINKED = 68 + + LF_E_FEATURE_ENTITLEMENT_NOT_FOUND = 69 + LF_E_CLIENT = 70 LF_E_SERVER = 71