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")
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))
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}')
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}')
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))