예제 #1
0
    def getUser(self, token):
        headers = {
            'Authorization': 'Bearer %s' % token['access_token'],
            'Accept': 'application/json'
        }

        # Get user's OAuth2 ID, email, and name
        # For privacy and efficiency, fetch only the specific needed fields
        # https://developer.linkedin.com/docs/signin-with-linkedin
        url = '%s:(%s)?%s' % (self._API_USER_URL, ','.join(
            self._API_USER_FIELDS), urllib.parse.urlencode({'format': 'json'}))
        resp = self._getJson(method='GET', url=url, headers=headers)

        oauthId = resp.get('id')
        if not oauthId:
            raise RestException('LinkedIn did not return user ID.', code=502)

        email = resp.get('emailAddress')
        if not email:
            raise RestException(
                'This LinkedIn user has no registered email address.',
                code=502)

        # Get user's name
        firstName = resp.get('firstName', '')
        lastName = resp.get('lastName', '')

        user = self._createOrReuseUser(oauthId, email, firstName, lastName)
        return user
예제 #2
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=20000, 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: girderformindlogger.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
예제 #3
0
    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
예제 #4
0
    def requireParams(self, required, provided=None):
        """
        This method has two modes. In the first mode, this takes two
        parameters, the first being a required parameter or list of
        them, and the second the dictionary of parameters that were
        passed. If the required parameter does not appear in the
        passed parameters, a ValidationException is raised.

        The second mode of operation takes only a single
        parameter, which is a dict mapping required parameter names
        to passed in values for those params. If the value is ``None``,
        a ValidationException is raised. This mode works well in conjunction
        with the ``autoDescribeRoute`` decorator, where the parameters are
        not all contained in a single dictionary.

        :param required: An iterable of required params, or if just one is
            required, you can simply pass it as a string.
        :type required: `list, tuple, or str`
        :param provided: The list of provided parameters.
        :type provided: dict
        """
        if provided is None and isinstance(required, dict):
            for name, val in six.viewitems(required):
                if val is None:
                    raise RestException('Parameter "%s" is required.' % name)
        else:
            if isinstance(required, six.string_types):
                required = (required,)

            for param in required:
                if provided is None or param not in provided:
                    raise RestException('Parameter "%s" is required.' % param)
예제 #5
0
    def login(self):
        import threading
        from girderformindlogger.utility.mail_utils import validateEmailAddress

        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)
            if validateEmailAddress(login):
                raise AccessException(
                    "Please log in with a username, not an email address.")
            otpToken = cherrypy.request.headers.get('Girder-OTP')
            try:
                user = self._model.authenticate(login, password, otpToken)
            except:
                raise AccessException(
                    "Incorrect password for {} if that user exists".format(
                        login))

            thread = threading.Thread(
                target=AppletModel().updateUserCacheAllRoles, args=(user, ))

            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.'
        }
예제 #6
0
 def _validateJsonType(self, name, info, val):
     if info.get('schema') is not None:
         try:
             jsonschema.validate(val, info['schema'])
         except jsonschema.ValidationError as e:
             raise RestException(
                 'Invalid JSON object for parameter %s: %s' %
                 (name, str(e)))
     elif info['requireObject'] and not isinstance(val, dict):
         raise RestException('Parameter %s must be a JSON object.' % name)
     elif info['requireArray'] and not isinstance(val, list):
         raise RestException('Parameter %s must be a JSON array.' % name)
예제 #7
0
    def setTimestamp(self, id, type, created, updated):
        user = self.getCurrentUser()
        model = self._getResourceModel(type)
        doc = model.load(id=id, user=user, level=AccessType.WRITE, exc=True)

        if created is not None:
            if 'created' not in doc:
                raise RestException('Resource has no "created" field.')
            doc['created'] = parseTimestamp(created)
        if updated is not None:
            if 'updated' not in doc:
                raise RestException('Resource has no "updated" field.')
            doc['updated'] = parseTimestamp(updated)
        return model.filter(model.save(doc), user=user)
예제 #8
0
    def finalizeOtp(self, user):
        otpToken = cherrypy.request.headers.get('Girder-OTP')
        if not otpToken:
            raise RestException('The "Girder-OTP" header must be provided.')

        if 'otp' not in user:
            raise RestException('The user has not initialized one-time passwords.')
        if self._model.hasOtpEnabled(user):
            raise RestException('The user has already enabled one-time passwords.')

        user['otp']['enabled'] = True
        # This will raise an exception if the verification fails, so the user will not be saved
        self._model.verifyOtp(user, otpToken)

        self._model.save(user)
예제 #9
0
 def updateProfile(self, update={}, id=None, applet=None, idCode=None):
     if (id is not None) and (applet is not None or idCode is not None):
         raise RestException(
             'Pass __either__ profile ID __OR__ (applet ID and ID code), '
             'not both.')
     elif (id is None) and (applet is None or idCode is None):
         raise RestException(
             'Either profile ID __OR__ (applet ID and ID code) required.')
     else:
         currentUser = self.getCurrentUser()
         id = id if id is not None else Profile().getProfile(
             applet=AppletModel().load(applet, force=True),
             idCode=idCode,
             user=currentUser)
     return (ProfileModel().updateProfile(id, currentUser, update))
예제 #10
0
        def wrapped(*args, **kwargs):
            model = ModelImporter.model(self.model, self.plugin)

            for raw, converted in six.viewitems(self.map):
                id = self._getIdValue(kwargs, raw)

                if self.force:
                    kwargs[converted] = model.load(
                        id, force=True, **self.kwargs)
                elif self.level is not None:
                    kwargs[converted] = model.load(
                        id=id, level=self.level, user=getCurrentUser(),
                        **self.kwargs)
                else:
                    kwargs[converted] = model.load(id, **self.kwargs)

                if kwargs[converted] is None and self.exc:
                    raise RestException(
                        'Invalid %s id (%s).' % (model.name, str(id)))

                if self.requiredFlags:
                    model.requireAccessFlags(
                        kwargs[converted], user=getCurrentUser(), flags=self.requiredFlags)

            return fun(*args, **kwargs)
예제 #11
0
 def _getIdValue(self, kwargs, idParam):
     if idParam in kwargs:
         return kwargs.pop(idParam)
     elif idParam in kwargs['params']:
         return kwargs['params'].pop(idParam)
     else:
         raise RestException('No ID parameter passed: ' + idParam)
예제 #12
0
    def _validateParam(self, name, descParam, value):
        """
        Validates and transforms a single parameter that was passed. Raises
        RestException if the passed value is invalid.

        :param name: The name of the param.
        :type name: str
        :param descParam: The formal parameter in the Description.
        :type descParam: dict
        :param value: The value passed in for this param for the current request.
        :returns: The value transformed
        """
        type = descParam.get('type')

        # Coerce to the correct data type
        if type == 'string':
            value = self._handleString(name, descParam, value)
        elif type == 'boolean':
            value = toBool(value)
        elif type == 'integer':
            value = self._handleInt(name, descParam, value)
        elif type == 'number':
            value = self._handleNumber(name, descParam, value)

        # Enum validation (should be after type coercion)
        if 'enum' in descParam and value not in descParam['enum']:
            raise RestException(
                'Invalid value for %s: "%s". Allowed values: %s.' %
                (name, value, ', '.join(str(v) for v in descParam['enum'])))

        return value
예제 #13
0
 def createAssetstore(self, name, type, root, perms, db, mongohost,
                      replicaset, bucket, prefix, accessKeyId, secret,
                      service, readOnly, region, inferCredentials,
                      serverSideEncryption):
     if type == AssetstoreType.FILESYSTEM:
         self.requireParams({'root': root})
         return self._model.createFilesystemAssetstore(name=name,
                                                       root=root,
                                                       perms=perms)
     elif type == AssetstoreType.GRIDFS:
         self.requireParams({'db': db})
         return self._model.createGridFsAssetstore(name=name,
                                                   db=db,
                                                   mongohost=mongohost,
                                                   replicaset=replicaset)
     elif type == AssetstoreType.S3:
         self.requireParams({'bucket': bucket})
         return self._model.createS3Assetstore(
             name=name,
             bucket=bucket,
             prefix=prefix,
             secret=secret,
             accessKeyId=accessKeyId,
             service=service,
             readOnly=readOnly,
             region=region,
             inferCredentials=inferCredentials,
             serverSideEncryption=serverSideEncryption)
     else:
         raise RestException('Invalid type parameter')
예제 #14
0
    def listResources(self, params):
        # Paths Object
        paths = {}

        # Definitions Object
        definitions = dict(**docs.models[None])

        # List of Tag Objects
        tags = []

        routeMap = _apiRouteMap()

        for resource in sorted(six.viewkeys(docs.routes), key=str):
            # Update Definitions Object
            if resource in docs.models:
                for name, model in six.viewitems(docs.models[resource]):
                    definitions[name] = model

            prefixPath = None
            tag = resource
            if isinstance(resource, Resource):
                if resource not in routeMap:
                    raise RestException('Resource not mounted: %s' % resource)
                prefixPath = routeMap[resource]
                tag = prefixPath[0]

            # Tag Object
            tags.append({'name': tag})

            for route, methods in six.viewitems(docs.routes[resource]):
                # Path Item Object
                pathItem = {}
                for method, operation in six.viewitems(methods):
                    # Operation Object
                    pathItem[method.lower()] = operation
                    if prefixPath:
                        operation['tags'] = prefixPath[:1]

                if prefixPath:
                    route = '/'.join([''] + prefixPath + [route[1:]])

                paths[route] = pathItem

        apiUrl = getApiUrl(preferReferer=True)
        urlParts = getUrlParts(apiUrl)
        host = urlParts.netloc
        basePath = urlParts.path

        return {
            'swagger': SWAGGER_VERSION,
            'info': {
                'title': 'Girder REST API',
                'version': VERSION['release']
            },
            'host': host,
            'basePath': basePath,
            'tags': tags,
            'paths': paths,
            'definitions': definitions
        }
예제 #15
0
    def generateTemporaryPassword(self, email):
        user = self._model.findOne({'email': self._model.hash(email.lower()), 'email_encrypted': True})

        if not user:
            user = self._model.findOne({'email': email.lower(), 'email_encrypted': {'$ne': True}})

        if not user:
            raise RestException('That email is not registered.')

        token = Token().createToken(user, days=(15/1440.0), scope=TokenScope.TEMPORARY_USER_AUTH)

        url = '%s#useraccount/%s/token/%s' % (
            mail_utils.getEmailUrlPrefix(), str(user['_id']), str(token['_id']))

        html = mail_utils.renderTemplate('temporaryAccess.mako', {
            'url': url,
            'token': str(token['_id'])
        })

        mail_utils.sendMail(
            '%s: Temporary access' % Setting().get(SettingKey.BRAND_NAME),
            html,
            [email]
        )
        return {'message': 'Sent temporary access email.'}
예제 #16
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', {}))

            kwargs['params'] = 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 descParam['in'] == 'header':
                    continue  # For now, do nothing with header params
                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)
예제 #17
0
    def _matchRoute(self, method, path):
        """
        Helper function that attempts to match the requested ``method`` and ``path`` with a
        registered route specification.

        :param method: The requested HTTP method, in lowercase.
        :type method: str
        :param path: The requested path.
        :type path: tuple[str]
        :returns: A tuple of ``(route, handler, wildcards)``, where ``route`` is the registered
                  `list` of route components, ``handler`` is the route handler `function`, and
                  ``wildcards`` is a `dict` of kwargs that should be passed to the underlying
                  handler, based on the wildcard tokens of the route.
        :raises: `GirderException`, when no routes are defined on this resource.
        :raises: `RestException`, when no route can be matched.
        """
        if not self._routes:
            raise GirderException('No routes defined for resource')

        for route, handler in self._routes[method][len(path)]:
            wildcards = {}
            for routeComponent, pathComponent in six.moves.zip(route, path):
                if routeComponent[0] == ':':  # Wildcard token
                    wildcards[routeComponent[1:]] = pathComponent
                elif routeComponent != pathComponent:  # Exact match token
                    break
            else:
                return route, handler, wildcards

        raise RestException('No matching route for "%s %s"' % (method.upper(), '/'.join(path)))
예제 #18
0
    def stream(self, timeout, params):
        if not Setting().get(SettingKey.ENABLE_NOTIFICATION_STREAM):
            raise RestException('The notification stream is not enabled.',
                                code=503)

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

        setResponseHeader('Content-Type', 'text/event-stream')
        setResponseHeader('Cache-Control', 'no-cache')
        since = params.get('since')
        if since is not None:
            since = datetime.utcfromtimestamp(since)

        def streamGen():
            lastUpdate = since
            start = time.time()
            wait = MIN_POLL_INTERVAL
            while cherrypy.engine.state == cherrypy.engine.states.STARTED:
                wait = min(wait + MIN_POLL_INTERVAL, MAX_POLL_INTERVAL)
                for event in NotificationModel().get(user,
                                                     lastUpdate,
                                                     token=token):
                    if lastUpdate is None or event['updated'] > lastUpdate:
                        lastUpdate = event['updated']
                    wait = MIN_POLL_INTERVAL
                    start = time.time()
                    yield sseMessage(event)
                if time.time() - start > timeout:
                    break

                time.sleep(wait)

        return streamGen
예제 #19
0
    def find(self, parentType, parentId, text, name, limit, offset, sort):
        """
        Get a list of folders with given search parameters. Currently accepted
        search modes are:

        1. Searching by parentId and parentType, with optional additional
           filtering by the name field (exact match) or using full text search
           within a single parent folder. Pass a "name" parameter or "text"
           parameter to invoke these additional filters.
        2. Searching with full text search across all folders in the system.
           Simply pass a "text" parameter for this mode.
        """
        user = self.getCurrentUser()

        if parentType and parentId:
            parent = ModelImporter.model(parentType).load(
                parentId, user=user, level=AccessType.READ, exc=True)

            filters = {}
            if text:
                filters['$text'] = {
                    '$search': text
                }
            if name:
                filters['name'] = name

            return self._model.childFolders(
                parentType=parentType, parent=parent, user=user,
                offset=offset, limit=limit, sort=sort, filters=filters)
        elif text:
            return self._model.textSearch(
                text, user=user, limit=limit, offset=offset, sort=sort)
        else:
            raise RestException('Invalid search mode.')
예제 #20
0
    def download(self, resources, includeMetadata):
        """
        Returns a generator function that will be used to stream out a zip
        file containing the listed resource's contents, filtered by
        permissions.
        """
        user = self.getCurrentUser()
        self._validateResourceSet(resources)
        # Check that all the resources are valid, so we don't download the zip
        # file if it would throw an error.
        for kind in resources:
            model = self._getResourceModel(kind, 'fileList')
            for id in resources[kind]:
                if not model.load(id=id, user=user, level=AccessType.READ):
                    raise RestException('Resource %s %s not found.' %
                                        (kind, id))
        setResponseHeader('Content-Type', 'application/zip')
        setContentDisposition('Resources.zip')

        def stream():
            zip = ziputil.ZipGenerator()
            for kind in resources:
                model = ModelImporter.model(kind)
                for id in resources[kind]:
                    doc = model.load(id=id, user=user, level=AccessType.READ)
                    for (path, file) in model.fileList(
                            doc=doc,
                            user=user,
                            includeMetadata=includeMetadata,
                            subpath=True):
                        for data in zip.addFile(file, path):
                            yield data
            yield zip.footer()

        return stream
예제 #21
0
 def download(self, item, offset, format, contentDisposition,
              extraParameters):
     user = self.getCurrentUser()
     files = list(self._model.childFiles(item=item, limit=2))
     if format not in (None, '', 'zip'):
         raise RestException('Unsupported format: %s.' % format)
     if len(files) == 1 and format != 'zip':
         if contentDisposition not in {None, 'inline', 'attachment'}:
             raise RestException('Unallowed contentDisposition type "%s".' %
                                 contentDisposition)
         return File().download(files[0],
                                offset,
                                contentDisposition=contentDisposition,
                                extraParameters=extraParameters)
     else:
         return self._downloadMultifileItem(item, user)
예제 #22
0
    def initializeOtp(self, user):
        if self._model.hasOtpEnabled(user):
            raise RestException('The user has already enabled one-time passwords.')

        otpUris = self._model.initializeOtp(user)
        self._model.save(user)

        return otpUris
예제 #23
0
    def sendVerificationEmail(self, email):
        user = self._model.findOne({'email': email})

        if not user:
            raise RestException('That login is not registered.', 401)

        self._model._sendVerificationEmail(user, email)
        return {'message': 'Sent verification email.'}
예제 #24
0
 def _validateAlgo(self, algo):
     """
     Print an exception if a user requests an invalid checksum algorithm.
     """
     if algo not in SUPPORTED_ALGORITHMS:
         msg = 'Invalid algorithm "%s". Supported algorithms: %s.' % (
             algo, ', '.join(SUPPORTED_ALGORITHMS))
         raise RestException(msg, code=400)
예제 #25
0
    def createUser(
        self,
        login,
        password,
        displayName="",
        email="",
        admin=False,
        lastName=None,
        firstName=None
    ): # 🔥 delete lastName once fully deprecated
        currentUser = self.getCurrentUser()

        regPolicy = Setting().get(SettingKey.REGISTRATION_POLICY)

        if not currentUser or not currentUser['admin']:
            admin = False
            if regPolicy == 'closed':
                raise RestException(
                    'Registration on this instance is closed. Contact an '
                    'administrator to create an account for you.')

        user = self._model.createUser(
            login=login, password=password, email=email,
            firstName=displayName if len(
                displayName
            ) else firstName if firstName is not None else "",
            lastName=lastName, admin=admin, currentUser=currentUser) # 🔥 delete firstName and lastName once fully deprecated

        if not currentUser and self._model.canLogin(user):
            setCurrentUser(user)
            token = self.sendAuthTokenCookie(user)
            user['authToken'] = {
                'token': token['_id'],
                'expires': token['expires']
            }

        # Assign all new users to a "New Users" Group
        newUserGroup = GroupModel().findOne({'name': 'New Users'})
        newUserGroup = newUserGroup if (
            newUserGroup is not None and bool(newUserGroup)
        ) else GroupModel(
        ).createGroup(
            name="New Users",
            creator=UserModel().findOne(
                query={'admin': True},
                sort=[('created', SortDir.ASCENDING)]
            ),
            public=False
        )
        group = GroupModel().addUser(
            newUserGroup,
            user,
            level=AccessType.READ
        )
        group['access'] = GroupModel().getFullAccessList(group)
        group['requests'] = list(GroupModel().getFullRequestList(group))

        return(user)
예제 #26
0
    def sendVerificationEmail(self, login):
        loginField = 'email' if '@' in login else 'login'
        user = self._model.findOne({loginField: login.lower()})

        if not user:
            raise RestException('That login is not registered.', 401)

        self._model._sendVerificationEmail(user)
        return {'message': 'Sent verification email.'}
예제 #27
0
    def _validateResourceSet(self, resources, allowedModels=None):
        """
        Validate a set of resources against a set of allowed models.
        Also ensures the requested resource set is not empty.
        # TODO jsonschema could replace this probably

        :param resources: The set of resources requested.
        :param allowedModels: if present, an iterable of models that may be
            included in the resources.
        """
        if allowedModels:
            invalid = set(resources.keys()) - set(allowedModels)
            if invalid:
                raise RestException('Invalid resource types requested: ' +
                                    ', '.join(invalid))
        count = sum([len(v) for v in six.viewvalues(resources)])
        if not count:
            raise RestException('No resources specified.')
예제 #28
0
    def _loadJson(self, name, info, value):
        try:
            val = bson.json_util.loads(value)
        except ValueError:
            raise RestException('Parameter %s must be valid JSON.' % name)

        self._validateJsonType(name, info, val)

        return val
예제 #29
0
    def _prepareMoveOrCopy(self, resources, parentType, parentId):
        user = self.getCurrentUser()
        self._validateResourceSet(resources, ('folder', 'item'))

        if resources.get('item') and parentType != 'folder':
            raise RestException('Invalid parentType.')
        return ModelImporter.model(parentType).load(parentId,
                                                    level=AccessType.WRITE,
                                                    user=user,
                                                    exc=True)
예제 #30
0
 def createKey(self, name, scope, tokenDuration, active):
     if Setting().get(SettingKey.API_KEYS):
         return ApiKeyModel().createApiKey(user=self.getCurrentUser(),
                                           name=name,
                                           scope=scope,
                                           days=tokenDuration,
                                           active=active)
     else:
         raise RestException(
             'API key functionality is disabled on this instance.')