mirror of
https://github.com/jazzband/django-fernet-encrypted-fields.git
synced 2026-03-16 22:40:27 +00:00
Merge 9c768e7e7c into 3b906d62c8
This commit is contained in:
commit
3f8b5400eb
6 changed files with 66 additions and 45 deletions
24
.github/workflows/lint-and-test.yml
vendored
24
.github/workflows/lint-and-test.yml
vendored
|
|
@ -10,18 +10,22 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install ruff black
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Lint with Ruff
|
||||
run: |
|
||||
ruff check .
|
||||
- name: "Set up Python"
|
||||
uses: actions/setup-python@v6
|
||||
|
||||
- name: Lint with Black
|
||||
run: |
|
||||
black --check .
|
||||
- name: "install Ruff"
|
||||
uses: astral-sh/ruff-action@v3
|
||||
with:
|
||||
version: ">=0.15,<0.16"
|
||||
# use args to avoid the default behavior of running ruff check automatically
|
||||
args: "--version"
|
||||
# ToDo: use pyrpoject.toml as version-file
|
||||
# version-file: "pyproject.toml"
|
||||
|
||||
- name: "Check formatting"
|
||||
run: ruff format --check --diff
|
||||
|
||||
test:
|
||||
strategy:
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -7,3 +7,6 @@ dist/
|
|||
.ruff_cache
|
||||
.venv
|
||||
.venv_django_*
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
|
|
|
|||
|
|
@ -48,3 +48,11 @@ repos:
|
|||
- id: pyupgrade
|
||||
name: pyupgrade
|
||||
args: [--py312-plus]
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.15.6
|
||||
hooks:
|
||||
# uncomment after linting initially passes
|
||||
# - id: ruff-check
|
||||
# args: [ --fix ]
|
||||
- id: ruff-format
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@ class EncryptedFieldMixin:
|
|||
def keys(self) -> list[bytes]:
|
||||
keys = []
|
||||
salt_keys = (
|
||||
settings.SALT_KEY
|
||||
if isinstance(settings.SALT_KEY, list)
|
||||
else [settings.SALT_KEY]
|
||||
settings.SALT_KEY if isinstance(settings.SALT_KEY, list) else [settings.SALT_KEY]
|
||||
)
|
||||
secret_keys = [settings.SECRET_KEY] + getattr(settings, "SECRET_KEY_FALLBACKS", list())
|
||||
for secret_key in secret_keys:
|
||||
|
|
@ -39,11 +37,7 @@ class EncryptedFieldMixin:
|
|||
iterations=100_000,
|
||||
backend=default_backend(),
|
||||
)
|
||||
keys.append(
|
||||
base64.urlsafe_b64encode(
|
||||
kdf.derive(secret_key.encode("utf-8"))
|
||||
)
|
||||
)
|
||||
keys.append(base64.urlsafe_b64encode(kdf.derive(secret_key.encode("utf-8"))))
|
||||
return keys
|
||||
|
||||
@cached_property
|
||||
|
|
@ -85,11 +79,7 @@ class EncryptedFieldMixin:
|
|||
return self.to_python(value)
|
||||
|
||||
def to_python(self, value: _TypeAny) -> _TypeAny:
|
||||
if (
|
||||
value is None
|
||||
or not isinstance(value, str)
|
||||
or hasattr(self, "_already_decrypted")
|
||||
):
|
||||
if value is None or not isinstance(value, str) or hasattr(self, "_already_decrypted"):
|
||||
return value
|
||||
try:
|
||||
value = self.f.decrypt(bytes(value, "utf-8")).decode("utf-8")
|
||||
|
|
@ -129,9 +119,7 @@ class EncryptedIntegerField(EncryptedFieldMixin, models.IntegerField):
|
|||
# they're based on values retrieved from `connection`.
|
||||
validators_ = [*self.default_validators, *self._validators]
|
||||
internal_type = models.IntegerField().get_internal_type()
|
||||
min_value, max_value = BaseDatabaseOperations.integer_field_ranges[
|
||||
internal_type
|
||||
]
|
||||
min_value, max_value = BaseDatabaseOperations.integer_field_ranges[internal_type]
|
||||
if min_value is not None and not any(
|
||||
(
|
||||
isinstance(validator, MinValueValidator)
|
||||
|
|
@ -203,11 +191,7 @@ class EncryptedJSONField(EncryptedFieldMixin, models.JSONField):
|
|||
return "JSONField"
|
||||
|
||||
def to_python(self, value: _TypeAny) -> _TypeAny:
|
||||
if (
|
||||
value is None
|
||||
or not isinstance(value, str)
|
||||
or hasattr(self, "_already_decrypted")
|
||||
):
|
||||
if value is None or not isinstance(value, str) or hasattr(self, "_already_decrypted"):
|
||||
return value
|
||||
try:
|
||||
value = self._decrypt_values(value=json.loads(value))
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ from .models import TestModel
|
|||
class FieldTest(TestCase):
|
||||
def get_db_value(self, field: str, model_id: int) -> None:
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(
|
||||
f"select {field} from package_test_testmodel where id = {model_id};"
|
||||
)
|
||||
cursor.execute(f"select {field} from package_test_testmodel where id = {model_id};")
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def test_char_field_encrypted(self) -> None:
|
||||
|
|
@ -258,14 +256,13 @@ class RotatedSaltTestCase(TestCase):
|
|||
|
||||
|
||||
class RotatedSecretKeyTestCase(TestCase):
|
||||
|
||||
@staticmethod
|
||||
def clear_cached_properties():
|
||||
# we have to clear the cached properties of EncryptedFieldMixin so we have the right encryption keys
|
||||
text_field = TestModel._meta.get_field('text')
|
||||
if hasattr(text_field, 'keys'):
|
||||
text_field = TestModel._meta.get_field("text")
|
||||
if hasattr(text_field, "keys"):
|
||||
del text_field.keys
|
||||
if hasattr(text_field, 'f'):
|
||||
if hasattr(text_field, "f"):
|
||||
del text_field.f
|
||||
|
||||
@classmethod
|
||||
|
|
@ -308,4 +305,3 @@ class RotatedSecretKeyTestCase(TestCase):
|
|||
assert old_record.text.endswith("=")
|
||||
# assert that old record cannot be decrypted now
|
||||
assert old_record.text != plaintext
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,38 @@
|
|||
##################
|
||||
[tool.ruff]
|
||||
fix = true
|
||||
lint.fixable = ["ALL"]
|
||||
lint.ignore = ["A003", "COM812", "D", "DJ008", "ERA001", "ISC001", "PLC2401", "PLC2403", "PT011", "RUF001", "S101", "S105", "S608", "SIM103", "TC001", "TC002", "TC003", "UP040"]
|
||||
lint.select = ["ALL"]
|
||||
lint.unfixable = ["ERA001", "F401"]
|
||||
include = ["encrypted_fields/*.py", "package_test/*.py"]
|
||||
target-version = "py312"
|
||||
extend-include = ["package_test/**/*.py"]
|
||||
target-version = "py310"
|
||||
line-length = 100
|
||||
|
||||
[tool.ruff.lint]
|
||||
fixable = ["ALL"]
|
||||
extend-ignore = [
|
||||
"RUF012",
|
||||
"A003",
|
||||
"COM812",
|
||||
"D",
|
||||
"DJ008",
|
||||
"ERA001",
|
||||
"ISC001",
|
||||
"PLC2401",
|
||||
"PLC2403",
|
||||
"PT011",
|
||||
"RUF001",
|
||||
"S101",
|
||||
"S105",
|
||||
"S608",
|
||||
"SIM103",
|
||||
"TC001",
|
||||
"TC002",
|
||||
"TC003",
|
||||
"UP040"
|
||||
]
|
||||
select = ["ALL"]
|
||||
unfixable = [
|
||||
"ERA001",
|
||||
"F401"
|
||||
]
|
||||
|
||||
##################
|
||||
# mypy
|
||||
|
|
|
|||
Loading…
Reference in a new issue