add related model load tests
This commit is contained in:
@ -472,6 +472,7 @@ Available Model Fields (with required args - optional ones in docs):
|
||||
* `Decimal(scale, precision)`
|
||||
* `UUID()`
|
||||
* `EnumField` - by passing `choices` to any other Field type
|
||||
* `EncryptedString` - by passing `encrypt_secret` and `encrypt_backend`
|
||||
* `ForeignKey(to)`
|
||||
* `ManyToMany(to, through)`
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ Note that since this backend never decrypt the stored value it's only applicable
|
||||
|
||||
!!!note
|
||||
Note that provided `encrypt_secret` is first hashed itself and used as salt, so in order to
|
||||
compare to stored string you need to recreate this steps.
|
||||
compare to stored string you need to recreate this steps. The `order_by` will not work as encrypted strings are compared so you cannot reliably order by.
|
||||
|
||||
```python
|
||||
class Hash(ormar.Model):
|
||||
@ -101,7 +101,8 @@ Value is encrypted on way to database end decrypted on way out. Can be used on a
|
||||
as the returned value is parsed to corresponding python type.
|
||||
|
||||
!!!warning
|
||||
Note that in `FERNET` backend you loose `filtering` possibility altogether as part of the encrypted value is a timestamp
|
||||
Note that in `FERNET` backend you loose `filter`ing possibility altogether as part of the encrypted value is a timestamp.
|
||||
The same goes for `order_by` as encrypted strings are compared so you cannot reliably order by.
|
||||
|
||||
```python
|
||||
class Filter(ormar.Model):
|
||||
|
||||
@ -472,6 +472,7 @@ Available Model Fields (with required args - optional ones in docs):
|
||||
* `Decimal(scale, precision)`
|
||||
* `UUID()`
|
||||
* `EnumField` - by passing `choices` to any other Field type
|
||||
* `EncryptedString` - by passing `encrypt_secret` and `encrypt_backend`
|
||||
* `ForeignKey(to)`
|
||||
* `ManyToMany(to, through)`
|
||||
|
||||
|
||||
@ -144,7 +144,7 @@ class EncryptedString(types.TypeDecorator):
|
||||
self.type_: Any = type_
|
||||
|
||||
def __repr__(self) -> str: # pragma: nocover
|
||||
return f"TEXT()"
|
||||
return "TEXT()"
|
||||
|
||||
def load_dialect_impl(self, dialect: DefaultDialect) -> Any:
|
||||
return dialect.type_descriptor(types.TEXT())
|
||||
|
||||
@ -77,14 +77,6 @@ class Author(ormar.Model):
|
||||
)
|
||||
|
||||
|
||||
class Filter(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "filters"
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, **default_fernet)
|
||||
|
||||
|
||||
class Hash(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "hashes"
|
||||
@ -97,6 +89,24 @@ class Hash(ormar.Model):
|
||||
)
|
||||
|
||||
|
||||
class Filter(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "filters"
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100, **default_fernet)
|
||||
hash = ormar.ForeignKey(Hash)
|
||||
|
||||
|
||||
class Report(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "reports"
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
name: str = ormar.String(max_length=100)
|
||||
filters = ormar.ManyToMany(Filter)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def create_test_database():
|
||||
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||
@ -236,3 +246,24 @@ async def test_hash_filters_works():
|
||||
|
||||
with pytest.raises(NoMatch):
|
||||
await Filter.objects.get(name__icontains="test")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_related_model_fields_properly_decrypted():
|
||||
async with database:
|
||||
hash1 = await Hash(name="test1").save()
|
||||
report = await Report.objects.create(name="Report1")
|
||||
await report.filters.create(name="test1", hash=hash1)
|
||||
await report.filters.create(name="test2")
|
||||
|
||||
report2 = await Report.objects.select_related("filters").get()
|
||||
assert report2.filters[0].name == "test1"
|
||||
assert report2.filters[1].name == "test2"
|
||||
|
||||
secret = hashlib.sha256("udxc32".encode()).digest()
|
||||
secret = base64.urlsafe_b64encode(secret)
|
||||
hashed_test1 = hashlib.sha512(secret + "test1".encode()).hexdigest()
|
||||
|
||||
report2 = await Report.objects.select_related("filters__hash").get()
|
||||
assert report2.filters[0].name == "test1"
|
||||
assert report2.filters[0].hash.name == hashed_test1
|
||||
|
||||
Reference in New Issue
Block a user