コード例 #1
0
ファイル: __init__.py プロジェクト: wphicks/girder
def dicomSubstringSearchHandler(query,
                                types,
                                user=None,
                                level=None,
                                limit=0,
                                offset=0):
    """
    Provide a substring search on both keys and values.
    """
    if types != ['item']:
        raise RestException('The dicom search is only able to search in Item.')
    if not isinstance(query, six.string_types):
        raise RestException('The search query must be a string.')

    jsQuery = """
        function() {
            var queryKey = %(query)s.toLowerCase();
            var queryValue = queryKey;
            var dicomMeta = obj.dicom.meta;
            return Object.keys(dicomMeta).some(
                function(key) {
                    return (key.toLowerCase().indexOf(queryKey) !== -1)  ||
                        dicomMeta[key].toString().toLowerCase().indexOf(queryValue) !== -1;
                })
            }
    """ % {
        # This could eventually be a separately-defined key and value
        'query': json.dumps(query)
    }

    # Sort the documents inside MongoDB
    cursor = Item().find({'dicom': {'$exists': True}, '$where': jsQuery})
    # Filter the result
    result = {
        'item': [
            Item().filter(doc, user)
            for doc in Item().filterResultsByPermission(
                cursor, user, level, limit, offset)
        ]
    }

    return result
コード例 #2
0
ファイル: google.py プロジェクト: xinlaoda/girder
    def getUser(self, token):
        headers = {
            'Authorization': ' '.join(
                (token['token_type'], token['access_token']))
        }
        # For privacy and efficiency, fetch only the specific needed fields
        # https://developers.google.com/+/web/api/rest/#partial-response
        query = urllib.parse.urlencode(
            {'fields': ','.join(self._API_USER_FIELDS)})
        resp = self._getJson(method='GET',
                             url='%s?%s' % (self._API_USER_URL, query),
                             headers=headers)

        # Get user's OAuth2 ID
        oauthId = resp.get('id')
        if not oauthId:
            raise RestException('Google Plus did not return a user ID.',
                                code=502)

        # Get user's email address
        # Prefer email address with 'account' type
        emails = [
            email.get('value') for email in resp.get('emails', [])
            if email.get('type') == 'account'
        ]
        if not emails:
            # If an 'account' email can't be found, consider them all
            emails = [email.get('value') for email in resp.get('emails', [])]
        if emails:
            # Even if there are multiple emails, just use the first one
            email = emails[0]
        else:
            raise RestException(
                'This Google Plus user has no available email address.',
                code=502)

        # Get user's name
        firstName = resp.get('name', {}).get('givenName', '')
        lastName = resp.get('name', {}).get('familyName', '')

        user = self._createOrReuseUser(oauthId, email, firstName, lastName)
        return user
コード例 #3
0
ファイル: quota.py プロジェクト: xinlaoda/girder
    def _validate_fileSizeQuota(self, value):
        """Validate the fileSizeQuota parameter.

        :param value: the proposed value.
        :returns: the validated value
        :rtype: None or int
        """
        (value, err) = ValidateSizeQuota(value)
        if err:
            raise RestException(err, extra='fileSizeQuota')
        return value
コード例 #4
0
 def createColormapFromGradient(self, name, public, gradient, labels,
                                labelmap):
     try:
         return Colormap().createColormapFromGradient(
             self.getCurrentUser(), gradient, name, labels, public,
             labelmap)
     except ValidationException as exc:
         logger.exception('Failed to validate colormap')
         raise RestException(
             "Validation Error: JSON doesn\'t follow schema (%r)." %
             (exc.args, ))
コード例 #5
0
    def _getGeometry(self, geometry):
        try:
            GeoJSON.to_instance(geometry, strict=True)

            if geometry['type'] != 'Point':
                raise ValueError

            return geometry
        except (TypeError, ValueError):
            raise RestException(
                "Invalid GeoJSON passed as 'geometry' parameter.")
コード例 #6
0
 def verify(self):
     headers = {
         "X-Dataverse-key": "{}".format(self.key),
     }
     try:
         r = requests.get(self.token_url, headers=headers)
         r.raise_for_status()
     except requests.exceptions.HTTPError:
         raise RestException(
             "Key '{}' is not valid for '{}'".format(self.key, self.resource_server)
         )
コード例 #7
0
 def acquireLock(self, params):
     user = self.getCurrentUser()
     sessionId = params['sessionId']
     itemId = params['itemId']
     ownerId = None
     if 'ownerId' in params:
         ownerId = params['ownerId']
     if not Session().containsItem(sessionId, itemId, user):
         raise RestException('Item not in the session', 404)
     return self.model('lock', 'wt_data_manager').acquireLock(
         user, sessionId, itemId, ownerId)
コード例 #8
0
    def importData(self, assetstore, params):
        self.requireParams(('parentId', 'path'), params)

        user = self.getCurrentUser()
        parentType = params.get('parentType', 'folder')
        if parentType not in ('user', 'collection', 'folder'):
            raise RestException('Invalid parentType.')

        parent = self.model(parentType).load(params['parentId'], force=True, exc=True)

        progress = self.boolParam('progress', params, default=False)
        client = HdfsClient(
            host=assetstore['hdfs']['host'], port=assetstore['hdfs']['port'], use_trash=False)
        path = params['path']

        with ProgressContext(progress, user=user, title='Importing data from HDFS') as ctx:
            try:
                self._importData(parentType, parent, assetstore, client, path, ctx, user)
            except FileNotFoundException:
                raise RestException('File not found: %s.' % path)
コード例 #9
0
    def getUser(self, token):
        headers = {
            'Authorization': 'Bearer {}'.format(token['access_token']),
            'Accept': 'application/json'
        }

        # Get user's email address
        # In the unlikely case that a user has more than 30 email addresses,
        # this HTTP request might have to be made multiple times with
        # pagination
        resp = self._getJson(method='GET',
                             url=self._API_EMAILS_URL,
                             headers=headers)
        emails = [
            email.get('email') for email in resp['values']
            if email.get('is_primary') and email.get('is_confirmed')
        ]
        if not emails:
            raise RestException(
                'This Bitbucket user has no registered email address.',
                code=502)
        # There should never be more than one primary email
        email = emails[0]

        # Get user's OAuth2 ID, login, and name
        resp = self._getJson(method='GET',
                             url=self._API_USER_URL,
                             headers=headers)
        oauthId = resp.get('uuid')
        if not oauthId:
            raise RestException('Bitbucket did not return a user ID.',
                                code=502)

        login = resp.get('username', None)

        names = (resp.get('display_name') or login).split()
        firstName, lastName = names[0], names[-1]

        user = self._createOrReuseUser(oauthId, email, firstName, lastName,
                                       login)
        return user
コード例 #10
0
ファイル: rest.py プロジェクト: ziqiangxu/girder
    def callback(self, provider, state, code, error):
        if error is not None:
            raise RestException("Provider returned error: '%s'." % error,
                                code=502)

        self.requireParams({'state': state, 'code': code})

        providerName = provider
        provider = providers.idMap.get(providerName)
        if not provider:
            raise RestException('Unknown provider "%s".' % providerName)

        redirect = self._validateCsrfToken(state)

        providerObj = provider(cherrypy.url())
        token = providerObj.getToken(code)

        event = events.trigger('oauth.auth_callback.before', {
            'provider': provider,
            'token': token
        })
        if event.defaultPrevented:
            raise cherrypy.HTTPRedirect(redirect)

        user = providerObj.getUser(token)

        event = events.trigger('oauth.auth_callback.after', {
            'provider': provider,
            'token': token,
            'user': user
        })
        if event.defaultPrevented:
            raise cherrypy.HTTPRedirect(redirect)

        girderToken = self.sendAuthTokenCookie(user)
        try:
            redirect = redirect.format(girderToken=str(girderToken['_id']))
        except KeyError:
            pass  # in case there's another {} that's not handled by format

        raise cherrypy.HTTPRedirect(redirect)
コード例 #11
0
ファイル: file.py プロジェクト: RazerEdge64/containerFiles
    def readChunk(self, upload, offset, params):
        """
        After the temporary upload record has been created (see initUpload),
        the bytes themselves should be passed up in ordered chunks. The user
        must remain logged in when passing each chunk, to authenticate that
        the writer of the chunk is the same as the person who initiated the
        upload. The passed offset is a verification mechanism for ensuring the
        server and client agree on the number of bytes sent/received.
        """
        if cherrypy.request.headers.get('Content-Type',
                                        '').startswith('multipart/form-data'):
            raise RestException(
                'Multipart encoding is no longer supported. Send the chunk in '
                'the request body, and other parameters in the query string.')

        if 'chunk' in params:
            # If we see the undocumented "chunk" query string parameter, then we abort trying to
            # read the body, use the query string value as chunk, and pass it through to
            # Upload().handleChunk. This case is used by the direct S3 upload process.
            chunk = params['chunk']
        else:
            chunk = RequestBodyStream(cherrypy.request.body)
            logging.error(chunk)
            logging.error(params)
            logging.error(offset)
        user = self.getCurrentUser()

        if upload['userId'] != user['_id']:
            raise AccessException('You did not initiate this upload.')

        if upload['received'] != offset:
            raise RestException(
                'Server has received %s bytes, but client sent offset %s.' %
                (upload['received'], offset))
        try:
            logging.error('S3 upload----')
            return Upload().handleChunk(upload, chunk, filter=True, user=user)
        except IOError as exc:
            if exc.errno == errno.EACCES:
                raise Exception('Failed to store upload.')
            raise
コード例 #12
0
    def revokeAccount(self, provider, resource_server):
        """Revoke account authorization.

        In case of OAuth use the proper flow (usually calling /revoke with refreshToken).
        In case of API Key, just drop it from the user model.
        In case of DataONE, hahaha you thought that's possible via API?! You silly goose!
        (User would have to clear cookies from CN or login to ORCID and deauthorize there)
        """
        try:
            provider_obj = self.supported_providers()[provider]
        except KeyError:
            raise RestException(
                "Invalid account provider (provider={})".format(provider))

        if provider_obj["type"] == "apikey" and not resource_server:
            raise RestException(
                "Missing resource_server for apikey provider (provider={})".
                format(provider))

        user = self.getCurrentUser()
        user_tokens = user.get("otherTokens", [])

        # In case of APIKey, it's resource_server that's unique, not provider id
        if resource_server:
            key = "resource_server"
            target_value = resource_server
        else:
            key = "provider"
            target_value = provider

        token = next((_ for _ in user_tokens if _.get(key) == target_value),
                     None)
        if token:
            user_tokens.remove(token)
            user["otherTokens"] = user_tokens
            User().save(user)

            if provider_obj["type"] == "bearer":
                oauth_provider = providers.idMap[provider]
                # NOTE: only ORCID has that implemented
                oauth_provider("").revokeToken(token)
コード例 #13
0
ファイル: rest.py プロジェクト: mbrukman/girder
def setContentDisposition(filename, disposition='attachment', setHeader=True):
    """
    Set the content disposition header to either inline or attachment, and
    specify a filename that is properly escaped.  See
    developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition,
    tools.ietf.org/html/rfc2183, tools.ietf.org/html/rfc6266, and
    tools.ietf.org/html/rfc5987 for specifications and details.

    :param filename: the filename to add to the content disposition header.
    :param disposition: either 'inline' or 'attachment'.  None is the same as
        'attachment'.  Any other value skips setting the content disposition
        header.
    :param setHeader: if False, return the value that would be set to the
        Content-Disposition header, but do not set it.
    :returns: the content-disposition header value.
    """
    if (not disposition or (disposition not in ('inline', 'attachment') and
                            not disposition.startswith('form-data'))):
        raise RestException(
            'Error: Content-Disposition (%r) is not a recognized value.' % disposition)
    if not filename:
        raise RestException('Error: Content-Disposition filename is empty.')
    if not isinstance(disposition, six.binary_type):
        disposition = disposition.encode('iso8859-1', 'ignore')
    if not isinstance(filename, six.text_type):
        filename = filename.decode('utf8', 'ignore')
    # Decompose the name before trying to encode it.  This will de-accent
    # characters rather than remove them in some instances.
    safeFilename = unicodedata.normalize('NFKD', filename).encode('iso8859-1', 'ignore')
    utf8Filename = filename.encode('utf8', 'ignore')
    value = disposition + b'; filename="' + safeFilename.replace(
        b'\\', b'\\\\').replace(b'"', b'\\"') + b'"'
    if safeFilename != utf8Filename:
        quotedFilename = six.moves.urllib.parse.quote(utf8Filename)
        if not isinstance(quotedFilename, six.binary_type):
            quotedFilename = quotedFilename.encode('iso8859-1', 'ignore')
        value += b'; filename*=UTF-8\'\'' + quotedFilename
    value = value.decode('utf8')
    if setHeader:
        setResponseHeader('Content-Disposition', value)
    return value
コード例 #14
0
        def wrapped(*args, **kwargs):
            """
            Transform any passed params according to the spec, or
            fill in default values for any params not passed.
            """
            # Combine path params with form/query params into a single lookup table
            params = {k: v for k, v in six.viewitems(kwargs) if k != 'params'}
            params.update(kwargs.get('params', {}))

            for descParam in self.description.params:
                # We need either a type or a schema ( for message body )
                if 'type' not in descParam and 'schema' not in descParam:
                    continue

                name = descParam['name']
                model = self._getModel(name, self.description.modelParams)
                if name in params:
                    if name in self.description.jsonParams:
                        info = self.description.jsonParams[name]
                        val = self._loadJson(name, info, params[name])
                        self._passArg(fun, kwargs, name, val)
                    elif name in self.description.modelParams:
                        info = self.description.modelParams[name]
                        kwargs.pop(name, None)  # Remove from path params
                        val = self._loadModel(name, info, params[name], model)
                        self._passArg(fun, kwargs, self._destName(info, model), val)
                    else:
                        val = self._validateParam(name, descParam, params[name])
                        self._passArg(fun, kwargs, name, val)
                elif descParam['in'] == 'body':
                    if name in self.description.jsonParams:
                        info = self.description.jsonParams[name].copy()
                        info['required'] = descParam['required']
                        val = self._loadJsonBody(name, info)
                        self._passArg(fun, kwargs, name, val)
                    else:
                        self._passArg(fun, kwargs, name, cherrypy.request.body)
                elif 'default' in descParam:
                    self._passArg(fun, kwargs, name, descParam['default'])
                elif descParam['required']:
                    raise RestException('Parameter "%s" is required.' % name)
                else:
                    # If required=False but no default is specified, use None
                    if name in self.description.modelParams:
                        info = self.description.modelParams[name]
                        kwargs.pop(name, None)  # Remove from path params
                        self._passArg(fun, kwargs, info['destName'] or model.name, None)
                    else:
                        self._passArg(fun, kwargs, name, None)

            self._mungeKwargs(kwargs, fun)

            return fun(*args, **kwargs)
コード例 #15
0
ファイル: tiles.py プロジェクト: p829911/large_image
 def convertImage(self, item, params):
     if 'concurrent' in params:
         params['_concurrency'] = params.pop('concurrent')
     largeImageFileId = params.get('fileId')
     if largeImageFileId is None:
         files = list(Item().childFiles(item=item, limit=2))
         if len(files) == 1:
             largeImageFileId = str(files[0]['_id'])
     if not largeImageFileId:
         raise RestException('Missing "fileId" parameter.')
     largeImageFile = File().load(largeImageFileId, force=True, exc=True)
     user = self.getCurrentUser()
     token = self.getCurrentToken()
     params.pop('notify', None)
     localJob = self.boolParam('localJob', params, default=True)
     params.pop('localJob', None)
     try:
         return self.imageItemModel.convertImage(
             item, largeImageFile, user, token, localJob=localJob, **params)
     except TileGeneralException as e:
         raise RestException(e.args[0])
コード例 #16
0
    def getUser(self, token):
        headers = {
            'Authorization': 'Bearer %s' % token['access_token'],
            'Accept': 'application/json'
        }

        # Get user's email address
        resp = self._getJson(method='GET', url=self._API_USER_URL, headers=headers)
        email = resp.get('login')
        if not email:
            raise RestException(
                'Box did not return user information.', code=502)

        # Get user's OAuth2 ID, login, and name
        oauthId = resp.get('id')
        if not oauthId:
            raise RestException('Box did not return a user ID.', code=502)

        names = resp.get('name').split()
        firstName, lastName = names[0], names[-1]
        return self._createOrReuseUser(oauthId, email, firstName, lastName)
コード例 #17
0
    def _getTilesInfo(self, item, imageArgs):
        """
        Get metadata for an item's large image.

        :param item: the item to query.
        :param imageArgs: additional arguments to use when fetching image data.
        :return: the tile metadata.
        """
        try:
            return self.imageItemModel.getMetadata(item, **imageArgs)
        except TileGeneralException as e:
            raise RestException(e.args[0], code=400)
コード例 #18
0
ファイル: user.py プロジェクト: kelliecorona/girder
    def login(self):
        if not Setting().get(SettingKey.ENABLE_PASSWORD_LOGIN):
            raise RestException('Password login is disabled on this instance.')

        user, token = self.getCurrentUser(returnToken=True)

        # Only create and send new cookie if user isn't already sending a valid one.
        if not user:
            authHeader = cherrypy.request.headers.get('Authorization')

            if not authHeader:
                authHeader = cherrypy.request.headers.get(
                    'Girder-Authorization')

            if not authHeader or not authHeader[0:6] == 'Basic ':
                raise RestException('Use HTTP Basic Authentication', 401)

            try:
                credentials = base64.b64decode(authHeader[6:]).decode('utf8')
                if ':' not in credentials:
                    raise TypeError
            except Exception:
                raise RestException('Invalid HTTP Authorization header', 401)

            login, password = credentials.split(':', 1)
            otpToken = cherrypy.request.headers.get('Girder-OTP')
            user = self._model.authenticate(login, password, otpToken)

            setCurrentUser(user)
            token = self.sendAuthTokenCookie(user)

        return {
            'user': self._model.filter(user, user),
            'authToken': {
                'token': token['_id'],
                'expires': token['expires'],
                'scope': token['scope']
            },
            'message': 'Login succeeded.'
        }
コード例 #19
0
ファイル: tiles.py プロジェクト: knowledgevis/large_image
 def getTilesRegion(self, item, params):
     _adjustParams(params)
     params = self._parseParams(params, True, [
         ('left', float, 'region', 'left'),
         ('top', float, 'region', 'top'),
         ('right', float, 'region', 'right'),
         ('bottom', float, 'region', 'bottom'),
         ('regionWidth', float, 'region', 'width'),
         ('regionHeight', float, 'region', 'height'),
         ('units', str, 'region', 'units'),
         ('unitsWH', str, 'region', 'unitsWH'),
         ('width', int, 'output', 'maxWidth'),
         ('height', int, 'output', 'maxHeight'),
         ('fill', str),
         ('magnification', float, 'scale', 'magnification'),
         ('mm_x', float, 'scale', 'mm_x'),
         ('mm_y', float, 'scale', 'mm_y'),
         ('exact', bool, 'scale', 'exact'),
         ('frame', int),
         ('encoding', str),
         ('jpegQuality', int),
         ('jpegSubsampling', int),
         ('tiffCompression', str),
         ('style', str),
         ('resample', 'boolOrInt'),
         ('contentDisposition', str),
     ])
     _handleETag('getTilesRegion', item, params)
     try:
         regionData, regionMime = self.imageItemModel.getRegion(
             item, **params)
     except TileGeneralException as e:
         raise RestException(e.args[0])
     except ValueError as e:
         raise RestException('Value Error: %s' % e.args[0])
     self._setContentDisposition(
         item, params.get('contentDisposition'), regionMime, 'region')
     setResponseHeader('Content-Type', regionMime)
     setRawResponse()
     return regionData
コード例 #20
0
    def callbackAccount(self, provider, state, code, error):
        """Classical OAuth callback endpoint that parses incoming token.

        The main difference between this callback and /oauth/:provider/callback
        is that we store the incoming bearer token into User model, instead of using it
        to actually login to Girder.
        Note: We conveniently hid the userId in the OAuth state.
        """
        if error is not None:
            raise RestException("Provider returned error: '%s'." % error,
                                code=502)

        providerName = provider
        provider = providers.idMap.get(providerName)
        if not provider:
            raise RestException('Unknown provider "%s".' % providerName)

        self.requireParams({"state": state, "code": code})

        user, redirect = self._validateCsrfToken(state)
        providerObj = provider(cherrypy.url())
        new_token = providerObj.getToken(code)

        if "resource_server" not in new_token:
            new_token["resource_server"] = providerObj.getProviderName(
                external=False)
        new_token["provider"] = providerObj.getProviderName(external=False)

        user_tokens = user.get("otherTokens", [])
        for i, user_token in enumerate(user_tokens):
            if user_token["resource_server"] == new_token["resource_server"]:
                user_tokens[i] = new_token  # update token if found.
                break
        else:
            user_tokens.append(new_token)  # not found, append

        user["otherTokens"] = user_tokens
        user = User().save(user)
        self.sendAuthTokenCookie(user)
        raise cherrypy.HTTPRedirect(redirect)
コード例 #21
0
    def run_pipeline_task(self, folder, pipeline: PipelineDescription):
        """
        Run a pipeline on a dataset.

        :param folder: The girder folder containing the dataset to run on.
        :param pipeline: The pipeline to run the dataset on.
        """
        folder_id_str = str(folder["_id"])
        # First, verify that no other outstanding jobs are running on this dataset
        existing_jobs = Job().findOne({
            JOBCONST_DATASET_ID: folder_id_str,
            'status': {
                # Find jobs that are inactive, queued, or running
                # https://github.com/girder/girder/blob/master/plugins/jobs/girder_jobs/constants.py
                '$in': [0, 1, 2]
            },
        })
        if existing_jobs is not None:
            raise RestException(
                (f"A pipeline for {folder_id_str} is already running. "
                 "Only one outstanding job may be run at a time for "
                 "a dataset."))

        user = self.getCurrentUser()
        token = Token().createToken(user=user, days=14)
        move_existing_result_to_auxiliary_folder(folder, user)

        params: PipelineJob = {
            "input_folder": folder_id_str,
            "input_type": folder["meta"]["type"],
            "output_folder": folder_id_str,
            "pipeline": pipeline,
        }

        newjob = run_pipeline.apply_async(
            queue="pipelines",
            kwargs=dict(
                params=params,
                girder_job_title=
                f"Running {pipeline['name']} on {str(folder['name'])}",
                girder_client_token=str(token["_id"]),
                girder_job_type="pipelines",
            ),
        )
        newjob.job[JOBCONST_DATASET_ID] = folder_id_str
        newjob.job[JOBCONST_RESULTS_FOLDER_ID] = folder_id_str
        newjob.job[JOBCONST_PIPELINE_NAME] = pipeline['name']
        # Allow any users with accecss to the input data to also
        # see and possibly manage the job
        Job().copyAccessPolicies(folder, newjob.job)
        Job().save(newjob.job)
        return newjob.job
コード例 #22
0
ファイル: study.py プロジェクト: d9n13lt4n/isic-archive
    def deleteStudy(self, study, params):
        user = self.getCurrentUser()
        # For now, study admins will be the ones that can delete studies
        User().requireAdminStudy(user)

        if Study().childAnnotations(study=study,
                                    state=Study().State.COMPLETE).count():
            raise RestException('Study has completed annotations.', 409)

        Study().remove(study)

        # No Content
        cherrypy.response.status = 204
コード例 #23
0
ファイル: __init__.py プロジェクト: wphicks/girder
def acceptCollectionTerms(self, collection, termsHash):
    if not collection.get('terms'):
        raise RestException('This collection currently has no terms.')

    # termsHash should be encoded to a bytes object, but storing bytes into MongoDB behaves
    # differently in Python 2 vs 3. Additionally, serializing a bytes to JSON behaves differently
    # in Python 2 vs 3. So, just keep it as a unicode (or ordinary Python 2 str).
    realTermsHash = hashlib.sha256(collection['terms'].encode('utf-8')).hexdigest()
    if termsHash != realTermsHash:
        # This "proves" that the client has at least accessed the terms
        raise RestException(
            'The submitted "termsHash" does not correspond to the collection\'s current terms.')

    User().update(
        {'_id': self.getCurrentUser()['_id']},
        {'$set': {
            'terms.collection.%s' % collection['_id']: {
                'hash': termsHash,
                'accepted': datetime.datetime.now()
            }
        }}
    )
コード例 #24
0
    def intersects(self, field, geometry, limit, offset, sort):
        try:
            GeoJSON.to_instance(geometry, strict=True)
        except (TypeError, ValueError):
            raise RestException(
                "Invalid GeoJSON passed as 'geometry' parameter.")

        if field[:3] != '%s.' % GEOSPATIAL_FIELD:
            field = '%s.%s' % (GEOSPATIAL_FIELD, field)

        query = {field: {'$geoIntersects': {'$geometry': geometry}}}

        return self._find(query, limit, offset, sort)
コード例 #25
0
    def getPagingParameters(self,
                            params,
                            defaultSortField=None,
                            defaultSortDir=SortDir.ASCENDING):
        """
        Pass the URL parameters into this function if the request is for a
        list of resources that should be paginated. It will return a tuple of
        the form (limit, offset, sort) whose values should be passed directly
        into the model methods that are finding the resources. If the client
        did not pass the parameters, this always uses the same defaults of
        limit=50, offset=0, sort='name', sortdir=SortDir.ASCENDING=1.

        :param params: The URL query parameters.
        :type params: dict
        :param defaultSortField: If the client did not pass a 'sort' parameter,
            set this to choose a default sort field. If None, the results will
            be returned unsorted.
        :type defaultSortField: str or None
        :param defaultSortDir: Sort direction.
        :type defaultSortDir: girder.constants.SortDir
        """
        try:
            offset = int(params.get('offset', 0))
            limit = int(params.get('limit', 50))
            sortdir = int(params.get('sortdir', defaultSortDir))
        except ValueError:
            raise RestException(
                'Invalid value for offset, limit, or sortdir parameter.')
        if sortdir not in [SortDir.ASCENDING, SortDir.DESCENDING]:
            raise RestException('Invalid value for sortdir parameter.')

        if 'sort' in params:
            sort = [(params['sort'].strip(), sortdir)]
        elif isinstance(defaultSortField, six.string_types):
            sort = [(defaultSortField, sortdir)]
        else:
            sort = None

        return limit, offset, sort
コード例 #26
0
 def updateColormap(self, model, name, colormap):
     user = self.getCurrentUser()
     if name is not None:
         model['name'] = name
     if colormap is not None:
         model['colormap'] = colormap
     try:
         return Colormap().updateColormap(model, updateUser=user)
     except ValidationException as exc:
         logger.exception('Failed to validate colormap')
         raise RestException(
             "Validation Error: JSON doesn\'t follow schema (%r)." %
             (exc.args, ))
コード例 #27
0
ファイル: rest.py プロジェクト: xinlaoda/girder
    def _validateCsrfToken(self, state):
        """
        Tests the CSRF token value in the cookie to authenticate the user as
        the originator of the OAuth2 login. Raises a RestException if the token
        is invalid.
        """
        csrfTokenId, _, redirect = state.partition('.')

        token = Token().load(csrfTokenId, objectId=False, level=AccessType.READ)
        if token is None:
            raise RestException('Invalid CSRF token (state="%s").' % state, code=403)

        Token().remove(token)

        if token['expires'] < datetime.datetime.utcnow():
            raise RestException('Expired CSRF token (state="%s").' % state,
                                code=403)

        if not redirect:
            raise RestException('No redirect location (state="%s").' % state)

        return redirect
コード例 #28
0
 def createTiles(self, item, params):
     largeImageFileId = params.get('fileId')
     if largeImageFileId is None:
         files = list(Item().childFiles(item=item, limit=2))
         if len(files) == 1:
             largeImageFileId = str(files[0]['_id'])
     if not largeImageFileId:
         raise RestException('Missing "fileId" parameter.')
     largeImageFile = File().load(largeImageFileId, force=True, exc=True)
     user = self.getCurrentUser()
     token = self.getCurrentToken()
     try:
         return self.imageItemModel.createImageItem(item,
                                                    largeImageFile,
                                                    user,
                                                    token,
                                                    notify=self.boolParam(
                                                        'notify',
                                                        params,
                                                        default=True))
     except TileGeneralException as e:
         raise RestException(e.args[0])
コード例 #29
0
ファイル: globus.py プロジェクト: ziqiangxu/girder
    def getUser(self, token):
        headers = {'Authorization': 'Bearer {}'.format(token['access_token'])}

        resp = self._getJson(method='GET',
                             url=self._API_USER_URL,
                             headers=headers)

        oauthId = resp.get('sub')
        if not oauthId:
            raise RestException('Globus identity did not return a valid ID.',
                                code=502)

        email = resp.get('email')
        if not email:
            raise RestException(
                'Globus identity did not return a valid email.', code=502)

        name = resp['name'].split()
        firstName = name[0]
        lastName = name[-1]

        return self._createOrReuseUser(oauthId, email, firstName, lastName)
コード例 #30
0
    def createThumbnail(self, file, width, height, crop, attachToId, attachToType):
        user = self.getCurrentUser()

        ModelImporter.model(attachToType).load(
            attachToId, user=user, level=AccessType.WRITE, exc=True)

        width = max(width, 0)
        height = max(height, 0)

        if not width and not height:
            raise RestException('You must specify a valid width, height, or both.')

        return utils.scheduleThumbnailJob(file, attachToType, attachToId, user, width, height, crop)