recipe-server: Remove unneeded data from signed recipe listing.

Fixes #759.
This commit is contained in:
Mike Cooper 2017-05-15 14:31:50 -07:00
Родитель 04374ab223
Коммит 5a570ae514
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 74AB8817639D69C1
4 изменённых файлов: 32 добавлений и 23 удалений

Просмотреть файл

@ -47,9 +47,6 @@ class ApprovalRequestSerializer(serializers.ModelSerializer):
class RecipeSerializer(serializers.ModelSerializer):
# Attributes serialized here are made available to filter expressions via
# normandy.recipe, and should be documented if they are intended to be
# used in filter expressions.
enabled = serializers.BooleanField(read_only=True)
last_updated = serializers.DateTimeField(read_only=True)
revision_id = serializers.CharField(read_only=True)
@ -158,6 +155,31 @@ class RecipeSerializer(serializers.ModelSerializer):
return value
class MinimalRecipeSerializer(RecipeSerializer):
"""
The minimum amount of fields needed for clients to verify and execute recipes.
"""
revision_id = serializers.CharField(source='current_revision.id', read_only=True)
class Meta(RecipeSerializer.Meta):
# Attributes serialized here are made available to filter expressions via
# normandy.recipe, and should be documented if they are intended to be
# used in filter expressions.
fields = [
'id',
'last_updated',
'name',
'enabled',
'is_approved',
'revision_id',
'action',
'arguments',
'filter_expression',
'revision_id',
]
class RecipeRevisionSerializer(serializers.ModelSerializer):
date_created = serializers.DateTimeField(source='created', read_only=True)
recipe = RecipeSerializer(source='serializable_recipe', read_only=True)
@ -200,4 +222,5 @@ class SignedRecipeSerializer(serializers.ModelSerializer):
fields = ['signature', 'recipe']
def get_recipe(self, recipe):
return RecipeSerializer(recipe).data
# `recipe` here is the main object for the serializer.
return MinimalRecipeSerializer(recipe).data

Просмотреть файл

@ -186,8 +186,9 @@ class Recipe(DirtyFieldsMixin, models.Model):
return None
def canonical_json(self):
from normandy.recipes.api.serializers import RecipeSerializer # Avoid circular import
data = RecipeSerializer(self).data
# Avoid circular import
from normandy.recipes.api.serializers import MinimalRecipeSerializer
data = MinimalRecipeSerializer(self).data
return CanonicalJSONRenderer().render(data)
def update_signature(self):

Просмотреть файл

@ -207,19 +207,12 @@ class TestRecipe(object):
expected = (
'{'
'"action":"action",'
'"approval_request":null,'
'"approved_revision_id":null,'
'"arguments":{"bar":2,"foo":1},'
'"channels":["beta"],'
'"countries":["CA"],'
'"enabled":false,'
'"extra_filter_expression":"2 + 2 == 4",'
'"filter_expression":"%(filter_expression)s",'
'"id":%(id)s,'
'"is_approved":false,'
'"last_updated":"%(last_updated)s",'
'"latest_revision_id":"%(latest_revision_id)s",'
'"locales":["en-US"],'
'"name":"canonical",'
'"revision_id":"%(revision_id)s"'
'}'
@ -227,7 +220,6 @@ class TestRecipe(object):
'id': recipe.id,
'revision_id': recipe.revision_id,
'last_updated': recipe.last_updated.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
'latest_revision_id': recipe.latest_revision.id,
'filter_expression': filter_expression
}
expected = expected.encode()

Просмотреть файл

@ -12,7 +12,7 @@ from normandy.recipes.tests import (
RecipeFactory,
)
from normandy.recipes.api.serializers import (
ActionSerializer, RecipeSerializer, SignedRecipeSerializer)
ActionSerializer, RecipeSerializer, MinimalRecipeSerializer, SignedRecipeSerializer)
@pytest.mark.django_db()
@ -184,7 +184,7 @@ class TestSignedRecipeSerializer:
recipe = RecipeFactory(signed=True)
context = {'request': rf.get('/')}
combined_serializer = SignedRecipeSerializer(instance=recipe, context=context)
recipe_serializer = RecipeSerializer(instance=recipe, context=context)
recipe_serializer = MinimalRecipeSerializer(instance=recipe, context=context)
# Testing for shape of data, not contents
assert combined_serializer.data == {
@ -208,18 +208,11 @@ class TestSignedRecipeSerializer:
'name': recipe.name,
'id': recipe.id,
'enabled': recipe.enabled,
'extra_filter_expression': recipe.extra_filter_expression,
'filter_expression': recipe.filter_expression,
'revision_id': recipe.revision_id,
'action': action.name,
'arguments': recipe.arguments,
'last_updated': Whatever(),
'channels': [],
'countries': [],
'locales': [],
'is_approved': False,
'latest_revision_id': recipe.latest_revision.id,
'approved_revision_id': recipe.approved_revision_id,
'approval_request': None,
}
}