Skip to content

Commit

Permalink
update owner transfer api view (#836)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jan 17, 2025
1 parent f7b3298 commit bbeff39
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 20 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Changed
- Allow no role for old owner in ``RoleAssignmentOwnerTransferMixin`` (#836, #1391)
- Allow no role for old owner in ``perform_owner_transfer()`` (#836, #1391)
- Move app setting form helpers in ``SODARAppSettingFormMixin`` (#1545)
- Upgrade projectroles REST API version to v1.1 (#836)
- Allow empty ``old_owner_role`` in ``RoleAssignmentOwnerTransferAPIView`` (#836)
- **Tokens**
- Update UI for site read-only mode (#24)
- **Userprofile**
Expand Down
14 changes: 12 additions & 2 deletions docs/source/app_projectroles_api_rest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ Projectroles REST API Versioning
Media Type
``application/vnd.bihealth.sodar-core.projectroles+json``
Current Version
``1.0``
``1.1``
Accepted Versions
``1.0``
``1.0``, ``1.1``
Header Example
``Accept: application/vnd.bihealth.sodar-core.projectroles+json; version=x.y``

Expand Down Expand Up @@ -174,3 +174,13 @@ Projectroles REST API Views
.. autoclass:: UserListAPIView

.. autoclass:: CurrentUserRetrieveAPIView


Projectroles REST API Version Changes
=====================================

v1.1
----

- ``RoleAssignmentOwnerTransferAPIView``
* Allow empty value for ``old_owner_role``
10 changes: 10 additions & 0 deletions docs/source/major_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Release Highlights
- Add app setting definition as objects
- Update owner transfer form to allow setting no role for old owner
- Update app settings API
- Upgrade projectroles REST API version to v1.1
- Remove support for features deprecated in v1.0
- Remove squashed migrations

Expand Down Expand Up @@ -54,6 +55,15 @@ argument may be ``None``. This is used in cases where project role for the
previous owner is removed. Implementations of ``perform_role_modify()`` must be
changed accordingly. The same also applies to ``revert_role_modify()``.

REST API View Changes
---------------------

- Projectroles API (``vnd.bihealth.sodar-core.projectroles``)
* Current version: ``1.1`` (non-breaking changes)
* Allowed versions: ``1.0``, ``1.1``
* ``RoleAssignmentOwnerTransferAPIView``: Allow empty value for
``old_owner_role``

Deprecated Features
-------------------

Expand Down
43 changes: 43 additions & 0 deletions projectroles/tests/test_views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2255,6 +2255,49 @@ def test_post_remote(self):
self.assertEqual(response.status_code, 400, msg=response.content)
self.assertEqual(self.project.get_owner().user, self.user_owner)

def test_post_no_old_role(self):
"""Test POST with no old user role"""
self.make_assignment(self.project, self.user_new, self.role_contributor)
self.assertEqual(self.project.get_owner().user, self.user_owner)
post_data = {
'new_owner': self.user_new.username,
'old_owner_role': None,
}
response = self.request_knox(self.url, method='POST', data=post_data)
self.assertEqual(response.status_code, 200, msg=response.content)
self.assertEqual(self.project.get_owner().user, self.user_new)
self.assertIsNone(
RoleAssignment.objects.filter(
project=self.project, user=self.user_owner
).first()
)

def test_post_no_old_role_v1_0(self):
"""Test POST with no old user role and v1.0 (should fail)"""
self.make_assignment(self.project, self.user_new, self.role_contributor)
self.assertEqual(self.project.get_owner().user, self.user_owner)
post_data = {
'new_owner': self.user_new.username,
'old_owner_role': None,
}
response = self.request_knox(
self.url, method='POST', data=post_data, version='1.0'
)
self.assertEqual(response.status_code, 400, msg=response.content)
self.assertEqual(self.project.get_owner().user, self.user_owner)

def test_post_invalid_role(self):
"""Test POST with invalid old owner role (should fail)"""
self.make_assignment(self.project, self.user_new, self.role_contributor)
self.assertEqual(self.project.get_owner().user, self.user_owner)
post_data = {
'new_owner': self.user_new.username,
'old_owner_role': 'INVALID ROLE',
}
response = self.request_knox(self.url, method='POST', data=post_data)
self.assertEqual(response.status_code, 400, msg=response.content)
self.assertEqual(self.project.get_owner().user, self.user_owner)


class TestProjectInviteListAPIView(
ProjectInviteMixin, ProjectrolesAPIViewTestBase
Expand Down
46 changes: 28 additions & 18 deletions projectroles/views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@
PROJECTROLES_API_MEDIA_TYPE = (
'application/vnd.bihealth.sodar-core.projectroles+json'
)
PROJECTROLES_API_DEFAULT_VERSION = '1.0'
PROJECTROLES_API_ALLOWED_VERSIONS = ['1.0']
PROJECTROLES_API_DEFAULT_VERSION = '1.1'
PROJECTROLES_API_ALLOWED_VERSIONS = ['1.0', '1.1']
SYNC_API_MEDIA_TYPE = (
'application/vnd.bihealth.sodar-core.projectroles.sync+json'
)
Expand Down Expand Up @@ -619,37 +619,47 @@ class RoleAssignmentOwnerTransferAPIView(
**Parameters:**
- ``new_owner``: User name of new owner (string)
- ``old_owner_role``: Role for old owner (string. e.g. "project delegate")
- ``old_owner_role``: Role for old owner (string or None, e.g. "project delegate")
**Version Changes**:
- ``1.1``: Allow empty value for ``old_owner_role``
"""

permission_required = 'projectroles.update_project_owner'

def post(self, request, *args, **kwargs):
"""Handle ownership transfer in a POST request"""
d_new_owner = request.data.get('new_owner')
d_old_owner_role = request.data.get('old_owner_role')
# Validate input
if not d_new_owner:
raise serializers.ValidationError(
'Field "new_owner" must be present'
)
# Prevent old_owner_role=None if v1.0
if request.version == '1.0' and not d_old_owner_role:
raise serializers.ValidationError(
'Field "old_owner_role" must be present'
)

project = self.get_project()
# Validation for remote sites and projects
if project.is_remote():
raise serializers.ValidationError(REMOTE_MODIFY_MSG)

new_owner = User.objects.filter(
username=request.data.get('new_owner')
).first()
old_owner_role = Role.objects.filter(
name=request.data.get('old_owner_role')
).first()
new_owner = User.objects.filter(username=d_new_owner).first()
old_owner_role = None
if d_old_owner_role:
old_owner_role = Role.objects.filter(name=d_old_owner_role).first()
old_owner_as = project.get_owner()
old_owner = old_owner_as.user

# Validate input
if not new_owner or not old_owner_role:
raise serializers.ValidationError(
'Fields "new_owner" and "old_owner_role" must be present'
)
if not old_owner_role:
if d_old_owner_role and not old_owner_role:
raise serializers.ValidationError(
'Unknown role "{}"'.format(request.data.get('old_owner_role'))
'Unknown role "{}"'.format(d_old_owner_role)
)
if project.type not in old_owner_role.project_types:
if old_owner_role and project.type not in old_owner_role.project_types:
raise serializers.ValidationError(
ROLE_PROJECT_TYPE_ERROR_MSG.format(
project_type=project.type, role_name=old_owner_role.name
Expand All @@ -659,7 +669,7 @@ def post(self, request, *args, **kwargs):
raise serializers.ValidationError('Existing owner role not found')
if not new_owner:
raise serializers.ValidationError(
'User "{}" not found'.format(request.data.get('new_owner'))
'User "{}" not found'.format(d_new_owner)
)
if new_owner == old_owner:
raise serializers.ValidationError('Owner role already set for user')
Expand Down

0 comments on commit bbeff39

Please sign in to comment.