launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #07207
[Merge] lp:~rvb/maas/views-bug-973215-5 into lp:maas
Raphaël Badin has proposed merging lp:~rvb/maas/views-bug-973215-5 into lp:maas with lp:~rvb/maas/views-bug-973215-4 as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #973215 in MAAS: "src/maasserver/views.py is huge."
https://bugs.launchpad.net/maas/+bug/973215
For more details, see:
https://code.launchpad.net/~rvb/maas/views-bug-973215-5/+merge/103104
This branch is the fifth (and last) in a series of branches that will refactor src/maasserver/views.py into modules in src/maasserver/views/.
This branch follows up on the work done in https://code.launchpad.net/~rvb/maas/views-bug-973215-4/+merge/103098.
It moves settings views to src/maasserver/views/settings.py. It also moves the related tests in src/maasserver/tests/test_views_settings.py.
It also moves some tests I forgot which belong to src/maasserver/tests/test_views_nodes.py.
--
https://code.launchpad.net/~rvb/maas/views-bug-973215-5/+merge/103104
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/views-bug-973215-5 into lp:maas.
=== modified file 'src/maasserver/tests/test_views.py'
--- src/maasserver/tests/test_views.py 2012-04-23 14:05:38 +0000
+++ src/maasserver/tests/test_views.py 2012-04-23 14:05:38 +0000
@@ -17,7 +17,6 @@
from xmlrpclib import Fault
from django.conf.urls.defaults import patterns
-from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.http import Http404
@@ -26,16 +25,7 @@
from lxml.html import fromstring
from maasserver import components
from maasserver.components import register_persistent_error
-from maasserver.enum import NODE_AFTER_COMMISSIONING_ACTION
from maasserver.exceptions import ExternalComponentException
-from maasserver.models import (
- Config,
- UserProfile,
- )
-from maasserver.testing import (
- get_prefixed_form_data,
- reload_object,
- )
from maasserver.testing.enum import map_enum
from maasserver.testing.factory import factory
from maasserver.testing.testcase import (
@@ -44,10 +34,7 @@
)
from maasserver.views import HelpfulDeleteView
from maasserver.views.nodes import NodeEdit
-from provisioningserver.enum import (
- POWER_TYPE_CHOICES,
- PSERV_FAULT,
- )
+from provisioningserver.enum import PSERV_FAULT
from testtools.matchers import (
Contains,
MatchesAll,
@@ -224,15 +211,6 @@
view.compose_feedback_deleted(view.obj))
-class AdminLoggedInTestCase(LoggedInTestCase):
-
- def setUp(self):
- super(AdminLoggedInTestCase, self).setUp()
- # Promote the logged-in user to admin.
- self.logged_in_user.is_superuser = True
- self.logged_in_user.save()
-
-
class MAASExceptionHandledInView(LoggedInTestCase):
def test_raised_MAASException_redirects(self):
@@ -270,268 +248,6 @@
[message.message for message in response.context['messages']])
-class AdminNodeViewsTest(AdminLoggedInTestCase):
-
- def test_admin_can_edit_nodes(self):
- node = factory.make_node(owner=factory.make_user())
- node_edit_link = reverse('node-edit', args=[node.system_id])
- params = {
- 'hostname': factory.getRandomString(),
- 'after_commissioning_action': factory.getRandomEnum(
- NODE_AFTER_COMMISSIONING_ACTION),
- 'power_type': factory.getRandomChoice(POWER_TYPE_CHOICES),
- }
- response = self.client.post(node_edit_link, params)
-
- node = reload_object(node)
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertAttributes(node, params)
-
-
-class SettingsTest(AdminLoggedInTestCase):
-
- def test_settings_list_users(self):
- # The settings page displays a list of the users with links to view,
- # delete or edit each user. Note that the link to delete the the
- # logged-in user is not display.
- [factory.make_user() for i in range(3)]
- users = UserProfile.objects.all_users()
- response = self.client.get('/settings/')
- doc = fromstring(response.content)
- tab = doc.cssselect('#users')[0]
- all_links = [elem.get('href') for elem in tab.cssselect('a')]
- # "Add a user" link.
- self.assertIn(reverse('accounts-add'), all_links)
- for user in users:
- rows = tab.cssselect('tr#%s' % user.username)
- # Only one row for the user.
- self.assertEqual(1, len(rows))
- row = rows[0]
- links = [elem.get('href') for elem in row.cssselect('a')]
- # The username is shown...
- self.assertSequenceEqual(
- [user.username],
- [link.text.strip() for link in row.cssselect('a.user')])
- # ...with a link to view the user's profile.
- self.assertSequenceEqual(
- [reverse('accounts-view', args=[user.username])],
- [link.get('href') for link in row.cssselect('a.user')])
- # A link to edit the user is shown.
- self.assertIn(
- reverse('accounts-edit', args=[user.username]), links)
- if user != self.logged_in_user:
- # A link to delete the user is shown.
- self.assertIn(
- reverse('accounts-del', args=[user.username]), links)
- else:
- # No link to delete the user is shown if the user is the
- # logged-in user.
- self.assertNotIn(
- reverse('accounts-del', args=[user.username]), links)
-
- def test_settings_maas_and_network_POST(self):
- new_name = factory.getRandomString()
- new_domain = factory.getRandomString()
- response = self.client.post(
- '/settings/',
- get_prefixed_form_data(
- prefix='maas_and_network',
- data={
- 'maas_name': new_name,
- 'enlistment_domain': new_domain,
- }))
-
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertEqual(new_name, Config.objects.get_config('maas_name'))
- self.assertEqual(
- new_domain, Config.objects.get_config('enlistment_domain'))
-
- def test_settings_commissioning_POST(self):
- new_after_commissioning = factory.getRandomEnum(
- NODE_AFTER_COMMISSIONING_ACTION)
- new_check_compatibility = factory.getRandomBoolean()
- response = self.client.post(
- '/settings/',
- get_prefixed_form_data(
- prefix='commissioning',
- data={
- 'after_commissioning': new_after_commissioning,
- 'check_compatibility': new_check_compatibility,
- }))
-
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertEqual(
- new_after_commissioning,
- Config.objects.get_config('after_commissioning'))
- self.assertEqual(
- new_check_compatibility,
- Config.objects.get_config('check_compatibility'))
-
- def test_settings_ubuntu_POST(self):
- new_fallback_master_archive = factory.getRandomBoolean()
- new_keep_mirror_list_uptodate = factory.getRandomBoolean()
- new_fetch_new_releases = factory.getRandomBoolean()
- choices = Config.objects.get_config('update_from_choice')
- new_update_from = factory.getRandomChoice(choices)
- response = self.client.post(
- '/settings/',
- get_prefixed_form_data(
- prefix='ubuntu',
- data={
- 'fallback_master_archive': new_fallback_master_archive,
- 'keep_mirror_list_uptodate': new_keep_mirror_list_uptodate,
- 'fetch_new_releases': new_fetch_new_releases,
- 'update_from': new_update_from,
- }))
-
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertEqual(
- new_fallback_master_archive,
- Config.objects.get_config('fallback_master_archive'))
- self.assertEqual(
- new_keep_mirror_list_uptodate,
- Config.objects.get_config('keep_mirror_list_uptodate'))
- self.assertEqual(
- new_fetch_new_releases,
- Config.objects.get_config('fetch_new_releases'))
- self.assertEqual(
- new_update_from, Config.objects.get_config('update_from'))
-
- def test_settings_add_archive_POST(self):
- choices = Config.objects.get_config('update_from_choice')
- response = self.client.post(
- '/settings/archives/add/',
- data={'archive_name': 'my.hostname.com'}
- )
- new_choices = Config.objects.get_config('update_from_choice')
-
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertItemsEqual(
- choices + [['my.hostname.com', 'my.hostname.com']],
- new_choices)
-
-
-# Settable attributes on User.
-user_attributes = [
- 'email',
- 'is_superuser',
- 'last_name',
- 'username',
- ]
-
-
-def make_user_attribute_params(user):
- """Compose a dict of form parameters for a user's account data.
-
- By default, each attribute in the dict maps to the user's existing value
- for that atrribute.
- """
- return {
- attr: getattr(user, attr)
- for attr in user_attributes
- }
-
-
-def make_password_params(password):
- """Create a dict of parameters for setting a given password."""
- return {
- 'password1': password,
- 'password2': password,
- }
-
-
-def subset_dict(input_dict, keys_subset):
- """Return a subset of `input_dict` restricted to `keys_subset`.
-
- All keys in `keys_subset` must be in `input_dict`.
- """
- return {key: input_dict[key] for key in keys_subset}
-
-
-class UserManagementTest(AdminLoggedInTestCase):
-
- def test_add_user_POST(self):
- params = {
- 'username': factory.getRandomString(),
- 'last_name': factory.getRandomString(30),
- 'email': factory.getRandomEmail(),
- 'is_superuser': factory.getRandomBoolean(),
- }
- password = factory.getRandomString()
- params.update(make_password_params(password))
-
- response = self.client.post(reverse('accounts-add'), params)
- self.assertEqual(httplib.FOUND, response.status_code)
- user = User.objects.get(username=params['username'])
- self.assertAttributes(user, subset_dict(params, user_attributes))
- self.assertTrue(user.check_password(password))
-
- def test_edit_user_POST_profile_updates_attributes(self):
- user = factory.make_user()
- params = make_user_attribute_params(user)
- params.update({
- 'last_name': 'Newname-%s' % factory.getRandomString(),
- 'email': 'new-%s@xxxxxxxxxxx' % factory.getRandomString(),
- 'is_superuser': True,
- 'username': 'newname-%s' % factory.getRandomString(),
- })
-
- response = self.client.post(
- reverse('accounts-edit', args=[user.username]),
- get_prefixed_form_data('profile', params))
-
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertAttributes(
- reload_object(user), subset_dict(params, user_attributes))
-
- def test_edit_user_POST_updates_password(self):
- user = factory.make_user()
- new_password = factory.getRandomString()
- params = make_password_params(new_password)
- response = self.client.post(
- reverse('accounts-edit', args=[user.username]),
- get_prefixed_form_data('password', params))
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertTrue(reload_object(user).check_password(new_password))
-
- def test_delete_user_GET(self):
- # The user delete page displays a confirmation page with a form.
- user = factory.make_user()
- del_link = reverse('accounts-del', args=[user.username])
- response = self.client.get(del_link)
- doc = fromstring(response.content)
- confirmation_message = (
- 'Are you sure you want to delete the user "%s"?' %
- user.username)
- self.assertSequenceEqual(
- [confirmation_message],
- [elem.text.strip() for elem in doc.cssselect('h2')])
- # The page features a form that submits to itself.
- self.assertSequenceEqual(
- ['.'],
- [elem.get('action').strip() for elem in doc.cssselect(
- '#content form')])
-
- def test_delete_user_POST(self):
- # A POST request to the user delete finally deletes the user.
- user = factory.make_user()
- user_id = user.id
- del_link = reverse('accounts-del', args=[user.username])
- response = self.client.post(del_link, {'post': 'yes'})
- self.assertEqual(httplib.FOUND, response.status_code)
- self.assertItemsEqual([], User.objects.filter(id=user_id))
-
- def test_view_user(self):
- # The user page feature the basic information about the user.
- user = factory.make_user()
- del_link = reverse('accounts-view', args=[user.username])
- response = self.client.get(del_link)
- doc = fromstring(response.content)
- content_text = doc.cssselect('#content')[0].text_content()
- self.assertIn(user.username, content_text)
- self.assertIn(user.email, content_text)
-
-
class PermanentErrorDisplayTest(LoggedInTestCase):
def test_permanent_error_displayed(self):
=== modified file 'src/maasserver/tests/test_views_nodes.py'
--- src/maasserver/tests/test_views_nodes.py 2012-04-23 14:05:38 +0000
+++ src/maasserver/tests/test_views_nodes.py 2012-04-23 14:05:38 +0000
@@ -32,12 +32,14 @@
from maasserver.testing.enum import map_enum
from maasserver.testing.factory import factory
from maasserver.testing.testcase import (
+ AdminLoggedInTestCase,
LoggedInTestCase,
TestCase,
)
from maasserver.views import nodes as nodes_views
from maasserver.views.nodes import get_longpoll_context
from maastesting.rabbit import uses_rabbit_fixture
+from provisioningserver.enum import POWER_TYPE_CHOICES
class NodeViewsTest(LoggedInTestCase):
@@ -299,6 +301,24 @@
[message.message for message in response.context['messages']])
+class AdminNodeViewsTest(AdminLoggedInTestCase):
+
+ def test_admin_can_edit_nodes(self):
+ node = factory.make_node(owner=factory.make_user())
+ node_edit_link = reverse('node-edit', args=[node.system_id])
+ params = {
+ 'hostname': factory.getRandomString(),
+ 'after_commissioning_action': factory.getRandomEnum(
+ NODE_AFTER_COMMISSIONING_ACTION),
+ 'power_type': factory.getRandomChoice(POWER_TYPE_CHOICES),
+ }
+ response = self.client.post(node_edit_link, params)
+
+ node = reload_object(node)
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertAttributes(node, params)
+
+
class TestGetLongpollContext(TestCase):
def test_get_longpoll_context_empty_if_rabbitmq_publish_is_none(self):
=== added file 'src/maasserver/tests/test_views_settings.py'
--- src/maasserver/tests/test_views_settings.py 1970-01-01 00:00:00 +0000
+++ src/maasserver/tests/test_views_settings.py 2012-04-23 14:05:38 +0000
@@ -0,0 +1,274 @@
+# Copyright 2012 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test maasserver settings views."""
+
+from __future__ import (
+ absolute_import,
+ print_function,
+ unicode_literals,
+ )
+
+__metaclass__ = type
+__all__ = []
+
+import httplib
+
+from django.contrib.auth.models import User
+from django.core.urlresolvers import reverse
+from lxml.html import fromstring
+from maasserver.enum import NODE_AFTER_COMMISSIONING_ACTION
+from maasserver.models import (
+ Config,
+ UserProfile,
+ )
+from maasserver.testing import (
+ get_prefixed_form_data,
+ reload_object,
+ )
+from maasserver.testing.factory import factory
+from maasserver.testing.testcase import AdminLoggedInTestCase
+
+
+class SettingsTest(AdminLoggedInTestCase):
+
+ def test_settings_list_users(self):
+ # The settings page displays a list of the users with links to view,
+ # delete or edit each user. Note that the link to delete the the
+ # logged-in user is not display.
+ [factory.make_user() for i in range(3)]
+ users = UserProfile.objects.all_users()
+ response = self.client.get('/settings/')
+ doc = fromstring(response.content)
+ tab = doc.cssselect('#users')[0]
+ all_links = [elem.get('href') for elem in tab.cssselect('a')]
+ # "Add a user" link.
+ self.assertIn(reverse('accounts-add'), all_links)
+ for user in users:
+ rows = tab.cssselect('tr#%s' % user.username)
+ # Only one row for the user.
+ self.assertEqual(1, len(rows))
+ row = rows[0]
+ links = [elem.get('href') for elem in row.cssselect('a')]
+ # The username is shown...
+ self.assertSequenceEqual(
+ [user.username],
+ [link.text.strip() for link in row.cssselect('a.user')])
+ # ...with a link to view the user's profile.
+ self.assertSequenceEqual(
+ [reverse('accounts-view', args=[user.username])],
+ [link.get('href') for link in row.cssselect('a.user')])
+ # A link to edit the user is shown.
+ self.assertIn(
+ reverse('accounts-edit', args=[user.username]), links)
+ if user != self.logged_in_user:
+ # A link to delete the user is shown.
+ self.assertIn(
+ reverse('accounts-del', args=[user.username]), links)
+ else:
+ # No link to delete the user is shown if the user is the
+ # logged-in user.
+ self.assertNotIn(
+ reverse('accounts-del', args=[user.username]), links)
+
+ def test_settings_maas_and_network_POST(self):
+ new_name = factory.getRandomString()
+ new_domain = factory.getRandomString()
+ response = self.client.post(
+ '/settings/',
+ get_prefixed_form_data(
+ prefix='maas_and_network',
+ data={
+ 'maas_name': new_name,
+ 'enlistment_domain': new_domain,
+ }))
+
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertEqual(new_name, Config.objects.get_config('maas_name'))
+ self.assertEqual(
+ new_domain, Config.objects.get_config('enlistment_domain'))
+
+ def test_settings_commissioning_POST(self):
+ new_after_commissioning = factory.getRandomEnum(
+ NODE_AFTER_COMMISSIONING_ACTION)
+ new_check_compatibility = factory.getRandomBoolean()
+ response = self.client.post(
+ '/settings/',
+ get_prefixed_form_data(
+ prefix='commissioning',
+ data={
+ 'after_commissioning': new_after_commissioning,
+ 'check_compatibility': new_check_compatibility,
+ }))
+
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertEqual(
+ new_after_commissioning,
+ Config.objects.get_config('after_commissioning'))
+ self.assertEqual(
+ new_check_compatibility,
+ Config.objects.get_config('check_compatibility'))
+
+ def test_settings_ubuntu_POST(self):
+ new_fallback_master_archive = factory.getRandomBoolean()
+ new_keep_mirror_list_uptodate = factory.getRandomBoolean()
+ new_fetch_new_releases = factory.getRandomBoolean()
+ choices = Config.objects.get_config('update_from_choice')
+ new_update_from = factory.getRandomChoice(choices)
+ response = self.client.post(
+ '/settings/',
+ get_prefixed_form_data(
+ prefix='ubuntu',
+ data={
+ 'fallback_master_archive': new_fallback_master_archive,
+ 'keep_mirror_list_uptodate': new_keep_mirror_list_uptodate,
+ 'fetch_new_releases': new_fetch_new_releases,
+ 'update_from': new_update_from,
+ }))
+
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertEqual(
+ new_fallback_master_archive,
+ Config.objects.get_config('fallback_master_archive'))
+ self.assertEqual(
+ new_keep_mirror_list_uptodate,
+ Config.objects.get_config('keep_mirror_list_uptodate'))
+ self.assertEqual(
+ new_fetch_new_releases,
+ Config.objects.get_config('fetch_new_releases'))
+ self.assertEqual(
+ new_update_from, Config.objects.get_config('update_from'))
+
+ def test_settings_add_archive_POST(self):
+ choices = Config.objects.get_config('update_from_choice')
+ response = self.client.post(
+ '/settings/archives/add/',
+ data={'archive_name': 'my.hostname.com'}
+ )
+ new_choices = Config.objects.get_config('update_from_choice')
+
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertItemsEqual(
+ choices + [['my.hostname.com', 'my.hostname.com']],
+ new_choices)
+
+
+# Settable attributes on User.
+user_attributes = [
+ 'email',
+ 'is_superuser',
+ 'last_name',
+ 'username',
+ ]
+
+
+def make_user_attribute_params(user):
+ """Compose a dict of form parameters for a user's account data.
+
+ By default, each attribute in the dict maps to the user's existing value
+ for that atrribute.
+ """
+ return {
+ attr: getattr(user, attr)
+ for attr in user_attributes
+ }
+
+
+def make_password_params(password):
+ """Create a dict of parameters for setting a given password."""
+ return {
+ 'password1': password,
+ 'password2': password,
+ }
+
+
+def subset_dict(input_dict, keys_subset):
+ """Return a subset of `input_dict` restricted to `keys_subset`.
+
+ All keys in `keys_subset` must be in `input_dict`.
+ """
+ return {key: input_dict[key] for key in keys_subset}
+
+
+class UserManagementTest(AdminLoggedInTestCase):
+
+ def test_add_user_POST(self):
+ params = {
+ 'username': factory.getRandomString(),
+ 'last_name': factory.getRandomString(30),
+ 'email': factory.getRandomEmail(),
+ 'is_superuser': factory.getRandomBoolean(),
+ }
+ password = factory.getRandomString()
+ params.update(make_password_params(password))
+
+ response = self.client.post(reverse('accounts-add'), params)
+ self.assertEqual(httplib.FOUND, response.status_code)
+ user = User.objects.get(username=params['username'])
+ self.assertAttributes(user, subset_dict(params, user_attributes))
+ self.assertTrue(user.check_password(password))
+
+ def test_edit_user_POST_profile_updates_attributes(self):
+ user = factory.make_user()
+ params = make_user_attribute_params(user)
+ params.update({
+ 'last_name': 'Newname-%s' % factory.getRandomString(),
+ 'email': 'new-%s@xxxxxxxxxxx' % factory.getRandomString(),
+ 'is_superuser': True,
+ 'username': 'newname-%s' % factory.getRandomString(),
+ })
+
+ response = self.client.post(
+ reverse('accounts-edit', args=[user.username]),
+ get_prefixed_form_data('profile', params))
+
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertAttributes(
+ reload_object(user), subset_dict(params, user_attributes))
+
+ def test_edit_user_POST_updates_password(self):
+ user = factory.make_user()
+ new_password = factory.getRandomString()
+ params = make_password_params(new_password)
+ response = self.client.post(
+ reverse('accounts-edit', args=[user.username]),
+ get_prefixed_form_data('password', params))
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertTrue(reload_object(user).check_password(new_password))
+
+ def test_delete_user_GET(self):
+ # The user delete page displays a confirmation page with a form.
+ user = factory.make_user()
+ del_link = reverse('accounts-del', args=[user.username])
+ response = self.client.get(del_link)
+ doc = fromstring(response.content)
+ confirmation_message = (
+ 'Are you sure you want to delete the user "%s"?' %
+ user.username)
+ self.assertSequenceEqual(
+ [confirmation_message],
+ [elem.text.strip() for elem in doc.cssselect('h2')])
+ # The page features a form that submits to itself.
+ self.assertSequenceEqual(
+ ['.'],
+ [elem.get('action').strip() for elem in doc.cssselect(
+ '#content form')])
+
+ def test_delete_user_POST(self):
+ # A POST request to the user delete finally deletes the user.
+ user = factory.make_user()
+ user_id = user.id
+ del_link = reverse('accounts-del', args=[user.username])
+ response = self.client.post(del_link, {'post': 'yes'})
+ self.assertEqual(httplib.FOUND, response.status_code)
+ self.assertItemsEqual([], User.objects.filter(id=user_id))
+
+ def test_view_user(self):
+ # The user page feature the basic information about the user.
+ user = factory.make_user()
+ del_link = reverse('accounts-view', args=[user.username])
+ response = self.client.get(del_link)
+ doc = fromstring(response.content)
+ content_text = doc.cssselect('#content')[0].text_content()
+ self.assertIn(user.username, content_text)
+ self.assertIn(user.email, content_text)
=== modified file 'src/maasserver/urls.py'
--- src/maasserver/urls.py 2012-04-23 14:05:38 +0000
+++ src/maasserver/urls.py 2012-04-23 14:05:38 +0000
@@ -27,14 +27,6 @@
)
from maasserver.maasavahi import setup_maas_avahi_service
from maasserver.models import Node
-from maasserver.views import (
- AccountsAdd,
- AccountsDelete,
- AccountsEdit,
- AccountsView,
- settings,
- settings_add_archive,
- )
from maasserver.views.account import (
login,
logout,
@@ -51,6 +43,14 @@
SSHKeyDeleteView,
userprefsview,
)
+from maasserver.views.settings import (
+ AccountsAdd,
+ AccountsDelete,
+ AccountsEdit,
+ AccountsView,
+ settings,
+ settings_add_archive,
+ )
def adminurl(regexp, view, *args, **kwargs):
=== modified file 'src/maasserver/views/__init__.py'
--- src/maasserver/views/__init__.py 2012-04-23 14:05:38 +0000
+++ src/maasserver/views/__init__.py 2012-04-23 14:05:38 +0000
@@ -11,8 +11,8 @@
__metaclass__ = type
__all__ = [
- "AccountsAdd",
- "AccountsDelete",
+ "HelpfulDeleteView",
+ "process_form",
"AccountsEdit",
"AccountsView",
"settings",
@@ -25,36 +25,11 @@
)
from django.contrib import messages
-from django.contrib.auth.forms import AdminPasswordChangeForm
-from django.contrib.auth.models import User
-from django.core.urlresolvers import reverse
from django.http import (
Http404,
HttpResponseRedirect,
)
-from django.shortcuts import (
- get_object_or_404,
- render_to_response,
- )
-from django.template import RequestContext
-from django.views.generic import (
- CreateView,
- DeleteView,
- DetailView,
- )
-from django.views.generic.base import TemplateView
-from django.views.generic.detail import SingleObjectTemplateResponseMixin
-from django.views.generic.edit import ModelFormMixin
-from maasserver.exceptions import CannotDeleteUserException
-from maasserver.forms import (
- AddArchiveForm,
- CommissioningForm,
- EditUserForm,
- MAASAndNetworkForm,
- NewUserCreationForm,
- UbuntuForm,
- )
-from maasserver.models import UserProfile
+from django.views.generic import DeleteView
class HelpfulDeleteView(DeleteView):
@@ -172,153 +147,3 @@
else:
form = form_class(prefix=prefix, **form_kwargs)
return form, None
-
-
-class AccountsView(DetailView):
- """Read-only view of user's account information."""
-
- template_name = 'maasserver/user_view.html'
-
- context_object_name = 'view_user'
-
- def get_object(self):
- username = self.kwargs.get('username', None)
- user = get_object_or_404(User, username=username)
- return user
-
-
-class AccountsAdd(CreateView):
- """Add-user view."""
-
- form_class = NewUserCreationForm
-
- template_name = 'maasserver/user_add.html'
-
- context_object_name = 'new_user'
-
- def get_success_url(self):
- return reverse('settings')
-
- def form_valid(self, form):
- messages.info(self.request, "User added.")
- return super(AccountsAdd, self).form_valid(form)
-
-
-class AccountsDelete(DeleteView):
-
- template_name = 'maasserver/user_confirm_delete.html'
- context_object_name = 'user_to_delete'
-
- def get_object(self):
- username = self.kwargs.get('username', None)
- user = get_object_or_404(User, username=username)
- return user.get_profile()
-
- def get_next_url(self):
- return reverse('settings')
-
- def delete(self, request, *args, **kwargs):
- profile = self.get_object()
- username = profile.user.username
- try:
- profile.delete()
- messages.info(request, "User %s deleted." % username)
- except CannotDeleteUserException as e:
- messages.info(request, unicode(e))
- return HttpResponseRedirect(self.get_next_url())
-
-
-class AccountsEdit(TemplateView, ModelFormMixin,
- SingleObjectTemplateResponseMixin):
-
- model = User
- template_name = 'maasserver/user_edit.html'
-
- def get_object(self):
- username = self.kwargs.get('username', None)
- return get_object_or_404(User, username=username)
-
- def respond(self, request, profile_form, password_form):
- """Generate a response."""
- return self.render_to_response({
- 'profile_form': profile_form,
- 'password_form': password_form,
- })
-
- def get(self, request, *args, **kwargs):
- """Called by `TemplateView`: handle a GET request."""
- self.object = user = self.get_object()
- profile_form = EditUserForm(instance=user, prefix='profile')
- password_form = AdminPasswordChangeForm(user=user, prefix='password')
- return self.respond(request, profile_form, password_form)
-
- def post(self, request, *args, **kwargs):
- """Called by `TemplateView`: handle a POST request."""
- self.object = user = self.get_object()
- next_page = reverse('settings')
-
- # Process the profile-editing form, if that's what was submitted.
- profile_form, response = process_form(
- request, EditUserForm, next_page, 'profile', "Profile updated.",
- {'instance': user})
- if response is not None:
- return response
-
- # Process the password change form, if that's what was submitted.
- password_form, response = process_form(
- request, AdminPasswordChangeForm, next_page, 'password',
- "Password updated.", {'user': user})
- if response is not None:
- return response
-
- return self.respond(request, profile_form, password_form)
-
-
-def settings(request):
- user_list = UserProfile.objects.all_users().order_by('username')
- # Process the MAAS & network form.
- maas_and_network_form, response = process_form(
- request, MAASAndNetworkForm, reverse('settings'), 'maas_and_network',
- "Configuration updated.")
- if response is not None:
- return response
-
- # Process the Commissioning form.
- commissioning_form, response = process_form(
- request, CommissioningForm, reverse('settings'), 'commissioning',
- "Configuration updated.")
- if response is not None:
- return response
-
- # Process the Ubuntu form.
- ubuntu_form, response = process_form(
- request, UbuntuForm, reverse('settings'), 'ubuntu',
- "Configuration updated.")
- if response is not None:
- return response
-
- return render_to_response(
- 'maasserver/settings.html',
- {
- 'user_list': user_list,
- 'maas_and_network_form': maas_and_network_form,
- 'commissioning_form': commissioning_form,
- 'ubuntu_form': ubuntu_form,
- },
- context_instance=RequestContext(request))
-
-
-def settings_add_archive(request):
- if request.method == 'POST':
- form = AddArchiveForm(request.POST)
- if form.is_valid():
- form.save()
- messages.info(request, "Archive added.")
- return HttpResponseRedirect(reverse('settings'))
- else:
- form = AddArchiveForm()
-
- return render_to_response(
- 'maasserver/settings_add_archive.html',
- {'form': form},
- context_instance=RequestContext(request))
=== added file 'src/maasserver/views/settings.py'
--- src/maasserver/views/settings.py 1970-01-01 00:00:00 +0000
+++ src/maasserver/views/settings.py 2012-04-23 14:05:38 +0000
@@ -0,0 +1,200 @@
+# Copyright 2012 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Settings views."""
+
+from __future__ import (
+ absolute_import,
+ print_function,
+ unicode_literals,
+ )
+
+__metaclass__ = type
+__all__ = [
+ "AccountsAdd",
+ "AccountsDelete",
+ "AccountsEdit",
+ "AccountsView",
+ "settings",
+ "settings_add_archive",
+ ]
+
+from django.contrib import messages
+from django.contrib.auth.forms import AdminPasswordChangeForm
+from django.contrib.auth.models import User
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect
+from django.shortcuts import (
+ get_object_or_404,
+ render_to_response,
+ )
+from django.template import RequestContext
+from django.views.generic import (
+ CreateView,
+ DeleteView,
+ DetailView,
+ )
+from django.views.generic.base import TemplateView
+from django.views.generic.detail import SingleObjectTemplateResponseMixin
+from django.views.generic.edit import ModelFormMixin
+from maasserver.exceptions import CannotDeleteUserException
+from maasserver.forms import (
+ AddArchiveForm,
+ CommissioningForm,
+ EditUserForm,
+ MAASAndNetworkForm,
+ NewUserCreationForm,
+ UbuntuForm,
+ )
+from maasserver.models import UserProfile
+from maasserver.views import process_form
+
+
+class AccountsView(DetailView):
+ """Read-only view of user's account information."""
+
+ template_name = 'maasserver/user_view.html'
+
+ context_object_name = 'view_user'
+
+ def get_object(self):
+ username = self.kwargs.get('username', None)
+ user = get_object_or_404(User, username=username)
+ return user
+
+
+class AccountsAdd(CreateView):
+ """Add-user view."""
+
+ form_class = NewUserCreationForm
+
+ template_name = 'maasserver/user_add.html'
+
+ context_object_name = 'new_user'
+
+ def get_success_url(self):
+ return reverse('settings')
+
+ def form_valid(self, form):
+ messages.info(self.request, "User added.")
+ return super(AccountsAdd, self).form_valid(form)
+
+
+class AccountsDelete(DeleteView):
+
+ template_name = 'maasserver/user_confirm_delete.html'
+ context_object_name = 'user_to_delete'
+
+ def get_object(self):
+ username = self.kwargs.get('username', None)
+ user = get_object_or_404(User, username=username)
+ return user.get_profile()
+
+ def get_next_url(self):
+ return reverse('settings')
+
+ def delete(self, request, *args, **kwargs):
+ profile = self.get_object()
+ username = profile.user.username
+ try:
+ profile.delete()
+ messages.info(request, "User %s deleted." % username)
+ except CannotDeleteUserException as e:
+ messages.info(request, unicode(e))
+ return HttpResponseRedirect(self.get_next_url())
+
+
+class AccountsEdit(TemplateView, ModelFormMixin,
+ SingleObjectTemplateResponseMixin):
+
+ model = User
+ template_name = 'maasserver/user_edit.html'
+
+ def get_object(self):
+ username = self.kwargs.get('username', None)
+ return get_object_or_404(User, username=username)
+
+ def respond(self, request, profile_form, password_form):
+ """Generate a response."""
+ return self.render_to_response({
+ 'profile_form': profile_form,
+ 'password_form': password_form,
+ })
+
+ def get(self, request, *args, **kwargs):
+ """Called by `TemplateView`: handle a GET request."""
+ self.object = user = self.get_object()
+ profile_form = EditUserForm(instance=user, prefix='profile')
+ password_form = AdminPasswordChangeForm(user=user, prefix='password')
+ return self.respond(request, profile_form, password_form)
+
+ def post(self, request, *args, **kwargs):
+ """Called by `TemplateView`: handle a POST request."""
+ self.object = user = self.get_object()
+ next_page = reverse('settings')
+
+ # Process the profile-editing form, if that's what was submitted.
+ profile_form, response = process_form(
+ request, EditUserForm, next_page, 'profile', "Profile updated.",
+ {'instance': user})
+ if response is not None:
+ return response
+
+ # Process the password change form, if that's what was submitted.
+ password_form, response = process_form(
+ request, AdminPasswordChangeForm, next_page, 'password',
+ "Password updated.", {'user': user})
+ if response is not None:
+ return response
+
+ return self.respond(request, profile_form, password_form)
+
+
+def settings(request):
+ user_list = UserProfile.objects.all_users().order_by('username')
+ # Process the MAAS & network form.
+ maas_and_network_form, response = process_form(
+ request, MAASAndNetworkForm, reverse('settings'), 'maas_and_network',
+ "Configuration updated.")
+ if response is not None:
+ return response
+
+ # Process the Commissioning form.
+ commissioning_form, response = process_form(
+ request, CommissioningForm, reverse('settings'), 'commissioning',
+ "Configuration updated.")
+ if response is not None:
+ return response
+
+ # Process the Ubuntu form.
+ ubuntu_form, response = process_form(
+ request, UbuntuForm, reverse('settings'), 'ubuntu',
+ "Configuration updated.")
+ if response is not None:
+ return response
+
+ return render_to_response(
+ 'maasserver/settings.html',
+ {
+ 'user_list': user_list,
+ 'maas_and_network_form': maas_and_network_form,
+ 'commissioning_form': commissioning_form,
+ 'ubuntu_form': ubuntu_form,
+ },
+ context_instance=RequestContext(request))
+
+
+def settings_add_archive(request):
+ if request.method == 'POST':
+ form = AddArchiveForm(request.POST)
+ if form.is_valid():
+ form.save()
+ messages.info(request, "Archive added.")
+ return HttpResponseRedirect(reverse('settings'))
+ else:
+ form = AddArchiveForm()
+
+ return render_to_response(
+ 'maasserver/settings_add_archive.html',
+ {'form': form},
+ context_instance=RequestContext(request))