Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -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)
====================

Expand Down
4 changes: 2 additions & 2 deletions api/nodes/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
22 changes: 8 additions & 14 deletions osf/models/registrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions osf/utils/machines.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
30 changes: 29 additions & 1 deletion osf_tests/test_institutional_admin_contributors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down