Delete account #456

This commit is contained in:
Daniel Grams 2023-05-02 23:24:33 +02:00
parent 5a85bec540
commit 51780c17f7
9 changed files with 65 additions and 18 deletions

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-05-01 18:11+0200\n" "POT-Creation-Date: 2023-05-02 23:21+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -2271,7 +2271,7 @@ msgid "Organization successfully deleted"
msgstr "" msgstr ""
#: project/views/admin.py:113 project/views/manage.py:432 #: project/views/admin.py:113 project/views/manage.py:432
#: project/views/user.py:40 #: project/views/user.py:41
msgid "Settings successfully updated" msgid "Settings successfully updated"
msgstr "" msgstr ""
@ -2502,11 +2502,17 @@ msgid ""
"verified automatically." "verified automatically."
msgstr "" msgstr ""
#: project/views/user.py:84 project/views/user.py:111 #: project/views/user.py:85
msgid ""
"You are administrator of at least one organization. Cancel your "
"membership to delete your account."
msgstr ""
#: project/views/user.py:92 project/views/user.py:119
msgid "Entered email does not match your email" msgid "Entered email does not match your email"
msgstr "" msgstr ""
#: project/views/user.py:130 #: project/views/user.py:138
msgid "User deletion requested" msgid "User deletion requested"
msgstr "" msgstr ""

View File

@ -46,7 +46,6 @@ class AdminUnitMember(db.Model):
__tablename__ = "adminunitmember" __tablename__ = "adminunitmember"
id = Column(Integer(), primary_key=True) id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False) admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
user = db.relationship("User", backref=db.backref("adminunitmembers", lazy=True)) user = db.relationship("User", backref=db.backref("adminunitmembers", lazy=True))
user_id = db.Column( user_id = db.Column(
db.Integer, db.ForeignKey("user.id", ondelete="CASCADE"), nullable=False db.Integer, db.ForeignKey("user.id", ondelete="CASCADE"), nullable=False

View File

@ -4,6 +4,7 @@ from flask_security import hash_password
from project import db, user_datastore from project import db, user_datastore
from project.models import Event, Role, User, UserFavoriteEvents from project.models import Event, Role, User, UserFavoriteEvents
from project.models.admin_unit import AdminUnitMember, AdminUnitMemberRole
def create_user(email, password): def create_user(email, password):
@ -111,3 +112,13 @@ def get_users_with_due_delete_request():
def delete_user(user): def delete_user(user):
user_datastore.delete_user(user) user_datastore.delete_user(user)
db.session.commit() db.session.commit()
def is_user_admin_member(user: User) -> bool:
return (
AdminUnitMember.query.filter(
AdminUnitMember.user_id == user.id,
AdminUnitMember.roles.any(AdminUnitMemberRole.name == "admin"),
).first()
is not None
)

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-05-01 18:11+0200\n" "POT-Creation-Date: 2023-05-02 23:21+0200\n"
"PO-Revision-Date: 2020-06-07 18:51+0200\n" "PO-Revision-Date: 2020-06-07 18:51+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n" "Language: de\n"
@ -2343,7 +2343,7 @@ msgid "Organization successfully deleted"
msgstr "Organisation erfolgreich gelöscht" msgstr "Organisation erfolgreich gelöscht"
#: project/views/admin.py:113 project/views/manage.py:432 #: project/views/admin.py:113 project/views/manage.py:432
#: project/views/user.py:40 #: project/views/user.py:41
msgid "Settings successfully updated" msgid "Settings successfully updated"
msgstr "Einstellungen erfolgreich aktualisiert" msgstr "Einstellungen erfolgreich aktualisiert"
@ -2581,11 +2581,17 @@ msgstr ""
"Ob alle zukünftigen Empfehlungsanfragen von %(admin_unit_name)s " "Ob alle zukünftigen Empfehlungsanfragen von %(admin_unit_name)s "
"automatisch verifiziert werden sollen." "automatisch verifiziert werden sollen."
#: project/views/user.py:84 project/views/user.py:111 #: project/views/user.py:85
msgid ""
"You are administrator of at least one organization. Cancel your "
"membership to delete your account."
msgstr "Du bist Administrator von mindestens einer Organisation. Beende deine Mitgliedschaft, um deinen Account zu löschen."
#: project/views/user.py:92 project/views/user.py:119
msgid "Entered email does not match your email" msgid "Entered email does not match your email"
msgstr "Die eingegebene Email entspricht nicht deiner Email" msgstr "Die eingegebene Email entspricht nicht deiner Email"
#: project/views/user.py:130 #: project/views/user.py:138
msgid "User deletion requested" msgid "User deletion requested"
msgstr "Löschung des Nutzers beantragt" msgstr "Löschung des Nutzers beantragt"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-05-01 18:11+0200\n" "POT-Creation-Date: 2023-05-02 23:21+0200\n"
"PO-Revision-Date: 2021-04-30 15:04+0200\n" "PO-Revision-Date: 2021-04-30 15:04+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n" "Language: en\n"
@ -2279,7 +2279,7 @@ msgid "Organization successfully deleted"
msgstr "" msgstr ""
#: project/views/admin.py:113 project/views/manage.py:432 #: project/views/admin.py:113 project/views/manage.py:432
#: project/views/user.py:40 #: project/views/user.py:41
msgid "Settings successfully updated" msgid "Settings successfully updated"
msgstr "" msgstr ""
@ -2510,11 +2510,17 @@ msgid ""
"verified automatically." "verified automatically."
msgstr "" msgstr ""
#: project/views/user.py:84 project/views/user.py:111 #: project/views/user.py:85
msgid ""
"You are administrator of at least one organization. Cancel your "
"membership to delete your account."
msgstr ""
#: project/views/user.py:92 project/views/user.py:119
msgid "Entered email does not match your email" msgid "Entered email does not match your email"
msgstr "" msgstr ""
#: project/views/user.py:130 #: project/views/user.py:138
msgid "User deletion requested" msgid "User deletion requested"
msgstr "" msgstr ""

View File

@ -12,6 +12,7 @@ from project.forms.user import (
RequestUserDeletionForm, RequestUserDeletionForm,
) )
from project.models import AdminUnitInvitation, User from project.models import AdminUnitInvitation, User
from project.services.user import is_user_admin_member
from project.views.utils import ( from project.views.utils import (
flash_errors, flash_errors,
get_invitation_access_result, get_invitation_access_result,
@ -79,7 +80,14 @@ def user_request_deletion():
form = None form = None
form = RequestUserDeletionForm() form = RequestUserDeletionForm()
if form.validate_on_submit(): if is_user_admin_member(current_user):
flash(
gettext(
"You are administrator of at least one organization. Cancel your membership to delete your account."
),
"danger",
)
elif form.validate_on_submit():
if non_match_for_deletion(form.email.data, current_user.email): if non_match_for_deletion(form.email.data, current_user.email):
flash(gettext("Entered email does not match your email"), "danger") flash(gettext("Entered email does not match your email"), "danger")
else: else:

View File

@ -119,9 +119,9 @@ def test_login_flash(client, seeder, utils):
def test_user_request_deletion( def test_user_request_deletion(
client, seeder: Seeder, utils, app, db, mocker, db_error, non_match client, seeder: Seeder, utils, app, db, mocker, db_error, non_match
): ):
user_id, admin_unit_id = seeder.setup_base() owner_id, admin_unit_id, member_id = seeder.setup_base_event_verifier()
url = utils.get_url("user_request_deletion", id=user_id) url = utils.get_url("user_request_deletion")
response = utils.get_ok(url) response = utils.get_ok(url)
if db_error: if db_error:
@ -155,10 +155,21 @@ def test_user_request_deletion(
with app.app_context(): with app.app_context():
from project.models import User from project.models import User
user = db.session.get(User, user_id) user = db.session.get(User, member_id)
assert user.deletion_requested_at is not None assert user.deletion_requested_at is not None
def test_user_request_deletion_admin_member(client, seeder: Seeder, utils, app, db):
seeder.setup_base()
url = utils.get_url("user_request_deletion")
response = utils.get_ok(url)
utils.assert_response_error_message(
response,
"Du bist Administrator von mindestens einer Organisation. Beende deine Mitgliedschaft, um deinen Account zu löschen.",
)
@pytest.mark.parametrize("db_error", [True, False]) @pytest.mark.parametrize("db_error", [True, False])
@pytest.mark.parametrize("non_match", [True, False]) @pytest.mark.parametrize("non_match", [True, False])
def test_user_cancel_deletion( def test_user_cancel_deletion(
@ -175,7 +186,7 @@ def test_user_cancel_deletion(
user.deletion_requested_at = datetime.datetime.utcnow() user.deletion_requested_at = datetime.datetime.utcnow()
db.session.commit() db.session.commit()
url = utils.get_url("user_cancel_deletion", id=user_id) url = utils.get_url("user_cancel_deletion")
response = utils.get_ok(url) response = utils.get_ok(url)
if db_error: if db_error: