Skip to content

Commit d847753

Browse files
committed
Merge pull request #203 from opdemand/56-account-cancellation
Fixed #56 -- implemented account cancellation.
2 parents 27c29af + 0d43479 commit d847753

4 files changed

Lines changed: 76 additions & 1 deletion

File tree

api/tests/auth.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,36 @@ def test_auth(self):
7878
url = '/api/providers'
7979
response = self.client.get(url)
8080
self.assertEqual(response.status_code, 200)
81+
82+
def test_cancel(self):
83+
"""Test that a registered user can cancel her account."""
84+
# test registration workflow
85+
username, password = 'newuser', 'password'
86+
first_name, last_name = 'Otto', 'Test'
87+
email = 'autotest@deis.io'
88+
submit = {
89+
'username': username,
90+
'password': password,
91+
'first_name': first_name,
92+
'last_name': last_name,
93+
'email': email,
94+
# try to abuse superuser/staff level perms
95+
'is_superuser': True,
96+
'is_staff': True,
97+
}
98+
url = '/api/auth/register'
99+
response = self.client.post(url, json.dumps(submit), content_type='application/json')
100+
self.assertEqual(response.status_code, 201)
101+
self.assertTrue(
102+
self.client.login(username=username, password=password))
103+
# test for default objects
104+
url = '/api/providers'
105+
response = self.client.get(url)
106+
self.assertEqual(response.status_code, 200)
107+
self.assertEqual(response.data['count'], len(settings.PROVIDER_MODULES))
108+
# cancel the account
109+
url = '/api/auth/cancel'
110+
response = self.client.delete(url)
111+
self.assertEqual(response.status_code, 204)
112+
self.assertFalse(
113+
self.client.login(username=username, password=password))

api/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,10 @@
289289
290290
Create a new :class:`~django.contrib.auth.models.User`.
291291
292+
.. http:delete:: /api/auth/register/
293+
294+
Destroy the logged-in :class:`~django.contrib.auth.models.User`.
295+
292296
.. http:post:: /api/auth/login
293297
294298
Authenticate for the REST framework.
@@ -407,6 +411,8 @@
407411
# authn / authz
408412
url(r'^auth/register/?',
409413
views.UserRegistrationView.as_view({'post': 'create'})),
414+
url(r'^auth/cancel/?',
415+
views.UserCancellationView.as_view({'delete': 'destroy'})),
410416
url(r'^auth/',
411417
include('rest_framework.urls', namespace='rest_framework')),
412418
url(r'^generate-api-key/',

api/views.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,18 @@ def pre_save(self, obj):
8484
obj.set_password(obj.password)
8585

8686

87+
class UserCancellationView(viewsets.GenericViewSet,
88+
viewsets.mixins.DestroyModelMixin):
89+
model = User
90+
91+
permission_classes = (permissions.IsAuthenticated,)
92+
93+
def destroy(self, request, *args, **kwargs):
94+
obj = self.request.user
95+
obj.delete()
96+
return Response(status=status.HTTP_204_NO_CONTENT)
97+
98+
8799
class OwnerViewSet(viewsets.ModelViewSet):
88100
"""Scope views to an `owner` attribute."""
89101

client/deis.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,30 @@ def auth_register(self, args):
604604
print('Registration failed', response.content)
605605
return False
606606

607+
def auth_cancel(self, args):
608+
"""
609+
Cancel and remove the current account.
610+
611+
Usage: deis auth:cancel
612+
"""
613+
controller = self._settings.get('controller')
614+
if not controller:
615+
print('Not logged in to a Deis controller')
616+
return False
617+
print('Please log in again in order to cancel this account')
618+
username = self.auth_login({'<controller>': controller})
619+
if username:
620+
confirm = raw_input("Cancel account \"{}\" at {}? (y/n) ".format(username, controller))
621+
if confirm == 'y':
622+
self._dispatch('delete', '/api/auth/cancel')
623+
self._session.cookies.clear()
624+
self._session.cookies.save()
625+
self._settings['controller'] = None
626+
self._settings.save()
627+
print('Account cancelled')
628+
else:
629+
print('Accont not changed')
630+
607631
def auth_login(self, args):
608632
"""
609633
Login by authenticating against a controller
@@ -630,7 +654,7 @@ def auth_login(self, args):
630654
self._settings['controller'] = controller
631655
self._settings.save()
632656
print("Logged in as {}".format(username))
633-
return True
657+
return username
634658
else:
635659
print('Login failed')
636660
self._session.cookies.clear()

0 commit comments

Comments
 (0)