~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/app/webservice/tests/test_marshallers.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2011-07-05 14:31:38 UTC
  • mfrom: (13316.10.21 bug-740208-obfuscate-ws)
  • Revision ID: launchpad@pqm.canonical.com-20110705143138-yd0hdrvbeslquzfm
[r=deryck][bug=740208] obfuscated email addresses for anonymous
 webservice requests

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2011 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
"""Tests for the webservice marshallers."""
 
5
 
 
6
__metaclass__ = type
 
7
 
 
8
import transaction
 
9
from zope.component import getUtility
 
10
 
 
11
from canonical.launchpad.testing.pages import (
 
12
    LaunchpadWebServiceCaller,
 
13
    webservice_for_person,
 
14
    )
 
15
from canonical.launchpad.webapp.interfaces import IPlacelessAuthUtility
 
16
from canonical.launchpad.webapp.servers import WebServiceTestRequest
 
17
from canonical.testing.layers import DatabaseFunctionalLayer
 
18
from lp.app.webservice.marshallers import TextFieldMarshaller
 
19
from lp.testing import logout, TestCaseWithFactory
 
20
 
 
21
 
 
22
def ws_url(bug):
 
23
    url = "/bugs/%d" % bug.id
 
24
    return url
 
25
 
 
26
 
 
27
class TestTextFieldMarshaller(TestCaseWithFactory):
 
28
 
 
29
    layer = DatabaseFunctionalLayer
 
30
 
 
31
    def _makeRequest(self, is_anonymous):
 
32
        """Create either an anonymous or authenticated request."""
 
33
        request = WebServiceTestRequest()
 
34
        if is_anonymous:
 
35
            request.setPrincipal(
 
36
                getUtility(IPlacelessAuthUtility).unauthenticatedPrincipal())
 
37
        else:
 
38
            request.setPrincipal(self.factory.makePerson())
 
39
        return request
 
40
 
 
41
    def test_unmarshall_obfuscated(self):
 
42
        # Data is obfuccated if the request is anonynous.
 
43
        request = self._makeRequest(is_anonymous=True)
 
44
        marshaller = TextFieldMarshaller(None, request)
 
45
        result = marshaller.unmarshall(None, u"foo@example.com")
 
46
        self.assertEqual(u"<email address hidden>", result)
 
47
 
 
48
    def test_unmarshall_not_obfuscated(self):
 
49
        # Data is not obfuccated if the request is authenticated.
 
50
        request = self._makeRequest(is_anonymous=False)
 
51
        marshaller = TextFieldMarshaller(None, request)
 
52
        result = marshaller.unmarshall(None, u"foo@example.com")
 
53
        self.assertEqual(u"foo@example.com", result)
 
54
 
 
55
 
 
56
class TestWebServiceObfuscation(TestCaseWithFactory):
 
57
    """Integration test for obfuscation marshaller.
 
58
 
 
59
    Not using WebServiceTestCase because that assumes too much about users
 
60
    """
 
61
 
 
62
    layer = DatabaseFunctionalLayer
 
63
 
 
64
    email_address = "joe@example.com"
 
65
    email_address_obfuscated = "<email address hidden>"
 
66
    email_address_obfuscated_escaped = "&lt;email address hidden&gt;"
 
67
    bug_title = "Title with address %s in it"
 
68
    bug_description = "Description with address %s in it"
 
69
 
 
70
    def _makeBug(self):
 
71
        """Create a bug with an email address in title and description."""
 
72
        bug = self.factory.makeBug(
 
73
            title=self.bug_title % self.email_address,
 
74
            description=self.bug_description % self.email_address)
 
75
        transaction.commit()
 
76
        return bug
 
77
 
 
78
    def test_email_address_obfuscated(self):
 
79
        # Email addresses are obfuscated for anonymous users.
 
80
        bug = self._makeBug()
 
81
        logout()
 
82
        webservice = LaunchpadWebServiceCaller()
 
83
        result = webservice(ws_url(bug)).jsonBody()
 
84
        self.assertEqual(
 
85
            self.bug_title % self.email_address_obfuscated,
 
86
            result['title'])
 
87
        self.assertEqual(
 
88
            self.bug_description % self.email_address_obfuscated,
 
89
            result['description'])
 
90
 
 
91
    def test_email_address_not_obfuscated(self):
 
92
        # Email addresses are not obfuscated for authenticated users.
 
93
        bug = self._makeBug()
 
94
        user = self.factory.makePerson()
 
95
        webservice = webservice_for_person(user)
 
96
        result = webservice(ws_url(bug)).jsonBody()
 
97
        self.assertEqual(self.bug_title % self.email_address, result['title'])
 
98
        self.assertEqual(
 
99
            self.bug_description % self.email_address, result['description'])
 
100
 
 
101
    def test_xhtml_email_address_not_obfuscated(self):
 
102
        # Email addresses are not obfuscated for authenticated users.
 
103
        bug = self._makeBug()
 
104
        user = self.factory.makePerson()
 
105
        webservice = webservice_for_person(user)
 
106
        result = webservice(
 
107
            ws_url(bug), headers={'Accept': 'application/xhtml+xml'})
 
108
        self.assertIn(self.email_address, result.body)
 
109
        self.assertNotIn(
 
110
            self.email_address_obfuscated_escaped, result.body)
 
111
 
 
112
    def test_xhtml_email_address_obfuscated(self):
 
113
        # Email addresses are obfuscated in the XML representation for
 
114
        # anonymous users.
 
115
        bug = self._makeBug()
 
116
        logout()
 
117
        webservice = LaunchpadWebServiceCaller()
 
118
        result = webservice(
 
119
            ws_url(bug), headers={'Accept': 'application/xhtml+xml'})
 
120
        self.assertNotIn(self.email_address, result.body)
 
121
        self.assertIn(self.email_address_obfuscated_escaped, result.body)
 
122
 
 
123
    def test_etags_differ_for_anon_and_non_anon_represetations(self):
 
124
        # When a webservice client retrieves data anonymously, this
 
125
        # data should not be used in later write requests, if the
 
126
        # text fields contain obfuscated email addresses. The etag
 
127
        # for a GET request is calculated after the email address
 
128
        # obfuscation and thus differs from the etag returned for
 
129
        # not obfuscated data, so clients usings etags to check if the
 
130
        # cached data is up to date will not use the obfuscated data
 
131
        # in PATCH or PUT requests.
 
132
        bug = self._makeBug()
 
133
        user = self.factory.makePerson()
 
134
        webservice = webservice_for_person(user)
 
135
        etag_logged_in = webservice(ws_url(bug)).getheader('etag')
 
136
        logout()
 
137
        webservice = LaunchpadWebServiceCaller()
 
138
        etag_logged_out = webservice(ws_url(bug)).getheader('etag')
 
139
        self.assertNotEqual(etag_logged_in, etag_logged_out)