Skip to content

Commit

Permalink
Merge pull request #1538 from digitalfabrik/enhancement/version-uniqu…
Browse files Browse the repository at this point in the history
…e-constraint

Add database constraints to enforce unique version numbers
  • Loading branch information
timobrembeck authored Jun 11, 2022
2 parents f94d0ee + 1c34ae3 commit 5caacf0
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 29 deletions.
44 changes: 44 additions & 0 deletions integreat_cms/cms/migrations/0031_unique_version_constraint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Generated by Django 3.2.13 on 2022-06-09 20:00

from django.db import migrations, models


class Migration(migrations.Migration):
"""
Ensure version numbers are unique for all content objects in each language.
"""

dependencies = [
("cms", "0030_alter_region_aliases"),
]

operations = [
migrations.AddConstraint(
model_name="eventtranslation",
constraint=models.UniqueConstraint(
fields=("event", "language", "version"),
name="eventtranslation_unique_version",
),
),
migrations.AddConstraint(
model_name="imprintpagetranslation",
constraint=models.UniqueConstraint(
fields=("page", "language", "version"),
name="imprintpagetranslation_unique_version",
),
),
migrations.AddConstraint(
model_name="pagetranslation",
constraint=models.UniqueConstraint(
fields=("page", "language", "version"),
name="pagetranslation_unique_version",
),
),
migrations.AddConstraint(
model_name="poitranslation",
constraint=models.UniqueConstraint(
fields=("poi", "language", "version"),
name="poitranslation_unique_version",
),
),
]
7 changes: 7 additions & 0 deletions integreat_cms/cms/models/events/event_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,10 @@ class Meta:
default_permissions = ()
#: The fields which are used to sort the returned objects of a QuerySet
ordering = ["event__pk", "language__pk", "-version"]
#: A list of database constraints for this model
constraints = [
models.UniqueConstraint(
fields=["event", "language", "version"],
name="%(class)s_unique_version",
),
]
7 changes: 7 additions & 0 deletions integreat_cms/cms/models/pages/imprint_page_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,10 @@ class Meta:
default_permissions = ()
#: The fields which are used to sort the returned objects of a QuerySet
ordering = ["page__pk", "language__pk", "-version"]
#: A list of database constraints for this model
constraints = [
models.UniqueConstraint(
fields=["page", "language", "version"],
name="%(class)s_unique_version",
),
]
7 changes: 7 additions & 0 deletions integreat_cms/cms/models/pages/page_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,10 @@ class Meta:
default_permissions = ()
#: The fields which are used to sort the returned objects of a QuerySet
ordering = ["page__pk", "language__pk", "-version"]
#: A list of database constraints for this model
constraints = [
models.UniqueConstraint(
fields=["page", "language", "version"],
name="%(class)s_unique_version",
),
]
7 changes: 7 additions & 0 deletions integreat_cms/cms/models/pois/poi_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,10 @@ class Meta:
default_permissions = ()
#: The fields which are used to sort the returned objects of a QuerySet
ordering = ["poi__pk", "language__pk", "-version"]
#: A list of database constraints for this model
constraints = [
models.UniqueConstraint(
fields=["poi", "language", "version"],
name="%(class)s_unique_version",
),
]
2 changes: 1 addition & 1 deletion integreat_cms/locale/de/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-08 20:12+0000\n"
"POT-Creation-Date: 2022-06-09 22:40+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Integreat <[email protected]>\n"
"Language-Team: Integreat <[email protected]>\n"
Expand Down
69 changes: 41 additions & 28 deletions tests/xliff/xliff_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,31 +138,42 @@ def test_xliff_import(login_role_user, settings):
import_path = "tests/xliff/files/import"
file_1 = "augsburg_de_en_1_2_willkommen.xliff"
file_2 = "augsburg_de_en_2_1_willkommen-in-augsburg.xliff"
# Upload once for successful import
with open(f"{import_path}/{file_1}", encoding="utf-8") as f1:
with open(f"{import_path}/{file_2}", encoding="utf-8") as f2:
response = client.post(
response1 = client.post(
upload_xliff, data={"xliff_file": [f1, f2]}, format="multipart"
)
print(response.headers)
print(response1.headers)
# Upload second time to test unchanged import
with open(f"{import_path}/{file_1}", encoding="utf-8") as f1:
with open(f"{import_path}/{file_2}", encoding="utf-8") as f2:
response2 = client.post(
upload_xliff, data={"xliff_file": [f1, f2]}, format="multipart"
)
print(response2.headers)

if role in PRIV_STAFF_ROLES + [MANAGEMENT, EDITOR, AUTHOR]:
# If the role should be allowed to access the view, we expect a successful result
assert response.status_code == 302
page_tree = reverse(
"pages", kwargs={"region_slug": "augsburg", "language_slug": "en"}
)
redirect_location = response.headers.get("Location")
# If errors occur, we get redirected to the page tree
assert redirect_location != page_tree
# Check if xliff import view is correctly rendered
response = client.get(redirect_location)
print(response.headers)
assert response.status_code == 200
assert file_1 in response.content.decode("utf-8")
assert file_2 in response.content.decode("utf-8")
# Check if XLIFF import is correctly confirmed
# (perform test twice to check whether unchanged diffs can be imported as well)
for msg in ["successfully", "without changes"]:
# Perform test twice to check whether unchanged diffs can be imported as well
for response, msg in [
(response1, "successfully"),
(response2, "without changes"),
]:
# If the role should be allowed to access the view, we expect a successful result
assert response.status_code == 302
page_tree = reverse(
"pages", kwargs={"region_slug": "augsburg", "language_slug": "en"}
)
redirect_location = response.headers.get("Location")
# If errors occur, we get redirected to the page tree
assert redirect_location != page_tree
# Check if xliff import view is correctly rendered
response = client.get(redirect_location)
print(response.headers)
assert response.status_code == 200
assert file_1 in response.content.decode("utf-8")
assert file_2 in response.content.decode("utf-8")
# Check if XLIFF import is correctly confirmed
response = client.post(redirect_location)
print(response.headers)
assert response.status_code == 302
Expand All @@ -183,7 +194,7 @@ def test_xliff_import(login_role_user, settings):
in response.content.decode("utf-8")
)
if translation.version > 1:
# If a translation already exists for this version, asser that the status is inherited
# If a translation already exists for this version, assert that the status is inherited
previous_translation = page.translations.get(
language__slug="en", version=translation.version - 1
)
Expand All @@ -192,12 +203,14 @@ def test_xliff_import(login_role_user, settings):
# Else, the status should be inherited from the source translation
assert translation.source_translation.status == translation.status
elif role == ANONYMOUS:
# For anonymous users, we want to redirect to the login form instead of showing an error
assert response.status_code == 302
assert (
response.headers.get("location")
== f"{settings.LOGIN_URL}?next={upload_xliff}"
)
for response in [response1, response2]:
# For anonymous users, we want to redirect to the login form instead of showing an error
assert response.status_code == 302
assert (
response.headers.get("location")
== f"{settings.LOGIN_URL}?next={upload_xliff}"
)
else:
# For logged in users, we want to show an error if they get a permission denied
assert response.status_code == 403
for response in [response1, response2]:
# For logged in users, we want to show an error if they get a permission denied
assert response.status_code == 403

0 comments on commit 5caacf0

Please sign in to comment.