From 02d1a97f20401aaaa0f7a6f9455055b9757e2e2f Mon Sep 17 00:00:00 2001 From: Bradley Zylstra Date: Wed, 19 Nov 2025 00:19:36 +0000 Subject: [PATCH 1/4] Fixed issue where importing data from older versions of InvenTree+Postgres would fail --- tasks.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tasks.py b/tasks.py index 8aa2a0148493..7fcc6615bb99 100644 --- a/tasks.py +++ b/tasks.py @@ -1023,6 +1023,7 @@ def import_records( auth_data = [] load_data = [] + user_pk_pairing = {} for entry in data: if 'model' in entry: @@ -1030,9 +1031,10 @@ def import_records( if entry['model'] == 'auth.group': entry['fields']['permissions'] = [] - # Clear out any permissions specified for a user + # Clear out any permissions specified for a user and store the user's primary key for later if entry['model'] == 'auth.user': entry['fields']['user_permissions'] = [] + user_pk_pairing[entry['fields']['username']] = entry['pk'] # Save auth data for later if entry['model'].startswith('auth.'): @@ -1043,6 +1045,18 @@ def import_records( warning('WARNING: Invalid entry in data file') print(entry) + # User profiles should have the same primary key as auth.user, fix this if not the case + for entry in load_data: + if 'model' not in entry or 'fields' not in entry: + continue + + if not entry['model'].startswith('users.userprofile'): + continue + + user_profile_username = entry['fields']['user'][0] + # Set user profile primary key to corresponding auth.user primary key + entry['pk'] = user_pk_pairing[user_profile_username] + # Write the auth file data with open(authfile, 'w', encoding='utf-8') as f_out: f_out.write(json.dumps(auth_data, indent=2)) From 38ab057b8daeb2114287e19b978d3b85db8dcf5c Mon Sep 17 00:00:00 2001 From: Bradley Zylstra Date: Wed, 19 Nov 2025 10:11:32 -0500 Subject: [PATCH 2/4] Update tasks.py Changed .startswith to exact matching for users.userprofile. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks.py b/tasks.py index a4c6bdab79a3..72ea01aa65ef 100644 --- a/tasks.py +++ b/tasks.py @@ -1059,7 +1059,7 @@ def import_records( if 'model' not in entry or 'fields' not in entry: continue - if not entry['model'].startswith('users.userprofile'): + if entry['model'] != 'users.userprofile': continue user_profile_username = entry['fields']['user'][0] From 2898524422f57d5a514f035d7e9dbe8d7fb25e33 Mon Sep 17 00:00:00 2001 From: Bradley Zylstra Date: Wed, 19 Nov 2025 10:13:43 -0500 Subject: [PATCH 3/4] Update tasks.py Added validation checks to user primary key pairing dict. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tasks.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tasks.py b/tasks.py index 72ea01aa65ef..bbaf3ee2fd3e 100644 --- a/tasks.py +++ b/tasks.py @@ -1062,7 +1062,18 @@ def import_records( if entry['model'] != 'users.userprofile': continue - user_profile_username = entry['fields']['user'][0] + # Validate 'user' field + user_field = entry['fields'].get('user') + if ( + not isinstance(user_field, list) + or len(user_field) == 0 + or user_field[0] not in user_pk_pairing + ): + warning( + f"WARNING: Skipping userprofile entry due to missing or invalid user field: {entry}" + ) + continue + user_profile_username = user_field[0] # Set user profile primary key to corresponding auth.user primary key entry['pk'] = user_pk_pairing[user_profile_username] From f17a11eed142ff6816868395ac56e9501a529173 Mon Sep 17 00:00:00 2001 From: Bradley Zylstra Date: Thu, 20 Nov 2025 18:36:41 +0000 Subject: [PATCH 4/4] Reverted tasks.py, disabled signals in user model when importing data --- src/backend/InvenTree/users/models.py | 8 ++++++++ tasks.py | 27 +-------------------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/src/backend/InvenTree/users/models.py b/src/backend/InvenTree/users/models.py index 3ead74515da4..a9df02432fdd 100644 --- a/src/backend/InvenTree/users/models.py +++ b/src/backend/InvenTree/users/models.py @@ -600,6 +600,10 @@ def save(self, *args, **kwargs): @receiver(post_save, sender=User) def create_or_update_user_profile(sender, instance, created, **kwargs): """Create or update user profile when user is saved.""" + # Disable profile creation if importing data from file + if isImportingData(): + return + if created: UserProfile.objects.create(user=instance) instance.profile.save() @@ -629,6 +633,10 @@ def validate_primary_group_on_delete(sender, instance, **kwargs): @receiver(m2m_changed, sender=User.groups.through) def validate_primary_group_on_group_change(sender, instance, action, **kwargs): """Validate primary_group on user profiles when a group is added or removed.""" + # Disable user profile validation if importing data from file + if isImportingData(): + return + if action in ['post_add', 'post_remove']: profile = instance.profile if profile.primary_group and profile.primary_group not in instance.groups.all(): diff --git a/tasks.py b/tasks.py index bbaf3ee2fd3e..7dbc5ca68ac2 100644 --- a/tasks.py +++ b/tasks.py @@ -1032,7 +1032,6 @@ def import_records( auth_data = [] load_data = [] - user_pk_pairing = {} for entry in data: if 'model' in entry: @@ -1040,10 +1039,9 @@ def import_records( if entry['model'] == 'auth.group': entry['fields']['permissions'] = [] - # Clear out any permissions specified for a user and store the user's primary key for later + # Clear out any permissions specified for a user if entry['model'] == 'auth.user': entry['fields']['user_permissions'] = [] - user_pk_pairing[entry['fields']['username']] = entry['pk'] # Save auth data for later if entry['model'].startswith('auth.'): @@ -1054,29 +1052,6 @@ def import_records( warning('WARNING: Invalid entry in data file') print(entry) - # User profiles should have the same primary key as auth.user, fix this if not the case - for entry in load_data: - if 'model' not in entry or 'fields' not in entry: - continue - - if entry['model'] != 'users.userprofile': - continue - - # Validate 'user' field - user_field = entry['fields'].get('user') - if ( - not isinstance(user_field, list) - or len(user_field) == 0 - or user_field[0] not in user_pk_pairing - ): - warning( - f"WARNING: Skipping userprofile entry due to missing or invalid user field: {entry}" - ) - continue - user_profile_username = user_field[0] - # Set user profile primary key to corresponding auth.user primary key - entry['pk'] = user_pk_pairing[user_profile_username] - # Write the auth file data with open(authfile, 'w', encoding='utf-8') as f_out: f_out.write(json.dumps(auth_data, indent=2))