Skip to content

Commit

Permalink
Add report data scrubber
Browse files Browse the repository at this point in the history
The Report.parse() method now removes sensitive report data returned
from the API. By default the 'breakdown' and 'properties' values are
removed. This behaviour can be overridden by setting
ONFIDO_REPORT_SCRUBBER to an alternative function that takes the raw
dict and updates it in whichever way you require.
  • Loading branch information
hugorodgerbrown committed Oct 25, 2016
1 parent 6534c6c commit f84a986
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 1 deletion.
11 changes: 10 additions & 1 deletion onfido/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from .api import get
from .db.fields import JSONField
from .settings import scrub_report_data
from .signals import on_status_change, on_completion

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -342,7 +343,15 @@ def __repr__(self):
)

def parse(self, raw_json):
"""Parse the raw value out into other properties."""
"""
Parse the raw value out into other properties.
Before parsing the data, this method will call the
scrub_report_data function to remove sensitive data
so that it is not saved into the local object.
"""
scrub_report_data(raw_json)
super(Report, self).parse(raw_json)
self.report_type = self.raw['name']
return self
Expand Down
16 changes: 16 additions & 0 deletions onfido/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,23 @@
# the API HTTP root url
API_ROOT = "https://api.onfido.com/v2/"

# flag to turn event logging on/off
LOG_EVENTS = (
getattr(settings, 'ONFIDO_LOG_EVENTS', False) or
getenv('ONFIDO_LOG_EVENTS', False)
)

def DEFAULT_REPORT_SCRUBBER(raw):
"""Default report scrubber, removes breakdown and properties."""
try:
del raw['breakdown']
del raw['properties']
except KeyError:
pass
return raw

# function used to scrub sensitive data from reports
scrub_report_data = (
getattr(settings, 'ONFIDO_REPORT_SCRUBBER', None) or
DEFAULT_REPORT_SCRUBBER
)
26 changes: 26 additions & 0 deletions onfido/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
# -*- coding: utf-8 -*-
from decimal import Decimal
import mock

from django.contrib.auth.models import User
from django.test import TestCase

from ..admin import (
RawMixin,
UserMixin,
Applicant
)


class RawMixinTests(TestCase):

"""Tests for RawMixin admin class."""

def test__raw(self):
mixin = RawMixin()
obj = Applicant(raw={'foo': 'bar'})
Expand All @@ -20,3 +25,24 @@ def test__raw(self):
# test with Decimal (stdlib json won't work) and unicode
obj = Applicant(raw={'foo': Decimal(1.0), 'bar': u'åß∂ƒ©˙∆'})
html = mixin._raw(obj)


class UserMixinTests(TestCase):

"""Tests for UserMixin admin class."""

def test__user(self):

def assertUser(first_name, last_name, expected):
mixin = UserMixin()
user = User(first_name=first_name, last_name=last_name)
obj = mock.Mock(user=user)
self.assertEqual(mixin._user(obj), expected)

assertUser('fred', 'flintstone', 'Fred Flintstone')
assertUser('', '', '')
assertUser(u'fredå', 'flintstone', u'Fredå Flintstone')
# this fails, something that title() does to unicode?
with self.assertRaises(AssertionError):
self.assertEqual(u'ƒ', u'ƒ'.title())
assertUser(u'ƒredå', '', u'ƒredå'.title())
16 changes: 16 additions & 0 deletions onfido/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,22 @@ def test_parse(self):
self.assertEqual(report.result, "clear")
self.assertEqual(report.report_type, "identity")

def test_parse_scrubs_data(self):
"""Test the parse method also removes sensitive data."""
data = {
"id": "c26f22d5-4903-401f-8a48-7b0211d03c1f",
"created_at": "2016-10-15T19:05:50Z",
"status": "awaiting_applicant",
"result": "clear",
"name": "identity",
"breakdown": {},
"properties": {}
}
report = Report().parse(data)
# the default report scrubber should have removed data:
self.assertFalse('breakdown' in report.raw)
self.assertFalse('properties' in report.raw)


class EventTests(TestCase):

Expand Down
39 changes: 39 additions & 0 deletions onfido/tests/test_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
import mock

from django.test import TestCase, override_settings

from ..settings import DEFAULT_REPORT_SCRUBBER


class SettingsTests(TestCase):

"""settings module tests."""

def test_default_report_scrubber(self):
"""Test the report_scrubber default function."""
data = {
'foo': 'bar',
'breakdown': {},
'properties': {}
}
# default function should remove breakdown and properties
data = DEFAULT_REPORT_SCRUBBER(data)
self.assertFalse('breakdown' in data)
self.assertFalse('properties' in data)

# mock scrubber that does nothing and returns the data unchanged
@mock.patch('onfido.settings.scrub_report_data', lambda d: d)
def test_override_report_scrubber(self):
"""Test the report_scrubber default function."""
data = {
'foo': 'bar',
'breakdown': {},
'properties': {}
}
# import here otherwise the mock is ineffective
from ..settings import scrub_report_data
# default function should remove breakdown and properties
scrub_report_data(data)
self.assertTrue('breakdown' in data)
self.assertTrue('properties' in data)

0 comments on commit f84a986

Please sign in to comment.