Exemplo n.º 1
0
def is_visible(event, user_id, session=None):
    if event is None:
        return False
    if 'worklist_contents' in event.event_type:
        event_info = json.loads(event.event_info)
        if event_info['updated'] is not None:
            info = event_info['updated']['old']
        elif event_info['removed'] is not None:
            info = event_info['removed']
        elif event_info['added'] is not None:
            info = event_info['added']
        else:
            return True

        if info.get('item_type') == 'story':
            story = stories_api.story_get_simple(info['item_id'],
                                                 current_user=user_id,
                                                 session=session)
            if story is None:
                return False
        elif info.get('item_type') == 'task':
            task = tasks_api.task_get(info['item_id'],
                                      current_user=user_id,
                                      session=session)
            if task is None:
                return False
    return True
Exemplo n.º 2
0
    def test_delete_story(self):
        # This test uses mock_data
        story_id = 1
        # Verify that we can look up a story with tasks and events
        story = stories_api.story_get_simple(story_id)
        self.assertIsNotNone(story)
        tasks = tasks_api.task_get_all(story_id=story_id)
        self.assertEqual(len(tasks), 3)
        task_ids = [t.id for t in tasks]
        events = events_api.events_get_all(story_id=story_id)
        self.assertEqual(len(events), 3)
        event_ids = [e.id for e in events]

        # Delete the story
        stories_api.story_delete(story_id)
        story = stories_api.story_get_simple(story_id)
        self.assertIsNone(story)
        # Verify that the story's tasks were deleted
        tasks = tasks_api.task_get_all(story_id=story_id)
        self.assertEqual(len(tasks), 0)
        for tid in task_ids:
            task = tasks_api.task_get(task_id=tid)
            self.assertIsNone(task)
        # And the events
        events = events_api.events_get_all(story_id=story_id)
        self.assertEqual(len(events), 0)
        for eid in event_ids:
            event = events_api.event_get(event_id=eid)
            self.assertIsNone(event)
Exemplo n.º 3
0
    def post(self, id, item_id, item_type, list_position):
        """Add an item to a worklist.

        :param id: The ID of the worklist.
        :param item_id: The ID of the item.
        :param item_type: The type of the item (i.e. "story" or "task").
        :param list_position: The position in the list to add the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id),
                                               user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        item = None
        if item_type == 'story':
            item = stories_api.story_get(
                item_id, current_user=request.current_user_id)
        elif item_type == 'task':
            item = tasks_api.task_get(
                item_id, current_user=request.current_user_id)
        if item is None:
            raise exc.NotFound(_("Item %s refers to a non-existent task or "
                                 "story.") % item_id)

        worklists_api.add_item(
            id, item_id, item_type, list_position,
            current_user=request.current_user_id)

        return wmodels.WorklistItem.from_db_model(
            worklists_api.get_item_at_position(id, list_position))
Exemplo n.º 4
0
 def resolve_item(self, item, story_cache, task_cache, due_dates=True):
     user_id = request.current_user_id
     if item.item_type == 'story':
         story = story_cache.get(item.item_id) or stories_api.story_get(
             item.item_id, current_user=request.current_user_id)
         if story is None:
             return False
         self.story = Story.from_db_model(story)
         if due_dates:
             self.story.due_dates = [
                 date.id for date in story.due_dates
                 if due_dates_api.visible(date, user_id)
             ]
     elif item.item_type == 'task':
         task = task_cache.get(item.item_id) or tasks_api.task_get(
             item.item_id, current_user=request.current_user_id)
         if task is None or task.story is None:
             return False
         self.task = Task.from_db_model(task)
         if due_dates:
             self.task.due_dates = [
                 date.id for date in task.due_dates
                 if due_dates_api.visible(date, user_id)
             ]
     return True
Exemplo n.º 5
0
    def put(self, task_id, task):
        """Modify this task.

        Example::

          curl https://my.example.org/api/v1/tasks -X PUT \\
          -H 'Authorization: Bearer MY_ACCESS_TOKEN' \\
          -H 'Content-Type: application/json;charset=UTF-8' \\
          --data-binary '{"task_id":27,"status":"merged"}'

        :param task_id: An ID of the task.
        :param task: A task within the request body.
        """

        original_task = copy.deepcopy(
            tasks_api.task_get(task_id, current_user=request.current_user_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found.") % task_id)

        task = task_is_valid_put(task, original_task)

        updated_task = tasks_api.task_update(task_id, task.as_dict(
            omit_unset=True))

        post_timeline_events(original_task, updated_task)
        return wmodels.Task.from_db_model(updated_task)
Exemplo n.º 6
0
    def test_delete_story(self):
        # This test uses mock_data
        story_id = 1
        # Verify that we can look up a story with tasks and events
        story = stories_api.story_get_simple(story_id)
        self.assertIsNotNone(story)
        tasks = tasks_api.task_get_all(story_id=story_id)
        self.assertEqual(len(tasks), 3)
        task_ids = [t.id for t in tasks]
        events = events_api.events_get_all(story_id=story_id)
        self.assertEqual(len(events), 3)
        event_ids = [e.id for e in events]

        # Delete the story
        stories_api.story_delete(story_id)
        story = stories_api.story_get_simple(story_id)
        self.assertIsNone(story)
        # Verify that the story's tasks were deleted
        tasks = tasks_api.task_get_all(story_id=story_id)
        self.assertEqual(len(tasks), 0)
        for tid in task_ids:
            task = tasks_api.task_get(task_id=tid)
            self.assertIsNone(task)
        # And the events
        events = events_api.events_get_all(story_id=story_id)
        self.assertEqual(len(events), 0)
        for eid in event_ids:
            event = events_api.event_get(event_id=eid)
            self.assertIsNone(event)
Exemplo n.º 7
0
def is_visible(event, user_id, session=None):
    if event is None:
        return False
    if 'worklist_contents' in event.event_type:
        event_info = json.loads(event.event_info)
        if event_info['updated'] is not None:
            info = event_info['updated']['old']
        elif event_info['removed'] is not None:
            info = event_info['removed']
        elif event_info['added'] is not None:
            info = event_info['added']
        else:
            return True

        if info.get('item_type') == 'story':
            story = stories_api.story_get_simple(
                info['item_id'], current_user=user_id, session=session)
            if story is None:
                return False
        elif info.get('item_type') == 'task':
            task = tasks_api.task_get(
                info['item_id'], current_user=user_id, session=session)
            if task is None:
                return False
    return True
Exemplo n.º 8
0
 def resolve_item(self, item):
     user_id = request.current_user_id
     if item.item_type == 'story':
         story = stories_api.story_get(item.item_id,
                                       current_user=request.current_user_id)
         if story is None:
             return False
         self.story = Story.from_db_model(story)
         due_dates = [
             date.id for date in story.due_dates
             if due_dates_api.visible(date, user_id)
         ]
         self.story.due_dates = due_dates
     elif item.item_type == 'task':
         task = tasks_api.task_get(item.item_id,
                                   current_user=request.current_user_id)
         if task is None or task.story is None:
             return False
         self.task = Task.from_db_model(task)
         due_dates = [
             date.id for date in task.due_dates
             if due_dates_api.visible(date, user_id)
         ]
         self.task.due_dates = due_dates
     return True
Exemplo n.º 9
0
    def delete(self, story_id, task_id):
        """Delete this task.

        Example::

          curl 'https://my.example.org/api/v1/stories/11/tasks/28' -X DELETE \\
          -H 'Authorization: Bearer MY_ACCESS_TOKEN'

        :param story_id: An ID of the story.
        :param task_id: An ID of the task.
        """

        original_task = copy.deepcopy(
            tasks_api.task_get(task_id, current_user=request.current_user_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found.") % task_id)

        if original_task.story_id != story_id:
            abort(400, _("URL story_id and task.story_id do not match"))

        events_api.task_deleted_event(
            story_id=original_task.story_id,
            task_id=original_task.id,
            task_title=original_task.title,
            author_id=request.current_user_id)

        tasks_api.task_delete(task_id)
Exemplo n.º 10
0
def add_item(worklist_id, item_id, item_type, list_position,
             current_user=None):
    worklist = _worklist_get(worklist_id)
    if worklist is None:
        raise exc.NotFound(_("Worklist %s not found") % worklist_id)

    # Check if this item has an archived card in this worklist to restore
    archived = get_item_by_item_id(
        worklist, item_type, item_id, archived=True)
    if archived:
        update = {
            'archived': False,
            'list_position': list_position
        }
        api_base.entity_update(models.WorklistItem, archived.id, update)
        return worklist

    # If this worklist is a lane, check if the item has an archived card
    # somewhere in the board to restore
    if is_lane(worklist):
        board = boards.get_from_lane(worklist)
        archived = boards.get_card(board, item_type, item_id, archived=True)
        if archived:
            update = {
                'archived': False,
                'list_id': worklist_id,
                'list_position': list_position
            }
            api_base.entity_update(models.WorklistItem, archived.id, update)
            return worklist

    # Create a new card
    if item_type == 'story':
        item = stories_api.story_get(item_id, current_user=current_user)
    elif item_type == 'task':
        item = tasks_api.task_get(item_id, current_user=current_user)
    else:
        raise ClientSideError(_("An item in a worklist must be either a "
                                "story or a task"))

    if item is None:
        raise exc.NotFound(_("%(type)s %(id)s not found") %
                           {'type': item_type, 'id': item_id})

    item_dict = {
        'list_id': worklist_id,
        'item_id': item_id,
        'item_type': item_type,
        'list_position': list_position
    }
    worklist_item = api_base.entity_create(models.WorklistItem, item_dict)

    if worklist.items is None:
        worklist.items = [worklist_item]
    else:
        worklist.items.append(worklist_item)

    return worklist
Exemplo n.º 11
0
def add_item(worklist_id, item_id, item_type, list_position,
             current_user=None):
    worklist = _worklist_get(worklist_id)
    if worklist is None:
        raise exc.NotFound(_("Worklist %s not found") % worklist_id)

    # Check if this item has an archived card in this worklist to restore
    archived = get_item_by_item_id(
        worklist, item_type, item_id, archived=True)
    if archived:
        update = {
            'archived': False,
            'list_position': list_position
        }
        api_base.entity_update(models.WorklistItem, archived.id, update)
        return worklist

    # If this worklist is a lane, check if the item has an archived card
    # somewhere in the board to restore
    if is_lane(worklist):
        board = boards.get_from_lane(worklist)
        archived = boards.get_card(board, item_type, item_id, archived=True)
        if archived:
            update = {
                'archived': False,
                'list_id': worklist_id,
                'list_position': list_position
            }
            api_base.entity_update(models.WorklistItem, archived.id, update)
            return worklist

    # Create a new card
    if item_type == 'story':
        item = stories_api.story_get(item_id, current_user=current_user)
    elif item_type == 'task':
        item = tasks_api.task_get(item_id, current_user=current_user)
    else:
        raise ClientSideError(_("An item in a worklist must be either a "
                                "story or a task"))

    if item is None:
        raise exc.NotFound(_("%(type)s %(id)s not found") %
                           {'type': item_type, 'id': item_id})

    item_dict = {
        'list_id': worklist_id,
        'item_id': item_id,
        'item_type': item_type,
        'list_position': list_position
    }
    worklist_item = api_base.entity_create(models.WorklistItem, item_dict)

    if worklist.items is None:
        worklist.items = [worklist_item]
    else:
        worklist.items.append(worklist_item)

    return worklist
Exemplo n.º 12
0
    def put(self, id, due_date):
        """Modify a due date.

        :param id: The ID of the due date to edit.
        :param due_date: The new due date within the request body.

        """
        if not due_dates_api.assignable(due_dates_api.get(id), request.current_user_id):
            raise exc.NotFound(_("Due date %s not found") % id)

        original_due_date = due_dates_api.get(id)

        due_date_dict = due_date.as_dict(omit_unset=True)
        editing = any(prop in due_date_dict for prop in ("name", "date", "private"))
        if editing and not due_dates_api.editable(original_due_date, request.current_user_id):
            raise exc.NotFound(_("Due date %s not found") % id)

        if due_date.creator_id and due_date.creator_id != original_due_date.creator_id:
            abort(400, _("You can't select the creator of a due date."))

        if "tasks" in due_date_dict:
            tasks = due_date_dict.pop("tasks")
            db_tasks = []
            for task in tasks:
                db_tasks.append(tasks_api.task_get(task.id, current_user=request.current_user_id))
            due_date_dict["tasks"] = db_tasks

        if "stories" in due_date_dict:
            stories = due_date_dict.pop("stories")
            db_stories = []
            for story in stories:
                db_stories.append(stories_api.story_get_simple(story.id, current_user=request.current_user_id))
            due_date_dict["stories"] = db_stories

        board = None
        worklist = None
        if "board_id" in due_date_dict:
            board = boards_api.get(due_date_dict["board_id"])

        if "worklist_id" in due_date_dict:
            worklist = worklists_api.get(due_date_dict["worklist_id"])

        updated_due_date = due_dates_api.update(id, due_date_dict)

        if board:
            updated_due_date.boards.append(board)

        if worklist:
            updated_due_date.worklists.append(worklist)

        if due_dates_api.visible(updated_due_date, request.current_user_id):
            due_date_model = wmodels.DueDate.from_db_model(updated_due_date)
            due_date_model.resolve_items(updated_due_date)
            due_date_model.resolve_permissions(updated_due_date, request.current_user_id)
            return due_date_model
        else:
            raise exc.NotFound(_("Due date %s not found") % id)
Exemplo n.º 13
0
def subscription_get_resource(target_type, target_id, current_user=None):
    if target_type not in SUPPORTED_TYPES:
        return None
    if target_type == 'story':
        return stories_api.story_get(target_id, current_user=current_user)
    elif target_type == 'task':
        return tasks_api.task_get(target_id, current_user=current_user)

    return api_base.entity_get(SUPPORTED_TYPES[target_type], target_id)
Exemplo n.º 14
0
def subscription_get_resource(target_type, target_id, current_user=None):
    if target_type not in SUPPORTED_TYPES:
        return None
    if target_type == 'story':
        return stories_api.story_get(target_id, current_user=current_user)
    elif target_type == 'task':
        return tasks_api.task_get(target_id, current_user=current_user)

    return api_base.entity_get(SUPPORTED_TYPES[target_type], target_id)
Exemplo n.º 15
0
    def get_one(self, task_id):
        """Retrieve details about one task.

        :param task_id: An ID of the task.
        """
        task = tasks_api.task_get(task_id)

        if task:
            return wmodels.Task.from_db_model(task)
        else:
            raise exc.NotFound(_("Task %s not found") % task_id)
Exemplo n.º 16
0
    def get_one(self, task_id):
        """Retrieve details about one task.

        :param task_id: An ID of the task.
        """
        task = tasks_api.task_get(
            task_id, current_user=request.current_user_id)

        if task:
            return wmodels.Task.from_db_model(task)
        else:
            raise exc.NotFound(_("Task %s not found") % task_id)
Exemplo n.º 17
0
def subscription_get_resource(target_type, target_id, current_user=None):
    if target_type not in SUPPORTED_TYPES:
        return None
    if target_type == 'story':
        return stories_api.story_get(target_id, current_user=current_user)
    elif target_type == 'task':
        return tasks_api.task_get(target_id, current_user=current_user)
    elif target_type == 'worklist':
        worklist = worklists_api.get(target_id)
        if worklists_api.visible(worklist, current_user):
            return worklist
        return None

    return api_base.entity_get(SUPPORTED_TYPES[target_type], target_id)
Exemplo n.º 18
0
def subscription_get_resource(target_type, target_id, current_user=None):
    if target_type not in SUPPORTED_TYPES:
        return None
    if target_type == 'story':
        return stories_api.story_get(target_id, current_user=current_user)
    elif target_type == 'task':
        return tasks_api.task_get(target_id, current_user=current_user)
    elif target_type == 'worklist':
        worklist = worklists_api.get(target_id)
        if worklists_api.visible(worklist, current_user):
            return worklist
        return None

    return api_base.entity_get(SUPPORTED_TYPES[target_type], target_id)
Exemplo n.º 19
0
    def get_one(self, story_id, task_id):
        """Retrieve details about one task.

        :param story_id: An ID of the story.
        :param task_id: An ID of the task.
        """
        task = tasks_api.task_get(task_id)

        if task:
            if task.story_id != story_id:
                abort(400, _("URL story_id and task.story_id do not match"))
            return wmodels.Task.from_db_model(task)
        else:
            raise exc.NotFound(_("Task %s not found") % task_id)
Exemplo n.º 20
0
    def get_one(self, story_id, task_id):
        """Retrieve details about one task.

        :param story_id: An ID of the story.
        :param task_id: An ID of the task.
        """
        task = tasks_api.task_get(
            task_id, current_user=request.current_user_id)

        if task:
            if task.story_id != story_id:
                abort(400, _("URL story_id and task.story_id do not match"))
            return wmodels.Task.from_db_model(task)
        else:
            raise exc.NotFound(_("Task %s not found") % task_id)
Exemplo n.º 21
0
    def get_one(self, task_id):
        """Retrieve details about one task.

        Example::

          curl https://my.example.org/api/v1/tasks/24

        :param task_id: An ID of the task.
        """
        task = tasks_api.task_get(
            task_id, current_user=request.current_user_id)

        if task:
            return wmodels.Task.from_db_model(task)
        else:
            raise exc.NotFound(_("Task %s not found") % task_id)
Exemplo n.º 22
0
    def put(self, id, item_id, list_position, list_id=None,
            display_due_date=None):
        """Update a WorklistItem.

        This method also updates the positions of other items in affected
        worklists, if necessary.

        :param id: The ID of the worklist.
        :param item_id: The ID of the worklist_item to be moved.
        :param display_due_date: The ID of the due date displayed on the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id),
                                               user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        card = worklists_api.get_item_by_id(item_id)
        if card is None:
            raise exc.NotFound(_("Item %s seems to have been deleted, "
                                 "try refreshing your page.") % item_id)

        item = None
        if card.item_type == 'story':
            item = stories_api.story_get(
                card.item_id, current_user=request.current_user_id)
        elif card.item_type == 'task':
            item = tasks_api.task_get(
                card.item_id, current_user=request.current_user_id)

        if item is None:
            raise exc.NotFound(_("Item %s refers to a non-existent task or "
                                 "story.") % item_id)

        worklists_api.move_item(id, item_id, list_position, list_id)

        if display_due_date is not None:
            if display_due_date == -1:
                display_due_date = None
            update_dict = {
                'display_due_date': display_due_date
            }
            worklists_api.update_item(item_id, update_dict)

        updated = worklists_api.get_item_by_id(item_id)
        result = wmodels.WorklistItem.from_db_model(updated)
        result.resolve_due_date(updated)
        return result
Exemplo n.º 23
0
    def delete(self, task_id):
        """Delete this task.

        :param task_id: An ID of the task.
        """
        original_task = copy.deepcopy(tasks_api.task_get(task_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found.") % task_id)

        events_api.task_deleted_event(
            story_id=original_task.story_id,
            task_id=original_task.id,
            task_title=original_task.title,
            author_id=request.current_user_id)

        tasks_api.task_delete(task_id)
Exemplo n.º 24
0
    def post(self, id, item_id, item_type, list_position):
        """Add an item to a worklist.

        Example::

          TODO

        :param id: The ID of the worklist.
        :param item_id: The ID of the item.
        :param item_type: The type of the item (i.e. "story" or "task").
        :param list_position: The position in the list to add the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id), user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        item = None
        if item_type == 'story':
            item = stories_api.story_get(item_id,
                                         current_user=request.current_user_id)
        elif item_type == 'task':
            item = tasks_api.task_get(item_id,
                                      current_user=request.current_user_id)
        if item is None:
            raise exc.NotFound(
                _("Item %s refers to a non-existent task or "
                  "story.") % item_id)

        card = worklists_api.add_item(id,
                                      item_id,
                                      item_type,
                                      list_position,
                                      current_user=request.current_user_id)

        added = {
            "worklist_id": id,
            "item_id": item_id,
            "item_title": item.title,
            "item_type": item_type,
            "position": card.list_position
        }

        events_api.worklist_contents_changed_event(id, user_id, added=added)

        return wmodels.WorklistItem.from_db_model(card)
Exemplo n.º 25
0
    def delete(self, task_id):
        """Delete this task.

        :param task_id: An ID of the task.
        """
        original_task = copy.deepcopy(
            tasks_api.task_get(task_id, current_user=request.current_user_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found.") % task_id)

        events_api.task_deleted_event(
            story_id=original_task.story_id,
            task_id=original_task.id,
            task_title=original_task.title,
            author_id=request.current_user_id)

        tasks_api.task_delete(task_id)
Exemplo n.º 26
0
    def post(self, id, item_id, item_type, list_position):
        """Add an item to a worklist.

        Example::

          TODO

        :param id: The ID of the worklist.
        :param item_id: The ID of the item.
        :param item_type: The type of the item (i.e. "story" or "task").
        :param list_position: The position in the list to add the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id),
                                               user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        item = None
        if item_type == 'story':
            item = stories_api.story_get(
                item_id, current_user=request.current_user_id)
        elif item_type == 'task':
            item = tasks_api.task_get(
                item_id, current_user=request.current_user_id)
        if item is None:
            raise exc.NotFound(_("Item %s refers to a non-existent task or "
                                 "story.") % item_id)

        card = worklists_api.add_item(
            id, item_id, item_type, list_position,
            current_user=request.current_user_id)

        added = {
            "worklist_id": id,
            "item_id": item_id,
            "item_title": item.title,
            "item_type": item_type,
            "position": card.list_position
        }

        events_api.worklist_contents_changed_event(id, user_id, added=added)

        return wmodels.WorklistItem.from_db_model(card)
Exemplo n.º 27
0
    def get_one(self, story_id, task_id):
        """Retrieve details about one task.

        Example::

          curl https://my.example.org/api/v1/stories/11/tasks/2691

        :param story_id: An ID of the story.
        :param task_id: An ID of the task.
        """
        task = tasks_api.task_get(
            task_id, current_user=request.current_user_id)

        if task:
            if task.story_id != story_id:
                abort(400, _("URL story_id and task.story_id do not match"))
            return wmodels.Task.from_db_model(task)
        else:
            raise exc.NotFound(_("Task %s not found") % task_id)
Exemplo n.º 28
0
    def put(self, task_id, task):
        """Modify this task.

        :param task_id: An ID of the task.
        :param task: A task within the request body.
        """

        original_task = copy.deepcopy(tasks_api.task_get(task_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found.") % task_id)

        task = task_is_valid_put(task, original_task)

        updated_task = tasks_api.task_update(task_id, task.as_dict(
            omit_unset=True))

        post_timeline_events(original_task, updated_task)
        return wmodels.Task.from_db_model(updated_task)
Exemplo n.º 29
0
    def put(self, task_id, task):
        """Modify this task.

        :param task_id: An ID of the task.
        :param task: A task within the request body.
        """

        original_task = copy.deepcopy(
            tasks_api.task_get(task_id, current_user=request.current_user_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found.") % task_id)

        task = task_is_valid_put(task, original_task)

        updated_task = tasks_api.task_update(task_id, task.as_dict(
            omit_unset=True))

        post_timeline_events(original_task, updated_task)
        return wmodels.Task.from_db_model(updated_task)
Exemplo n.º 30
0
    def delete(self, id, item_id):
        """Remove an item from a worklist.

        Example::

          TODO

        :param id: The ID of the worklist.
        :param item_id: The ID of the worklist item to be removed.

        """
        user_id = request.current_user_id
        worklist = worklists_api.get(id)
        if not worklists_api.editable_contents(worklist, user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        card = worklists_api.get_item_by_id(item_id)
        if card is None:
            raise exc.NotFound(_("Item %s seems to have already been deleted,"
                                 " try refreshing your page.") % item_id)

        worklists_api.archive_item(item_id)

        item = None
        if card.item_type == 'story':
            item = stories_api.story_get(
                card.item_id, current_user=user_id)
        elif card.item_type == 'task':
            item = tasks_api.task_get(
                card.item_id, current_user=user_id)
        if item is None:
            item.title = ''

        removed = {
            "worklist_id": id,
            "item_id": card.item_id,
            "item_type": card.item_type,
            "item_title": item.title
        }
        events_api.worklist_contents_changed_event(id,
                                                   user_id,
                                                   removed=removed)
Exemplo n.º 31
0
    def delete(self, id, item_id):
        """Remove an item from a worklist.

        Example::

          TODO

        :param id: The ID of the worklist.
        :param item_id: The ID of the worklist item to be removed.

        """
        user_id = request.current_user_id
        worklist = worklists_api.get(id)
        if not worklists_api.editable_contents(worklist, user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        card = worklists_api.get_item_by_id(item_id)
        if card is None:
            raise exc.NotFound(
                _("Item %s seems to have already been deleted,"
                  " try refreshing your page.") % item_id)
        worklists_api.update_item(item_id, {'archived': True})
        worklists_api.normalize_positions(worklist)

        item = None
        if card.item_type == 'story':
            item = stories_api.story_get(card.item_id, current_user=user_id)
        elif card.item_type == 'task':
            item = tasks_api.task_get(card.item_id, current_user=user_id)
        if item is None:
            item.title = ''

        removed = {
            "worklist_id": id,
            "item_id": card.item_id,
            "item_type": card.item_type,
            "item_title": item.title
        }
        events_api.worklist_contents_changed_event(id,
                                                   user_id,
                                                   removed=removed)
Exemplo n.º 32
0
    def put(self, id, item_id, list_position, list_id=None, display_due_date=None):
        """Update a WorklistItem.

        This method also updates the positions of other items in affected
        worklists, if necessary.

        :param id: The ID of the worklist.
        :param item_id: The ID of the worklist_item to be moved.
        :param display_due_date: The ID of the due date displayed on the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id), user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        card = worklists_api.get_item_by_id(item_id)
        if card is None:
            raise exc.NotFound(_("Item %s seems to have been deleted, " "try refreshing your page.") % item_id)

        item = None
        if card.item_type == "story":
            item = stories_api.story_get(card.item_id, current_user=request.current_user_id)
        elif card.item_type == "task":
            item = tasks_api.task_get(card.item_id, current_user=request.current_user_id)

        if item is None:
            raise exc.NotFound(_("Item %s refers to a non-existent task or " "story.") % item_id)

        worklists_api.move_item(id, item_id, list_position, list_id)

        if display_due_date is not None:
            if display_due_date == -1:
                display_due_date = None
            update_dict = {"display_due_date": display_due_date}
            worklists_api.update_item(item_id, update_dict)

        updated = worklists_api.get_item_by_id(item_id)
        result = wmodels.WorklistItem.from_db_model(updated)
        result.resolve_due_date(updated)
        return result
Exemplo n.º 33
0
    def put(self, story_id, task_id, task):
        """Modify this task.

        :param story_id: An ID of the story.
        :param task_id: An ID of the task.
        :param task: a task within the request body.
        """

        original_task = copy.deepcopy(tasks_api.task_get(task_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found") % task_id)

        if original_task.story_id != story_id:
            abort(400, _("URL story_id and task.story_id do not match"))

        task = task_is_valid_put(task, original_task)

        updated_task = tasks_api.task_update(task_id, task.as_dict(
            omit_unset=True))

        post_timeline_events(original_task, updated_task)
        return wmodels.Task.from_db_model(updated_task)
Exemplo n.º 34
0
    def post(self, id, item_id, item_type, list_position):
        """Add an item to a worklist.

        :param id: The ID of the worklist.
        :param item_id: The ID of the item.
        :param item_type: The type of the item (i.e. "story" or "task").
        :param list_position: The position in the list to add the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id), user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        item = None
        if item_type == "story":
            item = stories_api.story_get(item_id, current_user=request.current_user_id)
        elif item_type == "task":
            item = tasks_api.task_get(item_id, current_user=request.current_user_id)
        if item is None:
            raise exc.NotFound(_("Item %s refers to a non-existent task or " "story.") % item_id)

        worklists_api.add_item(id, item_id, item_type, list_position, current_user=request.current_user_id)

        return wmodels.WorklistItem.from_db_model(worklists_api.get_item_at_position(id, list_position))
Exemplo n.º 35
0
    def delete(self, story_id, task_id):
        """Delete this task.

        :param story_id: An ID of the story.
        :param task_id: An ID of the task.
        """

        original_task = copy.deepcopy(
            tasks_api.task_get(task_id, current_user=request.current_user_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found.") % task_id)

        if original_task.story_id != story_id:
            abort(400, _("URL story_id and task.story_id do not match"))

        events_api.task_deleted_event(
            story_id=original_task.story_id,
            task_id=original_task.id,
            task_title=original_task.title,
            author_id=request.current_user_id)

        tasks_api.task_delete(task_id)
Exemplo n.º 36
0
    def put(self, story_id, task_id, task):
        """Modify this task.

        Example::

          curl 'https://my.example.org/api/v1/stories/19/tasks/19' -X PUT \\
          -H 'Authorization: Bearer MY_ACCESS_TOKEN' \\
          -H 'Content-Type: application/json;charset=UTF-8' \\
          --data-binary '{"title":"Task Foio","project_id":153,"key":"todo"}'

        :param story_id: An ID of the story.
        :param task_id: An ID of the task.
        :param task: a task within the request body.
        """

        original_task = copy.deepcopy(
            tasks_api.task_get(task_id, current_user=request.current_user_id))

        if not original_task:
            raise exc.NotFound(_("Task %s not found") % task_id)

        if original_task.story_id != story_id:
            abort(400, _("URL story_id and task.story_id do not match"))

        if task.story_id and original_task.story_id != task.story_id:
            abort(
                400,
                _("the story_id of a task cannot be changed through this API"),
            )

        task = task_is_valid_put(task, original_task)

        updated_task = tasks_api.task_update(task_id, task.as_dict(
            omit_unset=True))

        post_timeline_events(original_task, updated_task)
        return wmodels.Task.from_db_model(updated_task)
Exemplo n.º 37
0
    def get_all(self, title=None, creator_id=None, project_id=None,
                archived=False, user_id=None, story_id=None, task_id=None,
                hide_lanes=True, sort_field='id', sort_dir='asc',
                item_type=None, board_id=None, subscriber_id=None,
                offset=None, limit=None):
        """Retrieve definitions of all of the worklists.

        Example::

          curl https://my.example.org/api/v1/worklists

        :param title: A string to filter the title by.
        :param creator_id: Filter worklists by their creator.
        :param project_id: Filter worklists by project ID.
        :param archived: Filter worklists by whether they are archived or not.
        :param user_id: Filter worklists by the users with permissions.
        :param story_id: Filter worklists by whether they contain a story.
        :param task_id: Filter worklists by whether they contain a task.
        :param hide_lanes: If true, don't return worklists which are lanes in
                           a board.
        :param sort_field: The name of the field to sort on.
        :param sort_dir: Sort direction for results (asc, desc).
        :param item_type: Used when filtering by story_id. If
                          item_type is 'story' then only return
                          worklists that contain the story, if
                          item_type is 'task' then only return
                          worklists that contain tasks from the story,
                          otherwise return worklists that contain the
                          story or tasks from the story.
        :param board_id: Get all worklists in the board with this id. Other
                         filters are not applied.
        :param subscriber_id: Filter worklists by whether a user is subscribed.
        :param offset: Offset at which to begin the results.
        :param limit: Maximum number of results to return.

        """
        current_user = request.current_user_id

        # If a non existent story/task is requested, there is no point trying
        # to find worklists which contain it
        if story_id:
            story = stories_api.story_get(story_id, current_user=current_user)
            if story is None:
                response.headers['X-Total'] = '0'
                return []
        if task_id:
            task = tasks_api.task_get(task_id, current_user=current_user)
            if task is None:
                response.headers['X-Total'] = '0'
                return []

        worklists = worklists_api.get_all(title=title,
                                          creator_id=creator_id,
                                          project_id=project_id,
                                          archived=archived,
                                          board_id=board_id,
                                          user_id=user_id,
                                          story_id=story_id,
                                          task_id=task_id,
                                          subscriber_id=subscriber_id,
                                          sort_field=sort_field,
                                          sort_dir=sort_dir,
                                          offset=offset,
                                          limit=limit,
                                          current_user=current_user,
                                          hide_lanes=hide_lanes,
                                          item_type=item_type)
        count = worklists_api.get_count(title=title,
                                        creator_id=creator_id,
                                        project_id=project_id,
                                        archived=archived,
                                        board_id=board_id,
                                        user_id=user_id,
                                        story_id=story_id,
                                        task_id=task_id,
                                        subscriber_id=subscriber_id,
                                        current_user=current_user,
                                        hide_lanes=hide_lanes,
                                        item_type=item_type)

        visible_worklists = []
        for worklist in worklists:
            worklist_model = wmodels.Worklist.from_db_model(worklist)
            worklist_model.resolve_permissions(worklist)
            visible_items = worklists_api.get_visible_items(
                worklist, request.current_user_id)
            worklist_model.items = [
                wmodels.WorklistItem.from_db_model(item)
                for item in visible_items
            ]
            visible_worklists.append(worklist_model)

        # Apply the query response headers
        response.headers['X-Total'] = str(count)
        if limit is not None:
            response.headers['X-Limit'] = str(limit)
        if offset is not None:
            response.headers['X-Offset'] = str(offset)

        return visible_worklists
Exemplo n.º 38
0
def add_item(worklist_id,
             item_id,
             item_type,
             list_position,
             current_user=None):
    worklist = _worklist_get(worklist_id)
    if worklist is None:
        raise exc.NotFound(_("Worklist %s not found") % worklist_id)

    # If the target position is "outside" the list, override it
    if list_position > worklist.items.count():
        list_position = worklist.items.count()

    # Check if this item has an archived card in this worklist to restore
    archived = get_item_by_item_id(worklist, item_type, item_id, archived=True)
    if archived:
        update_item(archived.id, {'archived': False})
        # Move the newly unarchived card into position, and move other cards
        # to compensate for the move
        move_item(archived.id, list_position)
        return archived

    # If this worklist is a lane, check if the item has an archived card
    # somewhere in the board to restore
    if is_lane(worklist):
        board = boards.get_from_lane(worklist)
        archived = boards.get_card(board, item_type, item_id, archived=True)
        if archived:
            update_item(archived.id, {'archived': False})
            # Move the newly unarchived card into position, and move other
            # cards to compensate for the move
            move_item(archived.id, list_position, new_list_id=worklist_id)
            return archived

    # Create a new card
    if item_type == 'story':
        item = stories_api.story_get(item_id, current_user=current_user)
    elif item_type == 'task':
        item = tasks_api.task_get(item_id, current_user=current_user)
    else:
        raise ClientSideError(
            _("An item in a worklist must be either a "
              "story or a task"))

    if item is None:
        raise exc.NotFound(
            _("%(type)s %(id)s not found") % {
                'type': item_type,
                'id': item_id
            })

    card_dict = {
        'list_id': worklist_id,
        'item_id': item_id,
        'item_type': item_type,
        'list_position': 99999  # Initialise the card "outside" the list
    }
    card = api_base.entity_create(models.WorklistItem, card_dict)

    # Move the card into position, and move other cards to compensate
    card = move_item(card.id, list_position)

    if worklist.items is None:
        worklist.items = [card]
    else:
        worklist.items.append(card)

    return card
Exemplo n.º 39
0
    def put(self, id, due_date):
        """Modify a due date.

        :param id: The ID of the due date to edit.
        :param due_date: The new due date within the request body.

        """
        if not due_dates_api.assignable(due_dates_api.get(id),
                                        request.current_user_id):
            raise exc.NotFound(_("Due date %s not found") % id)

        original_due_date = due_dates_api.get(id)

        due_date_dict = due_date.as_dict(omit_unset=True)
        editing = any(prop in due_date_dict
                      for prop in ('name', 'date', 'private'))
        if editing and not due_dates_api.editable(original_due_date,
                                                  request.current_user_id):
            raise exc.NotFound(_("Due date %s not found") % id)

        if due_date.creator_id \
                and due_date.creator_id != original_due_date.creator_id:
            abort(400, _("You can't select the creator of a due date."))

        if 'tasks' in due_date_dict:
            tasks = due_date_dict.pop('tasks')
            db_tasks = []
            for task in tasks:
                db_tasks.append(tasks_api.task_get(
                    task.id, current_user=request.current_user_id))
            due_date_dict['tasks'] = db_tasks

        if 'stories' in due_date_dict:
            stories = due_date_dict.pop('stories')
            db_stories = []
            for story in stories:
                db_stories.append(stories_api.story_get_simple(
                    story.id, current_user=request.current_user_id))
            due_date_dict['stories'] = db_stories

        board = None
        worklist = None
        if 'board_id' in due_date_dict:
            board = boards_api.get(due_date_dict['board_id'])

        if 'worklist_id' in due_date_dict:
            worklist = worklists_api.get(due_date_dict['worklist_id'])

        updated_due_date = due_dates_api.update(id, due_date_dict)

        if board:
            updated_due_date.boards.append(board)

        if worklist:
            updated_due_date.worklists.append(worklist)

        if due_dates_api.visible(updated_due_date, request.current_user_id):
            due_date_model = wmodels.DueDate.from_db_model(updated_due_date)
            due_date_model.resolve_items(updated_due_date)
            due_date_model.resolve_permissions(updated_due_date,
                                               request.current_user_id)
            return due_date_model
        else:
            raise exc.NotFound(_("Due date %s not found") % id)
Exemplo n.º 40
0
    def get_all(self, story_id, title=None, assignee_id=None, project_id=None,
                project_group_id=None, branch_id=None, milestone_id=None,
                status=None, priority=None, marker=None, limit=None,
                sort_field='id', sort_dir='asc', link=None):
        """Retrieve definitions of all of the tasks.

        :param story_id: filter tasks by story ID.
        :param title: search by task title.
        :param assignee_id: filter tasks by who they are assigned to.
        :param project_id: filter the tasks based on project.
        :param project_group_id: filter tasks based on project group.
        :param branch_id: filter tasks based on branch_id.
        :param milestone_id: filter tasks based on milestone.
        :param status: filter tasks by status.
        :param priority: filter tasks by priority.
        :param marker: The resource id where the page should begin.
        :param limit: The number of tasks to retrieve.
        :param sort_field: The name of the field to sort on.
        :param sort_dir: sort direction for results (asc, desc).
        """

        # Boundary check on limit.
        if limit is not None:
            limit = max(0, limit)

        # Resolve the marker record.
        marker_task = tasks_api.task_get(
            marker, current_user=request.current_user_id)

        tasks = tasks_api \
            .task_get_all(title=title,
                          link=link,
                          story_id=story_id,
                          assignee_id=assignee_id,
                          project_id=project_id,
                          project_group_id=project_group_id,
                          branch_id=branch_id,
                          milestone_id=milestone_id,
                          status=status,
                          priority=priority,
                          sort_field=sort_field,
                          sort_dir=sort_dir,
                          marker=marker_task,
                          limit=limit,
                          current_user=request.current_user_id)
        task_count = tasks_api \
            .task_get_count(title=title,
                            link=link,
                            story_id=story_id,
                            assignee_id=assignee_id,
                            project_id=project_id,
                            project_group_id=project_group_id,
                            branch_id=branch_id,
                            milestone_id=milestone_id,
                            status=status,
                            priority=priority,
                            current_user=request.current_user_id)

        # Apply the query response headers.
        response.headers['X-Limit'] = str(limit)
        response.headers['X-Total'] = str(task_count)
        if marker_task:
            response.headers['X-Marker'] = str(marker_task.id)

        return [wmodels.Task.from_db_model(s) for s in tasks]
Exemplo n.º 41
0
    def put(self,
            id,
            item_id,
            list_position,
            list_id=None,
            display_due_date=None):
        """Update a WorklistItem.

        Example::

          TODO

        This method also updates the positions of other items in affected
        worklists, if necessary.

        :param id: The ID of the worklist.
        :param item_id: The ID of the worklist_item to be moved.
        :param display_due_date: The ID of the due date displayed on the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id), user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        card = worklists_api.get_item_by_id(item_id)
        if card is None:
            raise exc.NotFound(
                _("Item %s seems to have been deleted, "
                  "try refreshing your page.") % item_id)

        item = None
        if card.item_type == 'story':
            item = stories_api.story_get(card.item_id,
                                         current_user=request.current_user_id)
        elif card.item_type == 'task':
            item = tasks_api.task_get(card.item_id,
                                      current_user=request.current_user_id)

        if item is None:
            raise exc.NotFound(
                _("Item %s refers to a non-existent task or "
                  "story.") % item_id)

        old = {
            "worklist_id": card.list_id,
            "item_id": card.item_id,
            "item_title": item.title,
            "item_type": card.item_type,
            "position": card.list_position,
            "due_date_id": card.display_due_date
        }

        new = {
            "item_id": card.item_id,
            "item_title": item.title,
            "item_type": card.item_type
        }

        if list_position != card.list_position and list_position is not None:
            new['position'] = list_position
        if list_id != card.list_id and list_id is not None:
            new['worklist_id'] = list_id

        worklists_api.move_item(id, item_id, list_position, list_id)

        if display_due_date is not None:
            if display_due_date == -1:
                display_due_date = None
            update_dict = {'display_due_date': display_due_date}
            worklists_api.update_item(item_id, update_dict)
            new['due_date_id'] = display_due_date

        updated = {"old": old, "new": new}
        events_api.worklist_contents_changed_event(id,
                                                   user_id,
                                                   updated=updated)

        updated = worklists_api.get_item_by_id(item_id)
        result = wmodels.WorklistItem.from_db_model(updated)
        result.resolve_due_date(updated)
        return result
Exemplo n.º 42
0
    def get_all(self,
                title=None,
                creator_id=None,
                project_id=None,
                archived=False,
                user_id=None,
                story_id=None,
                task_id=None,
                hide_lanes=True,
                sort_field='id',
                sort_dir='asc',
                item_type=None,
                board_id=None,
                subscriber_id=None,
                offset=None,
                limit=None):
        """Retrieve definitions of all of the worklists.

        Example::

          curl https://my.example.org/api/v1/worklists

        :param title: A string to filter the title by.
        :param creator_id: Filter worklists by their creator.
        :param project_id: Filter worklists by project ID.
        :param archived: Filter worklists by whether they are archived or not.
        :param user_id: Filter worklists by the users with permissions.
        :param story_id: Filter worklists by whether they contain a story.
        :param task_id: Filter worklists by whether they contain a task.
        :param hide_lanes: If true, don't return worklists which are lanes in
                           a board.
        :param sort_field: The name of the field to sort on.
        :param sort_dir: Sort direction for results (asc, desc).
        :param item_type: Used when filtering by story_id. If
                          item_type is 'story' then only return
                          worklists that contain the story, if
                          item_type is 'task' then only return
                          worklists that contain tasks from the story,
                          otherwise return worklists that contain the
                          story or tasks from the story.
        :param board_id: Get all worklists in the board with this id. Other
                         filters are not applied.
        :param subscriber_id: Filter worklists by whether a user is subscribed.
        :param offset: Offset at which to begin the results.
        :param limit: Maximum number of results to return.

        """
        current_user = request.current_user_id

        # If a non existent story/task is requested, there is no point trying
        # to find worklists which contain it
        if story_id:
            story = stories_api.story_get(story_id, current_user=current_user)
            if story is None:
                response.headers['X-Total'] = '0'
                return []
        if task_id:
            task = tasks_api.task_get(task_id, current_user=current_user)
            if task is None:
                response.headers['X-Total'] = '0'
                return []

        worklists = worklists_api.get_all(title=title,
                                          creator_id=creator_id,
                                          project_id=project_id,
                                          archived=archived,
                                          board_id=board_id,
                                          user_id=user_id,
                                          story_id=story_id,
                                          task_id=task_id,
                                          subscriber_id=subscriber_id,
                                          sort_field=sort_field,
                                          sort_dir=sort_dir,
                                          offset=offset,
                                          limit=limit,
                                          current_user=current_user,
                                          hide_lanes=hide_lanes,
                                          item_type=item_type)
        count = worklists_api.get_count(title=title,
                                        creator_id=creator_id,
                                        project_id=project_id,
                                        archived=archived,
                                        board_id=board_id,
                                        user_id=user_id,
                                        story_id=story_id,
                                        task_id=task_id,
                                        subscriber_id=subscriber_id,
                                        current_user=current_user,
                                        hide_lanes=hide_lanes,
                                        item_type=item_type)

        visible_worklists = []
        for worklist in worklists:
            worklist_model = wmodels.Worklist.from_db_model(worklist)
            worklist_model.resolve_permissions(worklist)
            visible_items = worklists_api.get_visible_items(
                worklist, request.current_user_id)
            worklist_model.items = [
                wmodels.WorklistItem.from_db_model(item)
                for item in visible_items
            ]
            visible_worklists.append(worklist_model)

        # Apply the query response headers
        response.headers['X-Total'] = str(count)
        if limit is not None:
            response.headers['X-Limit'] = str(limit)
        if offset is not None:
            response.headers['X-Offset'] = str(offset)

        return visible_worklists
Exemplo n.º 43
0
    def put(self, id, item_id, list_position, list_id=None,
            display_due_date=None):
        """Update a WorklistItem.

        Example::

          TODO

        This method also updates the positions of other items in affected
        worklists, if necessary.

        :param id: The ID of the worklist.
        :param item_id: The ID of the worklist_item to be moved.
        :param display_due_date: The ID of the due date displayed on the item.

        """
        user_id = request.current_user_id
        if not worklists_api.editable_contents(worklists_api.get(id),
                                               user_id):
            raise exc.NotFound(_("Worklist %s not found") % id)
        card = worklists_api.get_item_by_id(item_id)
        if card is None:
            raise exc.NotFound(_("Item %s seems to have been deleted, "
                                 "try refreshing your page.") % item_id)

        item = None
        if card.item_type == 'story':
            item = stories_api.story_get(
                card.item_id, current_user=request.current_user_id)
        elif card.item_type == 'task':
            item = tasks_api.task_get(
                card.item_id, current_user=request.current_user_id)

        if item is None:
            raise exc.NotFound(_("Item %s refers to a non-existent task or "
                                 "story.") % item_id)

        old = {
            "worklist_id": card.list_id,
            "item_id": card.item_id,
            "item_title": item.title,
            "item_type": card.item_type,
            "position": card.list_position,
            "due_date_id": card.display_due_date
        }

        new = {
            "item_id": card.item_id,
            "item_title": item.title,
            "item_type": card.item_type
        }

        if list_position != card.list_position and list_position is not None:
            new['position'] = list_position
        if list_id != card.list_id and list_id is not None:
            new['worklist_id'] = list_id

        worklists_api.move_item(item_id, list_position, list_id)

        if display_due_date is not None:
            if display_due_date == -1:
                display_due_date = None
            update_dict = {
                'display_due_date': display_due_date
            }
            worklists_api.update_item(item_id, update_dict)
            new['due_date_id'] = display_due_date

        updated = {
            "old": old,
            "new": new
        }
        events_api.worklist_contents_changed_event(id,
                                                   user_id,
                                                   updated=updated)

        updated = worklists_api.get_item_by_id(item_id)
        result = wmodels.WorklistItem.from_db_model(updated)
        result.resolve_due_date(updated)
        return result