Merge ~vtapia/maas:lp1894727-28 into maas:2.8

Proposed by Victor Tapia
Status: Merged
Approved by: Adam Collard
Approved revision: 41737a6fdf7ff6ff8bb89db00b082755b7c1e407
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~vtapia/maas:lp1894727-28
Merge into: maas:2.8
Diff against target: 107 lines (+76/-1)
2 files modified
src/maasserver/websockets/handlers/tests/test_user.py (+60/-0)
src/maasserver/websockets/handlers/user.py (+16/-1)
Reviewer Review Type Date Requested Status
Adam Collard (community) Approve
MAAS Lander Approve
Review via email: mp+397131@code.launchpad.net

Commit message

LP 1894727: Add websocket endpoint for superusers to change password

Description of the change

Backport of commit 839b79338aa10b81af55047f857cbc7499c9c29b in master

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp1894727-28 lp:~vtapia/maas/+git/maas into -b 2.8 lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/9119/console
COMMIT: 73ffa6762403f41186e41ed006717ce555b895ce

review: Needs Fixing
~vtapia/maas:lp1894727-28 updated
41737a6... by Victor Tapia

Fix test format

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp1894727-28 lp:~vtapia/maas/+git/maas into -b 2.8 lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 41737a6fdf7ff6ff8bb89db00b082755b7c1e407

review: Approve
Revision history for this message
Adam Collard (adam-collard) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/websockets/handlers/tests/test_user.py b/src/maasserver/websockets/handlers/tests/test_user.py
2index f62c79c..3311922 100644
3--- a/src/maasserver/websockets/handlers/tests/test_user.py
4+++ b/src/maasserver/websockets/handlers/tests/test_user.py
5@@ -396,3 +396,63 @@ class TestUserHandler(MAASServerTestCase):
6 )
7 self.assertEqual(self.dehydrate_user(user, for_self=True), observed)
8 self.assertTrue(user.check_password("newpassword"))
9+
10+ def test_change_other_users_password_as_admin(self):
11+ admin_user = factory.make_admin()
12+ handler = UserHandler(admin_user, {}, None)
13+ user = factory.make_User()
14+
15+ response = handler.admin_change_password(
16+ {
17+ "id": user.id,
18+ "password1": "newpassword",
19+ "password2": "newpassword",
20+ }
21+ )
22+ user = reload_object(user)
23+
24+ self.assertIsNone(response)
25+ self.assertTrue(
26+ user.check_password("newpassword"),
27+ "Password not correctly changed",
28+ )
29+
30+ def test_cannot_change_other_users_password_as_unprivileged(self):
31+ unprivileged_user = factory.make_User()
32+ handler = UserHandler(unprivileged_user, {}, None)
33+ user = factory.make_User()
34+
35+ self.assertRaises(
36+ HandlerPermissionError,
37+ handler.admin_change_password,
38+ {
39+ "id": user.id,
40+ "password1": "newpassword",
41+ "password2": "newpassword",
42+ },
43+ )
44+
45+ def test_cannot_change_own_password_as_unprivileged_using_admin(self):
46+ unprivileged_user = factory.make_User()
47+ handler = UserHandler(unprivileged_user, {}, None)
48+
49+ self.assertRaises(
50+ HandlerPermissionError,
51+ handler.admin_change_password,
52+ {
53+ "id": unprivileged_user.id,
54+ "password1": "newpassword",
55+ "password2": "newpassword",
56+ },
57+ )
58+
59+ def test_cannot_change_other_users_password_as_admin_bad_password(self):
60+ admin_user = factory.make_admin()
61+ handler = UserHandler(admin_user, {}, None)
62+ user = factory.make_User()
63+
64+ self.assertRaises(
65+ HandlerValidationError,
66+ handler.admin_change_password,
67+ {"id": user.id, "password1": "foo", "password2": "bar"},
68+ )
69diff --git a/src/maasserver/websockets/handlers/user.py b/src/maasserver/websockets/handlers/user.py
70index cba0ce6..7109aed 100644
71--- a/src/maasserver/websockets/handlers/user.py
72+++ b/src/maasserver/websockets/handlers/user.py
73@@ -5,7 +5,10 @@
74
75 __all__ = ["UserHandler"]
76
77-from django.contrib.auth.forms import PasswordChangeForm
78+from django.contrib.auth.forms import (
79+ AdminPasswordChangeForm,
80+ PasswordChangeForm,
81+)
82 from django.contrib.auth.models import User
83 from django.db.models import Count
84 from django.http import HttpRequest
85@@ -51,6 +54,7 @@ class UserHandler(Handler):
86 "auth_user",
87 "mark_intro_complete",
88 "change_password",
89+ "admin_change_password",
90 ]
91 fields = [
92 "id",
93@@ -208,3 +212,14 @@ class UserHandler(Handler):
94 return self.full_dehydrate(self.user)
95 else:
96 raise HandlerValidationError(form.errors)
97+
98+ def admin_change_password(self, params):
99+ """As Admin, update another user's password."""
100+ if not self.user.is_superuser:
101+ raise HandlerPermissionError()
102+ user = self.get_object(params)
103+ form = AdminPasswordChangeForm(user=user, data=get_QueryDict(params))
104+ if form.is_valid():
105+ form.save()
106+ else:
107+ raise HandlerValidationError(form.errors)

Subscribers

People subscribed via source and target branches