Skip to content

Commit

Permalink
✨ Data responses: GET /applet/{id}/data (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
shnizzedy authored Jan 17, 2020
2 parents 76abb94 + e93a321 commit 6461f27
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Changes
-------
Unreleased
==========
2019-12-20: v0.8.1
^^^^^^^^^^^^^^^^^^
* :sparkles: Data access for reviewers

2019-12-18: v0.7.5
^^^^^^^^^^^^^^^^^^
* :racehorse: Check if user requesting user list is a coordinator just once
Expand Down
43 changes: 41 additions & 2 deletions girderformindlogger/api/v1/applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import uuid
import requests
from ..describe import Description, autoDescribeRoute
from ..rest import Resource
from ..rest import Resource, rawResponse
from bson.objectid import ObjectId
from girderformindlogger.constants import AccessType, SortDir, TokenScope, \
DEFINED_INFORMANTS, REPROLIB_CANONICAL, SPECIAL_SUBJECTS, USER_ROLES
Expand All @@ -50,6 +50,7 @@ def __init__(self):
self.resourceName = 'applet'
self._model = AppletModel()
self.route('GET', (':id',), self.getApplet)
self.route('GET', (':id', 'data'), self.getAppletData)
self.route('GET', (':id', 'groups'), self.getAppletGroups)
self.route('POST', (), self.createApplet)
self.route('PUT', (':id', 'informant'), self.updateInformant)
Expand Down Expand Up @@ -187,6 +188,44 @@ def createApplet(self, protocolUrl=None, name=None, informant=None):
"an email when your applet is ready."
})

@access.user(scope=TokenScope.DATA_WRITE)
@autoDescribeRoute(
Description('Get all data you are authorized to see for an applet.')
.param(
'id',
'ID of the applet for which to fetch data',
required=True
)
.param(
'format',
'JSON or CSV',
required=False
)
.errorResponse('Write access was denied for this applet.', 403)
)
def getAppletData(self, id, format='json'):
import pandas as pd
from datetime import datetime
from ..rest import setContentDisposition, setRawResponse, setResponseHeader

format = ('json' if format is None else format).lower()
thisUser = self.getCurrentUser()
data = AppletModel().getResponseData(id, thisUser)

setContentDisposition("{}-{}.{}".format(
str(id),
datetime.now().isoformat(),
format
))
if format=='csv':
setRawResponse()
setResponseHeader('Content-Type', 'text/{}'.format(format))
csv = pd.DataFrame(data).to_csv(index=False)
return(csv)
setResponseHeader('Content-Type', 'application/{}'.format(format))
return(data)


@access.user(scope=TokenScope.DATA_WRITE)
@autoDescribeRoute(
Description('(managers only) Update the informant of an applet.')
Expand Down Expand Up @@ -356,7 +395,7 @@ def getAppletRoles(self, folder):
)
.param(
'role',
'Role to invite this user to. One of ' + str(USER_ROLE_KEYS),
'Role to invite this user to. One of ' + str(set(USER_ROLE_KEYS)),
default='user',
required=False,
strip=True
Expand Down
13 changes: 10 additions & 3 deletions girderformindlogger/models/ID_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,20 @@ def load(self, id, level=AccessType.ADMIN, user=None, objectId=True,
return doc

def findIdCodes(self, profileId):
return([
from .profile import Profile

idCodes = [
i['code'] for i in list(self.find({'profileId': {'$in': [
str(profileId),
ObjectId(profileId)
]}})) if isinstance(i, dict) and 'code' in i
])
]

if not len(idCodes):
self.createIdCode(Profile().load(profileId, force=True))
return(self.findIdCodes(profileId))

return(idCodes)

def removeCode(self, profileId, code):
from .profile import Profile
Expand Down Expand Up @@ -165,7 +173,6 @@ def createIdCode(self, profile, idCode=None):
raise e
print(sys.exc_info())


def findProfile(self, idCode):
"""
Find a list of profiles for a given ID code.
Expand Down
35 changes: 34 additions & 1 deletion girderformindlogger/models/applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,40 @@ def getResponseData(self, appletId, reviewer, filter={}):
:type filter: dict
:reutrns: TBD
"""
pass
from .ID_code import IDCode
from .profile import Profile
from .response_folder import ResponseItem
from .user import User
from pymongo import DESCENDING

if not self._hasRole(appletId, reviewer, 'reviewer'):
raise AccessException("You are not a reviewer for this applet.")
query = {
"baseParentType": "user",
"meta.applet.@id": ObjectId(appletId)
}
responses = list(ResponseItem().find(
query=query,
user=reviewer,
sort=[("created", DESCENDING)]
))
respondents = {
str(response['baseParentId']): IDCode().findIdCodes(
Profile().createProfile(
appletId,
User().load(response['baseParentId'], force=True),
'user'
)['_id']
) for response in responses if 'baseParentId' in response
}
return([
{
"respondent": code,
**response.get('meta', {})
} for response in responses for code in respondents[
str(response['baseParentId'])
]
])

def updateRelationship(self, applet, relationship):
"""
Expand Down
1 change: 1 addition & 0 deletions girderformindlogger/utility/jsonld_expander.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ def delanguageTag(obj):

def expandOneLevel(obj):
if obj is None:
# We only want to catch `None`s here, not other falsy objects
return(obj)
try:
newObj = jsonld.expand(obj)
Expand Down

0 comments on commit 6461f27

Please sign in to comment.