3
0
Fork 0

feat: add first-time setup page to create admin user

This commit is contained in:
Lance Edgar 2024-08-14 18:29:08 -05:00
parent bc49392140
commit 675b51cac2
6 changed files with 241 additions and 79 deletions

View file

@ -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