From 728d506cbe48ce28d7b98bc8fab8fc8456c3406a Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 8 Mar 2017 17:27:00 +0100 Subject: [PATCH] change serialization format for attribute kind string, title and boolean (fixes #15607) --- src/authentic2/attribute_kinds.py | 6 ++- .../0017_modify_boolean_serialization.py | 60 ++++++++++++++++++++++ tests/test_api.py | 2 +- tests/test_auth_oidc.py | 8 +-- 4 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 src/authentic2/migrations/0017_modify_boolean_serialization.py diff --git a/src/authentic2/attribute_kinds.py b/src/authentic2/attribute_kinds.py index 6c76e56..9e37fde 100644 --- a/src/authentic2/attribute_kinds.py +++ b/src/authentic2/attribute_kinds.py @@ -45,6 +45,8 @@ DEFAULT_ATTRIBUTE_KINDS = [ 'label': _('boolean'), 'name': 'boolean', 'field_class': forms.BooleanField, + 'serialize': lambda x: str(int(bool(x))), + 'deserialize': lambda x: bool(int(x)), }, ] @@ -105,6 +107,6 @@ def get_form_field(kind, **kwargs): def get_kind(kind): d = get_attribute_kinds()[kind] d.setdefault('default', None) - d.setdefault('serialize', json.dumps) - d.setdefault('deserialize', json.loads) + d.setdefault('serialize', lambda x: x) + d.setdefault('deserialize', lambda x: x) return d diff --git a/src/authentic2/migrations/0017_modify_boolean_serialization.py b/src/authentic2/migrations/0017_modify_boolean_serialization.py new file mode 100644 index 0000000..0d455bf --- /dev/null +++ b/src/authentic2/migrations/0017_modify_boolean_serialization.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +import json + +from django.db import migrations + + +def clean_null(apps, schema_editor): + AttributeValue = apps.get_model('authentic2', 'AttributeValue') + AttributeValue.objects.filter(attribute__required=True, content='null').update(content='""') + AttributeValue.objects.filter(attribute__required=False, content='null').delete() + AttributeValue.objects.filter(attribute__required=False, content='""').delete() + + +def noop(apps, schema_editor): + pass + + +def modify_string_serialization(apps, schema_editor): + AttributeValue = apps.get_model('authentic2', 'AttributeValue') + for atv in AttributeValue.objects.filter(attribute__kind__in=['string', 'title']): + b = json.loads(atv.content) + assert isinstance(b, unicode) + atv.content = b + atv.save() + + +def reverse_modify_string_serialization(apps, schema_editor): + AttributeValue = apps.get_model('authentic2', 'AttributeValue') + for atv in AttributeValue.objects.filter(attribute__kind__in=['string', 'title']): + atv.content = json.dumps(atv.content) + atv.save() + + +def modify_boolean_serialization(apps, schema_editor): + AttributeValue = apps.get_model('authentic2', 'AttributeValue') + for atv in AttributeValue.objects.filter(attribute__kind='boolean'): + b = json.loads(atv.content) + atv.content = str(int(bool(b))) + atv.save() + + +def reverse_modify_boolean_serialization(apps, schema_editor): + AttributeValue = apps.get_model('authentic2', 'AttributeValue') + for atv in AttributeValue.objects.filter(attribute__kind='boolean'): + b = bool(int(atv.content)) + atv.content = json.dumps(b) + atv.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentic2', '0016_attribute_disabled'), + ] + + operations = [ + migrations.RunPython(clean_null, noop), + migrations.RunPython(modify_string_serialization, reverse_modify_string_serialization), + migrations.RunPython(modify_boolean_serialization, reverse_modify_boolean_serialization), + ] diff --git a/tests/test_api.py b/tests/test_api.py index 4605d41..7fe1e08 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -193,7 +193,7 @@ def test_api_users_create(app, user): assert new_user.last_name == resp.json['last_name'] assert AttributeValue.objects.with_owner(new_user).count() == 3 assert AttributeValue.objects.with_owner(new_user).filter(attribute=at).exists() - assert (json.loads(AttributeValue.objects.with_owner(new_user).get(attribute=at).content) == + assert (AttributeValue.objects.with_owner(new_user).get(attribute=at).content == payload['title']) resp2 = app.get('/api/users/%s/' % resp.json['uuid']) assert resp.json == resp2.json diff --git a/tests/test_auth_oidc.py b/tests/test_auth_oidc.py index 4bb3fe6..6629379 100644 --- a/tests/test_auth_oidc.py +++ b/tests/test_auth_oidc.py @@ -272,13 +272,13 @@ def test_sso(app, caplog, code, oidc_provider, login_url, login_callback_url): assert user.email == 'john.doe@example.com' assert user.attributes.first_name == 'John' assert user.attributes.last_name == 'Doe' - assert AttributeValue.objects.filter(content='"John"', verified=True).count() == 1 - assert AttributeValue.objects.filter(content='"Doe"', verified=False).count() == 1 + assert AttributeValue.objects.filter(content='John', verified=True).count() == 1 + assert AttributeValue.objects.filter(content='Doe', verified=False).count() == 1 with oidc_provider_mock(oidc_provider, code, extra_user_info={'family_name_verified': True}): response = app.get(login_callback_url, params={'code': code, 'state': query['state']}) - assert AttributeValue.objects.filter(content='"Doe"', verified=False).count() == 0 - assert AttributeValue.objects.filter(content='"Doe"', verified=True).count() == 1 + assert AttributeValue.objects.filter(content='Doe', verified=False).count() == 0 + assert AttributeValue.objects.filter(content='Doe', verified=True).count() == 1 response = app.get(reverse('account_management')) with utils.check_log(caplog, 'revoked token from OIDC'): -- 2.1.4