feat: add first-time setup page to create admin user
This commit is contained in:
parent
bc49392140
commit
675b51cac2
6 changed files with 241 additions and 79 deletions
|
@ -1,90 +1,88 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from pyramid import testing
|
||||
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
|
||||
from tests.util import WebTestCase
|
||||
|
||||
|
||||
class TestAuthView(TestCase):
|
||||
class TestAuthView(WebTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.db.default.url': 'sqlite://',
|
||||
})
|
||||
|
||||
self.request = testing.DummyRequest(wutta_config=self.config, user=None)
|
||||
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()
|
||||
model = self.app.model
|
||||
model.Base.metadata.create_all(bind=self.config.appdb_engine)
|
||||
self.session = self.app.make_session()
|
||||
self.user = model.User(username='barney')
|
||||
self.session.add(self.user)
|
||||
auth.set_user_password(self.user, 'testpass')
|
||||
self.session.commit()
|
||||
|
||||
self.pyramid_config.set_security_policy(WuttaSecurityPolicy(db_session=self.session))
|
||||
self.pyramid_config.include('wuttaweb.views.auth')
|
||||
self.setup_web()
|
||||
self.pyramid_config.include('wuttaweb.views.common')
|
||||
|
||||
def tearDown(self):
|
||||
testing.tearDown()
|
||||
def make_view(self):
|
||||
return mod.AuthView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.auth')
|
||||
|
||||
def test_login(self):
|
||||
view = mod.AuthView(self.request)
|
||||
context = view.login()
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
||||
# until user exists, will redirect
|
||||
self.assertEqual(self.session.query(model.User).count(), 0)
|
||||
response = view.login(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# make a user
|
||||
barney = model.User(username='barney')
|
||||
auth.set_user_password(barney, 'testpass')
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
|
||||
# now since user exists, form will display
|
||||
context = view.login(session=self.session)
|
||||
self.assertIn('form', context)
|
||||
|
||||
# redirect if user already logged in
|
||||
self.request.user = self.user
|
||||
view = mod.AuthView(self.request)
|
||||
redirect = view.login(session=self.session)
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
with patch.object(self.request, 'user', new=barney):
|
||||
view = self.make_view()
|
||||
response = view.login(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# login fails w/ wrong password
|
||||
self.request.user = None
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'username': 'barney', 'password': 'WRONG'}
|
||||
view = mod.AuthView(self.request)
|
||||
view = self.make_view()
|
||||
context = view.login(session=self.session)
|
||||
self.assertIn('form', context)
|
||||
|
||||
# redirect if login succeeds
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'username': 'barney', 'password': 'testpass'}
|
||||
view = mod.AuthView(self.request)
|
||||
redirect = view.login(session=self.session)
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
view = self.make_view()
|
||||
response = view.login(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_logout(self):
|
||||
view = mod.AuthView(self.request)
|
||||
self.pyramid_config.add_route('login', '/login')
|
||||
view = self.make_view()
|
||||
self.request.session.delete = MagicMock()
|
||||
redirect = view.logout()
|
||||
response = view.logout()
|
||||
self.request.session.delete.assert_called_once_with()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_change_password(self):
|
||||
view = mod.AuthView(self.request)
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
barney = model.User(username='barney')
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
|
||||
# unauthenticated user is redirected
|
||||
redirect = view.change_password()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
|
||||
# now "login" the user, and set initial password
|
||||
self.request.user = self.user
|
||||
auth.set_user_password(self.user, 'foo')
|
||||
self.request.user = barney
|
||||
auth.set_user_password(barney, 'foo')
|
||||
self.session.commit()
|
||||
|
||||
# view should now return context w/ form
|
||||
|
@ -105,9 +103,8 @@ class TestAuthView(TestCase):
|
|||
redirect = view.change_password()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
self.session.commit()
|
||||
self.session.refresh(self.user)
|
||||
self.assertFalse(auth.check_user_password(self.user, 'foo'))
|
||||
self.assertTrue(auth.check_user_password(self.user, 'bar'))
|
||||
self.assertFalse(auth.check_user_password(barney, 'foo'))
|
||||
self.assertTrue(auth.check_user_password(barney, 'bar'))
|
||||
|
||||
# at this point 'foo' is the password, now let's submit some
|
||||
# invalid forms and make sure we get back a context w/ form
|
||||
|
@ -147,8 +144,6 @@ class TestAuthView(TestCase):
|
|||
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
|
||||
|
@ -168,8 +163,6 @@ class TestAuthView(TestCase):
|
|||
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
|
||||
|
|
|
@ -1,27 +1,85 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from pyramid import testing
|
||||
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttaweb.views import common
|
||||
from wuttaweb.views import common as mod
|
||||
from tests.util import WebTestCase
|
||||
|
||||
|
||||
class TestCommonView(TestCase):
|
||||
class TestCommonView(WebTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig()
|
||||
self.app = self.config.get_app()
|
||||
self.request = testing.DummyRequest()
|
||||
self.request.wutta_config = self.config
|
||||
self.pyramid_config = testing.setUp(request=self.request)
|
||||
def make_view(self):
|
||||
return mod.CommonView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.common')
|
||||
|
||||
def tearDown(self):
|
||||
testing.tearDown()
|
||||
|
||||
def test_home(self):
|
||||
view = common.CommonView(self.request)
|
||||
context = view.home()
|
||||
self.pyramid_config.add_route('setup', '/setup')
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
# if no users then home page will redirect
|
||||
response = view.home(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# so add a user
|
||||
user = model.User(username='foo')
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
# now we see the home page
|
||||
context = view.home(session=self.session)
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
|
||||
def test_setup(self):
|
||||
self.pyramid_config.add_route('home', '/')
|
||||
self.pyramid_config.add_route('login', '/login')
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
||||
# at first, can see the setup page
|
||||
self.assertEqual(self.session.query(model.User).count(), 0)
|
||||
context = view.setup(session=self.session)
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
|
||||
# so add a user
|
||||
user = model.User(username='foo')
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
# once user exists it will always redirect
|
||||
response = view.setup(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# delete that user
|
||||
self.session.delete(user)
|
||||
self.session.commit()
|
||||
|
||||
# so we can see the setup page again
|
||||
context = view.setup(session=self.session)
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
|
||||
# and finally, post data to create admin user
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {
|
||||
'username': 'barney',
|
||||
'__start__': 'password:mapping',
|
||||
'password': 'testpass',
|
||||
'password-confirm': 'testpass',
|
||||
'__end__': 'password:mapping',
|
||||
'first_name': "Barney",
|
||||
'last_name': "Rubble",
|
||||
}
|
||||
response = view.setup(session=self.session)
|
||||
# nb. redirects on success
|
||||
self.assertEqual(response.status_code, 302)
|
||||
barney = self.session.query(model.User).one()
|
||||
self.assertEqual(barney.username, 'barney')
|
||||
self.assertTrue(auth.check_user_password(barney, 'testpass'))
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
self.assertIn(admin, barney.roles)
|
||||
self.assertIsNotNone(barney.person)
|
||||
person = barney.person
|
||||
self.assertEqual(person.first_name, "Barney")
|
||||
self.assertEqual(person.last_name, "Rubble")
|
||||
self.assertEqual(person.full_name, "Barney Rubble")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue