コード例 #1
0
    def _validate_disable(self, updates, original):
        """
        Checks the templates and desks that are referencing the given
        content profile if the profile is being disabled
        """
        if 'enabled' in updates and updates.get('enabled') is False and original.get('enabled') is True:
            templates = list(superdesk.get_resource_service('content_templates').
                             get_templates_by_profile_id(original.get('_id')))

            if len(templates) > 0:
                template_names = ', '.join([t.get('template_name') for t in templates])
                raise SuperdeskApiError.badRequestError(
                    message='Cannot disable content profile as following templates are referencing: {}'.
                    format(template_names))

            req = ParsedRequest()
            all_desks = list(superdesk.get_resource_service('desks').get(req=req, lookup={}))
            profile_desks = [desk for desk in all_desks if
                             desk.get('default_content_profile') == str(original.get('_id'))]

            if len(profile_desks) > 0:
                profile_desk_names = ', '.join([d.get('name') for d in profile_desks])
                raise SuperdeskApiError.badRequestError(
                    message='Cannot disable content profile as following desks are referencing: {}'.
                    format(profile_desk_names))
コード例 #2
0
ファイル: crop.py プロジェクト: MiczFlor/superdesk-core
    def _validate_aspect_ratio(self, crop, doc):
        """
        Checks if the aspect ratio is consistent with one in defined in spec
        :param crop: Spec parameters
        :param doc: Posted parameters
        :raises SuperdeskApiError.badRequestError:
        """
        if 'CropLeft' not in doc:
            return

        width = doc['CropRight'] - doc['CropLeft']
        height = doc['CropBottom'] - doc['CropTop']
        if not (crop.get('width') or crop.get('height') or crop.get('ratio')):
            raise SuperdeskApiError.badRequestError(
                message='Crop data are missing. width, height or ratio need to be defined')
        if crop.get('width') and crop.get('height'):
            expected_crop_width = int(crop['width'])
            expected_crop_height = int(crop['height'])
            if width < expected_crop_width or height < expected_crop_height:
                raise SuperdeskApiError.badRequestError(
                    message='Wrong crop size. Minimum crop size is {}x{}.'.format(crop['width'], crop['height']))
                doc_ratio = round(width / height, 1)
                spec_ratio = round(expected_crop_width / expected_crop_height, 1)
                if doc_ratio != spec_ratio:
                    raise SuperdeskApiError.badRequestError(message='Wrong aspect ratio!')
        elif crop.get('ratio'):
            ratio = crop.get('ratio')
            if type(ratio) not in [int, float]:
                ratio = ratio.split(':')
                ratio = int(ratio[0]) / int(ratio[1])
            if abs((width / height) - ratio) > 0.01:
                raise SuperdeskApiError.badRequestError(
                    message='Ratio %s is not respected. We got %f' % (crop.get('ratio'), abs((width / height))))
コード例 #3
0
ファイル: routing_rules.py プロジェクト: oxcarh/superdesk
    def __validate_schedule(self, schedule):
        if schedule is not None \
                and (len(schedule) == 0
                     or (schedule.get('day_of_week') is None
                         or len(schedule.get('day_of_week', [])) == 0)):
            raise SuperdeskApiError.badRequestError(message="Schedule when defined can't be empty.")

        if schedule:
            day_of_week = [str(week_day).upper() for week_day in schedule.get('day_of_week', [])]
            if not (len(set(day_of_week) & set(self.day_of_week)) == len(day_of_week)):
                raise SuperdeskApiError.badRequestError(message="Invalid values for day of week.")

            if schedule.get('hour_of_day_from') or schedule.get('hour_of_day_to'):
                try:
                    from_time = datetime.strptime(schedule.get('hour_of_day_from'), '%H%M')
                except:
                    raise SuperdeskApiError.badRequestError(message="Invalid value for from time.")

                try:
                    to_time = datetime.strptime(schedule.get('hour_of_day_to'), '%H%M')
                except:
                    raise SuperdeskApiError.badRequestError(message="Invalid value for to time.")

                if from_time > to_time:
                    raise SuperdeskApiError.badRequestError(message="From time should be less than To Time.")
コード例 #4
0
ファイル: routing_rules.py プロジェクト: copyfun/superdesk
    def _validate_routing_scheme(self, routing_scheme):
        """
        Validates routing scheme for the below:
            1. A routing scheme must have at least one rule.
            2. Every rule in the routing scheme must have name, filter and at least one action

        Will throw BadRequestError if any of the conditions fail.

        :param routing_scheme:
        """

        routing_rules = routing_scheme.get('rules', [])
        if len(routing_rules) == 0:
            raise SuperdeskApiError.badRequestError(message="A Routing Scheme must have at least one Rule")
        for routing_rule in routing_rules:
            invalid_fields = [field for field in routing_rule.keys()
                              if field not in ('name', 'filter', 'actions', 'schedule')]

            if invalid_fields:
                raise SuperdeskApiError.badRequestError(
                    message="A routing rule has invalid fields %s".format(invalid_fields))

            schedule = routing_rule.get('schedule')
            actions = routing_rule.get('actions')

            if routing_rule.get('name') is None:
                raise SuperdeskApiError.badRequestError(message="A routing rule must have a name")
            elif actions is None or len(actions) == 0 or (actions.get('fetch') is None and actions.get(
                    'publish') is None and actions.get('exit') is None):
                raise SuperdeskApiError.badRequestError(message="A routing rule must have actions")
            else:
                self._validate_schedule(schedule)
コード例 #5
0
    def validate_embargo(self, item):
        """Validates the embargo of the item.

        Following are checked:
            1. Item can't be a package or a re-write of another story
            2. Publish Schedule and Embargo are mutually exclusive
            3. Always a future date except in case of Corrected and Killed.
        :raises: SuperdeskApiError.badRequestError() if the validation fails
        """

        if item[ITEM_TYPE] != CONTENT_TYPE.COMPOSITE:
            if EMBARGO in item:
                embargo = item.get(SCHEDULE_SETTINGS, {}).get('utc_{}'.format(EMBARGO))
                if embargo:
                    if item.get(PUBLISH_SCHEDULE) or item[ITEM_STATE] == CONTENT_STATE.SCHEDULED:
                        raise SuperdeskApiError.badRequestError("An item can't have both Publish Schedule and Embargo")

                    if (item[ITEM_STATE] not in {
                        CONTENT_STATE.KILLED, CONTENT_STATE.RECALLED, CONTENT_STATE.SCHEDULED}) \
                            and embargo <= utcnow():
                        raise SuperdeskApiError.badRequestError("Embargo cannot be earlier than now")

                    if item.get('rewrite_of'):
                        raise SuperdeskApiError.badRequestError("Rewrites doesn't support Embargo")

                    if not isinstance(embargo, datetime.date) or not embargo.time():
                        raise SuperdeskApiError.badRequestError("Invalid Embargo")

        elif is_normal_package(item):
            if item.get(EMBARGO):
                raise SuperdeskApiError.badRequestError("A Package doesn't support Embargo")

            self.packageService.check_if_any_item_in_package_has_embargo(item)
コード例 #6
0
ファイル: service.py プロジェクト: liveblog/superdesk-core
    def create(self, docs, **kwargs):
        service = get_resource_service('archive')
        doc = docs[0]
        formatter_name = doc.get('formatter_name')

        if not formatter_name:
            raise SuperdeskApiError.badRequestError('Formatter name not found')

        formatter = self._get_formatter(formatter_name)

        if not formatter:
                raise SuperdeskApiError.badRequestError('Formatter not found')

        if 'article_id' in doc:
            article_id = doc.get('article_id')
            article = service.find_one(req=None, _id=article_id)

            if not article:
                raise SuperdeskApiError.badRequestError('Article not found!')

            try:
                self._validate(article)
                sequence, formatted_doc = formatter.format(article, {'_id': '0'}, None)[0]
                formatted_doc = formatted_doc.replace('\'\'', '\'')
            except Exception as ex:
                raise SuperdeskApiError.\
                    badRequestError('Error in formatting article: {}'.format(str(ex)))

            return [{'formatted_doc': formatted_doc}]
コード例 #7
0
    def __validate_seq_num_settings(self, output_channel):
        """
        Validates the 'sequence_num_settings' property if present in output_channel. Below are the validation rules:
            1.  If min value is present then it should be greater than 0
            2.  If min is present and max value isn't available then it's defaulted to MAX_VALUE_OF_PUBLISH_SEQUENCE
            3.  If start_from present then the value should be between min and max.
                Otherwise, it's defaulted to the value of min

        :return: True if validation succeeds otherwise return False.
        """

        if output_channel.get('sequence_num_settings'):
            min = output_channel.get('sequence_num_settings').get('min', 1)
            max = output_channel.get('sequence_num_settings').get('max', MAX_VALUE_OF_PUBLISH_SEQUENCE)
            start_from = output_channel.get('sequence_num_settings').get('start_from', min)

            if min <= 0:
                raise SuperdeskApiError.badRequestError(payload={"sequence_num_settings.min": 1},
                                                        message="Value of Minimum in Sequence Number Settings should "
                                                                "be greater than 0")

            if min >= max:
                raise SuperdeskApiError.badRequestError(payload={"sequence_num_settings.min": 1},
                                                        message="Value of Minimum in Sequence Number Settings should "
                                                                "be less than the value of Maximum")

            if not min <= start_from <= max:
                raise SuperdeskApiError.badRequestError(payload={"sequence_num_settings.start_from": 1},
                                                        message="Value of Start From in Sequence Number Settings "
                                                                "should be between Minimum and Maximum")

            del output_channel['sequence_num_settings']
            output_channel['sequence_num_settings'] = {"min": min, "max": max, "start_from": start_from}

        return True
コード例 #8
0
ファイル: crop.py プロジェクト: MiczFlor/superdesk-core
    def validate_crop(self, original, updates, crop_name):
        """
        :param dict original: original item
        :param dict updates: updated renditions
        :param str crop_name: name of the crop
        :param dict doc: crop co-ordinates
        :raises SuperdeskApiError.badRequestError:
            For following conditions:
            1) if type != picture
            2) if renditions are missing in the original image
            3) if original rendition is missing
            4) Crop name is invalid
        """
        # Check if type is picture
        if original[ITEM_TYPE] != CONTENT_TYPE.PICTURE:
            raise SuperdeskApiError.badRequestError(message='Only images can be cropped!')

        # Check if the renditions exists
        if not original.get('renditions'):
            raise SuperdeskApiError.badRequestError(message='Missing renditions!')

        # Check if the original rendition exists
        if not original.get('renditions').get('original'):
            raise SuperdeskApiError.badRequestError(message='Missing original rendition!')

        # Check if the crop name is valid
        crop = self.get_crop_by_name(crop_name)
        crop_data = updates.get('renditions', {}).get(crop_name, {})
        if not crop and 'CropLeft' in crop_data:
            raise SuperdeskApiError.badRequestError(message='Unknown crop name! (name=%s)' % crop_name)

        self._validate_values(crop_data)
        self._validate_poi(original, updates, crop_name)
        self._validate_aspect_ratio(crop, crop_data)
コード例 #9
0
ファイル: crop.py プロジェクト: nistormihai/superdesk-core
    def create_crop(self, original_image, crop_name, crop_data):
        """Create a new crop based on the crop co-ordinates

        :param original: Article to add the crop
        :param crop_name: Name of the crop
        :param doc: Crop details
        :raises SuperdeskApiError.badRequestError
        :return dict: rendition
        """
        original_file = superdesk.app.media.fetch_rendition(original_image)
        if not original_file:
            raise SuperdeskApiError.badRequestError('Original file couldn\'t be found')
        try:
            cropped, out = crop_image(original_file, crop_name, crop_data)
            crop = self.get_crop_by_name(crop_name)
            if not cropped:
                raise SuperdeskApiError.badRequestError('Saving crop failed.')
            # resize if needed
            if crop.get('width') or crop.get('height'):
                out, width, height = _resize_image(out,
                                                   size=(crop.get('width'), crop.get('height')),
                                                   keepProportions=crop.get('keep_proportions', True))
                crop['width'] = width
                crop['height'] = height
                out.seek(0)
            return self._save_cropped_image(out, original_image, crop_data)
        except SuperdeskApiError:
            raise
        except Exception as ex:
            raise SuperdeskApiError.badRequestError('Generating crop failed: {}'.format(str(ex)))
コード例 #10
0
ファイル: crop.py プロジェクト: ahilles107/superdesk-core
    def create_crop(self, original, crop_name, crop_data):
        """
        Create a new crop based on the crop co-ordinates
        :param original: Article to add the crop
        :param crop_name: Name of the crop
        :param doc: Crop details
        :raises SuperdeskApiError.badRequestError
        :return dict: modified renditions
        """
        renditions = original.get('renditions', {})
        original_crop = renditions.get(crop_name, {})
        fields = ('CropLeft', 'CropTop', 'CropRight', 'CropBottom')
        crop_created = False

        if any(crop_data.get(name) != original_crop.get(name) for name in fields):
            original_image = renditions.get('original', {})
            original_file = superdesk.app.media.fetch_rendition(original_image)
            if not original_file:
                raise SuperdeskApiError.badRequestError('Original file couldn\'t be found')

            try:
                cropped, out = crop_image(original_file, crop_name, crop_data)

                if not cropped:
                    raise SuperdeskApiError.badRequestError('Saving crop failed.')

                renditions[crop_name] = self._save_cropped_image(out, original_image, crop_data)
                crop_created = True
            except SuperdeskApiError:
                raise
            except Exception as ex:
                raise SuperdeskApiError.badRequestError('Generating crop failed: {}'.format(str(ex)))

        return renditions, crop_created
コード例 #11
0
 def create(self, docs, **kwargs):
     for doc in docs:
         if doc.get('group_by') and doc.get('desk'):
             raise SuperdeskApiError.badRequestError('The desk must not be defined when group by is defined.')
         if not doc.get('group_by', False) and not doc.get('desk'):
             raise SuperdeskApiError.badRequestError('The desk is required when group by desk is false')
     return super().create(docs, **kwargs)
コード例 #12
0
ファイル: subscribers.py プロジェクト: copyfun/superdesk-core
    def _validate_seq_num_settings(self, subscriber):
        """
        Validates the 'sequence_num_settings' property if present in subscriber. Below are the validation rules:
            1.  If min value is present then it should be greater than 0
            2.  If min is present and max value isn't available then it's defaulted to MAX_VALUE_OF_PUBLISH_SEQUENCE

        :return: True if validation succeeds otherwise return False.
        """

        if subscriber.get('sequence_num_settings'):
            min = subscriber.get('sequence_num_settings').get('min', 1)
            max = subscriber.get('sequence_num_settings').get('max', app.config['MAX_VALUE_OF_PUBLISH_SEQUENCE'])

            if min <= 0:
                raise SuperdeskApiError.badRequestError(payload={"sequence_num_settings.min": 1},
                                                        message="Value of Minimum in Sequence Number Settings should "
                                                                "be greater than 0")

            if min >= max:
                raise SuperdeskApiError.badRequestError(payload={"sequence_num_settings.min": 1},
                                                        message="Value of Minimum in Sequence Number Settings should "
                                                                "be less than the value of Maximum")

            del subscriber['sequence_num_settings']
            subscriber['sequence_num_settings'] = {"min": min, "max": max}

        return True
コード例 #13
0
    def delete(self, lookup):
        filter_id = lookup.get('_id')

        # check if the filter is referenced by any subscribers...
        subscribers = self._get_referencing_subscribers(filter_id)
        if subscribers.count() > 0:
            references = ','.join(s['name'] for s in subscribers)
            raise SuperdeskApiError.badRequestError(
                'Content filter has been referenced by '
                'subscriber(s) {}'.format(references)
            )

        # check if the filter is referenced by any routing schemes...
        schemes = self._get_referencing_routing_schemes(filter_id)
        if schemes.count() > 0:
            references = ','.join(s['name'] for s in schemes)
            raise SuperdeskApiError.badRequestError(
                'Content filter has been referenced by '
                'routing scheme(s) {}'.format(references)
            )

        # check if the filter is referenced by any other content filters...
        referenced_filters = self._get_content_filters_by_content_filter(filter_id)
        if referenced_filters.count() > 0:
            references = ','.join([pf['name'] for pf in referenced_filters])
            raise SuperdeskApiError.badRequestError(
                'Content filter has been referenced in {}'.format(references))

        return super().delete(lookup)
コード例 #14
0
    def create(self, docs, **kwargs):
        service = get_resource_service('archive')
        doc = docs[0]
        formatter_name = doc.get('formatter_name')

        if not formatter_name:
            raise SuperdeskApiError.badRequestError('Formatter name not found')

        formatter = self._get_formatter(formatter_name)

        if not formatter:
                raise SuperdeskApiError.badRequestError('Formatter not found')

        if 'article_id' in doc:
            article_id = doc.get('article_id')
            article = service.find_one(req=None, _id=article_id)

            if not article:
                raise SuperdeskApiError.badRequestError('Article not found!')

            try:
                self._validate(article)
                sequence, formatted_doc = formatter.format(apply_schema(article), {'_id': '0'}, None)[0]
                formatted_doc = formatted_doc.replace('\'\'', '\'')

                # respond only with the formatted output if output_field is configured
                if hasattr(formatter, 'output_field'):
                    formatted_doc = json.loads(formatted_doc)
                    formatted_doc = formatted_doc.get(formatter.output_field, '').replace('\'\'', '\'')
            except Exception as ex:
                logger.exception(ex)
                raise SuperdeskApiError.\
                    badRequestError('Error in formatting article: {}'.format(str(ex)))

            return [{'formatted_doc': formatted_doc}]
コード例 #15
0
    def _validate_products_destinations(self, subscriber):
        """Validates the subscribers
            1. At least one destination or one api_products is specified.
            2. If direct products are specified then at least one destination is specified.
        :param dict subscriber:
        :return:
        """
        if not subscriber.get('is_active'):
            return

        if not subscriber.get('destinations') and not subscriber.get('api_products'):
            raise SuperdeskApiError.badRequestError(payload={"destinations": {"required": 1},
                                                             "api_products": {"required": 1}},
                                                    message="At least one destination or one API Product should "
                                                            "be specified")

        if len(subscriber.get("products") or []) and not subscriber.get('destinations'):
            raise SuperdeskApiError.badRequestError(payload={"destinations": {"required": 1}},
                                                    message="Destinations not specified.")

        if subscriber.get('products'):
            lookup = {config.ID_FIELD: {'$in': subscriber.get('products')}, 'product_type': ProductTypes.API.value}
            products = get_resource_service('products').get_product_names(lookup)
            if products:
                raise SuperdeskApiError.badRequestError(payload={'products': 1},
                                                        message="Invalid Product Type. "
                                                                "Products {}.".format(', '.join(products)))
        if subscriber.get('api_products'):
            lookup = {config.ID_FIELD: {'$in': subscriber.get('api_products')},
                      'product_type': ProductTypes.DIRECT.value}
            products = get_resource_service('products').get_product_names(lookup)
            if products:
                raise SuperdeskApiError.badRequestError(payload={'products': 1},
                                                        message="Invalid Product Type. "
                                                                "API Products {}.".format(', '.join(products)))
コード例 #16
0
ファイル: common.py プロジェクト: PressAssociation/superdesk
    def _publish_package_items(self, package, updates):
        """
        Publishes all items of a package recursively then publishes the package itself
        :param package: package to publish
        :param updates: payload
        """
        items = self.package_service.get_residrefs(package)

        if len(items) == 0 and self.publish_type == ITEM_PUBLISH:
            raise SuperdeskApiError.badRequestError("Empty package cannot be published!")

        removed_items = []
        if self.publish_type == ITEM_CORRECT:
            removed_items, added_items = self._get_changed_items(items, updates)
            if len(removed_items) == len(items) and len(added_items) == 0:
                raise SuperdeskApiError.badRequestError("Corrected package cannot be empty!")
            items.extend(added_items)

        subscriber_items = {}
        if items:
            archive_publish = get_resource_service('archive_publish')
            for guid in items:
                package_item = super().find_one(req=None, _id=guid)

                if not package_item:
                    raise SuperdeskApiError.badRequestError(
                        "Package item with id: {} does not exist.".format(guid))

                if package_item[ITEM_STATE] not in PUBLISH_STATES:
                    # if the item is not published then publish it

                    if package_item[ITEM_TYPE] == CONTENT_TYPE.COMPOSITE:
                        # if the item is a package do recursion to publish
                        sub_updates = {i: updates[i] for i in ['state', 'operation'] if i in updates}
                        sub_updates['groups'] = list(package_item['groups'])
                        self._publish_package_items(package_item, sub_updates)
                        self._update_archive(original=package_item, updates=sub_updates,
                                             should_insert_into_versions=False)
                        self.update_published_collection(published_item_id=package_item[config.ID_FIELD])
                    else:
                        # publish the item
                        archive_publish.patch(id=package_item.pop(config.ID_FIELD), updates=package_item)

                    insert_into_versions(id_=guid)
                    package_item = super().find_one(req=None, _id=guid)

                subscribers = self._get_subscribers_for_package_item(package_item)
                self.package_service.update_field_in_package(updates, package_item[config.ID_FIELD],
                                                             config.VERSION, package_item[config.VERSION])

                if package_item[config.ID_FIELD] in removed_items:
                    digital_item_id = None
                else:
                    digital_item_id = self._get_digital_id_for_package_item(package_item)

                self._extend_subscriber_items(subscriber_items, subscribers, package_item, digital_item_id)

            self.publish_package(package, updates, target_subscribers=subscriber_items)
            return subscribers
コード例 #17
0
    def _validate_dictionary(self, updates, original={}):
        dict_type = updates.get('type', original.get('type', DictionaryType.DICTIONARY.value))
        if dict_type == DictionaryType.ABBREVIATIONS.value and not updates.get('user', original.get('user')):
            raise SuperdeskApiError.badRequestError(message='User is required for the abbreviations dictionary.',
                                                    payload={'user': '******'})

        if original and dict_type != original.get('type', DictionaryType.DICTIONARY.value):
            raise SuperdeskApiError.badRequestError(message='The dictionary type cannot be changed.')
コード例 #18
0
ファイル: archive.py プロジェクト: jey07ro/superdesk
 def validate_schedule(self, schedule):
     if not isinstance(schedule, datetime.date):
         raise SuperdeskApiError.badRequestError("Schedule date is not recognized")
     if not schedule.date() or schedule.date().year <= 1970:
         raise SuperdeskApiError.badRequestError("Schedule date is not recognized")
     if not schedule.time():
         raise SuperdeskApiError.badRequestError("Schedule time is not recognized")
     if schedule < utcnow():
         raise SuperdeskApiError.badRequestError("Schedule cannot be earlier than now")
コード例 #19
0
ファイル: common.py プロジェクト: akintolga/superdesk-core
    def _publish_package_items(self, package, updates):
        """
        Publishes all items of a package recursively then publishes the package itself
        :param package: package to publish
        :param updates: payload
        """
        items = self.package_service.get_residrefs(package)

        if len(items) == 0 and self.publish_type == ITEM_PUBLISH:
            raise SuperdeskApiError.badRequestError("Empty package cannot be published!")

        removed_items = []
        if self.publish_type in [ITEM_CORRECT, ITEM_KILL]:
            removed_items, added_items = self._get_changed_items(items, updates)
            # we raise error if correction is done on a empty package. Kill is fine.
            if len(removed_items) == len(items) and len(added_items) == 0 and self.publish_type == ITEM_CORRECT:
                raise SuperdeskApiError.badRequestError("Corrected package cannot be empty!")
            items.extend(added_items)

        if items:
            archive_publish = get_resource_service('archive_publish')
            for guid in items:
                package_item = super().find_one(req=None, _id=guid)

                if not package_item:
                    raise SuperdeskApiError.badRequestError(
                        "Package item with id: {} does not exist.".format(guid))

                if package_item[ITEM_STATE] not in PUBLISH_STATES:  # if the item is not published then publish it
                    if package_item[ITEM_TYPE] == CONTENT_TYPE.COMPOSITE:
                        # if the item is a package do recursion to publish
                        sub_updates = {i: updates[i] for i in ['state', 'operation'] if i in updates}
                        sub_updates['groups'] = list(package_item['groups'])
                        self._publish_package_items(package_item, sub_updates)
                        self._update_archive(original=package_item, updates=sub_updates,
                                             should_insert_into_versions=False)
                    else:
                        # publish the item
                        package_item[PUBLISHED_IN_PACKAGE] = package[config.ID_FIELD]
                        archive_publish.patch(id=package_item.pop(config.ID_FIELD), updates=package_item)

                    insert_into_versions(id_=guid)

                elif guid in removed_items:
                    # remove the package information from the package item.
                    linked_in_packages = [linked for linked in package_item.get(LINKED_IN_PACKAGES)
                                          if linked.get(PACKAGE) != package.get(config.ID_FIELD)]
                    super().system_update(guid, {LINKED_IN_PACKAGES: linked_in_packages}, package_item)

                package_item = super().find_one(req=None, _id=guid)
                self.package_service.update_field_in_package(updates, package_item[config.ID_FIELD],
                                                             config.VERSION, package_item[config.VERSION])

        updated = deepcopy(package)
        updated.update(updates)
        self.update_published_collection(published_item_id=package[config.ID_FIELD], updated=updated)
コード例 #20
0
ファイル: resend.py プロジェクト: MiczFlor/superdesk-core
    def _validate_subscribers(self, subscriber_ids):
        if not subscriber_ids:
            raise SuperdeskApiError.badRequestError(message='No subscribers selected!')

        query = {'$and': [{config.ID_FIELD: {'$in': list(subscriber_ids)}}, {'is_active': True}]}
        subscribers = list(get_resource_service('subscribers').get(req=None, lookup=query))

        if len(subscribers) == 0:
            raise SuperdeskApiError.badRequestError(message='No active subscribers found!')

        return subscribers
コード例 #21
0
ファイル: service.py プロジェクト: nistormihai/superdesk-core
    def _validate_and_get_formatter(self, doc):
        """Validates incoming request and gets the formatter to be used"""
        if doc.get('item_ids') == 0:
            raise SuperdeskApiError.badRequestError('No items to export.')

        formatter_name = doc.get('format_type')
        formatter = next((f for f in get_all_formatters() if type(f).__name__ == formatter_name), None)
        if not formatter:
            raise SuperdeskApiError.badRequestError('Formatter not found for requested format type.')

        return formatter
コード例 #22
0
 def _check_parameters(self, docs):
     parameters = get_resource_service("filter_condition_parameters").get(req=None, lookup=None)
     for doc in docs:
         parameter = [p for p in parameters if p["field"] == doc["field"]]
         if not parameter or len(parameter) == 0:
             raise SuperdeskApiError.badRequestError(
                 "Filter condition:{} has unidentified field: {}".format(doc["name"], doc["field"])
             )
         if doc["operator"] not in parameter[0]["operators"]:
             raise SuperdeskApiError.badRequestError(
                 "Filter condition:{} has unidentified operator: {}".format(doc["name"], doc["operator"])
             )
コード例 #23
0
    def _validate_kill_template(self, doc):
        """
        Validates input values for kill templates
        """
        if doc.get('template_type') != TemplateType.KILL.value:
            return

        if doc.get('template_desks'):
            raise SuperdeskApiError.badRequestError('Kill templates can not be assigned to desks')
        if 'is_public' in doc and doc['is_public'] is False:
            raise SuperdeskApiError.badRequestError('Kill templates must be public')
        doc['is_public'] = True
コード例 #24
0
ファイル: filter_condition.py プロジェクト: m038/superdesk
 def _check_parameters(self, docs):
     parameters = get_resource_service('filter_condition_parameters').get(req=None, lookup=None)
     for doc in docs:
         parameter = [p for p in parameters if p['field'] == doc['field']]
         if not parameter or len(parameter) == 0:
             raise SuperdeskApiError.badRequestError(
                 'Filter condition:{} has unidentified field: {}'
                 .format(doc['name'], doc['field']))
         if doc['operator'] not in parameter[0]['operators']:
             raise SuperdeskApiError.badRequestError(
                 'Filter condition:{} has unidentified operator: {}'
                 .format(doc['name'], doc['operator']))
コード例 #25
0
ファイル: common.py プロジェクト: superdesk/superdesk-core
    def _validate(self, original, updates):
        self.raise_if_not_marked_for_publication(original)
        self.raise_if_invalid_state_transition(original)

        updated = original.copy()
        updated.update(updates)

        takes_package = self.takes_package_service.get_take_package(original)

        if self.publish_type == 'publish':
            # validate if take can be published
            if takes_package and not self.takes_package_service.can_publish_take(
                    takes_package, updates.get(SEQUENCE, original.get(SEQUENCE, 1))):
                raise PublishQueueError.previous_take_not_published_error(
                    Exception("Previous takes are not published."))

            update_schedule_settings(updated, PUBLISH_SCHEDULE, updated.get(PUBLISH_SCHEDULE))
            validate_schedule(updated.get(SCHEDULE_SETTINGS, {}).get('utc_{}'.format(PUBLISH_SCHEDULE)),
                              takes_package.get(SEQUENCE, 1) if takes_package else 1)

        if original[ITEM_TYPE] != CONTENT_TYPE.COMPOSITE and updates.get(EMBARGO):
            update_schedule_settings(updated, EMBARGO, updated.get(EMBARGO))
            get_resource_service(ARCHIVE).validate_embargo(updated)

        if self.publish_type in [ITEM_CORRECT, ITEM_KILL]:
            if updates.get(EMBARGO) and not original.get(EMBARGO):
                raise SuperdeskApiError.badRequestError("Embargo can't be set after publishing")

        if self.publish_type in [ITEM_CORRECT, ITEM_KILL]:
            if updates.get('dateline'):
                raise SuperdeskApiError.badRequestError("Dateline can't be modified after publishing")

        if self.publish_type == ITEM_PUBLISH and updated.get('rewritten_by'):
            # if update is published then user cannot publish the takes
            rewritten_by = get_resource_service(ARCHIVE).find_one(req=None, _id=updated.get('rewritten_by'))
            if rewritten_by and rewritten_by.get(ITEM_STATE) in PUBLISH_STATES:
                raise SuperdeskApiError.badRequestError("Cannot publish the story after Update is published.!")

        publish_type = 'auto_publish' if updates.get('auto_publish') else self.publish_type
        validate_item = {'act': publish_type, 'type': original['type'], 'validate': updated}
        validation_errors = get_resource_service('validate').post([validate_item])
        if validation_errors[0]:
            raise ValidationError(validation_errors)

        validation_errors = []
        self._validate_associated_items(original, takes_package, validation_errors)

        if original[ITEM_TYPE] == CONTENT_TYPE.COMPOSITE:
            self._validate_package(original, updates, validation_errors)

        if len(validation_errors) > 0:
            raise ValidationError(validation_errors)
コード例 #26
0
def render_content_template_by_id(item, template_id):
    """Apply template by name.

    :param dict item: item on which template is applied
    :param str template_id: template _id
    :return dict: updates to the item
    """
    # get the kill template
    template = superdesk.get_resource_service('content_templates').find_one(req=None, _id=template_id)
    if not template:
        SuperdeskApiError.badRequestError(message='{} Template missing.'.format(template_id))

    return render_content_template(item, template)
コード例 #27
0
def render_content_template_by_name(item, template_name):
    """
    Apply template by name
    :param dict item: item on which template is applied
    :param str template_name: template name
    :return dict: updates to the item
    """
    # get the kill template
    template = superdesk.get_resource_service('content_templates').get_template_by_name(template_name)
    if not template:
        SuperdeskApiError.badRequestError(message='{} Template missing.'.format(template_name))

    # apply the kill template
    return render_content_template(item, template)
コード例 #28
0
ファイル: archive_link.py プロジェクト: chalkjockey/superdesk
    def _validate_link(self, target, target_id):
        """
        Validates the article to be linked
        :param target: article to be linked
        :param target_id: id of the article to be linked
        :raises: SuperdeskApiError
        """
        if not target:
            raise SuperdeskApiError.notFoundError(message='Cannot find the target item with id {}.'.format(target_id))

        if target.get(EMBARGO):
            raise SuperdeskApiError.badRequestError("Takes can't be created for an Item having Embargo")

        if get_resource_service('published').is_rewritten_before(target['_id']):
            raise SuperdeskApiError.badRequestError(message='Article has been rewritten before !')
コード例 #29
0
def validate_schedule(schedule):
    """Validates the publish schedule.

    :param datetime schedule: schedule datetime
    :raises: SuperdeskApiError.badRequestError if following cases
        - Not a valid datetime
        - Less than current utc time
    """
    if schedule:
        if not isinstance(schedule, datetime):
            raise SuperdeskApiError.badRequestError("Schedule date is not recognized")
        if not schedule.date() or schedule.date().year <= 1970:
            raise SuperdeskApiError.badRequestError("Schedule date is not recognized")
        if schedule < utcnow():
            raise SuperdeskApiError.badRequestError("Schedule cannot be earlier than now")
コード例 #30
0
ファイル: broadcast.py プロジェクト: akintolga/superdesk-core
    def _valid_broadcast_item(self, item):
        """
        Broadcast item can only be created for Text or Pre-formatted item.
        Item state needs to be Published or Corrected
        :param dict item: Item from which the broadcast item will be created
        """
        if not item:
            raise SuperdeskApiError.notFoundError(
                message="Cannot find the requested item id.")

        if not item.get(ITEM_TYPE) in [CONTENT_TYPE.TEXT, CONTENT_TYPE.PREFORMATTED]:
            raise SuperdeskApiError.badRequestError(message="Invalid content type.")

        if item.get(ITEM_STATE) not in [CONTENT_STATE.CORRECTED, CONTENT_STATE.PUBLISHED]:
            raise SuperdeskApiError.badRequestError(message="Invalid content state.")
コード例 #31
0
    def validate_embargo(self, item):
        """Validates the embargo of the item.

        Following are checked:
            1. Item can't be a package or a re-write of another story
            2. Publish Schedule and Embargo are mutually exclusive
            3. Always a future date except in case of Corrected and Killed.
        :raises: SuperdeskApiError.badRequestError() if the validation fails
        """

        if item[ITEM_TYPE] != CONTENT_TYPE.COMPOSITE:
            if EMBARGO in item:
                embargo = item.get(SCHEDULE_SETTINGS,
                                   {}).get('utc_{}'.format(EMBARGO))
                if embargo:
                    if item.get(PUBLISH_SCHEDULE) or item[
                            ITEM_STATE] == CONTENT_STATE.SCHEDULED:
                        raise SuperdeskApiError.badRequestError(
                            "An item can't have both Publish Schedule and Embargo"
                        )

                    if (item[ITEM_STATE] not in {CONTENT_STATE.KILLED, CONTENT_STATE.SCHEDULED}) \
                            and embargo <= utcnow():
                        raise SuperdeskApiError.badRequestError(
                            "Embargo cannot be earlier than now")

                    if item.get('rewrite_of'):
                        raise SuperdeskApiError.badRequestError(
                            "Rewrites doesn't support Embargo")

                    if not isinstance(embargo,
                                      datetime.date) or not embargo.time():
                        raise SuperdeskApiError.badRequestError(
                            "Invalid Embargo")

        elif is_normal_package(item):
            if item.get(EMBARGO):
                raise SuperdeskApiError.badRequestError(
                    "A Package doesn't support Embargo")

            self.packageService.check_if_any_item_in_package_has_embargo(item)
コード例 #32
0
    def update(self, id, updates, original):
        """
        Handles workflow of each Publish, Corrected and Killed.
        """
        try:
            user = get_user()
            auto_publish = updates.pop('auto_publish', False)

            if original[ITEM_TYPE] == CONTENT_TYPE.COMPOSITE:
                self._publish_package_items(original, updates)
                self._update_archive(original,
                                     updates,
                                     should_insert_into_versions=auto_publish)
            else:
                self._refresh_associated_items(original)
                self._publish_associations(original, id)
                updated = deepcopy(original)
                updated.update(updates)

                if updates.get('associations'):
                    self._refresh_associated_items(
                        updated)  # updates got lost with update

                if self.published_state != CONTENT_STATE.KILLED:
                    self._process_takes_package(original, updated, updates)

                self._update_archive(original,
                                     updates,
                                     should_insert_into_versions=auto_publish)
                self.update_published_collection(
                    published_item_id=original[config.ID_FIELD],
                    updated=updated)

            from apps.publish.enqueue import enqueue_published
            enqueue_published.apply_async()

            push_notification('item:publish',
                              item=str(id),
                              unique_name=original['unique_name'],
                              desk=str(
                                  original.get('task', {}).get('desk', '')),
                              user=str(user.get(config.ID_FIELD, '')))
        except SuperdeskApiError as e:
            raise e
        except KeyError as e:
            raise SuperdeskApiError.badRequestError(
                message="Key is missing on article to be published: {}".format(
                    str(e)))
        except Exception as e:
            logger.exception(
                "Something bad happened while publishing %s".format(id))
            raise SuperdeskApiError.internalError(
                message="Failed to publish the item: {}".format(str(e)))
コード例 #33
0
    def _validate_language(self, doc):
        # fetch languages from CVs
        req = ParsedRequest()
        req.projection = json.dumps({"items.qcode": 1})

        try:
            languages = (
                superdesk.get_resource_service("vocabularies").find_one(req=req, _id="languages").get("items", [])
            )
        except AttributeError:
            raise SuperdeskApiError.badRequestError(
                message="Request is not valid",
                payload={"language": "Concept items requires 'languages' vocabulary to be set"},
            )

        languages_qcodes = [lang["qcode"] for lang in languages]

        if doc["language"] not in languages_qcodes:
            raise SuperdeskApiError.badRequestError(
                message="Request is not valid", payload={"language": "unallowed value '{}'".format(doc["language"])}
            )
コード例 #34
0
 def _validate_template_desks(self, updates, original=None):
     """
     Validate template desks value
     """
     if original is None:
         original = {}
     template_type = updates.get('template_type', original.get('template_type'))
     if template_type != TemplateType.CREATE.value and \
             type(updates.get('template_desks')) == list and \
             len(updates['template_desks']) > 1:
         raise SuperdeskApiError.badRequestError(
             message=_('Templates that are not create type can only be assigned to one desk!'))
コード例 #35
0
    def create(self, docs, **kwargs):
        archive_service = get_resource_service('archive')
        doc = docs[0]
        if not doc.get('article_id'):
            raise SuperdeskApiError.badRequestError(_('Article id cannot be empty!'))

        article_id = doc.get('article_id')
        article = archive_service.find_one(req=None, _id=article_id)

        if not article:
            raise SuperdeskApiError.badRequestError(_('Article not found!'))

        try:
            results = self.test_products(article)
        except Exception as ex:
            logger.exception(ex)
            raise SuperdeskApiError.badRequestError(
                _('Error in testing article: {exception}').format(exception=str(ex)))

        doc['_items'] = results
        return [article_id]
コード例 #36
0
ファイル: archive.py プロジェクト: vanzeelandj/superdesk-core
    def create(self, docs, **kwargs):
        if not docs:
            raise SuperdeskApiError.notFoundError('Content is missing')

        req = parse_request(self.datasource)
        try:
            get_component(ItemAutosave).autosave(docs[0]['_id'], docs[0], get_user(required=True), req.if_match)
        except InvalidEtag:
            raise SuperdeskApiError.preconditionFailedError(_('Client and server etags don\'t match'))
        except KeyError:
            raise SuperdeskApiError.badRequestError(_("Request for Auto-save must have _id"))
        return [docs[0]['_id']]
コード例 #37
0
 def validate_assignment_lock(self, item, user_id):
     if item.get('assignment_id'):
         assignment_update_data = self._get_assignment_data_on_archive_update(
             {}, item)
         if assignment_update_data.get('assignment'):
             assignment = assignment_update_data.get('assignment')
             if assignment and assignment.get('lock_user'):
                 if assignment['lock_session'] != get_auth(
                 )['_id'] or assignment['lock_user'] != user_id:
                     raise SuperdeskApiError.badRequestError(
                         message="Lock Failed: Related assignment is locked."
                     )
コード例 #38
0
    def process_query(self, doc):
        """
        Processes the Saved Search document
        """

        if not doc['filter'].get('query'):
            raise SuperdeskApiError.badRequestError(
                'Search cannot be saved without a filter!')

        return self.get_location(doc), build_elastic_query(
            {k: v
             for k, v in doc['filter']['query'].items() if k != 'repo'})
コード例 #39
0
ファイル: common.py プロジェクト: vanzeelandj/superdesk-core
    def update(self, id, updates, original):
        """
        Handles workflow of each Publish, Corrected, Killed and TakeDown.
        """
        try:
            user = get_user()
            auto_publish = updates.get('auto_publish', False)

            if original[ITEM_TYPE] == CONTENT_TYPE.COMPOSITE:
                self._publish_package_items(original, updates)
                self._update_archive(original,
                                     updates,
                                     should_insert_into_versions=auto_publish)
            else:
                self._publish_associated_items(original, updates)
                updated = deepcopy(original)
                updated.update(deepcopy(updates))

                if updates.get(ASSOCIATIONS):
                    self._refresh_associated_items(
                        updated,
                        skip_related=True)  # updates got lost with update

                signals.item_publish.send(self, item=updated)
                self._update_archive(original,
                                     updates,
                                     should_insert_into_versions=auto_publish)
                self.update_published_collection(
                    published_item_id=original[config.ID_FIELD],
                    updated=updated)

            from apps.publish.enqueue import enqueue_published
            enqueue_published.apply_async()

            push_notification('item:publish',
                              item=str(id),
                              unique_name=original['unique_name'],
                              desk=str(
                                  original.get('task', {}).get('desk', '')),
                              user=str(user.get(config.ID_FIELD, '')))
        except SuperdeskApiError:
            raise
        except KeyError as e:
            logger.exception(e)
            raise SuperdeskApiError.badRequestError(message=_(
                "Key is missing on article to be published: {exception}").
                                                    format(exception=str(e)))
        except Exception as e:
            logger.exception(e)
            raise SuperdeskApiError.internalError(
                message=_("Failed to publish the item: {id}").format(
                    id=str(id)),
                exception=e)
コード例 #40
0
 def _validate_item(self, original):
     """
     Raises an exception if the item is linked in a non-take package, the idea being that you don't whant to
     inadvertently remove the item from the packages, this force that to be done as a conscious action.
     :param original:
     :raise: An exception or nothing
     """
     if is_item_in_package(original):
         raise SuperdeskApiError.badRequestError(
             message="The item \"{}\" is in a package".format(
                 original.get('slugline', '')) +
             " it needs to be removed before the item can be spiked")
コード例 #41
0
def read_from_file(doc):
    """
    Plain text file
    One word per line
    UTF-8 encoding
    """

    content = doc.pop(DICTIONARY_FILE)
    if 'text/' not in content.mimetype:
        raise SuperdeskApiError.badRequestError(
            'A text dictionary file is required')
    return train(words(read(content)))
コード例 #42
0
    def _set_event_cancelled(updates, original, occur_cancel_state):
        if not EventsCancelService.validate_states(original):
            raise SuperdeskApiError.badRequestError(
                'Event not in valid state for cancellation')

        remove_lock_information(updates)
        updates.update({
            'state': WORKFLOW_STATE.CANCELLED,
            'occur_status': occur_cancel_state,
            'state_reason': updates.get('reason')
        })
        set_actioned_date_to_event(updates, original)
コード例 #43
0
 def _get_sort(self, req):
     """
     Returns the sort fields in a list based on the received request.
     """
     if not req or not req.sort:
         return [self.DEFAULT_SORT]
     sort_fields = req.sort.split(",")
     for field in sort_fields:
         if field not in self.SORT_FIELDS:
             raise SuperdeskApiError.badRequestError(
                 "Invalid sort field %s" % field)
     return sort_fields
コード例 #44
0
ファイル: broadcast.py プロジェクト: thnkloud9/superdesk-core
    def create(self, docs):
        service = get_resource_service(SOURCE)
        item_id = request.view_args['item_id']
        item = service.find_one(req=None, _id=item_id)
        doc = docs[0]

        self._valid_broadcast_item(item)

        desk_id = doc.get('desk')
        desk = None

        if desk_id:
            desk = get_resource_service('desks').find_one(req=None,
                                                          _id=desk_id)

        doc.pop('desk', None)
        doc['task'] = {}
        if desk:
            doc['task']['desk'] = desk.get(config.ID_FIELD)
            doc['task']['stage'] = desk.get('working_stage')

        doc['task']['user'] = get_user().get('_id')
        genre_list = get_resource_service('vocabularies').find_one(
            req=None, _id='genre') or {}
        broadcast_genre = [
            {
                'qcode': genre.get('qcode'),
                'name': genre.get('name')
            } for genre in genre_list.get('items', [])
            if genre.get('qcode') == BROADCAST_GENRE and genre.get('is_active')
        ]

        if not broadcast_genre:
            raise SuperdeskApiError.badRequestError(
                message="Cannot find the {} genre.".format(BROADCAST_GENRE))

        doc['broadcast'] = {
            'status': '',
            'master_id': item_id,
            'rewrite_id': item.get('rewritten_by')
        }

        doc['genre'] = broadcast_genre
        doc['family_id'] = item.get('family_id')

        for key in FIELDS_TO_COPY:
            doc[key] = item.get(key)

        resolve_document_version(document=doc, resource=SOURCE, method='POST')
        service.post(docs)
        insert_into_versions(id_=doc[config.ID_FIELD])
        build_custom_hateoas(CUSTOM_HATEOAS, doc)
        return [doc[config.ID_FIELD]]
コード例 #45
0
    def process_query(self, doc):
        """
        Processes the Saved Search document
        """

        if not doc["filter"].get("query"):
            raise SuperdeskApiError.badRequestError(
                _("Search cannot be saved without a filter!"))

        return self.get_location(doc), build_elastic_query(
            {k: v
             for k, v in doc["filter"]["query"].items() if k != "repo"})
コード例 #46
0
ファイル: service.py プロジェクト: vanzeelandj/superdesk-core
    def _validate_event_properties(self, doc):
        # Step to implement validation(s):
        # 1) define schema_event in resource (https://iptc.org/std/NewsML-G2/guidelines/#more-real-world-entities)
        # 2) create cerberus Validator based on the schema_event
        # 3) validate doc['properties'] using cerberus Validator instance
        # TODO if we want to have a case insensitive sort, please, add a proper index

        raise SuperdeskApiError.badRequestError(
            message="Request is not valid",
            payload={
                "cpnat_type": "concept type 'cpnat:event' is not supported"
            })
コード例 #47
0
 def _get_response(self, resp, *status):
     json = json_util.loads(resp.text)
     if resp.status_code not in status:
         if resp.status_code == 400:
             raise SuperdeskApiError.badRequestError(message=json)
         if resp.status_code == 409:
             raise SuperdeskApiError.conflictError(message=json)
         if resp.status_code == 404:
             raise SuperdeskApiError.notFoundError(message=json)
         if resp.status_code == 500:
             raise SuperdeskApiError.internalError(message=json)
     return json
コード例 #48
0
    def _valid_broadcast_item(self, item):
        """
        Broadcast item can only be created for Text or Pre-formatted item.
        Item state needs to be Published or Corrected
        :param dict item: Item from which the broadcast item will be created
        """
        if not item:
            raise SuperdeskApiError.notFoundError(
                message="Cannot find the requested item id.")

        if not item.get(ITEM_TYPE) in [
                CONTENT_TYPE.TEXT, CONTENT_TYPE.PREFORMATTED
        ]:
            raise SuperdeskApiError.badRequestError(
                message="Invalid content type.")

        if item.get(ITEM_STATE) not in [
                CONTENT_STATE.CORRECTED, CONTENT_STATE.PUBLISHED
        ]:
            raise SuperdeskApiError.badRequestError(
                message="Invalid content state.")
コード例 #49
0
    def create(self, docs, **kwargs):
        for doc in docs:
            email = doc.get('email')
            key = doc.get('token')
            password = doc.get('password')

            if key and password:
                return self.reset_password(doc)
            if email:
                return self.initialize_reset_password(doc, email)

            raise SuperdeskApiError.badRequestError('Either key:password or email must be provided')
コード例 #50
0
    def validate(self, item, user_id):
        get_resource_service('assignments').validate_assignment_action(item)
        # Validate workflow state
        if item.get('assigned_to').get('state') not in [
                ASSIGNMENT_WORKFLOW_STATE.IN_PROGRESS,
                ASSIGNMENT_WORKFLOW_STATE.SUBMITTED,
                ASSIGNMENT_WORKFLOW_STATE.ASSIGNED,
                ASSIGNMENT_WORKFLOW_STATE.COMPLETED
        ]:
            raise SuperdeskApiError.badRequestError(
                message="Assignment workflow state error.")

        if item.get('assigned_to').get(
                'state') == ASSIGNMENT_WORKFLOW_STATE.IN_PROGRESS:
            archive_item = get_resource_service('archive').find_one(
                req=None, assignment_id=item.get(config.ID_FIELD))
            if archive_item and archive_item.get(
                    'lock_user') and archive_item['lock_user'] != user_id:
                # archive item it locked by another user
                raise SuperdeskApiError.badRequestError(
                    message="Archive item is locked by another user.")
コード例 #51
0
    def _validate_routing_scheme(self, routing_scheme):
        """Validates routing scheme for the below:

            1. A routing scheme must have at least one rule.
            2. Every rule in the routing scheme must have name, filter and at least one action

        Will throw BadRequestError if any of the conditions fail.

        :param routing_scheme:
        """

        routing_rules = routing_scheme.get('rules', [])
        if len(routing_rules) == 0:
            raise SuperdeskApiError.badRequestError(
                message=_("A Routing Scheme must have at least one Rule"))
        for routing_rule in routing_rules:
            invalid_fields = [
                field for field in routing_rule.keys()
                if field not in ('name', 'filter', 'actions', 'schedule')
            ]

            if invalid_fields:
                raise SuperdeskApiError.badRequestError(message=_(
                    "A routing rule has invalid fields {fields}").format(
                        fields=invalid_fields))

            schedule = routing_rule.get('schedule')
            actions = routing_rule.get('actions')

            if routing_rule.get('name') is None:
                raise SuperdeskApiError.badRequestError(
                    message=_("A routing rule must have a name"))
            elif actions is None or len(actions) == 0 or (
                    actions.get('fetch') is None
                    and actions.get('publish') is None
                    and actions.get('exit') is None):
                raise SuperdeskApiError.badRequestError(
                    message=_("A routing rule must have actions"))
            else:
                self._validate_schedule(schedule)
コード例 #52
0
    def _validate_rewrite(self, original, update):
        """Validates the article to be rewritten.

        :param original: article to be rewritten
        :param update: article as the rewrite
        :raises: SuperdeskApiError
        """
        if not original:
            raise SuperdeskApiError.notFoundError(message='Cannot find the article')

        if original.get(EMBARGO):
            raise SuperdeskApiError.badRequestError("Rewrite of an Item having embargo isn't possible")

        if not original.get('event_id'):
            raise SuperdeskApiError.notFoundError(message='Event id does not exist')

        if original.get('rewritten_by'):
            raise SuperdeskApiError.badRequestError(message='Article has been rewritten before !')

        if not is_workflow_state_transition_valid('rewrite', original[ITEM_STATE]):
            raise InvalidStateTransitionError()

        if not TakesPackageService().is_last_takes_package_item(original):
            raise SuperdeskApiError.badRequestError(message="Only last take of the package can be rewritten.")

        if original.get('rewrite_of') and not (original.get(ITEM_STATE) in PUBLISH_STATES):
            raise SuperdeskApiError.badRequestError(message="Rewrite is not published. Cannot rewrite the story again.")

        if update:
            # in case of associate as update
            if update.get('rewrite_of'):
                raise SuperdeskApiError.badRequestError("Rewrite story has been used as update before !")

            if update.get(ITEM_STATE) in [CONTENT_STATE.PUBLISHED,
                                          CONTENT_STATE.CORRECTED,
                                          CONTENT_STATE.KILLED,
                                          CONTENT_STATE.SCHEDULED,
                                          CONTENT_STATE.SPIKED]:
                raise InvalidStateTransitionError()

            if update.get(ITEM_TYPE) not in [CONTENT_TYPE.TEXT, CONTENT_TYPE.PREFORMATTED]:
                raise SuperdeskApiError.badRequestError("Rewrite story can only be text or pre-formatted !")

            if update.get('genre') and \
                    any(genre.get('value', '').lower() == BROADCAST_GENRE.lower() for genre in update.get('genre')):
                raise SuperdeskApiError.badRequestError("Broadcast cannot be a update story !")

            if original.get('profile') and original.get('profile') != update.get('profile'):
                raise SuperdeskApiError.badRequestError("Rewrite item content profile does "
                                                        "not match with Original item.")
コード例 #53
0
    def create(self, docs, **kwargs):
        service = get_resource_service("archive")
        doc = docs[0]
        formatter_name = doc.get("formatter_name")

        if not formatter_name:
            raise SuperdeskApiError.badRequestError(
                _("Formatter name not found"))

        formatter = self._get_formatter(formatter_name)

        if not formatter:
            raise SuperdeskApiError.badRequestError(_("Formatter not found"))

        if "article_id" in doc:
            article_id = doc.get("article_id")
            article = service.find_one(req=None, _id=article_id)

            if not article:
                raise SuperdeskApiError.badRequestError(
                    _("Article not found!"))

            try:
                self._validate(article)
                sequence, formatted_doc = formatter.format(
                    apply_schema(article), {"_id": "0"}, None)[0]
                formatted_doc = formatted_doc.replace("''", "'")

                # respond only with the formatted output if output_field is configured
                if hasattr(formatter, "output_field"):
                    formatted_doc = json.loads(formatted_doc)
                    formatted_doc = formatted_doc.get(formatter.output_field,
                                                      "").replace("''", "'")
            except Exception as ex:
                logger.exception(ex)
                raise SuperdeskApiError.badRequestError(
                    _("Error in formatting article: {exception}").format(
                        exception=str(ex)))

            return [{"formatted_doc": formatted_doc}]
コード例 #54
0
ファイル: resend.py プロジェクト: superdesk/superdesk-core
    def _validate_article(self, article_id, article_version):
        article = get_resource_service(ARCHIVE).find_one(req=None,
                                                         _id=article_id)

        if app.config.get("CORRECTIONS_WORKFLOW") and article.get(
                ITEM_STATE) == "correction":
            publish_service = get_resource_service("published")
            article = publish_service.find_one(req=None,
                                               guid=article.get("guid"),
                                               state="being_corrected")

        if not article:
            raise SuperdeskApiError.badRequestError(
                message=_("Story couldn't be found!"))

        if article[ITEM_TYPE] not in [
                CONTENT_TYPE.TEXT, CONTENT_TYPE.PREFORMATTED
        ]:
            raise SuperdeskApiError.badRequestError(
                message=_("Only text stories can be resent!"))

        if article.get(ITEM_STATE) not in [
                CONTENT_STATE.PUBLISHED,
                CONTENT_STATE.CORRECTED,
                CONTENT_STATE.KILLED,
                CONTENT_STATE.BEING_CORRECTED,
        ]:
            raise SuperdeskApiError.badRequestError(message=_(
                "Only published, corrected or killed stories can be resent!"))

        if article[config.VERSION] != article_version:
            raise SuperdeskApiError.badRequestError(message=_(
                "Please use the newest version {version} to resend!").format(
                    version=article[config.VERSION]))

        if article.get("rewritten_by"):
            raise SuperdeskApiError.badRequestError(
                message=_("Updated story cannot be resent!"))

        return article
コード例 #55
0
    def create(self, docs, **kwargs):
        service = get_resource_service('content_filters')
        for doc in docs:
            filter_id = doc.get('filter_id')
            if filter_id:
                content_filter = service.find_one(req=None, _id=filter_id)
            else:
                content_filter = doc.get('filter')

            if not content_filter:
                raise SuperdeskApiError.badRequestError('Content filter not found')

            if 'article_id' in doc:
                article_id = doc.get('article_id')
                article = get_resource_service('archive').find_one(req=None, _id=article_id)
                if not article:
                    article = get_resource_service('ingest').find_one(req=None, _id=article_id)
                    if not article:
                        raise SuperdeskApiError.badRequestError('Article not found!')
                try:
                    doc['match_results'] = service.does_match(content_filter, article)
                except Exception as ex:
                    raise SuperdeskApiError.\
                        badRequestError('Error in testing article: {}'.format(str(ex)))
            else:
                try:
                    if doc.get('return_matching', True):
                        query = service.build_elastic_query(content_filter)
                    else:
                        query = service.build_elastic_not_filter(content_filter)
                    query['sort'] = [{'versioncreated': 'desc'}]
                    query['size'] = 200
                    req = ParsedRequest()
                    req.args = {'source': json.dumps(query)}
                    doc['match_results'] = list(get_resource_service('archive').get(req=req, lookup=None))
                except Exception as ex:
                    raise SuperdeskApiError.\
                        badRequestError('Error in testing archive: {}'.format(str(ex)))

        return [len(docs)]
コード例 #56
0
    def create_crop(self, original, crop_name, crop_data):
        """
        Create a new crop based on the crop co-ordinates
        :param original: Article to add the crop
        :param crop_name: Name of the crop
        :param doc: Crop details
        :raises SuperdeskApiError.badRequestError
        :return dict: modified renditions
        """
        renditions = original.get('renditions', {})
        original_crop = renditions.get(crop_name, {})
        fields = ('CropLeft', 'CropTop', 'CropRight', 'CropBottom')
        crop_created = False

        if any(
                crop_data.get(name) != original_crop.get(name)
                for name in fields):
            original_image = renditions.get('original', {})
            original_file = superdesk.app.media.fetch_rendition(original_image)
            if not original_file:
                raise SuperdeskApiError.badRequestError(
                    'Original file couldn\'t be found')

            try:
                cropped, out = crop_image(original_file, crop_name, crop_data)

                if not cropped:
                    raise SuperdeskApiError.badRequestError(
                        'Saving crop failed.')

                renditions[crop_name] = self._save_cropped_image(
                    out, original_image, crop_data)
                crop_created = True
            except SuperdeskApiError:
                raise
            except Exception as ex:
                raise SuperdeskApiError.badRequestError(
                    'Generating crop failed: {}'.format(str(ex)))

        return renditions, crop_created
コード例 #57
0
    def create(self, docs, **kwargs):
        doc = docs[0] if len(docs) > 0 else {}
        template_name = doc.get("template_name")
        item = doc.get("item") or {}
        item["desk_name"] = get_resource_service("desks").get_desk_name(
            item.get("task", {}).get("desk"))

        if not template_name:
            SuperdeskApiError.badRequestError(message="Invalid Template Name")

        if not item:
            SuperdeskApiError.badRequestError(message="Invalid Item")

        template = superdesk.get_resource_service(
            "content_templates").get_template_by_name(template_name)
        if not template:
            SuperdeskApiError.badRequestError(message="Invalid Template")

        updates = render_content_template(item, template)
        item.update(updates)

        editor_utils.generate_fields(item, reload=True)

        if template_name == "kill":
            apply_null_override_for_kill(item)

        docs[0] = item
        build_custom_hateoas(CUSTOM_HATEOAS, docs[0])
        return [docs[0].get(config.ID_FIELD)]
コード例 #58
0
ファイル: client_modules.py プロジェクト: dev-tsoni/liveblog
def _check_for_unknown_params(request, whitelist, allow_filtering=True):
    """Check if the request contains only allowed parameters.

    :param req: object representing the HTTP request
    :type req: `eve.utils.ParsedRequest`
    :param whitelist: iterable containing the names of allowed parameters.
    :param bool allow_filtering: whether or not the filtering parameter is
        allowed (True by default). Used for disallowing it when retrieving
        a single object.

    :raises SuperdeskApiError.badRequestError:
        * if the request contains a parameter that is not whitelisted
        * if the request contains more than one value for any of the
            parameters
    """
    if not request or not getattr(request, 'args'):
        return
    request_params = request.args or MultiDict()

    if not allow_filtering:
        err_msg = ("Filtering{} is not supported when retrieving a "
                   "single object (the \"{param}\" parameter)")

        if 'start_date' in request_params.keys():
            message = err_msg.format(' by date range', param='start_date')
            raise SuperdeskApiError.badRequestError(message=message)

        if 'end_date' in request_params.keys():
            message = err_msg.format(' by date range', param='end_date')
            raise SuperdeskApiError.badRequestError(message=message)

    for param_name in request_params.keys():
        if param_name not in whitelist:
            raise SuperdeskApiError.badRequestError(
                message="Unexpected parameter ({})".format(param_name))

        if len(request_params.getlist(param_name)) > 1:
            message = "Multiple values received for parameter ({})"
            raise SuperdeskApiError.badRequestError(
                message=message.format(param_name))
コード例 #59
0
    def create(self, docs, **kwargs):
        service = get_resource_service('archive')
        doc = docs[0]
        formatter_name = doc.get('formatter_name')

        if not formatter_name:
            raise SuperdeskApiError.badRequestError(
                _('Formatter name not found'))

        formatter = self._get_formatter(formatter_name)

        if not formatter:
            raise SuperdeskApiError.badRequestError(_('Formatter not found'))

        if 'article_id' in doc:
            article_id = doc.get('article_id')
            article = service.find_one(req=None, _id=article_id)

            if not article:
                raise SuperdeskApiError.badRequestError(
                    _('Article not found!'))

            try:
                self._validate(article)
                sequence, formatted_doc = formatter.format(
                    apply_schema(article), {'_id': '0'}, None)[0]
                formatted_doc = formatted_doc.replace('\'\'', '\'')

                # respond only with the formatted output if output_field is configured
                if hasattr(formatter, 'output_field'):
                    formatted_doc = json.loads(formatted_doc)
                    formatted_doc = formatted_doc.get(formatter.output_field,
                                                      '').replace(
                                                          '\'\'', '\'')
            except Exception as ex:
                logger.exception(ex)
                raise SuperdeskApiError.\
                    badRequestError(_('Error in formatting article: {exception}').format(exception=str(ex)))

            return [{'formatted_doc': formatted_doc}]
コード例 #60
0
    def create(self, docs, **kwargs):
        doc = docs[0] if len(docs) > 0 else {}
        template_name = doc.get('template_name')
        item = doc.get('item') or {}
        item['desk_name'] = get_resource_service('desks').get_desk_name(item.get('task', {}).get('desk'))

        if not template_name:
            SuperdeskApiError.badRequestError(message='Invalid Template Name')

        if not item:
            SuperdeskApiError.badRequestError(message='Invalid Item')

        template = superdesk.get_resource_service('content_templates').get_template_by_name(template_name)
        if not template:
            SuperdeskApiError.badRequestError(message='Invalid Template')

        updates = render_content_template(item, template)
        item.update(updates)

        if template_name == 'kill':
            apply_null_override_for_kill(item)

        docs[0] = item
        build_custom_hateoas(CUSTOM_HATEOAS, docs[0])
        return [docs[0].get(config.ID_FIELD)]