Merge ~adam-collard/maas:websocket-user-change-password into maas:master

Proposed by Adam Collard
Status: Merged
Approved by: Adam Collard
Approved revision: 9c40e496b7f1aef1036b870c950010af6349f4ab
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~adam-collard/maas:websocket-user-change-password
Merge into: maas:master
Diff against target: 111 lines (+80/-1)
2 files modified
src/maasserver/websockets/handlers/tests/test_user.py (+64/-0)
src/maasserver/websockets/handlers/user.py (+16/-1)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Alberto Donato (community) Approve
Review via email: mp+392616@code.launchpad.net

Commit message

LP 1894727: Add websocket endpoint for superusers to change password

To post a comment you must log in.
Revision history for this message
Adam Collard (adam-collard) wrote :

Open question as to whether this is suitable for use by UI.

The UX right now seems to have one form for user details and passwords. This requires logic in the JS app to direct user details to one endpoint and password changes to another, multiplexing the responses and error messages (which I appreciate is non-trivial).

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

UNIT TESTS
-b websocket-user-change-password lp:~adam-collard/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: f76a8607261f8c1a7e004c92e15aad6d259fbe73

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

+1 with a comment inline

Revision history for this message
Alberto Donato (ack) :
review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b websocket-user-change-password lp:~adam-collard/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 9c40e496b7f1aef1036b870c950010af6349f4ab

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

LANDING
-b websocket-user-change-password lp:~adam-collard/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/8553/consoleText

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/maasserver/websockets/handlers/tests/test_user.py b/src/maasserver/websockets/handlers/tests/test_user.py
index 67bcd6e..d221fa2 100644
--- a/src/maasserver/websockets/handlers/tests/test_user.py
+++ b/src/maasserver/websockets/handlers/tests/test_user.py
@@ -394,3 +394,67 @@ class TestUserHandler(MAASServerTestCase):
394 )394 )
395 self.assertEqual(self.dehydrate_user(user, for_self=True), observed)395 self.assertEqual(self.dehydrate_user(user, for_self=True), observed)
396 self.assertTrue(user.check_password("newpassword"))396 self.assertTrue(user.check_password("newpassword"))
397
398 def test_change_other_users_password_as_admin(self):
399 admin_user = factory.make_admin()
400 handler = UserHandler(admin_user, {}, None)
401 user = factory.make_User()
402
403 response = handler.admin_change_password(
404 {
405 "id": user.id,
406 "password1": "newpassword",
407 "password2": "newpassword",
408 }
409 )
410 user = reload_object(user)
411
412 self.assertIsNone(response)
413 self.assertTrue(
414 user.check_password("newpassword"),
415 "Password not correctly changed",
416 )
417
418 def test_cannot_change_other_users_password_as_unprivileged(self):
419 unprivileged_user = factory.make_User()
420 handler = UserHandler(unprivileged_user, {}, None)
421 user = factory.make_User()
422
423 self.assertRaises(
424 HandlerPermissionError,
425 handler.admin_change_password,
426 {
427 "id": user.id,
428 "password1": "newpassword",
429 "password2": "newpassword",
430 },
431 )
432
433 def test_cannot_change_own_password_as_unprivileged_using_admin(self):
434 unprivileged_user = factory.make_User()
435 handler = UserHandler(unprivileged_user, {}, None)
436
437 self.assertRaises(
438 HandlerPermissionError,
439 handler.admin_change_password,
440 {
441 "id": unprivileged_user.id,
442 "password1": "newpassword",
443 "password2": "newpassword",
444 },
445 )
446
447 def test_cannot_change_other_users_password_as_admin_bad_password(self):
448 admin_user = factory.make_admin()
449 handler = UserHandler(admin_user, {}, None)
450 user = factory.make_User()
451
452 self.assertRaises(
453 HandlerValidationError,
454 handler.admin_change_password,
455 {
456 "id": user.id,
457 "password1": "foo",
458 "password2": "bar",
459 },
460 )
diff --git a/src/maasserver/websockets/handlers/user.py b/src/maasserver/websockets/handlers/user.py
index 7a12ac0..865f331 100644
--- a/src/maasserver/websockets/handlers/user.py
+++ b/src/maasserver/websockets/handlers/user.py
@@ -5,7 +5,10 @@
55
6__all__ = ["UserHandler"]6__all__ = ["UserHandler"]
77
8from django.contrib.auth.forms import PasswordChangeForm8from django.contrib.auth.forms import (
9 AdminPasswordChangeForm,
10 PasswordChangeForm,
11)
9from django.contrib.auth.models import User12from django.contrib.auth.models import User
10from django.db.models import Count13from django.db.models import Count
11from django.http import HttpRequest14from django.http import HttpRequest
@@ -51,6 +54,7 @@ class UserHandler(Handler):
51 "auth_user",54 "auth_user",
52 "mark_intro_complete",55 "mark_intro_complete",
53 "change_password",56 "change_password",
57 "admin_change_password",
54 ]58 ]
55 fields = [59 fields = [
56 "id",60 "id",
@@ -208,3 +212,14 @@ class UserHandler(Handler):
208 return self.full_dehydrate(self.user)212 return self.full_dehydrate(self.user)
209 else:213 else:
210 raise HandlerValidationError(form.errors)214 raise HandlerValidationError(form.errors)
215
216 def admin_change_password(self, params):
217 """As Admin, update another user's password."""
218 if not self.user.is_superuser:
219 raise HandlerPermissionError()
220 user = self.get_object(params)
221 form = AdminPasswordChangeForm(user=user, data=get_QueryDict(params))
222 if form.is_valid():
223 form.save()
224 else:
225 raise HandlerValidationError(form.errors)

Subscribers

People subscribed via source and target branches