From 41f0886aeac43387dc8b4d54b1ca69f21e2ec2a8 Mon Sep 17 00:00:00 2001 From: Roald de Vries Date: Wed, 30 Nov 2016 15:00:58 +0100 Subject: remove PublicRootResource and use a flag on RootResource instead --- service/pixelated/application.py | 4 +- service/pixelated/resources/root_resource.py | 62 ++++++++++------------ service/test/unit/resources/test_auth.py | 6 +-- service/test/unit/resources/test_root_resource.py | 63 ++++++++++++++++++++++- 4 files changed, 94 insertions(+), 41 deletions(-) diff --git a/service/pixelated/application.py b/service/pixelated/application.py index aee84cef..9f33cb82 100644 --- a/service/pixelated/application.py +++ b/service/pixelated/application.py @@ -37,7 +37,7 @@ from pixelated.config.leap import initialize_leap_single_user, init_monkeypatche from pixelated.config.services import ServicesFactory, SingleUserServicesFactory from pixelated.config.site import PixelatedSite from pixelated.resources.auth import PixelatedRealm, PixelatedAuthSessionWrapper, SessionChecker -from pixelated.resources.root_resource import PublicRootResource, RootResource +from pixelated.resources.root_resource import RootResource log = Logger() @@ -154,7 +154,7 @@ def _setup_multi_user(args, root_resource, services_factory): def set_up_protected_resources(root_resource, provider, services_factory, banner=None, authenticator=None): session_checker = SessionChecker(services_factory) - anonymous_resource = PublicRootResource(services_factory) + anonymous_resource = RootResource(services_factory, public=True) realm = PixelatedRealm(root_resource, anonymous_resource) _portal = portal.Portal(realm, [session_checker, AllowAnonymousAccess()]) diff --git a/service/pixelated/resources/root_resource.py b/service/pixelated/resources/root_resource.py index 035d5f18..3f09848f 100644 --- a/service/pixelated/resources/root_resource.py +++ b/service/pixelated/resources/root_resource.py @@ -42,26 +42,11 @@ from twisted.logger import Logger logger = Logger() -class PublicRootResource(BaseResource): +class RootResource(BaseResource): - def __init__(self, services_factory): + def __init__(self, services_factory, public=False): BaseResource.__init__(self, services_factory) - self._redirect_to_inbox_resource = Redirect('login') - - def initialize(self, provider=None, disclaimer_banner=None, authenticator=None): - self.putChild(LoginResource.BASE_URL, - LoginResource(self._services_factory, provider, disclaimer_banner=disclaimer_banner, authenticator=authenticator)) - - def getChildWithDefault(self, path, request): - if path == '': - return self._redirect_to_inbox_resource - return BaseResource.getChildWithDefault(self, path, request) - - -class RootResource(PublicRootResource): - - def __init__(self, services_factory): - PublicRootResource.__init__(self, services_factory) + self._public = public self._assets_folder = self._get_assets_folder() self._startup_assets_folder = self._get_startup_folder() self._static_folder = self._get_static_folder() @@ -69,18 +54,19 @@ class RootResource(PublicRootResource): self._services_factory = services_factory with open(os.path.join(self._startup_assets_folder, 'Interstitial.html')) as f: self.interstitial = f.read() + self._redirect_to_login_resource = Redirect('login') self._inbox_resource = InboxResource(services_factory) self._startup_mode() def _startup_mode(self): - self.putChild('assets', File(self._assets_folder)) - self.putChild('startup-assets', File(self._startup_assets_folder)) + self.putChildProtected('assets', File(self._assets_folder)) + self.putChildPublic('startup-assets', File(self._startup_assets_folder)) self._mode = MODE_STARTUP logger.debug('Root in STARTUP mode. %s' % self) def getChildWithDefault(self, path, request): if path == '': - return self._inbox_resource + return self._redirect_to_login_resource if self._public else self._inbox_resource if self._mode == MODE_STARTUP: return UnavailableResource() if self._is_xsrf_valid(request): @@ -104,20 +90,28 @@ class RootResource(PublicRootResource): csrf_input = request.args.get('csrftoken', [None])[0] or json.loads(request.content.read()).get('csrftoken', [None])[0] return csrf_input and csrf_input == xsrf_token + def putChildPublic(self, path, resource): + return BaseResource.putChild(self, path, resource) + + def putChildProtected(self, path, resource): + return BaseResource.putChild(self, path, UnAuthorizedResource() if self._public else resource) + putChild = putChildProtected + def initialize(self, provider=None, disclaimer_banner=None, authenticator=None): - PublicRootResource.initialize(self, provider, disclaimer_banner, authenticator) - self.putChild('sandbox', SandboxResource(self._static_folder)) - self.putChild('keys', KeysResource(self._services_factory)) - self.putChild(AttachmentsResource.BASE_URL, AttachmentsResource(self._services_factory)) - self.putChild('contacts', ContactsResource(self._services_factory)) - self.putChild('features', FeaturesResource(provider)) - self.putChild('tags', TagsResource(self._services_factory)) - self.putChild('mails', MailsResource(self._services_factory)) - self.putChild('mail', MailResource(self._services_factory)) - self.putChild('feedback', FeedbackResource(self._services_factory)) - self.putChild('user-settings', UserSettingsResource(self._services_factory)) - self.putChild('users', UsersResource(self._services_factory)) - self.putChild(LogoutResource.BASE_URL, LogoutResource(self._services_factory)) + self.putChildProtected('sandbox', SandboxResource(self._static_folder)) + self.putChildProtected('keys', KeysResource(self._services_factory)) + self.putChildProtected(AttachmentsResource.BASE_URL, AttachmentsResource(self._services_factory)) + self.putChildProtected('contacts', ContactsResource(self._services_factory)) + self.putChildProtected('features', FeaturesResource(provider)) + self.putChildProtected('tags', TagsResource(self._services_factory)) + self.putChildProtected('mails', MailsResource(self._services_factory)) + self.putChildProtected('mail', MailResource(self._services_factory)) + self.putChildProtected('feedback', FeedbackResource(self._services_factory)) + self.putChildProtected('user-settings', UserSettingsResource(self._services_factory)) + self.putChildProtected('users', UsersResource(self._services_factory)) + self.putChildPublic(LoginResource.BASE_URL, + LoginResource(self._services_factory, provider, disclaimer_banner=disclaimer_banner, authenticator=authenticator)) + self.putChildProtected(LogoutResource.BASE_URL, LogoutResource(self._services_factory)) self._inbox_resource.initialize() self._mode = MODE_RUNNING diff --git a/service/test/unit/resources/test_auth.py b/service/test/unit/resources/test_auth.py index 793069dd..f4012b1b 100644 --- a/service/test/unit/resources/test_auth.py +++ b/service/test/unit/resources/test_auth.py @@ -1,7 +1,7 @@ from mockito import mock, when, any as ANY from pixelated.resources.auth import SessionChecker, PixelatedRealm, PixelatedAuthSessionWrapper from pixelated.resources.login_resource import LoginResource -from pixelated.resources.root_resource import PublicRootResource, RootResource +from pixelated.resources.root_resource import RootResource from test.unit.resources import DummySite from twisted.cred import error from twisted.cred.checkers import ANONYMOUS, AllowAnonymousAccess @@ -41,7 +41,7 @@ class TestPixelatedAuthSessionWrapper(unittest.TestCase): self.portal = Portal(self.realm_mock, [session_checker, AllowAnonymousAccess()]) self.user_uuid_mock = mock() self.root_resource = RootResource(services_factory) - self.anonymous_resource = PublicRootResource(services_factory) + self.anonymous_resource = RootResource(services_factory, public=True) self.session_wrapper = PixelatedAuthSessionWrapper(self.portal, self.root_resource, self.anonymous_resource) self.request = DummyRequest([]) @@ -55,7 +55,7 @@ class TestPixelatedAuthSessionWrapper(unittest.TestCase): d = deferred_resource.d def assert_public_root_resource(resource): - self.assertIsInstance(resource, PublicRootResource) + self.assertIs(resource, self.anonymous_resource) return d.addCallback(assert_public_root_resource) diff --git a/service/test/unit/resources/test_root_resource.py b/service/test/unit/resources/test_root_resource.py index 1543f650..b674103c 100644 --- a/service/test/unit/resources/test_root_resource.py +++ b/service/test/unit/resources/test_root_resource.py @@ -6,6 +6,7 @@ from mockito import mock, when, any as ANY import pixelated from pixelated.application import UserAgentMode +from pixelated.resources import UnAuthorizedResource from pixelated.resources.features_resource import FeaturesResource from pixelated.resources.login_resource import LoginResource from test.unit.resources import DummySite @@ -15,15 +16,55 @@ from twisted.trial import unittest 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, PublicRootResource, RootResource, MODE_STARTUP, MODE_RUNNING +from pixelated.resources.root_resource import InboxResource, RootResource, MODE_STARTUP, MODE_RUNNING class TestPublicRootResource(unittest.TestCase): def setUp(self): - self.public_root_resource = PublicRootResource(mock()) + self.public_root_resource = RootResource(mock(), public=True) self.web = DummySite(self.public_root_resource) + def test_put_child_public_adds_resource(self): + self.public_root_resource.initialize(provider=mock(), authenticator=mock()) + url_fragment, resource_mock = 'some-url-fragment', mock() + self.public_root_resource.putChildPublic(url_fragment, resource_mock) + request = DummyRequest([url_fragment]) + request.addCookie = lambda key, value: 'stubbed' + child_resource = getChildForRequest(self.public_root_resource, request) + self.assertIs(child_resource, resource_mock) + + def test_put_child_protected_adds_unauthorized(self): + self.public_root_resource.initialize(provider=mock(), authenticator=mock()) + url_fragment, resource_mock = 'some-url-fragment', mock() + self.public_root_resource.putChildProtected(url_fragment, resource_mock) + request = DummyRequest([url_fragment]) + request.addCookie = lambda key, value: 'stubbed' + child_resource = getChildForRequest(self.public_root_resource, request) + self.assertIsInstance(child_resource, UnAuthorizedResource) + + def test_put_child_adds_unauthorized(self): + self.public_root_resource.initialize(provider=mock(), authenticator=mock()) + url_fragment, resource_mock = 'some-url-fragment', mock() + self.public_root_resource.putChild(url_fragment, resource_mock) + request = DummyRequest([url_fragment]) + request.addCookie = lambda key, value: 'stubbed' + child_resource = getChildForRequest(self.public_root_resource, request) + self.assertIsInstance(child_resource, UnAuthorizedResource) + + def test_private_resource_returns_401(self): + self.public_root_resource.initialize(provider=mock(), authenticator=mock()) + request = DummyRequest(['mails']) + request.addCookie = lambda key, value: 'stubbed' + d = self.web.get(request) + + def assert_unauthorized(request): + self.assertEqual(401, request.responseCode) + self.assertEqual("Unauthorized!", request.written[0]) + + d.addCallback(assert_unauthorized) + return d + def test_login_url_should_delegate_to_login_resource(self): self.public_root_resource.initialize(provider=mock(), authenticator=mock()) request = DummyRequest(['login']) @@ -61,6 +102,24 @@ class TestRootResource(unittest.TestCase): self.root_resource = RootResource(self.services_factory) self.web = DummySite(self.root_resource) + def test_put_child_protected_adds_resource(self): + self.root_resource.initialize(provider=mock(), authenticator=mock()) + url_fragment, resource_mock = 'some-url-fragment', mock() + self.root_resource.putChildProtected(url_fragment, resource_mock) + request = DummyRequest([url_fragment]) + request.addCookie = lambda key, value: 'stubbed' + child_resource = getChildForRequest(self.root_resource, request) + self.assertIs(child_resource, resource_mock) + + def test_put_child_adds_resource(self): + self.root_resource.initialize(provider=mock(), authenticator=mock()) + url_fragment, resource_mock = 'some-url-fragment', mock() + self.root_resource.putChild(url_fragment, resource_mock) + request = DummyRequest([url_fragment]) + request.addCookie = lambda key, value: 'stubbed' + child_resource = getChildForRequest(self.root_resource, request) + self.assertIs(child_resource, resource_mock) + def test_root_url_should_delegate_to_inbox(self): request = DummyRequest(['']) request.addCookie = lambda key, value: 'stubbed' -- cgit v1.2.3