mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-19 12:49:01 +02:00
Implement "delete account" function
Make it possible for users to delete their own account and all associated information from the database, should they decide they no longer wish to use it. (I checked the implications of doing this on our model structure - anything with a foreign key to user is safe to delete with the exception of RRS MaintenancePlan.admin which I needed to change on_delete for so that it doesn't get deleted with the user). Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
parent
23194fc5d4
commit
2c8f979f9c
|
@ -4,9 +4,12 @@
|
|||
#
|
||||
# Licensed under the MIT license, see COPYING.MIT for details
|
||||
|
||||
from django import forms
|
||||
from captcha.fields import CaptchaField
|
||||
from registration.forms import RegistrationForm
|
||||
from django.contrib.auth.forms import PasswordResetForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.hashers import check_password
|
||||
|
||||
|
||||
class CaptchaRegistrationForm(RegistrationForm):
|
||||
|
@ -14,3 +17,18 @@ class CaptchaRegistrationForm(RegistrationForm):
|
|||
|
||||
class CaptchaPasswordResetForm(PasswordResetForm):
|
||||
captcha = CaptchaField(label='Verification', help_text='Please enter the letters displayed for verification purposes', error_messages={'invalid':'Incorrect entry, please try again'})
|
||||
|
||||
|
||||
class DeleteAccountForm(forms.ModelForm):
|
||||
confirm_password = forms.CharField(widget=forms.PasswordInput)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('confirm_password', )
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(DeleteAccountForm, self).clean()
|
||||
confirm_password = cleaned_data.get('confirm_password')
|
||||
if not check_password(confirm_password, self.instance.password):
|
||||
self.add_error('confirm_password', 'Password does not match.')
|
||||
return cleaned_data
|
||||
|
|
|
@ -4,9 +4,15 @@
|
|||
#
|
||||
# Licensed under the MIT license, see COPYING.MIT for details
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import render
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import logout
|
||||
from registration.backends.model_activation.views import RegistrationView
|
||||
from django.contrib.auth.views import PasswordResetView
|
||||
from layerindex.auth_forms import CaptchaRegistrationForm, CaptchaPasswordResetForm
|
||||
from layerindex.auth_forms import CaptchaRegistrationForm, CaptchaPasswordResetForm, DeleteAccountForm
|
||||
|
||||
|
||||
class CaptchaRegistrationView(RegistrationView):
|
||||
|
@ -28,3 +34,30 @@ class CaptchaRegistrationView(RegistrationView):
|
|||
|
||||
class CaptchaPasswordResetView(PasswordResetView):
|
||||
form_class = CaptchaPasswordResetForm
|
||||
|
||||
|
||||
def delete_account_view(request, template_name):
|
||||
if not request.user.is_authenticated():
|
||||
raise PermissionDenied
|
||||
if request.user.is_superuser:
|
||||
# It's not really appropriate for the superuser to be deleted this way
|
||||
raise PermissionDenied
|
||||
if request.method == 'POST':
|
||||
form = DeleteAccountForm(request.POST, instance=request.user)
|
||||
if form.is_valid():
|
||||
# Naturally we don't call form.save() here !
|
||||
# Take a copy of request.user as it is about to be invalidated by logout()
|
||||
user = request.user
|
||||
logout(request)
|
||||
user.delete()
|
||||
messages.add_message(request, messages.SUCCESS,
|
||||
'Your user account has been successfully deleted')
|
||||
return HttpResponseRedirect(reverse('frontpage'))
|
||||
else:
|
||||
form = DeleteAccountForm(instance=request.user)
|
||||
|
||||
return render(request, template_name, {
|
||||
'user': request.user,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class MaintenancePlan(models.Model):
|
|||
email_subject = models.CharField(max_length=255, blank=True, default='[Recipe reporting system] Upgradable recipe name list', help_text='Subject line of automated emails')
|
||||
email_from = models.CharField(max_length=255, blank=True, help_text='Sender for automated emails')
|
||||
email_to = models.CharField(max_length=255, blank=True, help_text='Recipient for automated emails (separate multiple addresses with ;)')
|
||||
admin = models.ForeignKey(User, blank=True, null=True, help_text='Plan administrator')
|
||||
admin = models.ForeignKey(User, blank=True, null=True, help_text='Plan administrator', on_delete=models.SET_NULL)
|
||||
maintainer_style = models.CharField(max_length=1, choices=MAINTENANCEPLAN_MAINTAINER_STYLE, default='L', help_text='Maintainer tracking style for the layers within this plan')
|
||||
|
||||
def get_default_release(self):
|
||||
|
|
56
templates/layerindex/deleteaccount.html
Normal file
56
templates/layerindex/deleteaccount.html
Normal file
|
@ -0,0 +1,56 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% comment %}
|
||||
|
||||
layerindex-web - delete account confirmation template
|
||||
|
||||
Copyright (C) 2018 Intel Corporation
|
||||
Licensed under the MIT license, see COPYING.MIT for details
|
||||
|
||||
{% endcomment %}
|
||||
|
||||
<!--
|
||||
{% autoescape on %}
|
||||
{% block title_append %} - delete account{% endblock %}
|
||||
{% endautoescape %}
|
||||
-->
|
||||
|
||||
{% block content %}
|
||||
{% autoescape on %}
|
||||
|
||||
<h2>Delete account</h2>
|
||||
|
||||
<p>Are you sure you want to delete your account under the name "{{ user.username }}"? <strong>This will remove all associated records and cannot be undone!</strong></p>
|
||||
|
||||
<p>To confirm, please enter your password below and then click on <em>Delete account</em>.</p>
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% endfor %}
|
||||
|
||||
{% for field in form.visible_fields %}
|
||||
{% if field.errors %}
|
||||
<div class="form-group alert alert-danger">
|
||||
{{ field.errors }}
|
||||
{% else %}
|
||||
<div class="form-group">
|
||||
{% endif %}
|
||||
<div class="control-label {% if field.required %}requiredlabel{% endif %}">
|
||||
{{ field.label_tag }}
|
||||
</div>
|
||||
<div class="controls">
|
||||
{{ field }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<input type="submit" value="Delete account" class="btn btn-danger" />
|
||||
<a href="{% url 'profile' %}" class="btn btn-default">Cancel</a>
|
||||
</form>
|
||||
|
||||
{% endautoescape %}
|
||||
|
||||
{% endblock %}
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
<input type="submit" class="btn btn-default" value="{% trans 'Save' %}" />
|
||||
<a class="btn btn-default" href="{% url 'frontpage' %}">{% trans 'Cancel' %}</a>
|
||||
<a class="btn btn-danger" href="{% url 'delete_account' %}">{% trans 'Delete account' %}</a>
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
|
||||
|
|
5
urls.py
5
urls.py
|
@ -8,7 +8,7 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.views.generic import RedirectView
|
||||
from layerindex.auth_views import CaptchaRegistrationView, CaptchaPasswordResetView
|
||||
from layerindex.auth_views import CaptchaRegistrationView, CaptchaPasswordResetView, delete_account_view
|
||||
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
@ -25,6 +25,9 @@ urlpatterns = [
|
|||
name='auth_password_reset'),
|
||||
url(r'^accounts/register/$', CaptchaRegistrationView.as_view(),
|
||||
name='registration_register'),
|
||||
url(r'^accounts/delete/$', delete_account_view,
|
||||
{'template_name': 'layerindex/deleteaccount.html'},
|
||||
name='delete_account'),
|
||||
url(r'^accounts/', include('registration.backends.default.urls')),
|
||||
url(r'^captcha/', include('captcha.urls')),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue
Block a user