From 3f97f5c444ea4caa01111f3902871975430d9d97 Mon Sep 17 00:00:00 2001 From: Roald de Vries Date: Tue, 29 Nov 2016 17:34:41 +0100 Subject: add inbox resource --- service/pixelated/resources/inbox_resource.py | 64 +++++++++++++++++++ service/test/unit/resources/test_inbox_resource.py | 72 ++++++++++++++++++++++ service/test/unit/resources/test_root_resource.py | 19 ++---- 3 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 service/pixelated/resources/inbox_resource.py create mode 100644 service/test/unit/resources/test_inbox_resource.py (limited to 'service') diff --git a/service/pixelated/resources/inbox_resource.py b/service/pixelated/resources/inbox_resource.py new file mode 100644 index 00000000..47a3c072 --- /dev/null +++ b/service/pixelated/resources/inbox_resource.py @@ -0,0 +1,64 @@ +# +# Copyright (c) 2016 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . +import hashlib +import os +from string import Template + +import pixelated +from pixelated.resources import BaseResource + +from twisted.logger import Logger + +logger = Logger() + + +MODE_STARTUP = 1 +MODE_RUNNING = 2 + + +class InboxResource(BaseResource): + isLeaf = True + + def __init__(self, services_factory): + BaseResource.__init__(self, services_factory) + self._templates_folder = self._get_templates_folder() + self._html_template = open(os.path.join(self._templates_folder, 'index.html')).read() + with open(os.path.join(self._templates_folder, 'Interstitial.html')) as f: + self.interstitial = f.read() + self._mode = MODE_STARTUP + + def initialize(self): + self._mode = MODE_RUNNING + logger.debug('Inbox in RUNNING mode. %s' % self) + + def _get_templates_folder(self): + path = os.path.dirname(os.path.abspath(pixelated.__file__)) + return os.path.join(path, 'assets') + + def _is_starting(self): + return self._mode == MODE_STARTUP + + def render_GET(self, request): + logger.debug('Inbox rendering GET. %s' % self) + self._add_csrf_cookie(request) + if self._is_starting(): + logger.debug('Inbox rendering interstitial. %s' % self) + return self.interstitial + else: + logger.debug('Inbox rendering from template. %s' % self) + account_email = self.mail_service(request).account_email + response = Template(self._html_template).safe_substitute(account_email=account_email) + return str(response) diff --git a/service/test/unit/resources/test_inbox_resource.py b/service/test/unit/resources/test_inbox_resource.py new file mode 100644 index 00000000..03fe6f1a --- /dev/null +++ b/service/test/unit/resources/test_inbox_resource.py @@ -0,0 +1,72 @@ +import re + +from mock import MagicMock, patch +from mockito import mock, when, any as ANY + +from pixelated.application import UserAgentMode +from pixelated.resources.features_resource import FeaturesResource +from test.unit.resources import DummySite +from twisted.trial import unittest +from twisted.web.test.requesthelper import DummyRequest +from pixelated.resources.inbox_resource import InboxResource, MODE_STARTUP, MODE_RUNNING + + +class TestInboxResource(unittest.TestCase): + MAIL_ADDRESS = 'test_user@pixelated-project.org' + + def setUp(self): + mail_service = mock() + mail_service.account_email = self.MAIL_ADDRESS + + services = mock() + services.mail_service = mail_service + + services_factory = mock() + services_factory.mode = mock() + when(services_factory).services(ANY()).thenReturn(services) + + self.inbox_resource = InboxResource(services_factory) + self.web = DummySite(self.inbox_resource) + + def test_render_GET_should_template_account_email(self): + self.inbox_resource._html_template = "$account_email" + self.inbox_resource.initialize() + + request = DummyRequest(['']) + request.addCookie = lambda key, value: 'stubbed' + + d = self.web.get(request) + + def assert_response(_): + expected = "{0}".format(self.MAIL_ADDRESS) + matches = re.findall(expected, request.written[0]) + self.assertEquals(len(matches), 1) + + d.addCallback(assert_response) + return d + + def _test_should_renew_xsrf_cookie(self): + request = DummyRequest(['']) + request.addCookie = MagicMock() + generated_csrf_token = 'csrf_token' + mock_sha = MagicMock() + mock_sha.hexdigest = MagicMock(return_value=generated_csrf_token) + + with patch('hashlib.sha256', return_value=mock_sha): + d = self.web.get(request) + + def assert_csrf_cookie(_): + request.addCookie.assert_called_once_with('XSRF-TOKEN', generated_csrf_token) + + d.addCallback(assert_csrf_cookie) + return d + + # TODO should this be here or just in the root resource test? + def test_should_renew_xsrf_cookie_on_startup_mode(self): + self.inbox_resource._mode = MODE_STARTUP + self._test_should_renew_xsrf_cookie() + + # TODO should this be here or just in the root resource test? + def test_should_renew_xsrf_cookie_on_running_mode(self): + self.inbox_resource._mode = MODE_RUNNING + self._test_should_renew_xsrf_cookie() diff --git a/service/test/unit/resources/test_root_resource.py b/service/test/unit/resources/test_root_resource.py index 2c74d7b9..079793b5 100644 --- a/service/test/unit/resources/test_root_resource.py +++ b/service/test/unit/resources/test_root_resource.py @@ -11,7 +11,7 @@ from test.unit.resources import DummySite from twisted.cred.checkers import ANONYMOUS from twisted.internet.defer import succeed from twisted.trial import unittest -from twisted.web.resource import IResource +from twisted.web.resource import IResource, getChildForRequest from twisted.web.static import File from twisted.web.test.requesthelper import DummyRequest from pixelated.resources.root_resource import InboxResource, RootResource, MODE_STARTUP, MODE_RUNNING @@ -34,22 +34,11 @@ class TestRootResource(unittest.TestCase): self.web = DummySite(root_resource) self.root_resource = root_resource - def test_render_GET_should_template_account_email(self): - self.root_resource._inbox_resource._html_template = "$account_email" - self.root_resource.initialize(provider=mock(), authenticator=mock()) - + def test_root_should_delegate_to_inbox(self): request = DummyRequest(['']) request.addCookie = lambda key, value: 'stubbed' - - d = self.web.get(request) - - def assert_response(_): - expected = "{0}".format(self.MAIL_ADDRESS) - matches = re.findall(expected, request.written[0]) - self.assertEquals(len(matches), 1) - - d.addCallback(assert_response) - return d + child_resource = getChildForRequest(self.root_resource, request) + self.assertIsInstance(child_resource, InboxResource) def _test_should_renew_xsrf_cookie(self): request = DummyRequest(['']) -- cgit v1.2.3