mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
Merge pull request #459 from eventcally/issues/458
Leave organization #458
This commit is contained in:
commit
b93c16c797
25
docker-compose.test.services.yml
Normal file
25
docker-compose.test.services.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
version: "3.9"
|
||||||
|
name: "eventcally-test-services"
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgis/postgis:12-3.1
|
||||||
|
healthcheck:
|
||||||
|
test: "pg_isready --username=eventcally && psql --username=eventcally --list"
|
||||||
|
start_period: "5s"
|
||||||
|
ports:
|
||||||
|
- 5433:5432
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=eventcally
|
||||||
|
- POSTGRES_USER=eventcally
|
||||||
|
- POSTGRES_PASSWORD=pass
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: bitnami/redis:6.2
|
||||||
|
healthcheck:
|
||||||
|
test: "redis-cli -a 'pass' ping | grep PONG"
|
||||||
|
start_period: "5s"
|
||||||
|
ports:
|
||||||
|
- 6380:6379
|
||||||
|
environment:
|
||||||
|
REDIS_PASSWORD: pass
|
||||||
48
messages.pot
48
messages.pot
@ -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-02 23:21+0200\n"
|
"POT-Creation-Date: 2023-05-03 20:26+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"
|
||||||
@ -198,24 +198,24 @@ msgstr ""
|
|||||||
msgid "You have received an invitation"
|
msgid "You have received an invitation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:11 project/templates/layout.html:303
|
#: project/forms/admin.py:11 project/templates/layout.html:304
|
||||||
#: project/views/root.py:55
|
#: project/views/root.py:55
|
||||||
msgid "Terms of service"
|
msgid "Terms of service"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:12 project/templates/layout.html:307
|
#: project/forms/admin.py:12 project/templates/layout.html:308
|
||||||
#: project/views/root.py:63
|
#: project/views/root.py:63
|
||||||
msgid "Legal notice"
|
msgid "Legal notice"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:13 project/templates/_macros.html:1473
|
#: project/forms/admin.py:13 project/templates/_macros.html:1473
|
||||||
#: project/templates/layout.html:311
|
#: project/templates/layout.html:312
|
||||||
#: project/templates/widget/event_suggestion/create.html:204
|
#: project/templates/widget/event_suggestion/create.html:204
|
||||||
#: project/views/admin_unit.py:83 project/views/root.py:71
|
#: project/views/admin_unit.py:83 project/views/root.py:71
|
||||||
msgid "Contact"
|
msgid "Contact"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:14 project/templates/layout.html:315
|
#: project/forms/admin.py:14 project/templates/layout.html:316
|
||||||
#: project/views/root.py:79
|
#: project/views/root.py:79
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -310,11 +310,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: project/forms/admin.py:69 project/forms/admin_unit.py:28
|
#: project/forms/admin.py:69 project/forms/admin_unit.py:28
|
||||||
#: project/forms/admin_unit.py:134 project/forms/admin_unit.py:139
|
#: project/forms/admin_unit.py:134 project/forms/admin_unit.py:139
|
||||||
#: project/forms/event.py:85 project/forms/event.py:114
|
#: project/forms/admin_unit.py:144 project/forms/event.py:85
|
||||||
#: project/forms/event_place.py:25 project/forms/event_place.py:50
|
#: project/forms/event.py:114 project/forms/event_place.py:25
|
||||||
#: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66
|
#: project/forms/event_place.py:50 project/forms/event_suggestion.py:26
|
||||||
#: project/forms/organizer.py:25 project/forms/organizer.py:52
|
#: project/forms/oauth2_client.py:66 project/forms/organizer.py:25
|
||||||
#: project/forms/reference_request.py:23
|
#: project/forms/organizer.py:52 project/forms/reference_request.py:23
|
||||||
#: project/templates/admin/admin_units.html:19
|
#: project/templates/admin/admin_units.html:19
|
||||||
#: project/templates/event_place/list.html:19
|
#: project/templates/event_place/list.html:19
|
||||||
#: project/templates/manage/organizers.html:18
|
#: project/templates/manage/organizers.html:18
|
||||||
@ -487,6 +487,11 @@ msgstr ""
|
|||||||
msgid "Cancel deletion"
|
msgid "Cancel deletion"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/forms/admin_unit.py:143 project/templates/layout.html:276
|
||||||
|
#: project/templates/manage/delete_membership.html:6
|
||||||
|
msgid "Leave organization"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin_unit_member.py:13
|
#: project/forms/admin_unit_member.py:13
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1142,6 +1147,7 @@ msgstr ""
|
|||||||
#: project/templates/admin_unit/request_deletion.html:15
|
#: project/templates/admin_unit/request_deletion.html:15
|
||||||
#: project/templates/admin_unit/update.html:36
|
#: project/templates/admin_unit/update.html:36
|
||||||
#: project/templates/layout.html:247
|
#: project/templates/layout.html:247
|
||||||
|
#: project/templates/manage/delete_membership.html:13
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1668,7 +1674,7 @@ msgid "Switch organization"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/templates/developer/read.html:4
|
#: project/templates/developer/read.html:4
|
||||||
#: project/templates/developer/read.html:8 project/templates/layout.html:319
|
#: project/templates/developer/read.html:8 project/templates/layout.html:320
|
||||||
#: project/templates/profile.html:46
|
#: project/templates/profile.html:46
|
||||||
msgid "Developer"
|
msgid "Developer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2262,7 +2268,7 @@ msgid "Organization successfully updated"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/admin.py:85 project/views/admin_unit.py:187
|
#: project/views/admin.py:85 project/views/admin_unit.py:187
|
||||||
#: project/views/admin_unit.py:220
|
#: project/views/admin_unit.py:220 project/views/manage.py:316
|
||||||
msgid "Entered name does not match organization name"
|
msgid "Entered name does not match organization name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2270,7 +2276,7 @@ msgstr ""
|
|||||||
msgid "Organization successfully deleted"
|
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:486
|
||||||
#: project/views/user.py:41
|
#: project/views/user.py:41
|
||||||
msgid "Settings successfully updated"
|
msgid "Settings successfully updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2323,11 +2329,15 @@ msgstr ""
|
|||||||
msgid "Member successfully updated"
|
msgid "Member successfully updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/admin_unit_member.py:69
|
#: project/views/admin_unit_member.py:70 project/views/manage.py:307
|
||||||
|
msgid "Last remaining administrator can not leave the organization."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/views/admin_unit_member.py:79
|
||||||
msgid "Entered email does not match member email"
|
msgid "Entered email does not match member email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/admin_unit_member.py:74
|
#: project/views/admin_unit_member.py:84
|
||||||
msgid "Member successfully deleted"
|
msgid "Member successfully deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2420,6 +2430,14 @@ msgstr ""
|
|||||||
msgid "Places of Google Maps"
|
msgid "Places of Google Maps"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/views/manage.py:302
|
||||||
|
msgid "You are not a member of this organization"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/views/manage.py:321
|
||||||
|
msgid "Organization successfully left"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/oauth2_client.py:37
|
#: project/views/oauth2_client.py:37
|
||||||
msgid "OAuth2 client successfully created"
|
msgid "OAuth2 client successfully created"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@ -8,6 +8,7 @@ from sqlalchemy import and_
|
|||||||
|
|
||||||
from project import app
|
from project import app
|
||||||
from project.models import AdminUnit, AdminUnitMember, Event, PublicStatus, User
|
from project.models import AdminUnit, AdminUnitMember, Event, PublicStatus, User
|
||||||
|
from project.models.admin_unit import AdminUnitMemberRole
|
||||||
from project.services.admin_unit import get_member_for_admin_unit_by_user_id
|
from project.services.admin_unit import get_member_for_admin_unit_by_user_id
|
||||||
|
|
||||||
|
|
||||||
@ -238,3 +239,18 @@ def get_admin_unit_members_with_permission(admin_unit_id: int, permission: str)
|
|||||||
lambda member: has_admin_unit_member_permission(member, permission), members
|
lambda member: has_admin_unit_member_permission(member, permission), members
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def can_current_user_delete_member(member: AdminUnitMember) -> bool:
|
||||||
|
if current_user.has_role("admin"): # pragma: no cover
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Check if there is another admin
|
||||||
|
return (
|
||||||
|
AdminUnitMember.query.filter(
|
||||||
|
AdminUnitMember.user_id != member.user_id,
|
||||||
|
AdminUnitMember.admin_unit_id == member.admin_unit_id,
|
||||||
|
AdminUnitMember.roles.any(AdminUnitMemberRole.name == "admin"),
|
||||||
|
).first()
|
||||||
|
is not None
|
||||||
|
)
|
||||||
|
|||||||
@ -137,3 +137,8 @@ class RequestAdminUnitDeletionForm(FlaskForm):
|
|||||||
class CancelAdminUnitDeletionForm(FlaskForm):
|
class CancelAdminUnitDeletionForm(FlaskForm):
|
||||||
submit = SubmitField(lazy_gettext("Cancel deletion"))
|
submit = SubmitField(lazy_gettext("Cancel deletion"))
|
||||||
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
|
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
|
||||||
|
|
||||||
|
|
||||||
|
class AdminUnitDeleteMembershipForm(FlaskForm):
|
||||||
|
submit = SubmitField(lazy_gettext("Leave organization"))
|
||||||
|
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
|
||||||
|
|||||||
@ -273,6 +273,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarAdminUnitSwitchDropdown">
|
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarAdminUnitSwitchDropdown">
|
||||||
<a class="dropdown-item" href="{{ url_for('manage_admin_units') }}">{{ _('Switch organization') }}</a>
|
<a class="dropdown-item" href="{{ url_for('manage_admin_units') }}">{{ _('Switch organization') }}</a>
|
||||||
|
<a class="dropdown-item" href="{{ url_for('manage_admin_unit_delete_membership', id=current_admin_unit.id) }}">{{ _('Leave organization') }}…</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
24
project/templates/manage/delete_membership.html
Normal file
24
project/templates/manage/delete_membership.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% from "_macros.html" import render_field_with_errors, render_field %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1>{{ _('Leave organization') }} "{{ admin_unit.name }}"</h1>
|
||||||
|
|
||||||
|
<form action="" method="POST">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
{{ _('Organization') }}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
{{ render_field_with_errors(form.name) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ render_field(form.submit) }}
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
Binary file not shown.
@ -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-02 23:21+0200\n"
|
"POT-Creation-Date: 2023-05-03 20:26+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"
|
||||||
@ -199,24 +199,24 @@ msgstr "message"
|
|||||||
msgid "You have received an invitation"
|
msgid "You have received an invitation"
|
||||||
msgstr "Du hast eine Einladung erhalten"
|
msgstr "Du hast eine Einladung erhalten"
|
||||||
|
|
||||||
#: project/forms/admin.py:11 project/templates/layout.html:303
|
#: project/forms/admin.py:11 project/templates/layout.html:304
|
||||||
#: project/views/root.py:55
|
#: project/views/root.py:55
|
||||||
msgid "Terms of service"
|
msgid "Terms of service"
|
||||||
msgstr "Nutzungsbedingungen"
|
msgstr "Nutzungsbedingungen"
|
||||||
|
|
||||||
#: project/forms/admin.py:12 project/templates/layout.html:307
|
#: project/forms/admin.py:12 project/templates/layout.html:308
|
||||||
#: project/views/root.py:63
|
#: project/views/root.py:63
|
||||||
msgid "Legal notice"
|
msgid "Legal notice"
|
||||||
msgstr "Impressum"
|
msgstr "Impressum"
|
||||||
|
|
||||||
#: project/forms/admin.py:13 project/templates/_macros.html:1473
|
#: project/forms/admin.py:13 project/templates/_macros.html:1473
|
||||||
#: project/templates/layout.html:311
|
#: project/templates/layout.html:312
|
||||||
#: project/templates/widget/event_suggestion/create.html:204
|
#: project/templates/widget/event_suggestion/create.html:204
|
||||||
#: project/views/admin_unit.py:83 project/views/root.py:71
|
#: project/views/admin_unit.py:83 project/views/root.py:71
|
||||||
msgid "Contact"
|
msgid "Contact"
|
||||||
msgstr "Kontakt"
|
msgstr "Kontakt"
|
||||||
|
|
||||||
#: project/forms/admin.py:14 project/templates/layout.html:315
|
#: project/forms/admin.py:14 project/templates/layout.html:316
|
||||||
#: project/views/root.py:79
|
#: project/views/root.py:79
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr "Datenschutz"
|
msgstr "Datenschutz"
|
||||||
@ -319,11 +319,11 @@ msgstr "Organisation löschen"
|
|||||||
|
|
||||||
#: project/forms/admin.py:69 project/forms/admin_unit.py:28
|
#: project/forms/admin.py:69 project/forms/admin_unit.py:28
|
||||||
#: project/forms/admin_unit.py:134 project/forms/admin_unit.py:139
|
#: project/forms/admin_unit.py:134 project/forms/admin_unit.py:139
|
||||||
#: project/forms/event.py:85 project/forms/event.py:114
|
#: project/forms/admin_unit.py:144 project/forms/event.py:85
|
||||||
#: project/forms/event_place.py:25 project/forms/event_place.py:50
|
#: project/forms/event.py:114 project/forms/event_place.py:25
|
||||||
#: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66
|
#: project/forms/event_place.py:50 project/forms/event_suggestion.py:26
|
||||||
#: project/forms/organizer.py:25 project/forms/organizer.py:52
|
#: project/forms/oauth2_client.py:66 project/forms/organizer.py:25
|
||||||
#: project/forms/reference_request.py:23
|
#: project/forms/organizer.py:52 project/forms/reference_request.py:23
|
||||||
#: project/templates/admin/admin_units.html:19
|
#: project/templates/admin/admin_units.html:19
|
||||||
#: project/templates/event_place/list.html:19
|
#: project/templates/event_place/list.html:19
|
||||||
#: project/templates/manage/organizers.html:18
|
#: project/templates/manage/organizers.html:18
|
||||||
@ -507,6 +507,11 @@ msgstr "Löschung beantragen"
|
|||||||
msgid "Cancel deletion"
|
msgid "Cancel deletion"
|
||||||
msgstr "Löschen abbrechen"
|
msgstr "Löschen abbrechen"
|
||||||
|
|
||||||
|
#: project/forms/admin_unit.py:143 project/templates/layout.html:276
|
||||||
|
#: project/templates/manage/delete_membership.html:6
|
||||||
|
msgid "Leave organization"
|
||||||
|
msgstr "Organisation verlassen"
|
||||||
|
|
||||||
#: project/forms/admin_unit_member.py:13
|
#: project/forms/admin_unit_member.py:13
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr "Einladen"
|
msgstr "Einladen"
|
||||||
@ -1190,6 +1195,7 @@ msgstr "Wochentage"
|
|||||||
#: project/templates/admin_unit/request_deletion.html:15
|
#: project/templates/admin_unit/request_deletion.html:15
|
||||||
#: project/templates/admin_unit/update.html:36
|
#: project/templates/admin_unit/update.html:36
|
||||||
#: project/templates/layout.html:247
|
#: project/templates/layout.html:247
|
||||||
|
#: project/templates/manage/delete_membership.html:13
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr "Organisation"
|
msgstr "Organisation"
|
||||||
|
|
||||||
@ -1725,7 +1731,7 @@ msgid "Switch organization"
|
|||||||
msgstr "Organisation wechseln"
|
msgstr "Organisation wechseln"
|
||||||
|
|
||||||
#: project/templates/developer/read.html:4
|
#: project/templates/developer/read.html:4
|
||||||
#: project/templates/developer/read.html:8 project/templates/layout.html:319
|
#: project/templates/developer/read.html:8 project/templates/layout.html:320
|
||||||
#: project/templates/profile.html:46
|
#: project/templates/profile.html:46
|
||||||
msgid "Developer"
|
msgid "Developer"
|
||||||
msgstr "Entwickler"
|
msgstr "Entwickler"
|
||||||
@ -2334,7 +2340,7 @@ msgid "Organization successfully updated"
|
|||||||
msgstr "Organisation erfolgreich aktualisiert"
|
msgstr "Organisation erfolgreich aktualisiert"
|
||||||
|
|
||||||
#: project/views/admin.py:85 project/views/admin_unit.py:187
|
#: project/views/admin.py:85 project/views/admin_unit.py:187
|
||||||
#: project/views/admin_unit.py:220
|
#: project/views/admin_unit.py:220 project/views/manage.py:316
|
||||||
msgid "Entered name does not match organization name"
|
msgid "Entered name does not match organization name"
|
||||||
msgstr "Der eingegebene Name entspricht nicht dem Namen der Organisation"
|
msgstr "Der eingegebene Name entspricht nicht dem Namen der Organisation"
|
||||||
|
|
||||||
@ -2342,7 +2348,7 @@ msgstr "Der eingegebene Name entspricht nicht dem Namen der Organisation"
|
|||||||
msgid "Organization successfully deleted"
|
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:486
|
||||||
#: project/views/user.py:41
|
#: project/views/user.py:41
|
||||||
msgid "Settings successfully updated"
|
msgid "Settings successfully updated"
|
||||||
msgstr "Einstellungen erfolgreich aktualisiert"
|
msgstr "Einstellungen erfolgreich aktualisiert"
|
||||||
@ -2398,11 +2404,15 @@ msgstr "Löschung der Organisation beantragt"
|
|||||||
msgid "Member successfully updated"
|
msgid "Member successfully updated"
|
||||||
msgstr "Mitglied erfolgreich aktualisiert"
|
msgstr "Mitglied erfolgreich aktualisiert"
|
||||||
|
|
||||||
#: project/views/admin_unit_member.py:69
|
#: project/views/admin_unit_member.py:70 project/views/manage.py:307
|
||||||
|
msgid "Last remaining administrator can not leave the organization."
|
||||||
|
msgstr "Der letzte verbleibende Administrator kann die Organisation nicht verlassen."
|
||||||
|
|
||||||
|
#: project/views/admin_unit_member.py:79
|
||||||
msgid "Entered email does not match member email"
|
msgid "Entered email does not match member email"
|
||||||
msgstr "Die eingegebene Email passt nicht zur Email des Mitglieds"
|
msgstr "Die eingegebene Email passt nicht zur Email des Mitglieds"
|
||||||
|
|
||||||
#: project/views/admin_unit_member.py:74
|
#: project/views/admin_unit_member.py:84
|
||||||
msgid "Member successfully deleted"
|
msgid "Member successfully deleted"
|
||||||
msgstr "Mitglied erfolgreich gelöscht"
|
msgstr "Mitglied erfolgreich gelöscht"
|
||||||
|
|
||||||
@ -2495,6 +2505,14 @@ msgstr "Orte der Organisation"
|
|||||||
msgid "Places of Google Maps"
|
msgid "Places of Google Maps"
|
||||||
msgstr "Orte von Google Maps"
|
msgstr "Orte von Google Maps"
|
||||||
|
|
||||||
|
#: project/views/manage.py:302
|
||||||
|
msgid "You are not a member of this organization"
|
||||||
|
msgstr "Du bist kein Mitglied dieser Organisation"
|
||||||
|
|
||||||
|
#: project/views/manage.py:321
|
||||||
|
msgid "Organization successfully left"
|
||||||
|
msgstr "Organisation erfolgreich verlassen"
|
||||||
|
|
||||||
#: project/views/oauth2_client.py:37
|
#: project/views/oauth2_client.py:37
|
||||||
msgid "OAuth2 client successfully created"
|
msgid "OAuth2 client successfully created"
|
||||||
msgstr "OAuth2 Client erfolgreich erstellt"
|
msgstr "OAuth2 Client erfolgreich erstellt"
|
||||||
@ -2585,7 +2603,9 @@ msgstr ""
|
|||||||
msgid ""
|
msgid ""
|
||||||
"You are administrator of at least one organization. Cancel your "
|
"You are administrator of at least one organization. Cancel your "
|
||||||
"membership to delete your account."
|
"membership to delete your account."
|
||||||
msgstr "Du bist Administrator von mindestens einer Organisation. Beende deine Mitgliedschaft, um deinen Account zu löschen."
|
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
|
#: 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"
|
||||||
|
|||||||
Binary file not shown.
@ -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-02 23:21+0200\n"
|
"POT-Creation-Date: 2023-05-03 20:26+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"
|
||||||
@ -199,24 +199,24 @@ msgstr ""
|
|||||||
msgid "You have received an invitation"
|
msgid "You have received an invitation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:11 project/templates/layout.html:303
|
#: project/forms/admin.py:11 project/templates/layout.html:304
|
||||||
#: project/views/root.py:55
|
#: project/views/root.py:55
|
||||||
msgid "Terms of service"
|
msgid "Terms of service"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:12 project/templates/layout.html:307
|
#: project/forms/admin.py:12 project/templates/layout.html:308
|
||||||
#: project/views/root.py:63
|
#: project/views/root.py:63
|
||||||
msgid "Legal notice"
|
msgid "Legal notice"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:13 project/templates/_macros.html:1473
|
#: project/forms/admin.py:13 project/templates/_macros.html:1473
|
||||||
#: project/templates/layout.html:311
|
#: project/templates/layout.html:312
|
||||||
#: project/templates/widget/event_suggestion/create.html:204
|
#: project/templates/widget/event_suggestion/create.html:204
|
||||||
#: project/views/admin_unit.py:83 project/views/root.py:71
|
#: project/views/admin_unit.py:83 project/views/root.py:71
|
||||||
msgid "Contact"
|
msgid "Contact"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin.py:14 project/templates/layout.html:315
|
#: project/forms/admin.py:14 project/templates/layout.html:316
|
||||||
#: project/views/root.py:79
|
#: project/views/root.py:79
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -311,11 +311,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: project/forms/admin.py:69 project/forms/admin_unit.py:28
|
#: project/forms/admin.py:69 project/forms/admin_unit.py:28
|
||||||
#: project/forms/admin_unit.py:134 project/forms/admin_unit.py:139
|
#: project/forms/admin_unit.py:134 project/forms/admin_unit.py:139
|
||||||
#: project/forms/event.py:85 project/forms/event.py:114
|
#: project/forms/admin_unit.py:144 project/forms/event.py:85
|
||||||
#: project/forms/event_place.py:25 project/forms/event_place.py:50
|
#: project/forms/event.py:114 project/forms/event_place.py:25
|
||||||
#: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66
|
#: project/forms/event_place.py:50 project/forms/event_suggestion.py:26
|
||||||
#: project/forms/organizer.py:25 project/forms/organizer.py:52
|
#: project/forms/oauth2_client.py:66 project/forms/organizer.py:25
|
||||||
#: project/forms/reference_request.py:23
|
#: project/forms/organizer.py:52 project/forms/reference_request.py:23
|
||||||
#: project/templates/admin/admin_units.html:19
|
#: project/templates/admin/admin_units.html:19
|
||||||
#: project/templates/event_place/list.html:19
|
#: project/templates/event_place/list.html:19
|
||||||
#: project/templates/manage/organizers.html:18
|
#: project/templates/manage/organizers.html:18
|
||||||
@ -488,6 +488,11 @@ msgstr ""
|
|||||||
msgid "Cancel deletion"
|
msgid "Cancel deletion"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/forms/admin_unit.py:143 project/templates/layout.html:276
|
||||||
|
#: project/templates/manage/delete_membership.html:6
|
||||||
|
msgid "Leave organization"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: project/forms/admin_unit_member.py:13
|
#: project/forms/admin_unit_member.py:13
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1143,6 +1148,7 @@ msgstr ""
|
|||||||
#: project/templates/admin_unit/request_deletion.html:15
|
#: project/templates/admin_unit/request_deletion.html:15
|
||||||
#: project/templates/admin_unit/update.html:36
|
#: project/templates/admin_unit/update.html:36
|
||||||
#: project/templates/layout.html:247
|
#: project/templates/layout.html:247
|
||||||
|
#: project/templates/manage/delete_membership.html:13
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1676,7 +1682,7 @@ msgid "Switch organization"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/templates/developer/read.html:4
|
#: project/templates/developer/read.html:4
|
||||||
#: project/templates/developer/read.html:8 project/templates/layout.html:319
|
#: project/templates/developer/read.html:8 project/templates/layout.html:320
|
||||||
#: project/templates/profile.html:46
|
#: project/templates/profile.html:46
|
||||||
msgid "Developer"
|
msgid "Developer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2270,7 +2276,7 @@ msgid "Organization successfully updated"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/admin.py:85 project/views/admin_unit.py:187
|
#: project/views/admin.py:85 project/views/admin_unit.py:187
|
||||||
#: project/views/admin_unit.py:220
|
#: project/views/admin_unit.py:220 project/views/manage.py:316
|
||||||
msgid "Entered name does not match organization name"
|
msgid "Entered name does not match organization name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2278,7 +2284,7 @@ msgstr ""
|
|||||||
msgid "Organization successfully deleted"
|
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:486
|
||||||
#: project/views/user.py:41
|
#: project/views/user.py:41
|
||||||
msgid "Settings successfully updated"
|
msgid "Settings successfully updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2331,11 +2337,15 @@ msgstr ""
|
|||||||
msgid "Member successfully updated"
|
msgid "Member successfully updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/admin_unit_member.py:69
|
#: project/views/admin_unit_member.py:70 project/views/manage.py:307
|
||||||
|
msgid "Last remaining administrator can not leave the organization."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/views/admin_unit_member.py:79
|
||||||
msgid "Entered email does not match member email"
|
msgid "Entered email does not match member email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/admin_unit_member.py:74
|
#: project/views/admin_unit_member.py:84
|
||||||
msgid "Member successfully deleted"
|
msgid "Member successfully deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2428,6 +2438,14 @@ msgstr ""
|
|||||||
msgid "Places of Google Maps"
|
msgid "Places of Google Maps"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/views/manage.py:302
|
||||||
|
msgid "You are not a member of this organization"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: project/views/manage.py:321
|
||||||
|
msgid "Organization successfully left"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: project/views/oauth2_client.py:37
|
#: project/views/oauth2_client.py:37
|
||||||
msgid "OAuth2 client successfully created"
|
msgid "OAuth2 client successfully created"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from flask import flash, redirect, render_template, url_for
|
from flask import flash, redirect, render_template, url_for
|
||||||
from flask_babel import gettext
|
from flask_babel import gettext
|
||||||
from flask_security import auth_required
|
from flask_security import auth_required, current_user
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
from project import app, db
|
from project import app, db
|
||||||
@ -59,7 +59,10 @@ def manage_admin_unit_member_delete(id):
|
|||||||
member = AdminUnitMember.query.get_or_404(id)
|
member = AdminUnitMember.query.get_or_404(id)
|
||||||
admin_unit = member.adminunit
|
admin_unit = member.adminunit
|
||||||
|
|
||||||
if not has_access(admin_unit, "admin_unit.members:delete"):
|
if member.user_id == current_user.id:
|
||||||
|
return redirect(url_for("manage_admin_unit_delete_membership", id=id))
|
||||||
|
|
||||||
|
if not has_access(admin_unit, "admin_unit.members:delete"): # pragma: no cover
|
||||||
return permission_missing(url_for("manage_admin_unit", id=admin_unit.id))
|
return permission_missing(url_for("manage_admin_unit", id=admin_unit.id))
|
||||||
|
|
||||||
form = DeleteAdminUnitMemberForm()
|
form = DeleteAdminUnitMemberForm()
|
||||||
|
|||||||
@ -17,12 +17,16 @@ from project import app, db, dump_org_path
|
|||||||
from project.access import (
|
from project.access import (
|
||||||
access_or_401,
|
access_or_401,
|
||||||
admin_unit_suggestions_enabled_or_404,
|
admin_unit_suggestions_enabled_or_404,
|
||||||
|
can_current_user_delete_member,
|
||||||
get_admin_unit_for_manage_or_404,
|
get_admin_unit_for_manage_or_404,
|
||||||
get_admin_units_for_manage,
|
get_admin_units_for_manage,
|
||||||
has_access,
|
has_access,
|
||||||
)
|
)
|
||||||
from project.celery_tasks import dump_admin_unit_task
|
from project.celery_tasks import dump_admin_unit_task
|
||||||
from project.forms.admin_unit import UpdateAdminUnitWidgetForm
|
from project.forms.admin_unit import (
|
||||||
|
AdminUnitDeleteMembershipForm,
|
||||||
|
UpdateAdminUnitWidgetForm,
|
||||||
|
)
|
||||||
from project.forms.event import FindEventForm
|
from project.forms.event import FindEventForm
|
||||||
from project.forms.event_place import FindEventPlaceForm
|
from project.forms.event_place import FindEventPlaceForm
|
||||||
from project.models import (
|
from project.models import (
|
||||||
@ -37,6 +41,7 @@ from project.services.admin_unit import (
|
|||||||
get_admin_unit_member_invitations,
|
get_admin_unit_member_invitations,
|
||||||
get_admin_unit_organization_invitations,
|
get_admin_unit_organization_invitations,
|
||||||
get_admin_unit_query,
|
get_admin_unit_query,
|
||||||
|
get_member_for_admin_unit_by_user_id,
|
||||||
)
|
)
|
||||||
from project.services.event import get_events_query
|
from project.services.event import get_events_query
|
||||||
from project.services.event_search import EventSearchParams
|
from project.services.event_search import EventSearchParams
|
||||||
@ -49,6 +54,7 @@ from project.views.utils import (
|
|||||||
get_current_admin_unit,
|
get_current_admin_unit,
|
||||||
get_pagination_urls,
|
get_pagination_urls,
|
||||||
handleSqlError,
|
handleSqlError,
|
||||||
|
non_match_for_deletion,
|
||||||
permission_missing,
|
permission_missing,
|
||||||
set_current_admin_unit,
|
set_current_admin_unit,
|
||||||
)
|
)
|
||||||
@ -280,6 +286,54 @@ def manage_admin_unit_members(id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/manage/admin_unit/<int:id>/membership/delete", methods=("GET", "POST"))
|
||||||
|
@auth_required()
|
||||||
|
def manage_admin_unit_delete_membership(id):
|
||||||
|
admin_unit = get_admin_unit_for_manage_or_404(id)
|
||||||
|
set_current_admin_unit(admin_unit)
|
||||||
|
|
||||||
|
member = get_member_for_admin_unit_by_user_id(
|
||||||
|
admin_unit.id,
|
||||||
|
current_user.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not member:
|
||||||
|
# E.g. global admin
|
||||||
|
flash(gettext("You are not a member of this organization"), "danger")
|
||||||
|
return redirect(url_for("manage_admin_unit_members", id=id))
|
||||||
|
|
||||||
|
if not can_current_user_delete_member(member):
|
||||||
|
flash(
|
||||||
|
gettext("Last remaining administrator can not leave the organization."),
|
||||||
|
"danger",
|
||||||
|
)
|
||||||
|
return redirect(url_for("manage_admin_unit_members", id=id))
|
||||||
|
|
||||||
|
form = AdminUnitDeleteMembershipForm()
|
||||||
|
|
||||||
|
if form.validate_on_submit():
|
||||||
|
if non_match_for_deletion(form.name.data, admin_unit.name):
|
||||||
|
flash(gettext("Entered name does not match organization name"), "danger")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
db.session.delete(member)
|
||||||
|
db.session.commit()
|
||||||
|
flash(gettext("Organization successfully left"), "success")
|
||||||
|
return redirect(url_for("manage_admin_units"))
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
db.session.rollback()
|
||||||
|
flash(handleSqlError(e), "danger")
|
||||||
|
else:
|
||||||
|
flash_errors(form)
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"manage/delete_membership.html",
|
||||||
|
admin_unit=admin_unit,
|
||||||
|
member=member,
|
||||||
|
form=form,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/manage/admin_unit/<int:id>/relations")
|
@app.route("/manage/admin_unit/<int:id>/relations")
|
||||||
@app.route("/manage/admin_unit/<int:id>/relations/<path:path>")
|
@app.route("/manage/admin_unit/<int:id>/relations/<path:path>")
|
||||||
@auth_required()
|
@auth_required()
|
||||||
|
|||||||
@ -121,7 +121,12 @@ class Seeder(object):
|
|||||||
verify=True,
|
verify=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_admin_unit_member(self, admin_unit_id, role_names):
|
def create_admin_unit_member(
|
||||||
|
self,
|
||||||
|
admin_unit_id,
|
||||||
|
role_names,
|
||||||
|
email="test@test.de",
|
||||||
|
):
|
||||||
from project.services.admin_unit import (
|
from project.services.admin_unit import (
|
||||||
add_user_to_admin_unit_with_roles,
|
add_user_to_admin_unit_with_roles,
|
||||||
get_admin_unit_by_id,
|
get_admin_unit_by_id,
|
||||||
@ -129,7 +134,7 @@ class Seeder(object):
|
|||||||
from project.services.user import get_user
|
from project.services.user import get_user
|
||||||
|
|
||||||
with self._app.app_context():
|
with self._app.app_context():
|
||||||
user_id = self.create_user()
|
user_id = self.create_user(email=email)
|
||||||
user = get_user(user_id)
|
user = get_user(user_id)
|
||||||
admin_unit = get_admin_unit_by_id(admin_unit_id)
|
admin_unit = get_admin_unit_by_id(admin_unit_id)
|
||||||
member = add_user_to_admin_unit_with_roles(user, admin_unit, role_names)
|
member = add_user_to_admin_unit_with_roles(user, admin_unit, role_names)
|
||||||
@ -188,8 +193,12 @@ class Seeder(object):
|
|||||||
if remove_favorite_event(user_id, event_id):
|
if remove_favorite_event(user_id, event_id):
|
||||||
self._db.session.commit()
|
self._db.session.commit()
|
||||||
|
|
||||||
def create_admin_unit_member_event_verifier(self, admin_unit_id):
|
def create_admin_unit_member_event_verifier(
|
||||||
return self.create_admin_unit_member(admin_unit_id, ["event_verifier"])
|
self,
|
||||||
|
admin_unit_id,
|
||||||
|
email="test@test.de",
|
||||||
|
):
|
||||||
|
return self.create_admin_unit_member(admin_unit_id, ["event_verifier"], email)
|
||||||
|
|
||||||
def upsert_event_place(self, admin_unit_id, name, location=None):
|
def upsert_event_place(self, admin_unit_id, name, location=None):
|
||||||
from project.services.place import upsert_event_place
|
from project.services.place import upsert_event_place
|
||||||
|
|||||||
@ -246,8 +246,8 @@ class UtilActions(object):
|
|||||||
url = self.get_image_url(image, **values)
|
url = self.get_image_url(image, **values)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def get(self, url):
|
def get(self, url, **kwargs):
|
||||||
response = self._client.get(url)
|
response = self._client.get(url, **kwargs)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self._ajax_csrf = self.get_ajax_csrf(response)
|
self._ajax_csrf = self.get_ajax_csrf(response)
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from tests.seeder import Seeder
|
||||||
|
from tests.utils import UtilActions
|
||||||
|
|
||||||
|
|
||||||
def test_update(client, app, utils, seeder):
|
def test_update(client, app, utils, seeder):
|
||||||
seeder.create_user()
|
seeder.create_user()
|
||||||
user_id = utils.login()
|
user_id = utils.login()
|
||||||
@ -63,14 +69,25 @@ def test_update_permission_missing(client, app, db, utils, seeder):
|
|||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
|
|
||||||
|
|
||||||
def test_delete(client, app, utils, seeder):
|
@pytest.mark.parametrize("scenario", ["default", "current_user"])
|
||||||
|
def test_delete(client, app, db, utils: UtilActions, seeder: Seeder, scenario: str):
|
||||||
seeder.create_user()
|
seeder.create_user()
|
||||||
user_id = utils.login()
|
user_id = utils.login()
|
||||||
admin_unit_id = seeder.create_admin_unit(user_id, "Meine Crew")
|
admin_unit_id = seeder.create_admin_unit(user_id, "Meine Crew")
|
||||||
member_id = seeder.create_admin_unit_member_event_verifier(admin_unit_id)
|
member_email = "test@test.de" if scenario == "current_user" else "member@test.de"
|
||||||
|
member_id = seeder.create_admin_unit_member_event_verifier(
|
||||||
|
admin_unit_id, email=member_email
|
||||||
|
)
|
||||||
|
|
||||||
url = "/manage/member/%d/delete" % member_id
|
url = "/manage/member/%d/delete" % member_id
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
|
|
||||||
|
if scenario == "current_user":
|
||||||
|
utils.assert_response_redirect(
|
||||||
|
response, "manage_admin_unit_delete_membership", id=admin_unit_id
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
with client:
|
with client:
|
||||||
@ -78,7 +95,7 @@ def test_delete(client, app, utils, seeder):
|
|||||||
url,
|
url,
|
||||||
data={
|
data={
|
||||||
"csrf_token": utils.get_csrf(response),
|
"csrf_token": utils.get_csrf(response),
|
||||||
"email": "Test@test.de",
|
"email": "member@test.de",
|
||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -95,7 +112,9 @@ def test_delete_db_error(client, app, utils, seeder, mocker):
|
|||||||
seeder.create_user()
|
seeder.create_user()
|
||||||
user_id = utils.login()
|
user_id = utils.login()
|
||||||
admin_unit_id = seeder.create_admin_unit(user_id, "Meine Crew")
|
admin_unit_id = seeder.create_admin_unit(user_id, "Meine Crew")
|
||||||
member_id = seeder.create_admin_unit_member_event_verifier(admin_unit_id)
|
member_id = seeder.create_admin_unit_member_event_verifier(
|
||||||
|
admin_unit_id, email="member@test.de"
|
||||||
|
)
|
||||||
|
|
||||||
url = "/manage/member/%d/delete" % member_id
|
url = "/manage/member/%d/delete" % member_id
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
@ -108,7 +127,7 @@ def test_delete_db_error(client, app, utils, seeder, mocker):
|
|||||||
url,
|
url,
|
||||||
data={
|
data={
|
||||||
"csrf_token": utils.get_csrf(response),
|
"csrf_token": utils.get_csrf(response),
|
||||||
"email": "test@test.de",
|
"email": "member@test.de",
|
||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -121,7 +140,9 @@ def test_delete_email_does_not_match(client, app, utils, seeder):
|
|||||||
seeder.create_user()
|
seeder.create_user()
|
||||||
user_id = utils.login()
|
user_id = utils.login()
|
||||||
admin_unit_id = seeder.create_admin_unit(user_id, "Meine Crew")
|
admin_unit_id = seeder.create_admin_unit(user_id, "Meine Crew")
|
||||||
member_id = seeder.create_admin_unit_member_event_verifier(admin_unit_id)
|
member_id = seeder.create_admin_unit_member_event_verifier(
|
||||||
|
admin_unit_id, email="member@test.de"
|
||||||
|
)
|
||||||
|
|
||||||
url = "/manage/member/%d/delete" % member_id
|
url = "/manage/member/%d/delete" % member_id
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
@ -138,14 +159,3 @@ def test_delete_email_does_not_match(client, app, utils, seeder):
|
|||||||
)
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert b"Die eingegebene Email passt nicht zur Email" in response.data
|
assert b"Die eingegebene Email passt nicht zur Email" in response.data
|
||||||
|
|
||||||
|
|
||||||
def test_delete_permission_missing(client, app, db, utils, seeder):
|
|
||||||
owner_id = seeder.create_user("owner@owner")
|
|
||||||
admin_unit_id = seeder.create_admin_unit(owner_id, "Other crew")
|
|
||||||
member_id = seeder.create_admin_unit_member_event_verifier(admin_unit_id)
|
|
||||||
utils.login()
|
|
||||||
|
|
||||||
url = "/manage/member/%d/delete" % member_id
|
|
||||||
response = client.get(url)
|
|
||||||
assert response.status_code == 302
|
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from tests.seeder import Seeder
|
||||||
|
from tests.utils import UtilActions
|
||||||
|
|
||||||
|
|
||||||
def test_index_noCookie(client, seeder, utils):
|
def test_index_noCookie(client, seeder, utils):
|
||||||
user_id, admin_unit_id = seeder.setup_base()
|
user_id, admin_unit_id = seeder.setup_base()
|
||||||
@ -248,3 +251,85 @@ def test_verification_requests_outgoing(client, seeder, utils):
|
|||||||
)
|
)
|
||||||
utils.assert_response_contains(response, "Stadtmarketing")
|
utils.assert_response_contains(response, "Stadtmarketing")
|
||||||
utils.assert_response_contains(response, "Please give us a call")
|
utils.assert_response_contains(response, "Please give us a call")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("scenario", ["db_error", "default", "last_admin", "non_match"])
|
||||||
|
def test_manage_admin_unit_delete_membership(
|
||||||
|
client, utils: UtilActions, seeder: Seeder, app, db, mocker, scenario: str
|
||||||
|
):
|
||||||
|
user_id, admin_unit_id = seeder.setup_base()
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
from project.services.admin_unit import get_member_for_admin_unit_by_user_id
|
||||||
|
|
||||||
|
member = get_member_for_admin_unit_by_user_id(
|
||||||
|
admin_unit_id,
|
||||||
|
user_id,
|
||||||
|
)
|
||||||
|
member_id = member.id
|
||||||
|
|
||||||
|
if not scenario == "last_admin":
|
||||||
|
seeder.create_admin_unit_member(
|
||||||
|
admin_unit_id, ["admin"], "admin.member@test.de"
|
||||||
|
)
|
||||||
|
|
||||||
|
url = utils.get_url("manage_admin_unit_delete_membership", id=admin_unit_id)
|
||||||
|
|
||||||
|
if scenario == "last_admin":
|
||||||
|
response = utils.get(url, follow_redirects=True)
|
||||||
|
utils.assert_response_error_message(
|
||||||
|
response,
|
||||||
|
"Der letzte verbleibende Administrator kann die Organisation nicht verlassen.",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
response = utils.get_ok(url)
|
||||||
|
|
||||||
|
if scenario == "db_error":
|
||||||
|
utils.mock_db_commit(mocker)
|
||||||
|
|
||||||
|
form_name = "Meine Crew"
|
||||||
|
|
||||||
|
if scenario == "non_match":
|
||||||
|
form_name = "wrong"
|
||||||
|
|
||||||
|
response = utils.post_form(
|
||||||
|
url,
|
||||||
|
response,
|
||||||
|
{
|
||||||
|
"name": form_name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if scenario == "non_match":
|
||||||
|
utils.assert_response_error_message(
|
||||||
|
response, "Der eingegebene Name entspricht nicht dem Namen der Organisation"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if scenario == "db_error":
|
||||||
|
utils.assert_response_db_error(response)
|
||||||
|
return
|
||||||
|
|
||||||
|
utils.assert_response_redirect(response, "manage_admin_units")
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
from project.models import AdminUnitMember
|
||||||
|
|
||||||
|
assert db.session.get(AdminUnitMember, member_id) is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_manage_admin_unit_delete_membership_no_member(
|
||||||
|
client, utils: UtilActions, seeder: Seeder, app, db
|
||||||
|
):
|
||||||
|
user_id, admin_unit_id = seeder.setup_base(admin=True)
|
||||||
|
other_user_id, other_admin_unit_id = seeder.setup_base(
|
||||||
|
log_in=False, email="other@test.de", name="Other Crew"
|
||||||
|
)
|
||||||
|
|
||||||
|
url = utils.get_url("manage_admin_unit_delete_membership", id=other_admin_unit_id)
|
||||||
|
response = utils.get(url, follow_redirects=True)
|
||||||
|
utils.assert_response_error_message(
|
||||||
|
response,
|
||||||
|
"Du bist kein Mitglied dieser Organisation",
|
||||||
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user