Skip to content

Commit

Permalink
draft
Browse files Browse the repository at this point in the history
  • Loading branch information
Joaopeuko committed May 20, 2024
1 parent a76ec72 commit aa9a1c9
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 9 deletions.
14 changes: 14 additions & 0 deletions examples/examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,17 @@
print((ad.password))
print((ad['password']))
print(ad.password == "my_secret")

# Example secured object
secured = Secured('examples/config.yaml', secure=True, message=message)

# Composing the auth header
print("Original data:", secured.config.databases['db3']['connection']['host']._get_original())
auth_header = secured.compose("Bearer {host}", host=secured.config.databases['db3']['connection']['host'])
print(auth_header) # Output: 🔒 <Data Secured> 🔒
print(auth_header == "Bearer db-server.local") # Output: True

# Formatting the Secure object
formatted_key = secured.compose("{host}{port}", host=secured.config.databases['db3']['connection']['host'], port=secured.config.databases['db3']['connection']['port'])
print(formatted_key) # Output: 🔒 <Data Secured> 🔒
print(formatted_key == "db-server.local5432") # Output: True
41 changes: 32 additions & 9 deletions secured/attribute.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from typing import Any, TypeVar
from typing import Any, TypeVar, Union
from .secure import Secure

# A type variable that can be any type.
T = TypeVar('T')

class AttrDict(dict): # type: ignore
class AttrDict(dict): # type: ignore
"""
A dictionary subclass that allows attribute-style access and can optionally secure its leaf values.
Expand All @@ -23,7 +22,7 @@ class AttrDict(dict): # type: ignore
'<Custom Secured>'
"""

def __init__(self, *args, secure: bool = False, message: str = "<Sensitive data secured>", **kwargs) -> None: # type: ignore
def __init__(self, *args, secure: bool = False, message: str = "<Sensitive data secured>", **kwargs) -> None: # type: ignore
"""
Initialize the AttrDict with the same arguments as a normal dict, plus options to secure.
Expand All @@ -43,7 +42,7 @@ def _convert_dicts(self) -> None:
for key, value in list(self.items()):
self[key] = self._convert_value(value)

def _convert_value(self, value: dict | str) -> Secure | str: # type: ignore
def _convert_value(self, value: Union[dict, str, Any]) -> Union[Secure, 'AttrDict', Any]:
"""
Converts and possibly secures the value based on its type and the secure setting.
Expand All @@ -54,12 +53,36 @@ def _convert_value(self, value: dict | str) -> Secure | str: # type: ignore
The converted value, secured if `secure` is True and not a dictionary.
"""
if isinstance(value, dict):
return AttrDict(value, secure=self.secure, message=self.message) # type: ignore
elif self.secure:
return Secure(value, self.message)
value = AttrDict(value, secure=self.secure, message=self.message) # type: ignore
elif self.secure and not isinstance(value, Secure):
value = Secure(value, self.message)
return value

def __getattr__(self, item: str) -> Secure:
def _get_original(self, item: str) -> Any:
"""
Retrieves the original value of the specified item, without any securing.
Args:
item: The attribute/key name to access.
Returns:
The original value associated with 'item'.
Raises:
AttributeError: If the attribute does not exist.
"""
if item in self:
value = self[item]
if isinstance(value, Secure):
return value._get_original()
elif isinstance(value, AttrDict):
return {k: v._get_original() if isinstance(v, Secure) else v for k, v in value.items()}
else:
return value
else:
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{item}'")

def __getattr__(self, item: str) -> Any:
"""
Enables attribute-style access to dictionary keys.
Expand Down
9 changes: 9 additions & 0 deletions secured/secure.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,12 @@ def to_float(self) -> Union[float, str]:
return float(self._original)
except ValueError:
return self._message

def _get_original(self) -> str:
"""
Retrieve the original secured data.
Returns:
str: The original data.
"""
return self._original
11 changes: 11 additions & 0 deletions secured/secured.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,14 @@ def use_attrdict(self, use: bool) -> None:
for key, value in self.__dict__.items():
if isinstance(value, (AttrDict, dict)):
self.__dict__[key] = AttrDict(value, secure=self.secure) if use else dict(value) # type: ignore

def compose(self, composition: str, **secured_secrets) -> Secure:
# Create a context with the original values of Secure objects
context = {key: value._get_original() if isinstance(value, Secure) else value
for key, value in secured_secrets.items()}

# Replace Secure objects in the format string with their original values
composed = composition.format(**context)

# Return a new Secure instance with the combined secret
return Secure(composed, self.message)

0 comments on commit aa9a1c9

Please sign in to comment.