#169 Admin on teams

* adds admin column on team index view
* refactors Team model, so multiple members can become admins
* adds team migration for switch from fkey->m2m structure
* renames 'Group' to 'Permission' on user index view to avoid confusion between 'Groups' and Teams
* adds new autocomplete route for team-admin selection based on already selected members of the TeamForm
pull/170/head
mpeltriaux 2 years ago
parent b790921e42
commit 170e5798ec

@ -108,6 +108,29 @@ class ShareTeamAutocomplete(Select2QuerySetView):
return qs return qs
class TeamAdminAutocomplete(Select2QuerySetView):
""" Autocomplete for share with teams
"""
def get_queryset(self):
if self.request.user.is_anonymous:
return User.objects.none()
qs = User.objects.filter(
id__in=self.forwarded.get("members", [])
).exclude(
id__in=self.forwarded.get("admins", [])
)
if self.q:
# Due to privacy concerns only a full username match will return the proper user entry
qs = qs.filter(
name__icontains=self.q
)
qs = qs.order_by(
"username"
)
return qs
class KonovaCodeAutocomplete(Select2GroupQuerySetView): class KonovaCodeAutocomplete(Select2GroupQuerySetView):
""" """
Provides simple autocomplete functionality for codes Provides simple autocomplete functionality for codes

@ -326,7 +326,7 @@ class SimpleGeomForm(BaseForm):
features = [] features = []
features_json = geom.get("features", []) features_json = geom.get("features", [])
for feature in features_json: for feature in features_json:
g = gdal.OGRGeometry(json.dumps(feature["geometry"]), srs=DEFAULT_SRID_RLP) g = gdal.OGRGeometry(json.dumps(feature.get("geometry", feature)), srs=DEFAULT_SRID_RLP)
if g.geom_type not in ["Polygon", "MultiPolygon"]: if g.geom_type not in ["Polygon", "MultiPolygon"]:
self.add_error("geom", _("Only surfaces allowed. Points or lines must be buffered.")) self.add_error("geom", _("Only surfaces allowed. Points or lines must be buffered."))
is_valid = False is_valid = False

@ -72,6 +72,7 @@ class AutocompleteTestCase(BaseTestCase):
"codes-conservation-office-autocomplete", "codes-conservation-office-autocomplete",
"share-user-autocomplete", "share-user-autocomplete",
"share-team-autocomplete", "share-team-autocomplete",
"team-admin-autocomplete",
] ]
for test in tests: for test in tests:
self.client.login(username=self.superuser.username, password=self.superuser_pw) self.client.login(username=self.superuser.username, password=self.superuser_pw)

@ -274,7 +274,7 @@ class BaseTestCase(TestCase):
team = Team.objects.get_or_create( team = Team.objects.get_or_create(
name="Testteam", name="Testteam",
description="Testdescription", description="Testdescription",
admin=self.superuser, admins__in=[self.superuser],
)[0] )[0]
team.users.add(self.superuser) team.users.add(self.superuser)

@ -21,7 +21,7 @@ from konova.autocompletes import EcoAccountAutocomplete, \
InterventionAutocomplete, CompensationActionCodeAutocomplete, BiotopeCodeAutocomplete, LawCodeAutocomplete, \ InterventionAutocomplete, CompensationActionCodeAutocomplete, BiotopeCodeAutocomplete, LawCodeAutocomplete, \
RegistrationOfficeCodeAutocomplete, ConservationOfficeCodeAutocomplete, ProcessTypeCodeAutocomplete, \ RegistrationOfficeCodeAutocomplete, ConservationOfficeCodeAutocomplete, ProcessTypeCodeAutocomplete, \
ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete, \ ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete, \
ShareTeamAutocomplete, HandlerCodeAutocomplete ShareTeamAutocomplete, HandlerCodeAutocomplete, TeamAdminAutocomplete
from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
from konova.sso.sso import KonovaSSOClient from konova.sso.sso import KonovaSSOClient
from konova.views import logout_view, home_view, get_geom_parcels, get_geom_parcels_content, map_client_proxy_view from konova.views import logout_view, home_view, get_geom_parcels, get_geom_parcels_content, map_client_proxy_view
@ -58,6 +58,7 @@ urlpatterns = [
path("atcmplt/codes/handler", HandlerCodeAutocomplete.as_view(), name="codes-handler-autocomplete"), path("atcmplt/codes/handler", HandlerCodeAutocomplete.as_view(), name="codes-handler-autocomplete"),
path("atcmplt/share/u", ShareUserAutocomplete.as_view(), name="share-user-autocomplete"), path("atcmplt/share/u", ShareUserAutocomplete.as_view(), name="share-user-autocomplete"),
path("atcmplt/share/t", ShareTeamAutocomplete.as_view(), name="share-team-autocomplete"), path("atcmplt/share/t", ShareTeamAutocomplete.as_view(), name="share-team-autocomplete"),
path("atcmplt/team/admin", TeamAdminAutocomplete.as_view(), name="team-admin-autocomplete"),
] ]
if DEBUG: if DEBUG:

Binary file not shown.

@ -26,7 +26,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-30 09:16+0200\n" "POT-Creation-Date: 2022-05-30 11:51+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"
@ -65,7 +65,7 @@ msgstr "Verantwortliche Stelle"
#: intervention/forms/forms.py:64 intervention/forms/forms.py:81 #: intervention/forms/forms.py:64 intervention/forms/forms.py:81
#: intervention/forms/forms.py:97 intervention/forms/forms.py:113 #: intervention/forms/forms.py:97 intervention/forms/forms.py:113
#: intervention/forms/forms.py:154 intervention/forms/modalForms.py:49 #: intervention/forms/forms.py:154 intervention/forms/modalForms.py:49
#: intervention/forms/modalForms.py:63 user/forms.py:196 #: intervention/forms/modalForms.py:63 user/forms.py:196 user/forms.py:260
msgid "Click for selection" msgid "Click for selection"
msgstr "Auswählen..." msgstr "Auswählen..."
@ -138,11 +138,11 @@ msgstr "Zuständigkeitsbereich"
#: analysis/templates/analysis/reports/includes/intervention/amount.html:17 #: analysis/templates/analysis/reports/includes/intervention/amount.html:17
#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:8 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:8
#: analysis/templates/analysis/reports/includes/intervention/laws.html:17 #: analysis/templates/analysis/reports/includes/intervention/laws.html:17
#: compensation/tables.py:41 #: compensation/tables.py:38
#: compensation/templates/compensation/detail/compensation/view.html:64 #: compensation/templates/compensation/detail/compensation/view.html:64
#: intervention/tables.py:40 #: intervention/tables.py:38
#: intervention/templates/intervention/detail/view.html:68 #: intervention/templates/intervention/detail/view.html:68
#: user/models/user_action.py:20 #: user/models/user_action.py:21
msgid "Checked" msgid "Checked"
msgstr "Geprüft" msgstr "Geprüft"
@ -154,14 +154,14 @@ msgstr "Geprüft"
#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:9 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:9
#: analysis/templates/analysis/reports/includes/intervention/laws.html:20 #: analysis/templates/analysis/reports/includes/intervention/laws.html:20
#: analysis/templates/analysis/reports/includes/old_data/amount.html:18 #: analysis/templates/analysis/reports/includes/old_data/amount.html:18
#: compensation/tables.py:47 compensation/tables.py:230 #: compensation/tables.py:44 compensation/tables.py:219
#: compensation/templates/compensation/detail/compensation/view.html:78 #: compensation/templates/compensation/detail/compensation/view.html:83
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:31 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:31
#: compensation/templates/compensation/detail/eco_account/view.html:45 #: compensation/templates/compensation/detail/eco_account/view.html:45
#: ema/tables.py:44 ema/templates/ema/detail/view.html:35 #: ema/tables.py:44 ema/templates/ema/detail/view.html:35
#: intervention/tables.py:46 #: intervention/tables.py:44
#: intervention/templates/intervention/detail/view.html:82 #: intervention/templates/intervention/detail/view.html:87
#: user/models/user_action.py:21 #: user/models/user_action.py:22
msgid "Recorded" msgid "Recorded"
msgstr "Verzeichnet" msgstr "Verzeichnet"
@ -198,7 +198,7 @@ msgid "Other registration office"
msgstr "Andere Zulassungsbehörden" msgstr "Andere Zulassungsbehörden"
#: analysis/templates/analysis/reports/includes/compensation/card_compensation.html:11 #: analysis/templates/analysis/reports/includes/compensation/card_compensation.html:11
#: compensation/tables.py:68 #: compensation/tables.py:65
#: intervention/templates/intervention/detail/includes/compensations.html:8 #: intervention/templates/intervention/detail/includes/compensations.html:8
#: intervention/templates/intervention/report/report.html:45 #: intervention/templates/intervention/report/report.html:45
msgid "Compensations" msgid "Compensations"
@ -227,7 +227,7 @@ msgid "Surface"
msgstr "Fläche" msgstr "Fläche"
#: analysis/templates/analysis/reports/includes/intervention/card_intervention.html:10 #: analysis/templates/analysis/reports/includes/intervention/card_intervention.html:10
#: intervention/tables.py:67 #: intervention/tables.py:65
msgid "Interventions" msgid "Interventions"
msgstr "Eingriffe" msgstr "Eingriffe"
@ -285,8 +285,8 @@ msgid "Type"
msgstr "Typ" msgstr "Typ"
#: analysis/templates/analysis/reports/includes/old_data/amount.html:24 #: analysis/templates/analysis/reports/includes/old_data/amount.html:24
#: compensation/tables.py:90 intervention/forms/modalForms.py:375 #: compensation/tables.py:87 intervention/forms/modalForms.py:375
#: intervention/forms/modalForms.py:382 intervention/tables.py:89 #: intervention/forms/modalForms.py:382 intervention/tables.py:87
#: intervention/templates/intervention/detail/view.html:19 #: intervention/templates/intervention/detail/view.html:19
#: konova/templates/konova/includes/quickstart/interventions.html:4 #: konova/templates/konova/includes/quickstart/interventions.html:4
#: templates/navbars/navbar.html:22 #: templates/navbars/navbar.html:22
@ -294,7 +294,7 @@ msgid "Intervention"
msgstr "Eingriff" msgstr "Eingriff"
#: analysis/templates/analysis/reports/includes/old_data/amount.html:34 #: analysis/templates/analysis/reports/includes/old_data/amount.html:34
#: compensation/tables.py:274 #: compensation/tables.py:263
#: compensation/templates/compensation/detail/eco_account/view.html:20 #: compensation/templates/compensation/detail/eco_account/view.html:20
#: intervention/forms/modalForms.py:348 intervention/forms/modalForms.py:355 #: intervention/forms/modalForms.py:348 intervention/forms/modalForms.py:355
#: konova/templates/konova/includes/quickstart/ecoaccounts.html:4 #: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
@ -314,9 +314,9 @@ msgstr "Vor"
msgid "Show only unrecorded" msgid "Show only unrecorded"
msgstr "Nur unverzeichnete anzeigen" msgstr "Nur unverzeichnete anzeigen"
#: compensation/forms/forms.py:32 compensation/tables.py:26 #: compensation/forms/forms.py:32 compensation/tables.py:23
#: compensation/tables.py:205 ema/tables.py:29 intervention/forms/forms.py:28 #: compensation/tables.py:194 ema/tables.py:29 intervention/forms/forms.py:28
#: intervention/tables.py:25 #: intervention/tables.py:23
#: intervention/templates/intervention/detail/includes/compensations.html:30 #: intervention/templates/intervention/detail/includes/compensations.html:30
msgid "Identifier" msgid "Identifier"
msgstr "Kennung" msgstr "Kennung"
@ -326,8 +326,8 @@ msgstr "Kennung"
msgid "Generated automatically" msgid "Generated automatically"
msgstr "Automatisch generiert" msgstr "Automatisch generiert"
#: compensation/forms/forms.py:44 compensation/tables.py:31 #: compensation/forms/forms.py:44 compensation/tables.py:28
#: compensation/tables.py:210 #: compensation/tables.py:199
#: compensation/templates/compensation/detail/compensation/includes/documents.html:28 #: compensation/templates/compensation/detail/compensation/includes/documents.html:28
#: compensation/templates/compensation/detail/compensation/view.html:32 #: compensation/templates/compensation/detail/compensation/view.html:32
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:28 #: compensation/templates/compensation/detail/eco_account/includes/documents.html:28
@ -337,7 +337,7 @@ msgstr "Automatisch generiert"
#: ema/tables.py:34 ema/templates/ema/detail/includes/documents.html:28 #: ema/tables.py:34 ema/templates/ema/detail/includes/documents.html:28
#: ema/templates/ema/detail/view.html:31 #: ema/templates/ema/detail/view.html:31
#: ema/templates/ema/report/report.html:12 intervention/forms/forms.py:40 #: ema/templates/ema/report/report.html:12 intervention/forms/forms.py:40
#: intervention/tables.py:30 #: intervention/tables.py:28
#: intervention/templates/intervention/detail/includes/compensations.html:33 #: intervention/templates/intervention/detail/includes/compensations.html:33
#: intervention/templates/intervention/detail/includes/documents.html:28 #: intervention/templates/intervention/detail/includes/documents.html:28
#: intervention/templates/intervention/detail/view.html:31 #: intervention/templates/intervention/detail/view.html:31
@ -675,62 +675,62 @@ msgstr ""
"Es wurde bereits mehr Fläche abgebucht, als Sie nun als abbuchbar einstellen " "Es wurde bereits mehr Fläche abgebucht, als Sie nun als abbuchbar einstellen "
"wollen. Kontaktieren Sie die für die Abbuchungen verantwortlichen Nutzer!" "wollen. Kontaktieren Sie die für die Abbuchungen verantwortlichen Nutzer!"
#: compensation/tables.py:36 compensation/tables.py:215 ema/tables.py:39 #: compensation/tables.py:33 compensation/tables.py:204 ema/tables.py:39
#: intervention/tables.py:35 konova/filters/mixins.py:98 #: intervention/tables.py:33 konova/filters/mixins.py:98
msgid "Parcel gmrkng" msgid "Parcel gmrkng"
msgstr "Gemarkung" msgstr "Gemarkung"
#: compensation/tables.py:53 compensation/tables.py:236 ema/tables.py:50 #: compensation/tables.py:50 compensation/tables.py:225 ema/tables.py:50
#: intervention/tables.py:52 #: intervention/tables.py:50
msgid "Editable" msgid "Editable"
msgstr "Freigegeben" msgstr "Freigegeben"
#: compensation/tables.py:59 compensation/tables.py:242 ema/tables.py:56 #: compensation/tables.py:56 compensation/tables.py:231 ema/tables.py:56
#: intervention/tables.py:58 #: intervention/tables.py:56
msgid "Last edit" msgid "Last edit"
msgstr "Zuletzt bearbeitet" msgstr "Zuletzt bearbeitet"
#: compensation/tables.py:90 compensation/tables.py:274 ema/tables.py:89 #: compensation/tables.py:87 compensation/tables.py:263 ema/tables.py:89
#: intervention/tables.py:89 #: intervention/tables.py:87
msgid "Open {}" msgid "Open {}"
msgstr "Öffne {}" msgstr "Öffne {}"
#: compensation/tables.py:170 #: compensation/tables.py:163
#: compensation/templates/compensation/detail/compensation/view.html:81 #: compensation/templates/compensation/detail/compensation/view.html:86
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:58 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:58
#: compensation/templates/compensation/detail/eco_account/view.html:48 #: compensation/templates/compensation/detail/eco_account/view.html:48
#: ema/tables.py:131 ema/templates/ema/detail/view.html:38 #: ema/tables.py:130 ema/templates/ema/detail/view.html:38
#: intervention/tables.py:167 #: intervention/tables.py:161
#: intervention/templates/intervention/detail/view.html:85 #: intervention/templates/intervention/detail/view.html:90
msgid "Not recorded yet" msgid "Not recorded yet"
msgstr "Noch nicht verzeichnet" msgstr "Noch nicht verzeichnet"
#: compensation/tables.py:175 compensation/tables.py:334 ema/tables.py:136 #: compensation/tables.py:166 compensation/tables.py:321 ema/tables.py:133
#: intervention/tables.py:172 #: intervention/tables.py:164
msgid "Recorded on {} by {}" msgid "Recorded on {} by {}"
msgstr "Am {} von {} verzeichnet worden" msgstr "Am {} von {} verzeichnet worden"
#: compensation/tables.py:197 compensation/tables.py:356 ema/tables.py:157 #: compensation/tables.py:186 compensation/tables.py:343 ema/tables.py:154
#: intervention/tables.py:193 #: intervention/tables.py:185
msgid "Full access granted" msgid "Full access granted"
msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden" msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden"
#: compensation/tables.py:197 compensation/tables.py:356 ema/tables.py:157 #: compensation/tables.py:186 compensation/tables.py:343 ema/tables.py:154
#: intervention/tables.py:193 #: intervention/tables.py:185
msgid "Access not granted" msgid "Access not granted"
msgstr "Nicht freigegeben - Datensatz nur lesbar" msgstr "Nicht freigegeben - Datensatz nur lesbar"
#: compensation/tables.py:220 #: compensation/tables.py:209
#: compensation/templates/compensation/detail/eco_account/view.html:36 #: compensation/templates/compensation/detail/eco_account/view.html:36
#: konova/templates/konova/widgets/progressbar.html:3 #: konova/templates/konova/widgets/progressbar.html:3
msgid "Available" msgid "Available"
msgstr "Verfügbar" msgstr "Verfügbar"
#: compensation/tables.py:251 #: compensation/tables.py:240
msgid "Eco Accounts" msgid "Eco Accounts"
msgstr "Ökokonten" msgstr "Ökokonten"
#: compensation/tables.py:329 #: compensation/tables.py:318
msgid "Not recorded yet. Can not be used for deductions, yet." msgid "Not recorded yet. Can not be used for deductions, yet."
msgstr "" msgstr ""
"Noch nicht verzeichnet. Kann noch nicht für Abbuchungen genutzt werden." "Noch nicht verzeichnet. Kann noch nicht für Abbuchungen genutzt werden."
@ -782,7 +782,7 @@ msgstr "Menge"
#: intervention/templates/intervention/detail/includes/documents.html:39 #: intervention/templates/intervention/detail/includes/documents.html:39
#: intervention/templates/intervention/detail/includes/payments.html:39 #: intervention/templates/intervention/detail/includes/payments.html:39
#: intervention/templates/intervention/detail/includes/revocation.html:43 #: intervention/templates/intervention/detail/includes/revocation.html:43
#: templates/log.html:10 user/templates/user/team/index.html:32 #: templates/log.html:10 user/templates/user/team/index.html:33
msgid "Action" msgid "Action"
msgstr "Aktionen" msgstr "Aktionen"
@ -975,43 +975,43 @@ msgstr "Nein"
msgid "Is Coherence keeping compensation" msgid "Is Coherence keeping compensation"
msgstr "Ist Kohärenzsicherungsmaßnahme" msgstr "Ist Kohärenzsicherungsmaßnahme"
#: compensation/templates/compensation/detail/compensation/view.html:71 #: compensation/templates/compensation/detail/compensation/view.html:76
#: intervention/templates/intervention/detail/view.html:75 #: intervention/templates/intervention/detail/view.html:80
msgid "Checked on " msgid "Checked on "
msgstr "Geprüft am " msgstr "Geprüft am "
#: compensation/templates/compensation/detail/compensation/view.html:71 #: compensation/templates/compensation/detail/compensation/view.html:76
#: compensation/templates/compensation/detail/compensation/view.html:85 #: compensation/templates/compensation/detail/compensation/view.html:90
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:56 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:56
#: compensation/templates/compensation/detail/eco_account/view.html:52 #: compensation/templates/compensation/detail/eco_account/view.html:52
#: ema/templates/ema/detail/view.html:42 #: ema/templates/ema/detail/view.html:42
#: intervention/templates/intervention/detail/view.html:75 #: intervention/templates/intervention/detail/view.html:80
#: intervention/templates/intervention/detail/view.html:89 #: intervention/templates/intervention/detail/view.html:94
msgid "by" msgid "by"
msgstr "von" msgstr "von"
#: compensation/templates/compensation/detail/compensation/view.html:85 #: compensation/templates/compensation/detail/compensation/view.html:90
#: compensation/templates/compensation/detail/eco_account/view.html:52 #: compensation/templates/compensation/detail/eco_account/view.html:52
#: ema/templates/ema/detail/view.html:42 #: ema/templates/ema/detail/view.html:42
#: intervention/templates/intervention/detail/view.html:89 #: intervention/templates/intervention/detail/view.html:94
msgid "Recorded on " msgid "Recorded on "
msgstr "Verzeichnet am" msgstr "Verzeichnet am"
#: compensation/templates/compensation/detail/compensation/view.html:92 #: compensation/templates/compensation/detail/compensation/view.html:97
#: compensation/templates/compensation/detail/eco_account/view.html:75 #: compensation/templates/compensation/detail/eco_account/view.html:75
#: compensation/templates/compensation/report/compensation/report.html:24 #: compensation/templates/compensation/report/compensation/report.html:24
#: compensation/templates/compensation/report/eco_account/report.html:37 #: compensation/templates/compensation/report/eco_account/report.html:37
#: ema/templates/ema/detail/view.html:61 #: ema/templates/ema/detail/view.html:61
#: ema/templates/ema/report/report.html:24 #: ema/templates/ema/report/report.html:24
#: intervention/templates/intervention/detail/view.html:108 #: intervention/templates/intervention/detail/view.html:113
#: intervention/templates/intervention/report/report.html:87 #: intervention/templates/intervention/report/report.html:87
msgid "Last modified" msgid "Last modified"
msgstr "Zuletzt bearbeitet" msgstr "Zuletzt bearbeitet"
#: compensation/templates/compensation/detail/compensation/view.html:106 #: compensation/templates/compensation/detail/compensation/view.html:111
#: compensation/templates/compensation/detail/eco_account/view.html:89 #: compensation/templates/compensation/detail/eco_account/view.html:89
#: ema/templates/ema/detail/view.html:75 #: ema/templates/ema/detail/view.html:75
#: intervention/templates/intervention/detail/view.html:122 #: intervention/templates/intervention/detail/view.html:127
msgid "Shared with" msgid "Shared with"
msgstr "Freigegeben für" msgstr "Freigegeben für"
@ -1050,7 +1050,7 @@ msgstr "Eingriffskennung"
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:37 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:37
#: intervention/templates/intervention/detail/includes/deductions.html:34 #: intervention/templates/intervention/detail/includes/deductions.html:34
#: user/models/user_action.py:23 #: user/models/user_action.py:24
msgid "Created" msgid "Created"
msgstr "Erstellt" msgstr "Erstellt"
@ -1087,8 +1087,8 @@ msgstr "Keine Flächenmenge für Abbuchungen eingegeben. Bitte bearbeiten."
#: intervention/templates/intervention/detail/view.html:55 #: intervention/templates/intervention/detail/view.html:55
#: intervention/templates/intervention/detail/view.html:59 #: intervention/templates/intervention/detail/view.html:59
#: intervention/templates/intervention/detail/view.html:63 #: intervention/templates/intervention/detail/view.html:63
#: intervention/templates/intervention/detail/view.html:95 #: intervention/templates/intervention/detail/view.html:100
#: intervention/templates/intervention/detail/view.html:99 #: intervention/templates/intervention/detail/view.html:104
msgid "Missing" msgid "Missing"
msgstr "fehlt" msgstr "fehlt"
@ -1142,17 +1142,17 @@ msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet" msgstr "Kompensation {} bearbeitet"
#: compensation/views/compensation.py:182 compensation/views/eco_account.py:173 #: compensation/views/compensation.py:182 compensation/views/eco_account.py:173
#: ema/views.py:240 intervention/views.py:332 #: ema/views.py:240 intervention/views.py:338
msgid "Edit {}" msgid "Edit {}"
msgstr "Bearbeite {}" msgstr "Bearbeite {}"
#: compensation/views/compensation.py:261 compensation/views/eco_account.py:359 #: compensation/views/compensation.py:268 compensation/views/eco_account.py:359
#: ema/views.py:194 intervention/views.py:536 #: ema/views.py:194 intervention/views.py:542
msgid "Log" msgid "Log"
msgstr "Log" msgstr "Log"
#: compensation/views/compensation.py:605 compensation/views/eco_account.py:727 #: compensation/views/compensation.py:612 compensation/views/eco_account.py:727
#: ema/views.py:558 intervention/views.py:682 #: ema/views.py:558 intervention/views.py:688
msgid "Report {}" msgid "Report {}"
msgstr "Bericht {}" msgstr "Bericht {}"
@ -1173,32 +1173,32 @@ msgid "Eco-account removed"
msgstr "Ökokonto entfernt" msgstr "Ökokonto entfernt"
#: compensation/views/eco_account.py:380 ema/views.py:282 #: compensation/views/eco_account.py:380 ema/views.py:282
#: intervention/views.py:635 #: intervention/views.py:641
msgid "{} unrecorded" msgid "{} unrecorded"
msgstr "{} entzeichnet" msgstr "{} entzeichnet"
#: compensation/views/eco_account.py:380 ema/views.py:282 #: compensation/views/eco_account.py:380 ema/views.py:282
#: intervention/views.py:635 #: intervention/views.py:641
msgid "{} recorded" msgid "{} recorded"
msgstr "{} verzeichnet" msgstr "{} verzeichnet"
#: compensation/views/eco_account.py:804 ema/views.py:628 #: compensation/views/eco_account.py:804 ema/views.py:628
#: intervention/views.py:433 #: intervention/views.py:439
msgid "{} has already been shared with you" msgid "{} has already been shared with you"
msgstr "{} wurde bereits für Sie freigegeben" msgstr "{} wurde bereits für Sie freigegeben"
#: compensation/views/eco_account.py:809 ema/views.py:633 #: compensation/views/eco_account.py:809 ema/views.py:633
#: intervention/views.py:438 #: intervention/views.py:444
msgid "{} has been shared with you" msgid "{} has been shared with you"
msgstr "{} ist nun für Sie freigegeben" msgstr "{} ist nun für Sie freigegeben"
#: compensation/views/eco_account.py:816 ema/views.py:640 #: compensation/views/eco_account.py:816 ema/views.py:640
#: intervention/views.py:445 #: intervention/views.py:451
msgid "Share link invalid" msgid "Share link invalid"
msgstr "Freigabelink ungültig" msgstr "Freigabelink ungültig"
#: compensation/views/eco_account.py:839 ema/views.py:663 #: compensation/views/eco_account.py:839 ema/views.py:663
#: intervention/views.py:468 #: intervention/views.py:474
msgid "Share settings updated" msgid "Share settings updated"
msgstr "Freigabe Einstellungen aktualisiert" msgstr "Freigabe Einstellungen aktualisiert"
@ -1292,14 +1292,14 @@ msgid "Intervention handler detail"
msgstr "Detailangabe zum Eingriffsverursacher" msgstr "Detailangabe zum Eingriffsverursacher"
#: intervention/forms/forms.py:173 #: intervention/forms/forms.py:173
#: intervention/templates/intervention/detail/view.html:96 #: intervention/templates/intervention/detail/view.html:101
#: intervention/templates/intervention/report/report.html:79 #: intervention/templates/intervention/report/report.html:79
#: intervention/utils/quality.py:73 #: intervention/utils/quality.py:73
msgid "Registration date" msgid "Registration date"
msgstr "Datum Zulassung bzw. Satzungsbeschluss" msgstr "Datum Zulassung bzw. Satzungsbeschluss"
#: intervention/forms/forms.py:185 #: intervention/forms/forms.py:185
#: intervention/templates/intervention/detail/view.html:100 #: intervention/templates/intervention/detail/view.html:105
#: intervention/templates/intervention/report/report.html:83 #: intervention/templates/intervention/report/report.html:83
msgid "Binding on" msgid "Binding on"
msgstr "Datum Bestandskraft bzw. Rechtskraft" msgstr "Datum Bestandskraft bzw. Rechtskraft"
@ -1471,7 +1471,7 @@ msgid "Remove payment"
msgstr "Zahlung entfernen" msgstr "Zahlung entfernen"
#: intervention/templates/intervention/detail/includes/revocation.html:8 #: intervention/templates/intervention/detail/includes/revocation.html:8
#: intervention/templates/intervention/detail/view.html:104 #: intervention/templates/intervention/detail/view.html:109
msgid "Revocations" msgid "Revocations"
msgstr "Widersprüche" msgstr "Widersprüche"
@ -1493,7 +1493,7 @@ msgstr "Widerspruch entfernen"
msgid "Intervention handler" msgid "Intervention handler"
msgstr "Eingriffsverursacher" msgstr "Eingriffsverursacher"
#: intervention/templates/intervention/detail/view.html:103 #: intervention/templates/intervention/detail/view.html:108
msgid "Exists" msgid "Exists"
msgstr "vorhanden" msgstr "vorhanden"
@ -1532,19 +1532,19 @@ msgstr "Eingriffe - Übersicht"
msgid "Intervention {} added" msgid "Intervention {} added"
msgstr "Eingriff {} hinzugefügt" msgstr "Eingriff {} hinzugefügt"
#: intervention/views.py:320 #: intervention/views.py:326
msgid "Intervention {} edited" msgid "Intervention {} edited"
msgstr "Eingriff {} bearbeitet" msgstr "Eingriff {} bearbeitet"
#: intervention/views.py:356 #: intervention/views.py:362
msgid "{} removed" msgid "{} removed"
msgstr "{} entfernt" msgstr "{} entfernt"
#: intervention/views.py:489 #: intervention/views.py:495
msgid "Check performed" msgid "Check performed"
msgstr "Prüfung durchgeführt" msgstr "Prüfung durchgeführt"
#: intervention/views.py:640 #: intervention/views.py:646
msgid "There are errors on this intervention:" msgid "There are errors on this intervention:"
msgstr "Es liegen Fehler in diesem Eingriff vor:" msgstr "Es liegen Fehler in diesem Eingriff vor:"
@ -2058,7 +2058,8 @@ msgstr "Am {} von {} geprüft worden"
#: konova/utils/message_templates.py:87 #: konova/utils/message_templates.py:87
msgid "Data has changed since last check on {} by {}" msgid "Data has changed since last check on {} by {}"
msgstr "Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}" msgstr ""
"Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}"
#: konova/utils/message_templates.py:88 #: konova/utils/message_templates.py:88
msgid "Current data not checked yet" msgid "Current data not checked yet"
@ -2547,11 +2548,11 @@ msgstr "Neuen Token generieren"
msgid "A new token needs to be validated by an administrator!" msgid "A new token needs to be validated by an administrator!"
msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!" msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
#: user/forms.py:168 user/forms.py:172 user/forms.py:332 user/forms.py:337 #: user/forms.py:168 user/forms.py:172 user/forms.py:351 user/forms.py:356
msgid "Team name" msgid "Team name"
msgstr "Team Name" msgstr "Team Name"
#: user/forms.py:179 user/forms.py:345 user/templates/user/team/index.html:30 #: user/forms.py:179 user/forms.py:364 user/templates/user/team/index.html:30
msgid "Description" msgid "Description"
msgstr "Beschreibung" msgstr "Beschreibung"
@ -2579,43 +2580,61 @@ msgstr ""
"Sie werden standardmäßig der Administrator dieses Teams. Sie müssen sich " "Sie werden standardmäßig der Administrator dieses Teams. Sie müssen sich "
"selbst nicht zur Liste der Mitglieder hinzufügen." "selbst nicht zur Liste der Mitglieder hinzufügen."
#: user/forms.py:218 user/forms.py:279 #: user/forms.py:218 user/forms.py:296
msgid "Name already taken. Try another." msgid "Name already taken. Try another."
msgstr "Name bereits vergeben. Probieren Sie einen anderen." msgstr "Name bereits vergeben. Probieren Sie einen anderen."
#: user/forms.py:249 #: user/forms.py:248
msgid "Admin" msgid "Admins"
msgstr "Administrator" msgstr "Administratoren"
#: user/forms.py:250 #: user/forms.py:250
msgid "Administrators manage team details and members" msgid "Administrators manage team details and members"
msgstr "Administratoren verwalten die Teamdaten und Mitglieder" msgstr "Administratoren verwalten die Teamdaten und Mitglieder"
#: user/forms.py:263 #: user/forms.py:273
msgid "Selected admin ({}) needs to be a member of this team." msgid "Selected admins need to be members of this team."
msgstr "Gewählter Administrator ({}) muss ein Mitglied des Teams sein." msgstr "Gewählte Administratoren müssen Teammitglieder sein."
#: user/forms.py:280
msgid "There must be at least one admin on this team."
msgstr "Es muss mindestens einen Administrator für das Team geben."
#: user/forms.py:291 user/templates/user/team/index.html:54 #: user/forms.py:308 user/templates/user/team/index.html:60
msgid "Edit team" msgid "Edit team"
msgstr "Team bearbeiten" msgstr "Team bearbeiten"
#: user/forms.py:323 user/templates/user/team/index.html:50 #: user/forms.py:336
msgid ""
"ATTENTION!\n"
"\n"
"Removing the team means all members will lose their access to data, based on "
"this team! \n"
"\n"
"Are you sure to remove this team?"
msgstr ""
"ACHTUNG!\n\n"
"Wenn dieses Team gelöscht wird, verlieren alle Teammitglieder den Zugriff auf die Daten, die nur über dieses Team freigegeben sind!\n"
"\n"
"Sind Sie sicher, dass Sie dieses Team löschen möchten?"
#: user/forms.py:342 user/templates/user/team/index.html:56
msgid "Leave team" msgid "Leave team"
msgstr "Team verlassen" msgstr "Team verlassen"
#: user/forms.py:356 #: user/forms.py:375
msgid "Team" msgid "Team"
msgstr "Team" msgstr "Team"
#: user/models/user_action.py:22 #: user/models/user_action.py:23
msgid "Unrecorded" msgid "Unrecorded"
msgstr "Entzeichnet" msgstr "Entzeichnet"
#: user/models/user_action.py:24 #: user/models/user_action.py:25
msgid "Edited" msgid "Edited"
msgstr "Bearbeitet" msgstr "Bearbeitet"
#: user/models/user_action.py:25 #: user/models/user_action.py:26
msgid "Deleted" msgid "Deleted"
msgstr "Gelöscht" msgstr "Gelöscht"
@ -2632,8 +2651,8 @@ msgid "Name"
msgstr "" msgstr ""
#: user/templates/user/index.html:21 #: user/templates/user/index.html:21
msgid "Groups" msgid "Permissions"
msgstr "Gruppen" msgstr "Berechtigungen"
#: user/templates/user/index.html:34 #: user/templates/user/index.html:34
msgid "" msgid ""
@ -2689,7 +2708,11 @@ msgstr "Neues Team hinzufügen"
msgid "Members" msgid "Members"
msgstr "Mitglieder" msgstr "Mitglieder"
#: user/templates/user/team/index.html:57 #: user/templates/user/team/index.html:32
msgid "Administrator"
msgstr ""
#: user/templates/user/team/index.html:63
msgid "Remove team" msgid "Remove team"
msgstr "Team entfernen" msgstr "Team entfernen"
@ -2741,19 +2764,19 @@ msgstr "API Nutzer Token"
msgid "New team added" msgid "New team added"
msgstr "Neues Team hinzugefügt" msgstr "Neues Team hinzugefügt"
#: user/views.py:191 #: user/views.py:192
msgid "Team edited" msgid "Team edited"
msgstr "Team bearbeitet" msgstr "Team bearbeitet"
#: user/views.py:204 #: user/views.py:206
msgid "Team removed" msgid "Team removed"
msgstr "Team gelöscht" msgstr "Team gelöscht"
#: user/views.py:218 #: user/views.py:220
msgid "You are not a member of this team" msgid "You are not a member of this team"
msgstr "Sie sind kein Mitglied dieses Teams" msgstr "Sie sind kein Mitglied dieses Teams"
#: user/views.py:225 #: user/views.py:227
msgid "Left Team" msgid "Left Team"
msgstr "Team verlassen" msgstr "Team verlassen"
@ -4256,6 +4279,9 @@ msgstr ""
msgid "Unable to connect to qpid with SASL mechanism %s" msgid "Unable to connect to qpid with SASL mechanism %s"
msgstr "" msgstr ""
#~ msgid "Groups"
#~ msgstr "Gruppen"
#~ msgid "Show more..." #~ msgid "Show more..."
#~ msgstr "Mehr anzeigen..." #~ msgstr "Mehr anzeigen..."

@ -11,7 +11,7 @@
</h4> </h4>
{% if form.form_caption is not None %} {% if form.form_caption is not None %}
<small> <small>
{{ form.form_caption }} {{ form.form_caption|linebreaks }}
</small> </small>
{% endif %} {% endif %}
<form method="post" action="{{ form.action_url }}" {% for attr_key, attr_val in form.form_attrs.items %} {{attr_key}}="{{attr_val}}"{% endfor %}> <form method="post" action="{{ form.action_url }}" {% for attr_key, attr_val in form.form_attrs.items %} {{attr_key}}="{{attr_val}}"{% endfor %}>

@ -16,7 +16,7 @@
<div class="modal-body"> <div class="modal-body">
<article> <article>
{{ form.form_caption }} {{ form.form_caption|linebreaks }}
</article> </article>
{% include 'form/table/generic_table_form_body.html' %} {% include 'form/table/generic_table_form_body.html' %}
</div> </div>

@ -68,22 +68,16 @@ class TeamAdmin(admin.ModelAdmin):
list_display = [ list_display = [
"name", "name",
"description", "description",
"admin",
] ]
search_fields = [ search_fields = [
"name", "name",
"description", "description",
] ]
filter_horizontal = [ filter_horizontal = [
"users" "users",
"admins",
] ]
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "admin":
team_id = request.resolver_match.kwargs.get("object_id", None)
kwargs["queryset"] = User.objects.filter(teams__id__in=[team_id])
return super().formfield_for_foreignkey(db_field, request, **kwargs)
admin.site.register(User, UserAdmin) admin.site.register(User, UserAdmin)
admin.site.register(Team, TeamAdmin) admin.site.register(Team, TeamAdmin)

@ -230,7 +230,7 @@ class NewTeamModalForm(BaseModalForm):
team = Team.objects.create( team = Team.objects.create(
name=self.cleaned_data.get("name", None), name=self.cleaned_data.get("name", None),
description=self.cleaned_data.get("description", None), description=self.cleaned_data.get("description", None),
admin=self.user, admins__in=[self.user],
) )
members = self.cleaned_data.get("members", User.objects.none()) members = self.cleaned_data.get("members", User.objects.none())
if self.user.id not in members: if self.user.id not in members:
@ -244,23 +244,40 @@ class NewTeamModalForm(BaseModalForm):
class EditTeamModalForm(NewTeamModalForm): class EditTeamModalForm(NewTeamModalForm):
admin = forms.ModelChoiceField( admins = forms.ModelMultipleChoiceField(
label=_("Admins"),
label_suffix="", label_suffix="",
label=_("Admin"),
help_text=_("Administrators manage team details and members"), help_text=_("Administrators manage team details and members"),
queryset=User.objects.none(), required=True,
empty_label=None, queryset=User.objects.all(),
widget=autocomplete.ModelSelect2Multiple(
url="team-admin-autocomplete",
forward=[
"members",
"admins",
],
attrs={
"data-placeholder": _("Click for selection"),
},
),
) )
def __is_admin_valid(self): def __is_admins_valid(self):
admin = self.cleaned_data.get("admin", None) admins = set(self.cleaned_data.get("admins", {}))
members = self.cleaned_data.get("members", None) members = set(self.cleaned_data.get("members", {}))
_is_valid = admin in members _is_valid = admins.issubset(members)
if not _is_valid: if not _is_valid:
self.add_error( self.add_error(
"members", "admins",
_("Selected admin ({}) needs to be a member of this team.").format(admin.username) _("Selected admins need to be members of this team.")
)
_is_admin_length_valid = len(admins) > 0
if not _is_admin_length_valid:
self.add_error(
"admins",
_("There must be at least one admin on this team.")
) )
return _is_valid return _is_valid
@ -283,7 +300,7 @@ class EditTeamModalForm(NewTeamModalForm):
def is_valid(self): def is_valid(self):
super_valid = super().is_valid() super_valid = super().is_valid()
admin_valid = self.__is_admin_valid() admin_valid = self.__is_admins_valid()
return super_valid and admin_valid return super_valid and admin_valid
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -293,13 +310,13 @@ class EditTeamModalForm(NewTeamModalForm):
self.cancel_redirect = reverse("user:team-index") self.cancel_redirect = reverse("user:team-index")
members = self.instance.users.all() members = self.instance.users.all()
self.fields["admin"].queryset = members #self.fields["admins"].queryset = members
form_data = { form_data = {
"members": members, "members": members,
"name": self.instance.name, "name": self.instance.name,
"description": self.instance.description, "description": self.instance.description,
"admin": self.instance.admin, "admins": self.instance.admins.all(),
} }
self.load_initial_data(form_data) self.load_initial_data(form_data)
@ -307,14 +324,16 @@ class EditTeamModalForm(NewTeamModalForm):
with transaction.atomic(): with transaction.atomic():
self.instance.name = self.cleaned_data.get("name", None) self.instance.name = self.cleaned_data.get("name", None)
self.instance.description = self.cleaned_data.get("description", None) self.instance.description = self.cleaned_data.get("description", None)
self.instance.admin = self.cleaned_data.get("admin", None)
self.instance.save() self.instance.save()
self.instance.users.set(self.cleaned_data.get("members", [])) self.instance.users.set(self.cleaned_data.get("members", []))
self.instance.admins.set(self.cleaned_data.get("admins", []))
return self.instance return self.instance
class RemoveTeamModalForm(RemoveModalForm): class RemoveTeamModalForm(RemoveModalForm):
pass def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form_caption = _("ATTENTION!\n\nRemoving the team means all members will lose their access to data, based on this team! \n\nAre you sure to remove this team?")
class LeaveTeamModalForm(RemoveModalForm): class LeaveTeamModalForm(RemoveModalForm):

@ -0,0 +1,35 @@
# Generated by Django 3.1.3 on 2022-05-30 09:05
from django.conf import settings
from django.db import migrations, models
def migrate_fkey_admin_to_m2m(apps, schema_editor):
Team = apps.get_model('user', 'Team')
all_teams = Team.objects.all()
for team in all_teams:
admin = team.admin
if admin is None:
continue
team.admins.add(admin)
team.save()
class Migration(migrations.Migration):
dependencies = [
('user', '0003_team'),
]
operations = [
migrations.AddField(
model_name='team',
name='admins',
field=models.ManyToManyField(blank=True, related_name='_team_admins_+', to=settings.AUTH_USER_MODEL),
),
migrations.RunPython(migrate_fkey_admin_to_m2m),
migrations.RemoveField(
model_name='team',
name='admin',
),
]

@ -11,7 +11,7 @@ class Team(UuidModel):
name = models.CharField(max_length=500, null=True, blank=True) name = models.CharField(max_length=500, null=True, blank=True)
description = models.TextField(null=True, blank=True) description = models.TextField(null=True, blank=True)
users = models.ManyToManyField("user.User", blank=True, related_name="teams") users = models.ManyToManyField("user.User", blank=True, related_name="teams")
admin = models.ForeignKey("user.User", blank=True, null=True, related_name="+", on_delete=models.SET_NULL) admins = models.ManyToManyField("user.User", blank=True, related_name="+")
def __str__(self): def __str__(self):
return self.name return self.name
@ -104,6 +104,19 @@ class Team(UuidModel):
""" """
self.users.remove(user) self.users.remove(user)
if self.admin == user: self.admins.remove(user)
self.admin = self.users.first()
self.save() self.save()
def is_user_admin(self, user) -> bool:
""" Returns whether a given user is an admin of the team
Args:
user (User): The user
Returns:
user_is_admin (bool): Whether the user is an admin or not
"""
user_is_admin = self.admins.filter(
id=user.id
).exists()
return user_is_admin

@ -18,7 +18,7 @@
<td>{{user.email}}</td> <td>{{user.email}}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans 'Groups' %}</th> <th scope="row">{% trans 'Permissions' %}</th>
<td> <td>
{% for group in user.groups.all %} {% for group in user.groups.all %}
<span class="badge badge-pill rlp-r">{% trans group.name %}</span> <span class="badge badge-pill rlp-r">{% trans group.name %}</span>

@ -28,6 +28,7 @@
<th scope="col" class="align-middle">{% trans 'Name' %}</th> <th scope="col" class="align-middle">{% trans 'Name' %}</th>
<th scope="col" class="align-middle w-20">{% trans 'Description' %}</th> <th scope="col" class="align-middle w-20">{% trans 'Description' %}</th>
<th scope="col" class="align-middle">{% trans 'Members' %}</th> <th scope="col" class="align-middle">{% trans 'Members' %}</th>
<th scope="col" class="align-middle">{% trans 'Administrator' %}</th>
<th scope="col" class="align-middle">{% trans 'Action' %}</th> <th scope="col" class="align-middle">{% trans 'Action' %}</th>
</tr> </tr>
</thead> </thead>
@ -45,11 +46,16 @@
<span class="badge badge-pill rlp-r">{{member.username}}</span> <span class="badge badge-pill rlp-r">{{member.username}}</span>
{% endfor %} {% endfor %}
</td> </td>
<td>
{% for admin in team.admins.all %}
<span class="badge badge-pill rlp-r">{{admin.username}}</span>
{% endfor %}
</td>
<td> <td>
<button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-leave' team.id %}" title="{% trans 'Leave team' %}"> <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-leave' team.id %}" title="{% trans 'Leave team' %}">
{% fa5_icon 'sign-out-alt' %} {% fa5_icon 'sign-out-alt' %}
</button> </button>
{% if team.admin == user %} {% if user in team.admins.all %}
<button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-edit' team.id %}" title="{% trans 'Edit team' %}"> <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-edit' team.id %}" title="{% trans 'Edit team' %}">
{% fa5_icon 'edit' %} {% fa5_icon 'edit' %}
</button> </button>

@ -183,7 +183,8 @@ def new_team_view(request: HttpRequest):
@login_required @login_required
def edit_team_view(request: HttpRequest, id: str): def edit_team_view(request: HttpRequest, id: str):
team = get_object_or_404(Team, id=id) team = get_object_or_404(Team, id=id)
if request.user != team.admin: user_is_admin = team.is_user_admin(request.user)
if not user_is_admin:
raise Http404() raise Http404()
form = EditTeamModalForm(request.POST or None, instance=team, request=request) form = EditTeamModalForm(request.POST or None, instance=team, request=request)
return form.process_request( return form.process_request(
@ -196,7 +197,8 @@ def edit_team_view(request: HttpRequest, id: str):
@login_required @login_required
def remove_team_view(request: HttpRequest, id: str): def remove_team_view(request: HttpRequest, id: str):
team = get_object_or_404(Team, id=id) team = get_object_or_404(Team, id=id)
if request.user != team.admin: user_is_admin = team.is_user_admin(request.user)
if not user_is_admin:
raise Http404() raise Http404()
form = RemoveTeamModalForm(request.POST or None, instance=team, request=request) form = RemoveTeamModalForm(request.POST or None, instance=team, request=request)
return form.process_request( return form.process_request(

Loading…
Cancel
Save