110 lines
3.2 KiB
Python
110 lines
3.2 KiB
Python
"""
|
||
# Summary
|
||
|
||
Local filesystem–based credential persistence for Mail Intake.
|
||
|
||
This module provides a file-backed implementation of the
|
||
`CredentialStore` abstraction using Python's `pickle` module.
|
||
|
||
The `pickle`-based credential store is intended for local development,
|
||
single-node deployments, and controlled environments where credentials
|
||
do not need to be shared across processes or machines.
|
||
|
||
Due to the security and portability risks associated with `pickle`-based
|
||
serialization, this implementation is not suitable for distributed or
|
||
untrusted environments.
|
||
"""
|
||
|
||
import pickle
|
||
from typing import Optional, TypeVar
|
||
|
||
from mail_intake.credentials.store import CredentialStore
|
||
|
||
T = TypeVar("T")
|
||
|
||
|
||
class PickleCredentialStore(CredentialStore[T]):
|
||
"""
|
||
Filesystem-backed credential store using pickle serialization.
|
||
|
||
This store persists credentials as a pickled object on the local
|
||
filesystem. It is a simple implementation intended primarily for
|
||
development, testing, and single-process execution contexts.
|
||
|
||
Notes:
|
||
**Guarantees:**
|
||
|
||
- Stores credentials on the local filesystem.
|
||
- Uses `pickle` for serialization and deserialization.
|
||
- Does not provide encryption, locking, or concurrency guarantees.
|
||
|
||
**Constraints:**
|
||
|
||
- Credential lifecycle management, validation, and refresh logic are
|
||
explicitly out of scope for this class.
|
||
"""
|
||
|
||
def __init__(self, path: str):
|
||
"""
|
||
Initialize a pickle-backed credential store.
|
||
|
||
Args:
|
||
path (str):
|
||
Filesystem path where credentials will be stored.
|
||
The file will be created or overwritten as needed.
|
||
"""
|
||
self.path = path
|
||
|
||
def load(self) -> Optional[T]:
|
||
"""
|
||
Load credentials from the local filesystem.
|
||
|
||
Returns:
|
||
Optional[T]:
|
||
An instance of type `T` if credentials are present and
|
||
successfully deserialized; otherwise `None`.
|
||
|
||
Notes:
|
||
**Guarantees:**
|
||
|
||
- If the credential file does not exist or cannot be successfully
|
||
deserialized, this method returns `None`.
|
||
- The store does not attempt to validate or interpret the
|
||
returned credentials.
|
||
"""
|
||
try:
|
||
with open(self.path, "rb") as fh:
|
||
return pickle.load(fh)
|
||
except Exception:
|
||
return None
|
||
|
||
def save(self, credentials: T) -> None:
|
||
"""
|
||
Persist credentials to the local filesystem.
|
||
|
||
Args:
|
||
credentials (T):
|
||
The credential object to persist.
|
||
|
||
Notes:
|
||
**Responsibilities:**
|
||
|
||
- Any previously stored credentials at the configured path are overwritten
|
||
"""
|
||
with open(self.path, "wb") as fh:
|
||
pickle.dump(credentials, fh)
|
||
|
||
def clear(self) -> None:
|
||
"""
|
||
Remove persisted credentials from the local filesystem.
|
||
|
||
Notes:
|
||
**Lifecycle:**
|
||
|
||
- This method deletes the credential file if it exists and should be treated as an idempotent operation
|
||
"""
|
||
import os
|
||
|
||
if os.path.exists(self.path):
|
||
os.remove(self.path)
|