From 2279497214b2e303d5b95f43eb6fbcb4a908e24b Mon Sep 17 00:00:00 2001 From: Austin Riba Date: Wed, 24 Jun 2026 14:03:00 -0700 Subject: [PATCH 1/4] Use correct app label for sharing persmissions This appears to have been broken for users that use custom targets. It only worked for non-custom targets by coincidence - PersistentShare has the same app label as the default target object. As soon as a custom target model is used, the app label changes (for example custom_code) but then the permissions don't match. They need to be tom_targets.add_persistentshare, for example, not custom_code.add_persistenceshare. --- tom_targets/templatetags/targets_extras.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tom_targets/templatetags/targets_extras.py b/tom_targets/templatetags/targets_extras.py index 0f1effe49..3daa97322 100644 --- a/tom_targets/templatetags/targets_extras.py +++ b/tom_targets/templatetags/targets_extras.py @@ -21,7 +21,7 @@ from tom_observations.utils import get_sidereal_visibility from tom_targets.base_models import BaseTarget -from tom_targets.models import Target, TargetExtra, TargetList +from tom_targets.models import Target, TargetExtra, TargetList, PersistentShare from tom_targets.forms import TargetVisibilityForm, PersistentShareForm from tom_targets.permissions import targets_for_user @@ -473,10 +473,10 @@ def persistent_share_table(context, target): Returns a partial for a table of persistent shares, used in persistent share management forms """ request = context['request'] - persistentshares = get_objects_for_user(request.user, f'{Target._meta.app_label}.view_persistentshare') + persistentshares = get_objects_for_user(request.user, f'{PersistentShare._meta.app_label}.view_persistentshare') if target: persistentshares = persistentshares.filter(target__pk=target.pk) - can_delete = request.user.has_perm(f'{Target._meta.app_label}.delete_persistentshare') + can_delete = request.user.has_perm(f'{PersistentShare._meta.app_label}.delete_persistentshare') return {'persistentshares': persistentshares, 'target': target, 'can_delete': can_delete} @@ -486,7 +486,7 @@ def create_persistent_share(context, target): Returns a partial for a creation form for creating persistent shares """ request = context['request'] - if request.user.has_perm(f'{Target._meta.app_label}.add_persistentshare'): + if request.user.has_perm(f'{PersistentShare._meta.app_label}.add_persistentshare'): if target: form = PersistentShareForm(target_id=target.pk) else: From de441311fc4aa20b40e100204a53ecfffc74f9df Mon Sep 17 00:00:00 2001 From: Austin Riba Date: Wed, 24 Jun 2026 14:14:37 -0700 Subject: [PATCH 2/4] Fix share submit button floating in the middle of nowhere --- tom_targets/templates/tom_targets/target_share.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tom_targets/templates/tom_targets/target_share.html b/tom_targets/templates/tom_targets/target_share.html index e191afcf2..de771fa00 100644 --- a/tom_targets/templates/tom_targets/target_share.html +++ b/tom_targets/templates/tom_targets/target_share.html @@ -23,7 +23,7 @@

Share {{ tar
- From a316da15a7d5d96ceb09aac5e893da0b19bf5e67 Mon Sep 17 00:00:00 2001 From: Austin Riba Date: Wed, 24 Jun 2026 16:06:35 -0700 Subject: [PATCH 3/4] Sharing: convert custom target model fiends to target extras --- tom_targets/sharing.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tom_targets/sharing.py b/tom_targets/sharing.py index 8dea14260..e070a5c4a 100644 --- a/tom_targets/sharing.py +++ b/tom_targets/sharing.py @@ -1,10 +1,11 @@ +from tom_targets.base_models import get_target_model_app_label, BaseTarget import requests from django.conf import settings from django.core.exceptions import ImproperlyConfigured from tom_targets.serializers import TargetSerializer -from tom_targets.models import PersistentShare +from tom_targets.models import PersistentShare, get_target_model_class from tom_dataproducts.sharing import (share_data_with_tom, get_destination_target, sharing_feedback_converter) @@ -37,6 +38,20 @@ def continuous_share_data(target, reduced_datums): share_data_with_tom(share_destination, None, None, None, selected_data=reduced_datum_pks) +def custom_target_to_extras(target_id) -> list[dict]: + target_app_label = get_target_model_app_label() + extra_fields = [] + if target_app_label != 'tom_targets': + target = get_target_model_class().objects.get(pk=target_id) + for field in target._meta.get_fields(): + if field not in BaseTarget._meta.get_fields() and field.name not in ['id', 'basetarget_ptr']: + value = getattr(target, field.name, None) + if value is not None: + extra_fields.append({'key': field.name, 'value': value}) + + return extra_fields + + def share_target_with_tom(share_destination, form_data, target_lists=()): """ Share a target with a remote TOM. @@ -76,6 +91,11 @@ def share_target_with_tom(share_destination, form_data, target_lists=()): if destination_target_id is None: # If target is not in Destination, serialize and create new target. serialized_target = TargetSerializer(form_data['target']).data + # If the shared target is a custom model custom fields should still be shared. + # Because the destination TOM might not have the same fields, we convert them to + # target extras. + extra_extras = custom_target_to_extras(serialized_target['id']) + serialized_target['targetextra_set'].extend(extra_extras) # Remove local User Groups serialized_target['groups'] = [] # Add target lists From d44f8e841a52aca5f244637ca8745284624e6ee0 Mon Sep 17 00:00:00 2001 From: Austin Riba Date: Thu, 2 Jul 2026 11:11:30 -0700 Subject: [PATCH 4/4] Always convert shared value to string --- tom_targets/sharing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tom_targets/sharing.py b/tom_targets/sharing.py index e070a5c4a..8f9b3a311 100644 --- a/tom_targets/sharing.py +++ b/tom_targets/sharing.py @@ -47,7 +47,7 @@ def custom_target_to_extras(target_id) -> list[dict]: if field not in BaseTarget._meta.get_fields() and field.name not in ['id', 'basetarget_ptr']: value = getattr(target, field.name, None) if value is not None: - extra_fields.append({'key': field.name, 'value': value}) + extra_fields.append({'key': field.name, 'value': str(value)}) return extra_fields