Skip to content

Commit

Permalink
add view to check protected datasets
Browse files Browse the repository at this point in the history
  • Loading branch information
mayofaulkner committed Mar 20, 2024
1 parent 63c6871 commit bfcd921
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
31 changes: 31 additions & 0 deletions alyx/data/tests_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,37 @@ def test_protected_view(self):
self.assertEqual(name, 'test_prot/a.b.e1')
self.assertEqual(prot_info, [])

def test_check_protected(self):
self.post(reverse('datarepository-list'), {'name': 'drb1', 'hostname': 'hostb1'})
self.post(reverse('lab-list'), {'name': 'labb', 'repositories': ['drb1']})

# Create protected tag
self.client.post(reverse('tag-list'), {'name': 'tag1', 'protected': True})

# Create some datasets and register
data = {'path': '%s/2018-01-01/002/' % self.subject,
'filenames': 'test_prot/a.c.e2',
'name': 'drb1', # this is the repository name
}

d = self.client.post(reverse('register-file'), data)

# Check the same dataset to see if it is protected, should be unprotected
# and get a status 200 respons
_ = data.pop('name')
r = self.client.post(reverse('check-protected'), data)
self.assertEqual(r['status'], 200)

# add protected tag to the first dataset
dataset1 = Dataset.objects.get(pk=d[0]['id'])
tag1 = Tag.objects.get(name='tag1')
dataset1.tags.add(tag1)

# Check the same dataset to see if it is protected
r = self.client.post(reverse('check-protected'), data)
self.assertEqual(r['status'], 403)
self.assertEqual(r['error'], 'One or more datasets is protected')

def test_revisions(self):
# Check revision lookup with name
self.post(reverse('revision-list'), {'name': 'v2'})
Expand Down
6 changes: 6 additions & 0 deletions alyx/data/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
'post': 'create'
})

check_protected = dv.ProtectedFileViewSet.as_view({
'get': 'list'
})

urlpatterns = [
path('data-formats', dv.DataFormatList.as_view(),
Expand Down Expand Up @@ -78,4 +81,7 @@
path('sync-file-status', sync_file_status,
name="sync-file-status"),

path('check-protected', check_protected,
name="check-protected"),

]
71 changes: 71 additions & 0 deletions alyx/data/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,77 @@ def _parse_path(path):
return subject, date, session_number


class ProtectedFileViewSet(mixins.ListModelMixin,
viewsets.GenericViewSet):

serializer_class = serializers.Serializer

def list(self, request):
"""
Endpoint to check if set of files are protected or not
The session is retrieved by the ALF convention in the relative path, so this field has to
match the format Subject/Date/Number as shown below.
The client side REST query should look like this:
```python
r_ = {'created_by': 'user_name_alyx',
'path': 'ZM_1085/2019-02-12/002/alf', # relative path to repo path
'filenames': ['file1', 'file2'],
}
```
Returns a response indicating if any of the datasets are protected or not
- Status 403 if a dataset is protected, details contains a list of protected datasets
- Status 200 is none of the datasets are protected
"""

user = request.data.get('created_by', None)
if user:
user = get_user_model().objects.get(username=user)
else:
user = request.user

rel_dir_path = request.data.get('path', '')
if not rel_dir_path:
raise ValueError("The path argument is required.")

# Extract the data repository from the hostname, the subject, the directory path.
rel_dir_path = rel_dir_path.replace('\\', '/')
rel_dir_path = rel_dir_path.replace('//', '/')
subject, date, session_number = _parse_path(rel_dir_path)

filenames = request.data.get('filenames', ())
if isinstance(filenames, str):
filenames = filenames.split(',')

session = _get_session(
subject=subject, date=date, number=session_number, user=user)
assert session

# Loop through the files to see if any are protected
prot_response = []
protected = []
for file in filenames:
info, resp = _get_name_collection_revision(file, rel_dir_path)
if resp:
return resp
prot, prot_info = _check_dataset_protected(
session, info['collection'], info['filename'])
protected.append(prot)
prot_response.append({file: prot_info})
if any(protected):
data = {'status_code': 403,
'error': 'One or more datasets is protected',
'details': prot_response}
return Response(data=data)
else:
data = {'status_code': 200,
'details': 'None of the datasets are protected'}
return Response(data=data)


class RegisterFileViewSet(mixins.CreateModelMixin,
viewsets.GenericViewSet):

Expand Down

0 comments on commit bfcd921

Please sign in to comment.