diff --git a/messages.pot b/messages.pot index a9d2953..3105a05 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-09-07 22:54+0200\n" +"POT-Creation-Date: 2021-09-08 14:40+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -235,7 +235,15 @@ msgstr "" msgid "If set, the organization can work with suggestions." msgstr "" -#: project/forms/admin.py:36 project/templates/admin/update_admin_unit.html:4 +#: project/forms/admin.py:37 +msgid "Create other organizations" +msgstr "" + +#: project/forms/admin.py:38 +msgid "If set, members of the organization can create other organizations." +msgstr "" + +#: project/forms/admin.py:43 project/templates/admin/update_admin_unit.html:4 #: project/templates/admin/update_admin_unit.html:8 msgid "Update organization" msgstr "" diff --git a/migrations/versions/e759ca20884f_.py b/migrations/versions/e759ca20884f_.py new file mode 100644 index 0000000..69f28de --- /dev/null +++ b/migrations/versions/e759ca20884f_.py @@ -0,0 +1,29 @@ +"""empty message + +Revision ID: e759ca20884f +Revises: 4a5c083c649b +Create Date: 2021-09-08 14:38:28.975242 + +""" +import sqlalchemy as sa +import sqlalchemy_utils +from alembic import op + +from project import dbtypes + +# revision identifiers, used by Alembic. +revision = "e759ca20884f" +down_revision = "4a5c083c649b" +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column( + "adminunit", + sa.Column("can_create_other", sa.Boolean(), server_default="0", nullable=False), + ) + + +def downgrade(): + op.drop_column("adminunit", "can_create_other") diff --git a/project/access.py b/project/access.py index 2bc5965..e6146a2 100644 --- a/project/access.py +++ b/project/access.py @@ -189,7 +189,11 @@ def can_create_admin_unit(): if not app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"]: return True - return has_current_user_role("admin") + if has_current_user_role("admin"): + return True + + admin_units = get_admin_units_for_manage() + return any(admin_unit.can_create_other for admin_unit in admin_units) def can_read_event(event: Event) -> bool: diff --git a/project/cli/test.py b/project/cli/test.py index d934d4c..4006585 100644 --- a/project/cli/test.py +++ b/project/cli/test.py @@ -115,6 +115,7 @@ def _create_admin_unit(user_id, name): admin_unit.short_name = name.lower().replace(" ", "") admin_unit.incoming_reference_requests_allowed = True admin_unit.suggestions_enabled = True + admin_unit.can_create_other = True admin_unit.location = Location() admin_unit.location.postalCode = "38640" admin_unit.location.city = "Goslar" diff --git a/project/forms/admin.py b/project/forms/admin.py index 35cc1d1..d31ada7 100644 --- a/project/forms/admin.py +++ b/project/forms/admin.py @@ -33,4 +33,11 @@ class UpdateAdminUnitForm(FlaskForm): description=lazy_gettext("If set, the organization can work with suggestions."), validators=[Optional()], ) + can_create_other = BooleanField( + lazy_gettext("Create other organizations"), + description=lazy_gettext( + "If set, members of the organization can create other organizations." + ), + validators=[Optional()], + ) submit = SubmitField(lazy_gettext("Update organization")) diff --git a/project/models.py b/project/models.py index 3608a12..9c4a1a1 100644 --- a/project/models.py +++ b/project/models.py @@ -399,6 +399,14 @@ class AdminUnit(db.Model, TrackableMixin): server_default="0", ) ) + can_create_other = deferred( + Column( + Boolean(), + nullable=False, + default=False, + server_default="0", + ) + ) outgoing_relations = relationship( "AdminUnitRelation", primaryjoin=remote(AdminUnitRelation.source_admin_unit_id) == id, diff --git a/project/templates/admin/update_admin_unit.html b/project/templates/admin/update_admin_unit.html index 00baf8d..243c986 100644 --- a/project/templates/admin/update_admin_unit.html +++ b/project/templates/admin/update_admin_unit.html @@ -17,6 +17,7 @@
{{ render_field_with_errors(form.incoming_reference_requests_allowed, ri="switch") }} {{ render_field_with_errors(form.suggestions_enabled, ri="switch") }} + {{ render_field_with_errors(form.can_create_other, ri="switch") }}
diff --git a/project/translations/de/LC_MESSAGES/messages.mo b/project/translations/de/LC_MESSAGES/messages.mo index 6f3c3e9..faec52f 100644 Binary files a/project/translations/de/LC_MESSAGES/messages.mo and b/project/translations/de/LC_MESSAGES/messages.mo differ diff --git a/project/translations/de/LC_MESSAGES/messages.po b/project/translations/de/LC_MESSAGES/messages.po index 893f7fb..9907901 100644 --- a/project/translations/de/LC_MESSAGES/messages.po +++ b/project/translations/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-09-07 22:54+0200\n" +"POT-Creation-Date: 2021-09-08 14:40+0200\n" "PO-Revision-Date: 2020-06-07 18:51+0200\n" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -238,7 +238,15 @@ msgstr "Vorschläge aktiv" msgid "If set, the organization can work with suggestions." msgstr "Wenn gesetzt, kann die Organisation mit Vorschlägen arbeiten." -#: project/forms/admin.py:36 project/templates/admin/update_admin_unit.html:4 +#: project/forms/admin.py:37 +msgid "Create other organizations" +msgstr "Andere Organisationen erstellen" + +#: project/forms/admin.py:38 +msgid "If set, members of the organization can create other organizations." +msgstr "Wenn gesetzt, können Mitglieder der Organisation andere Organisationen erstellen." + +#: project/forms/admin.py:43 project/templates/admin/update_admin_unit.html:4 #: project/templates/admin/update_admin_unit.html:8 msgid "Update organization" msgstr "Organisation aktualisieren" diff --git a/project/translations/en/LC_MESSAGES/messages.mo b/project/translations/en/LC_MESSAGES/messages.mo index 9cee47d..02ab09e 100644 Binary files a/project/translations/en/LC_MESSAGES/messages.mo and b/project/translations/en/LC_MESSAGES/messages.mo differ diff --git a/project/translations/en/LC_MESSAGES/messages.po b/project/translations/en/LC_MESSAGES/messages.po index e097ead..7590b4a 100644 --- a/project/translations/en/LC_MESSAGES/messages.po +++ b/project/translations/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-09-07 22:54+0200\n" +"POT-Creation-Date: 2021-09-08 14:40+0200\n" "PO-Revision-Date: 2021-04-30 15:04+0200\n" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -236,7 +236,15 @@ msgstr "" msgid "If set, the organization can work with suggestions." msgstr "" -#: project/forms/admin.py:36 project/templates/admin/update_admin_unit.html:4 +#: project/forms/admin.py:37 +msgid "Create other organizations" +msgstr "" + +#: project/forms/admin.py:38 +msgid "If set, members of the organization can create other organizations." +msgstr "" + +#: project/forms/admin.py:43 project/templates/admin/update_admin_unit.html:4 #: project/templates/admin/update_admin_unit.html:8 msgid "Update organization" msgstr "" diff --git a/tests/seeder.py b/tests/seeder.py index 127691a..a3984a7 100644 --- a/tests/seeder.py +++ b/tests/seeder.py @@ -44,7 +44,13 @@ class Seeder(object): return user_id - def create_admin_unit(self, user_id, name="Meine Crew", suggestions_enabled=True): + def create_admin_unit( + self, + user_id, + name="Meine Crew", + suggestions_enabled=True, + can_create_other=False, + ): from project.models import AdminUnit from project.services.admin_unit import insert_admin_unit_for_user from project.services.user import get_user @@ -56,6 +62,7 @@ class Seeder(object): admin_unit.short_name = name.lower().replace(" ", "") admin_unit.incoming_reference_requests_allowed = True admin_unit.suggestions_enabled = suggestions_enabled + admin_unit.can_create_other = can_create_other insert_admin_unit_for_user(admin_unit, user) self._db.session.commit() admin_unit_id = admin_unit.id diff --git a/tests/views/test_admin.py b/tests/views/test_admin.py index d8b94f2..2fa8d15 100644 --- a/tests/views/test_admin.py +++ b/tests/views/test_admin.py @@ -119,6 +119,7 @@ def test_admin_admin_unit_update(client, seeder, utils, app, mocker, db, db_erro admin_unit = AdminUnit.query.get_or_404(admin_unit_id) admin_unit.incoming_reference_requests_allowed = False admin_unit.suggestions_enabled = False + admin_unit.can_create_other = False db.session.commit() url = utils.get_url("admin_admin_unit_update", id=admin_unit_id) @@ -133,6 +134,7 @@ def test_admin_admin_unit_update(client, seeder, utils, app, mocker, db, db_erro { "incoming_reference_requests_allowed": "y", "suggestions_enabled": "y", + "can_create_other": "y", }, ) @@ -148,3 +150,4 @@ def test_admin_admin_unit_update(client, seeder, utils, app, mocker, db, db_erro admin_unit = AdminUnit.query.get_or_404(admin_unit_id) assert admin_unit.incoming_reference_requests_allowed assert admin_unit.suggestions_enabled + assert admin_unit.can_create_other diff --git a/tests/views/test_admin_unit.py b/tests/views/test_admin_unit.py index 2648125..1ca3285 100644 --- a/tests/views/test_admin_unit.py +++ b/tests/views/test_admin_unit.py @@ -71,17 +71,69 @@ def test_create_duplicate(client, app, utils, seeder): assert b"duplicate" in response.data -def test_create_requiresadmin_nonadmin(client, app, utils, seeder): +def test_create_requiresAdmin_nonAdmin(client, app, utils, seeder): app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = True seeder.create_user() - user_id = utils.login() - seeder.create_admin_unit(user_id, "Meine Crew") + utils.login() - response = client.get("/admin_unit/create") + url = utils.get_url("admin_unit_create") + response = utils.get(url) utils.assert_response_redirect(response, "manage_admin_units") +def test_create_requiresAdmin_globalAdmin(client, app, utils, seeder): + app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = True + seeder.create_user(admin=True) + utils.login() + + url = utils.get_url("admin_unit_create") + response = utils.get_ok(url) + + response = utils.post_form( + url, + response, + { + "name": "Meine Crew", + "short_name": "meine_crew", + "location-postalCode": "38640", + "location-city": "Goslar", + }, + ) + assert response.status_code == 302 + + +def test_create_requiresAdmin_memberOfOrgWithoutFlag(client, app, utils, seeder): + app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = True + seeder.setup_base() + + url = utils.get_url("admin_unit_create") + response = utils.get(url) + utils.assert_response_redirect(response, "manage_admin_units") + + +def test_create_requiresAdmin_memberOfOrgWithFlag(client, app, utils, seeder): + app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = True + user_id = seeder.create_user(admin=False) + utils.login() + seeder.create_admin_unit(user_id, can_create_other=True) + + url = utils.get_url("admin_unit_create") + response = utils.get_ok(url) + + response = utils.post_form( + url, + response, + { + "name": "Other Crew", + "short_name": "other_crew", + "location-postalCode": "38640", + "location-city": "Goslar", + }, + ) + assert response.status_code == 302 + + def test_update(client, app, utils, seeder): seeder.create_user() user_id = utils.login()