diff --git a/tom_targets/base_models.py b/tom_targets/base_models.py index c4e81974f..eeeb4c63a 100644 --- a/tom_targets/base_models.py +++ b/tom_targets/base_models.py @@ -306,6 +306,12 @@ class BaseTarget(models.Model): :param slope: Asteroid/Comet slope parameter (G or k1) :type slope: float + + :param shared_by: If this target was shared to this TOM, the username of the user that shared it. + :type shared_by: str + + :param shared_from: If this target was shared to this TOM, the name of the TOM that shared it. + :type shared_from: str """ SIDEREAL = 'SIDEREAL' @@ -428,6 +434,12 @@ class Permissions(models.TextChoices): slope = models.FloatField( null=True, blank=True, verbose_name='Slope parameter', help_text='mag' ) + shared_by = models.CharField( + default='', blank=True, verbose_name='Shared by', help_text='Username' + ) + shared_from = models.CharField( + default='', blank=True, verbose_name='Shared from', help_text='TOM name' + ) objects = models.Manager() try: diff --git a/tom_targets/migrations/0031_basetarget_shared_by_basetarget_shared_from.py b/tom_targets/migrations/0031_basetarget_shared_by_basetarget_shared_from.py new file mode 100644 index 000000000..c898bac50 --- /dev/null +++ b/tom_targets/migrations/0031_basetarget_shared_by_basetarget_shared_from.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.13 on 2026-07-16 17:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tom_targets', '0030_alter_basetarget_slope'), + ] + + operations = [ + migrations.AddField( + model_name='basetarget', + name='shared_by', + field=models.CharField(blank=True, default='', help_text='Username', verbose_name='Shared by'), + ), + migrations.AddField( + model_name='basetarget', + name='shared_from', + field=models.CharField(blank=True, default='', help_text='TOM name', verbose_name='Shared from'), + ), + ] diff --git a/tom_targets/persistent_sharing_serializers.py b/tom_targets/persistent_sharing_serializers.py index 9a72b5162..ff4bbf4b7 100644 --- a/tom_targets/persistent_sharing_serializers.py +++ b/tom_targets/persistent_sharing_serializers.py @@ -19,7 +19,11 @@ class Meta: def create(self, validated_data): shared_existing_data = validated_data.pop('share_existing_data', None) if shared_existing_data: - sharing_feedback = share_target_and_all_data(validated_data['destination'], validated_data['target']) + sharing_feedback = share_target_and_all_data( + validated_data['destination'], + validated_data['target'], + validated_data['user'], + ) if 'ERROR' in sharing_feedback.upper(): raise serializers.ValidationError( f"Failed to share existing data of target {validated_data['target'].name}: {sharing_feedback}" diff --git a/tom_targets/sharing.py b/tom_targets/sharing.py index 8f9b3a311..ccfba928f 100644 --- a/tom_targets/sharing.py +++ b/tom_targets/sharing.py @@ -10,14 +10,14 @@ get_destination_target, sharing_feedback_converter) -def share_target_and_all_data(share_destination, target): +def share_target_and_all_data(share_destination, target, user): """ Given a sharing destination, shares the target and all its current dataproducts with that destination. Will raise an Exception is any portion of sharing fails. :param share_destination: String sharing destination from the DATA_SHARING setting :param target: Target instance that should be shared with all its data """ - response = share_target_with_tom(share_destination, {'target': target}) + response = share_target_with_tom(share_destination, {'target': target}, user=user) response_feedback = sharing_feedback_converter(response) if 'ERROR' in response_feedback.upper(): return response_feedback @@ -52,7 +52,7 @@ def custom_target_to_extras(target_id) -> list[dict]: return extra_fields -def share_target_with_tom(share_destination, form_data, target_lists=()): +def share_target_with_tom(share_destination, form_data, target_lists=(), user=None): """ Share a target with a remote TOM. :param share_destination: The name of the destination TOM as defined in settings.DATA_SHARING @@ -96,6 +96,10 @@ def share_target_with_tom(share_destination, form_data, target_lists=()): # target extras. extra_extras = custom_target_to_extras(serialized_target['id']) serialized_target['targetextra_set'].extend(extra_extras) + # Basic provenance + if user is not None: + serialized_target['shared_by'] = user.username + serialized_target['shared_from'] = settings.TOM_NAME # Remove local User Groups serialized_target['groups'] = [] # Add target lists diff --git a/tom_targets/views.py b/tom_targets/views.py index 5f94682a6..087b920fa 100644 --- a/tom_targets/views.py +++ b/tom_targets/views.py @@ -429,7 +429,7 @@ def form_valid(self, form): share_destination = form_data['share_destination'] selected_data = self.request.POST.getlist("share-box") # Share Target with Destination TOM - response = share_target_with_tom(share_destination, form_data) + response = share_target_with_tom(share_destination, form_data, user=self.request.user) sharing_feedback_handler(response, self.request) if selected_data: # Share Data with Destination TOM @@ -834,7 +834,12 @@ def form_valid(self, form): for target in selected_targets: # Share each target individually form_data['target'] = Target.objects.get(id=target) - response = share_target_with_tom(share_destination, form_data, target_lists=[form_data['target_list']]) + response = share_target_with_tom( + share_destination, + form_data, + target_lists=[form_data["target_list"]], + user=self.request.user, + ) sharing_feedback_handler(response, self.request) if data_switch: # If Data sharing request, share all data associated with the target