Skip to content
This repository has been archived by the owner on Sep 5, 2019. It is now read-only.

Commit

Permalink
Stores a checksum with each form definition and submission.
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Krienbühl committed Jun 3, 2015
1 parent 9e27249 commit eea34bd
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 1 deletion.
3 changes: 3 additions & 0 deletions HISTORY.rst
Expand Up @@ -4,6 +4,9 @@ Changelog
Unreleased
~~~~~~~~~~

- Stores a checksum with each form definition and submission.
[href]

- Adds the ability to filter out submissions older than one hour.
[href]

Expand Down
22 changes: 22 additions & 0 deletions onegov/form/models.py
@@ -1,3 +1,4 @@
from hashlib import md5
from onegov.core.orm import Base
from onegov.core.orm.mixins import TimestampMixin
from onegov.core.orm.types import JSON, UUID
Expand All @@ -8,9 +9,14 @@
deferred,
relationship,
)
from sqlalchemy_utils import observes
from uuid import uuid4


def hash_definition(definition):
return md5(definition.encode('utf-8')).hexdigest()


class FormDefinition(Base, TimestampMixin):
""" Defines a form stored in the database. """

Expand All @@ -31,6 +37,10 @@ class FormDefinition(Base, TimestampMixin):
#: the form as parsable string
definition = Column(Text, nullable=False)

#: the checksum of the definition, forms and submissions with matching
#: checksums are guaranteed to have the exact same definition
checksum = Column(Text, nullable=False)

#: the type of the form, this can be used to create custom polymorphic
#: subclasses. See `<http://docs.sqlalchemy.org/en/improve_toc/\
#: orm/extensions/declarative/inheritance.html>`_.
Expand All @@ -49,6 +59,10 @@ def form_class(self):

return parse_form(self.definition)

@observes('definition')
def definition_observer(self, definition):
self.checksum = hash_definition(definition)


class FormSubmission(Base, TimestampMixin):
""" Defines a submitted form in the database. """
Expand All @@ -66,6 +80,10 @@ class FormSubmission(Base, TimestampMixin):
#: want to keep the old form around just in case.
definition = Column(Text, nullable=False)

#: the checksum of the definition, forms and submissions with matching
#: checksums are guaranteed to have the exact same definition
checksum = Column(Text, nullable=False)

#: the submission data
data = Column(JSON, nullable=False)

Expand All @@ -92,6 +110,10 @@ def form_class(self):

return parse_form(self.definition)

@observes('definition')
def definition_observer(self, definition):
self.checksum = hash_definition(definition)

def complete(self):
""" Changes the state to 'complete', if the data is valid. """

Expand Down
11 changes: 10 additions & 1 deletion onegov/form/tests/test_collection.py
Expand Up @@ -4,7 +4,7 @@
from delorean import Delorean
from onegov.core.compat import BytesIO
from onegov.form import FormCollection, PendingFormSubmission
from onegov.form.models import FormSubmissionFile
from onegov.form.models import FormSubmissionFile, hash_definition
from onegov.form.errors import UnableToComplete
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.exc import FlushError
Expand All @@ -14,6 +14,10 @@
from wtforms.csrf.core import CSRF


def test_form_checksum():
assert hash_definition('abc') == '900150983cd24fb0d6963f7d28e17f72'


def test_add_form(session):
collection = FormCollection(session)

Expand All @@ -36,6 +40,8 @@ def test_add_form(session):
Last Name * = ___
"""))

assert form.checksum and form.checksum == hash_definition(form.definition)


def test_submit_form(session):
collection = FormCollection(session)
Expand All @@ -58,6 +64,9 @@ def test_submit_form(session):
form = collection.definitions.by_name('tps-report')
submission = form.submissions[0]

assert submission.checksum and submission.checksum == hash_definition(
form.definition) == hash_definition(submission.definition)

stored_form = submission.form_class(data=submission.data)

assert submitted_form.data == stored_form.data
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Expand Up @@ -34,13 +34,15 @@ def get_long_description():
zip_safe=False,
platforms='any',
install_requires=[
'delorean',
'humanize',
'jsonpickle',
'onegov.core>=0.3.5',
'pyparsing',
'pyyaml',
'python-magic',
'python-stdnum',
'sqlalchemy_utils',
'wtforms',
'wtforms-components[color]',
'unidecode'
Expand Down

0 comments on commit eea34bd

Please sign in to comment.