Source code for scholar_flux.security.utils

# /security/utils.py
"""The scholar_flux.security.utils module defines the SecretUtils class that implements the basic set of tools for both
masking and unmasking text, and identifying if a field is masked.

This class uses the pydantic.SecretStr class to mask and unmask fields and can be further extended to encrypt and
decrypt text as needed before and after conversion to a secret string, respectively.

"""

from typing import Any, Optional, overload, MutableMapping, TypeVar
from typing_extensions import TypeGuard
from pydantic import SecretStr


K = TypeVar("K", bound=object)


[docs] class SecretUtils: """Helper utility for both masking and unmasking strings. Class methods are defined so that they can be used directly or implemented as a mixin so that subclasses can implement the class methods directly. """ @classmethod @overload def mask_secret(cls, obj: None, convert_object: bool = True) -> None: """The mask_secret utility will only return None if the input is None.""" ... @classmethod @overload def mask_secret(cls, obj: Any, convert_object: bool = True) -> SecretStr: """The mask_secret method will return a secret string if the provided value is not None.""" ...
[docs] @classmethod def mask_secret(cls, obj: Any, convert_object: bool = True) -> Optional[SecretStr]: """Helper method masking variables into secret strings: Args: obj (Any | SecretStr): An object to attempt to unmask if it is a secret string convert_object (bool): Determines whether the object is converted into a string prior to masking. Objects are converted into strings by default. Returns: obj (SecretStr): A SecretStr representation of the original object Examples: >>> from pydantic import SecretStr >>> from scholar_flux.security import SecretUtils >>> string = 'a secret' >>> secret_string = SecretUtils.mask_secret(string) >>> isinstance(secret_string, SecretStr) is True # OUTPUT: True >>> no_string = None >>> non_secret = SecretUtils.mask_secret(no_string) >>> non_secret is None # OUTPUT: True ## Note that the original type is preserved when `convert_object=False` >>> not_a_string = ['a', 'secret', 'list'] >>> secretly_not_a_string = SecretUtils.mask_secret(not_a_string, convert_object=False) >>> isinstance(secretly_not_a_string, SecretStr) is True # OUTPUT: True ## Undoing the transformation: the original object is returned >>> SecretUtils.unmask_secret(secretly_not_a_string) is not_a_string # OUTPUT: True """ if cls.is_secret(obj) or obj is None: return obj # Convert by default if not explicitly selected return SecretStr(str(obj) if convert_object else obj)
[docs] @classmethod def unmask_secret(cls, obj: Any) -> Any: """Helper method for unmasking a variable from a SecretStr into its native type if a secret string. Args: obj (Any | SecretStr): An object to attempt to unmask if it is a secret string. Returns: obj (Any): The object's original type before being converted into a secret string. Examples: >>> from scholar_flux.security import SecretUtils >>> from pydantic import SecretStr >>> string = 'a secret' >>> secret_string = SecretUtils.mask_secret(string) >>> isinstance(secret_string, SecretStr) is True # OUTPUT: True >>> SecretUtils.unmask_secret(secret_string) == string # OUTPUT: True >>> SecretUtils.unmask_secret(None) is None # OUTPUT: True """ return obj.get_secret_value() if cls.is_secret(obj) else obj
[docs] @classmethod def unmask_parameters(cls, data: MutableMapping[K, Any]) -> dict[K, Any]: """Helper method for unmasking dictionary parameters from secret strings into their native types. Args: data (MutableMapping[K, Any]): An dictionary containing value parameters to unmask. Returns: dict[K, Any]: A new dictionary with identical keys and subsequently unmasked values, if masked. Examples: >>> from scholar_flux.security import SecretUtils >>> from pydantic import SecretStr >>> values_dict = {"a": SecretStr("one"), "b": "two", "c": 3, "d": SecretStr("four")} >>> expected = {"a": "one", "b": "two", "c": 3, "d": "four"} >>> unmasked_values_dict = SecretUtils.unmask_parameters(values_dict) >>> isinstance(values_dict, dict) is True # OUTPUT: True >>> SecretUtils.unmask_parameters(values_dict) == expected # OUTPUT: True """ return {key: cls.unmask_secret(value) for key, value in data.items()}
[docs] @classmethod def is_secret(cls, obj: Any) -> TypeGuard[SecretStr]: """Utility class method used to verify whether the current variable is a secret string. This method abstracts the implementation details into a single method to aid further extensibility. Args: obj (Any): The object to check Returns: TypeGuard[SecretStr]: True if the object is a SecretStr, False otherwise """ return isinstance(obj, SecretStr)
__all__ = ["SecretUtils"]