コード例 #1
0
    def get(self, req, lookup):
        field = request.args.get('field', 'slugline')
        language = request.args.get('language',
                                    app.config.get('DEFAULT_LANGUAGE', 'en'))

        if not app.config.get(SETTING_ENABLED):
            raise SuperdeskApiError(_("Archive autocomplete is not enabled"),
                                    404)

        if field not in self.allowed_fields:
            raise SuperdeskApiError(
                _("Field %(field)s is not allowed", field=field), 400)

        _filter = {
            'state': 'published',
            'language': language,
            'versioncreated': {
                '$gte':
                utcnow() - timedelta(
                    days=app.config[SETTING_DAYS],
                    hours=app.config[SETTING_HOURS],
                )
            },
        }
        values = self.backend._backend(
            'archive').driver.db['archive'].distinct(field, _filter)
        sorted_values = sorted(values, key=locale.strxfrm)
        docs = [{'value': value} for value in sorted_values]
        return ListCursor(docs)
コード例 #2
0
    def get(self, req, lookup):
        field = request.args.get("field", "slugline")
        language = request.args.get("language",
                                    app.config.get("DEFAULT_LANGUAGE", "en"))

        if not app.config.get(SETTING_ENABLED):
            raise SuperdeskApiError(_("Archive autocomplete is not enabled"),
                                    404)

        if field not in self.allowed_fields:
            raise SuperdeskApiError(
                _("Field %(field)s is not allowed", field=field), 400)

        _filter = {
            "state": "published",
            "language": language,
            "versioncreated": {
                "$gte":
                utcnow() - timedelta(
                    days=app.config[SETTING_DAYS],
                    hours=app.config[SETTING_HOURS],
                )
            },
        }
        values = self.backend._backend(
            "archive").driver.db["archive"].distinct(field, _filter)
        sorted_values = sorted(values, key=locale.strxfrm)
        docs = [{"value": value} for value in sorted_values]
        return ListCursor(docs)
コード例 #3
0
    def validate_event(self, event):
        """Validate the event

        @:param dict event: event created or updated
        """
        self._validate_multiday_event_duration(event)
        self._validate_dates(event)

        if len(event.get('calendars', [])) > 0:
            existing_calendars = get_resource_service('vocabularies').find_one(
                req=None, _id='event_calendars')
            for calendar in event['calendars']:
                cal = [
                    x for x in existing_calendars.get('items', [])
                    if x['qcode'] == calendar.get('qcode')
                ]
                if not cal:
                    raise SuperdeskApiError(message="Calendar does not exist.")
                if not cal[0].get('is_active'):
                    raise SuperdeskApiError(
                        message="Disabled calendar cannot be selected.")

            # Remove duplicated calendars
            uniq_qcodes = list_uniq_with_order(
                [o['qcode'] for o in event['calendars']])
            event['calendars'] = [
                cal for cal in existing_calendars.get('items', [])
                if cal['qcode'] in uniq_qcodes
            ]
コード例 #4
0
    def on_create(self, docs):
        for doc in docs:
            self._validate_items(doc)

            if doc.get("field_type") and doc["_id"] in self.system_keys:
                raise SuperdeskApiError(message="{} is in use".format(doc["_id"]), payload={"_id": {"conflict": 1}})

            if self.find_one(req=None, **{"_id": doc["_id"], "_deleted": True}):
                raise SuperdeskApiError(
                    message="{} is used by deleted vocabulary".format(doc["_id"]), payload={"_id": {"deleted": 1}}
                )
コード例 #5
0
    def on_create(self, docs):
        for doc in docs:
            self._validate_items(doc)

            if doc.get('field_type') and doc['_id'] in self.system_keys:
                raise SuperdeskApiError(
                    message='{} is in use'.format(doc['_id']),
                    payload={'_id': {'conflict': 1}})

            if self.find_one(req=None, **{'_id': doc['_id'], '_deleted': True}):
                raise SuperdeskApiError(
                    message='{} is used by deleted vocabulary'.format(doc['_id']),
                    payload={'_id': {'deleted': 1}})
コード例 #6
0
 def post(self, file_storage):
     try:
         video_file = {'file': (file_storage.filename, file_storage.read(), file_storage.mimetype)}
         resp = self.session.post(self.get_base_url(), files=video_file)
         return self._get_response(resp, 201)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #7
0
    def _validate_poi(self, original, updates, crop_name):
        """
        Validate the crop point of interest in the renditions dictionary for the given crop
        :param dict original: original item
        :param dict updates: updated renditions
        """
        renditions = original.get('renditions', {})
        updated_renditions = updates.get('renditions', {})
        original_image = deepcopy(renditions['original'])
        original_image.update(updated_renditions.get('original', {}))
        if 'poi' in updates:
            if 'x' not in updates['poi'] or 'y' not in updates['poi']:
                del updates['poi']
                return
            poi = updates['poi']
        elif 'poi' not in original:
            return
        else:
            if crop_name not in updated_renditions:
                return
            poi = original['poi']

        crop_data = updated_renditions[
            crop_name] if crop_name in updated_renditions else renditions[
                crop_name]
        orig_poi_x = int(original_image['width'] * poi['x'])
        orig_poi_y = int(original_image['height'] * poi['y'])

        if orig_poi_y < crop_data.get('CropTop', 0) \
                or orig_poi_y > crop_data.get('CropBottom', original_image['height']) \
                or orig_poi_x < crop_data.get('CropLeft', 0) \
                or orig_poi_x > crop_data.get('CropRight', original_image['width']):
            raise SuperdeskApiError(
                'Point of interest outside the crop %s limits' % crop_name)
コード例 #8
0
 def on_create(self, docs):
     for doc in docs:
         self._validate_items(doc)
         if doc.get('field_type') and doc['_id'] in self.system_keys:
             raise SuperdeskApiError(
                 message='{} is in use'.format(doc['_id']),
                 payload={'_id': {'conflict': 1}})
コード例 #9
0
ファイル: crop.py プロジェクト: superdesk/superdesk-core
    def _validate_poi(self, original, updates, crop_name):
        """Validate the crop point of interest in the renditions dictionary for the given crop

        :param dict original: original item
        :param dict updates: updated renditions
        """
        renditions = original.get("renditions", {})
        updated_renditions = updates.get("renditions", {})
        original_image = deepcopy(renditions["original"])
        original_image.update(updated_renditions.get("original", {}))
        if "poi" in updates:
            if "x" not in updates["poi"] or "y" not in updates["poi"]:
                del updates["poi"]
                return
            poi = updates["poi"]
        elif "poi" not in original:
            return
        else:
            if crop_name not in updated_renditions:
                return
            poi = original["poi"]

        crop_data = updated_renditions[crop_name] if crop_name in updated_renditions else renditions[crop_name]
        orig_poi_x = int(original_image["width"] * poi["x"])
        orig_poi_y = int(original_image["height"] * poi["y"])

        if (
            orig_poi_y < crop_data.get("CropTop", 0)
            or orig_poi_y > crop_data.get("CropBottom", original_image["height"])
            or orig_poi_x < crop_data.get("CropLeft", 0)
            or orig_poi_x > crop_data.get("CropRight", original_image["width"])
        ):
            raise SuperdeskApiError("Point of interest outside the crop %s limits" % crop_name)
コード例 #10
0
 def _get_timeline_thumbnails(self, project_id, amount):
     try:
         params = {'type': 'timeline', 'amount': amount}
         resp = self.session.get(self._url(project_id, 'thumbnails'),
                                 params=params)
         return self._get_response(resp, 202)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #11
0
 def post_preview_thumbnail(self, project_id, file):
     try:
         payloads = {
             'file': file,
         }
         resp = self.session.post(self._url(project_id, 'thumbnails'), json=payloads)
         return self._get_response(resp, 200)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #12
0
 def _delete(self, project_id):
     try:
         resp = self.session.delete(self._url(project_id))
         if resp.status_code != 204:
             logger.exception(resp.text)
             resp.raise_for_status()
         return True
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #13
0
 def _post_preview_thumbnail(self, project_id, file_storage):
     try:
         video_file = {
             'file': (file_storage.filename, file_storage.read(),
                      file_storage.mimetype)
         }
         resp = self.session.post(self._url(project_id, 'thumbnails'),
                                  files=video_file)
         return self._get_response(resp, 200)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #14
0
    def on_create(self, docs):
        """Create corresponding item on file upload."""

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")
            # check content type of video by python-magic
            content_type = magic.from_buffer(doc['media'].read(1024),
                                             mime=True)
            doc['media'].seek(0)
            file_type = content_type.split('/')[0]
            if file_type == 'video' and app.config.get("VIDEO_SERVER_ENABLE"):
                if not self.videoEditor.check_video_server():
                    raise SuperdeskApiError(
                        message="Cannot connect to videoserver",
                        status_code=500)
                # upload media to video server
                res, renditions, metadata = self.upload_file_to_video_server(
                    doc)
                # get thumbnails for timeline bar
                self.videoEditor.get_timeline_thumbnails(doc.get('media'), 40)
            else:
                file, content_type, metadata = self.get_file_from_document(doc)
                inserted = [doc['media']]
                # if no_custom_crops is set to False the custom crops are generated automatically on media upload
                # see (SDESK-4742)
                rendition_spec = get_renditions_spec(
                    no_custom_crops=app.config.get("NO_CUSTOM_CROPS"))
                with timer('archive:renditions'):
                    renditions = generate_renditions(file, doc['media'],
                                                     inserted, file_type,
                                                     content_type,
                                                     rendition_spec,
                                                     url_for_media)
            try:
                self._set_metadata(doc)
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                doc[ITEM_STATE] = CONTENT_STATE.PROGRESS
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                set_filemeta(doc, metadata)
                add_activity('upload',
                             'uploaded media {{ name }}',
                             'archive',
                             item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                if res:
                    self.videoEditor.delete(res.get('_id'))
                abort(500)
コード例 #15
0
ファイル: events.py プロジェクト: ride90/superdesk-planning
    def _validate_convert_to_recurring(self, updates, original):
        """Validates if the convert to recurring action is valid.

        :param updates:
        :param original:
        :return:
        """
        if not original:
            return

        if original.get(LOCK_ACTION) == 'convert_recurring' and \
                updates.get('dates', {}).get('recurring_rule', None) is None:
            raise SuperdeskApiError(
                message=
                'Event recurring rules are mandatory for convert to recurring action.'
            )
        if original.get(LOCK_ACTION) == 'convert_recurring' and original.get(
                'recurrence_id'):
            raise SuperdeskApiError(
                message='Event is already converted to recurring event.')
コード例 #16
0
ファイル: events.py プロジェクト: ride90/superdesk-planning
    def _validate_dates(self, updates, original=None):
        """Validate the dates

        @:param dict event:
        """
        event = updates if updates.get('dates') or not original else original
        start_date = event.get('dates', {}).get('start')
        end_date = event.get('dates', {}).get('end')

        if not start_date or not end_date:
            raise SuperdeskApiError(
                message="Event START DATE and END DATE are mandatory.")

        if end_date < start_date:
            raise SuperdeskApiError(
                message="END TIME should be after START TIME")

        if event.get('dates', {}).get('recurring_rule') and not event['dates']['recurring_rule'].get('until') and \
                not event['dates']['recurring_rule'].get('count'):
            raise SuperdeskApiError(
                message="Recurring event should have an end (until or count)")
コード例 #17
0
    def _validate_dates(self, event):
        """Validate the dates

        @:param dict event:
        """
        start_date = event.get('dates', {}).get('start')
        end_date = event.get('dates', {}).get('end')

        if not start_date or not end_date:
            return

        if end_date < start_date:
            raise SuperdeskApiError(
                message="END TIME should be after START TIME")
コード例 #18
0
 def get_preview_thumbnail(self, project_id, position=0, crop=None, rotate=None):
     try:
         params = {
             "type": "preview",
             "position": position
         }
         if crop:
             params["crop"] = crop
         if rotate:
             params["rotate"] = rotate
         resp = self.session.get(self._url(project_id, 'thumbnails'), params=params)
         return self._get_response(resp, 202)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #19
0
def raise_sams_error(response: Response):
    """If an error was raised from SAMS, attempts to re-raise it as a Superdesk error

    Raising Superdesk errors are to be used outside the SAMS workspace functionality
    i.e. with the Eve MediaStorage provider functionality
    """

    try:
        response.raise_for_status()
    except HTTPError as http_error:
        error = response.json()
        raise SuperdeskApiError(
            status_code=response.status_code,
            message=error.get("description") or "",
            payload=error,
            exception=http_error,
        )
コード例 #20
0
ファイル: events.py プロジェクト: ride90/superdesk-planning
    def _validate_multiday_event_duration(self, event):
        """Validate that the multiday event duration is not greater than PLANNING_MAX_MULTI_DAY_DURATION

        @:param dict event: event created or updated
        """
        max_duration = get_event_max_multi_day_duration(app)
        if not max_duration > 0:
            return

        if not event.get('dates'):
            return

        event_duration = event.get('dates').get('end') - event.get(
            'dates').get('start')
        if event_duration.days > max_duration:
            raise SuperdeskApiError(
                message="Event duration is greater than {} days.".format(
                    max_duration))
コード例 #21
0
    def validate_planning(self, updates, original=None):
        if (not original and not updates.get('planning_date')) or \
                ('planning_date' in updates and updates['planning_date'] is None):
            raise SuperdeskApiError(message="Planning item should have a date")

        # Validate if agendas being added are enabled agendas
        agenda_service = get_resource_service('agenda')
        for agenda_id in updates.get('agendas', []):
            agenda = agenda_service.find_one(req=None, _id=str(agenda_id))
            if not agenda:
                raise SuperdeskApiError.forbiddenError(
                    'Agenda \'{}\' does not exist'.format(agenda.get('name')))
            if not agenda.get('is_enabled', False):
                raise SuperdeskApiError.forbiddenError(
                    'Agenda \'{}\' is not enabled'.format(agenda.get('name')))

        # Remove duplicate agendas
        if len(updates.get('agendas', [])) > 0:
            updates['agendas'] = list_uniq_with_order(updates['agendas'])
コード例 #22
0
    def validate_item(doc, event, new_post_status):
        if new_post_status == POST_STATE.USABLE and event and event.get(
                'pubstatus') == POST_STATE.CANCELLED:
            raise SuperdeskApiError(
                message=
                "Can't post the planning item as event is already unposted/cancelled."
            )

        errors = get_resource_service('planning_validator').post([{
            'validate_on_post':
            True,
            'type':
            'planning',
            'validate':
            doc
        }])[0]

        if errors:
            # We use abort here instead of raising SuperdeskApiError.badRequestError
            # as eve handles error responses differently between POST and PATCH methods
            abort(400, description=errors)
コード例 #23
0
 def on_delete(self, doc):
     if doc.get('is_used'):
         raise SuperdeskApiError(status_code=202, payload={"is_used": True})
コード例 #24
0
    def _validate(self, doc):
        assignment = get_resource_service('assignments').find_one(
            req=None, _id=doc.get('assignment_id'))

        if not assignment:
            raise SuperdeskApiError.badRequestError('Assignment not found.')

        item = get_resource_service('archive').find_one(req=None,
                                                        _id=doc.get('item_id'))

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

        if not doc.get('force') and item.get('assignment_id'):
            raise SuperdeskApiError.badRequestError(
                'Content is already linked to an assignment. Cannot link assignment and content.'
            )

        if not is_assigned_to_a_desk(item):
            raise SuperdeskApiError.badRequestError(
                'Content not in workflow. Cannot link assignment and content.')

        if not item.get('rewrite_of'):
            delivery = get_resource_service('delivery').find_one(
                req=None, assignment_id=ObjectId(doc.get('assignment_id')))

            if delivery:
                raise SuperdeskApiError.badRequestError(
                    'Content already exists for the assignment. Cannot link assignment and content.'
                )

            # scheduled update validation
            if assignment.get('scheduled_update_id'):
                raise SuperdeskApiError.badRequestError(
                    'Only updates can be linked to a scheduled update assignment'
                )

        coverage = get_coverage_for_assignment(assignment)
        allowed_states = [
            ASSIGNMENT_WORKFLOW_STATE.IN_PROGRESS,
            ASSIGNMENT_WORKFLOW_STATE.COMPLETED
        ]
        if (coverage and len(coverage.get('scheduled_updates')) > 0
                and str(assignment['_id']) != str(
                    (coverage.get('assigned_to') or {}).get('assignment_id'))):
            if (coverage.get('assigned_to')
                    or {}).get('state') not in allowed_states:
                raise SuperdeskApiError(
                    'Previous coverage is not linked to content.')

            # Check all previous scheduled updated to be linked/completed
            for s in coverage.get('scheduled_updates'):
                assigned_to = (s.get('assigned_to') or {})
                if str(assigned_to.get('assignment_id')) == str(
                        doc.get('assignment_id')):
                    break

                if assigned_to.get('state') not in allowed_states:
                    raise SuperdeskApiError(
                        'Previous scheduled-update pending content-linking/completion'
                    )
コード例 #25
0
 def is_valid(self, doc):
     """Check if the filter is valid"""
     if not doc.get('calendars') and not doc.get('agendas'):
         raise SuperdeskApiError(message="Either Calendar or Agenda is required.")
コード例 #26
0
 def on_delete(self, doc):
     if doc.get('is_used'):
         raise SuperdeskApiError(status_code=202, payload={"is_used": True})
     remove_profile_from_templates(doc)
     remove_profile_from_desks(doc)
コード例 #27
0
ファイル: common.py プロジェクト: sfcaru/liveblog
def check_comment_length(text):
    if not 1 <= len(text) <= 300:
        raise SuperdeskApiError(
            payload=
            'Allowed length: between 1 and 300. You exceeded the allowed length'
        )
コード例 #28
0
 def _get_paginate(self, page):
     try:
         resp = self.session.get(self.get_base_url(), params={'page': page})
         return self._get_response(resp, 200)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #29
0
 def _get(self, project_id):
     try:
         resp = self.session.get(self._url(project_id))
         return self._get_response(resp, 200)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)
コード例 #30
0
 def _put(self, project_id, updates):
     try:
         resp = self.session.put(self._url(project_id), json=updates)
         return self._get_response(resp, 202)
     except ConnectionError as ex:
         raise SuperdeskApiError(message=ex.args[0], status_code=500)