1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-07 06:15:36 +00:00

Safely handle missing fields during import for LocalBaserowUserSource and LocalBaserowPasswordAppAuthProvider

This commit is contained in:
Tsering Paljor 2025-01-29 11:27:21 +00:00
parent 5f8c81271a
commit 7e32a8d2ed
5 changed files with 181 additions and 3 deletions
changelog/entries/unreleased/bug
enterprise/backend
src/baserow_enterprise/integrations/local_baserow
tests/baserow_enterprise_tests/integrations/local_baserow

View file

@ -0,0 +1,7 @@
{
"type": "bug",
"message": "[Builder] Fixed bug that caused a workspace import to fail when certain fields were missing.",
"issue_number": 3375,
"bullet_points": [],
"created_at": "2025-01-28"
}

View file

@ -187,7 +187,7 @@ class LocalBaserowPasswordAppAuthProviderType(AppAuthProviderType):
and value
and "database_fields" in id_mapping
):
return id_mapping["database_fields"][value]
return id_mapping["database_fields"].get(value)
return super().deserialize_property(
prop_name,

View file

@ -416,14 +416,14 @@ class LocalBaserowUserSourceType(UserSourceType):
"""
if value and "database_tables" in id_mapping and prop_name == "table_id":
return id_mapping["database_tables"][value]
return id_mapping["database_tables"].get(value)
if (
value
and "database_fields" in id_mapping
and prop_name in ("email_field_id", "name_field_id", "role_field_id")
):
return id_mapping["database_fields"][value]
return id_mapping["database_fields"].get(value)
return super().deserialize_property(
prop_name,

View file

@ -395,3 +395,75 @@ def test_import_local_baserow_password_app_auth_provider(data_fixture):
imported_instance.auth_providers.first().specific.password_field_id
== password_field.id
)
@pytest.mark.django_db
def test_import_local_baserow_password_app_auth_provider_without_database(data_fixture):
"""
Test the import of the LocalBaserowPasswordAppAuthProvider when the
password field is missing in the id_mapping.
The password field might be missing during an import, because the user
might have either deleted the password field in the database, or deleted
the table entirely.
"""
user = data_fixture.create_user()
workspace = data_fixture.create_workspace(user=user)
application = data_fixture.create_builder_application(workspace=workspace)
database = data_fixture.create_database_application(workspace=workspace)
integration = data_fixture.create_local_baserow_integration(
application=application, user=user
)
table_from_same_workspace1, fields, rows = data_fixture.build_table(
user=user,
database=database,
columns=[
("Email", "text"),
("Name", "text"),
("Password", "password"),
],
rows=[
["test@baserow.io", "Test", "password"],
],
)
email_field, name_field, password_field = fields
TO_IMPORT = {
"email_field_id": 42,
"id": 28,
"integration_id": 42,
"name": "Test name",
"name_field_id": 43,
"order": "1.00000000000000000000",
"table_id": 42,
"type": "local_baserow",
"auth_providers": [
{
"id": 42,
"type": "local_baserow_password",
"domain": None,
"enabled": True,
"password_field_id": 44,
}
],
}
id_mapping = defaultdict(MirrorDict)
id_mapping["integrations"] = {42: integration.id}
id_mapping["database_tables"] = {42: table_from_same_workspace1.id}
# the password field is intentionally excluded from database_fields
id_mapping["database_fields"] = {
42: email_field.id,
43: name_field.id,
}
imported_instance = UserSourceHandler().import_user_source(
application, TO_IMPORT, id_mapping
)
assert imported_instance.auth_providers.first().specific.password_field_id is None

View file

@ -868,6 +868,105 @@ def test_import_local_baserow_user_source(data_fixture):
assert imported_instance.name_field_id == name_field.id
@pytest.mark.django_db
@pytest.mark.parametrize(
"id_mapping_key,missing_field_name",
[
("database_tables", "table_id"),
("database_fields", "email_field_id"),
("database_fields", "name_field_id"),
("database_fields", "role_field_id"),
],
)
def test_import_local_baserow_user_source_with_missing_fields(
data_fixture, id_mapping_key, missing_field_name
):
"""
Test the import of the LocalBaserowUserSource when one or more fields
are missing in the exported workspace's database.
A field, such as the Role field might have been deleted before the user
has exported the workspace. As such, when importing the workspace, the
missing field needs to be safely handled.
"""
user = data_fixture.create_user()
workspace = data_fixture.create_workspace(user=user)
application = data_fixture.create_builder_application(workspace=workspace)
database = data_fixture.create_database_application(workspace=workspace)
integration = data_fixture.create_local_baserow_integration(
application=application, user=user
)
table_from_same_workspace1, fields, rows = data_fixture.build_table(
user=user,
database=database,
columns=[
("Email", "text"),
("Name", "text"),
("Role", "text"),
],
rows=[
["test@baserow.io", "Test", "Foo Role"],
],
)
email_field, name_field, role_field = fields
TO_IMPORT = {
"id": 28,
"name": "Test name",
"order": "1.00000000000000000000",
"type": "local_baserow",
"integration_id": 42,
"table_id": 42,
"name_field_id": 43,
"email_field_id": 42,
"role_field_id": 44,
"auth_providers": [
{
"id": 42,
"type": "local_baserow_password",
"domain": None,
"enabled": True,
"password_field_id": None,
}
],
}
id_mapping = defaultdict(MirrorDict)
id_mapping_data = {
"table_id": (42, table_from_same_workspace1.id),
"email_field_id": (42, email_field.id),
"name_field_id": (43, name_field.id),
"role_field_id": (44, role_field.id),
}
id_mapping["integrations"] = {42: integration.id}
id_mapping["database_tables"] = {42: table_from_same_workspace1.id}
id_mapping["database_fields"] = {
42: email_field.id,
43: name_field.id,
44: role_field.id,
}
# Remove a specific field to simulate a "missing field"
id_mapping[id_mapping_key].pop(id_mapping_data[missing_field_name][0])
imported_instance = UserSourceHandler().import_user_source(
application, TO_IMPORT, id_mapping
)
for property in id_mapping_data:
value = getattr(imported_instance, property)
if property == missing_field_name:
# Ensure that None is returned instead of raising a KeyError
assert value is None
else:
assert value is id_mapping_data[property][1]
@pytest.mark.django_db
def test_create_local_baserow_user_source_w_auth_providers(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()