Skip to content

Commit

Permalink
Merge pull request #825 from cortex-lab/dev
Browse files Browse the repository at this point in the history
User rest endpoint changes to allow delegate information access from clients - Photometry datasets
  • Loading branch information
oliche authored Nov 30, 2023
2 parents 5b8229b + 236dbba commit f938172
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 28 deletions.
2 changes: 1 addition & 1 deletion alyx/alyx/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = __version__ = '1.16.2'
VERSION = __version__ = '1.17.0'
11 changes: 11 additions & 0 deletions alyx/data/fixtures/data.datasettype.json
Original file line number Diff line number Diff line change
Expand Up @@ -2209,5 +2209,16 @@
"description": "Unique identifier assigned to each ROI when ALF files created after ROI detection.",
"filename_pattern": ""
}
},
{
"model": "data.datasettype",
"pk": "e0a71fbc-f8ff-42a1-bfa7-d7764ab4104d",
"fields": {
"json": null,
"name": "photometryROI.locations",
"created_by": null,
"description": "Look up table from photometry ROI, to fiber name registered in the database and Allen brain location",
"filename_pattern": "*photometryROI.locations*"
}
}
]
4 changes: 3 additions & 1 deletion alyx/misc/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class Meta:
class UserSerializer(serializers.ModelSerializer):
subjects_responsible = serializers.SlugRelatedField(
many=True, queryset=Subject.objects.all(), slug_field='nickname')
allowed_users = serializers.SlugRelatedField(
many=True, queryset=LabMember.objects.all(), slug_field='username')

@staticmethod
def setup_eager_loading(queryset):
Expand All @@ -58,7 +60,7 @@ def setup_eager_loading(queryset):

class Meta:
model = get_user_model()
fields = ('id', 'username', 'email', 'subjects_responsible', 'lab')
fields = ('id', 'username', 'email', 'subjects_responsible', 'lab', 'allowed_users')


class LabSerializer(serializers.HyperlinkedModelSerializer):
Expand Down
9 changes: 8 additions & 1 deletion alyx/misc/tests_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def setUp(self):
self.lab = Lab.objects.create(name='basement')
self.public_user = get_user_model().objects.create(
username='troublemaker', password='azerty', is_public_user=True)
self.public_user.allowed_users.set([self.superuser])

def test_create_lab_membership(self):
# first test creation of lab through rest endpoint
Expand Down Expand Up @@ -55,6 +56,12 @@ def test_public_user(self):
def test_user_rest(self):
response = self.client.get(reverse('user-list') + '/test')
self.ar(response, 200)
response = self.client.get(reverse('user-list') + '/troublemaker')
self.ar(response, 200)
self.assertEqual(
response.data.get('allowed_users'),
list(self.public_user.allowed_users.all().values_list('username', flat=True))
)

def test_note_rest(self):
user = self.ar(self.client.get(reverse('user-list')), 200)
Expand All @@ -71,7 +78,7 @@ def test_note_rest(self):

class TestCacheView(BaseTests):
def setUp(self):
# This doesn't need super user privilages but I didn't know how to create a normal user
# This doesn't need super user privileges but I didn't know how to create a normal user
self.superuser = get_user_model().objects.create_user('test', 'test', 'test')
self.client.login(username='test', password='test')
self.tag = Tag.objects.create(name='2022_Q1_paper')
Expand Down
7 changes: 2 additions & 5 deletions alyx/misc/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@
from django.conf.urls import include


user_list = mv.UserViewSet.as_view({'get': 'list'})
user_detail = mv.UserViewSet.as_view({'get': 'retrieve'})

urlpatterns = [
path('', RedirectView.as_view(url='/admin')), # redirect the page to admin interface
path('labs', mv.LabList.as_view(), name="lab-list"),
path('labs/<str:name>', mv.LabDetail.as_view(), name="lab-detail"),
path('notes', mv.NoteList.as_view(), name="note-list"),
path('notes/<uuid:pk>', mv.NoteDetail.as_view(), name="note-detail"),
path('users/<str:username>', user_detail, name='user-detail'),
path('users', user_list, name='user-list'),
path('users', mv.UserList.as_view(), name="user-list"),
path('users/<str:username>', mv.UserDetail.as_view(), name="user-detail"),
re_path('^uploaded/(?P<img_url>.*)', mv.UploadedView.as_view(), name='uploaded'),
path('cache.zip', mv.CacheDownloadView.as_view(), name='cache-download'),
re_path(r'^cache/info(?:/(?P<tag>\w+))?/$', mv.CacheVersionView.as_view(), name='cache-info'),
Expand Down
30 changes: 25 additions & 5 deletions alyx/misc/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
HttpResponse, FileResponse, JsonResponse, HttpResponseRedirect, HttpResponseNotFound
)

from rest_framework import viewsets, views
from rest_framework import views
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.reverse import reverse
Expand Down Expand Up @@ -69,15 +69,35 @@ def api_root(request, format=None):
})


class UserViewSet(viewsets.ReadOnlyModelViewSet):
class UserFilter(BaseFilterSet):
class Meta:
model = get_user_model()
exclude = ['json']


class UserList(generics.ListCreateAPIView):
"""
Lists all users with the subjects which they are responsible for.
get: **FILTERS**
- 'id'
- 'username'
- 'email'
- 'subjects_responsible'
- 'lab'
- 'allowed_users'
[===> user model reference](/admin/doc/models/misc.labmember)
"""
queryset = get_user_model().objects.all()
queryset = UserSerializer.setup_eager_loading(queryset)
queryset = UserSerializer.setup_eager_loading(get_user_model().objects.all())
serializer_class = UserSerializer
permission_classes = rest_permission_classes()
filter_class = UserFilter
lookup_field = 'username'


class UserDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = UserSerializer.setup_eager_loading(get_user_model().objects.all())
serializer_class = UserSerializer
permission_classes = rest_permission_classes()
lookup_field = 'username'


class LabFilter(BaseFilterSet):
Expand Down
28 changes: 14 additions & 14 deletions requirements_frozen.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
asgiref==3.7.2
backports.zoneinfo==0.2.1
boto3==1.28.78
botocore==1.31.78
certifi==2023.7.22
boto3==1.33.4
botocore==1.33.4
certifi==2023.11.17
cffi==1.16.0
charset-normalizer==3.3.2
click==8.1.7
Expand All @@ -12,7 +12,7 @@ coreapi==2.3.3
coreschema==0.0.4
coverage==6.5.0
coveralls==3.3.1
cryptography==41.0.5
cryptography==41.0.7
cycler==0.12.1
Django==4.2.7
django-admin-list-filter-dropdown==1.0.3
Expand All @@ -24,22 +24,22 @@ django-ipware==5.0.2
django-js-asset==2.1.0
django-mptt==0.14.0
django-polymorphic==3.1.0
django-reversion==5.0.6
django-reversion==5.0.8
django-storages==1.14.2
django-structlog==6.0.0
django-structlog==6.0.1
django-test-without-migrations==0.6
djangorestframework==3.14.0
docopt==0.6.2
docutils==0.20.1
drfdocs==0.0.11
flake8==6.1.0
fonttools==4.44.0
globus-cli==3.18.0
globus-sdk==3.28.0
fonttools==4.45.1
globus-cli==3.19.0
globus-sdk==3.30.0
iblutil==1.7.1
idna==3.4
idna==3.6
importlib-metadata==6.8.0
importlib-resources==6.1.0
importlib-resources==6.1.1
itypes==1.2.0
Jinja2==3.1.2
jmespath==1.0.1
Expand All @@ -48,7 +48,7 @@ llvmlite==0.41.1
lxml==4.9.3
Markdown==3.5.1
MarkupSafe==2.1.3
matplotlib==3.7.3
matplotlib==3.7.4
mccabe==0.7.0
numba==0.58.1
numpy==1.24.4
Expand All @@ -57,7 +57,7 @@ packaging==23.2
pandas==2.0.3
Pillow==10.1.0
psycopg2-binary==2.9.9
pyarrow==14.0.0
pyarrow==14.0.1
pycodestyle==2.11.1
pycparser==2.21
pyflakes==3.1.0
Expand All @@ -68,7 +68,7 @@ python-magic==0.4.27
pytz==2023.3.post1
PyYAML==6.0.1
requests==2.31.0
s3transfer==0.7.0
s3transfer==0.8.2
six==1.16.0
sqlparse==0.4.4
structlog==23.2.0
Expand Down
3 changes: 2 additions & 1 deletion scripts/sync_ucl/prune_cortexlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@

# only imports users that are relevant to IBL
users_to_import = ['cyrille', 'Gaelle', 'kenneth', 'lauren', 'matteo', 'miles', 'nick', 'olivier',
'Karolina_Socha', 'Hamish', 'laura', 'niccolo', 'SamuelP', 'miriam.jansen', 'carolina.quadrado']
'Karolina_Socha', 'Hamish', 'laura', 'niccolo', 'SamuelP', 'miriam.jansen',
'carolina.quadrado']
users_to_leave = LabMember.objects.using('cortexlab').exclude(username__in=users_to_import)
users_to_keep = Dataset.objects.using('cortexlab').values_list('created_by', flat=True).distinct()
users_to_leave = users_to_leave.exclude(pk__in=users_to_keep)
Expand Down

0 comments on commit f938172

Please sign in to comment.