1
0
mirror of https://gitlab.com/bramw/baserow.git synced 2024-11-22 07:42:36 +00:00
bramw_baserow/backend/tests/baserow/api/trash/test_trash_views.py
Petr Stribny c6a9f7ce5f Django 5
2024-09-18 08:18:20 +00:00

904 lines
28 KiB
Python
Executable File

from datetime import datetime, timedelta, timezone
from django.shortcuts import reverse
import pytest
from freezegun import freeze_time
from rest_framework.status import (
HTTP_200_OK,
HTTP_204_NO_CONTENT,
HTTP_400_BAD_REQUEST,
HTTP_404_NOT_FOUND,
)
from baserow.contrib.database.fields.handler import FieldHandler
from baserow.contrib.database.rows.handler import RowHandler
from baserow.core.models import Application, TrashEntry, Workspace
from baserow.core.trash.handler import TrashHandler
@pytest.mark.django_db
def test_deleting_a_workspace_moves_it_to_the_trash_and_hides_it(
api_client, data_fixture
):
user = data_fixture.create_user()
workspace_to_delete = data_fixture.create_workspace(user=user)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
token = data_fixture.generate_token(user)
response = api_client.get(
reverse("api:workspaces:list"),
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == []
response = api_client.get(
reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace_to_delete.id,
},
),
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == {
"count": 1,
"next": None,
"previous": None,
"results": [
{
"application": None,
"workspace": workspace_to_delete.id,
"id": TrashEntry.objects.first().id,
"parent_trash_item_id": None,
"trash_item_id": workspace_to_delete.id,
"trash_item_type": "workspace",
"trashed_at": "2020-01-01T12:00:00Z",
"user_who_trashed": user.first_name,
"name": workspace_to_delete.name,
"parent_name": None,
"names": None,
}
],
}
@pytest.mark.django_db
def test_can_restore_a_deleted_trash_item(api_client, data_fixture):
user = data_fixture.create_user()
workspace_to_delete = data_fixture.create_workspace(user=user)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
token = data_fixture.generate_token(user)
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "workspace",
"trash_item_id": workspace_to_delete.id,
},
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_204_NO_CONTENT
assert Workspace.objects.count() == 1
assert Workspace.trash.count() == 0
response = api_client.get(
reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace_to_delete.id,
},
),
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == {
"count": 0,
"next": None,
"previous": None,
"results": [],
}
@pytest.mark.django_db
def test_cant_restore_a_deleted_trash_item_if_not_in_workspace(
api_client, data_fixture
):
user = data_fixture.create_user()
other_user, other_token = data_fixture.create_user_and_token()
workspace_to_delete = data_fixture.create_workspace(user=user)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "workspace",
"trash_item_id": workspace_to_delete.id,
},
format="json",
HTTP_AUTHORIZATION=f"JWT {other_token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_USER_NOT_IN_GROUP"
@pytest.mark.django_db
def test_cant_restore_a_non_existent_trashed_item(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "workspace",
"trash_item_id": 99999,
},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_TRASH_ITEM_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_cant_restore_a_trashed_item_with_a_missing_parent(api_client, data_fixture):
user = data_fixture.create_user()
workspace = data_fixture.create_workspace(user=user)
application = data_fixture.create_database_application(
user=user, workspace=workspace
)
table = data_fixture.create_database_table(user=user, database=application)
model = table.get_model()
row = model.objects.create()
url = reverse(
"api:database:rows:item", kwargs={"table_id": table.id, "row_id": row.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
token = data_fixture.generate_token(user)
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "row",
"parent_trash_item_id": 99999,
"trash_item_id": row.id,
},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_TRASH_ITEM_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_cant_restore_a_trash_item_marked_for_perm_deletion(
api_client, data_fixture, settings
):
user, token = data_fixture.create_user_and_token()
workspace_to_delete = data_fixture.create_workspace(user=user)
trashed_at = datetime.now(tz=timezone.utc)
time_when_trash_item_old_enough = trashed_at + timedelta(
hours=settings.HOURS_UNTIL_TRASH_PERMANENTLY_DELETED + 1
)
with freeze_time(trashed_at):
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
with freeze_time(time_when_trash_item_old_enough):
TrashHandler.mark_old_trash_for_permanent_deletion()
TrashHandler.permanently_delete_marked_trash()
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "workspace",
"trash_item_id": workspace_to_delete.id,
},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_TRASH_ITEM_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_can_get_trash_structure(api_client, data_fixture):
user = data_fixture.create_user()
workspace_to_delete = data_fixture.create_workspace()
normal_workspace = data_fixture.create_workspace()
data_fixture.create_user_workspace(
user=user, workspace=workspace_to_delete, order=1
)
data_fixture.create_user_workspace(user=user, workspace=normal_workspace, order=2)
# Another workspace for a different user which should not be displayed below
data_fixture.create_workspace()
application = data_fixture.create_database_application(
user=user, workspace=workspace_to_delete
)
trashed_application = data_fixture.create_database_application(
user=user, workspace=normal_workspace
)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
url = reverse(
"api:applications:item", kwargs={"application_id": trashed_application.id}
)
with freeze_time("2020-01-01 12:00"):
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
token = data_fixture.generate_token(user)
response = api_client.get(
reverse(
"api:trash:list",
),
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == {
"workspaces": [
{
"id": workspace_to_delete.id,
"trashed": True,
"name": workspace_to_delete.name,
"applications": [
{"id": application.id, "name": application.name, "trashed": False}
],
},
{
"id": normal_workspace.id,
"trashed": False,
"name": normal_workspace.name,
"applications": [
{
"id": trashed_application.id,
"name": trashed_application.name,
"trashed": True,
}
],
},
],
}
@pytest.mark.django_db
def test_getting_a_non_existent_workspace_returns_404(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
response = api_client.get(
reverse(
"api:trash:contents",
kwargs={"workspace_id": 99999},
),
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_GROUP_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_getting_a_non_existent_app_returns_404(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
workspace = data_fixture.create_workspace(user=user)
url = reverse(
"api:trash:contents",
kwargs={"workspace_id": workspace.id},
)
response = api_client.get(
f"{url}?application_id=99999",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_APPLICATION_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_getting_a_app_for_diff_workspace_returns_400(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
workspace = data_fixture.create_workspace(user=user)
other_workspace = data_fixture.create_workspace(user=user)
app = data_fixture.create_database_application(user=user, workspace=other_workspace)
url = reverse(
"api:trash:contents",
kwargs={"workspace_id": workspace.id},
)
response = api_client.get(
f"{url}?application_id={app.id}",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_APPLICATION_NOT_IN_GROUP"
@pytest.mark.django_db
def test_user_cant_get_trash_contents_for_workspace_they_are_not_a_member_of(
api_client, data_fixture
):
user = data_fixture.create_user()
(
other_unpermissioned_user,
unpermissioned_token,
) = data_fixture.create_user_and_token()
workspace_to_delete = data_fixture.create_workspace(user=user)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
url = reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace_to_delete.id,
},
)
token = data_fixture.generate_token(user)
response = api_client.get(
url,
HTTP_AUTHORIZATION=f"JWT {unpermissioned_token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_USER_NOT_IN_GROUP"
@pytest.mark.django_db
def test_can_get_trash_contents_for_undeleted_workspace(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
workspace = data_fixture.create_workspace(user=user)
url = reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace.id,
},
)
response = api_client.get(
url,
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == {
"count": 0,
"next": None,
"previous": None,
"results": [],
}
@pytest.mark.django_db
def test_can_get_trash_contents_for_undeleted_app(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
workspace = data_fixture.create_workspace(user=user)
app = data_fixture.create_database_application(user=user, workspace=workspace)
url = reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace.id,
},
)
response = api_client.get(
f"{url}?application_id={app.id}",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == {
"count": 0,
"next": None,
"previous": None,
"results": [],
}
@pytest.mark.django_db
def test_emptying_a_trashed_workspace_marks_it_for_perm_deletion(
api_client, data_fixture
):
user = data_fixture.create_user()
workspace_to_delete = data_fixture.create_workspace(user=user)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
url = reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace_to_delete.id,
},
)
token = data_fixture.generate_token(user)
response = api_client.delete(
f"{url}",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_204_NO_CONTENT
assert Workspace.objects.count() == 0
assert Workspace.trash.count() == 1
assert TrashEntry.objects.get(
trash_item_id=workspace_to_delete.id
).should_be_permanently_deleted
response = api_client.get(
reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace_to_delete.id,
},
),
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_GROUP_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_emptying_a_non_existent_workspace_returns_404(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
response = api_client.delete(
reverse(
"api:trash:contents",
kwargs={"workspace_id": 99999},
),
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_GROUP_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_emptying_a_non_existent_app_returns_404(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
workspace = data_fixture.create_workspace(user=user)
url = reverse(
"api:trash:contents",
kwargs={"workspace_id": workspace.id},
)
response = api_client.delete(
f"{url}?application_id=99999",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_APPLICATION_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_emptying_a_app_for_diff_workspace_returns_400(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
workspace = data_fixture.create_workspace(user=user)
other_workspace = data_fixture.create_workspace(user=user)
app = data_fixture.create_database_application(user=user, workspace=other_workspace)
url = reverse(
"api:trash:contents",
kwargs={"workspace_id": workspace.id},
)
response = api_client.delete(
f"{url}?application_id={app.id}",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_APPLICATION_NOT_IN_GROUP"
@pytest.mark.django_db
def test_user_cant_empty_trash_contents_for_workspace_they_are_not_a_member_of(
api_client, data_fixture
):
user = data_fixture.create_user()
(
other_unpermissioned_user,
unpermissioned_token,
) = data_fixture.create_user_and_token()
workspace_to_delete = data_fixture.create_workspace(user=user)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
url = reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace_to_delete.id,
},
)
token = data_fixture.generate_token(user)
response = api_client.delete(
url,
HTTP_AUTHORIZATION=f"JWT {unpermissioned_token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_USER_NOT_IN_GROUP"
@pytest.mark.django_db
def test_emptying_a_trashed_app_marks_it_for_perm_deletion(api_client, data_fixture):
user = data_fixture.create_user()
workspace = data_fixture.create_workspace(user=user)
trashed_database = data_fixture.create_database_application(
user=user, workspace=workspace
)
url = reverse(
"api:applications:item", kwargs={"application_id": trashed_database.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
url = reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace.id,
},
)
token = data_fixture.generate_token(user)
response = api_client.delete(
f"{url}",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_204_NO_CONTENT
assert Application.objects.count() == 0
assert Application.trash.count() == 1
assert TrashEntry.objects.get(
trash_item_id=trashed_database.id
).should_be_permanently_deleted
url = reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace.id,
},
)
response = api_client.get(
f"{url}?application_id={trashed_database.id}",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_404_NOT_FOUND
assert response.json()["error"] == "ERROR_APPLICATION_DOES_NOT_EXIST"
@pytest.mark.django_db
def test_deleting_a_user_who_trashed_something_returns_null_user_who_trashed(
api_client, data_fixture
):
user = data_fixture.create_user()
other_user, other_token = data_fixture.create_user_and_token()
workspace_to_delete = data_fixture.create_workspace(user=user)
data_fixture.create_user_workspace(user=other_user, workspace=workspace_to_delete)
url = reverse(
"api:workspaces:item", kwargs={"workspace_id": workspace_to_delete.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
user.delete()
token = data_fixture.generate_token(other_user)
response = api_client.get(
reverse(
"api:trash:contents",
kwargs={
"workspace_id": workspace_to_delete.id,
},
),
HTTP_AUTHORIZATION=f"JWT {other_token}",
)
assert response.status_code == HTTP_200_OK
assert response.json() == {
"count": 1,
"next": None,
"previous": None,
"results": [
{
"application": None,
"workspace": workspace_to_delete.id,
"id": TrashEntry.objects.first().id,
"parent_trash_item_id": None,
"trash_item_id": workspace_to_delete.id,
"trash_item_type": "workspace",
"trashed_at": "2020-01-01T12:00:00Z",
"user_who_trashed": None,
"name": workspace_to_delete.name,
"parent_name": None,
"names": None,
}
],
}
@pytest.mark.django_db
def test_restoring_an_item_which_doesnt_need_parent_id_with_one_returns_error(
api_client, data_fixture
):
user = data_fixture.create_user()
workspace = data_fixture.create_workspace(user=user)
application = data_fixture.create_database_application(
user=user, workspace=workspace
)
url = reverse("api:applications:item", kwargs={"application_id": application.id})
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
token = data_fixture.generate_token(user)
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "application",
"parent_trash_item_id": 99999,
"trash_item_id": application.id,
},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_PARENT_ID_MUST_NOT_BE_PROVIDED"
@pytest.mark.django_db
def test_cant_restore_a_trashed_item_requiring_a_parent_id_without_providing_it(
api_client, data_fixture
):
user = data_fixture.create_user()
workspace = data_fixture.create_workspace(user=user)
application = data_fixture.create_database_application(
user=user, workspace=workspace
)
table = data_fixture.create_database_table(user=user, database=application)
model = table.get_model()
row = model.objects.create()
url = reverse(
"api:database:rows:item", kwargs={"table_id": table.id, "row_id": row.id}
)
with freeze_time("2020-01-01 12:00"):
token = data_fixture.generate_token(user)
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_204_NO_CONTENT
token = data_fixture.generate_token(user)
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "row",
"trash_item_id": row.id,
},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_PARENT_ID_MUST_BE_PROVIDED"
@pytest.mark.django_db
def test_cant_delete_same_item_twice(api_client, data_fixture):
user = data_fixture.create_user()
workspace = data_fixture.create_workspace(user=user)
database = data_fixture.create_database_application(user=user)
table = data_fixture.create_database_table(user=user)
field = data_fixture.create_text_field(user=user)
row_table, _, rows = data_fixture.build_table(
user=user, columns=[("text", "text")], rows=["test"]
)
row = rows[0]
def get_token():
return data_fixture.generate_token(user)
url = reverse("api:workspaces:item", kwargs={"workspace_id": workspace.id})
_assert_delete_called_twice_returns_correct_api_error(
api_client, workspace, get_token, url
)
url = reverse("api:applications:item", kwargs={"application_id": database.id})
_assert_delete_called_twice_returns_correct_api_error(
api_client, database, get_token, url
)
url = reverse("api:database:tables:item", kwargs={"table_id": table.id})
_assert_delete_called_twice_returns_correct_api_error(
api_client, table, get_token, url
)
url = reverse("api:database:fields:item", kwargs={"field_id": field.id})
_assert_delete_called_twice_returns_correct_api_error(
api_client, field, get_token, url, response_code=HTTP_200_OK
)
url = reverse(
"api:database:rows:item", kwargs={"table_id": row_table.id, "row_id": row.id}
)
_assert_delete_called_twice_returns_correct_api_error(
api_client, row, get_token, url
)
def _assert_delete_called_twice_returns_correct_api_error(
api_client, deletable_item, get_token, url, response_code=HTTP_204_NO_CONTENT
):
with freeze_time("2020-01-01 12:00"):
token = get_token()
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == response_code
# Fake two requests doing the deletion at once by manually unsetting the trashed
# flag so we can attempt to trash again and hit the integrity error.
deletable_item.trashed = False
deletable_item.save()
with freeze_time("2020-01-01 12:00"):
response = api_client.delete(url, HTTP_AUTHORIZATION=f"JWT {token}")
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_CANNOT_DELETE_ALREADY_DELETED_ITEM"
@pytest.mark.django_db
def test_restoring_a_field_which_depends_on_trashed_table_fails(
api_client, data_fixture
):
user, token = data_fixture.create_user_and_token()
database = data_fixture.create_database_application(user=user, name="Placeholder")
table_1 = data_fixture.create_database_table(name="Table 1", database=database)
table_2 = data_fixture.create_database_table(name="Table 2", database=database)
field_handler = FieldHandler()
row_handler = RowHandler()
table_1_primary_field = field_handler.create_field(
user=user, table=table_1, type_name="text", name="Name", primary=True
)
row_handler.create_row(
user=user,
table=table_1,
values={f"field_{table_1_primary_field.id}": "John"},
)
row_handler.create_row(
user=user,
table=table_1,
values={f"field_{table_1_primary_field.id}": "Jane"},
)
# Create a primary field and some example data for the cars table.
cars_primary_field = field_handler.create_field(
user=user, table=table_2, type_name="text", name="Name", primary=True
)
row_handler.create_row(
user=user, table=table_2, values={f"field_{cars_primary_field.id}": "BMW"}
)
row_handler.create_row(
user=user, table=table_2, values={f"field_{cars_primary_field.id}": "Audi"}
)
link_field_1 = field_handler.create_field(
user=user,
table=table_1,
type_name="link_row",
name="Customer",
link_row_table=table_2,
)
TrashHandler.trash(user, database.workspace, database, link_field_1)
TrashHandler.trash(user, database.workspace, database, table_1)
TrashHandler.trash(user, database.workspace, database, table_2)
TrashHandler.restore_item(user, "table", table_1.id)
response = api_client.patch(
reverse(
"api:trash:restore",
),
{
"trash_item_type": "field",
"trash_item_id": link_field_1.id,
},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_CANT_RESTORE_AS_RELATED_TABLE_TRASHED"