def createProtoUser(self, email):
        """
        Create a new protoUser with the given information.

        :returns: The user document that was created.
        """
        from girderformindlogger.models.group import Group
        from girderformindlogger.models.setting import Setting

        encryptedEmail = hashlib.sha224(email.encode('utf-8')).hexdigest()
        protoUser = self.findOne(query={"email": encryptedEmail}, force=True)
        if protoUser:
            protoUser['groupInvites'] = [{
                "groupId": gi.get('_id'),
                "level": 0
            } for gi in list(Group().find(query={"queue": encryptedEmail}))]
            self.save(protoUser)
            return (protoUser)
        protoUser = {
            'email':
            encryptedEmail,
            'created':
            datetime.datetime.utcnow(),
            'groupInvites': [{
                "groupId": gi.get('_id'),
                "level": 0
            } for gi in list(Group().find(query={"queue": encryptedEmail}))],
            'email_encrypted':
            True
        }
        protoUser = self.save(protoUser)
        self._sendCreateAccountEmail(protoUser, email)
        return (protoUser)
def removeApplet(user, appletObject):
    """
    remove an applet from a user without deleting their data

    inputs
    ------
    user: admin user object
    appletObject: appletObject
    """
    currentUser = authenticate(user)
    groupId = appletObject['roles']['user']['groups'][0]['id']
    Group().removeUser(Group().load(id=groupId, force=True), user=currentUser)
def deleteApplet(user, appletObject):
    """
    remove an applet from a user and also delete the user's data.

    inputs
    ------
    user: admin user object
    appletObject: appletObject
    """
    currentUser = authenticate(user)
    groupId = appletObject['roles']['user']['groups'][0]['id']
    Group().removeUser(Group().load(id=groupId, force=True),
                       user=currentUser,
                       delete=True)
def makeAReviewer(user, appletObject, userB):
    """
    give a user reviewer priveleges

    inputs
    ------
    user: admin user object
    appletObject: appletObject
    userB: user to make a reviewer
    """
    currentUser = authenticate(user)
    reviewerGroupId = appletObject['roles']['reviewer']['groups'][0]['id']
    group = Group().load(id=ObjectId(reviewerGroupId), force=True)
    return Group().addUser(group, currentUser, level=AccessType.READ)
def acceptAppletInvite(user, appletObject, role):
    """
    accept an applet invite

    inputs
    ------
    user: admin user object
    appletObject: appletObject
    """
    groupId = checkForInvite(user, appletObject)
    resp = Group().joinGroup(Group().load(groupId, force=True), user)
    assert role in resp[
        'lowerName'], "group name does not include \"{}\"".format(role)
    return 1
Exemple #6
0
def userCreated(event):
    """
    Check auto join rules when a new user is created. If a match is found,
    add the user to the group with the specified access level.
    """
    user = event.info
    email = user.get('email').lower()
    rules = Setting().get(PluginSettings.AUTOJOIN)
    for rule in rules:
        if rule['pattern'].lower() not in email:
            continue
        group = Group().load(rule['groupId'], force=True)
        if group:
            Group().addUser(group, user, rule['level'])
Exemple #7
0
    def getCollectionCreationPolicyAccess(self):
        cpp = Setting().get(SettingKey.COLLECTION_CREATE_POLICY)

        acList = {
            'users': [{
                'id': x
            } for x in cpp.get('users', [])],
            'groups': [{
                'id': x
            } for x in cpp.get('groups', [])]
        }

        for user in acList['users'][:]:
            userDoc = User().load(user['id'],
                                  force=True,
                                  fields=['firstName', 'login', 'email'])
            if userDoc is None:
                acList['users'].remove(user)
            else:
                user['login'] = userDoc['login']
                user['name'] = userDoc['firstName']
                user['email'] = userDoc['email']

        for grp in acList['groups'][:]:
            grpDoc = Group().load(grp['id'],
                                  force=True,
                                  fields=['name', 'description'])
            if grpDoc is None:
                acList['groups'].remove(grp)
            else:
                grp['name'] = grpDoc['name']
                grp['description'] = grpDoc['description']

        return acList
def inviteUserToApplet(user, appletObject, userB):
    """
    invite a user to an applet

    inputs
    ------
    user: a user object
    appletObject:
    userB: a user object of a user you want to invite. If they aren't
    defined yet, it should be a dict(email="emailaddress")
    """

    groupId = appletObject['roles']['user']['groups'][0]['id']
    currentUser = authenticate(user)
    group = Group().load(id=ObjectId(groupId), force=True)

    invitation = Invitation().createInvitation(appletObject,
                                               currentUser,
                                               role="user",
                                               profile=Profile().createProfile(
                                                   appletObject, userB),
                                               idCode=None)
    return Group().inviteUser(group, userB, level=AccessType.READ)
Exemple #9
0
    def _validateCollectionCreatePolicy(doc):
        from girderformindlogger.models.group import Group
        from girderformindlogger.models.user import User

        value = doc['value']

        if not isinstance(value, dict):
            raise ValidationException(
                'Collection creation policy must be a JSON object.', 'value')

        for i, groupId in enumerate(value.get('groups', ())):
            Group().load(groupId, force=True, exc=True)
            value['groups'][i] = ObjectId(value['groups'][i])

        for i, userId in enumerate(value.get('users', ())):
            User().load(userId, force=True, exc=True)
            value['users'][i] = ObjectId(value['users'][i])

        value['open'] = value.get('open', False)
Exemple #10
0
    def __init__(self):
        super(Group, self).__init__()
        self.resourceName = 'group'
        self._model = GroupModel()

        self.route('DELETE', (':id',), self.deleteGroup)
        self.route('DELETE', (':id', 'member'), self.removeFromGroup)
        self.route('DELETE', (':id', 'moderator'), self.demote)
        self.route('DELETE', (':id', 'admin'), self.demote)
        self.route('GET', (), self.find)
        self.route('GET', ('open',), self.getOpenGroups)
        self.route('GET', (':id',), self.getGroup)
        self.route('GET', (':id', 'access'), self.getGroupAccess)
        self.route('GET', (':id', 'invitation'), self.getGroupInvitations)
        self.route('GET', (':id', 'member'), self.listMembers)
        self.route('POST', (), self.createGroup)
        self.route('POST', (':id', 'invitation'), self.inviteToGroup)
        self.route('POST', (':id', 'member'), self.joinGroup)
        self.route('POST', (':id', 'moderator'), self.promoteToModerator)
        self.route('POST', (':id', 'admin'), self.promoteToAdmin)
        self.route('PUT', (':id',), self.updateGroup)
        self.route('PUT', (':id', 'access'), self.updateGroupAccess)
Exemple #11
0
    def remove(self, user, progress=None, **kwargs):
        """
        Delete a user, and all references to it in the database.

        :param user: The user document to delete.
        :type user: dict
        :param progress: A progress context to record progress on.
        :type progress: girderformindlogger.utility.progress.ProgressContext or None.
        """
        from girderformindlogger.models.folder import Folder
        from girderformindlogger.models.group import Group
        from girderformindlogger.models.token import Token

        # Delete all authentication tokens owned by this user
        Token().removeWithQuery({'userId': user['_id']})

        # Delete all pending group invites for this user
        Group().update({'requests': user['_id']},
                       {'$pull': {
                           'requests': user['_id']
                       }})

        # Delete all of the folders under this user
        folderModel = Folder()
        folders = folderModel.find({
            'parentId': user['_id'],
            'parentCollection': 'user'
        })
        for folder in folders:
            folderModel.remove(folder, progress=progress, **kwargs)

        # Finally, delete the user document itself
        AccessControlledModel.remove(self, user)
        if progress:
            progress.update(increment=1,
                            message='Deleted user ' + user['login'])
Exemple #12
0
class Group(Resource):
    """API Endpoint for groups."""

    def __init__(self):
        super(Group, self).__init__()
        self.resourceName = 'group'
        self._model = GroupModel()

        self.route('DELETE', (':id',), self.deleteGroup)
        self.route('DELETE', (':id', 'member'), self.removeFromGroup)
        self.route('DELETE', (':id', 'moderator'), self.demote)
        self.route('DELETE', (':id', 'admin'), self.demote)
        self.route('GET', (), self.find)
        self.route('GET', ('open',), self.getOpenGroups)
        self.route('GET', (':id',), self.getGroup)
        self.route('GET', (':id', 'access'), self.getGroupAccess)
        self.route('GET', (':id', 'invitation'), self.getGroupInvitations)
        self.route('GET', (':id', 'member'), self.listMembers)
        self.route('POST', (), self.createGroup)
        self.route('POST', (':id', 'invitation'), self.inviteToGroup)
        self.route('POST', (':id', 'member'), self.joinGroup)
        self.route('POST', (':id', 'moderator'), self.promoteToModerator)
        self.route('POST', (':id', 'admin'), self.promoteToAdmin)
        self.route('PUT', (':id',), self.updateGroup)
        self.route('PUT', (':id', 'access'), self.updateGroupAccess)

    @access.public
    @filtermodel(model=GroupModel)
    @autoDescribeRoute(
        Description('Search for groups or list all groups.')
        .param('text', 'Pass this to perform a full-text search for groups.', required=False)
        .param('exact', 'If true, only return exact name matches. This is '
               'case sensitive.', required=False, dataType='boolean', default=False)
        .pagingParams(defaultSort='name')
        .errorResponse()
    )
    def find(self, text, exact, limit, offset, sort):
        user = self.getCurrentUser()
        if text is not None:
            if exact:
                groupList = self._model.find(
                    {'name': text}, offset=offset, limit=limit, sort=sort)
            else:
                groupList = self._model.textSearch(
                    text, user=user, offset=offset, limit=limit, sort=sort)
        else:
            groupList = self._model.list(
                user=user, offset=offset, limit=limit, sort=sort)
        return groupList

    @access.public
    @filtermodel(model=GroupModel)
    @autoDescribeRoute(
        Description('List all groups with open registration.')
        .pagingParams(defaultSort='name')
        .errorResponse()
    )
    def getOpenGroups(self, limit, offset, sort):
        groupList = self._model.find(
            query={'openRegistration': True},
            limit=limit,
            offset=offset,
            sort=sort
        )
        return groupList

    @access.user
    @filtermodel(model=GroupModel)
    @autoDescribeRoute(
        Description('Create a new group.')
        .responseClass('Group')
        .notes('Must be logged in.')
        .param('name', 'Unique name for the group.', strip=True)
        .param('description', 'Description of the group.', required=False,
               default='', strip=True)
        .param(
            'openRegistration',
            'Whether users can join without being invited.',
            required=False,
            dataType='boolean',
            default=False
        )
        .param('public', 'Whether the group should be publicly visible.',
               required=False, dataType='boolean', default=False)
        .errorResponse()
        .errorResponse('Write access was denied on the parent', 403)
    )
    def createGroup(self, name, description, openRegistration, public):
        return(self._model.createGroup(
            name=name,
            creator=self.getCurrentUser(),
            description=description,
            openRegistration=openRegistration,
            public=public
        ))

    @access.public
    @filtermodel(model=GroupModel)
    @autoDescribeRoute(
        Description('Get a group by ID.')
        .responseClass('Group')
        .modelParam('id', model=GroupModel, level=AccessType.READ)
        .errorResponse('ID was invalid.')
        .errorResponse('Read access was denied for the group.', 403)
    )
    def getGroup(self, group):
        # Add in the current setting for adding to groups
        group['_addToGroupPolicy'] = Setting().get(SettingKey.ADD_TO_GROUP_POLICY)
        return group

    @access.public
    @filtermodel(model=GroupModel, addFields={'access', 'requests'})
    @autoDescribeRoute(
        Description('Get the access control list for a group.')
        .responseClass('Group')
        .modelParam('id', model=GroupModel, level=AccessType.READ)
        .errorResponse('ID was invalid.')
        .errorResponse('Read access was denied for the group.', 403)
    )
    def getGroupAccess(self, group):
        groupModel = self._model
        group['access'] = groupModel.getFullAccessList(group)
        group['requests'] = list(groupModel.getFullRequestList(group))
        return group

    @access.user
    @filtermodel(model=GroupModel, addFields={'access'})
    @autoDescribeRoute(
        Description('Update the access control list for a group.')
        .modelParam('id', model=GroupModel, level=AccessType.WRITE)
        .jsonParam('access', 'The JSON-encoded access control list.', requireObject=True)
        .errorResponse('ID was invalid.')
        .errorResponse('Admin access was denied for the user.', 403)
    )
    def updateGroupAccess(self, group, access):
        return self._model.setAccessList(
            group, access, save=True)

    @access.public
    @filtermodel(model=User)
    @autoDescribeRoute(
        Description('Show outstanding invitations for a group.')
        .responseClass('Group')
        .modelParam('id', model=GroupModel, level=AccessType.READ)
        .pagingParams(defaultSort='firstName') # 🚧 replace with customID once customID defined
        .errorResponse()
        .errorResponse('Read access was denied for the group.', 403)
    )
    def getGroupInvitations(self, group, limit, offset, sort):
        return self._model.getInvites(group, limit, offset, sort)

    @access.user
    @filtermodel(model=GroupModel)
    @autoDescribeRoute(
        Description('Update a group by ID.')
        .modelParam('id', model=GroupModel, level=AccessType.WRITE)
        .param('name', 'The name to set on the group.', required=False, strip=True)
        .param('description', 'Description for the group.', required=False, strip=True)
        .param(
            'openRegistration',
            'Whether users can join without being invited.',
            required=False,
            dataType='boolean'
        )
        .param('public', 'Whether the group should be publicly visible', dataType='boolean',
               required=False)
        .param('addAllowed', 'Can admins or moderators directly add members '
               'to this group?  Only system administrators are allowed to '
               'set this field', required=False,
               enum=['default', 'no', 'yesmod', 'yesadmin'])
        .errorResponse()
        .errorResponse('Write access was denied for the group.', 403)
    )
    def updateGroup(
        self,
        group,
        name,
        description,
        openRegistration,
        public,
        addAllowed
    ):
        if public is not None:
            self._model.setPublic(group, public)

        if openRegistration is not None:
            group['openRegistration'] = openRegistration
        if name is not None:
            group['name'] = name
        if description is not None:
            group['description'] = description
        if addAllowed is not None:
            self.requireAdmin(self.getCurrentUser())
            group['addAllowed'] = addAllowed

        return(self._model.updateGroup(group))

    @access.user
    @filtermodel(model=GroupModel, addFields={'access', 'requests'})
    @autoDescribeRoute(
        Description('Request to join a group, or accept an invitation to join.')
        .responseClass('Group')
        .modelParam('id', model=GroupModel, force=True)
        .errorResponse('ID was invalid.')
        .errorResponse('You were not invited to this group, or do not have '
                       'read access to it.', 403) # TODO: Update permissions error handling
    )
    def joinGroup(self, group):
        groupModel = self._model
        group = groupModel.joinGroup(group, self.getCurrentUser())
        group['access'] = groupModel.getFullAccessList(group)
        group['requests'] = list(groupModel.getFullRequestList(group))
        return({'_id': group['_id'], 'name': group['name']})

    @access.public
    @filtermodel(model=User)
    @autoDescribeRoute(
        Description('List members of a group.')
        .modelParam('id', model=GroupModel, level=AccessType.READ)
        .pagingParams(defaultSort='firstName') # 🚧 replace with customID once customID defined
        .errorResponse('ID was invalid.')
        .errorResponse('Read access was denied for the group.', 403)
    )
    def listMembers(self, group, limit, offset, sort):
        return self._model.listMembers(group, offset=offset, limit=limit, sort=sort)

    @access.user
    @filtermodel(model=GroupModel, addFields={'access', 'requests'})
    @autoDescribeRoute(
        Description(
            "Invite a user to join a group, or accept a user's request to join."
        )
        .responseClass('Group')
        .notes('The "force" option to this endpoint is only available to '
               'administrators and can be used to bypass the invitation process'
               ' and instead add the user directly to the group.')
        .modelParam('id', model=GroupModel, level=AccessType.WRITE)
        .modelParam(
            'userId',
            'The ID of the user to invite or accept. Alternatively, provide '
            '`email`.',
            model=User,
            destName='userToInvite',
            level=AccessType.READ,
            paramType='form',
            required=False
        )
        .param(
            'email',
            'Email address of user to invite. Alternatively, provide `userId`.',
            required=False
        )
        .param(
            'level',
            'The access level the user will be given when they accept the '
            'invitation.',
            required=False,
            dataType='integer',
            default=AccessType.READ
        )
        .param(
            'quiet',
            'If you do not want this action to send an email to '
            'the target user, set this to true.',
            dataType='boolean',
            required=False,
            default=False
        )
        .param(
            'force',
            'Add user directly rather than sending an invitation '
            '(admin-only option).',
            dataType='boolean',
            required=False,
            default=False
        )
        .errorResponse()
        .errorResponse('Write access was denied for the group.', 403)
    )
    def inviteToGroup(
        self,
        group,
        userToInvite=None,
        email=None,
        level=AccessType.READ,
        quiet=False,
        force=False
    ):
        if ((
            userToInvite is None and email is None
        ) or (
            userToInvite is not None and email is not None
        )):
            raise ValidationException(
                "`POST /group/{id}/invitation` requires exactly one of `userID`"
                "and `email`."
            )
        groupModel = self._model
        user = self.getCurrentUser()
        if email is not None:
            userToInvite = User().findOne(query={"email": email}, force=True)
        if userToInvite is None:
            try:
                group["queue"] = list(set([email, *group.get("queue", [])]))
            except:
                group["queue"] = list(set([email]))
            groupModel.updateGroup(group)
            userToInvite = ProtoUser().createProtoUser(email=email)
            # TODO: send email to invite user
            return(group)
        if force:
            if not user['admin']:
                mustBeAdmin = True
                addPolicy = Setting().get(SettingKey.ADD_TO_GROUP_POLICY)
                addGroup = group.get('addAllowed', 'default')
                if addGroup not in ['no', 'yesadmin', 'yesmod']:
                    addGroup = addPolicy
                if (groupModel.hasAccess(
                        group, user, AccessType.ADMIN)
                        and ('mod' in addPolicy or 'admin' in addPolicy)
                        and addGroup.startswith('yes')):
                    mustBeAdmin = False
                elif (groupModel.hasAccess(
                        group, user, AccessType.WRITE)
                        and 'mod' in addPolicy
                        and addGroup == 'yesmod'):
                    mustBeAdmin = False
                if mustBeAdmin:
                    self.requireAdmin(user)
            groupModel.addUser(group, userToInvite, level=level)
        else:
            # Can only invite into access levels that you yourself have
            groupModel.requireAccess(group, user, level)
            groupModel.inviteUser(group, userToInvite, level)

            if not quiet:
                html = mail_utils.renderTemplate('groupInvite.mako', {
                    'userToInvite': userToInvite,
                    'user': user,
                    'group': group
                })
                mail_utils.sendMail(
                    "%s: You've been invited to a group" % Setting().get(SettingKey.BRAND_NAME),
                    html,
                    [userToInvite['email']]
                )

        group['access'] = groupModel.getFullAccessList(group)
        group['requests'] = list(groupModel.getFullRequestList(group))
        return(group)

    @access.user
    @filtermodel(model=GroupModel, addFields={'access'})
    @autoDescribeRoute(
        Description('Promote a member to be a moderator of the group.')
        .responseClass('Group')
        .modelParam('id', model=GroupModel, level=AccessType.ADMIN)
        .modelParam('userId', 'The ID of the user to promote.', model=User,
                    level=AccessType.READ, paramType='formData')
        .errorResponse('ID was invalid.')
        .errorResponse("You don't have permission to promote users.", 403)
    )
    def promoteToModerator(self, group, user):
        return self._promote(group, user, AccessType.WRITE)

    @access.user
    @filtermodel(model=GroupModel, addFields={'access'})
    @autoDescribeRoute(
        Description('Promote a member to be an administrator of the group.')
        .responseClass('Group')
        .modelParam('id', model=GroupModel, level=AccessType.ADMIN)
        .modelParam('userId', 'The ID of the user to promote.', model=User,
                    level=AccessType.READ, paramType='formData')
        .errorResponse('ID was invalid.')
        .errorResponse("You don't have permission to promote users.", 403)
    )
    def promoteToAdmin(self, group, user):
        return self._promote(group, user, AccessType.ADMIN)

    def _promote(self, group, user, level):
        """
        Promote a user to moderator or administrator.

        :param group: The group to promote within.
        :param user: The user to promote.
        :param level: Either WRITE or ADMIN, for moderator or administrator.
        :type level: AccessType
        :returns: The updated group document.
        """
        if not group['_id'] in user.get('groups', []):
            raise AccessException('That user is not a group member.')

        group = self._model.setUserAccess(group, user, level=level, save=True)
        group['access'] = self._model.getFullAccessList(group)
        return group

    @access.user
    @filtermodel(model=GroupModel, addFields={'access', 'requests'})
    @autoDescribeRoute(
        Description('Demote a user to a normal group member.')
        .responseClass('Group')
        .modelParam('id', model=GroupModel, level=AccessType.ADMIN)
        .modelParam('userId', 'The ID of the user to demote.', model=User,
                    level=AccessType.READ, paramType='formData')
        .errorResponse()
        .errorResponse("You don't have permission to demote users.", 403)
    )
    def demote(self, group, user):
        groupModel = self._model
        group = groupModel.setUserAccess(group, user, level=AccessType.READ, save=True)
        group['access'] = groupModel.getFullAccessList(group)
        group['requests'] = list(groupModel.getFullRequestList(group))
        return group

    @access.user
    @filtermodel(model=GroupModel, addFields={'access', 'requests'})
    @autoDescribeRoute(
        Description('Remove a user from a group, or uninvite them.')
        .responseClass('Group')
        .notes('If the specified user is not yet a member of the group, this '
               'will delete any outstanding invitation or membership request for '
               'the user. Passing no userId parameter will assume that the '
               'current user is removing themself.')
        .modelParam('id', model=GroupModel, force=True)
        .modelParam('userId', 'The ID of the user to remove. If not passed, will '
                    'remove yourself from the group.', required=False, model=User,
                    force=True, destName='userToRemove', paramType='formData')
        .param(
            'delete',
            'Delete existing user data associated with this group membership?',
            dataType='boolean',
            required=False,
            default=False
        )
        .errorResponse()
        .errorResponse("You don't have permission to remove that user.", 403)
    )
    def removeFromGroup(self, group, userToRemove, delete):
        user = self.getCurrentUser()
        if not (bool(
            group.get('_id') in [
                *user.get('groups', []),
                *user.get('formerGroups', []),
                *[
                    g.get('groupId') for g  in [
                        *user.get('groupInvites', []),
                        *user.get('declinedInvites', [])
                    ]
                ]
            ]
        )):
            raise AccessException(message="You haven't been invited to that group.")
        else:
            groupModel = self._model
            if userToRemove is None:
                # Assume user is removing themself from the group
                userToRemove = user

            # # If removing someone else, you must have at least as high an
            # # access level as they do, and you must have at least write access
            # # to remove any user other than yourself.
            # if user['_id'] != userToRemove['_id']:
            #     if groupModel.hasAccess(group, userToRemove, AccessType.ADMIN):
            #         groupModel.requireAccess(group, user, AccessType.ADMIN)
            #     else:
            #         groupModel.requireAccess(group, user, AccessType.WRITE)
            group = groupModel.removeUser(group, userToRemove, delete)
            group['access'] = groupModel.getFullAccessList(group)
            group['requests'] = list(groupModel.getFullRequestList(group))
            return(group)

    @access.user
    @autoDescribeRoute(
        Description('Delete a group by ID.')
        .modelParam('id', model=GroupModel, level=AccessType.ADMIN)
        .errorResponse('ID was invalid.')
        .errorResponse('Admin access was denied for the group.', 403)
    )
    def deleteGroup(self, group):
        self._model.remove(group)
        return {'message': 'Deleted the group %s.' % group['name']}
Exemple #13
0
    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})
Exemple #14
0
    def createUser(self,
                   login,
                   password,
                   displayName="",
                   email="",
                   admin=False,
                   public=False,
                   currentUser=None,
                   firstName="",
                   lastName="",
                   encryptEmail=False):
        """
        Create a new user with the given information.

        :param admin: Whether user is global administrator.
        :type admin: bool
        :param public: Whether user is publicly visible.
        :type public: bool
        :returns: The user document that was created.
        """
        from girderformindlogger.models.group import Group
        from girderformindlogger.models.setting import Setting
        requireApproval = Setting().get(
            SettingKey.REGISTRATION_POLICY) == 'approve'
        email = "" if not email else email

        login = login.lower().strip()
        email = email.lower().strip()

        if self.findOne({
                'email': email,
                'email_encrypted': {
                    '$ne': True
                }
        }) or self.findOne({
                'email': self.hash(email),
                'email_encrypted': True
        }):
            raise ValidationException(
                'That email is already registered in the system.', )

        if admin:
            requireApproval = False
            encryptEmail = False
        user = {
            'login':
            login,
            'email':
            email,
            'displayName':
            displayName if len(displayName) else
            firstName if firstName is not None else "",
            'firstName':
            firstName,
            'lastName':
            lastName,
            'created':
            datetime.datetime.utcnow(),
            'emailVerified':
            False,
            'status':
            'pending' if requireApproval else 'enabled',
            'admin':
            admin,
            'size':
            0,
            'deviceId':
            '',
            'timezone':
            0,
            'groups': [],
            'groupInvites': [{
                "groupId": gi.get('_id'),
                "level": 0
            } for gi in list(Group().find(
                query={"queue": email}))] if len(email) else [],
            'email_encrypted':
            encryptEmail
        }
        if encryptEmail:
            if len(email) == 0 or not mail_utils.validateEmailAddress(email):
                raise ValidationException('Invalid email address.', 'email')

            user['email'] = self.hash(user['email'])

        self.setPassword(user, password, save=False)
        self.setPublic(user, public, save=False)

        if currentUser:
            self.setUserAccess(user,
                               user=currentUser,
                               level=AccessType.WRITE,
                               save=False)
            user['creatorId'] = currentUser['_id']

        user = self.save(user)

        if currentUser:
            User().setUserAccess(doc=currentUser,
                                 user=user,
                                 level=AccessType.READ,
                                 save=True)
        else:
            user['creatorId'] = user['_id']
            user = self.save(user)

        verifyEmail = Setting().get(
            SettingKey.EMAIL_VERIFICATION) != 'disabled'
        if verifyEmail:
            self._sendVerificationEmail(user, email)

        if requireApproval:
            self._sendApprovalEmail(user)
        Group().update(query={"queue": user['email']},
                       update={"$pull": {
                           "queue": user['email']
                       }},
                       multi=True)
        user = self._getGroupInvitesFromProtoUser(user)
        self._deleteProtoUser(user)
        return (user)
    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 testAutoJoinBehavior(self):
        admin, user = self.users

        # create some groups
        g1 = Group().createGroup('g1', admin)
        g2 = Group().createGroup('g2', admin)
        g3 = Group().createGroup('g3', admin)

        # set auto join rules
        rules = [
            {
                'pattern': '@test.com',
                'groupId': str(g1['_id']),
                'level': AccessType.ADMIN
            },
            {
                'pattern': '@example.com',
                'groupId': str(g2['_id']),
                'level': AccessType.READ
            },
            {
                'pattern': '@example.com',
                'groupId': str(g3['_id']),
                'level': AccessType.WRITE
            },
        ]
        params = {'list': json.dumps([{'key': 'autojoin', 'value': rules}])}
        resp = self.request('/system/setting',
                            user=admin,
                            method='PUT',
                            params=params)
        self.assertStatusOk(resp)

        # create users
        user1 = User().createUser('user1', 'password', 'John', 'Doe',
                                  '*****@*****.**')
        user2 = User().createUser('user2', 'password', 'John', 'Doe',
                                  '*****@*****.**')
        user3 = User().createUser('user3', 'password', 'John', 'Doe',
                                  '*****@*****.**')

        # check correct groups were joined
        self.assertEqual(user1['groups'], [g2['_id'], g3['_id']])
        self.assertEqual(user2['groups'], [g1['_id']])
        self.assertEqual(user3['groups'], [])

        # check correct access levels
        g1 = Group().load(g1['_id'], force=True)
        g3 = Group().load(g3['_id'], force=True)
        self.assertIn(
            {
                'id': user2['_id'],
                'level': AccessType.ADMIN,
                'flags': []
            }, g1['access']['users'])
        self.assertIn(
            {
                'id': user1['_id'],
                'level': AccessType.WRITE,
                'flags': []
            }, g3['access']['users'])