diff --git a/CHANGELOG b/CHANGELOG index 540c09878e3..5fcd0e35643 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,11 @@ We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO. +25.06.0 (2025-04-07) +==================== + +- Bugfix and Improvements + 25.05.0 (2025-03-11) ==================== diff --git a/api/nodes/views.py b/api/nodes/views.py index 7bc3ad929da..2c138685adb 100644 --- a/api/nodes/views.py +++ b/api/nodes/views.py @@ -212,13 +212,13 @@ class DraftMixin: def check_branched_from(self, draft): node_id = self.kwargs['node_id'] + if not draft.branched_from: + raise ValidationError('This draft registration is not created from the given node.') if not draft.branched_from._id == node_id: raise ValidationError('This draft registration is not created from the given node.') def check_resource_permissions(self, resource): # If branched from a node, use the node's contributor permissions. See [ENG-1563] - if resource.branched_from_type == 'Node': - resource = resource.branched_from return self.check_object_permissions(self.request, resource) def get_draft(self, draft_id=None, check_object_permissions=True): diff --git a/osf/models/registrations.py b/osf/models/registrations.py index f7b017d9ddf..b20236c9d8e 100644 --- a/osf/models/registrations.py +++ b/osf/models/registrations.py @@ -1269,27 +1269,21 @@ def create_from_node(cls, user, schema, node=None, data=None, provider=None): provider.validate_schema(schema) excluded_attributes = [] - if node: - branched_from = node - else: - branched_from = DraftNode.objects.create(creator=user, title=settings.DEFAULT_DRAFT_NODE_TITLE) - excluded_attributes.append('title') - - if not isinstance(branched_from, (Node, DraftNode)): - raise DraftRegistrationStateError() draft = cls( initiator=user, - branched_from=branched_from, + branched_from=node, registration_schema=schema, registration_metadata=data or {}, provider=provider, ) draft.save() - draft.copy_editable_fields( - branched_from, - excluded_attributes=excluded_attributes - ) + if node: + draft.copy_editable_fields( + node, + excluded_attributes=excluded_attributes + ) + draft.update(data, auth=Auth(user)) if not node: @@ -1501,7 +1495,7 @@ def create_django_groups_for_draft_registration(sender, instance, created, **kwa initiator = instance.initiator - if instance.branched_from.contributor_set.filter(user=initiator).exists(): + if instance.branched_from and instance.branched_from.contributor_set.filter(user=initiator).exists(): initiator_node_contributor = instance.branched_from.contributor_set.get(user=initiator) initiator_visibility = initiator_node_contributor.visible initiator_order = initiator_node_contributor._order diff --git a/osf/utils/machines.py b/osf/utils/machines.py index ab1c63afe49..04713b3cb26 100644 --- a/osf/utils/machines.py +++ b/osf/utils/machines.py @@ -211,9 +211,7 @@ def save_changes(self, ev): if ev.event.name == DefaultTriggers.ACCEPT.value: if not self.machineable.target.is_contributor(self.machineable.creator): - contributor_permissions = ( - self.machineable.requested_permissions or ev.kwargs.get('permissions') or permissions.READ - ) + contributor_permissions = ev.kwargs.get('permissions', self.machineable.requested_permissions) make_curator = self.machineable.request_type == NodeRequestTypes.INSTITUTIONAL_REQUEST.value visible = False if make_curator else ev.kwargs.get('visible', True) try: diff --git a/osf_tests/test_institutional_admin_contributors.py b/osf_tests/test_institutional_admin_contributors.py index a442e78565b..93ba0ac1305 100644 --- a/osf_tests/test_institutional_admin_contributors.py +++ b/osf_tests/test_institutional_admin_contributors.py @@ -146,7 +146,36 @@ def test_requested_permissions_or_default(self, app, project, institutional_admi make_curator=False, ) + def test_permissions_override_requested_permissions(self, app, project, institutional_admin): + """ + A project admin sees the requested permissions, but adds another type + """ + + node_request = project.requests.create( + creator=institutional_admin, + request_type=NodeRequestTypes.ACCESS.value, + requested_permissions=permissions.ADMIN, # Explicitly set permissions + machine_state=DefaultStates.PENDING.value, + ) + + with mock.patch('osf.models.Node.add_contributor') as mock_add_contributor: + node_request.run_accept( + user=project.creator, + comment='test comment', + ) + mock_add_contributor.assert_called_once_with( + institutional_admin, + auth=mock.ANY, + permissions=permissions.ADMIN, # `requested_permissions` should take precedence + visible=True, + send_email='access_request', + make_curator=False, + ) + def test_requested_permissions_is_used(self, app, project, institutional_admin): + """ + A project admin sees the requested permissions and doesn't override them. + """ node_request = project.requests.create( creator=institutional_admin, @@ -159,7 +188,6 @@ def test_requested_permissions_is_used(self, app, project, institutional_admin): node_request.run_accept( user=project.creator, comment='test comment', - permissions=permissions.WRITE # Default permissions to use if requested_permissions is None ) mock_add_contributor.assert_called_once_with( institutional_admin, diff --git a/package.json b/package.json index 1b289a11468..e97d5265722 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "OSF", - "version": "25.05.2", + "version": "25.06.0", "description": "Facilitating Open Science", "repository": "https://github.com/CenterForOpenScience/osf.io", "author": "Center for Open Science",