From 121167f1fed14ffb386e980673e163bce59b7647 Mon Sep 17 00:00:00 2001 From: Xeniac Date: Thu, 3 May 2018 09:45:06 +0200 Subject: [PATCH] Added a admin action to cleanup personal data from inactive members. --- src/membership/admin.py | 38 ++++++++++++++++-- .../locale/de/LC_MESSAGES/django.mo | Bin 9990 -> 10291 bytes .../locale/de/LC_MESSAGES/django.po | 34 +++++++++++----- src/membership/models.py | 10 +++-- 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/membership/admin.py b/src/membership/admin.py index d2daa27..22ab74b 100644 --- a/src/membership/admin.py +++ b/src/membership/admin.py @@ -1,11 +1,11 @@ """ Admin Interface to manage the memberships.""" # import stuff we need from django -from django.contrib import admin +from django.contrib import admin, messages from django.contrib.auth.admin import UserAdmin, GroupAdmin from django.contrib.auth.models import Group +from django.core.exceptions import PermissionDenied from django.utils.translation import ugettext as _ from easy_thumbnails import fields, widgets - from membership.models import Membership, ActivationRequest @@ -16,13 +16,14 @@ def activate_user(modeladmin, request, queryset): :param request: An HttpRequest representing the current request. :param queryset: A QuerySet containing the objects selected by the user. """ - [activation.activate() for activation in queryset ] + [activation.activate() for activation in queryset] activate_user.short_description = _('Activate selected User') -def cleanup_activation(modeladmin, request, queryset): # Ignore PyLintBear (W0613) +def cleanup_activation(modeladmin, request, + queryset): # Ignore PyLintBear (W0613) """Delete every selected activation request that has been expired. :param modeladmin: The ModelAdmin that triggered this action. @@ -38,6 +39,33 @@ cleanup_activation.short_description = _( "Cleanup selected Activation Requests") +def clear_personal_data(modeladmin, request, queryset): + """deactivates the account and removes all personal user information. + + :param modeladmin: The ModelAdmin that triggered this action. + :param request: An HttpRequest representing the current request. + :param queryset: A QuerySet containing the objects selected by the user. + """ + cleared_memberships = 0 + if not modeladmin.has_delete_permission(request): + raise PermissionDenied + for membership in queryset: + if membership.membership == False: + [ setattr(membership, fieldname, None) for fieldname in membership.nullable_personal_data ] + [ setattr(membership, fieldname, "") for fieldname in membership.blankable_personal_data ] + membership.is_active = False + membership.confirmed = False + membership.membership = False + membership.save() + cleared_memberships += 1 + else: + modeladmin.message_user(request, _("Can't remove personal data from active member %s.") % membership.username, messages.ERROR) + if cleared_memberships > 0: + modeladmin.message_user(request, _("Cleared %d personal data profiles.") % cleared_memberships, messages.INFO) + +clear_personal_data.short_description = _("Clear personal Data") + + class ProxyGroup(Group): """A Proxy to list Usergroups from django.contrib.auth here.""" @@ -50,6 +78,8 @@ class ProxyGroup(Group): class MembershipAdmin(UserAdmin): """Admin interface to manage membership. e.g. users.""" + actions = [clear_personal_data, ] + formfield_overrides = { fields.ThumbnailerImageField: { 'widget': widgets.ImageClearableFileInput}, diff --git a/src/membership/locale/de/LC_MESSAGES/django.mo b/src/membership/locale/de/LC_MESSAGES/django.mo index 3b4bdf7070fcd3bffaae1b88f0e3eef5352ec08d..75599b43bf9084f3184524a75a331d177b1ffe64 100644 GIT binary patch delta 2187 zcmZwIe@xVM9LMnw0SN~NVxasGz7=>>dV!!bDq^D`O4t>tjI4EdU*yK|MeZ)lwRJh0 zRMT8CH_K63&U7=Dozq%aOjnC?&XvQ>wHE!b*4m`jU$L>CFYY_}qu7qe_w)IFzwgic z^ZvXKcC{t^@$d7}_8Wepd`kG7Ox4JkbqnUrOfjaF@g!3lGmI%fU#2lR_#k%RdekeU zcnweC5mFKWRLQ45_#)-Ye; zO?U|v_$MT`nRdrBn9DeWo9S4HTBmGo95-ea7dJAo7TfTC%*R)ecgVbyOnn;w^X_cj5))74z6)>aT_mQtvM8!AATV z@57v%lL@tAgYKgiI)d@sP^JDIwV_2ckaoBPwQvdQxq4(TrWwh>bi}#PS@)t! zq_Il98}-5gRKP>1fbXH2>Nt+`wfr2*a2Mxyk@+Ls)VF0D=clH810#4Eb#!-7-Z5N- zylUdtxLD0aItQ)hxd)X<6SiPGD&rB?QCz|JGhBv$;GO7UH3eLQD*ZZCybVZum;fs7 zfII&@as+Yna`M6)L^aR*sAfFrj?bei@hvvvcc_Y$v$~pVEoz}A)KNZ)inAWI<4wq^ zm>|B5+fheXL?aclzPX(X1#CnG+=w~?8s=zcV zfqzhOZ{Vw?g>zBy%CMI8O%)e&3!=Jm0M+d~QGt(PHI8E?{)OdOY#DPKHlRuyL@hXg zowyx`@DeuQCOT1-89_aN7~?A433p-)mFWa(2bWPVOrZk*hDvN2l~@6twij2T5;}vl zgZUAk!dcX}=}EFw&m6*Lynv}#P)_}oNfB==uotsa_-BJ0lj&qqC4Uy1a0j;ImspP_ z%aav*0^1n(q2|X>3C^H4nCDFT|8(bPQGv5LA0?h&nJ8NDQEFAd@y4u(-Pb>8TU+f&wBHGYtzaM)u(~7teO6#| zEX18YyRXZRSQSy<@I}ufwRRvf|L_AmY#PJN*+Hu!IDca<%GOAKcPMN}eTk)6Js!{M zl~pxX)!lV9YldIRFU`C@Oq|H~q(8*^=T14{(B>Z7BCPFLgZ+*b=v5Am)f$Rz35T>u z)avCqhdGC5W0vj2y6uP)v$olhpzZjEKQ8jO`2QP?J=h^9w8eJJ|J)5ZO5dMM*ts6m Km&hod&H5MPtQ{)= delta 1915 zcmYMzduYvJ9LMozZDTvf7{|u23yx#MvESLnn5N0eWjHp3kh1I#(JW>ZIcjWwFjk9F7&Yh291?U;aPu?Myz z^TVc-Mjr;Ap%*{fKbRD^9WV=tWdhg}$D;z2Adi~)PQM%z>94|A+>DA_=k)htH~I%K zgvT(6_01O={2Mn>^*}$2!8BB$q0V>~szMfS!zU zI+9#W$LSbOp|OI-K-`K7cnG!N2`t4kSdZO^T8P_GmAZjk19Jyi%RE3O_zJbd&!`Q2 zcly6kM;S|*lvuAs>aWW*f`PR-5r^S9OvA@mj6ZN87Ez{5+=CPFDk`ALrbJvg7(G~v z`KZdCN8RfVEXUh833F8cA{sRwJEImX)&r=868qYv8;4q8Dyr0Fs2#3H?Qj!n;ab#l zN0FS(Nn|Z^83}3bqAK(fRq0P*8k+DM6)-Nz4%icQsXTav*KZW2V;AMR!*~Ke4#6j= zOBuyEuEsRf(e1=bxEGmf=27o_T#33nhf#@yPtZ`N7aTiq6#Yl2iSb+vl{g(WF$+0H zlZOfrbjHh2rC#h+?iP~8< zQY=$|2XO{+KTQ|1S@Q!GFFDnYHv(1av8cp@s147>IKBTBG?ZZ_YR7e`OWA~)5J6R- z4VA!6RHFA#3qMB%{D^rN&CUJ0AgUrk)TN$>in|d5*oc{W|F6;T;yWCQ9$rqBwg9zY z5EtSMtjFV6jM*7>WvWomuR~RCi_>pFCEA4AKr^b6EvUE`F|5qmXehHc*nqmqN@xdi zD&`C>!A{g`V{!9zN2+lO9zq?}8&o1)sJP$Nk1{5MT~Qq4C#cSTI!?y9Ug|%G#y$on z;CocbMl(Bv#i;QHRD!oqJA8pk-~%dPs?UCFe3(stBx-ySYTh!`5pQt%ji|~r`!emb zYGpu~w>v*{q5?ccW&YY1De2xC-I(W|7HM%;xB_|pTq`4B73LR=v~n!VRXWQ*yP{_K ln&qo1{lTTx6@?i&R$#2(`uAL'\n" "Language-Team: Kasu \n" "Language: de\n" @@ -31,27 +31,42 @@ msgstr "Weiblich" msgid "Activate selected User" msgstr "Ausgewählte Benutzer freischalten" -#: admin.py:38 +#: admin.py:39 msgid "Cleanup selected Activation Requests" msgstr "Ausgewählte Aktivierungsanfragen bereinigen" -#: admin.py:47 +#: admin.py:62 +#, python-format +msgid "Can't remove personal data from active member %s." +msgstr "" +"Persönliche Daten von aktiven Mitglied %s können nicht entfernt werden." + +#: admin.py:64 +#, python-format +msgid "Cleared %d personal data profiles." +msgstr "Persönliche Daten in %d Profilen entfernt." + +#: admin.py:66 +msgid "Clear personal Data" +msgstr "Persönliche Daten bereinigen" + +#: admin.py:75 msgid "Group" msgstr "Gruppe" -#: admin.py:48 +#: admin.py:76 msgid "Groups" msgstr "Gruppen" -#: admin.py:72 models.py:163 models.py:216 +#: admin.py:102 models.py:163 models.py:218 msgid "Membership" msgstr "Mitgliedschaft" -#: admin.py:77 +#: admin.py:107 msgid "Permissions" msgstr "Berechtigung" -#: admin.py:79 +#: admin.py:109 msgid "Important dates" msgstr "Wichtige Daten" @@ -159,7 +174,7 @@ msgstr "Bestätigt" msgid "This person has paid the membership fee." msgstr "Diese Person hat ihre Mitgliedschaft bezahlt" -#: models.py:217 +#: models.py:219 msgid "Memberships" msgstr "Mitgliedschaften" @@ -388,7 +403,6 @@ msgid "login" msgstr "Anmelden" #: templates/membership/register_form.html:26 -#| msgid "Membership" msgid "Club membership" msgstr "Vereinsmitgliedschaft" diff --git a/src/membership/models.py b/src/membership/models.py index 7b746d2..6aa9669 100644 --- a/src/membership/models.py +++ b/src/membership/models.py @@ -7,8 +7,8 @@ from os import path from django.conf import settings from django.contrib.auth.models import AbstractUser -from django.urls import reverse from django.db import models +from django.urls import reverse from django.utils import timezone from django.utils.translation import ugettext as _ from easy_thumbnails.fields import ThumbnailerImageField @@ -150,7 +150,7 @@ class Membership(AbstractUser): max_length=1, choices=GENDER_CHOICES, blank=True, - null=True + null=True, ) website = models.URLField(blank=True) avatar = ThumbnailerImageField( @@ -206,8 +206,10 @@ class Membership(AbstractUser): help_text=_('This person has paid the membership fee.') ) - # comment = models.TextField(blank=True) - # objects = MembershipManager() + nullable_personal_data = ( + 'gender', 'birthday', 'telephone', 'street_name', 'post_code', 'city') + blankable_personal_data = ( + 'email', 'password', 'first_name', 'last_name', 'website',) class Meta(object): """To manage object ordering and dispalynames on the admin interface."""