feat: add support for admin user to become / stop being root
This commit is contained in:
parent
a2ba88ca8f
commit
fc339ba81b
9 changed files with 335 additions and 22 deletions
|
@ -137,3 +137,9 @@ class TestWuttaSecurityPolicy(TestCase):
|
|||
self.user.roles.append(role)
|
||||
self.session.commit()
|
||||
self.assertTrue(self.policy.permits(self.request, None, 'baz.edit'))
|
||||
|
||||
# now let's try another perm - we won't grant it, but will
|
||||
# confirm user is denied access unless they become root
|
||||
self.assertFalse(self.policy.permits(self.request, None, 'some-root-perm'))
|
||||
self.request.is_root = True
|
||||
self.assertTrue(self.policy.permits(self.request, None, 'some-root-perm'))
|
||||
|
|
|
@ -18,40 +18,78 @@ class TestNewRequest(TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig()
|
||||
self.request = self.make_request()
|
||||
self.pyramid_config = testing.setUp(request=self.request, settings={
|
||||
'wutta_config': self.config,
|
||||
})
|
||||
|
||||
def tearDown(self):
|
||||
testing.tearDown()
|
||||
|
||||
def make_request(self):
|
||||
request = testing.DummyRequest()
|
||||
request.registry.settings = {'wutta_config': self.config}
|
||||
# request.registry.settings = {'wutta_config': self.config}
|
||||
return request
|
||||
|
||||
def test_wutta_config(self):
|
||||
request = self.make_request()
|
||||
event = MagicMock(request=request)
|
||||
event = MagicMock(request=self.request)
|
||||
|
||||
# request gets a new attr
|
||||
self.assertFalse(hasattr(request, 'wutta_config'))
|
||||
self.assertFalse(hasattr(self.request, 'wutta_config'))
|
||||
subscribers.new_request(event)
|
||||
self.assertTrue(hasattr(request, 'wutta_config'))
|
||||
self.assertIs(request.wutta_config, self.config)
|
||||
self.assertTrue(hasattr(self.request, 'wutta_config'))
|
||||
self.assertIs(self.request.wutta_config, self.config)
|
||||
|
||||
def test_use_oruga_default(self):
|
||||
request = self.make_request()
|
||||
event = MagicMock(request=request)
|
||||
event = MagicMock(request=self.request)
|
||||
|
||||
# request gets a new attr, false by default
|
||||
self.assertFalse(hasattr(request, 'use_oruga'))
|
||||
self.assertFalse(hasattr(self.request, 'use_oruga'))
|
||||
subscribers.new_request(event)
|
||||
self.assertFalse(request.use_oruga)
|
||||
self.assertFalse(self.request.use_oruga)
|
||||
|
||||
def test_use_oruga_custom(self):
|
||||
self.config.setdefault('wuttaweb.oruga_detector.spec', 'tests.test_subscribers:custom_oruga_detector')
|
||||
request = self.make_request()
|
||||
event = MagicMock(request=request)
|
||||
event = MagicMock(request=self.request)
|
||||
|
||||
# request gets a new attr, which should be true
|
||||
self.assertFalse(hasattr(request, 'use_oruga'))
|
||||
self.assertFalse(hasattr(self.request, 'use_oruga'))
|
||||
subscribers.new_request(event)
|
||||
self.assertTrue(request.use_oruga)
|
||||
self.assertTrue(self.request.use_oruga)
|
||||
|
||||
def test_get_referrer(self):
|
||||
event = MagicMock(request=self.request)
|
||||
|
||||
def home(request):
|
||||
pass
|
||||
|
||||
self.pyramid_config.add_route('home', '/')
|
||||
self.pyramid_config.add_view(home, route_name='home')
|
||||
|
||||
self.assertFalse(hasattr(self.request, 'get_referrer'))
|
||||
subscribers.new_request(event)
|
||||
self.assertTrue(hasattr(self.request, 'get_referrer'))
|
||||
|
||||
# default if no referrer, is home route
|
||||
url = self.request.get_referrer()
|
||||
self.assertEqual(url, self.request.route_url('home'))
|
||||
|
||||
# can specify another default
|
||||
url = self.request.get_referrer(default='https://wuttaproject.org')
|
||||
self.assertEqual(url, 'https://wuttaproject.org')
|
||||
|
||||
# or referrer can come from user session
|
||||
self.request.session['referrer'] = 'https://rattailproject.org'
|
||||
self.assertIn('referrer', self.request.session)
|
||||
url = self.request.get_referrer()
|
||||
self.assertEqual(url, 'https://rattailproject.org')
|
||||
# nb. referrer should also have been removed from user session
|
||||
self.assertNotIn('referrer', self.request.session)
|
||||
|
||||
# or referrer can come from request params
|
||||
self.request.params['referrer'] = 'https://kernel.org'
|
||||
url = self.request.get_referrer()
|
||||
self.assertEqual(url, 'https://kernel.org')
|
||||
|
||||
|
||||
def custom_oruga_detector(request):
|
||||
|
@ -97,6 +135,81 @@ class TestNewRequestSetUser(TestCase):
|
|||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIs(self.request.user, self.user)
|
||||
|
||||
def test_is_admin(self):
|
||||
event = MagicMock(request=self.request)
|
||||
|
||||
# anonymous user
|
||||
self.assertFalse(hasattr(self.request, 'user'))
|
||||
self.assertFalse(hasattr(self.request, 'is_admin'))
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIsNone(self.request.user)
|
||||
self.assertFalse(self.request.is_admin)
|
||||
|
||||
# reset
|
||||
del self.request.is_admin
|
||||
|
||||
# authenticated user, but still not an admin
|
||||
self.request.user = self.user
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIs(self.request.user, self.user)
|
||||
self.assertFalse(self.request.is_admin)
|
||||
|
||||
# reset
|
||||
del self.request.is_admin
|
||||
|
||||
# but if we make them an admin, it changes
|
||||
auth = self.app.get_auth_handler()
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
self.user.roles.append(admin)
|
||||
self.session.commit()
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIs(self.request.user, self.user)
|
||||
self.assertTrue(self.request.is_admin)
|
||||
|
||||
def test_is_root(self):
|
||||
event = MagicMock(request=self.request)
|
||||
|
||||
# anonymous user
|
||||
self.assertFalse(hasattr(self.request, 'user'))
|
||||
self.assertFalse(hasattr(self.request, 'is_root'))
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIsNone(self.request.user)
|
||||
self.assertFalse(self.request.is_root)
|
||||
|
||||
# reset
|
||||
del self.request.is_admin
|
||||
del self.request.is_root
|
||||
|
||||
# authenticated user, but still not an admin
|
||||
self.request.user = self.user
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIs(self.request.user, self.user)
|
||||
self.assertFalse(self.request.is_root)
|
||||
|
||||
# reset
|
||||
del self.request.is_admin
|
||||
del self.request.is_root
|
||||
|
||||
# even if we make them an admin, still not yet root
|
||||
auth = self.app.get_auth_handler()
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
self.user.roles.append(admin)
|
||||
self.session.commit()
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIs(self.request.user, self.user)
|
||||
self.assertTrue(self.request.is_admin)
|
||||
self.assertFalse(self.request.is_root)
|
||||
|
||||
# reset
|
||||
del self.request.is_admin
|
||||
del self.request.is_root
|
||||
|
||||
# root status flag lives in user session
|
||||
self.request.session['is_root'] = True
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertTrue(self.request.is_admin)
|
||||
self.assertTrue(self.request.is_root)
|
||||
|
||||
|
||||
class TestBeforeRender(TestCase):
|
||||
|
||||
|
|
|
@ -4,11 +4,12 @@ from unittest import TestCase
|
|||
from unittest.mock import MagicMock
|
||||
|
||||
from pyramid import testing
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
from pyramid.httpexceptions import HTTPFound, HTTPForbidden
|
||||
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttaweb.views import auth as mod
|
||||
from wuttaweb.auth import WuttaSecurityPolicy
|
||||
from wuttaweb.subscribers import new_request
|
||||
|
||||
|
||||
class TestAuthView(TestCase):
|
||||
|
@ -19,7 +20,9 @@ class TestAuthView(TestCase):
|
|||
})
|
||||
|
||||
self.request = testing.DummyRequest(wutta_config=self.config, user=None)
|
||||
self.pyramid_config = testing.setUp(request=self.request)
|
||||
self.pyramid_config = testing.setUp(request=self.request, settings={
|
||||
'wutta_config': self.config,
|
||||
})
|
||||
|
||||
self.app = self.config.get_app()
|
||||
auth = self.app.get_auth_handler()
|
||||
|
@ -142,3 +145,46 @@ class TestAuthView(TestCase):
|
|||
self.assertIn('form', context)
|
||||
dform = context['form'].get_deform()
|
||||
self.assertEqual(dform['new_password'].errormsg, "New password must be different from old password.")
|
||||
|
||||
def test_become_root(self):
|
||||
event = MagicMock(request=self.request)
|
||||
new_request(event) # add request.get_referrer()
|
||||
view = mod.AuthView(self.request)
|
||||
|
||||
# GET not allowed
|
||||
self.request.method = 'GET'
|
||||
self.assertRaises(HTTPForbidden, view.become_root)
|
||||
|
||||
# non-admin users also not allowed
|
||||
self.request.method = 'POST'
|
||||
self.request.is_admin = False
|
||||
self.assertRaises(HTTPForbidden, view.become_root)
|
||||
|
||||
# but admin users can become root
|
||||
self.request.is_admin = True
|
||||
self.assertNotIn('is_root', self.request.session)
|
||||
redirect = view.become_root()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
self.assertTrue(self.request.session['is_root'])
|
||||
|
||||
def test_stop_root(self):
|
||||
event = MagicMock(request=self.request)
|
||||
new_request(event) # add request.get_referrer()
|
||||
view = mod.AuthView(self.request)
|
||||
|
||||
# GET not allowed
|
||||
self.request.method = 'GET'
|
||||
self.assertRaises(HTTPForbidden, view.stop_root)
|
||||
|
||||
# non-admin users also not allowed
|
||||
self.request.method = 'POST'
|
||||
self.request.is_admin = False
|
||||
self.assertRaises(HTTPForbidden, view.stop_root)
|
||||
|
||||
# but admin users can stop being root
|
||||
# (nb. there is no check whether user is currently root)
|
||||
self.request.is_admin = True
|
||||
self.assertNotIn('is_root', self.request.session)
|
||||
redirect = view.stop_root()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
self.assertFalse(self.request.session['is_root'])
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from pyramid import testing
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
from pyramid.httpexceptions import HTTPFound, HTTPForbidden
|
||||
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttaweb.views import base
|
||||
|
@ -23,6 +23,10 @@ class TestView(TestCase):
|
|||
self.assertIs(self.view.config, self.config)
|
||||
self.assertIs(self.view.app, self.app)
|
||||
|
||||
def test_forbidden(self):
|
||||
error = self.view.forbidden()
|
||||
self.assertIsInstance(error, HTTPForbidden)
|
||||
|
||||
def test_make_form(self):
|
||||
form = self.view.make_form()
|
||||
self.assertIsInstance(form, Form)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue