From f72790b89cbc35282a222451c1b64aacef316ccd Mon Sep 17 00:00:00 2001 From: Vlad0n20 Date: Thu, 28 Aug 2025 16:20:27 +0300 Subject: [PATCH 1/2] Update permissions for write preprint contributors --- api/actions/permissions.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/api/actions/permissions.py b/api/actions/permissions.py index dec41f32c3b..a10108e7b28 100644 --- a/api/actions/permissions.py +++ b/api/actions/permissions.py @@ -46,7 +46,19 @@ def has_object_permission(self, request, view, obj): else: # Moderators and node admins can trigger state changes. is_node_admin = target is not None and target.has_permission(auth.user, osf_permissions.ADMIN) - if not (is_node_admin or auth.user.has_perm('view_submissions', provider)): + is_write_contributor = target is not None and target.has_permission(auth.user, osf_permissions.WRITE) + + provisional_write_allowed = False + if is_write_contributor: + try: + serializer = view.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + trigger = serializer.validated_data.get('trigger') + provisional_write_allowed = trigger == ReviewTriggers.SUBMIT.value + except Exception: + provisional_write_allowed = False + + if not (is_node_admin or auth.user.has_perm('view_submissions', provider) or provisional_write_allowed): return False # User can trigger state changes on this reviewable, but can they use this trigger in particular? @@ -54,4 +66,6 @@ def has_object_permission(self, request, view, obj): serializer.is_valid(raise_exception=True) trigger = serializer.validated_data.get('trigger') permission = TRIGGER_PERMISSIONS[trigger] + if permission is None and is_write_contributor and trigger == ReviewTriggers.SUBMIT.value: + return True return permission is None or request.user.has_perm(permission, target.provider) From b87ceb71645152a69596f6044a1942ca5c30902e Mon Sep 17 00:00:00 2001 From: Vlad0n20 Date: Mon, 24 Nov 2025 14:42:28 +0200 Subject: [PATCH 2/2] Remove duplicate code --- api/actions/permissions.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/api/actions/permissions.py b/api/actions/permissions.py index a10108e7b28..9ee74565471 100644 --- a/api/actions/permissions.py +++ b/api/actions/permissions.py @@ -48,23 +48,17 @@ def has_object_permission(self, request, view, obj): is_node_admin = target is not None and target.has_permission(auth.user, osf_permissions.ADMIN) is_write_contributor = target is not None and target.has_permission(auth.user, osf_permissions.WRITE) - provisional_write_allowed = False - if is_write_contributor: - try: - serializer = view.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - trigger = serializer.validated_data.get('trigger') - provisional_write_allowed = trigger == ReviewTriggers.SUBMIT.value - except Exception: - provisional_write_allowed = False + # Validate serializer once and extract trigger + serializer = view.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + trigger = serializer.validated_data.get('trigger') + + provisional_write_allowed = is_write_contributor and trigger == ReviewTriggers.SUBMIT.value if not (is_node_admin or auth.user.has_perm('view_submissions', provider) or provisional_write_allowed): return False # User can trigger state changes on this reviewable, but can they use this trigger in particular? - serializer = view.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - trigger = serializer.validated_data.get('trigger') permission = TRIGGER_PERMISSIONS[trigger] if permission is None and is_write_contributor and trigger == ReviewTriggers.SUBMIT.value: return True