Beispiel #1
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)
Beispiel #2
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')),
     )
Beispiel #3
0
    def on_create(self, docs, **kwargs):
        user_id = get_user(required=True)['_id']
        session_id = get_auth()['_id']

        existing_locks = list(self.find(where={}))
        for existing_lock in existing_locks:
            if str(existing_lock.get(LOCK_USER)) != str(user_id):
                raise SuperdeskApiError.forbiddenError(
                    message=
                    "Featured stories already being managed by another user.")
            elif str(existing_lock.get(LOCK_SESSION)) != str(session_id):
                raise SuperdeskApiError.forbiddenError(
                    message=
                    "Featured stories already being managed by you in another session."
                )

        # get the lock if not raise forbidden exception
        if not lock(LOCK_ID, expire=5):
            raise SuperdeskApiError.forbiddenError(
                message="Unable to obtain lock on Featured stories.")

        for doc in docs:
            doc['_id'] = generate_guid(type=GUID_NEWSML)
            lock_updates = {
                LOCK_USER: user_id,
                LOCK_SESSION: session_id,
                LOCK_TIME: utcnow()
            }
            doc.update(lock_updates)

        return docs
    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)
Beispiel #5
0
 def on_created(self, docs):
     user_id = get_user(required=True)['_id']
     session_id = get_auth()['_id']
     unlock(LOCK_ID, remove=True)
     push_notification('planning_featured_lock:lock',
                       user=str(user_id),
                       lock_session=str(session_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 _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 on_updated(self, updates, original):
        user = get_user(required=True).get(config.ID_FIELD, '')
        session = get_auth().get(config.ID_FIELD, '')

        # Save history
        get_resource_service(
            'assignments_history').on_item_revert_availability(
                updates, original)

        push_notification('assignments:reverted',
                          item=str(original[config.ID_FIELD]),
                          planning=original.get('planning_item'),
                          assigned_user=(original.get('assigned_to')
                                         or {}).get('user'),
                          assigned_desk=(original.get('assigned_to')
                                         or {}).get('desk'),
                          assignment_state=updates.get('assigned_to',
                                                       {})['state'],
                          user=str(user),
                          session=str(session),
                          coverage=original.get('coverage_item'))

        # publish the planning item
        get_resource_service('assignments').publish_planning(
            original.get('planning_item'))

        # External (slack/browser pop-up) notifications
        assignments_service = get_resource_service('assignments')
        assignments_service.send_assignment_notification(
            updates, original, True)
    def on_updated(self, updates, original):
        added, removed = self._get_added_removed_agendas(updates, original)
        session_id = get_auth().get(config.ID_FIELD)
        push_notification('planning:updated',
                          item=str(original[config.ID_FIELD]),
                          user=str(updates.get('version_creator', '')),
                          added_agendas=added,
                          removed_agendas=removed,
                          session=session_id)

        doc = deepcopy(original)
        doc.update(updates)
        self.__generate_related_assignments([doc])
        updates['coverages'] = doc.get('coverages') or []

        update_post_item(updates, original)

        # update planning_featured record if schedule has changed
        if original.get('featured'):
            removed_schedules = []
            for schdl in original.get('_planning_schedule', []):
                other_schedules_on_day = [
                    s for s in updates.get('_planning_schedule', []) if
                    schdl.get('scheduled').date() == s.get('scheduled').date()
                ]
                if len(other_schedules_on_day) == 0 and schdl.get(
                        'scheduled') not in removed_schedules:
                    removed_schedules.append(schdl.get('scheduled'))

            planning_featured_service = get_resource_service(
                'planning_featured')
            for removed_date in removed_schedules:
                # get the planning_featured record for that day
                planning_featured_service.remove_planning_item_for_date(
                    removed_date, original)
    def create(self, docs, **kwargs):
        user_id = get_user(required=True)['_id']
        session_id = get_auth()['_id']
        lock_service = LockService()

        # If the event is a recurrent event, unlock all other events in this series
        item_id = request.view_args['item_id']
        resource_service = get_resource_service('events')
        item = resource_service.find_one(req=None, _id=item_id)
        if item.get('recurrence_id') and not item.get(LOCK_USER):
            # Find the actual event that is locked
            historic, past, future = resource_service.get_recurring_timeline(
                item)
            series = historic + past + future

            for event in series:
                if event.get(LOCK_USER):
                    updated_item = lock_service.unlock(event, user_id,
                                                       session_id, 'events')
                    break
        else:
            updated_item = lock_service.unlock(item, user_id, session_id,
                                               'events')

        if updated_item is None:
            # version 1 item must have been deleted by now
            return [0]

        return _update_returned_document(docs[0], updated_item)
Beispiel #11
0
    def on_updated(self, updates, original):
        # Spike associated planning
        planning_spike_service = get_resource_service('planning_spike')
        query = {
            'query': {
                'bool': {
                    'must': {
                        'term': {
                            'event_item': str(original[config.ID_FIELD])
                        }
                    }
                }
            }
        }
        results = get_resource_service('planning').search(query)
        spiked_items = []
        if len(results.docs) > 0:
            for planning in results.docs:
                if planning['state'] == WORKFLOW_STATE.DRAFT:
                    planning_spike_service.patch(planning[config.ID_FIELD],
                                                 {'state': 'spiked'})
                    spiked_items.append(str(planning[config.ID_FIELD]))

            # When a planning item associated with this event is spiked
            # If there were any failures in removing assignments
            # Send those notifications here
            if len(spiked_items) > 0:
                query = {
                    'query': {
                        'filtered': {
                            'filter': {
                                'bool': {
                                    'must': {
                                        'terms': {
                                            'planning_item': spiked_items
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                req = ParsedRequest()
                req.args = {'source': json.dumps(query)}

                assignments = get_resource_service('assignments').get(
                    req=req, lookup=None)
                if assignments.count() > 0:
                    session_id = get_auth().get('_id')
                    user_id = get_user().get(config.ID_FIELD)
                    push_notification(
                        'assignments:delete:fail',
                        items=[{
                            'slugline': a.get('planning').get('slugline'),
                            'type': a.get('planning').get('g2_content_type')
                        } for a in assignments],
                        session=session_id,
                        user=user_id)
    def on_updated(self, updates, original):
        user = get_user(required=True).get(config.ID_FIELD, '')
        session = get_auth().get(config.ID_FIELD, '')

        push_notification('planning:rescheduled',
                          item=str(original[config.ID_FIELD]),
                          user=str(user),
                          session=str(session))
 def create(self, docs, **kwargs):
     user = get_user(required=True)
     auth = get_auth()
     item_id = request.view_args['item_id']
     lock_service = LockService()
     item = lock_service.unlock(item_id, user['_id'], auth['_id'],
                                'planning')
     return _update_returned_document(docs[0], item)
    def update(self, id, updates, original):
        user = get_user(required=True).get(config.ID_FIELD, '')
        session = get_auth().get(config.ID_FIELD, '')
        coverage_states = get_resource_service('vocabularies').find_one(
            req=None, _id='newscoveragestatus')

        event_cancellation = updates.pop('event_cancellation', False)
        cancel_all_coverage = updates.pop('cancel_all_coverage', False)

        coverage_cancel_state = None
        if coverage_states:
            coverage_cancel_state = next(
                (x for x in coverage_states.get('items', [])
                 if x['qcode'] == 'ncostat:notint'), None)
            coverage_cancel_state.pop('is_active', None)

        ids = []
        updates['coverages'] = deepcopy(original.get('coverages'))
        coverages = updates.get('coverages') or []
        reason = updates.pop('reason', None)

        planning_service = get_resource_service('planning')
        for coverage in coverages:
            if coverage['workflow_status'] != WORKFLOW_STATE.CANCELLED:
                ids.append(coverage.get('coverage_id'))
                planning_service.cancel_coverage(
                    coverage, coverage_cancel_state,
                    coverage.get('workflow_status'), None, reason,
                    event_cancellation)

        if cancel_all_coverage:
            item = None
            if len(ids) > 0:
                item = self.backend.update(self.datasource, id, updates,
                                           original)
                push_notification('coverage:cancelled',
                                  planning_item=str(original[config.ID_FIELD]),
                                  user=str(user),
                                  session=str(session),
                                  reason=reason,
                                  coverage_state=coverage_cancel_state,
                                  etag=item.get('_etag'),
                                  ids=ids)
            return item if item else self.find_one(req=None, _id=id)

        self._cancel_plan(updates, reason)

        item = self.backend.update(self.datasource, id, updates, original)

        push_notification('planning:cancelled',
                          item=str(original[config.ID_FIELD]),
                          user=str(user),
                          session=str(session),
                          reason=reason,
                          coverage_state=coverage_cancel_state,
                          event_cancellation=event_cancellation)

        return item
    def update(self, id, updates, original):
        user = get_user(required=True).get(config.ID_FIELD, '')
        session = get_auth().get(config.ID_FIELD, '')

        updates['assigned_to'] = deepcopy(original).get('assigned_to')

        # If we are confirming availability, save the revert state for revert action
        coverage_type = original.get('planning', {}).get('g2_content_type')
        if coverage_type != 'text':
            updates['assigned_to']['revert_state'] = updates['assigned_to'][
                'state']

        updates['assigned_to']['state'] = ASSIGNMENT_WORKFLOW_STATE.COMPLETED

        remove_lock_information(updates)

        item = self.backend.update(self.datasource, id, updates, original)

        # Save history if user initiates complete
        if coverage_type == 'text':
            get_resource_service('assignments_history').on_item_complete(
                updates, original)
        else:
            get_resource_service(
                'assignments_history').on_item_confirm_availability(
                    updates, original)

        push_notification('assignments:completed',
                          item=str(original[config.ID_FIELD]),
                          planning=original.get('planning_item'),
                          assigned_user=(original.get('assigned_to')
                                         or {}).get('user'),
                          assigned_desk=(original.get('assigned_to')
                                         or {}).get('desk'),
                          assignment_state=ASSIGNMENT_WORKFLOW_STATE.COMPLETED,
                          user=str(user),
                          session=str(session),
                          coverage=original.get('coverage_item'))

        # Send notification that the work has been completed
        # Determine the display name of the assignee
        assigned_to_user = get_resource_service('users').find_one(req=None,
                                                                  _id=user)
        assignee = assigned_to_user.get(
            'display_name') if assigned_to_user else 'Unknown'
        PlanningNotifications().notify_assignment(
            target_user=str(
                original.get('assigned_to', {}).get('assignor_user')),
            message='{{coverage_type}} coverage \"{{slugline}}\" has been '
            'completed by {{assignee}}',
            assignee=assignee,
            coverage_type=get_coverage_type_name(
                original.get('planning', {}).get('g2_content_type', '')),
            slugline=original.get('planning', {}).get('slugline'),
            omit_user=True)

        return item
Beispiel #16
0
 def unlock_item(self, item_id, doc):
     user_id = get_user(required=True)['_id']
     session_id = get_auth()['_id']
     lock_service = get_component(LockService)
     resource_service = get_resource_service('events')
     item = resource_service.find_one(req=None, _id=item_id)
     updated_item = lock_service.unlock(item, user_id, session_id, 'events')
     return update_returned_document(doc, updated_item,
                                     CUSTOM_HATEOAS_EVENTS)
Beispiel #17
0
 def create(self, docs, **kwargs):
     user_id = get_user(required=True)['_id']
     session_id = get_auth()['_id']
     item_id = request.view_args['item_id']
     lock_service = get_component(LockService)
     resource_service = get_resource_service('planning')
     item = resource_service.find_one(req=None, _id=item_id)
     updated_item = lock_service.unlock(item, user_id, session_id, 'planning')
     return update_returned_document(docs[0], updated_item, CUSTOM_HATEOAS_PLANNING)
Beispiel #18
0
def is_locked_in_this_session(item, user_id=None, session_id=None):
    if user_id is None:
        user = get_user(required=True)
        user_id = user.get(config.ID_FIELD)

    if session_id is None:
        session = get_auth()
        session_id = session.get(config.ID_FIELD)

    return item.get(LOCK_USER) == user_id and item.get(LOCK_SESSION) == session_id
Beispiel #19
0
 def on_duplicated(self, doc, parent_id):
     self._update_event_history(doc)
     session_id = get_auth().get('_id')
     push_notification('planning:duplicated',
                       item=str(doc.get(config.ID_FIELD)),
                       original=str(parent_id),
                       user=str(doc.get('original_creator', '')),
                       added_agendas=doc.get('agendas') or [],
                       removed_agendas=[],
                       session=session_id)
Beispiel #20
0
 def on_updated(self, updates, original):
     added, removed = self._get_added_removed_agendas(updates, original)
     session_id = get_auth().get('_id')
     push_notification(
         'planning:updated',
         item=str(original[config.ID_FIELD]),
         user=str(updates.get('version_creator', '')),
         added_agendas=added, removed_agendas=removed,
         session=session_id
     )
Beispiel #21
0
 def sync_assignment_unlock(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.get(LOCK_USER):
                 lock_service = get_component(LockService)
                 lock_service.unlock(assignment, user_id,
                                     get_auth()['_id'], 'assignments')
 def create(self, docs, **kwargs):
     user_id = get_user(required=True)['_id']
     session_id = get_auth()['_id']
     item_id = request.view_args['item_id']
     lock_action = docs[0].get('lock_action', 'edit')
     lock_service = LockService()
     resource_service = get_resource_service('planning')
     item = resource_service.find_one(req=None, _id=item_id)
     updated_item = lock_service.lock(item, user_id, session_id,
                                      lock_action, 'planning')
     return _update_returned_document(docs[0], updated_item)
Beispiel #23
0
    def create(self, docs, **kwargs):
        user_id = get_user(required=True)['_id']
        session_id = get_auth()['_id']
        lock_service = get_component(LockService)

        # If the event is a recurrent event, unlock all other events in this series
        item_id = request.view_args['item_id']
        resource_service = get_resource_service('events')
        item = resource_service.find_one(req=None, _id=item_id)
        updated_item = lock_service.unlock(item, user_id, session_id, 'events')
        return update_returned_document(docs[0], updated_item,
                                        CUSTOM_HATEOAS_EVENTS)
Beispiel #24
0
 def on_created(self, docs):
     session_id = get_auth().get('_id')
     for doc in docs:
         push_notification('planning:created',
                           item=str(doc.get(config.ID_FIELD)),
                           user=str(doc.get('original_creator', '')),
                           added_agendas=doc.get('agendas') or [],
                           removed_agendas=[],
                           session=session_id,
                           event_item=doc.get('event_item', None))
         self._update_event_history(doc)
     self.__generate_related_assignments(docs)
Beispiel #25
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."
                     )
Beispiel #26
0
    def lock_item(self, item_id, action, doc):
        user_id = get_user(required=True)['_id']
        session_id = get_auth()['_id']
        lock_action = action
        lock_service = get_component(LockService)
        item = get_resource_service('events').find_one(req=None, _id=item_id)

        lock_service.validate_relationship_locks(item, 'events')
        updated_item = lock_service.lock(item, user_id, session_id,
                                         lock_action, 'events')

        return update_returned_document(doc, updated_item,
                                        CUSTOM_HATEOAS_EVENTS)
Beispiel #27
0
    def create(self, docs, **kwargs):
        user_id = get_user(required=True)['_id']
        session_id = get_auth()['_id']
        item_id = request.view_args['item_id']
        lock_action = docs[0].get('lock_action', 'edit')
        lock_service = get_component(LockService)
        item = get_resource_service('planning').find_one(req=None, _id=item_id)

        if item and item.get('event_item'):
            lock_service.validate_relationship_locks(item, 'planning')

        updated_item = lock_service.lock(item, user_id, session_id, lock_action, 'planning')
        return update_returned_document(docs[0], updated_item, CUSTOM_HATEOAS_PLANNING)
    def on_deleted(self, doc):
        """Validate we can safely delete the Assignment item

        Make sure to clean up the Archive, Delivery and Planning items by:
            * Remove 'assignment_id' from Archive item (if linked)
            * Delete the Delivery record associated with the Assignment & Archive items (if linked)
            * Removing 'assigned_to' dictionary from the associated Coverage
        """
        archive_service = get_resource_service('archive')
        delivery_service = get_resource_service('delivery')
        planning_service = get_resource_service('planning')
        assignment_id = doc.get(config.ID_FIELD)

        # If we have a Content Item linked, then we need to remove the
        # assignment_id from it and remove the delivery record
        # Then send a notification that the content has been updated
        archive_item = archive_service.find_one(req=None,
                                                assignment_id=assignment_id)
        if archive_item:
            archive_service.system_update(archive_item[config.ID_FIELD],
                                          {'assignment_id': None},
                                          archive_item)

            delivery_service.delete_action(
                lookup={
                    'assignment_id': assignment_id,
                    'item_id': archive_item[config.ID_FIELD]
                })

            # Push content nofitication so connected clients can update the
            # content views (i.e. removes the Calendar icon from Monitoring)
            push_content_notification([archive_item])

        # Remove assignment information from coverage
        updated_planning = planning_service.remove_assignment(
            doc, unlock_planning=True)

        # Finally send a notification to connected clients that the Assignment
        # has been removed
        push_notification(
            'assignments:removed',
            item=archive_item[config.ID_FIELD] if archive_item else None,
            assignment=assignment_id,
            planning=doc.get('planning_item'),
            coverage=doc.get('coverage_item'),
            planning_etag=updated_planning.get(config.ETAG),
            session=get_auth()['_id'])

        # publish planning
        self.publish_planning(doc.get('planning_item'))
    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
            )
    def create(self, docs, **kwargs):
        user_id = get_user(required=True)['_id']
        session_id = get_auth()['_id']
        lock_service = get_component(LockService)

        # If the event is a recurrent event, unlock all other events in this series
        item_id = request.view_args['item_id']
        resource_service = get_resource_service('assignments')
        item = resource_service.find_one(req=None, _id=item_id)

        if not self.is_assignment_locked_by_user(item, user_id):
            updated_item = lock_service.unlock(item, user_id, session_id, 'assignments')
            return _update_returned_document(docs[0], updated_item)

        return _update_returned_document(docs[0], item)