def deactivateApplet(self, folder): from girderformindlogger.models.profile import Profile applet = folder user = Applet().getCurrentUser() applet['meta']['applet']['deleted'] = True applet = AppletModel().setMetadata(applet, applet.get('meta'), user) if applet.get('meta', {}).get('applet', {}).get('deleted') == True: message = 'Successfully deactivated applet {} ({}).'.format( AppletModel().preferredName(applet), applet.get('_id')) users = list(Profile().find( { 'appletId': ObjectId(applet['_id']), 'deactivated': { '$ne': True } }, fields=['userId'])) Profile().deactivateProfile(applet['_id'], None) for user in users: if 'userId' in user: UserModel().removeApplet( UserModel().findOne({'_id': ObjectId(user['userId'])}), applet['_id']) else: message = 'Could not deactivate applet {} ({}).'.format( AppletModel().preferredName(applet), applet.get('_id')) Description().errorResponse(message, 403) return (message)
def _cacheProfileDisplay(self, profile, user, forceManager=False, forceReviewer=False): from girderformindlogger.models.applet import Applet profileDefinitions = self.cycleDefinitions( profile, showEmail=forceManager if forceManager else Applet().isCoordinator( profile['appletId'], user), showIDCode=forceReviewer if forceReviewer else Applet().isCoordinator(profile['appletId'], user)) if 'invitedBy' in profile: profileDefinitions['invitedBy'] = self.cycleDefinitions( profile['invitedBy'], showEmail=False) if forceManager and not forceReviewer: profile['cachedDisplay']['manager'] = profileDefinitions self.save(profile, validate=False) elif forceReviewer: profile['cachedDisplay']['reviewer'] = profileDefinitions self.save(profile, validate=False) print(profileDefinitions) return (profileDefinitions)
def addApplet(new_user, protocolUrl): """ adds an applet for the user, where the user becomes a manager for it. inputs ------ new_user: a user oject (from testCreateUser) protocolURL: String, a valid URL to an activity set. returns ------- applet response object """ currentUser = authenticate(new_user) # TODO: create an activity-set that JUST for testing. # make sure it has all the weird qualities that can break userAppletsToStart = AppletModel().getAppletsForUser('manager', currentUser, active=True) userApplets = userAppletsToStart.copy() # for now, lets do the mindlogger demo protocol = ProtocolModel().getFromUrl(protocolUrl, 'protocol', currentUser)[0] randomAS = np.random.randint(1000000) ar = AppletModel().createAppletFromUrl( name="testProtocol{}".format(randomAS), protocolUrl=protocolUrl, user=currentUser, sendEmail=False) while len(userApplets) == len(userAppletsToStart): nightyNight(sleepInterval) userApplets = AppletModel().getAppletsForUser('manager', currentUser, active=True) ar = jsonld_expander.loadCache(userApplets[-1]['cached']) assert jsonld_expander.reprolibCanonize( ar['protocol']['url'] ) == jsonld_expander.reprolibCanonize(protocolUrl), \ 'the URLS do not match! {} {}'.format( ar['protocol']['url'], protocolUrl ) assert ar['applet']['_id'], 'there is no ID!' assert getAppletById(new_user, ar) is not None, 'something wrong with getAppletById' return ar
def deactivateApplet(self, folder): applet = folder user = Applet().getCurrentUser() applet['meta']['applet']['deleted'] = True applet = AppletModel().setMetadata(applet, applet.get('meta'), user) if applet.get('meta', {}).get('applet', {}).get('deleted') == True: message = 'Successfully deactivated applet {} ({}).'.format( AppletModel().preferredName(applet), applet.get('_id')) else: message = 'Could not deactivate applet {} ({}).'.format( AppletModel().preferredName(applet), applet.get('_id')) Description().errorResponse(message, 403) return (message)
def coordinatorProfile(self, appletId, coordinator): from girderformindlogger.models.applet import Applet if isinstance(coordinator, dict) and "userId" not in coordinator: coordinator = self.createProfile(appletId, coordinator, "coordinator") return (self.cycleDefinitions(coordinator, showEmail=True) if Applet().isCoordinator(appletId, coordinator) else {})
def getSchedule(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." }) model = AppletModel() filterRequired = model._hasRole( applet['_id'], user, 'user') if not model.isCoordinator(applet['_id'], user) else False schedule = model.filterScheduleEvents( applet.get('meta', {}).get('applet', {}).get('schedule', {}), user, filterRequired) return schedule
def create(self, applet, user): """ Create an Assignment for a given Applet, returning an existing Assignment if one or more exists. :param applet: The ID of the Applet for which to find Assignments. :type applet: str :param user: User :type user: User :returns: New Assignments """ # validate Applet ID try: applet = Applet().load(id=applet, force=True) except: raise ValidationException( message='Invalid Applet ID', field='applet' ) assignmentsCollection = Collection().findOne({'name': 'Assignments'}) # for some reason below didn't work/help.. so I added Assignments manually. if not assignmentsCollection: Collection().createCollection('Assignments') try: assignment = Folder().createFolder( parent=assignmentsCollection, parentType='collection', name=Applet().preferredName(applet), creator=user, reuseExisting=True, public=False) except: assignmentsCollection = Folder().createFolder( parent=user, parentType='user', name='Assignments', creator=user, reuseExisting=True, public=False) assignment = Folder().createFolder( parent=assignmentsCollection, parentType='folder', name=Applet().preferredName(applet), creator=user, reuseExisting=True, public=False) return(assignment)
def updateProfile(self, profileId, user, profileUpdate): from copy import deepcopy profile = self.load(profileId, force=True) if str(user["_id"] == profile["userId"]): update = deepcopy(profile.get("userDefined", {})) update.update(profileUpdate) profile["userDefined"] = update elif Applet().isCoordinator(profile["appletId"], user): update = deepcopy(profile.get("coordinatorDefined", {})) update.update(profileUpdate) profile["coordinatorDefined"] = update else: raise AccessException( "You do not have adequate permissions to update this profile.") return self.save(profile, validate=False)
def accessToDuplicatedApplets(self, invitation, user, userEmail=''): from girderformindlogger.models.applet import Applet from girderformindlogger.models.user import User as UserModel duplicates = list(Applet().find( {'duplicateOf': ObjectId(invitation['appletId'])})) if 'inviterId' not in invitation: return for duplicate in duplicates: newInvitation = self.createInvitationForSpecifiedUser( duplicate, UserModel().load(invitation['inviterId'], force=True), invitation.get('role', 'user'), user, invitation.get('firstName', ''), invitation.get('lastName', ''), invitation.get('MRN', ''), userEmail) self.acceptInvitation(self.load(newInvitation['_id'], force=True), user, userEmail)
def findAssignments(self, applet): """ Find all Assignments for a given Applet. :param applet: The ID of the Applet for which to find Assignments. :type applet: str :returns: list of Assignments """ # validate Applet ID try: Applet().load(id=applet, force=True) except: raise ValidationException( message='Invalid Applet ID', field='applet' ) allAssignments = [ { '_id': a['_id'], '_modelType': 'collection' } for a in Collection().find({'name': 'Assignments'}) ] + [ { '_id': a['_id'], '_modelType': 'folder' } for a in Folder().find({'name': 'Assignments'}) ] foundAssignments = Folder().find( { '$and': [ {'$or': [ {'meta.applet.@id': str(applet)}, {'meta.applet.url': str(applet)} ]}, {'$or': [ {'parentId': parent['_id']} for parent in allAssignments ]} ] } ) return(list(foundAssignments))
def acceptInvitation(self, invitation, user): from girderformindlogger.models.applet import Applet from girderformindlogger.models.ID_code import IDCode from girderformindlogger.models.profile import Profile applet = Applet().load(invitation['appletId'], force=True) profiles = None if 'idCode' in invitation: profiles = IDCode().findProfile(invitation['idCode']) if profiles and len(profiles): profile = [ pro for pro in profiles if str(pro.get('userId')) == str(user['_id']) ] profile = profile[0] if len(profile) else None else: profile = None if profiles == None or profile == None or not len(profile): profile = Profile().createProfile(applet, user, role=invitation.get( 'role', 'user')) IDCode().createIdCode(profile, invitation.get('idCode')) if 'schema:knows' in invitation: if 'schema:knows' not in profile: profile['schema:knows'] = invitation['schema:knows'] else: for k in invitation['schema:knows']: if k in profile['schema:knows']: profile['schema:knows'][k].extend([ r for r in invitation['schema:knows'][k] if r not in profile['schema:knows'][k] ]) else: profile['schema:knows'][k] = invitation[ 'schema:knows'][k] Profile().save(profile, validate=False) self.remove(invitation) return (Profile().displayProfileFields( Profile().load(profile['_id'], force=True), user))
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 removeUser(self, group, user, delete=False): """ Remove the user from the group. If the user is not in the group but has an outstanding invitation to the group, the invitation will be revoked. If the user has requested an invitation, calling this will deny that request, thereby deleting it. """ from girderformindlogger.models.applet import Applet from girderformindlogger.models.folder import Folder from girderformindlogger.models.item import Item from girderformindlogger.models.user import User # Remove group membership for this user. if delete: # Get applets for group and delete data for applets [ Folder().remove( Folder().load(rf, force=True), progress=None # TODO: enable progress response ) for rf in list( set(responseFolder['parentId'] for responseFolder in [ Folder().load( folder, fields=['_id', 'parentId', 'baseParentId'], force=True) for folder in list( set( item.get('folderId') for item in list(Item().find(query={ 'meta.applet.@id': { '$in': [ applet['_id'] for applet in Applet().getAppletsForGroup( 'user', group.get( '_id', group), False) ] }, 'baseParentType': 'user', 'baseParentId': user['_id'] }, fields=[ 'folderId' ])))) ] if responseFolder['baseParentId'] == user['_id'])) ] if 'groups' in user and group['_id'] in user['groups']: if not delete: # if not deleting, save as a former group if 'formerGroups' in user and isinstance( user['formerGroups'], list): user['formerGroups'].append(group['_id']) else: user['formerGroups'] = [group['_id']] user['groups'].remove(group['_id']) # Remove outstanding requests from this user self._deleteRequest(group, user) # Save as declined invitation user['declinedInvites'] = list( filter(lambda inv: inv['groupId'] == group['_id'], user.get('groupInvites', []))) # Remove any outstanding invitations for this group user['groupInvites'] = list( filter(lambda inv: not inv['groupId'] == group['_id'], user.get('groupInvites', []))) user = User().save(user, validate=False) # Remove all group access for this user on this group. self.setUserAccess(group, user, level=None, save=True) return (group)
def htmlInvitation(self, invitation, invitee=None, fullDoc=False, includeLink=True): """ Returns an HTML document rendering the invitation. :param invitation: Invitation to render :type invitation: dict :param invitee: Invited user :type invitee: dict or None :returns: html document """ from girderformindlogger.models.applet import Applet from girderformindlogger.models.profile import Profile from girderformindlogger.models.protocol import Protocol from girderformindlogger.models.token import Token from girderformindlogger.models.user import User from girderformindlogger.exceptions import GirderException from girderformindlogger.api.rest import getApiUrl from girderformindlogger.utility import context as contextUtil, \ mail_utils web_url = os.getenv('WEB_URI') or 'localhost:8082' accept = ("To accept or decline, visit <a href=\"{u}\">{u}</a>".format( u=f"https://{web_url}/#/invitation/{str(invitation['_id'])}") ) if includeLink else "" applet = Applet().load(ObjectId(invitation['appletId']), force=True) appletName = applet['meta']['applet'].get( 'displayName', applet.get('displayName', 'new applet')) try: skin = contextUtil.getSkin() except: skin = {} instanceName = skin.get("name", "MindLogger") role = invitation.get("role", "user") try: coordinator = Profile().coordinatorProfile(applet['_id'], invitation["invitedBy"]) except: coordinator = None displayProfile = Profile().displayProfileFields(invitation, invitee) description = applet.get('meta', {}).get('applet', {}).get( "schema:description", Protocol().load( applet['meta']['protocol']['_id'].split('protocol/')[-1], force=True).get('meta', {}).get('protocol') if 'protocol' in applet.get('meta', {}) else {}).get("schema:description", "") managers = mail_utils.htmlUserList(Applet().listUsers(applet, 'manager', force=True)) coordinators = mail_utils.htmlUserList(Applet().listUsers( applet, 'coordinator', force=True)) reviewers = mail_utils.htmlUserList(Applet().listUsers(applet, 'reviewer', force=True)) body = mail_utils.renderTemplate( f'welcome{"Owner" if role == "owner" else ""}.{invitation.get("lang", "en")}.mako', { 'accept': accept, 'appletName': appletName, 'byCoordinator': "by {} ({}) ".format( coordinator.get("displayName", "an anonymous entity"), "<a href=\"mailto:{email}\">{email}</a>".format( email=coordinator["email"]) if "email" in coordinator and coordinator["email"] is not None else "email not available") if isinstance( coordinator, dict) else "", 'coordinators': "{}".format(coordinators if len(coordinators) else "<ul><li>None</li></ul>"), 'instanceName': " on {}".format(instanceName) if instanceName is not None and len(instanceName) else "", 'managers': "{}".format( managers if len(managers) else "<ul><li>None</li></ul>"), 'reviewers': "{}".format( reviewers if len(reviewers) else "<ul><li>None</li></ul>"), 'role': "an editor" if role == "editor" else "a {}".format(role), 'url': f'https://{web_url}/#/invitation/{str(invitation["_id"])}' }) return (body if not fullDoc else """ <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Invitation to {appletName} on {instanceName}</title> </head> <body> {body} </body> </html> """.format(appletName=appletName, instanceName=instanceName, body=body).strip())
def generateMissing(self, applet): """ Helper function to generate profiles for users that predate this class. To be threaded unless no users with profiles exist. :param applet: Applet to get users for. :type applet: dict :returns: list of dicts """ from girderformindlogger.models.applet import Applet from girderformindlogger.models.user import User as UserModel # get groups for applet appletGroups = Applet().getAppletGroups(applet) userList = { role: { groupId: { 'active': list(UserModel().find( query={"groups": { "$in": [ObjectId(groupId)] }}, fields=['_id'])) } for groupId in appletGroups[role].keys() } for role in appletGroups.keys() } # restructure dictionary & return userList = { str(ulu["user"]["_id"]): { k: v for k, v in { "displayName": ulu["user"].get("coordinatorDefined", {}).get( "displayName", ulu["user"].get("userDefined", {}).get( "displayName", ulu["user"].get("displayName"))), "groups": ulu.get("groups") }.items() if v is not None } for ulu in [{ "user": self.createProfile( applet, UserModel().load(user, AccessType.READ, force=True)), "groups": [{ "_id": groupId, "name": appletGroups[role][groupId], "status": status, "role": role } for role in userList for groupId in userList[role] for status in userList[role][groupId]] } for user in set([ ui.get('_id') for u in (userList[role][groupId][status] for role in userList for groupId in userList[role] for status in userList[role][groupId]) for ui in u ])] } return (userList)
def createProfile(self, applet, user, role="user"): """ Create a new profile to store information specific to a given (applet ∩ user) :param applet: The applet for which this profile exists :type applet: dict :param user: The user for which this profile exists :type user: dict :returns: The profile document that was created. """ from girderformindlogger.models.applet import Applet from girderformindlogger.models.group import Group if not isinstance(applet, dict): applet = Applet().load(applet, force=True) user = self._canonicalUser(applet["_id"], user) returnFields = ["_id", "appletId", "coordinatorDefined", "userDefined"] existing = self.findOne( { 'appletId': applet['_id'], 'userId': user['_id'], 'profile': True }, fields=[*returnFields, "deactivated"]) if applet['_id'] not in [ a.get('_id') for a in Applet().getAppletsForUser(role, user) ]: appletGroups = Applet().getAppletGroups(applet) roles = ['user', 'editor', 'reviewer', 'coordinator', 'manager' ] if role == 'manager' else [role] if 'user' not in roles: roles.append('user') for role in roles: groups = appletGroups.get(role) if bool(groups): group = Group().load(ObjectId(list(groups.keys())[0]), force=True) if group['_id'] not in user.get('groups', []): Group().inviteUser(group, user, level=AccessType.READ) Group().joinGroup(group, user) else: raise ValidationException( "User does not have role \"{}\" in this \"{}\" applet " "({})".format(role, Applet().preferredName(applet), str(applet['_id']))) if existing and not existing.get('deactivated', False): if "deactivated" in existing: existing.pop("deactivated") return existing now = datetime.datetime.utcnow() managers = list( self.find(query={ 'appletId': applet['_id'], 'roles': 'manager' }, fields=['_id'])) profile = { k: v for k, v in { 'appletId': ObjectId(applet['_id']), 'userId': ObjectId(user['_id']), 'profile': True, 'badge': 0, 'created': now, 'updated': now, 'deviceId': user['deviceId'], 'timezone': user['timezone'], 'individual_events': 0, 'completed_activities': [{ 'activity_id': activity_id, 'completed_time': None } for activity_id in applet.get('meta', {}).get( 'protocol', {}).get('activities', [])], 'accountId': applet.get('accountId', None), 'size': 0, 'coordinatorDefined': {}, 'userDefined': { 'displayName': user.get('displayName', user.get('firstName')), 'email': user.get('email' ) if not user.get('email_encrypted', None) else '' }, 'reviewers': [manager['_id'] for manager in managers] }.items() if v is not None } if existing: profile['_id'] = existing['_id'] self.setPublic(profile, False, save=False) # Save the profile. self.save(profile, validate=False) return ({k: v for k, v in profile.items() if k in returnFields})
def hasAccess(self, doc, user=None, level=AccessType.READ): """ This overrides the default AccessControlledModel behavior for checking access to perform an optimized subset of the access control behavior. :param doc: The group to check permission on. :type doc: dict :param user: The user to check against. :type user: dict :param level: The access level. :type level: AccessType :returns: Whether the access is granted. """ import itertools from girderformindlogger.models.applet import Applet from girderformindlogger.models.user import User from girderformindlogger.constants import USER_ROLES if user is None: # Short-circuit the case of anonymous users return (level == AccessType.READ and doc.get('public', False) is True) elif user.get('_id') in [ u.get('_id') for u in list(User().find({ 'groups': { '$in': list( set([ g.get('id') for g in [ *list( itertools.chain.from_iterable([ mgr.get('roles', {}).get( 'manager', {}).get( 'groups', []) for mgr in [ *list( itertools.chain. from_iterable([ list(Applet().find({ 'roles.{}.groups.id'.format(role): doc.get('_id') })) for role in list( USER_ROLES.keys()) ])) ] ])) ] ])) } })) ]: # Short-circuit the case of admins and managers return (True) elif level == AccessType.READ: # Short-circuit in the case of members without write access to the # group if not self.getAccessLevel(doc, user) > 1: return (False) # For read access, just check user document for membership or public return (doc.get('public', False) is True or doc['_id'] in user.get('groups', []) or doc['_id'] in [i['groupId'] for i in user.get('groupInvites', [])]) else: # Check the actual permissions document for >=WRITE access return (self._hasUserAccess( doc.get('access', {}).get('users', []), user['_id'], level))
def createProfile(self, applet, user, role="user"): """ Create a new profile to store information specific to a given (applet ∩ user) :param applet: The applet for which this profile exists :type applet: dict :param user: The user for which this profile exists :type user: dict :returns: The profile document that was created. """ from girderformindlogger.models.applet import Applet from girderformindlogger.models.group import Group if not isinstance(applet, dict): applet = Applet().load(applet, force=True) user = self._canonicalUser(applet["_id"], user) returnFields = ["_id", "appletId", "coordinatorDefined", "userDefined"] existing = self.findOne( { 'appletId': applet['_id'], 'userId': user['_id'], 'profile': True }, fields=returnFields) if existing: return existing if applet['_id'] not in [ a.get('_id') for a in Applet().getAppletsForUser(role, user) ]: groups = Applet().getAppletGroups(applet).get(role) if bool(groups): group = Group().load(ObjectId(list(groups.keys())[0]), force=True) Group().inviteUser(group, user, level=AccessType.READ) Group().joinGroup(group, user) else: raise ValidationException( "User does not have role \"{}\" in this \"{}\" applet " "({})".format(role, Applet().preferredName(applet), str(applet['_id']))) now = datetime.datetime.utcnow() profile = { k: v for k, v in { 'appletId': ObjectId(applet['_id']), 'userId': ObjectId(user['_id']), 'profile': True, 'created': now, 'updated': now, 'size': 0, 'coordinatorDefined': {}, 'userDefined': { 'displayName': user.get('displayName', user.get( 'firstName')), 'email': user.get('email') } }.items() if v is not None } self.setPublic(profile, False, save=False) # Save the profile. self.save(profile, validate=False) return ({k: v for k, v in profile.items() if k in returnFields})
def createInvitation( self, applet, coordinator, role="user", profile=None, idCode=None ): """ Create a new invitation to store information specific to a given (applet ∩ (ID code ∪ profile)) :param applet: The applet for which this invitation exists :type parent: dict :param coordinator: user who is doing the inviting :type coordinator: dict :param profile: Profile to apply to (applet ∩ user) if the invitation is accepted :type profile: dict or none :param idCode: ID code to apply to (applet ∩ user) if invitation is accepted :type idCode: string or None :returns: The invitation document that was created. """ from girderformindlogger.models.applet import Applet from girderformindlogger.models.profile import Profile if not(Applet().isCoordinator(applet['_id'], coordinator)): raise AccessException( 'You do not have adequate permissions to invite users to this ' 'applet ({}).'.format(Applet().preferredName(applet)) ) codified = (isinstance(idCode, str) and len(idCode)) existing = self.findOne({ 'appletId': applet['_id'], 'idCode': idCode }) if codified else None if existing: return existing now = datetime.datetime.utcnow() invitation = { 'appletId': applet['_id'], 'created': now, 'updated': now, 'role': role, 'size': 0, 'invitedBy': Profile().coordinatorProfile( applet['_id'], coordinator ) } if codified: invitation["idCode"] = idCode if isinstance(profile, dict): invitation["coordinatorDefined"] = profile self.setPublic(invitation, False, save=False) # Now validate and save the profile. return ({ k: v for k, v in self.save(invitation, validate=False).items() if ( k!="idCode" and v is not None ) })
def htmlInvitation( self, invitation, invitee=None, fullDoc=False, includeLink=True ): """ Returns an HTML document rendering the invitation. :param invitation: Invitation to render :type invitation: dict :param invitee: Invited user :type invitee: dict or None :returns: html document """ from girderformindlogger.models.applet import Applet from girderformindlogger.models.profile import Profile from girderformindlogger.models.protocol import Protocol from girderformindlogger.models.token import Token from girderformindlogger.models.user import User from girderformindlogger.exceptions import GirderException from girderformindlogger.api.rest import getApiUrl from girderformindlogger.utility import context as contextUtil, \ mail_utils accept = ( "To accept or decline, visit <a href=\"{u}\">{u}</a>".format( u="https://web.mindlogger.org/#/invitation/{}".format(str( invitation['_id'] )) ) ) if includeLink else "" applet = Applet().load(ObjectId(invitation['appletId']), force=True) appletName = applet.get( 'displayName', 'a new applet' ) try: skin = contextUtil.getSkin() except: skin = {} instanceName = skin.get("name", "MindLogger") role = invitation.get("role", "user") try: coordinator = Profile().coordinatorProfile( applet['_id'], invitation["invitedBy"] ) except: coordinator = None displayProfile = Profile().displayProfileFields(invitation, invitee) description = applet.get('meta', {}).get( 'applet', {} ).get( "schema:desciription", Protocol().load( applet['meta']['protocol']['_id'].split('protocol/')[-1], force=True ).get('meta', {}).get('protocol') if 'protocol' in applet.get( 'meta', {} ) else {} ).get("schema:description", "") managers = mail_utils.htmlUserList( Applet().listUsers(applet, 'manager', force=True) ) coordinators = mail_utils.htmlUserList( Applet().listUsers(applet, 'coordinator', force=True) ) reviewers = mail_utils.htmlUserList( Applet().listUsers(applet, 'reviewer', force=True) ) body = """ {greeting}ou were invited {byCoordinator}to be {role} of <b>{appletName}</b>{instanceName}. <br/> Below are the users that have access to your data: {reviewers} {managers} {coordinators} <br/> {accept} """.format( accept=accept, appletName=appletName, byCoordinator="by {} ({}) ".format( coordinator.get("displayName", "an anonymous entity"), "<a href=\"mailto:{email}\">{email}</a>".format( email=coordinator["email"] ) if "email" in coordinator and coordinator["email"] is not None else "email not available" ) if isinstance(coordinator, dict) else "", coordinators="<h3>Users who can change this applet's settings, " "but who cannot change who can see your data: </h3>{}" "".format( coordinators if len( coordinators ) else "<ul><li>None</li></ul>" ), greeting="Welcome to MindLogger! Y", instanceName=" on {}".format( instanceName ) if instanceName is not None and len(instanceName) else "", managers="<h3>Users who can change this applet's settings, " " including who can access your data: </h3>{}" "".format( managers if len(managers) else "<ul><li>None</li></ul>" ), reviewers="<h3>Users who can see your data for this " "applet: </h3>{}" "".format( reviewers if len(reviewers) else "<ul><li>None</li></ul>" ), role="an editor" if role=="editor" else "a {}".format(role) ).strip() return(body if not fullDoc else """ <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Invitation to {appletName} on {instanceName}</title> </head> <body> {body} </body> </html> """.format( appletName=appletName, instanceName=instanceName, body=body ).strip())
def acceptInvitation(self, invitation, user, userEmail = ''): # we need to save coordinator/manager's email as plain text from girderformindlogger.models.applet import Applet from girderformindlogger.models.ID_code import IDCode from girderformindlogger.models.profile import Profile from girderformindlogger.utility import mail_utils applet = Applet().load(invitation['appletId'], force=True) profiles = None if 'idCode' in invitation: profiles = IDCode().findProfile(invitation['idCode']) if profiles and len(profiles): profile = [ pro for pro in profiles if str( pro.get('userId') )==str(user['_id']) ] profile = profile[0] if len(profile) else None else: profile = None Profile().removeWithQuery({ '_id': ObjectId(invitation['_id']) }) if profile==None or not len(profile): profile = Profile().createProfile( applet, user, role=invitation.get('role', 'user') ) IDCode().createIdCode(profile, invitation.get('idCode')) if 'schema:knows' in invitation: if 'schema:knows' not in profile: profile['schema:knows'] = invitation['schema:knows'] else: for k in invitation['schema:knows']: if k in profile['schema:knows']: profile['schema:knows'][k].extend([ r for r in invitation['schema:knows'][ k ] if r not in profile['schema:knows'][k] ]) else: profile['schema:knows'][k] = invitation['schema:knows'][ k ] # append role value profile = Profile().load(profile['_id'], force=True) profile['roles'] = profile.get('roles', []) invited_role = invitation.get('role','user') new_roles = [] # manager has get all roles by default for role in USER_ROLES.keys(): if role not in profile['roles']: if invited_role == 'manager' or invited_role == role or role == 'user': new_roles.append(role) profile['roles'].append(role) profile['firstName'] = invitation.get('firstName', '') profile['lastName'] = invitation.get('lastName', '') profile['MRN'] = invitation.get('MRN', '') Profile().save(profile, validate=False) from girderformindlogger.models.user import User as UserModel if not mail_utils.validateEmailAddress(userEmail): raise ValidationException( 'Invalid email address.', 'email' ) if invited_role != 'user' and user.get('email_encrypted', False): if UserModel().hash(userEmail) != user['email']: raise ValidationException( 'Invalid email address.', 'email' ) user['email'] = userEmail user['email_encrypted'] = False UserModel().save(user) UserModel().appendApplet(user, applet['_id'], new_roles) self.remove(invitation) return(Profile().displayProfileFields( Profile().load(profile['_id'], force=True), user ))