Example #1
0
def delete_topic(committer_id, topic_id, force_deletion=False):
    """Deletes the topic with the given topic_id.

    Args:
        committer_id: str. ID of the committer.
        topic_id: str. ID of the topic to be deleted.
        force_deletion: bool. If true, the topic and its history are fully
            deleted and are unrecoverable. Otherwise, the topic and all
            its history are marked as deleted, but the corresponding models are
            still retained in the datastore. This last option is the preferred
            one.

    Raises:
        ValueError: User does not have enough rights to delete a topic.
    """
    topic_rights_model = topic_models.TopicRightsModel.get(topic_id)
    topic_rights_model.delete(committer_id,
                              feconf.COMMIT_MESSAGE_TOPIC_DELETED,
                              force_deletion=force_deletion)

    # Delete the summary of the topic (regardless of whether
    # force_deletion is True or not).
    delete_topic_summary(topic_id)
    topic_model = topic_models.TopicModel.get(topic_id)
    for subtopic in topic_model.subtopics:
        subtopic_page_services.delete_subtopic_page(committer_id, topic_id,
                                                    subtopic['id'])
    topic_model.delete(committer_id,
                       feconf.COMMIT_MESSAGE_TOPIC_DELETED,
                       force_deletion=force_deletion)

    # This must come after the topic is retrieved. Otherwise the memcache
    # key will be reinstated.
    topic_memcache_key = _get_topic_memcache_key(topic_id)
    memcache_services.delete(topic_memcache_key)
 def test_cannot_get_with_deleted_subtopic_page(self):
     subtopic_page_services.delete_subtopic_page(self.admin_id,
                                                 self.topic_id, 1)
     with self.swap(constants, 'ENABLE_NEW_STRUCTURE_PLAYERS', True):
         self.get_json('%s/%s/%s' %
                       (feconf.SUBTOPIC_DATA_HANDLER, 'Name', 1),
                       expected_status_int=404)
Example #3
0
 def test_cannot_get_with_deleted_subtopic_page(self):
     subtopic_page_services.delete_subtopic_page(self.admin_id,
                                                 self.topic_id, 1)
     self.get_json(
         '%s/staging/%s/%s' %
         (feconf.SUBTOPIC_DATA_HANDLER, 'name', 'sub-url-frag-one'),
         expected_status_int=404)
    def test_job_skips_deleted_subtopics(self):
        topic_id1 = topic_services.get_new_topic_id()
        subtopic_page1 = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, topic_id1))
        subtopic_page_services.save_subtopic_page(
            self.albert_id, subtopic_page1, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])
        subtopic_page_services.delete_subtopic_page(self.albert_id, topic_id1,
                                                    1)

        job_id = (
            topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.create_new())
        topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()

        output = (topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.
                  get_output(job_id))

        self.assertEqual(output, [])
Example #5
0
def update_topic_and_subtopic_pages(committer_id, topic_id, change_list,
                                    commit_message):
    """Updates a topic and its subtopic pages. Commits changes.

    Args:
        committer_id: str. The id of the user who is performing the update
            action.
        topic_id: str. The topic id.
        change_list: list(TopicChange and SubtopicPageChange). These changes are
            applied in sequence to produce the resulting topic.
        commit_message: str or None. A description of changes made to the
            topic.

    Raises:
        ValueError. Current user does not have enough rights to edit a topic.
    """
    if not commit_message:
        raise ValueError('Expected a commit message, received none.')

    old_topic = topic_fetchers.get_topic_by_id(topic_id)
    (updated_topic, updated_subtopic_pages_dict, deleted_subtopic_ids,
     newly_created_subtopic_ids,
     updated_subtopic_pages_change_cmds_dict) = apply_change_list(
         topic_id, change_list)

    if (old_topic.url_fragment != updated_topic.url_fragment and
            does_topic_with_url_fragment_exist(updated_topic.url_fragment)):
        raise utils.ValidationError(
            'Topic with URL Fragment \'%s\' already exists' %
            updated_topic.url_fragment)
    if (old_topic.name != updated_topic.name
            and does_topic_with_name_exist(updated_topic.name)):
        raise utils.ValidationError('Topic with name \'%s\' already exists' %
                                    updated_topic.name)

    _save_topic(committer_id, updated_topic, commit_message, change_list)
    # The following loop deletes those subtopic pages that are already in the
    # datastore, which are supposed to be deleted in the current changelist.
    for subtopic_id in deleted_subtopic_ids:
        if subtopic_id not in newly_created_subtopic_ids:
            subtopic_page_services.delete_subtopic_page(
                committer_id, topic_id, subtopic_id)

    for subtopic_page_id in updated_subtopic_pages_dict:
        subtopic_page = updated_subtopic_pages_dict[subtopic_page_id]
        subtopic_page_change_list = updated_subtopic_pages_change_cmds_dict[
            subtopic_page_id]
        subtopic_id = subtopic_page.get_subtopic_id_from_subtopic_page_id()
        # The following condition prevents the creation of subtopic pages that
        # were deleted above.
        if subtopic_id not in deleted_subtopic_ids:
            subtopic_page_services.save_subtopic_page(
                committer_id, subtopic_page, commit_message,
                subtopic_page_change_list)
    generate_topic_summary(topic_id)

    if old_topic.name != updated_topic.name:
        opportunity_services.update_opportunities_with_new_topic_name(
            updated_topic.id, updated_topic.name)
 def test_delete_subtopic_page(self):
     subtopic_page_id = (
         subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
             self.TOPIC_ID, 1))
     subtopic_page_services.delete_subtopic_page(self.user_id,
                                                 self.TOPIC_ID, 1)
     with self.assertRaises(base_models.BaseModel.EntityNotFoundError):
         topic_models.SubtopicPageModel.get(subtopic_page_id)
     with self.assertRaises(base_models.BaseModel.EntityNotFoundError):
         subtopic_page_services.delete_subtopic_page(
             self.user_id, self.TOPIC_ID, 1)
Example #7
0
def delete_topic(committer_id, topic_id, force_deletion=False):
    """Deletes the topic with the given topic_id.

    Args:
        committer_id: str. ID of the committer.
        topic_id: str. ID of the topic to be deleted.
        force_deletion: bool. If true, the topic and its history are fully
            deleted and are unrecoverable. Otherwise, the topic and all
            its history are marked as deleted, but the corresponding models are
            still retained in the datastore. This last option is the preferred
            one.

    Raises:
        ValueError. User does not have enough rights to delete a topic.
    """
    topic_rights_model = topic_models.TopicRightsModel.get(topic_id)
    topic_rights_model.delete(
        committer_id, feconf.COMMIT_MESSAGE_TOPIC_DELETED,
        force_deletion=force_deletion)

    # Delete the summary of the topic (regardless of whether
    # force_deletion is True or not).
    delete_topic_summary(topic_id)
    topic_model = topic_models.TopicModel.get(topic_id)
    for subtopic in topic_model.subtopics:
        subtopic_page_services.delete_subtopic_page(
            committer_id, topic_id, subtopic['id'])

    all_story_references = (
        topic_model.canonical_story_references +
        topic_model.additional_story_references)
    for story_reference in all_story_references:
        story_services.delete_story(
            committer_id, story_reference['story_id'],
            force_deletion=force_deletion)
    topic_model.delete(
        committer_id, feconf.COMMIT_MESSAGE_TOPIC_DELETED,
        force_deletion=force_deletion)

    feedback_services.delete_threads_for_multiple_entities(
        feconf.ENTITY_TYPE_TOPIC, [topic_id])

    # This must come after the topic is retrieved. Otherwise the memcache
    # key will be reinstated.
    caching_services.delete_multi(
        caching_services.CACHE_NAMESPACE_TOPIC, None, [topic_id])
    (
        opportunity_services
        .delete_exploration_opportunities_corresponding_to_topic(topic_id))
Example #8
0
 def test_delete_subtopic_page(self):
     subtopic_page_id = (
         subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
             self.TOPIC_ID, 1))
     subtopic_page_services.delete_subtopic_page(
         self.user_id, self.TOPIC_ID, 1)
     with self.assertRaisesRegexp(
         base_models.BaseModel.EntityNotFoundError,
         r'Entity for class SubtopicPageModel with id %s not found' % (
             subtopic_page_id)):
         subtopic_models.SubtopicPageModel.get(subtopic_page_id)
     with self.assertRaisesRegexp(
         base_models.BaseModel.EntityNotFoundError,
         r'Entity for class SubtopicPageModel with id %s not found' % (
             subtopic_page_id)):
         subtopic_page_services.delete_subtopic_page(
             self.user_id, self.TOPIC_ID, 1)
Example #9
0
def update_topic_and_subtopic_pages(committer_id, topic_id, change_list,
                                    commit_message):
    """Updates a topic and its subtopic pages. Commits changes.

    Args:
        committer_id: str. The id of the user who is performing the update
            action.
        topic_id: str. The topic id.
        change_list: list(TopicChange and SubtopicPageChange). These changes are
            applied in sequence to produce the resulting topic.
        commit_message: str or None. A description of changes made to the
            topic.

    Raises:
        ValueError: Current user does not have enough rights to edit a topic.
    """
    if not commit_message:
        raise ValueError('Expected a commit message, received none.')

    (updated_topic, updated_subtopic_pages_dict, deleted_subtopic_ids,
     newly_created_subtopic_ids,
     updated_subtopic_pages_change_cmds_dict) = apply_change_list(
         topic_id, change_list)

    _save_topic(committer_id, updated_topic, commit_message, change_list)
    # The following loop deletes those subtopic pages that are already in the
    # datastore, which are supposed to be deleted in the current changelist.
    for subtopic_id in deleted_subtopic_ids:
        if subtopic_id not in newly_created_subtopic_ids:
            subtopic_page_services.delete_subtopic_page(
                committer_id, topic_id, subtopic_id)

    for subtopic_page_id in updated_subtopic_pages_dict:
        subtopic_page = updated_subtopic_pages_dict[subtopic_page_id]
        subtopic_page_change_list = updated_subtopic_pages_change_cmds_dict[
            subtopic_page_id]
        subtopic_id = subtopic_page.get_subtopic_id_from_subtopic_page_id()
        # The following condition prevents the creation of subtopic pages that
        # were deleted above.
        if subtopic_id not in deleted_subtopic_ids:
            subtopic_page_services.save_subtopic_page(
                committer_id, subtopic_page, commit_message,
                subtopic_page_change_list)
    create_topic_summary(topic_id)
 def test_delete_subtopic_page(self) -> None:
     subtopic_page_id = (
         subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
             self.TOPIC_ID, 1))
     subtopic_page_services.delete_subtopic_page(self.user_id,
                                                 self.TOPIC_ID, 1)
     with self.assertRaisesRegex(  # type: ignore[no-untyped-call]
             base_models.BaseModel.EntityNotFoundError,
             re.escape(
                 'Entity for class SubtopicPageModel with id %s not found' %
                 (subtopic_page_id))):
         subtopic_models.SubtopicPageModel.get(subtopic_page_id)
     with self.assertRaisesRegex(  # type: ignore[no-untyped-call]
             base_models.BaseModel.EntityNotFoundError,
             re.escape(
                 'Entity for class SubtopicPageModel with id %s not found' %
                 (subtopic_page_id))):
         subtopic_page_services.delete_subtopic_page(
             self.user_id, self.TOPIC_ID, 1)