Skip to content

Commit

Permalink
Merge branch 'dev' into davrods-link-and-irods-batch-accept
Browse files Browse the repository at this point in the history
  • Loading branch information
gromdimon authored Jun 26, 2023
2 parents 474c9a2 + de867f5 commit 014f10c
Show file tree
Hide file tree
Showing 32 changed files with 2,608 additions and 480 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Added
- Enable ``stem_cell_core_bulk`` ISA-Tab template (#1697)
- Enable ``stem_cell_core_sc`` ISA-Tab template (#1697)
- Enable ``tumor_normal_dna`` ISA-Tab template (#1697)
- General iRODS access ticket management for assay collections (#804)
- General iRODS access ticket management for assay collections (#804, #1717)
- **Taskflowbackend**
- ``BatchCalculateChecksumTask`` iRODS task (#1634)
- Automated generation of missing checksums in ``zone_move`` flow (#1634)
Expand Down
25 changes: 25 additions & 0 deletions docs_manual/source/api_irodsinfo.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.. _api_irodsinfo:

Irods Info API
^^^^^^^^^^^^^^^^^

The REST API for irods info operations is described in this document.


API Views
=========

.. currentmodule:: irodsinfo.views_api

.. autoclass:: IrodsConfigRetrieveAPIView


Versioning
==========

For accept header versioning, the following header is expected in the current
SODAR version:

.. code-block:: console
Accept: application/vnd.bihealth.sodar+json; version=0.13.4
12 changes: 12 additions & 0 deletions docs_manual/source/api_samplesheets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ API Views

.. autoclass:: IrodsCollsCreateAPIView

.. autoclass:: IrodsDataRequestListAPIView

.. autoclass:: IrodsRequestCreateAPIView

.. autoclass:: IrodsRequestUpdateAPIView

.. autoclass:: IrodsRequestDeleteAPIView

.. autoclass:: IrodsRequestAcceptAPIView

.. autoclass:: IrodsRequestRejectAPIView

.. autoclass:: SheetImportAPIView

.. autoclass:: SheetISAExportAPIView
Expand Down
6 changes: 0 additions & 6 deletions docs_manual/source/data_transfer_irods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ access the data from elsewhere on the network, you need to install the
`official installation instructions <https://irods.org/download/>`_ for more
information.

.. note::

On Ubuntu 20.04, installing iCommands is not officially supported at the
time of writing. For workarounds,
`see this discussion <https://github.com/irods/irods/issues/4883>`_.

To configure your iCommands connection, open the
:ref:`ui_irods_info` application. In the app, click the
:guilabel:`Download Configuration` button to download a configuration file
Expand Down
1 change: 1 addition & 0 deletions docs_manual/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ Table of Contents
Project Management API <api_projectroles>
Sample Sheets API <api_samplesheets>
Landing Zones API <api_landingzones>
iRODS Info API <api_irodsinfo>
api_examples

.. toctree::
Expand Down
27 changes: 27 additions & 0 deletions irodsinfo/tests/test_permissions_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Tests for API view permissions in the irodsinfo app"""

from django.urls import reverse

# Projectroles dependency
from projectroles.tests.test_permissions import TestPermissionBase


class TestIrodsConfigRetrieveAPIView(TestPermissionBase):
"""Tests for irodsinfo API"""

def setUp(self):
# Create users
self.superuser = self.make_user('superuser')
self.superuser.is_superuser = True
self.superuser.save()
self.regular_user = self.make_user('regular_user')
# No user
self.anonymous = None

def test_irods_config(self):
"""Test permissions for IrodsConfigRetrieveAPIView"""
url = reverse('irodsinfo:api_env')
good_users = [self.superuser, self.regular_user]
bad_users = [self.anonymous]
self.assert_response(url, good_users, 200)
self.assert_response(url, bad_users, 401)
37 changes: 37 additions & 0 deletions irodsinfo/tests/test_views_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Tests for API views in the irodsinfo app"""

from django.test import override_settings
from django.urls import reverse
from rest_framework import status

from test_plus.test import TestCase

from irodsinfo.tests.test_views import PLUGINS_DISABLE_IRODS


class TestIrodsConfigRetrieveAPIView(TestCase):
"""Tests for IrodsConfigRetrieveAPIView"""

def setUp(self):
# Create users
self.superuser = self.make_user('superuser')
self.superuser.is_superuser = True
self.superuser.save()
self.regular_user = self.make_user('regular_user')

def test_get_irods_config(self):
"""Test GET request to retrieve iRODS config"""
url = reverse('irodsinfo:api_env')
with self.login(self.regular_user):
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('irods_environment', response.data)

@override_settings(ENABLED_BACKEND_PLUGINS=PLUGINS_DISABLE_IRODS)
def test_get_irods_config_with_disabled_backend(self):
"""Test GET request to retrieve iRODS config with disabled backend"""
url = reverse('irodsinfo:api_env')
with self.login(self.regular_user):
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertIn('iRODS backend not enabled', response.data['detail'])
18 changes: 16 additions & 2 deletions irodsinfo/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""URL patterns for the irodsinfo app"""

from django.urls import path

from . import views
from irodsinfo import views, views_api

app_name = 'irodsinfo'

urlpatterns = [
# UI views
urls_ui = [
path(
route='info',
view=views.IrodsInfoView.as_view(),
Expand All @@ -16,3 +19,14 @@
name='config',
),
]

# REST API views
urls_api = [
path(
route='api/environment',
view=views_api.IrodsEnvRetrieveAPIView.as_view(),
name='api_env',
),
]

urlpatterns = urls_ui + urls_api
74 changes: 45 additions & 29 deletions irodsinfo/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,45 @@
logger = logging.getLogger(__name__)


class IrodsConfigMixin:
"""Mixin for iRODS configuration views"""

@staticmethod
def get_irods_client_env(user, irods_backend):
"""
Create iRODS configuration file for the current user.
"""
user_name = user.username
# Just in case Django mangles the user name case, as it might
if user_name.find('@') != -1:
user_name = (
user_name.split('@')[0] + '@' + user_name.split('@')[1].upper()
)
home_path = '/{}/home/{}'.format(settings.IRODS_ZONE, user_name)
cert_file_name = settings.IRODS_HOST + '.crt'

# Set up irods_environment.json
irods_env = dict(settings.IRODS_ENV_DEFAULT)
irods_env.update(
{
'irods_authentication_scheme': 'PAM',
'irods_cwd': home_path,
'irods_home': home_path,
'irods_host': settings.IRODS_HOST_FQDN,
'irods_port': settings.IRODS_PORT,
'irods_user_name': user_name,
'irods_zone_name': settings.IRODS_ZONE,
}
)
if settings.IRODS_CERT_PATH:
irods_env['irods_ssl_certificate_file'] = cert_file_name
# Get optional client environment overrides
irods_env.update(dict(settings.IRODS_ENV_CLIENT))
irods_env = irods_backend.format_env(irods_env)
logger.debug('iRODS environment: {}'.format(irods_env))
return irods_env


class IrodsInfoView(LoggedInPermissionMixin, HTTPRefererMixin, TemplateView):
"""iRODS Information View"""

Expand Down Expand Up @@ -66,7 +105,9 @@ def get_context_data(self, *args, **kwargs):
return context


class IrodsConfigView(LoggedInPermissionMixin, HTTPRefererMixin, View):
class IrodsConfigView(
IrodsConfigMixin, LoggedInPermissionMixin, HTTPRefererMixin, View
):
"""iRODS Configuration file download view"""

permission_required = 'irodsinfo.get_config'
Expand All @@ -77,34 +118,8 @@ def get(self, request, *args, **kwargs):
messages.error(request, 'iRODS Backend not enabled.')
return redirect(reverse('irodsinfo:info'))

user_name = request.user.username
# Just in case Django mangles the user name case, as it might
if user_name.find('@') != -1:
user_name = (
user_name.split('@')[0] + '@' + user_name.split('@')[1].upper()
)
home_path = '/{}/home/{}'.format(settings.IRODS_ZONE, user_name)
cert_file_name = settings.IRODS_HOST + '.crt'

# Set up irods_environment.json
irods_env = dict(settings.IRODS_ENV_DEFAULT)
irods_env.update(
{
'irods_authentication_scheme': 'PAM',
'irods_cwd': home_path,
'irods_home': home_path,
'irods_host': settings.IRODS_HOST_FQDN,
'irods_port': settings.IRODS_PORT,
'irods_user_name': user_name,
'irods_zone_name': settings.IRODS_ZONE,
}
)
if settings.IRODS_CERT_PATH:
irods_env['irods_ssl_certificate_file'] = cert_file_name
# Get optional client environment overrides
irods_env.update(dict(settings.IRODS_ENV_CLIENT))
irods_env = irods_backend.format_env(irods_env)
logger.debug('iRODS environment: {}'.format(irods_env))
# Create iRODS environment file
irods_env = self.get_irods_client_env(request.user, irods_backend)
env_json = json.dumps(irods_env, indent=2)

# Create zip archive
Expand All @@ -117,6 +132,7 @@ def get(self, request, *args, **kwargs):
if settings.IRODS_CERT_PATH:
try:
with open(settings.IRODS_CERT_PATH) as cert_file:
cert_file_name = irods_env['irods_ssl_certificate_file']
zip_file.writestr(cert_file_name, cert_file.read())
except FileNotFoundError:
logger.warning(
Expand Down
48 changes: 48 additions & 0 deletions irodsinfo/views_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""REST API views for the irodsinfo app"""

import logging

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

# Projectroles dependency
from projectroles.plugins import get_backend_api

from irodsinfo.views import IrodsConfigMixin


logger = logging.getLogger(__name__)


class IrodsEnvRetrieveAPIView(IrodsConfigMixin, APIView):
"""
Retrieve iRODS environment file for the current user.
**URL:** ``/irods/api/environment``
**Methods:** ``GET``
**Returns:**
- ``irods_environment``: iRODS client environment
"""

permission_classes = [IsAuthenticated]

def get(self, request, *args, **kwargs):
"""Get iRODS environment file"""
try:
irods_backend = get_backend_api('omics_irods')
if not irods_backend:
return Response(
{'detail': 'iRODS backend not enabled'}, status=404
)
env = self.get_irods_client_env(request.user, irods_backend)
return Response({'irods_environment': env})

except Exception as ex:
logger.error('iRODS config retrieval failed: {}'.format(ex))
return Response(
{'detail': 'iRODS config retrieval failed'}, status=400
)
Loading

0 comments on commit 014f10c

Please sign in to comment.