diff --git a/messages.pot b/messages.pot index 2929e3c..83c3c68 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\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" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -2271,7 +2271,7 @@ msgid "Organization successfully deleted" msgstr "" #: project/views/admin.py:113 project/views/manage.py:432 -#: project/views/user.py:40 +#: project/views/user.py:41 msgid "Settings successfully updated" msgstr "" @@ -2502,11 +2502,17 @@ msgid "" "verified automatically." 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" msgstr "" -#: project/views/user.py:130 +#: project/views/user.py:138 msgid "User deletion requested" msgstr "" diff --git a/project/models/admin_unit.py b/project/models/admin_unit.py index b3ab7c9..518caa1 100644 --- a/project/models/admin_unit.py +++ b/project/models/admin_unit.py @@ -46,7 +46,6 @@ class AdminUnitMember(db.Model): __tablename__ = "adminunitmember" id = Column(Integer(), primary_key=True) 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_id = db.Column( db.Integer, db.ForeignKey("user.id", ondelete="CASCADE"), nullable=False diff --git a/project/services/user.py b/project/services/user.py index 9d6e5ca..d13611d 100644 --- a/project/services/user.py +++ b/project/services/user.py @@ -4,6 +4,7 @@ from flask_security import hash_password from project import db, user_datastore from project.models import Event, Role, User, UserFavoriteEvents +from project.models.admin_unit import AdminUnitMember, AdminUnitMemberRole def create_user(email, password): @@ -111,3 +112,13 @@ def get_users_with_due_delete_request(): def delete_user(user): user_datastore.delete_user(user) 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 + ) diff --git a/project/translations/de/LC_MESSAGES/messages.mo b/project/translations/de/LC_MESSAGES/messages.mo index a047f11..aff23f3 100644 Binary files a/project/translations/de/LC_MESSAGES/messages.mo and b/project/translations/de/LC_MESSAGES/messages.mo differ diff --git a/project/translations/de/LC_MESSAGES/messages.po b/project/translations/de/LC_MESSAGES/messages.po index 403f51a..37ed8de 100644 --- a/project/translations/de/LC_MESSAGES/messages.po +++ b/project/translations/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\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" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -2343,7 +2343,7 @@ msgid "Organization successfully deleted" msgstr "Organisation erfolgreich gelöscht" #: project/views/admin.py:113 project/views/manage.py:432 -#: project/views/user.py:40 +#: project/views/user.py:41 msgid "Settings successfully updated" msgstr "Einstellungen erfolgreich aktualisiert" @@ -2581,11 +2581,17 @@ msgstr "" "Ob alle zukünftigen Empfehlungsanfragen von %(admin_unit_name)s " "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" msgstr "Die eingegebene Email entspricht nicht deiner Email" -#: project/views/user.py:130 +#: project/views/user.py:138 msgid "User deletion requested" msgstr "Löschung des Nutzers beantragt" diff --git a/project/translations/en/LC_MESSAGES/messages.mo b/project/translations/en/LC_MESSAGES/messages.mo index f4b8290..11a700d 100644 Binary files a/project/translations/en/LC_MESSAGES/messages.mo and b/project/translations/en/LC_MESSAGES/messages.mo differ diff --git a/project/translations/en/LC_MESSAGES/messages.po b/project/translations/en/LC_MESSAGES/messages.po index a077201..cf72353 100644 --- a/project/translations/en/LC_MESSAGES/messages.po +++ b/project/translations/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\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" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -2279,7 +2279,7 @@ msgid "Organization successfully deleted" msgstr "" #: project/views/admin.py:113 project/views/manage.py:432 -#: project/views/user.py:40 +#: project/views/user.py:41 msgid "Settings successfully updated" msgstr "" @@ -2510,11 +2510,17 @@ msgid "" "verified automatically." 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" msgstr "" -#: project/views/user.py:130 +#: project/views/user.py:138 msgid "User deletion requested" msgstr "" diff --git a/project/views/user.py b/project/views/user.py index d85aae7..bd82a2a 100644 --- a/project/views/user.py +++ b/project/views/user.py @@ -12,6 +12,7 @@ from project.forms.user import ( RequestUserDeletionForm, ) from project.models import AdminUnitInvitation, User +from project.services.user import is_user_admin_member from project.views.utils import ( flash_errors, get_invitation_access_result, @@ -79,7 +80,14 @@ def user_request_deletion(): form = None 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): flash(gettext("Entered email does not match your email"), "danger") else: diff --git a/tests/views/test_user.py b/tests/views/test_user.py index 73c0b9a..a5930b4 100644 --- a/tests/views/test_user.py +++ b/tests/views/test_user.py @@ -119,9 +119,9 @@ def test_login_flash(client, seeder, utils): def test_user_request_deletion( 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) if db_error: @@ -155,10 +155,21 @@ def test_user_request_deletion( with app.app_context(): 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 +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("non_match", [True, False]) def test_user_cancel_deletion( @@ -175,7 +186,7 @@ def test_user_cancel_deletion( user.deletion_requested_at = datetime.datetime.utcnow() 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) if db_error: