示例#1
0
    def joinGroup(self, group, user):
        """
        This method either accepts an invitation to join a group, or if the
        given user has not been invited to the group, this will create an
        invitation request that moderators and admins may grant or deny later.
        """
        from girderformindlogger.models.user import User

        if 'groupInvites' not in user:
            user['groupInvites'] = []

        if group.get('openRegistration', False):
            self.addUser(group, user, level=AccessType.READ)
            User().save(user, validate=False)

        else:
            for invite in user['groupInvites']:
                if invite['groupId'] == group['_id']:
                    self.addUser(group, user, level=invite['level'])
                    user['groupInvites'].remove(invite)
                    User().save(user, validate=False)
                    break
            else:
                if 'requests' not in group:
                    group['requests'] = []

                if not user['_id'] in group['requests']:
                    group['requests'].append(user['_id'])
                    group = self.save(group, validate=False)

        return (group)
示例#2
0
 def setUp(self):
     base.TestCase.setUp(self)
     admin = {
         'email': '*****@*****.**',
         'login': '******',
         'firstName': 'Admin',
         'lastName': 'Last',
         'password': '******',
         'admin': True
     }
     self.admin = User().createUser(**admin)
     user = {
         'email': '*****@*****.**',
         'login': '******',
         'firstName': 'First',
         'lastName': 'Last',
         'password': '******',
         'admin': False
     }
     self.user = User().createUser(**user)
     coll = {
         'name': 'Test Collection',
         'description': 'The description',
         'public': True,
         'creator': self.admin
     }
     self.collection = Collection().createCollection(**coll)
     Folder().createFolder(parent=self.collection,
                           parentType='collection',
                           name='Public',
                           public=True,
                           creator=self.admin)
示例#3
0
    def setUp(self):
        base.TestCase.setUp(self)

        self.admin = User().createUser(email='*****@*****.**',
                                       login='******',
                                       lastName='admin',
                                       firstName='admin',
                                       password='******',
                                       admin=True)
        self.user = User().createUser(email='*****@*****.**',
                                      login='******',
                                      lastName='u',
                                      firstName='u',
                                      password='******')

        self.f1 = Folder().createFolder(self.admin,
                                        'f1',
                                        creator=self.admin,
                                        parentType='user')
        self.f2 = Folder().createFolder(self.admin,
                                        'f2',
                                        creator=self.admin,
                                        parentType='user')
        self.virtual = Folder().createFolder(self.user,
                                             'v',
                                             creator=self.user,
                                             parentType='user')
        self.virtual['isVirtual'] = True
示例#4
0
    def load(self, info):
        User().ensureIndex((
            (('oauth.provider', SortDir.ASCENDING),
             ('oauth.id', SortDir.ASCENDING)), {}))
        User().reconnect()

        events.bind('no_password_login_attempt', 'oauth', checkOauthUser)

        info['apiRoot'].oauth = rest.OAuth()
示例#5
0
def fastCrypt():
    """
    Use faster password hashing to avoid unnecessary testing bottlenecks.
    """
    from girderformindlogger.models.user import User

    # CryptContext.update could be used to mutate the existing instance, but if this fixture's scope
    # is ever made more limited (so that the teardown matters), this approach is more maintainable
    originalCryptContext = User()._cryptContext
    User()._cryptContext = originalCryptContext.copy(schemes=['plaintext'])
    yield
    User()._cryptContext = originalCryptContext
示例#6
0
def _getLdapUser(attrs, server):
    emails = attrs.get('mail')
    if not emails:
        raise Exception('No email record present for the given LDAP user.')

    if not isinstance(emails, (list, tuple)):
        emails = (emails, )

    emails = [e.decode('utf8').lower() for e in emails]
    existing = User().find({'email': {'$in': emails}}, limit=1)
    if existing.count():
        return next(existing)

    return _registerLdapUser(attrs, emails[0], server)
示例#7
0
    def _testLogin(cls, login):
        """
        When attempting to generate a username, use this to test if the given
        name is valid.
        """
        try:
            User()._validateLogin(login)
        except ValidationException:
            # Still doesn't match regex, we're hosed
            return False

        # See if this is already taken.
        user = User().findOne({'login': login})
        return not user
示例#8
0
    def inviteUser(self, group, user, level=AccessType.READ):
        """
        Invite a user to join the group. Inviting them automatically
        grants the user read access to the group so that they can see it.
        Once they accept the invitation, they will be given the specified level
        of access.

        If the user has requested an invitation to this group, calling this
        will accept their request and add them to the group at the access
        level specified.
        """
        from girderformindlogger.models.user import User

        if group['_id'] in user.get('groups', []):
            raise ValidationException('User is already in this group.')

        # If there is an outstanding request to join from this user, we
        # just add them to the group instead of invite them.
        if user['_id'] in group.get('requests', []):
            return self.addUser(group, user, level)

        if 'groupInvites' not in user:
            user['groupInvites'] = []

        for invite in user['groupInvites']:
            if invite['groupId'] == group['_id']:
                invite['level'] = level
                break
        else:
            user['groupInvites'].append({
                'groupId': group['_id'],
                'level': level
            })

        return User().save(user, validate=False)
示例#9
0
    def validate(self, doc):
        from girderformindlogger.models.token import Token
        from girderformindlogger.models.user import User

        if doc['tokenDuration']:
            doc['tokenDuration'] = float(doc['tokenDuration'])
        else:
            doc['tokenDuration'] = None

        doc['name'] = doc['name'].strip()
        doc['active'] = bool(doc.get('active', True))

        if doc['scope'] is not None:
            if not isinstance(doc['scope'], (list, tuple)):
                raise ValidationException('Scope must be a list, or None.')
            if not doc['scope']:
                raise ValidationException('Custom scope list must not be empty.')

            # Ensure only registered scopes are being set
            admin = User().load(doc['userId'], force=True)['admin']
            scopes = TokenScope.scopeIds(admin)
            unknownScopes = set(doc['scope']) - scopes
            if unknownScopes:
                raise ValidationException('Invalid scopes: %s.' % ','.join(unknownScopes))

        # Deactivating an already existing token
        if '_id' in doc and not doc['active']:
            Token().clearForApiKey(doc)

        return doc
示例#10
0
    def createToken(self, key, days=None):
        """
        Create a token using an API key.

        :param key: The API key (the key itself, not the full document).
        :type key: str
        :param days: You may request a token duration up to the token duration
            of the API key itself, or pass None to use the API key duration.
        :type days: float or None
        """
        from girderformindlogger.models.setting import Setting
        from girderformindlogger.models.token import Token
        from girderformindlogger.models.user import User

        apiKey = self.findOne({
            'key': key
        })

        if apiKey is None or not apiKey['active']:
            raise ValidationException('Invalid API key.')

        cap = apiKey['tokenDuration'] or Setting().get(SettingKey.COOKIE_LIFETIME)
        days = min(float(days or cap), cap)

        user = User().load(apiKey['userId'], force=True)

        # Mark last used stamp
        apiKey['lastUse'] = datetime.datetime.utcnow()
        apiKey = self.save(apiKey)
        token = Token().createToken(user=user, days=days, scope=apiKey['scope'], apiKey=apiKey)
        return (user, token)
示例#11
0
    def __init__(self):
        super(User, self).__init__()
        self.resourceName = 'user'
        self._model = UserModel()

        self.route('DELETE', ('authentication', ), self.logout)
        self.route('DELETE', (':id', ), self.deleteUser)
        self.route('GET', (), self.find)
        self.route('GET', ('me', ), self.getMe)
        self.route('GET', ('authentication', ), self.login)
        self.route('GET', (':id', ), self.getUserByID)
        self.route('GET', (':id', 'access'), self.getUserAccess)
        self.route('PUT', (':id', 'access'), self.updateUserAccess)
        self.route('PUT', (':id', 'code'), self.updateIDCode)
        self.route('DELETE', (':id', 'code'), self.removeIDCode)
        self.route('GET', ('applets', ), self.getOwnApplets)
        self.route('GET', (':id', 'details'), self.getUserDetails)
        self.route('GET', ('invites', ), self.getGroupInvites)
        self.route('PUT', (':id', 'knows'), self.setUserRelationship)
        self.route('GET', ('details', ), self.getUsersDetails)
        self.route('POST', (), self.createUser)
        self.route('PUT', (':id', ), self.updateUser)
        self.route('PUT', ('password', ), self.changePassword)
        self.route('PUT', (':id', 'password'), self.changeUserPassword)
        self.route('GET', ('password', 'temporary', ':id'),
                   self.checkTemporaryPassword)
        self.route('PUT', ('password', 'temporary'),
                   self.generateTemporaryPassword)
        self.route('POST', (':id', 'otp'), self.initializeOtp)
        self.route('PUT', (':id', 'otp'), self.finalizeOtp)
        self.route('DELETE', (':id', 'otp'), self.removeOtp)
        self.route('PUT', ('profile', ), self.updateProfile)
        self.route('PUT', (':id', 'verification'), self.verifyEmail)
        self.route('POST', ('verification', ), self.sendVerificationEmail)
示例#12
0
def _uploadComplete(event):
    """
    Called after an upload finishes. We check if our current token is a special
    authorized upload token, and if so, delete it.

    TODO we could alternatively keep a reference count inside each token that authorized
    more than a single upload at a time, and just decrement it here.
    """
    token = getCurrentToken()
    if token and 'authorizedUploadId' in token:
        user = User().load(token['userId'], force=True)
        item = Item().load(event.info['file']['itemId'], force=True)

        # Save the metadata on the item
        item['description'] = token['authorizedUploadDescription']
        item['authorizedUploadEmail'] = token['authorizedUploadEmail']
        Item().save(item)

        text = mail_utils.renderTemplate('authorized_upload.uploadFinished.mako', {
            'itemId': item['_id'],
            'itemName': item['name'],
            'itemDescription': item.get('description', '')
        })
        mail_utils.sendMail('Authorized upload complete', text, [user['email']])
        Token().remove(token)
示例#13
0
    def setUp(self):
        base.TestCase.setUp(self)

        self.users = [
            User().createUser('usr%s' % num, 'passwd', 'tst', 'usr',
                              '*****@*****.**' % num) for num in [0, 1]
        ]
示例#14
0
    def testLdapStatusCheck(self):
        admin = User().createUser(login='******',
                                  email='*****@*****.**',
                                  firstName='admin',
                                  lastName='admin',
                                  password='******',
                                  admin=True)

        params = {
            'bindName': 'cn=foo,cn=Users,dc=foo,dc=bar,dc=org',
            'password': '******',
            'uri': 'ldap://foo.bar.org:389'
        }

        with mock.patch('ldap.initialize',
                        return_value=MockLdap(bindFail=True)):
            resp = self.request('/system/ldap_server/status',
                                user=admin,
                                params=params)
            self.assertStatusOk(resp)
            self.assertFalse(resp.json['connected'])
            self.assertEqual(resp.json['error'],
                             'LDAP connection error: failed to connect')

        with mock.patch('ldap.initialize',
                        return_value=MockLdap(bindFail=False)):
            resp = self.request('/system/ldap_server/status',
                                user=admin,
                                params=params)
            self.assertStatusOk(resp)
            self.assertTrue(resp.json['connected'])
            self.assertNotIn('error', resp.json)
示例#15
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
示例#16
0
    def setUp(self):
        base.TestCase.setUp(self)

        self.siteAdminUser = User().createUser(email='*****@*****.**',
                                               login='******',
                                               firstName='Robert',
                                               lastName='Balboa',
                                               password='******')
        self.creatorUser = User().createUser(email='*****@*****.**',
                                             login='******',
                                             firstName='Apollo',
                                             lastName='Creed',
                                             password='******')
        creationSetting = Setting().getDefault(
            SettingKey.COLLECTION_CREATE_POLICY)
        creationSetting['open'] = True
        Setting().set(SettingKey.COLLECTION_CREATE_POLICY, creationSetting)
    def setUp(self):
        base.TestCase.setUp(self)
        self.dataDir = os.path.join(
            os.environ['GIRDER_TEST_DATA_PREFIX'], 'plugins', 'dicom_viewer')

        self.users = [User().createUser(
            'usr%s' % num, 'passwd', 'tst', 'usr', '*****@*****.**' % num)
            for num in [0, 1]]
示例#18
0
    def _canonicalUser(self, appletId, user):
        from girderformindlogger.models.user import User

        if isinstance(user, dict):
            userId = str(user['_id'])
            user = User().load(userId, force=True)
            profile = self.load(userId, force=True)
            return (user if user is not None else (
                User().load(str(profile['userId']), force=True) if
                (isinstance(profile, dict) and 'userId' in profile) else {}))
        if isinstance(user, str):
            try:
                return (self._canonicalUser(appletId,
                                            User().load(user, force=True)))
            except:
                return (self._canonicalUser(appletId,
                                            self.load(user, force=True)))
示例#19
0
 def listMembers(self, group, offset=0, limit=0, sort=None):
     """
     List members of the group.
     """
     from girderformindlogger.models.user import User
     return User().find({'groups': group['_id']},
                        limit=limit,
                        offset=offset,
                        sort=sort)
示例#20
0
    def check_auth_password(self, username, password):
        if username.lower() == 'anonymous':
            return paramiko.AUTH_SUCCESSFUL

        try:
            self.girderUser = User().authenticate(username, password, otpToken=True)
            return paramiko.AUTH_SUCCESSFUL
        except AccessException:
            return paramiko.AUTH_FAILED
示例#21
0
    def setUp(self):
        # Since our plugin updates the model singleton, don't drop models
        base.TestCase.setUp(self, dropModels=False)

        self.admin = User().createUser(email='*****@*****.**',
                                       login='******',
                                       firstName='first',
                                       lastName='last',
                                       password='******',
                                       admin=True)
示例#22
0
    def getFullRequestList(self, group):
        """
        Return the set of all outstanding requests, filled in with the login
        and full names of the corresponding users.

        :param group: The group to get requests for.
        :type group: dict
        """
        from girderformindlogger.models.user import User
        userModel = User()
        for userId in group.get('requests', []):
            user = userModel.load(userId,
                                  force=True,
                                  fields=['firstName', 'login'])
            yield {
                'id': userId,
                'login': user['login'],
                'name': user['firstName']
            }
示例#23
0
def _registerLdapUser(attrs, email, server):
    first, last = None, None
    if attrs.get('givenName'):
        first = attrs['givenName'][0].decode('utf8')
    elif attrs.get('cn'):
        first = attrs['cn'][0].decode('utf8').split()[0]

    if attrs.get('sn'):
        last = attrs['sn'][0].decode('utf8')
    elif attrs.get('cn'):
        last = attrs['cn'][0].decode('utf8').split()[-1]

    if not first or not last:
        raise Exception('No LDAP name entry found for %s.' % email)

    # Try using the search field value as the login. If it's an email address,
    # use the part before the @.
    try:
        login = attrs[server['searchField']][0].decode('utf8').split('@')[0]
        return User().createUser(login,
                                 password=None,
                                 firstName=first,
                                 lastName=last,
                                 email=email)
    except ValidationException as e:
        if e.field != 'login':
            raise

    # Fall back to deriving login from user's name
    for i in six.moves.range(_MAX_NAME_ATTEMPTS):
        login = ''.join((first, last, str(i) if i else ''))
        try:
            return User().createUser(login,
                                     password=None,
                                     firstName=first,
                                     lastName=last,
                                     email=email)
        except ValidationException as e:
            if e.field != 'login':
                raise

    raise Exception('Failed to generate login name for LDAP user %s.' % email)
示例#24
0
 def _recalculateSizes(self, progress):
     fixes = 0
     models = [Collection(), User()]
     steps = sum(model.find().count() for model in models)
     progress.update(total=steps, current=0)
     for model in models:
         for doc in model.find():
             progress.update(increment=1)
             _, f = model.updateSize(doc)
             fixes += f
     return fixes
示例#25
0
    def listKeys(self, userId, limit, offset, sort):
        user = self.getCurrentUser()

        if userId not in {None, str(user['_id'])}:
            self.requireAdmin(user)
            user = User().load(userId, force=True, exc=True)

        return list(ApiKeyModel().list(user,
                                       offset=offset,
                                       limit=limit,
                                       sort=sort))
示例#26
0
    def load(self, info):
        getPlugin('jobs').load(info)

        name = 'thumbnails'
        info['apiRoot'].thumbnail = rest.Thumbnail()

        for model in (Item(), Collection(), Folder(), User()):
            model.exposeFields(level=AccessType.READ, fields='_thumbnails')
            events.bind('model.%s.remove' % model.name, name, removeThumbnails)

        events.bind('model.file.remove', name, removeThumbnailLink)
        events.bind('data.process', name, _onUpload)
示例#27
0
    def _grantCreatorAccess(self, event):
        """
        This callback makes the group creator an administrator member of the
        group.

        This generally should not be called or overridden directly, but it may
        be unregistered from the `model.group.save.created` event.
        """
        from girderformindlogger.models.user import User
        group = event.info
        creator = User().load(group['creatorId'], force=True, exc=True)

        self.addUser(group, creator, level=AccessType.ADMIN)
示例#28
0
def lookUpPath(path, user=None, filter=True, force=False):
    """
    Look up a resource in the data hierarchy by path.

    :param path: path of the resource
    :param user: user with correct privileges to access path
    :param filter: Whether the returned model should be filtered.
    :type filter: bool
    :param force: if True, don't validate the access.
    :type force: bool
    """
    path = path.lstrip('/')
    pathArray = split(path)
    model = pathArray[0]

    if model == 'user':
        username = pathArray[1]
        parent = User().findOne({'login': username})

        if parent is None:
            raise ResourcePathNotFound('User not found: %s' % username)

    elif model == 'collection':
        collectionName = pathArray[1]
        parent = Collection().findOne({'name': collectionName})

        if parent is None:
            raise ResourcePathNotFound('Collection not found: %s' %
                                       collectionName)

    else:
        raise ValidationException('Invalid path format')

    try:
        document = parent
        if not force:
            ModelImporter.model(model).requireAccess(document, user)
        for token in pathArray[2:]:
            document, model = lookUpToken(token, model, document)
            if not force:
                ModelImporter.model(model).requireAccess(document, user)
    except (ValidationException, AccessException):
        # We should not distinguish the response between access and validation errors so that
        # adversarial users cannot discover the existence of data they don't have access to by
        # looking up a path.
        raise ResourcePathNotFound('Path not found: %s' % path)

    if filter:
        document = ModelImporter.model(model).filter(document, user)

    return {'model': model, 'document': document}
示例#29
0
def admin(db):
    """
    Require an admin user.

    Provides a user with the admin flag set to True.
    """
    from girderformindlogger.models.user import User
    u = User().createUser(email='*****@*****.**',
                          login='******',
                          firstName='Admin',
                          password='******',
                          admin=True)

    yield u
示例#30
0
    def listChildJobs(self, job):
        """
        Lists the child jobs for a given job

        :param job: Job document
        :type job: Job
        """
        query = {'parentId': job['_id']}
        cursor = self.find(query)
        user = User().load(job['userId'], force=True)
        for r in self.filterResultsByPermission(cursor=cursor,
                                                user=user,
                                                level=AccessType.READ):
            yield r