Commit ed921fcb authored by Guy Willett's avatar Guy Willett
Browse files

Add test for max_len 255.

parent dce4afe4
......@@ -4,24 +4,25 @@ stages:
- release
black_formatting:
image: python:3.7-slim-stretch
image: python:3.9-slim-stretch
stage: format
before_script:
- pip install black
- pip install black==22.1.0
script:
# use black on the code
# '--check' returns error code 1, if something needs formatting
- black --version
- black . --check --exclude '\.venv/|\.local/|\.cache/|\.git/|migrations/'
allow_failure: false
code_test:
allow_failure: true
code_test_pg11:
stage: test
image: themattrix/tox
image: fkrull/multi-python:latest
services:
- postgres:10-alpine
- postgres:11-alpine
variables:
POSTGRES_DB: ci
POSTGRES_USER: postgres
......@@ -30,11 +31,11 @@ code_test:
script:
- tox
code_test_pg11:
code_test_pg12:
stage: test
image: themattrix/tox
image: fkrull/multi-python:latest
services:
- postgres:11-alpine
- postgres:12-alpine
variables:
POSTGRES_DB: ci
POSTGRES_USER: postgres
......@@ -45,7 +46,7 @@ code_test_pg11:
pypi_release:
stage: release
image: python:3.7-slim-stretch
image: python:3.9-slim-stretch
script:
- pip install twine
- python setup.py sdist
......
......@@ -155,7 +155,7 @@ See the `encrypted_fields_test` app for an example.
Be sure to keep all old encryption keys in the list until you are certain all objects have rotated to the new key.
## Compatability
`django-searchable-encrypted-fields` is tested with Django(2.1, 2.2, 3.0, 3.1) on Python(3.6, 3.7, 3.8) using SQLite and PostgreSQL (10 and 11).
`django-searchable-encrypted-fields` is tested with Django(3.2, 4.0, 4.1) on Python(3.8, 3.9) using SQLite and PostgreSQL (11 and 12).
Test coverage is at 96%.
......
......@@ -4,6 +4,7 @@ import datetime
import django.contrib.auth.models
import django.contrib.auth.validators
import django.core.validators
from django.conf import settings
from django.db import migrations, models
import django.utils.timezone
import encrypted_fields.fields
......@@ -157,6 +158,20 @@ class Migration(migrations.Migration):
('search', encrypted_fields.fields.SearchField(blank=True, db_index=True, encrypted_field_name='value', hash_key='abc123', max_length=66, null=True)),
],
),
migrations.CreateModel(
name='SearchCharBigMaxLen',
fields=[
('id',
models.AutoField(auto_created=True, primary_key=True, serialize=False,
verbose_name='ID')),
('value', encrypted_fields.fields.EncryptedCharField(max_length=255)),
('search',
encrypted_fields.fields.SearchField(blank=True, db_index=True,
encrypted_field_name='value',
hash_key='abc123', max_length=66,
null=True)),
],
),
migrations.CreateModel(
name='SearchDate',
fields=[
......@@ -237,4 +252,30 @@ class Migration(migrations.Migration):
('search', encrypted_fields.fields.SearchField(blank=True, db_index=True, encrypted_field_name='value', hash_key='abc123', max_length=66, null=True)),
],
),
migrations.CreateModel(
name='Profile',
fields=[
('id',
models.AutoField(auto_created=True, primary_key=True, serialize=False,
verbose_name='ID')),
('foo', models.CharField(blank=True, default='', max_length=255)),
('user',
models.OneToOneField(on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='EncryptedProfile',
fields=[
('id',
models.AutoField(auto_created=True, primary_key=True, serialize=False,
verbose_name='ID')),
('enc_foo',
encrypted_fields.fields.EncryptedCharField(blank=True, default='',
max_length=255)),
('user',
models.OneToOneField(on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL)),
],
),
]
......@@ -45,6 +45,11 @@ class SearchChar(models.Model):
search = fields.SearchField(hash_key="abc123", encrypted_field_name="value")
class SearchCharBigMaxLen(models.Model):
value = fields.EncryptedCharField(max_length=255)
search = fields.SearchField(hash_key="abc123", encrypted_field_name="value")
class SearchEmail(models.Model):
value = fields.EncryptedEmailField()
search = fields.SearchField(hash_key="abc123", encrypted_field_name="value")
......@@ -209,15 +214,22 @@ class User(AbstractUser):
username_validator = UnicodeUsernameValidator()
_username = fields.EncryptedCharField(
max_length=150,
validators=[username_validator],
max_length=150, validators=[username_validator],
)
username = fields.SearchField(
hash_key="abc123",
encrypted_field_name="_username",
unique=True,
error_messages={
"unique": "Custom error message for already exists.",
},
error_messages={"unique": "Custom error message for already exists.",},
)
USERNAME_FIELD = "username"
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
foo = models.CharField(max_length=255, default="", blank=True)
class EncryptedProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
enc_foo = fields.EncryptedCharField(max_length=255, default="", blank=True)
......@@ -25,6 +25,8 @@ SECRET_KEY = "#jxsm+ra21tg7v_fhw^z!tw^w*%7t8vt=h1m9$4f-f#@^*ukno"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
ALLOWED_HOSTS = []
......
......@@ -92,6 +92,13 @@ def test_is_hashed_already(value, result):
[
(models.SearchText, ["foo", "bar"]),
(models.SearchChar, ["one", "two"]),
(
models.SearchCharBigMaxLen,
[
"12345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyuiop",
"22345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyuiopdiff",
],
),
(models.SearchEmail, ["a@example.com", "b@example.com"]),
(models.SearchInt, [1, 2]),
(models.SearchDate, [DATE1, DATE2]),
......@@ -189,6 +196,11 @@ def test_validation():
search="12345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyuiop"
)
m.full_clean(exclude=["value"])
# SearchField has max_len of 66, this should pass despite this (max_len=255)
m = models.SearchCharBigMaxLen( # max_len=255
search="12345678901234567890123456789012345678901234567890123456789012345678901234567890qwertyuiop"
)
m.full_clean(exclude=["value"])
class TestFormField:
......@@ -333,3 +345,47 @@ class TestCustomUserModel:
)
assert response.status_code == 302
assert response.url == "/admin/"
class TestUserProfile:
def test_authentication(self):
user = User.objects.create_user(username="foo", password="123Frsdsdsd9tryyrh")
profile = models.Profile(user=user, foo="foo").save()
c = Client()
assert c.login(username="foo", password="fake") is False
assert c.login(username="foobar", password="fake") is False
assert c.login(username="foo", password="123Frsdsdsd9tryyrh") is True
def test_login_view(self):
user = User.objects.create_user(username="foo", password="123Frsdsdsd9tryyrh")
profile = models.Profile(user=user, foo="foo").save()
c = Client()
response = c.post(
"/accounts/login/", {"username": "foo", "password": "123Frsdsdsd9tryyrh"}
)
assert response.status_code == 302 # redirects to "profile" by default
user.refresh_from_db()
assert user.profile.foo == "foo"
assert user.username == "foo"
class TestUserEncryptedProfile:
def test_authentication(self):
user = User.objects.create_user(username="foo", password="123Frsdsdsd9tryyrh")
profile = models.EncryptedProfile(user=user, enc_foo="encfoo").save()
c = Client()
assert c.login(username="foo", password="fake") is False
assert c.login(username="foobar", password="fake") is False
assert c.login(username="foo", password="123Frsdsdsd9tryyrh") is True
def test_login_view(self):
user = User.objects.create_user(username="foo", password="123Frsdsdsd9tryyrh")
profile = models.EncryptedProfile(user=user, enc_foo="encfoo").save()
c = Client()
response = c.post(
"/accounts/login/", {"username": "foo", "password": "123Frsdsdsd9tryyrh"}
)
assert response.status_code == 302 # redirects to "profile" by default
user.refresh_from_db()
assert user.encryptedprofile.enc_foo == "encfoo"
assert user.username == "foo"
Django>=2.1
psycopg2==2.7.6.1
Django>=3.2
psycopg2==2.8.5
pycryptodome>=3.7.0
pytz==2018.7
pytz==2022.2.1
pytest==3.10.1 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.2 # https://github.com/Frozenball/pytest-sugar
pytest-django==3.4.4 # https://github.com/pytest-dev/pytest-django
coverage==4.5.2 # https://github.com/nedbat/coveragepy
django-coverage-plugin==1.6.0 # https://github.com/nedbat/django_coverage_plugin
tox==3.7.0
black==20.8b1
djangorestframework==3.11.1
\ No newline at end of file
black==22.1.0
djangorestframework==3.12.4
......@@ -4,7 +4,7 @@ from setuptools import setup
setup(
name="django-searchable-encrypted-fields",
version="0.1.9",
version="0.2.0",
license="MIT",
description="Django model fields encrypted using Pycryptodome AES-256 GCM.",
long_description=open("README.md").read(),
......@@ -15,17 +15,15 @@ setup(
maintainer_email="<guy@chamsoft.co>",
url="https://gitlab.com/guywillett/django-searchable-encrypted-fields",
packages=["encrypted_fields"],
install_requires=["Django>=2.1", "pycryptodome>=3.7.0"],
install_requires=["Django>=3.2", "pycryptodome>=3.7.0"],
classifiers=[
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Framework :: Django",
"Framework :: Django :: 2.1",
"Framework :: Django :: 2.2",
"Framework :: Django :: 3.0",
"Framework :: Django :: 3.1",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.1",
],
)
[tox]
envlist = {py36,py37,py38}-{django21, django22, django30, django31}-{sqlite,pg}
envlist = {py38,py39}-{django32, django40, django41}-{sqlite,pg}
[testenv]
......@@ -8,11 +8,11 @@ deps =
pytest==3.10.1
pytest-sugar==0.9.2
pytest-django==3.4.4
djangorestframework==3.11.1
django21: Django>=2.1,<2.2
django22: Django>=2.2,<2.3
django30: Django>=3.0,<3.1
django31: Django>=3.1,<3.2
djangorestframework==3.12.4
pytz==2022.2.1
django32: Django>=3.2,<3.3
django40: Django>=4.0,<4.1
django41: Django>=4.1,<4.2
pg: psycopg2-binary==2.8.5
setenv =
......@@ -24,4 +24,4 @@ commands =
python manage.py delete_test_migrations
python manage.py showmigrations
python manage.py makemigrations
pytest --migrations
\ No newline at end of file
pytest --migrations
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment