From ebb730e2c5e1ae9bd2921fdfa4c1e58ca82ba22d Mon Sep 17 00:00:00 2001 From: Josh Thomas Date: Mon, 13 May 2024 12:26:35 -0500 Subject: [PATCH] allow setting token in user settings (#4) --- src/django_opfield/conf.py | 11 ++++++++++- src/django_opfield/fields.py | 14 +++++++------- tests/test_fields.py | 5 +++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/django_opfield/conf.py b/src/django_opfield/conf.py index e67258d..4963ca2 100644 --- a/src/django_opfield/conf.py +++ b/src/django_opfield/conf.py @@ -7,6 +7,7 @@ from typing import Any from django.conf import settings +from django.core.exceptions import ImproperlyConfigured OPFIELD_SETTINGS_NAME = "DJANGO_OPFIELD" @@ -38,7 +39,15 @@ def OP_CLI_PATH(self) -> Path: @property def OP_SERVICE_ACCOUNT_TOKEN(self) -> str: - return os.environ.get("OP_SERVICE_ACCOUNT_TOKEN", "") + if user_token := self._get_user_settings("OP_SERVICE_ACCOUNT_TOKEN"): + token = user_token + else: + token = os.environ.get("OP_SERVICE_ACCOUNT_TOKEN", None) + + if not token: + raise ImproperlyConfigured("OP_SERVICE_ACCOUNT_TOKEN is not set") + + return token app_settings = AppSettings() diff --git a/src/django_opfield/fields.py b/src/django_opfield/fields.py index 3a9ec07..2adda62 100644 --- a/src/django_opfield/fields.py +++ b/src/django_opfield/fields.py @@ -40,14 +40,14 @@ def contribute_to_class( super().contribute_to_class(cls, name, private_only) def get_secret(self: models.Model) -> str | None: - if not app_settings.OP_SERVICE_ACCOUNT_TOKEN: - raise ValueError("OP_SERVICE_ACCOUNT_TOKEN is not set") - try: - op = app_settings.OP_CLI_PATH - except ImportError as err: - raise err + op = app_settings.OP_CLI_PATH op_uri = getattr(self, name) - result = subprocess.run([op, "read", op_uri], capture_output=True) + op_token = app_settings.OP_SERVICE_ACCOUNT_TOKEN + result = subprocess.run( + [op, "read", op_uri], + capture_output=True, + env={"OP_SERVICE_ACCOUNT_TOKEN": op_token}, + ) if result.returncode != 0: raise ValueError( f"Could not read secret from 1Password: {result.stderr.decode('utf-8')}" diff --git a/tests/test_fields.py b/tests/test_fields.py index 41d299d..570b935 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -5,6 +5,7 @@ from unittest.mock import patch import pytest +from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ValidationError from django.db import models @@ -88,7 +89,7 @@ def test_get_secret(mock_run): secret = model.op_uri_secret mock_run.assert_called_once_with( - [ANY, "read", "op://vault/item/field"], capture_output=True + [ANY, "read", "op://vault/item/field"], capture_output=True, env=ANY ) assert secret == "secret value" @@ -100,7 +101,7 @@ def test_get_secret_no_token(mock_run): model = TestModel(op_uri="op://vault/item/field") - with pytest.raises(ValueError) as exc_info: + with pytest.raises(ImproperlyConfigured) as exc_info: _ = model.op_uri_secret assert "OP_SERVICE_ACCOUNT_TOKEN is not set" in str(exc_info.value)