Example #1
0
def unlock_asset(asset_id):
    docs = request.json
    unlock_asset_response = get_sams_client().assets.unlock_asset(
        item_id=asset_id, external_user_id=get_user_id(True), external_session_id=get_auth()["_id"], docs=docs
    )
    if unlock_asset_response.status_code == 200:
        push_notification(
            "sams:asset:unlock_asset",
            item_id=asset_id,
            user_id=get_user_id(True),
            session_id=get_auth()["_id"],
            _etag=unlock_asset_response.json()["_etag"],
            extension="sams",
        )
    return unlock_asset_response.json(), unlock_asset_response.status_code
    def create(self, docs):
        ids = []
        production = get_resource_service('archive')
        for doc in docs:
            item_type = doc.pop('type')
            item_list = get_items(doc.pop('items', []), item_type)
            desk = get_resource_service('desks').find_one(req=None, _id=doc.pop('desk')) or {}
            article_template = doc.pop('article_template', None)
            if article_template:
                content_template = superdesk.get_resource_service('content_templates').find_one(
                    req=None, _id=article_template) or {}
            else:
                content_template = get_desk_template(desk)

            item = get_item_from_template(content_template)
            item[current_app.config['VERSION']] = 1
            item.setdefault('type', 'text')
            item.setdefault('slugline', 'Planning' if item_type == 'planning' else 'Event')
            item['task'] = {
                'desk': desk.get('_id'),
                'user': get_user_id(),
                'stage': desk.get('working_stage'),
            }
            item_from_template = generate_text_item(item_list, doc.pop('template', None), item_type)
            for key, val in item_from_template.items():
                placeholder = PLACEHOLDER_HTML if '_html' in key else PLACEHOLDER_TEXT
                if item.get(key) and placeholder in item[key]:
                    item[key] = item[key].replace(placeholder, val)
                else:
                    item[key] = val
            ids = production.post([item])
            insert_into_versions(doc=item)
            doc.update(item)
            ids.append(doc['_id'])
        return ids
    def create(self, docs, **kwargs):
        guid_of_item_to_be_copied = request.view_args["guid"]

        guid_of_copied_items = []

        for doc in docs:
            archive_service = get_resource_service(ARCHIVE)

            archived_doc = archive_service.find_one(req=None, _id=guid_of_item_to_be_copied)
            if not archived_doc:
                raise SuperdeskApiError.notFoundError(
                    _("Fail to found item with guid: {guid}").format(guid=guid_of_item_to_be_copied)
                )

            current_desk_of_item = archived_doc.get("task", {}).get("desk")
            if current_desk_of_item and not app.config["WORKFLOW_ALLOW_COPY_TO_PERSONAL"]:
                raise SuperdeskApiError.preconditionFailedError(message=_("Copy is not allowed on items in a desk."))
            elif current_desk_of_item:
                archived_doc["task"] = {}
                archived_doc["original_creator"] = get_user_id()

            if not is_workflow_state_transition_valid("copy", archived_doc[ITEM_STATE]):
                raise InvalidStateTransitionError()

            new_guid = archive_service.duplicate_content(archived_doc)
            guid_of_copied_items.append(new_guid)

        if kwargs.get("notify", True):
            user = get_user()
            push_notification("item:copy", copied=1, user=str(user.get(config.ID_FIELD, "")))

        return guid_of_copied_items
Example #4
0
 def on_update(self, updates, original):
     updated = deepcopy(original)
     updated.update(updates)
     self.is_valid(updated)
     user_id = get_user_id()
     if user_id:
         updates['version_creator'] = user_id
 def _push_notification(doc, operation):
     push_notification('savedreports:update',
                       report_type=doc['report'],
                       operation=operation,
                       report_id=str(doc.get('_id')),
                       user_id=str(get_user_id()),
                       session_id=str(get_auth().get('_id')))
    def validate(self, updates, original):
        """
        Generic validation for event actions

        A lock must be held by the user in their current session
        As well as the lock must solely be for the action being processed,
        i.e. lock_action='update_time'
        """
        if not original:
            raise SuperdeskApiError.notFoundError()

        if self.REQUIRE_LOCK:
            user_id = get_user_id()
            session_id = get_auth().get(config.ID_FIELD, None)

            lock_user = original.get(LOCK_USER, None)
            lock_session = original.get(LOCK_SESSION, None)
            lock_action = original.get(LOCK_ACTION, None)

            if not lock_user:
                raise SuperdeskApiError.forbiddenError(
                    message='The event must be locked')
            elif str(lock_user) != str(user_id):
                raise SuperdeskApiError.forbiddenError(
                    message='The event is locked by another user')
            elif str(lock_session) != str(session_id):
                raise SuperdeskApiError.forbiddenError(
                    message='The event is locked by you in another session')
            elif str(lock_action) != self.ACTION:
                raise SuperdeskApiError.forbiddenError(
                    message='The lock must be for the `{}` action'.format(
                        self.ACTION.lower().replace('_', ' ')))

        get_resource_service('events').validate_event(updates, original)
Example #7
0
def delete(item_id):
    """
    Uses item_id and deletes the corresponding asset
    """
    try:
        etag = request.headers["If-Match"]
    except KeyError:
        raise SuperdeskApiError.badRequestError(
            "If-Match field missing in header")

    if get_attachments_from_asset_id(item_id).count():
        raise SuperdeskApiError.badRequestError(
            _("Asset is attached to a news item, cannot delete"))

    delete_response = get_sams_client().assets.delete(
        item_id=item_id, headers={"If-Match": etag})
    if delete_response.status_code != 204:
        return delete_response.json(), delete_response.status_code
    if delete_response.status_code == 204:
        push_notification(
            "sams:asset:deleted",
            item_id=item_id,
            user_id=get_user_id(True),
            session_id=get_auth()["_id"],
            extension="sams",
        )
    return "", delete_response.status_code
Example #8
0
    def on_updated(self, updates, original):
        # If this Event was converted to a recurring series
        # Then update all associated Planning items with the recurrence_id
        if updates.get('recurrence_id') and not original.get('recurrence_id'):
            get_resource_service('planning').on_event_converted_to_recurring(
                updates, original)

        if not updates.get('duplicate_to'):
            posted = update_post_item(updates, original)
            if posted:
                new_event = get_resource_service('events').find_one(
                    req=None, _id=original.get(config.ID_FIELD))
                updates['_etag'] = new_event['_etag']
                updates['state_reason'] = new_event.get('state_reason')

        if original.get(
                'lock_user'
        ) and 'lock_user' in updates and updates.get('lock_user') is None:
            # when the event is unlocked by the patch.
            push_notification('events:unlock',
                              item=str(original.get(config.ID_FIELD)),
                              user=str(get_user_id()),
                              lock_session=str(get_auth().get('_id')),
                              etag=updates['_etag'],
                              recurrence_id=original.get('recurrence_id')
                              or None)

        self.delete_event_files(updates, original)

        if 'location' not in updates and original.get('location'):
            updates['location'] = original['location']

        self._enhance_event_item(updates)
Example #9
0
 def on_deleted(self, doc):
     push_notification(
         'events:delete',
         item=str(doc.get(config.ID_FIELD)),
         user=str(get_user_id()),
         lock_session=str(get_auth().get('_id')),
     )
Example #10
0
def update(item_id):
    """
    Uses item_id and updates the corresponding asset
    """
    try:
        etag = request.headers["If-Match"]
    except KeyError:
        raise SuperdeskApiError.badRequestError("If-Match field missing in header")

    if request.files.get("binary"):
        # The binary data was supplied so this must be a multipart request
        # Get the updates from the `request.form` attribute
        files = {"binary": request.files["binary"]}
        updates = request.form.to_dict()
    else:
        # Only the metadata was supplied so this must be a standard JSON request
        # Get the updates from the `request.get_json` function
        files = {}
        updates = request.get_json()

    update_response = get_sams_client().assets.update(
        item_id=item_id, updates=updates, headers={"If-Match": etag}, files=files, external_user_id=get_user_id(True)
    )
    if update_response.status_code == 200:
        push_notification(
            "sams:asset:updated",
            item_id=update_response.json()["_id"],
            user_id=get_user_id(True),
            session_id=get_auth()["_id"],
            _etag=update_response.json()["_etag"],
            extension="sams",
        )
    return update_response.json(), update_response.status_code
Example #11
0
 def _push_notification(self, _id, event_name):
     """Push socket notifiction"""
     push_notification(
         event_name,
         item=str(_id),
         user=str(get_user_id())
     )
    def on_updated(self, updates, original):
        planning_featured_service = get_resource_service('planning_featured')
        planning_featured_service.remove_planning_item(original)

        if original.get(
                'lock_user'
        ) and 'lock_user' in updates and updates.get('lock_user') is None:
            push_notification('planning:unlock',
                              item=str(original.get(config.ID_FIELD)),
                              user=str(get_user_id()),
                              lock_session=str(get_auth().get('_id')),
                              etag=updates.get('_etag'),
                              event_item=original.get('event_item') or None,
                              recurrence_id=original.get('recurrence_id')
                              or None)

        # Delete assignments in workflow
        assignments_to_delete = []
        coverages = original.get('coverages') or []
        for coverage in coverages:
            if coverage.get('workflow_status') == WORKFLOW_STATE.ACTIVE:
                assignments_to_delete.append(coverage)

        notify = True
        if original.get('event_item'):
            event = get_resource_service('events').find_one(
                req=None, _id=original.get('event_item'))
            notify = event.get('state') != WORKFLOW_STATE.SPIKED

        get_resource_service('planning').delete_assignments_for_coverages(
            assignments_to_delete, notify)
 def on_update(self, updates, original):
     self.set_schedule(updates)
     updated = deepcopy(original)
     updated.update(updates)
     user_id = get_user_id()
     if user_id:
         updates['version_creator'] = user_id
 def post_featured_planning(self, updates, original={}):
     if updates.get('posted', False):
         self.validate_post_status(
             updates.get('items', original.get('items' or [])))
         updates['posted'] = True
         updates['last_posted_time'] = utcnow()
         updates['last_posted_by'] = str(get_user_id())
Example #15
0
    def on_update(self, updates, original):
        """
        Process the action on the event provided

        Automatically sets the `version_creator`, then calls the appropriate method
        for single event (`update_single_event`) or a series of events (`update_recurring_events`)
        """
        user_id = get_user_id()
        if user_id:
            updates['version_creator'] = user_id
            set_ingested_event_state(updates, original)

        # If `skip_on_update` is provided in the updates
        # Then return here so no further processing is performed on this event.
        if 'skip_on_update' in updates:
            return

        # We only validate the original event,
        # not the events that are automatically updated by the system
        self.validate(updates, original)

        # Run the specific method based on if the original is a single or a series of recurring events
        # Or if the 'update_method' is 'UPDATE_SINGLE'
        update_method = self.get_update_method(original, updates)
        if update_method == UPDATE_SINGLE:
            self.update_single_event(updates, original)
        else:
            self.update_recurring_events(updates, original, update_method)
 def on_create(self, docs):
     for doc in docs:
         doc['user'] = get_user_id()
         if doc.get('media'):
             media = current_app.media.get(doc['media'], RESOURCE)
             doc.setdefault('filename', secure_filename(os.path.basename(getattr(media, 'filename'))))
             doc.setdefault('mimetype', getattr(media, 'content_type'))
             doc.setdefault('length', getattr(media, 'length'))
    def on_create(self, docs):
        for doc in docs:
            doc['user'] = get_user_id(required=True)
            if 'subscribers' in doc:
                raise SuperdeskApiError.forbiddenError("User's subscriptions are not allowed on create")

            self.process(doc)
        push_notification(UPDATE_NOTIFICATION)
Example #18
0
def create():
    """
    Creates new sets
    """
    docs = request.get_json()
    post_response = get_sams_client().sets.create(
        docs=docs, external_user_id=get_user_id(True))
    if post_response.status_code == 201:
        push_notification(
            "sams:set:created",
            item_id=post_response.json()["_id"],
            user_id=get_user_id(True),
            session_id=get_auth()["_id"],
            _etag=post_response.json()["_etag"],
            extension="sams",
        )
    return post_response.json(), post_response.status_code
Example #19
0
 def on_create(self, docs):
     for doc in docs:
         doc['user'] = get_user_id()
         if doc.get('media'):
             media = current_app.media.get(doc['media'], RESOURCE)
             doc.setdefault('filename', secure_filename(os.path.basename(getattr(media, 'filename'))))
             doc.setdefault('mimetype', getattr(media, 'content_type'))
             doc.setdefault('length', getattr(media, 'length'))
Example #20
0
def create():
    """
    Creates new Asset
    """
    files = {"binary": request.files["binary"]}
    docs = request.form.to_dict()
    sams_client = get_sams_client()
    post_response = sams_client.assets.create(
        docs=docs, files=files, external_user_id=get_user_id(True))
    response = post_response.json()
    if post_response.status_code == 201:
        if response.get("mimetype", "").startswith("image/"):

            # Create renditions.
            renditions = [k for k in app.config["RENDITIONS"]["sams"].keys()]
            for rendition in renditions:
                dimensions = app.config["RENDITIONS"]["sams"][rendition]
                rendition_response = sams_client.images.generate_rendition(
                    response["_id"],
                    width=dimensions.get("width"),
                    height=dimensions.get("height"),
                    name=rendition,
                    keep_proportions=True,
                )

                if not rendition_response.ok:
                    # We want to continue, even if SAMS failed to generate the rendition
                    # Instead we just log the error here and continue
                    error_json = rendition_response.json()
                    error_code = rendition_response.status_code
                    description = error_json.get(
                        "description") or f"Error [{error_code}]"
                    logger.error(
                        f"Failed to generate SAMS image rendition: {description}"
                    )

        push_notification(
            "sams:asset:created",
            item_id=response["_id"],
            user_id=get_user_id(True),
            session_id=get_auth()["_id"],
            _etag=response["_etag"],
            extension="sams",
        )
    return response, post_response.status_code
Example #21
0
def create():
    """
    Creates new Asset
    """
    files = {"binary": request.files["binary"]}
    docs = request.form.to_dict()
    post_response = get_sams_client().assets.create(
        docs=docs, files=files, external_user_id=get_user_id(True))
    if post_response.status_code == 201:
        push_notification(
            "sams:asset:created",
            item_id=post_response.json()["_id"],
            user_id=get_user_id(True),
            session_id=get_auth()["_id"],
            _etag=post_response.json()["_etag"],
            extension="sams",
        )
    return post_response.json(), post_response.status_code
 def on_update(self, updates, original):
     # Find all planning items in the list
     added_featured = [
         id for id in updates.get('items')
         if id not in original.get('items')
     ]
     self.validate_featured_attrribute(added_featured)
     updates['version_creator'] = str(get_user_id())
     self.post_featured_planning(updates, original)
Example #23
0
def unlock_asset_by_user(user_id, session_id):
    unlock_asset_response = get_sams_client().assets.unlock_assets_by_user(
        external_user_id=user_id, external_session_id=session_id)
    if unlock_asset_response.status_code == 200:
        push_notification("sams:asset:session_unlock",
                          user_id=get_user_id(True),
                          session_id=get_auth()["_id"],
                          extension="sams")
    return unlock_asset_response.status_code
    def create(self, docs, **kwargs):
        ids = []
        for doc in docs:
            item_type = doc.pop('type')
            item_list = get_items(doc.pop('items', []), item_type)
            desk = get_resource_service('desks').find_one(
                req=None, _id=doc.pop('desk')) or {}
            article_template = doc.pop('article_template', None)
            if article_template:
                content_template = get_resource_service(
                    'content_templates').find_one(req=None,
                                                  _id=article_template) or {}
            else:
                content_template = get_desk_template(desk)

            item = get_item_from_template(content_template)
            item[current_app.config['VERSION']] = 1
            item.setdefault('type', 'text')

            if item_type == 'planning':
                item.setdefault('slugline', 'Planning')
            elif item_type == 'event':
                item.setdefault('slugline', 'Event')
            else:
                item.setdefault('slugline', 'Events and Planning')

            item['task'] = {
                'desk': desk.get('_id'),
                'user': get_user_id(),
                'stage': desk.get('working_stage'),
            }
            item_from_template = generate_text_item(item_list,
                                                    doc.pop('template', None),
                                                    item_type)
            fields_to_override = []
            for key, val in item_from_template.items():
                if item.get(key):
                    fields_to_override.append(key)

                    placeholder = PLACEHOLDER_HTML if '_html' in key else PLACEHOLDER_TEXT
                    if placeholder in item[key]:
                        # The placeholder is found in the current field
                        # So replace {{content}} with the generated text
                        item[key] = item[key].replace(placeholder, val)
                    else:
                        # Otherwise append the generated text to the field
                        item[key] += val
                else:
                    item[key] = val

            item = create_item_from_template(item, fields_to_override)
            doc.update(item)
            ids.append(doc['_id'])
        return ids
 def on_create(self, docs):
     for doc in docs:
         doc["user"] = get_user_id()
         if doc.get("media"):
             media = current_app.media.get(doc["media"], RESOURCE)
             doc.setdefault(
                 "filename",
                 secure_filename(
                     os.path.basename(getattr(media, "filename"))))
             doc.setdefault("mimetype", getattr(media, "content_type"))
             doc.setdefault("length", getattr(media, "length"))
Example #26
0
 def send_to_original_desk(self, updates, original):
     if (
         app.config.get("CORRECTIONS_WORKFLOW")
         and original.get("state") == "correction"
         and original.get("task", {}).get("desk_history")
     ):
         send_to(
             doc=updates,
             desk_id=(original["task"]["desk_history"][0]),
             default_stage="working_stage",
             user_id=get_user_id(),
         )
Example #27
0
    def get(self, req, lookup):
        """
        Overriding to pass user as a search parameter
        """
        session_user = str(get_user_id(required=True))
        if not req:
            req = ParsedRequest()

        if lookup:
            req.where = json.dumps({'$or': [{'is_global': True}, {'user': session_user}, lookup]})
        else:
            req.where = json.dumps({'$or': [{'is_global': True}, {'user': session_user}]})

        return super().get(req, lookup=None)
Example #28
0
 def create(self, docs, **kwargs):
     ids = []
     for doc in docs:
         task = None
         if doc.get('desk'):
             desk = get_resource_service('desks').find_one(
                 req=None, _id=doc['desk']) or {}
             task = dict(desk=desk.get('_id'),
                         stage=desk.get('working_stage'),
                         user=get_user_id())
         ids.append(
             self._translate_item(doc['guid'], doc['language'], task,
                                  **kwargs))
     return ids
 def create(self, docs, **kwargs):
     ids = []
     for doc in docs:
         task = None
         if doc.get("desk"):
             desk = get_resource_service("desks").find_one(
                 req=None, _id=doc["desk"]) or {}
             task = dict(desk=desk.get("_id"),
                         stage=desk.get("working_stage"),
                         user=get_user_id())
         ids.append(
             self._translate_item(doc["guid"], doc["language"], task,
                                  **kwargs))
     return ids
    def on_updated(self, updates, original):
        planning_featured_service = get_resource_service('planning_featured')
        planning_featured_service.remove_planning_item(original)

        if original.get('lock_user') and 'lock_user' in updates and updates.get('lock_user') is None:
            push_notification(
                'planning:unlock',
                item=str(original.get(config.ID_FIELD)),
                user=str(get_user_id()),
                lock_session=str(get_auth().get('_id')),
                etag=updates.get('_etag'),
                event_item=original.get('event_item') or None,
                recurrence_id=original.get('recurrence_id') or None
            )
Example #31
0
    def on_create(self, docs):
        for doc in docs:
            doc["user"] = get_user_id()

            # If a `media` argument is passed into the request url then use that as the id for the media item
            # This is so that SAMS client can manually create this link between SAMS and the article
            if request.args.get("media"):
                doc["media"] = request.args["media"]

            if doc.get("media"):
                media = current_app.media.get(doc["media"], RESOURCE)
                doc.setdefault(
                    "filename",
                    secure_filename(
                        os.path.basename(getattr(media, "filename"))))
                doc.setdefault("mimetype", getattr(media, "content_type"))
                doc.setdefault("length", getattr(media, "length"))
Example #32
0
 def on_create(self, docs):
     for doc in docs:
         doc['user'] = get_user_id(required=True)
         self.process(doc)
     push_notification(UPDATE_NOTIFICATION)
Example #33
0
 def _set_created_by(self, doc):
     doc['created_by'] = get_user_id()
Example #34
0
 def _set_updated_by(self, doc):
     doc['updated_by'] = get_user_id()
 def create(self, docs, **kwargs):
     ids = []
     for doc in docs:
         task = None
         if doc.get('desk'):
             desk = get_resource_service('desks').find_one(req=None, _id=doc['desk']) or {}
             task = dict(desk=desk.get('_id'), stage=desk.get('working_stage'), user=get_user_id())
         ids.append(self._translate_item(doc['guid'], doc['language'], task, **kwargs))
     return ids