def put(self, skill_id): """Publishes a skill.""" skill = skill_services.get_skill_by_id(skill_id) version = self.payload.get('version') _require_valid_version(version, skill.version) skill_domain.Skill.require_valid_skill_id(skill_id) try: skill_services.publish_skill(skill_id, self.user_id) except Exception as e: raise self.UnauthorizedUserException(e) skill_rights = skill_services.get_skill_rights(skill_id, strict=False) user_actions_info = user_services.UserActionsInfo(self.user_id) can_edit_skill_description = check_can_edit_skill_description( user_actions_info) self.values.update({ 'skill_is_private': skill_rights.skill_is_private, 'creator_id': skill_rights.creator_id, 'can_edit_skill_description': can_edit_skill_description }) self.render_json(self.values)
def test_get(self): # Check that non-admins or non-topic managers cannot access the # topics and skills dashboard data. skill_id = skill_services.get_new_skill_id() skill_id_2 = skill_services.get_new_skill_id() self.save_new_skill(skill_id, self.admin_id, 'Description') skill_services.publish_skill(skill_id, self.admin_id) self.save_new_skill(skill_id_2, self.admin_id, 'Description 2') with self.swap(feconf, 'ENABLE_NEW_STRUCTURES', True): self.login(self.NEW_USER_EMAIL) response = self.testapp.get( '%s' % feconf.TOPICS_AND_SKILLS_DASHBOARD_DATA_URL, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() # Check that admins can access the topics and skills dashboard data. self.login(self.ADMIN_EMAIL) json_response = self.get_json( '%s' % feconf.TOPICS_AND_SKILLS_DASHBOARD_DATA_URL) self.assertEqual(len(json_response['topic_summary_dicts']), 1) self.assertEqual( json_response['topic_summary_dicts'][0]['can_edit_topic'], True) self.assertEqual(json_response['topic_summary_dicts'][0]['id'], self.topic_id) self.assertEqual( len(json_response['untriaged_skill_summary_dicts']), 1) self.assertEqual( json_response['untriaged_skill_summary_dicts'][0]['id'], skill_id) self.assertEqual( len(json_response['unpublished_skill_summary_dicts']), 1) self.assertEqual( json_response['unpublished_skill_summary_dicts'][0]['id'], skill_id_2) self.logout() # Check that topic managers can access the topics and skills # dashboard editable topic data. Topic managers should not have # access to any unpublished skills. self.login(self.TOPIC_MANAGER_EMAIL) json_response = self.get_json( '%s' % feconf.TOPICS_AND_SKILLS_DASHBOARD_DATA_URL) self.assertEqual(len(json_response['topic_summary_dicts']), 1) self.assertEqual( json_response['topic_summary_dicts'][0]['can_edit_topic'], False) self.assertEqual(json_response['topic_summary_dicts'][0]['id'], self.topic_id) self.assertEqual(json_response['topic_summary_dicts'][0]['id'], self.topic_id) self.assertEqual( len(json_response['untriaged_skill_summary_dicts']), 1) self.assertEqual( json_response['untriaged_skill_summary_dicts'][0]['id'], skill_id) self.assertEqual( len(json_response['unpublished_skill_summary_dicts']), 0) self.logout()
def test_get_unpublished_skill_rights_by_creator(self): self.save_new_skill('skill_a', self.user_id_admin, 'Description A', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', 'Explanation'), [state_domain.SubtitledHtml('2', 'Example 1')], {})) self.save_new_skill('skill_b', self.user_id_admin, 'Description B', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', 'Explanation'), [state_domain.SubtitledHtml('2', 'Example 1')], {})) skill_rights = skill_services.get_unpublished_skill_rights_by_creator( self.user_id_admin) skill_ids = [skill_rights_obj.id for skill_rights_obj in skill_rights] self.assertListEqual(skill_ids, ['skill_a', 'skill_b']) skill_services.publish_skill(self.SKILL_ID, self.user_id_admin) skill_rights = skill_services.get_unpublished_skill_rights_by_creator( self.user_id_admin) skill_ids = [skill_rights_obj.id for skill_rights_obj in skill_rights] self.assertListEqual(skill_ids, ['skill_a', 'skill_b'])
def test_get_unpublished_skill_rights_by_creator(self): self.save_new_skill( 'skill_a', self.user_id_admin, 'Description A', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [ state_domain.SubtitledHtml('2', '<p>Example 1</p>')], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': {'1': {}, '2': {}}}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': {'1': {}, '2': {}}}))) self.save_new_skill( 'skill_b', self.user_id_admin, 'Description B', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [ state_domain.SubtitledHtml('2', '<p>Example 1</p>')], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': {'1': {}, '2': {}}}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': {'1': {}, '2': {}}}))) skill_rights = skill_services.get_unpublished_skill_rights_by_creator( self.user_id_admin) skill_ids = [skill_rights_obj.id for skill_rights_obj in skill_rights] self.assertListEqual(skill_ids, ['skill_a', 'skill_b']) skill_services.publish_skill(self.SKILL_ID, self.user_id_admin) skill_rights = skill_services.get_unpublished_skill_rights_by_creator( self.user_id_admin) skill_ids = [skill_rights_obj.id for skill_rights_obj in skill_rights] self.assertListEqual(skill_ids, ['skill_a', 'skill_b'])
def setUp(self): """Completes the sign-up process for the various users.""" super(BaseTopicsAndSkillsDashboardTests, self).setUp() self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.signup(self.TOPIC_MANAGER_EMAIL, self.TOPIC_MANAGER_USERNAME) self.signup(self.NEW_USER_EMAIL, self.NEW_USER_USERNAME) self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL) self.topic_manager_id = self.get_user_id_from_email( self.TOPIC_MANAGER_EMAIL) self.new_user_id = self.get_user_id_from_email(self.NEW_USER_EMAIL) self.set_admins([self.ADMIN_USERNAME]) self.set_topic_managers([self.TOPIC_MANAGER_USERNAME]) self.topic_id = topic_services.get_new_topic_id() self.linked_skill_id = skill_services.get_new_skill_id() self.save_new_skill(self.linked_skill_id, self.admin_id, 'Description 3') skill_services.publish_skill(self.linked_skill_id, self.admin_id) self.save_new_topic(self.topic_id, self.admin_id, 'Name', 'abbrev', None, 'Description', [], [], [self.linked_skill_id], [], 1)
def post(self): description = self.payload.get('description') linked_topic_ids = self.payload.get('linked_topic_ids') explanation_dict = self.payload.get('explanation_dict') rubrics = self.payload.get('rubrics') if not isinstance(rubrics, list): raise self.InvalidInputException('Rubrics should be a list.') if not isinstance(explanation_dict, dict): raise self.InvalidInputException('Explanation should be a dict.') try: state_domain.SubtitledHtml.from_dict(explanation_dict) except: raise self.InvalidInputException( 'Explanation should be a valid SubtitledHtml dict.') rubrics = [skill_domain.Rubric.from_dict(rubric) for rubric in rubrics] new_skill_id = skill_services.get_new_skill_id() if linked_topic_ids is not None: topics = topic_fetchers.get_topics_by_ids(linked_topic_ids) for topic in topics: if topic is None: raise self.InvalidInputException topic_services.add_uncategorized_skill(self.user_id, topic.id, new_skill_id) skill_domain.Skill.require_valid_description(description) skill = skill_domain.Skill.create_default_skill( new_skill_id, description, rubrics) skill.update_explanation(explanation_dict) skill_services.save_new_skill(self.user_id, skill) skill_services.publish_skill(skill.id, self.user_id) self.render_json({'skillId': new_skill_id})
def test_normal_user_cannot_publish_skill(self): with self.assertRaisesRegexp( Exception, 'The user does not have enough rights to publish the skill.'): skill_services.publish_skill(self.SKILL_ID, self.USER_ID)
def test_cannot_publish_already_published_skill(self): skill_services.publish_skill(self.SKILL_ID, self.user_id_admin) with self.assertRaisesRegexp(Exception, 'The skill is already published.'): skill_services.publish_skill(self.SKILL_ID, self.user_id_admin)
def test_cannot_publish_skill_with_invalid_skill_id(self): with self.assertRaisesRegexp(Exception, 'The given skill does not exist.'): skill_services.publish_skill('invalid_skill_id', self.USER_ID)
def setUp(self): super(ContributionOpportunitiesHandlerTest, self).setUp() self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.set_admins([self.ADMIN_USERNAME]) explorations = [exp_domain.Exploration.create_default_exploration( '%s' % i, title='title %d' % i, category='category%d' % i, ) for i in python_utils.RANGE(2)] for exp in explorations: exp_services.save_new_exploration(self.owner_id, exp) topic = topic_domain.Topic.create_default_topic( topic_id='0', name='topic') topic_services.save_new_topic(self.owner_id, topic) self.skill_id_0 = 'skill_id_0' self.skill_id_1 = 'skill_id_1' self.skill_ids = [self.skill_id_0, self.skill_id_1] for skill_id in self.skill_ids: self.save_new_skill(skill_id, self.admin_id, 'skill_description') skill_services.publish_skill(skill_id, self.admin_id) topic_services.add_uncategorized_skill( self.admin_id, '0', skill_id) self.expected_skill_opportunity_dict_0 = { 'id': self.skill_id_0, 'skill_description': 'skill_description', 'question_count': 0, 'topic_name': 'topic' } self.expected_skill_opportunity_dict_1 = { 'id': self.skill_id_1, 'skill_description': 'skill_description', 'question_count': 0, 'topic_name': 'topic' } stories = [story_domain.Story.create_default_story( '%s' % i, title='title %d' % i, corresponding_topic_id='0' ) for i in python_utils.RANGE(2)] for index, story in enumerate(stories): story.language_code = 'en' story_services.save_new_story(self.owner_id, story) topic_services.add_canonical_story( self.owner_id, topic.id, story.id) story_services.update_story( self.owner_id, story.id, [story_domain.StoryChange({ 'cmd': 'add_story_node', 'node_id': 'node_1', 'title': 'Node1', }), story_domain.StoryChange({ 'cmd': 'update_story_node_property', 'property_name': 'exploration_id', 'node_id': 'node_1', 'old_value': None, 'new_value': explorations[index].id })], 'Changes.') self.expected_opportunity_dict_1 = { 'id': '0', 'topic_name': 'topic', 'story_title': 'title 0', 'chapter_title': 'Node1', 'content_count': 2, 'translation_counts': {} } self.expected_opportunity_dict_2 = { 'id': '1', 'topic_name': 'topic', 'story_title': 'title 1', 'chapter_title': 'Node1', 'content_count': 2, 'translation_counts': {} }
def _load_dummy_new_structures_data(self): """Loads the database with two topics (one of which is empty), a story and three skills in the topic (two of them in a subtopic) and a question attached to each skill. Raises: Exception: Cannot load new structures data in production mode. Exception: User does not have enough rights to generate data. """ if constants.DEV_MODE: if self.user.role != feconf.ROLE_ID_ADMIN: raise Exception( 'User does not have enough rights to generate data.') topic_id_1 = topic_services.get_new_topic_id() topic_id_2 = topic_services.get_new_topic_id() story_id = story_services.get_new_story_id() skill_id_1 = skill_services.get_new_skill_id() skill_id_2 = skill_services.get_new_skill_id() skill_id_3 = skill_services.get_new_skill_id() question_id_1 = question_services.get_new_question_id() question_id_2 = question_services.get_new_question_id() question_id_3 = question_services.get_new_question_id() skill_1 = self._create_dummy_skill(skill_id_1, 'Dummy Skill 1', '<p>Dummy Explanation 1</p>') skill_2 = self._create_dummy_skill(skill_id_2, 'Dummy Skill 2', '<p>Dummy Explanation 2</p>') skill_3 = self._create_dummy_skill(skill_id_3, 'Dummy Skill 3', '<p>Dummy Explanation 3</p>') question_1 = self._create_dummy_question(question_id_1, 'Question 1', [skill_id_1]) question_2 = self._create_dummy_question(question_id_2, 'Question 2', [skill_id_2]) question_3 = self._create_dummy_question(question_id_3, 'Question 3', [skill_id_3]) question_services.add_question(self.user_id, question_1) question_services.add_question(self.user_id, question_2) question_services.add_question(self.user_id, question_3) question_services.create_new_question_skill_link( self.user_id, question_id_1, skill_id_1, 0.3) question_services.create_new_question_skill_link( self.user_id, question_id_2, skill_id_2, 0.5) question_services.create_new_question_skill_link( self.user_id, question_id_3, skill_id_3, 0.7) topic_1 = topic_domain.Topic.create_default_topic( topic_id_1, 'Dummy Topic 1', 'abbrev') topic_2 = topic_domain.Topic.create_default_topic( topic_id_2, 'Empty Topic', 'abbrev') topic_1.add_canonical_story(story_id) topic_1.add_uncategorized_skill_id(skill_id_1) topic_1.add_uncategorized_skill_id(skill_id_2) topic_1.add_uncategorized_skill_id(skill_id_3) topic_1.add_subtopic(1, 'Dummy Subtopic Title') topic_1.move_skill_id_to_subtopic(None, 1, skill_id_2) topic_1.move_skill_id_to_subtopic(None, 1, skill_id_3) subtopic_page = ( subtopic_page_domain.SubtopicPage.create_default_subtopic_page( 1, topic_id_1)) self._reload_exploration('0') self._reload_exploration('16') story = story_domain.Story.create_default_story( story_id, 'Dummy Story 1', topic_id_1) story.add_node('%s%d' % (story_domain.NODE_ID_PREFIX, 1), 'Dummy Chapter 1') story.update_node_destination_node_ids( '%s%d' % (story_domain.NODE_ID_PREFIX, 1), ['%s%d' % (story_domain.NODE_ID_PREFIX, 2)]) story.update_node_exploration_id( '%s%d' % (story_domain.NODE_ID_PREFIX, 1), '0') story.add_node('%s%d' % (story_domain.NODE_ID_PREFIX, 2), 'Dummy Chapter 2') story.update_node_exploration_id( '%s%d' % (story_domain.NODE_ID_PREFIX, 2), '16') skill_services.save_new_skill(self.user_id, skill_1) skill_services.save_new_skill(self.user_id, skill_2) skill_services.save_new_skill(self.user_id, skill_3) story_services.save_new_story(self.user_id, story) topic_services.save_new_topic(self.user_id, topic_1) topic_services.save_new_topic(self.user_id, topic_2) subtopic_page_services.save_subtopic_page( self.user_id, subtopic_page, 'Added subtopic', [ topic_domain.TopicChange({ 'cmd': topic_domain.CMD_ADD_SUBTOPIC, 'subtopic_id': 1, 'title': 'Dummy Subtopic Title' }) ]) topic_services.publish_story(topic_id_1, story_id, self.user_id) topic_services.publish_topic(topic_id_1, self.user_id) skill_services.publish_skill(skill_id_1, self.user_id) skill_services.publish_skill(skill_id_2, self.user_id) skill_services.publish_skill(skill_id_3, self.user_id) else: raise Exception('Cannot load new structures data in production.')