Skip to content

Commit

Permalink
add UserRetrieveAPIView (#1555)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jan 24, 2025
1 parent f52b41e commit 0803855
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Added
- ``ProjectDestroyAPIView`` REST API view (#1090)
- ``ProjectSerializer`` ``children`` field (#1552)
- ``SODARUserSerializer`` ``auth_type`` field (#1501)
- ``UserRetrieveAPIView`` REST API view (#1555)

Changed
-------
Expand Down
4 changes: 4 additions & 0 deletions docs/source/app_projectroles_api_rest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ Projectroles REST API Views

.. autoclass:: UserListAPIView

.. autoclass:: UserRetrieveAPIView

.. autoclass:: CurrentUserRetrieveAPIView


Expand All @@ -190,5 +192,7 @@ v1.1
* Add ``children`` field
- ``RoleAssignmentOwnerTransferAPIView``
* Allow empty value for ``old_owner_role``
- ``UserRetrieveAPIView``
* Add view
- ``CurrentUserRetrieveAPIView``
* Add ``auth_type`` field
2 changes: 2 additions & 0 deletions docs/source/major_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Release Highlights
- Add removeroles management command
- Add app setting type constants
- Add app setting definition as objects
- Add API view to retrieve user details by user UUID
- Update owner transfer form to allow setting no role for old owner
- Update app settings API
- Upgrade filesfolders REST API version to v2.0
Expand Down Expand Up @@ -99,6 +100,7 @@ REST API View Changes
* ``ProjectRetrieveAPIView``: Add ``children`` field
* ``RoleAssignmentOwnerTransferAPIView``: Allow empty value for
``old_owner_role``
* ``UserRetrieveAPIView``: Add view
* ``CurrentUserRetrieveAPIView``: Add ``auth_type`` field
- Sodarcache API
* Current version: ``2.0`` (breaking changes)
Expand Down
28 changes: 28 additions & 0 deletions projectroles/tests/test_permissions_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2273,6 +2273,34 @@ def test_get_read_only(self):
self.assert_response_api(self.url, self.anonymous, 401)


class TestUserRetrieveAPIView(ProjectrolesAPIPermissionTestBase):
"""Tests for UserRetrieveAPIView permissions"""

def setUp(self):
super().setUp()
self.url = reverse(
'projectroles:api_user_retrieve',
kwargs={'user': self.superuser.sodar_uuid},
)

def test_get(self):
"""Test UserRetrieveAPIView GET"""
self.assert_response_api(self.url, self.auth_users, 200)
self.assert_response_api(self.url, self.anonymous, 401)
self.assert_response_api(self.url, self.auth_users, 200, knox=True)

@override_settings(PROJECTROLES_ALLOW_ANONYMOUS=True)
def test_get_anon(self):
"""Test GET with anonymous access"""
self.assert_response_api(self.url, [self.anonymous], 401)

def test_get_read_only(self):
"""Test GET with site read-only mode"""
self.set_site_read_only()
self.assert_response_api(self.url, self.auth_users, 200)
self.assert_response_api(self.url, self.anonymous, 401)


class TestCurrentUserRetrieveAPIView(ProjectrolesAPIPermissionTestBase):
"""Tests for CurrentUserRetrieveAPIView permissions"""

Expand Down
84 changes: 63 additions & 21 deletions projectroles/tests/test_views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3383,14 +3383,76 @@ def test_get_pagination(self):
self.assertEqual(response_data, expected)


class TestUserRetrieveAPIView(
SODARUserAdditionalEmailMixin, ProjectrolesAPIViewTestBase
):
"""Tests for UserRetrieveAPIView"""

def setUp(self):
super().setUp()
# Create additional user
self.user_ldap = self.make_user('user_ldap@' + LDAP_DOMAIN)
group, _ = Group.objects.get_or_create(name=LDAP_DOMAIN.lower())
group.user_set.add(self.user_ldap)
self.url = reverse(
'projectroles:api_user_retrieve',
kwargs={'user': self.user_ldap.sodar_uuid},
)

def test_get(self):
"""Test UserRetrieveAPIView GET"""
response = self.request_knox(self.url)
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
expected = {
'username': self.user_ldap.username,
'name': self.user_ldap.name,
'email': self.user_ldap.email,
'additional_emails': [],
'is_superuser': False,
'auth_type': AUTH_TYPE_LDAP,
'sodar_uuid': str(self.user_ldap.sodar_uuid),
}
self.assertEqual(response_data, expected)

def test_get_additional_email(self):
"""Test GET with additional email"""
self.make_email(self.user_ldap, ADD_EMAIL)
response = self.request_knox(self.url)
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
expected = {
'username': self.user_ldap.username,
'name': self.user_ldap.name,
'email': self.user_ldap.email,
'additional_emails': [ADD_EMAIL],
'is_superuser': False,
'auth_type': AUTH_TYPE_LDAP,
'sodar_uuid': str(self.user_ldap.sodar_uuid),
}
self.assertEqual(response_data, expected)

def test_get_invalid_uuid(self):
"""Test GET with invalid UUID"""
url = reverse(
'projectroles:api_user_retrieve', kwargs={'user': INVALID_UUID}
)
response = self.request_knox(url)
self.assertEqual(response.status_code, 404)

def test_get_v1_0(self):
"""Test GET with version 1.0"""
response = self.request_knox(self.url, version='1.0')
self.assertEqual(response.status_code, 406)


class TestCurrentUserRetrieveAPIView(
SODARUserAdditionalEmailMixin, ProjectrolesAPIViewTestBase
):
"""Tests for CurrentUserRetrieveAPIView"""

def setUp(self):
super().setUp()
# Create additional users
self.user_ldap = self.make_user('user_ldap@' + LDAP_DOMAIN)
group, _ = Group.objects.get_or_create(name=LDAP_DOMAIN.lower())
group.user_set.add(self.user_ldap)
Expand All @@ -3413,7 +3475,6 @@ def test_get(self):
'sodar_uuid': str(self.user_ldap.sodar_uuid),
}
self.assertEqual(response_data, expected)
self.assertIn('auth_type', response_data)

def test_get_superuser(self):
"""Test GET as superuser"""
Expand All @@ -3431,25 +3492,6 @@ def test_get_superuser(self):
}
self.assertEqual(response_data, expected)

def test_get_additional_email(self):
"""Test GET with additional email"""
self.make_email(self.user_ldap, ADD_EMAIL)
response = self.request_knox(
self.url, token=self.get_token(self.user_ldap)
)
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
expected = {
'username': self.user_ldap.username,
'name': self.user_ldap.name,
'email': self.user_ldap.email,
'additional_emails': [ADD_EMAIL],
'is_superuser': False,
'auth_type': AUTH_TYPE_LDAP,
'sodar_uuid': str(self.user_ldap.sodar_uuid),
}
self.assertEqual(response_data, expected)

def test_get_v1_0(self):
"""Test GET with version 1.0"""
response = self.request_knox(
Expand Down
5 changes: 5 additions & 0 deletions projectroles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@
view=views_api.UserListAPIView.as_view(),
name='api_user_list',
),
path(
route='api/users/<uuid:user>',
view=views_api.UserRetrieveAPIView.as_view(),
name='api_user_retrieve',
),
path(
route='api/users/current',
view=views_api.CurrentUserRetrieveAPIView.as_view(),
Expand Down
44 changes: 37 additions & 7 deletions projectroles/views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1349,20 +1349,16 @@ def get_queryset(self):
return qs.exclude(groups__name=SODAR_CONSTANTS['SYSTEM_USER_GROUP'])


class CurrentUserRetrieveAPIView(
ProjectrolesAPIVersioningMixin, RetrieveAPIView
):
class UserRetrieveAPIView(ProjectrolesAPIVersioningMixin, RetrieveAPIView):
"""
Return information on the user making the request.
Return user details for user with the given UUID.
**URL:** ``/project/api/users/current``
**URL:** ``/project/api/users/{SODARUser.sodar_uuid}``
**Methods:** ``GET``
**Returns**:
For current user:
- ``additional_emails``: Additional verified email addresses for user (list of strings)
- ``auth_type``: User authentication type (string)
- ``email``: Email address of the user (string)
Expand All @@ -1373,6 +1369,40 @@ class CurrentUserRetrieveAPIView(
**Version Changes**:
- ``1.1``: Add view
"""

permission_classes = [IsAuthenticated]
serializer_class = SODARUserSerializer

def get_object(self):
try:
return User.objects.get(sodar_uuid=self.kwargs.get('user'))
except User.DoesNotExist:
raise NotFound()

def get(self, request, *args, **kwargs):
if parse_version(request.version) < parse_version('1.1'):
raise NotAcceptable(VIEW_NOT_ACCEPTABLE_VERSION)
return super().get(request, *args, **kwargs)


class CurrentUserRetrieveAPIView(
ProjectrolesAPIVersioningMixin, RetrieveAPIView
):
"""
Return user details for user performing the request.
**URL:** ``/project/api/users/current``
**Methods:** ``GET``
**Returns**:
User details, see ``UserRetrieveAPIView``.
**Version Changes**:
- ``1.1``: Add ``auth_type`` field
"""

Expand Down

0 comments on commit 0803855

Please sign in to comment.