feat(system): add secrets module#41
Conversation
remove runUpdateQuery from db module
Reviewer's GuideIntroduces a new secrets management system API (Python-level wrappers and Java interop types), adds a generic ContextManager base class for context-managed resources, wires in stubs for type checking, and removes the deprecated db.runUpdateQuery API from both implementation and stubs. Sequence diagram for system.secrets decrypt and readSecretValuesequenceDiagram
participant Caller
participant system_secrets
participant Plaintext
participant PyPlaintext
Caller->>system_secrets: decrypt(json)
system_secrets->>Plaintext: fromString(json)
Plaintext-->>system_secrets: Plaintext
system_secrets->>PyPlaintext: __init__(Plaintext)
PyPlaintext-->>Caller: PyPlaintext
Caller->>system_secrets: readSecretValue(providerName, secretName)
system_secrets->>Plaintext: __init__()
Plaintext-->>system_secrets: Plaintext
system_secrets->>PyPlaintext: __init__(Plaintext)
PyPlaintext-->>Caller: PyPlaintext
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- PyPlaintext currently ignores the passed Plaintext instance and leaves clear/getSecretsAsBytes/getSecretsAsString unimplemented; consider storing the Plaintext on the instance and delegating these methods to it so that usage of the secrets API behaves as expected.
- The new ContextManager.enter/exit implementations only print and do not manage or return a context object; you may want to either remove the side-effect logging or have enter return self (and exit perform cleanup) so it behaves like a standard context manager.
- In Plaintext.fromBytes and Plaintext.fromString, the parameter names
bytesandstrshadow built-in names; renaming these (e.g., todataorvalue) would avoid potential confusion and accidental misuse.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- PyPlaintext currently ignores the passed Plaintext instance and leaves clear/getSecretsAsBytes/getSecretsAsString unimplemented; consider storing the Plaintext on the instance and delegating these methods to it so that usage of the secrets API behaves as expected.
- The new ContextManager.__enter__/__exit__ implementations only print and do not manage or return a context object; you may want to either remove the side-effect logging or have __enter__ return self (and __exit__ perform cleanup) so it behaves like a standard context manager.
- In Plaintext.fromBytes and Plaintext.fromString, the parameter names `bytes` and `str` shadow built-in names; renaming these (e.g., to `data` or `value`) would avoid potential confusion and accidental misuse.
## Individual Comments
### Comment 1
<location path="src/com/inductiveautomation/ignition/common/script/abc/__init__.py" line_range="286-295" />
<code_context>
pass
+
+
+class ContextManager(PyObject):
+ def __init__(self):
+ # type: () -> None
+ super(ContextManager, self).__init__()
+
+ def __enter__(self):
+ # type: () -> None
+ print("Enter")
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ # type: (object, object, object) -> None
+ print("Exit")
</code_context>
<issue_to_address>
**issue (bug_risk):** ContextManager’s __enter__/__exit__ behavior is surprising for a reusable base class.
`__enter__` currently returns `None` and both methods print on entry/exit. For a reusable base class, `with ContextManager() as cm:` (or via subclasses like `PyPlaintext`) will bind `cm` to `None`, which is likely to cause subtle bugs, and the prints will create noisy logs. Prefer returning `self` from `__enter__` and removing these prints, or make this an abstract shell that subclasses override.
</issue_to_address>
### Comment 2
<location path="src/system/secrets.py" line_range="81-90" />
<code_context>
+ ]
+
+
+def getSecrets(providerName):
+ # type: (Union[str, unicode]) -> List[SecretMeta]
+ """Returns a list of objects representing all secrets available for
+ the named Secret Provider.
+
+ Each list entry includes the name of the secret.
+
+ Args:
+ providerName: The name of the Secret Provider to fetch secrets
+ from.
+
+ Returns:
+ A list of SecretMeta instances that represent all secret names.
+ """
+ print(providerName)
+ return [SecretMeta("SecretName")]
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Printing providerName in getSecrets introduces unexpected side effects.
Having `getSecrets` print `providerName` forces all callers to get unexpected console output, which is unusual for an accessor and may break scripts that rely on clean stdout. If this is only for debugging, remove the `print` or replace it with a proper, configurable logging mechanism.
Suggested implementation:
```python
def getSecrets(providerName):
# type: (Union[str, unicode]) -> List[SecretMeta]
"""Returns a list of objects representing all secrets available for
the named Secret Provider.
Each list entry includes the name of the secret.
Args:
providerName: The name of the Secret Provider to fetch secrets
from.
Returns:
A list of SecretMeta instances that represent all secret names.
"""
return [SecretMeta("SecretName")]
```
```python
__all__ = [
"decrypt",
"encrypt",
"getProviders",
"getSecrets",
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| class ContextManager(PyObject): | ||
| def __init__(self): | ||
| # type: () -> None | ||
| super(ContextManager, self).__init__() | ||
|
|
||
| def __enter__(self): | ||
| # type: () -> None | ||
| print("Enter") | ||
|
|
||
| def __exit__(self, exc_type, exc_val, exc_tb): |
There was a problem hiding this comment.
issue (bug_risk): ContextManager’s enter/exit behavior is surprising for a reusable base class.
__enter__ currently returns None and both methods print on entry/exit. For a reusable base class, with ContextManager() as cm: (or via subclasses like PyPlaintext) will bind cm to None, which is likely to cause subtle bugs, and the prints will create noisy logs. Prefer returning self from __enter__ and removing these prints, or make this an abstract shell that subclasses override.
| def getSecrets(providerName): | ||
| # type: (Union[str, unicode]) -> List[SecretMeta] | ||
| """Returns a list of objects representing all secrets available for | ||
| the named Secret Provider. | ||
|
|
||
| Each list entry includes the name of the secret. | ||
|
|
||
| Args: | ||
| providerName: The name of the Secret Provider to fetch secrets | ||
| from. |
There was a problem hiding this comment.
suggestion (bug_risk): Printing providerName in getSecrets introduces unexpected side effects.
Having getSecrets print providerName forces all callers to get unexpected console output, which is unusual for an accessor and may break scripts that rely on clean stdout. If this is only for debugging, remove the print or replace it with a proper, configurable logging mechanism.
Suggested implementation:
def getSecrets(providerName):
# type: (Union[str, unicode]) -> List[SecretMeta]
"""Returns a list of objects representing all secrets available for
the named Secret Provider.
Each list entry includes the name of the secret.
Args:
providerName: The name of the Secret Provider to fetch secrets
from.
Returns:
A list of SecretMeta instances that represent all secret names.
"""
return [SecretMeta("SecretName")]__all__ = [
"decrypt",
"encrypt",
"getProviders",
"getSecrets",
remove runUpdateQuery from db module
Summary by Sourcery
Introduce a new system secrets API and supporting types while removing an obsolete database update helper.
New Features:
Enhancements: