def reloadAndUpdateCache(self, applet, editor): from girderformindlogger.models.protocol import Protocol protocolUrl = applet.get('meta', {}).get('protocol', applet).get( 'http://schema.org/url', applet.get('meta', {}).get('protocol', applet).get('url')) if protocolUrl is not None: protocol = Protocol().getFromUrl(protocolUrl, 'protocol', editor, thread=False, refreshCache=True) protocol = protocol[0].get('protocol', protocol[0]) if protocol.get('_id'): self.update({'_id': ObjectId(applet['_id'])}, {'$set': { 'meta.protocol._id': protocol['_id'] }}) if 'meta' in applet and 'protocol' in applet['meta']: applet['meta']['protocol']['_id'] = protocol['_id'] from girderformindlogger.utility import jsonld_expander jsonld_expander.formatLdObject(applet, 'applet', editor, refreshCache=False, responseDates=False)
def formatThenUpdate(self, applet, user): from girderformindlogger.utility import jsonld_expander jsonld_expander.formatLdObject(applet, 'applet', user, refreshCache=True) self.updateUserCacheAllRoles(user)
def updateUserCache(self, role, user, active=True, refreshCache=False): import threading from bson import json_util from girderformindlogger.models.profile import Profile from girderformindlogger.utility import jsonld_expander applets = self.getAppletsForUser(role, user, active) user['cached'] = user.get('cached', {}) user['cached'] = json_util.loads(user['cached']) if isinstance( user['cached'], str) else user['cached'] user['cached']['applets'] = user['cached'].get('applets', {}) user['cached']['applets'][role] = user['cached']['applets'].get( role, {}) formatted = [{ **jsonld_expander.formatLdObject(applet, 'applet', user, refreshCache=refreshCache, responseDates=False), "users": self.getAppletUsers(applet, user), "groups": self.getAppletGroups(applet, arrayOfObjects=True) } if role in ["coordinator", "manager"] else { **jsonld_expander.formatLdObject(applet, 'applet', user, refreshCache=refreshCache, responseDates=(role == "user")), "groups": [ group for group in self.getAppletGroups(applet).get(role) if ObjectId(group) in [ *user.get('groups', []), *user.get('formerGroups', []), *[ invite['groupId'] for invite in [ *user.get('groupInvites', []), *user.get('declinedInvites', []) ] ] ] ] } for applet in applets if ( applet is not None and not applet.get('meta', {}).get('applet', {}).get('deleted'))] postformatted = [] for applet in formatted: if applet['applet'].get('informantRelationship') == 'parent': [ postformatted.append(a) for a in jsonld_expander.childByParent(user, applet) ] else: postformatted.append(applet) user['cached']['applets'].update({role: postformatted}) thread = threading.Thread(target=UserModel().save, args=(user, )) thread.start() return (formatted)
def getUserApplets(self, user, role, ids_only): from bson.objectid import ObjectId reviewer = self.getCurrentUser() if reviewer is None: raise AccessException("You must be logged in to get user applets.") if user.get('_id') != reviewer.get('_id') and user.get( '_id') is not None: raise AccessException("You can only get your own applets.") role = role.lower() if role not in USER_ROLES.keys(): raise RestException('Invalid user role.', 'role') try: applets = AppletModel().getAppletsForUser(role, user, active=True) if len(applets) == 0: return ([]) if ids_only == True: return ([applet.get('_id') for applet in applets]) return ([{ **jsonld_expander.formatLdObject(applet, 'applet', reviewer, refreshCache=False), "users": AppletModel().getAppletUsers(applet, user), "groups": AppletModel().getAppletGroups(applet, arrayOfObjects=True) } if role == "manager" else { **jsonld_expander.formatLdObject(applet, 'applet', reviewer, dropErrors=True), "groups": [ group for group in AppletModel().getAppletGroups( applet).get(role) if ObjectId(group) in [ *user.get('groups', []), *user.get('formerGroups', []), *[ invite['groupId'] for invite in [ *user.get('groupInvites', []), *user.get('declinedInvites', []) ] ] ] ] } for applet in applets if (applet is not None and not applet.get( 'meta', {}).get('applet', {}).get('deleted'))]) except Exception as e: return (e)
def getProtocol(self, folder): try: protocol = folder user = self.getCurrentUser() return (jsonld_expander.formatLdObject(protocol, 'protocol', user)) except: import sys, traceback print(sys.exc_info()) return ({traceback.print_tb(sys.exc_info()[2])})
def updateInformant(self, applet, informant): user = self.getCurrentUser() if not AppletModel().isManager(applet['_id'], user): raise AccessException( "Only managers can update informant relationship") AppletModel().updateRelationship(applet, informant) return (jsonld_expander.formatLdObject(applet, 'applet', user, refreshCache=False))
def setConstraints(self, folder, activity, schedule, **kwargs): thisUser = self.getCurrentUser() applet = jsonld_expander.formatLdObject(_setConstraints( folder, activity, schedule, thisUser), 'applet', thisUser, refreshCache=True) jsonld_expander.createCache(folder, applet, 'applet') return (applet)
def getProtocolFromURL(self, url): try: thisUser = self.getCurrentUser() return (jsonld_expander.formatLdObject( ProtocolModel().importUrl(url, thisUser), 'protocol', thisUser)) except: import sys, traceback print(sys.exc_info()) return ({traceback.print_tb(sys.exc_info()[2])})
def setConstraints(self, folder, activity, schedule, **kwargs): thisUser = self.getCurrentUser() applet = jsonld_expander.formatLdObject(_setConstraints( folder, activity, schedule, thisUser), 'applet', thisUser, refreshCache=True) thread = threading.Thread( target=AppletModel().updateUserCacheAllUsersAllRoles, args=(applet, thisUser)) thread.start() return (applet)
def createScreen(self, activity, screenName=None): thisUser = self.getCurrentUser() activity = ActivityModel().load(activity, level=AccessType.WRITE, user=thisUser) screen = ScreenModel().createScreen( name=screenName if screenName is not None else str(len(list(FolderModel().childItems(activity))) + 1), creator=thisUser, folder=activity, reuseExisting=False) return (jsonld_expander._fixUpFormat( jsonld_expander.formatLdObject(screen, 'screen', thisUser)))
def getApplet(self, applet, refreshCache=False): user = self.getCurrentUser() if refreshCache: thread = threading.Thread(target=jsonld_expander.formatLdObject, args=(applet, 'applet', user), kwargs={'refreshCache': refreshCache}) thread.start() return ({ "message": "The applet is being refreshed. Please check back " "in several mintutes to see it." }) return (jsonld_expander.formatLdObject(applet, 'applet', user, refreshCache=refreshCache))
def getAppletById(user, ar): """ make sure the user has exactly one expected applet in its list inputs ------ user: a user object ar: an applet response object """ currentUser = authenticate(user=user['login'], password='******') res = AppletModel().getAppletsForUser(role='user', user=currentUser) assert str(res[0]['_id']) == str(ar['applet']['_id'].split('applet/') [-1]), 'applet ids are not the same' return (jsonld_expander.formatLdObject(res[0], 'applet', user, refreshCache=False))
def getApplet(self, applet, refreshCache=False): user = self.getCurrentUser() # we don't need to refreshCache here (cached data is automatically updated whenever original data changes). refreshCache = False if refreshCache: thread = threading.Thread(target=jsonld_expander.formatLdObject, args=(applet, 'applet', user), kwargs={'refreshCache': refreshCache}) thread.start() return ({ "message": "The applet is being refreshed. Please check back " "in several mintutes to see it." }) return (jsonld_expander.formatLdObject(applet, 'applet', user, refreshCache=refreshCache))
def getExpandedApplets(user): """ get the fully expanded applet for a user inputs ------ user: a user object """ currentUser = authenticate(user) applets = AppletModel().getAppletsForUser(role='user', user=currentUser) try: expandedApplets = [ jsonld_expander.formatLdObject(applet, 'applet', currentUser) for applet in applets ] except: return (applets) # TODO: add some checks to the structure of expandedApplets to make sure # the mobile app can parse it. checkObjectForURLs(expandedApplets) return expandedApplets
def createApplet(self, name, protocol={}, user=None, roles=None, constraints=None): """ Method to create an Applet. :param name: Name for the Applet :type name: str :param protocol: Protocol to link to this Applet, with one or both keys: {`_id`, `url`} :type protocol: dict :param user: User creating Applet :type user: dict :param roles: Roles to set to this Applet :type roles: dict or None :param constraints: Constraints to set to this Applet :type constraints: dict or None """ from girderformindlogger.utility import jsonld_expander if user == None: raise AccessException("You must be logged in to create an applet.") appletsCollection = CollectionModel().findOne({"name": "Applets"}) # create the Applets collection if it isn't there! if not appletsCollection: CollectionModel().createCollection('Applets') appletsCollection = CollectionModel().findOne({"name": "Applets"}) # create new applet applet = self.setMetadata( folder=self.createFolder(parent=appletsCollection, name=name, parentType='collection', public=True, creator=user, allowRename=True), metadata={ 'protocol': protocol, 'applet': constraints if constraints is not None and isinstance(constraints, dict) else {} }) appletGroupName = "Default {} ({})".format(name, str(applet.get('_id', ''))) print("Name: {}".format(appletGroupName)) # Create user groups for role in USER_ROLES.keys(): try: group = GroupModel().createGroup( name="{} {}s".format(appletGroupName, role.title()), creator=user, public=False if role == 'user' else True) except ValidationException: numero = 0 numberedName = appletGroupName while GroupModel().findOne(query={'name': numberedName}): numero += 1 numberedName = "{} {} {}s".format(appletGroupName, str(numero), role.title()) group = GroupModel().createGroup( name=numberedName, creator=user, public=False if role == 'user' else True) self.setGroupRole(doc=applet, group=group, role=role, currentUser=user, force=False) return (jsonld_expander.formatLdObject(applet, 'applet', user))
def getScreen(self, item): screen = item user = self.getCurrentUser() return (jsonld_expander._fixUpFormat( jsonld_expander.formatLdObject(screen, 'screen', user)))
def getScreenByURL(self, url): thisUser = self.getCurrentUser() return (jsonld_expander._fixUpFormat( jsonld_expander.formatLdObject( ScreenModel().importUrl(url=url, user=thisUser), 'screen', thisUser)))
def _setConstraints(applet, activity, schedule, user, refreshCache=False): """ Helper function for method recursion. :param applet: applet Object :type applet: dict :param activity: Activity ID :type activity: str, list, or None :param schedule: schedule data :type schedule: dict, list, or None :param user: user making the call :type user: dict :returns: updated applet Object """ if activity is None: if schedule is not None: appletMeta = applet.get('meta', {}) appletMeta['applet']['schedule'] = schedule applet = AppletModel().setMetadata(applet, appletMeta) return (applet) if isinstance(activity, str) and activity.startswith('['): try: activity = [ activity_.replace("'", "").replace('"', '').strip() for activity_ in activity[1:-1].split(',') ] except (TypeError, AttributeError) as e: print(e) if isinstance(activity, list): for activity_ in activity: applet = _setConstraints(applet, activity_, schedule, user) return (applet) try: activityLoaded = ActivityModel().getFromUrl(activity, 'activity', thisUser, refreshCache)[0] except: activityLoaded = ActivityModel().load(activity, AccessType.WRITE, user) try: activityMeta = activityLoaded['meta'].get('activity') except AttributeError: raise ValidationException('Invalid activity.', 'activity') activityKey = activityMeta.get( 'url', activityMeta.get('@id', activityLoaded.get('_id'))) if activityKey is None: raise ValidationException('Invalid activity.', 'activity') else: activityKey = jsonld_expander.reprolibPrefix(activityKey) protocolExpanded = jsonld_expander.formatLdObject(applet, 'applet', user).get('applet', {}) protocolOrder = protocolExpanded.get('ui', {}).get('order', []) framedActivityKeys = [ protocolOrder[i] for i, v in enumerate( protocolExpanded.get("reprolib:terms/order")[0].get("@list")) if jsonld_expander.reprolibPrefix(v.get("@id")) == activityKey ] if schedule is not None: appletMeta = applet.get('meta', {}) scheduleInApplet = appletMeta.get('applet', {}).get('schedule', {}) for k in framedActivityKeys: scheduleInApplet[k] = schedule appletMeta['applet']['schedule'] = scheduleInApplet applet = AppletModel().setMetadata(applet, appletMeta) return (applet)
def createApplet(self, name, protocol={}, user=None, roles=None, constraints=None, appletName=None): """ Method to create an Applet. :param name: Name for the Applet :type name: str :param protocol: Protocol to link to this Applet, with one or both keys: {`_id`, `url`} :type protocol: dict :param user: User creating Applet :type user: dict :param roles: Roles to set to this Applet :type roles: dict or None :param constraints: Constraints to set to this Applet :type constraints: dict or None """ from girderformindlogger.utility import jsonld_expander if user == None: raise AccessException("You must be logged in to create an applet.") appletsCollection = CollectionModel().findOne({"name": "Applets"}) # create the Applets collection if it isn't there! if not appletsCollection: CollectionModel().createCollection('Applets') appletsCollection = CollectionModel().findOne({"name": "Applets"}) appletName = self.validateAppletName(appletName, appletsCollection, user) # create new applet applet = self.setMetadata( folder=self.createFolder(parent=appletsCollection, name=name, parentType='collection', public=True, creator=user, allowRename=True, appletName=appletName), metadata={ 'protocol': protocol, 'applet': constraints if constraints is not None and isinstance(constraints, dict) else {} }) appletGroupName = "Default {} ({})".format(name, str(applet.get('_id', ''))) print("Name: {}".format(appletGroupName)) # Create user groups role2AccessLevel = { 'user': AccessType.READ, 'coordinator': AccessType.ADMIN, 'manager': AccessType.ADMIN, 'editor': AccessType.WRITE, 'reviewer': AccessType.READ } accessList = applet.get('access', {}) accessList['groups'] = [] for role in USER_ROLES.keys(): try: group = GroupModel().createGroup( name="{} {}s".format(appletGroupName, role.title()), creator=user, public=False if role == 'user' else True) accessList['groups'].append({ 'id': ObjectId(group['_id']), 'level': role2AccessLevel[role] }) except ValidationException: numero = 0 numberedName = appletGroupName while GroupModel().findOne(query={'name': numberedName}): numero += 1 numberedName = "{} {} {}s".format(appletGroupName, str(numero), role.title()) group = GroupModel().createGroup( name=numberedName, creator=user, public=False if role == 'user' else True) self.setGroupRole(doc=applet, group=group, role=role, currentUser=user, force=False) self.setAccessList(applet, accessList) self.update({'_id': ObjectId(applet['_id'])}, {'$set': { 'access': applet.get('access', {}) }}) from girderformindlogger.models.profile import Profile # give all roles to creator of an applet profile = Profile().createProfile(applet, user, 'manager') profile = Profile().load(profile['_id'], force=True) profile['roles'] = list(USER_ROLES.keys()) Profile().save(profile, False) UserModel().appendApplet(UserModel().load(user['_id'], force=True), applet['_id'], USER_ROLES.keys()) return (jsonld_expander.formatLdObject(applet, 'applet', user, refreshCache=False))
def getOwnApplets( self, role, ids_only=False, unexpanded=False, refreshCache=False ): from bson.objectid import ObjectId from girderformindlogger.utility.jsonld_expander import loadCache from girderformindlogger.utility.response import responseDateList reviewer = self.getCurrentUser() if reviewer is None: raise AccessException("You must be logged in to get user applets.") role = role.lower() if role not in USER_ROLES.keys(): raise RestException( 'Invalid user role.', 'role' ) applet_ids = reviewer.get('applets', {}).get(role, []) if ids_only: return applet_ids applets = [AppletModel().load(ObjectId(applet_id), AccessType.READ) for applet_id in applet_ids] if unexpanded: return([{ 'applet': AppletModel().unexpanded(applet) } for applet in applets]) try: result = [] for applet in applets: if applet.get('cached'): formatted = { **jsonld_expander.formatLdObject( applet, 'applet', reviewer, refreshCache=refreshCache, responseDates=False ), "users": AppletModel().getAppletUsers(applet, reviewer), "groups": AppletModel().getAppletGroups( applet, arrayOfObjects=True ) } if role in ["coordinator", "manager"] else { **jsonld_expander.formatLdObject( applet, 'applet', reviewer, refreshCache=refreshCache, responseDates=(role=="user") ), "groups": [ group for group in AppletModel().getAppletGroups(applet).get( role ) if ObjectId( group ) in [ *reviewer.get('groups', []), *reviewer.get('formerGroups', []), *[invite['groupId'] for invite in [ *reviewer.get('groupInvites', []), *reviewer.get('declinedInvites', []) ]] ] ] } try: formatted["applet"]["responseDates"] = responseDateList( applet.get('_id'), reviewer.get('_id'), reviewer ) except: formatted["applet"]["responseDates"] = [] result.append(formatted) return(result) except: import sys, traceback print(sys.exc_info()) return([])
def duplicateProtocol(self, protocolId, editor, prefLabel=None): from girderformindlogger.models.screen import Screen from girderformindlogger.utility import jsonld_expander formatted = jsonld_expander.formatLdObject( self.load(protocolId, force=True), 'protocol', editor) for key in ['url', 'schema:url']: if key in formatted['protocol']: formatted['protocol'].pop(key) if prefLabel: for key in formatted['protocol']: if key.endswith('prefLabel') and isinstance( formatted['protocol'][key], list): formatted['protocol'][key][0]['@value'] = prefLabel formatted['protocol'].pop('_id') protocol = { 'protocol': { formatted['protocol']['@id']: { 'expanded': formatted['protocol'], 'ref2Document': { 'duplicateOf': protocolId } } }, 'activity': {}, 'screen': {} } activityId2Key = {} for activityKey in formatted['activities']: activity = formatted['activities'][activityKey] activityId = activity.pop('_id').split('/')[-1] for key in ['url', 'schema:url']: if key in activity: activity.pop(key) protocol['activity'][activityKey] = { 'parentKey': 'protocol', 'parentId': formatted['protocol']['@id'], 'expanded': activity, 'ref2Document': { 'duplicateOf': activityId } } activityId2Key[activityId] = activityKey itemId2ActivityId = {} items = list(Screen().find({'meta.protocolId': protocolId})) for item in items: itemId2ActivityId[str(item['_id'])] = str(item['meta'].get( 'activityId', None)) for itemKey in formatted['items']: item = formatted['items'][itemKey] itemId = item.pop('_id').split('/')[-1] for key in ['url', 'schema:url']: if key in item: item.pop(key) protocol['screen'][itemKey] = { 'parentKey': 'activity', 'parentId': activityId2Key[itemId2ActivityId[itemId]], 'expanded': item, 'ref2Document': { 'duplicateOf': itemId } } protocolId = jsonld_expander.createProtocolFromExpandedDocument( protocol, editor) return jsonld_expander.formatLdObject(self.load(protocolId, force=True), mesoPrefix='protocol', user=editor, refreshCache=True)
def postResponse(user, actURI, itemURI, appletObject, password="******"): """ post a response as a user inputs ------ user: user object actURI: activity uri itemURI: item URI appletObject: appletObject password (optional): defaults to password """ currentUser = authenticate(user, password) appletId = appletObject['_id'] expandedApplet = jsonld_expander.formatLdObject(appletObject, 'applet', currentUser) a = expandedApplet['activities'][jsonld_expander.reprolibPrefix(actURI)] activityId = a['_id'].split('/')[1] response = {} response[jsonld_expander.reprolibPrefix(itemURI)] = np.random.randint(2) metadata = { 'responses': response, 'subject': { '@id': currentUser.get('_id') } } applet = appletObject activity = ActivityModel().load(activityId, user=currentUser, level=AccessType.READ) if activity is None: activity = ActivityModel().getFromUrl(actURI, modelType='activity', user=currentUser)[0] metadata['applet'] = { "@id": applet.get('_id'), "name": AppletModel().preferredName(applet), "url": applet.get('url', applet.get('meta', {}).get('applet', {}).get('url')) } metadata['activity'] = { "@id": activity.get('_id'), "name": ActivityModel().preferredName(activity), "url": activity.get('url', activity.get('meta', {}).get('activity', {}).get('url')) } now = datetime.now(tzlocal.get_localzone()) appletName = metadata['applet']['name'] UserResponsesFolder = ResponseFolderModel().load(user=currentUser, reviewer=currentUser, force=True) UserAppletResponsesFolder = Folder().createFolder( parent=UserResponsesFolder, parentType='folder', name=appletName, reuseExisting=True, public=False) AppletSubjectResponsesFolder = Folder().createFolder( parent=UserAppletResponsesFolder, parentType='folder', name=str(currentUser['_id']), reuseExisting=True, public=False) resp = ResponseItemModel().createResponseItem( folder=AppletSubjectResponsesFolder, name=now.strftime("%Y-%m-%d-%H-%M-%S-%Z"), creator=currentUser, description="{} response on {} at {}".format( metadata['activity']['name'], now.strftime("%Y-%m-%d"), now.strftime("%H:%M:%S %Z")), reuseExisting=False) resp = ResponseItemModel().setMetadata(resp, metadata) assert resp['_id'], 'response is weird and does not have an id' assert 'activity' in resp['meta'].keys( ), 'response does not have an activity' assert 'applet' in resp['meta'].keys(), 'response does not have an applet' assert 'responses' in resp['meta'].keys( ), 'response does not have an response' return resp
def getActivityByURL(self, url): thisUser = self.getCurrentUser() return (jsonld_expander.formatLdObject( ActivityModel().importUrl(url, thisUser), 'activity', thisUser))
def getActivity(self, folder): return (jsonld_expander.formatLdObject(folder, 'activity'))