Пример #1
0
    def _prepare_cloned_data(self, original_asset, source_version,
                             partial_update):
        """
        Some business rules must be applied when cloning an asset to another with a different type.
        It prepares the data to be cloned accordingly.

        It raises an exception if source and destination are not compatible for cloning.

        :param original_asset: Asset
        :param source_version: AssetVersion
        :param partial_update: Boolean
        :return: dict
        """
        if self._validate_destination_type(original_asset):
            # `to_clone_dict()` returns only `name`, `content`, `asset_type`,
            # and `tag_string`
            cloned_data = original_asset.to_clone_dict(version=source_version)

            # Allow the user's request data to override `cloned_data`
            cloned_data.update(self.request.data.items())

            if partial_update:
                # Because we're updating an asset from another which can have another type,
                # we need to remove `asset_type` from clone data to ensure it's not updated
                # when serializer is initialized.
                cloned_data.pop("asset_type", None)
            else:
                # Change asset_type if needed.
                cloned_data["asset_type"] = self.request.data.get(
                    ASSET_TYPE_ARG_NAME, original_asset.asset_type)

            cloned_asset_type = cloned_data.get("asset_type")
            # Settings are: Country, Description, Sector and Share-metadata
            # Copy settings only when original_asset is `survey` or `template`
            # and `asset_type` property of `cloned_data` is `survey` or `template`
            # or None (partial_update)
            if cloned_asset_type in [None, ASSET_TYPE_TEMPLATE, ASSET_TYPE_SURVEY] and \
                    original_asset.asset_type in [ASSET_TYPE_TEMPLATE, ASSET_TYPE_SURVEY]:

                settings = original_asset.settings.copy()
                settings.pop("share-metadata", None)

                cloned_data_settings = cloned_data.get("settings", {})

                # Depending of the client payload. settings can be JSON or string.
                # if it's a string. Let's load it to be able to merge it.
                if not isinstance(cloned_data_settings, dict):
                    cloned_data_settings = json.loads(cloned_data_settings)

                settings.update(cloned_data_settings)
                cloned_data['settings'] = json.dumps(settings)

            # until we get content passed as a dict, transform the content obj to a str
            # TODO, verify whether `Asset.content.settings.id_string` should be cleared out.
            cloned_data["content"] = json.dumps(cloned_data.get("content"))
            return cloned_data
        else:
            raise BadAssetTypeException(
                "Destination type is not compatible with source type")
Пример #2
0
    def deploy(self, backend=False, active=True):
        """this method could be called "deploy_latest_version()"."""

        if self.can_be_deployed:
            if not self.has_deployment:
                self.connect_deployment(backend=backend, active=active)
            else:
                self.deployment.redeploy(active=active)
            self._mark_latest_version_as_deployed()
        else:
            raise BadAssetTypeException("Only surveys may be deployed, but this asset is a {}".format(
                self.asset_type))
Пример #3
0
    def deploy(self, backend=False, active=True):
        """
        This method could be called `deploy_latest_version()`.
        """
        if self.can_be_deployed:
            if not self.has_deployment:
                self.connect_deployment(backend=backend, active=active)
                if self.has_deployment:  # Double-check, maybe overkill.
                    self.deployment.bulk_assign_mapped_perms()
            else:
                self.deployment.redeploy(active=active)

            self._mark_latest_version_as_deployed()
            self.async_media_files()

        else:
            raise BadAssetTypeException(
                'Only surveys may be deployed, but this asset is a '
                f'{self.asset_type}')
Пример #4
0
    def deploy(self, backend=False, active=True):
        """
        This method could be called `deploy_latest_version()`.
        """
        if self.can_be_deployed:
            if not self.has_deployment:
                self.connect_deployment(backend=backend, active=active)
                if self.has_deployment:  # Double-check, maybe overkill.
                    self.deployment.bulk_assign_mapped_perms()
            else:
                self.deployment.redeploy(active=active)

            self._mark_latest_version_as_deployed()
            self.deployment.store_data(
                {'status': self.deployment.STATUS_NOT_SYNCED})
            self.save(create_version=False, adjust_content=False)
            sync_media_files.delay(self.uid)

        else:
            raise BadAssetTypeException(
                'Only surveys may be deployed, but this asset is a '
                f'{self.asset_type}')
Пример #5
0
    def deployment(self, request, uid):
        """
        A GET request retrieves the existing deployment, if any.
        A POST request creates a new deployment, but only if a deployment does
            not exist already.
        A PATCH request updates the `active` field of the existing deployment.
        A PUT request overwrites the entire deployment, including the form
            contents, but does not change the deployment's identifier
        """
        asset = self.get_object()
        serializer_context = self.get_serializer_context()
        serializer_context['asset'] = asset

        # TODO: Require the client to provide a fully-qualified identifier,
        # otherwise provide less kludgy solution
        if 'identifier' not in request.data and 'id_string' in request.data:
            id_string = request.data.pop('id_string')[0]
            backend_name = request.data['backend']
            try:
                backend = DEPLOYMENT_BACKENDS[backend_name]
            except KeyError:
                raise KeyError(
                    'cannot retrieve asset backend: "{}"'.format(backend_name))
            request.data['identifier'] = backend.make_identifier(
                request.user.username, id_string)

        if request.method == 'GET':
            if not asset.has_deployment:
                raise Http404
            else:
                serializer = DeploymentSerializer(asset.deployment,
                                                  context=serializer_context)
                # TODO: Understand why this 404s when `serializer.data` is not
                # coerced to a dict
                return Response(dict(serializer.data))
        elif request.method == 'POST':
            if not asset.can_be_deployed:
                raise BadAssetTypeException(
                    "Only surveys may be deployed, but this asset is a {}".
                    format(asset.asset_type))
            else:
                if asset.has_deployment:
                    raise exceptions.MethodNotAllowed(
                        method=request.method,
                        detail='Use PATCH to update an existing deployment')
                serializer = DeploymentSerializer(data=request.data,
                                                  context=serializer_context)
                serializer.is_valid(raise_exception=True)
                serializer.save()
                # TODO: Understand why this 404s when `serializer.data` is not
                # coerced to a dict
                return Response(dict(serializer.data))

        elif request.method == 'PATCH':
            if not asset.can_be_deployed:
                raise BadAssetTypeException(
                    "Only surveys may be deployed, but this asset is a {}".
                    format(asset.asset_type))
            else:
                if not asset.has_deployment:
                    raise exceptions.MethodNotAllowed(
                        method=request.method,
                        detail='Use POST to create a new deployment')
                serializer = DeploymentSerializer(asset.deployment,
                                                  data=request.data,
                                                  context=serializer_context,
                                                  partial=True)
                serializer.is_valid(raise_exception=True)
                serializer.save()
                # TODO: Understand why this 404s when `serializer.data` is not
                # coerced to a dict
                return Response(dict(serializer.data))