Ejemplo n.º 1
0
    def post(self):
        """Handles POST requests."""
        username = self.payload.get("username")
        agreed_to_terms = self.payload.get("agreed_to_terms")
        can_receive_email_updates = self.payload.get("can_receive_email_updates")

        has_ever_registered = user_services.has_ever_registered(self.user_id)
        has_fully_registered = user_services.has_fully_registered(self.user_id)

        if has_fully_registered:
            self.render_json({})
            return

        if not isinstance(agreed_to_terms, bool) or not agreed_to_terms:
            raise self.InvalidInputException(
                "In order to edit explorations on this site, you will " "need to accept the license terms."
            )
        else:
            user_services.record_agreement_to_terms(self.user_id)

        if not user_services.get_username(self.user_id):
            try:
                user_services.set_username(self.user_id, username)
            except utils.ValidationError as e:
                raise self.InvalidInputException(e)

        if can_receive_email_updates is not None:
            user_services.update_email_preferences(self.user_id, can_receive_email_updates)

        # Note that an email is only sent when the user registers for the first
        # time.
        if feconf.CAN_SEND_EMAILS_TO_USERS and not has_ever_registered:
            email_manager.send_post_signup_email(self.user_id)

        self.render_json({})
Ejemplo n.º 2
0
    def post(self):
        """Post handler for query."""
        data = self.payload['data']
        kwargs = {key: data[key] for key in data if data[key] is not None}
        self._validate(kwargs)

        query_id = user_query_services.save_new_query_model(
            self.user_id, **kwargs)

        # Start MR job in background.
        job_id = user_query_jobs_one_off.UserQueryOneOffJob.create_new()
        params = {'query_id': query_id}
        user_query_jobs_one_off.UserQueryOneOffJob.enqueue(
            job_id, additional_job_params=params)

        query_model = user_models.UserQueryModel.get(query_id)
        query_data = {
            'id': query_model.id,
            'submitter_username': (
                user_services.get_username(query_model.submitter_id)),
            'created_on': query_model.created_on.strftime('%d-%m-%y %H:%M:%S'),
            'status': query_model.query_status,
            'num_qualified_users': len(query_model.user_ids)
        }

        data = {
            'query': query_data
        }
        self.render_json(data)
Ejemplo n.º 3
0
def send_user_query_email(
        sender_id, recipient_ids, email_subject, email_body, email_intent):
    bulk_email_model_id = email_models.BulkEmailModel.get_new_id('')
    sender_name = user_services.get_username(sender_id)
    sender_email = user_services.get_email_from_user_id(sender_id)
    _send_bulk_mail(
        recipient_ids, sender_id, email_intent, email_subject, email_body,
        sender_email, sender_name, bulk_email_model_id)
    return bulk_email_model_id
Ejemplo n.º 4
0
def _get_thread_dict_from_model_instance(thread):
    return {
        'last_updated': utils.get_time_in_millisecs(thread.last_updated),
        'original_author_username': user_services.get_username(
            thread.original_author_id) if thread.original_author_id else None,
        'state_name': thread.state_name,
        'status': thread.status,
        'subject': thread.subject,
        'summary': thread.summary,
        'thread_id': get_thread_id_from_full_thread_id(thread.id)}
Ejemplo n.º 5
0
    def test_set_and_get_username(self):
        user_id = "someUser"
        username = "******"
        with self.assertRaisesRegexp(Exception, "User not found."):
            user_services.set_username(user_id, username)

        user_services._create_user(user_id, "*****@*****.**")

        user_services.set_username(user_id, username)
        self.assertEquals(username, user_services.get_username(user_id))
Ejemplo n.º 6
0
    def test_set_and_get_username(self):
        user_id = 'someUser'
        username = '******'
        with self.assertRaisesRegexp(Exception, 'User not found.'):
            user_services.set_username(user_id, username)

        user_services._create_user(user_id, '*****@*****.**')

        user_services.set_username(user_id, username)
        self.assertEquals(username, user_services.get_username(user_id))
Ejemplo n.º 7
0
def _get_suggestion_dict_from_model_instance(suggestion):
    if suggestion is None:
        return suggestion
    return {
        'author_name': user_services.get_username(suggestion.author_id),
        'exploration_id': suggestion.exploration_id,
        'exploration_version': suggestion.exploration_version,
        'state_name': suggestion.state_name,
        'description': suggestion.description,
        'state_content': suggestion.state_content}
Ejemplo n.º 8
0
def get_threadlist(exploration_id):
    return [{
        'last_updated': utils.get_time_in_millisecs(t.last_updated),
        'original_author_username': user_services.get_username(
            t.original_author_id) if t.original_author_id else None,
        'state_name': t.state_name,
        'status': t.status,
        'subject': t.subject,
        'summary': t.summary,
        'thread_id': t.id,
    } for t in feedback_models.FeedbackThreadModel.get_threads(exploration_id)]
Ejemplo n.º 9
0
def _get_suggestion_dict_from_model_instance(suggestion):
    if suggestion is None:
        return suggestion
    return {
        "author_name": user_services.get_username(suggestion.author_id),
        "exploration_id": suggestion.exploration_id,
        "exploration_version": suggestion.exploration_version,
        "state_name": suggestion.state_name,
        "description": suggestion.description,
        "state_content": suggestion.state_content,
    }
Ejemplo n.º 10
0
 def to_dict(self):
     return {
         'last_updated': utils.get_time_in_millisecs(self.last_updated),
         'original_author_username': user_services.get_username(
             self.original_author_id) if self.original_author_id else None,
         'state_name': self.state_name,
         'status': self.status,
         'subject': self.subject,
         'summary': self.summary,
         'thread_id': self.get_thread_id()
     }
Ejemplo n.º 11
0
def _get_message_dict(message_instance):
    return {
        "author_username": (
            user_services.get_username(message_instance.author_id) if message_instance.author_id else None
        ),
        "created_on": utils.get_time_in_millisecs(message_instance.created_on),
        "exploration_id": message_instance.exploration_id,
        "message_id": message_instance.message_id,
        "text": message_instance.text,
        "updated_status": message_instance.updated_status,
        "updated_subject": message_instance.updated_subject,
    }
Ejemplo n.º 12
0
def _get_thread_dict_from_model_instance(thread):
    return {
        "last_updated": utils.get_time_in_millisecs(thread.last_updated),
        "original_author_username": user_services.get_username(thread.original_author_id)
        if thread.original_author_id
        else None,
        "state_name": thread.state_name,
        "status": thread.status,
        "subject": thread.subject,
        "summary": thread.summary,
        "thread_id": get_thread_id_from_full_thread_id(thread.id),
    }
Ejemplo n.º 13
0
def _get_message_dict(message_instance):
    return {
        'author_username': (
            user_services.get_username(message_instance.author_id)
            if message_instance.author_id else None),
        'created_on': utils.get_time_in_millisecs(message_instance.created_on),
        'exploration_id': message_instance.exploration_id,
        'message_id': message_instance.message_id,
        'text': message_instance.text,
        'updated_status': message_instance.updated_status,
        'updated_subject': message_instance.updated_subject,
    }
Ejemplo n.º 14
0
 def to_dict(self):
     return {
         'author_username': (
             user_services.get_username(self.author_id)
             if self.author_id else None),
         'created_on': utils.get_time_in_millisecs(self.created_on),
         'exploration_id': self.exploration_id,
         'message_id': self.message_id,
         'text': self.text,
         'updated_status': self.updated_status,
         'updated_subject': self.updated_subject,
     }
Ejemplo n.º 15
0
def send_test_email_for_bulk_emails(tester_id, email_subject, email_body):
    tester_name = user_services.get_username(tester_id)
    tester_email = user_services.get_email_from_user_id(tester_id)
    return _send_email(
        tester_id,
        tester_id,
        feconf.BULK_EMAIL_INTENT_TEST,
        email_subject,
        email_body,
        tester_email,
        sender_name=tester_name,
    )
Ejemplo n.º 16
0
    def get(self, exploration_id):
        """Handles GET requests."""
        snapshots = exp_services.get_exploration_snapshots_metadata(
            exploration_id, DEFAULT_NUM_SNAPSHOTS)

        # Patch `snapshots` to use the editor's display name.
        for snapshot in snapshots:
            if snapshot['committer_id'] != 'admin':
                snapshot['committer_id'] = user_services.get_username(
                    snapshot['committer_id'])

        self.render_json({
            'snapshots': snapshots,
        })
Ejemplo n.º 17
0
def send_emails_to_subscribers(creator_id, exploration_id, exploration_title):
    """Sends an email to all the subscribers of the creators when the creator
    publishes an exploration.

    Args:
        creator_id: str. The id of the creator who has published an exploration
            and to whose subscribers we are sending emails.
        exploration_id: str. The id of the exploration which the creator has
            published.
        exploration_title: str. The title of the exploration which the creator
            has published.
    """

    creator_name = user_services.get_username(creator_id)
    email_subject = ('%s has published a new exploration!' % creator_name)
    email_body_template = (
        'Hi %s,<br>'
        '<br>'
        '%s has published a new exploration! You can play it here: '
        '<a href="https://www.oppia.org/explore/%s">%s</a><br>'
        '<br>'
        'Thanks, and happy learning!<br>'
        '<br>'
        'Best wishes,<br>'
        '- The Oppia Team<br>'
        '<br>%s')

    if not feconf.CAN_SEND_EMAILS:
        log_new_error('This app cannot send emails to users.')
        return

    if not feconf.CAN_SEND_SUBSCRIPTION_EMAILS:
        log_new_error('This app cannot send subscription emails to users.')
        return

    recipient_list = subscription_services.get_all_subscribers_of_creator(
        creator_id)
    recipients_usernames = user_services.get_usernames(recipient_list)
    recipients_preferences = user_services.get_users_email_preferences(
        recipient_list)
    for index, username in enumerate(recipients_usernames):
        if recipients_preferences[index].can_receive_subscription_email:
            email_body = email_body_template % (
                username, creator_name, exploration_id,
                exploration_title, EMAIL_FOOTER.value)
            _send_email(
                recipient_list[index], feconf.SYSTEM_COMMITTER_ID,
                feconf.EMAIL_INTENT_SUBSCRIPTION_NOTIFICATION,
                email_subject, email_body, feconf.NOREPLY_EMAIL_ADDRESS)
Ejemplo n.º 18
0
    def get(self):
        query_id = self.request.get('query_id')
        query_model = user_models.UserQueryModel.get(query_id)
        query_data = {
            'id': query_model.id,
            'submitter_username': (
                user_services.get_username(query_model.submitter_id)),
            'created_on': query_model.created_on.strftime('%d-%m-%y %H:%M:%S'),
            'status': query_model.query_status,
            'num_qualified_users': len(query_model.user_ids)
        }

        data = {
            'query': query_data
        }

        self.render_json(data)
Ejemplo n.º 19
0
    def test_get_email_from_username(self):
        user_id = "someUser"
        username = "******"
        user_email = "*****@*****.**"

        user_services._create_user(user_id, user_email)
        user_services.set_username(user_id, username)
        self.assertEquals(user_services.get_username(user_id), username)

        # Handle usernames that exist.
        self.assertEquals(user_services.get_email_from_username(username), user_email)

        # Handle usernames in the same equivalence class correctly.
        self.assertEquals(user_services.get_email_from_username("USERNAME"), user_email)

        # Return None for usernames which don't exist.
        self.assertIsNone(user_services.get_email_from_username("fakeUsername"))
Ejemplo n.º 20
0
    def get(self, exploration_id):
        """Handles GET requests."""
        try:
            snapshots = exp_services.get_exploration_snapshots_metadata(
                exploration_id, DEFAULT_NUM_SNAPSHOTS)
        except:
            raise self.PageNotFoundException

        # Patch `snapshots` to use the editor's display name.
        for snapshot in snapshots:
            if snapshot['committer_id'] != feconf.ADMIN_COMMITTER_ID:
                snapshot['committer_id'] = user_services.get_username(
                    snapshot['committer_id'])

        self.render_json({
            'snapshots': snapshots,
        })
Ejemplo n.º 21
0
    def post(self):
        """Handles POST requests."""
        username = self.payload.get('username')
        agreed_to_terms = self.payload.get('agreed_to_terms')
        can_receive_email_updates = self.payload.get(
            'can_receive_email_updates')

        has_ever_registered = user_services.has_ever_registered(self.user_id)
        has_fully_registered = user_services.has_fully_registered(self.user_id)

        if has_fully_registered:
            self.render_json({})
            return

        if not isinstance(agreed_to_terms, bool) or not agreed_to_terms:
            raise self.InvalidInputException(
                'In order to edit explorations on this site, you will '
                'need to accept the license terms.')
        else:
            user_services.record_agreement_to_terms(self.user_id)

        if not user_services.get_username(self.user_id):
            try:
                user_services.set_username(self.user_id, username)
            except utils.ValidationError as e:
                raise self.InvalidInputException(e)

        if can_receive_email_updates is not None:
            user_services.update_email_preferences(
                self.user_id, can_receive_email_updates,
                feconf.DEFAULT_EDITOR_ROLE_EMAIL_PREFERENCE,
                feconf.DEFAULT_FEEDBACK_MESSAGE_EMAIL_PREFERENCE,
                feconf.DEFAULT_SUBSCRIPTION_EMAIL_PREFERENCE)

        # Note that an email is only sent when the user registers for the first
        # time.
        if feconf.CAN_SEND_EMAILS and not has_ever_registered:
            email_manager.send_post_signup_email(self.user_id)

        user_services.generate_initial_profile_picture(self.user_id)

        self.render_json({})
Ejemplo n.º 22
0
    def test_get_email_from_username(self):
        user_id = 'someUser'
        username = '******'
        user_email = '*****@*****.**'

        user_services.get_or_create_user(user_id, user_email)
        user_services.set_username(user_id, username)
        self.assertEquals(user_services.get_username(user_id), username)

        # Handle usernames that exist.
        self.assertEquals(
            user_services.get_email_from_username(username), user_email)

        # Handle usernames in the same equivalence class correctly.
        self.assertEquals(
            user_services.get_email_from_username('USERNAME'), user_email)

        # Return None for usernames which don't exist.
        self.assertIsNone(
            user_services.get_email_from_username('fakeUsername'))
Ejemplo n.º 23
0
    def post(self):
        """Handles POST requests."""
        username = self.payload.get('username')
        agreed_to_terms = self.payload.get('agreed_to_terms')

        if not isinstance(agreed_to_terms, bool) or not agreed_to_terms:
            raise self.InvalidInputException(
                'In order to edit explorations on this site, you will '
                'need to accept the license terms.')
        else:
            user_services.record_agreement_to_terms(self.user_id)

        if user_services.get_username(self.user_id):
            # A username has already been set for this user.
            self.render_json({})
            return

        try:
            user_services.set_username(self.user_id, username)
        except utils.ValidationError as e:
            raise self.InvalidInputException(e)

        self.render_json({})
Ejemplo n.º 24
0
    def setUp(self):
        super(TopicFetchersUnitTests, self).setUp()
        self.TOPIC_ID = topic_services.get_new_topic_id()
        changelist = [
            topic_domain.TopicChange({
                'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                'title': 'Title',
                'subtopic_id': 1
            })
        ]
        self.save_new_topic(self.TOPIC_ID, self.user_id, 'Name', 'Description',
                            [self.story_id_1, self.story_id_2],
                            [self.story_id_3],
                            [self.skill_id_1, self.skill_id_2], [], 1)
        self.save_new_story(self.story_id_1, self.user_id, 'Title',
                            'Description', 'Notes', self.TOPIC_ID)
        self.save_new_story(self.story_id_3, self.user_id, 'Title 3',
                            'Description 3', 'Notes', self.TOPIC_ID)
        self.signup('*****@*****.**', 'A')
        self.signup('*****@*****.**', 'B')
        self.signup(self.ADMIN_EMAIL, username=self.ADMIN_USERNAME)

        self.user_id_a = self.get_user_id_from_email('*****@*****.**')
        self.user_id_b = self.get_user_id_from_email('*****@*****.**')
        self.user_id_admin = self.get_user_id_from_email(self.ADMIN_EMAIL)
        topic_services.update_topic_and_subtopic_pages(self.user_id_admin,
                                                       self.TOPIC_ID,
                                                       changelist,
                                                       'Added a subtopic')

        self.topic = topic_fetchers.get_topic_by_id(self.TOPIC_ID)
        self.set_admins([self.ADMIN_USERNAME])
        self.set_topic_managers([user_services.get_username(self.user_id_a)])
        self.user_a = user_services.UserActionsInfo(self.user_id_a)
        self.user_b = user_services.UserActionsInfo(self.user_id_b)
        self.user_admin = user_services.UserActionsInfo(self.user_id_admin)
Ejemplo n.º 25
0
    def to_dict(self):
        """Returns a dict representation of this FeedbackMessage object.

        Returns:
            dict. Dict representation of the FeedbackMessage object.
        """
        return {
            'author_username': (user_services.get_username(self.author_id)
                                if self.author_id else None),
            'created_on_msecs':
            utils.get_time_in_millisecs(self.created_on),
            'entity_type':
            self.entity_type,
            'entity_id':
            self.entity_id,
            'message_id':
            self.message_id,
            'text':
            self.text,
            'updated_status':
            self.updated_status,
            'updated_subject':
            self.updated_subject
        }
Ejemplo n.º 26
0
    def setUp(self):
        super(StoryFetchersUnitTests, self).setUp()
        self.STORY_ID = story_services.get_new_story_id()
        self.TOPIC_ID = topic_services.get_new_topic_id()
        self.save_new_topic(
            self.TOPIC_ID, self.USER_ID, 'Topic', 'abbrev', None,
            'A new topic', [], [], [], [], 0)
        self.save_new_story(
            self.STORY_ID, self.USER_ID, 'Title', 'Description', 'Notes',
            self.TOPIC_ID)
        topic_services.add_canonical_story(
            self.USER_ID, self.TOPIC_ID, self.STORY_ID)
        changelist = [
            story_domain.StoryChange({
                'cmd': story_domain.CMD_ADD_STORY_NODE,
                'node_id': self.NODE_ID_1,
                'title': 'Title 1'
            })
        ]
        story_services.update_story(
            self.USER_ID, self.STORY_ID, changelist,
            'Added node.')
        self.story = story_fetchers.get_story_by_id(self.STORY_ID)
        self.signup('*****@*****.**', 'A')
        self.signup('*****@*****.**', 'B')
        self.signup(self.ADMIN_EMAIL, username=self.ADMIN_USERNAME)

        self.user_id_a = self.get_user_id_from_email('*****@*****.**')
        self.user_id_b = self.get_user_id_from_email('*****@*****.**')
        self.user_id_admin = self.get_user_id_from_email(self.ADMIN_EMAIL)

        self.set_admins([self.ADMIN_USERNAME])
        self.set_topic_managers([user_services.get_username(self.user_id_a)])
        self.user_a = user_services.UserActionsInfo(self.user_id_a)
        self.user_b = user_services.UserActionsInfo(self.user_id_b)
        self.user_admin = user_services.UserActionsInfo(self.user_id_admin)
Ejemplo n.º 27
0
def accept_suggestion(suggestion_id, reviewer_id, commit_message,
                      review_message):
    """Accepts the suggestion with the given suggestion_id after validating it.

    Args:
        suggestion_id: str. The id of the suggestion to be accepted.
        reviewer_id: str. The ID of the reviewer accepting the suggestion.
        commit_message: str. The commit message.
        review_message: str. The message provided by the reviewer while
            accepting the suggestion.

    Raises:
        Exception. The suggestion is already handled.
        Exception. The suggestion is not valid.
        Exception. The commit message is empty.
    """
    if not commit_message or not commit_message.strip():
        raise Exception('Commit message cannot be empty.')

    suggestion = get_suggestion_by_id(suggestion_id)

    if suggestion is None:
        raise Exception(
            'You cannot accept the suggestion with id %s because it does '
            'not exist.' % (suggestion_id))
    if suggestion.is_handled:
        raise Exception('The suggestion with id %s has already been accepted/'
                        'rejected.' % (suggestion_id))
    suggestion.pre_accept_validate()
    html_string = ''.join(suggestion.get_all_html_content_strings())
    error_list = (
        html_validation_service.
        validate_math_tags_in_html_with_attribute_math_content(html_string))
    if len(error_list) > 0:
        raise Exception(
            'Invalid math tags found in the suggestion with id %s.' %
            (suggestion.suggestion_id))

    suggestion.set_suggestion_status_to_accepted()
    suggestion.set_final_reviewer_id(reviewer_id)

    author_name = user_services.get_username(suggestion.author_id)
    commit_message = get_commit_message_for_suggestion(author_name,
                                                       commit_message)
    suggestion.accept(commit_message)

    _update_suggestion(suggestion)

    # Update the community contribution stats so that the number of suggestions
    # of this type that are in review decreases by one, since this
    # suggestion is no longer in review.
    _update_suggestion_counts_in_community_contribution_stats([suggestion], -1)

    feedback_services.create_message(suggestion_id, reviewer_id,
                                     feedback_models.STATUS_CHOICES_FIXED,
                                     None, review_message)

    # When recording of scores is enabled, the author of the suggestion gets an
    # increase in their score for the suggestion category.
    if feconf.ENABLE_RECORDING_OF_SCORES:
        user_id = suggestion.author_id
        score_category = suggestion.score_category

        # Get user proficiency domain object.
        user_proficiency = _get_user_proficiency(user_id, score_category)

        # Increment the score of the author due to their suggestion being
        # accepted.
        user_proficiency.increment_score(
            suggestion_models.INCREMENT_SCORE_OF_AUTHOR_BY)

        # Emails are sent to onboard new reviewers. These new reviewers are
        # created when the score of the user passes the minimum score required
        # to review.
        if feconf.SEND_SUGGESTION_REVIEW_RELATED_EMAILS:
            if user_proficiency.can_user_review_category() and (
                    not user_proficiency.onboarding_email_sent):
                email_manager.send_mail_to_onboard_new_reviewers(
                    user_id, score_category)
                user_proficiency.mark_onboarding_email_as_sent()

        # Need to update the corresponding user proficiency model after we
        # updated the domain object.
        _update_user_proficiency(user_proficiency)
Ejemplo n.º 28
0
def get_thread_summaries(user_id, thread_ids):
    """Returns a list of summaries corresponding to each of the threads given.
    It also returns the number of threads that are currently not read by the
    user.

    Args:
        user_id: str. The id of the user.
        thread_ids: list(str). The ids of the threads for which we have to fetch
            the summaries.

    Returns:
        tuple(thread_summaries, number_of_unread_threads), where:
            thread_summaries: list(FeedbackThreadSummary).
            number_of_unread_threads: int. The number of threads not read by the
                user.
    """
    thread_user_ids = [
        feedback_models.GeneralFeedbackThreadUserModel.generate_full_id(
            user_id, thread_id) for thread_id in thread_ids
    ]
    thread_exp_ids = [
        get_exp_id_from_thread_id(thread_id) for thread_id in thread_ids
    ]

    thread_models, thread_user_models, thread_exp_models = (
        datastore_services.fetch_multiple_entities_by_ids_and_models([
            ('GeneralFeedbackThreadModel', thread_ids),
            ('GeneralFeedbackThreadUserModel', thread_user_ids),
            ('ExplorationModel', thread_exp_ids),
        ]))

    threads = [_get_thread_from_model(m) for m in thread_models]
    flat_last_two_message_models = (
        feedback_models.GeneralFeedbackMessageModel.get_multi(
            itertools.chain.from_iterable(t.get_last_two_message_ids()
                                          for t in threads)))
    last_two_message_models_of_threads = [
        flat_last_two_message_models[i:i + 2]
        for i in python_utils.RANGE(0, len(flat_last_two_message_models), 2)
    ]

    thread_summaries = []
    number_of_unread_threads = 0
    for thread, last_two_message_models, user_model, exp_model in (
            python_utils.ZIP(threads, last_two_message_models_of_threads,
                             thread_user_models, thread_exp_models)):
        last_message_model, second_last_message_model = last_two_message_models
        message_ids_read_by_user = (() if user_model is None else
                                    user_model.message_ids_read_by_user)

        # The last message is never None because all threads have at least one
        # message.
        last_message_is_read = (last_message_model.message_id
                                in message_ids_read_by_user)
        author_last_message = (last_message_model.author_id
                               and user_services.get_username(
                                   last_message_model.author_id))

        # The second-to-last message, however, can be None.
        second_last_message_is_read = (second_last_message_model is not None
                                       and second_last_message_model.message_id
                                       in message_ids_read_by_user)
        author_second_last_message = (second_last_message_model
                                      and second_last_message_model.author_id
                                      and user_services.get_username(
                                          second_last_message_model.author_id))

        if not last_message_is_read:
            number_of_unread_threads += 1
        thread_summaries.append(
            feedback_domain.FeedbackThreadSummary(
                thread.status, thread.original_author_id, thread.last_updated,
                last_message_model.text, thread.message_count,
                last_message_is_read, second_last_message_is_read,
                author_last_message, author_second_last_message,
                exp_model.title, exp_model.id, thread.id))
    return thread_summaries, number_of_unread_threads
Ejemplo n.º 29
0
 def test_get_username_none(self):
     user_services.get_or_create_user('fakeUser', '*****@*****.**')
     self.assertEquals(None, user_services.get_username('fakeUser'))
Ejemplo n.º 30
0
def get_exp_thread_summaries(user_id, thread_ids):
    """Returns a list of summaries corresponding to the exploration threads from
    the given thread ids. Non-exploration threads are not included in the list.
    It also returns the number of threads that are currently not read by the
    user.

    Args:
        user_id: str. The id of the user.
        thread_ids: list(str). The ids of the threads for which we have to fetch
            the summaries.

    Returns:
        tuple(thread_summaries, number_of_unread_threads). Where:
            thread_summaries: list(FeedbackThreadSummary).
            number_of_unread_threads: int. The number of threads not read by the
                user.
    """
    # We need to fetch the thread models first to filter out the threads which
    # don't refer to an exploration.
    exp_thread_models = [
        model for model in
        feedback_models.GeneralFeedbackThreadModel.get_multi(thread_ids)
        if model and model.entity_type == feconf.ENTITY_TYPE_EXPLORATION
    ]

    exp_thread_user_model_ids = [
        feedback_models.GeneralFeedbackThreadUserModel.generate_full_id(
            user_id, model.id) for model in exp_thread_models
    ]
    exp_model_ids = [model.entity_id for model in exp_thread_models]

    exp_thread_user_models, exp_models = (
        datastore_services.fetch_multiple_entities_by_ids_and_models([
            ('GeneralFeedbackThreadUserModel', exp_thread_user_model_ids),
            ('ExplorationModel', exp_model_ids),
        ]))

    threads = [_get_thread_from_model(m) for m in exp_thread_models]
    flattened_last_two_message_models_of_threads = (
        feedback_models.GeneralFeedbackMessageModel.get_multi(
            itertools.chain.from_iterable(t.get_last_two_message_ids()
                                          for t in threads)))
    last_two_message_models_of_threads = [
        flattened_last_two_message_models_of_threads[i:i + 2]
        for i in python_utils.RANGE(
            0, len(flattened_last_two_message_models_of_threads), 2)
    ]

    thread_summaries = []
    number_of_unread_threads = 0
    for thread, last_two_message_models, thread_user_model, exp_model in (
            python_utils.ZIP(threads, last_two_message_models_of_threads,
                             exp_thread_user_models, exp_models)):
        message_ids_read_by_user = (() if thread_user_model is None else
                                    thread_user_model.message_ids_read_by_user)

        last_message_model, second_last_message_model = last_two_message_models
        # We don't need to check if the last message is None because all threads
        # have at least one message.
        last_message_is_read = (last_message_model.message_id
                                in message_ids_read_by_user)
        author_last_message = (last_message_model.author_id
                               and user_services.get_username(
                                   last_message_model.author_id))
        # The second-to-last message, however, might be None.
        second_last_message_is_read = (second_last_message_model is not None
                                       and second_last_message_model.message_id
                                       in message_ids_read_by_user)
        author_second_last_message = (second_last_message_model
                                      and second_last_message_model.author_id
                                      and user_services.get_username(
                                          second_last_message_model.author_id))

        if not last_message_is_read:
            number_of_unread_threads += 1
        thread_summaries.append(
            feedback_domain.FeedbackThreadSummary(
                thread.status, thread.original_author_id, thread.last_updated,
                last_message_model.text, thread.message_count,
                last_message_is_read, second_last_message_is_read,
                author_last_message, author_second_last_message,
                exp_model.title, exp_model.id, thread.id))
    return thread_summaries, number_of_unread_threads
Ejemplo n.º 31
0
 def test_get_username_none(self):
     user_services.get_or_create_user('fakeUser', '*****@*****.**')
     self.assertEquals(None, user_services.get_username('fakeUser'))
Ejemplo n.º 32
0
def _assign_role(
        committer_id, assignee_id, new_role, activity_id, activity_type):
    """Args:
    - committer_id: str. The user_id of the user who is performing the action.
    - activity_rights: The storage object for the rights of this activity (
        one of: ExplorationRightsModel or CollectionRightsModel).
    - assignee_id: str. The user_id of the user whose role is being changed.
    - new_role: str. The name of the new role: either 'owner', 'editor' or
        'viewer'.
    - activity_id: str. The ID of the exploration or collection.
    - activity_type: str. One of feconf.ACTIVITY_TYPE_EXPLORATION or
        feconf.ACTIVITY_TYPE_COLLECTION.
    """
    if not Actor(committer_id).can_modify_roles(activity_type, activity_id):
        logging.error(
            'User %s tried to allow user %s to be a(n) %s of activity %s '
            'but was refused permission.' % (
                committer_id, assignee_id, new_role, activity_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    activity_rights = _get_activity_rights(activity_type, activity_id)

    assignee_username = user_services.get_username(assignee_id)
    old_role = ROLE_NONE

    if new_role == ROLE_OWNER:
        if Actor(assignee_id)._is_owner(activity_rights):  # pylint: disable=protected-access
            raise Exception('This user already owns this %s.' % activity_type)

        activity_rights.owner_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER
        if assignee_id in activity_rights.editor_ids:
            activity_rights.editor_ids.remove(assignee_id)
            old_role = ROLE_EDITOR

    elif new_role == ROLE_EDITOR:
        if Actor(assignee_id)._has_editing_rights(activity_rights):  # pylint: disable=protected-access
            raise Exception(
                'This user already can edit this %s.' % activity_type)

        if activity_rights.community_owned:
            raise Exception(
                'Community-owned %ss can be edited by anyone.' % activity_type)

        activity_rights.editor_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER

    elif new_role == ROLE_VIEWER:
        if Actor(assignee_id)._has_viewing_rights(activity_rights):  # pylint: disable=protected-access
            raise Exception(
                'This user already can view this %s.' % activity_type)

        if activity_rights.status != ACTIVITY_STATUS_PRIVATE:
            raise Exception(
                'Public %ss can be viewed by anyone.' % activity_type)

        activity_rights.viewer_ids.append(assignee_id)

    else:
        raise Exception('Invalid role: %s' % new_role)

    commit_message = 'Changed role of %s from %s to %s' % (
        assignee_username, old_role, new_role)
    commit_cmds = [{
        'cmd': CMD_CHANGE_ROLE,
        'assignee_id': assignee_id,
        'old_role': old_role,
        'new_role': new_role
    }]

    _save_activity_rights(committer_id, activity_rights, activity_type,
                          commit_message, commit_cmds)
    _update_activity_summary(activity_type, activity_rights)
Ejemplo n.º 33
0
 def test_get_username_for_nonexistent_user(self):
     with self.assertRaisesRegexp(Exception, 'User not found.'):
         user_services.get_username('fakeUser')
Ejemplo n.º 34
0
def assign_role(committer_id, exploration_id, assignee_id, new_role):
    """Assign `assignee_id` to the given role and subscribes the assignee
    to future exploration updates.

    The caller should ensure that assignee_id corresponds to a valid user in
    the system.

    Args:
    - committer_id: str. The user_id of the user who is performing the action.
    - exploration_id: str. The exploration id.
    - assignee_id: str. The user_id of the user whose role is being changed.
    - new_role: str. The name of the new role: either 'owner', 'editor' or
        'viewer'.
    """

    if not Actor(committer_id).can_modify_roles(exploration_id):
        logging.error(
            'User %s tried to allow user %s to be a(n) %s of exploration %s '
            'but was refused permission.' %
            (committer_id, assignee_id, new_role, exploration_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    assignee_username = user_services.get_username(assignee_id)
    old_role = ROLE_NONE

    if new_role == ROLE_OWNER:
        if Actor(assignee_id).is_owner(exploration_id):
            raise Exception('This user already owns this exploration.')

        exp_rights = get_exploration_rights(exploration_id)
        exp_rights.owner_ids.append(assignee_id)

        if assignee_id in exp_rights.viewer_ids:
            exp_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER
        if assignee_id in exp_rights.editor_ids:
            exp_rights.editor_ids.remove(assignee_id)
            old_role = ROLE_EDITOR

    elif new_role == ROLE_EDITOR:
        if Actor(assignee_id).has_explicit_editing_rights(exploration_id):
            raise Exception('This user already can edit this exploration.')

        exp_rights = get_exploration_rights(exploration_id)
        if exp_rights.community_owned:
            raise Exception(
                'Community-owned explorations can be edited by anyone.')

        exp_rights.editor_ids.append(assignee_id)

        if assignee_id in exp_rights.viewer_ids:
            exp_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER

    elif new_role == ROLE_VIEWER:
        if Actor(assignee_id).has_explicit_viewing_rights(exploration_id):
            raise Exception('This user already can view this exploration.')

        exp_rights = get_exploration_rights(exploration_id)
        if exp_rights.status != EXPLORATION_STATUS_PRIVATE:
            raise Exception('Public explorations can be viewed by anyone.')

        exp_rights.viewer_ids.append(assignee_id)

    else:
        raise Exception('Invalid role: %s' % new_role)

    commit_message = 'Changed role of %s from %s to %s' % (assignee_username,
                                                           old_role, new_role)
    commit_cmds = [{
        'cmd': CMD_CHANGE_ROLE,
        'assignee_id': assignee_id,
        'old_role': old_role,
        'new_role': new_role
    }]

    _save_exploration_rights(committer_id, exp_rights, commit_message,
                             commit_cmds)

    if new_role in [ROLE_OWNER, ROLE_EDITOR]:
        subscription_services.subscribe_to_activity(assignee_id,
                                                    exploration_id)
Ejemplo n.º 35
0
def _assign_role(
        committer_id, assignee_id, new_role, activity_id, activity_type):
    """Args:
    - committer_id: str. The user_id of the user who is performing the action.
    - activity_rights: The storage object for the rights of this activity (
        one of: ExplorationRightsModel or CollectionRightsModel).
    - assignee_id: str. The user_id of the user whose role is being changed.
    - new_role: str. The name of the new role: either 'owner', 'editor' or
        'viewer'.
    - activity_id: str. The ID of the exploration or collection.
    - activity_type: str. One of ACTIVITY_TYPE_EXPLORATION or
        ACTIVITY_TYPE_COLLECTION.
    """
    if not Actor(committer_id).can_modify_roles(activity_type, activity_id):
        logging.error(
            'User %s tried to allow user %s to be a(n) %s of activity %s '
            'but was refused permission.' % (
                committer_id, assignee_id, new_role, activity_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    activity_rights = _get_activity_rights(activity_type, activity_id)

    assignee_username = user_services.get_username(assignee_id)
    old_role = ROLE_NONE

    if new_role == ROLE_OWNER:
        if Actor(assignee_id)._is_owner(activity_rights):  # pylint: disable=protected-access
            raise Exception('This user already owns this %s.' % activity_type)

        activity_rights.owner_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER
        if assignee_id in activity_rights.editor_ids:
            activity_rights.editor_ids.remove(assignee_id)
            old_role = ROLE_EDITOR

    elif new_role == ROLE_EDITOR:
        if Actor(assignee_id)._has_editing_rights(activity_rights):  # pylint: disable=protected-access
            raise Exception(
                'This user already can edit this %s.'  % activity_type)

        if activity_rights.community_owned:
            raise Exception(
                'Community-owned %ss can be edited by anyone.' % activity_type)

        activity_rights.editor_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER

    elif new_role == ROLE_VIEWER:
        if Actor(assignee_id)._has_viewing_rights(activity_rights):  # pylint: disable=protected-access
            raise Exception(
                'This user already can view this %s.' % activity_type)

        if activity_rights.status != ACTIVITY_STATUS_PRIVATE:
            raise Exception(
                'Public %ss can be viewed by anyone.' % activity_type)

        activity_rights.viewer_ids.append(assignee_id)

    else:
        raise Exception('Invalid role: %s' % new_role)

    commit_message = 'Changed role of %s from %s to %s' % (
        assignee_username, old_role, new_role)
    commit_cmds = [{
        'cmd': CMD_CHANGE_ROLE,
        'assignee_id': assignee_id,
        'old_role': old_role,
        'new_role': new_role
    }]

    _save_activity_rights(committer_id, activity_rights, activity_type,
                          commit_message, commit_cmds)
    _update_activity_summary(activity_type, activity_rights)
Ejemplo n.º 36
0
def get_thread_summaries(user_id, full_thread_ids):
    """Returns a list of summaries corresponding to each of the threads given.
    It also returns the number of threads that are currently not read by the
    user.

    Args:
        user_id: str. The id of the user.
        full_thread_ids: str. The complete ids of the threads for which we have
            to fetch the summaries.

    Returns:
        list(dict). A list of dictionaries containing the summaries of the
            threads given to it. Each dict has the following keys:
            - 'status': str. The status of the thread.
            - 'original_author_id': str. The id of the original author of the
                thread.
            - 'last_updated': datetime.datetime. When was the thread last
                updated.
            - 'last_message_text': str. The text of the last message.
            - 'total_message_count': int. The total number of messages in the
                thread.
            - 'last_message_read': boolean. Whether the last message is read by
                the user.
            - 'second_last_message_read': boolean. Whether the second last
                message is read by the user,
            - 'author_last_message': str. The name of the author of the last
                message.
            - 'author_second_last_message': str. The name of the author of the
                second last message.
            - 'exploration_title': str. The title of the exploration to which
                exploration belongs.
        int. The number of threads not read by the user.
    """
    exploration_ids, thread_ids = (
        feedback_models.FeedbackThreadModel.get_exploration_and_thread_ids(
            full_thread_ids))

    thread_model_ids = ([
        feedback_models.FeedbackThreadModel.generate_full_thread_id(
            exploration_id, thread_id)
        for exploration_id, thread_id in zip(exploration_ids, thread_ids)
    ])

    feedback_thread_user_model_ids = ([
        feedback_models.FeedbackThreadUserModel.generate_full_id(
            user_id, exploration_id, thread_id)
        for exploration_id, thread_id in zip(exploration_ids, thread_ids)
    ])

    multiple_models = (
        datastore_services.fetch_multiple_entities_by_ids_and_models([
            ('FeedbackThreadModel', thread_model_ids),
            ('FeedbackThreadUserModel', feedback_thread_user_model_ids),
            ('ExplorationModel', exploration_ids),
        ]))

    thread_models = multiple_models[0]
    feedback_thread_user_models = multiple_models[1]
    explorations = multiple_models[2]

    threads = [
        _get_thread_from_model(thread_model) for thread_model in thread_models
    ]

    last_two_messages_ids = []
    for thread in threads:
        last_two_messages_ids += thread.get_last_two_message_ids()

    messages = feedback_models.FeedbackMessageModel.get_multi(
        last_two_messages_ids)

    last_two_messages = [messages[i:i + 2] for i in range(0, len(messages), 2)]

    thread_summaries = []
    number_of_unread_threads = 0
    for index, thread in enumerate(threads):
        feedback_thread_user_model_exists = (feedback_thread_user_models[index]
                                             is not None)
        if feedback_thread_user_model_exists:
            last_message_read = (
                last_two_messages[index][0].message_id
                in feedback_thread_user_models[index].message_ids_read_by_user)
        else:
            last_message_read = False

        if last_two_messages[index][0].author_id is None:
            author_last_message = None
        else:
            author_last_message = user_services.get_username(
                last_two_messages[index][0].author_id)

        second_last_message_read = None
        author_second_last_message = None

        does_second_message_exist = (last_two_messages[index][1] is not None)
        if does_second_message_exist:
            if feedback_thread_user_model_exists:
                second_last_message_read = (
                    last_two_messages[index][1].message_id
                    in feedback_thread_user_models[index].message_ids_read_by_user)  # pylint: disable=line-too-long
            else:
                second_last_message_read = False

            if last_two_messages[index][1].author_id is None:
                author_second_last_message = None
            else:
                author_second_last_message = user_services.get_username(
                    last_two_messages[index][1].author_id)
        if not last_message_read:
            number_of_unread_threads += 1

        if thread.message_count:
            total_message_count = thread.message_count
        # TODO(Arunabh): Remove else clause after each thread has a message
        # count.
        else:
            total_message_count = (
                feedback_models.FeedbackMessageModel.get_message_count(
                    thread.exploration_id, thread.get_thread_id()))

        thread_summary = {
            'status': thread.status,
            'original_author_id': thread.original_author_id,
            'last_updated': utils.get_time_in_millisecs(thread.last_updated),
            'last_message_text': last_two_messages[index][0].text,
            'total_message_count': total_message_count,
            'last_message_read': last_message_read,
            'second_last_message_read': second_last_message_read,
            'author_last_message': author_last_message,
            'author_second_last_message': author_second_last_message,
            'exploration_title': explorations[index].title,
            'exploration_id': exploration_ids[index],
            'thread_id': thread_ids[index]
        }

        thread_summaries.append(thread_summary)

    return thread_summaries, number_of_unread_threads
Ejemplo n.º 37
0
    def test_get_thread_summaries(self):
        feedback_services.create_thread(
            'exploration', self.EXP_ID_1, self.user_id,
            self.EXPECTED_THREAD_DICT['subject'], 'not used here')
        feedback_services.create_thread(
            'exploration', self.EXP_ID_2, self.user_id,
            self.EXPECTED_THREAD_DICT['subject'], 'not used here')

        # The message count parameter is missing for this thread. The thread
        # summaries function should account for this and function
        # flawlessly.
        thread_3 = feedback_models.GeneralFeedbackThreadModel(
            id='exploration.' + self.EXP_ID_3 + '.' + self.THREAD_ID,
            entity_type='exploration', entity_id=self.EXP_ID_3,
            original_author_id=self.user_id, subject='Feedback',
            status=feedback_models.STATUS_CHOICES_OPEN, has_suggestion=False)
        thread_3.put()
        feedback_services.create_message(
            'exploration.' + self.EXP_ID_3 + '.' + self.THREAD_ID,
            self.user_id, None, None, 'not used here')


        thread_ids = subscription_services.get_all_threads_subscribed_to(
            self.user_id)
        thread_ids.append('exploration.' + self.EXP_ID_3 + '.' + self.THREAD_ID)
        thread_summaries, number_of_unread_threads = (
            feedback_services.get_thread_summaries(
                self.user_id, thread_ids))
        exploration_titles = (
            ['Bridges in England', 'Sillat Suomi', 'Leaning tower of Pisa'])

        # Fetch the threads.
        threads = []
        threads.append(feedback_services.get_thread(thread_ids[0]))
        threads.append(feedback_services.get_thread(thread_ids[1]))
        threads.append(feedback_services.get_thread(
            'exploration.' + self.EXP_ID_3 + '.' + self.THREAD_ID))
        # Check if the number of unread messages match.
        self.assertEqual(number_of_unread_threads, 0)
        for index, thread in enumerate(threads):
            thread_summary = {
                'status': thread.status,
                'original_author_id': thread.original_author_id,
                'last_updated': thread_summaries[index]['last_updated'],
                'last_message_text': 'not used here',
                'total_message_count': 1,
                'last_message_read': True,
                'second_last_message_read': None,
                'author_last_message': user_services.get_username(
                    self.user_id),
                'author_second_last_message': None,
                'exploration_title': exploration_titles[index]
            }
            # Check if the summaries match.
            self.assertDictContainsSubset(
                thread_summary, thread_summaries[index])

        feedback_services.create_message(
            threads[0].id, self.owner_id, None, None, 'editor message')
        _, number_of_unread_threads = (
            feedback_services.get_thread_summaries(self.user_id, thread_ids))

        # Check if the number of unread messages is equal to 1.
        self.assertEqual(number_of_unread_threads, 1)
Ejemplo n.º 38
0
 feconf.EMAIL_INTENT_FEEDBACK_MESSAGE_NOTIFICATION: (
     lambda x: x == feconf.SYSTEM_COMMITTER_ID),
 feconf.EMAIL_INTENT_SUGGESTION_NOTIFICATION: (
     lambda x: x == feconf.SYSTEM_COMMITTER_ID),
 feconf.EMAIL_INTENT_SUBSCRIPTION_NOTIFICATION: (
     lambda x: x == feconf.SYSTEM_COMMITTER_ID),
 feconf.EMAIL_INTENT_QUERY_STATUS_NOTIFICATION: (
     lambda x: x == feconf.SYSTEM_COMMITTER_ID),
 feconf.EMAIL_INTENT_MARKETING: (
     lambda x: rights_manager.Actor(x).is_admin()),
 feconf.EMAIL_INTENT_DELETE_EXPLORATION: (
     lambda x: rights_manager.Actor(x).is_moderator()),
 feconf.EMAIL_INTENT_REPORT_BAD_CONTENT: (
     lambda x: x == feconf.SYSTEM_COMMITTER_ID),
 feconf.BULK_EMAIL_INTENT_MARKETING: (
     lambda x: user_services.get_username(x) in
     config_domain.WHITELISTED_EMAIL_SENDERS.value),
 feconf.BULK_EMAIL_INTENT_IMPROVE_EXPLORATION: (
     lambda x: user_services.get_username(x) in
     config_domain.WHITELISTED_EMAIL_SENDERS.value),
 feconf.BULK_EMAIL_INTENT_CREATE_EXPLORATION: (
     lambda x: user_services.get_username(x) in
     config_domain.WHITELISTED_EMAIL_SENDERS.value),
 feconf.BULK_EMAIL_INTENT_CREATOR_REENGAGEMENT: (
     lambda x: user_services.get_username(x) in
     config_domain.WHITELISTED_EMAIL_SENDERS.value),
 feconf.BULK_EMAIL_INTENT_LEARNER_REENGAGEMENT: (
     lambda x: user_services.get_username(x) in
     config_domain.WHITELISTED_EMAIL_SENDERS.value),
 feconf.BULK_EMAIL_INTENT_TEST: (
     lambda x: user_services.get_username(x) in
Ejemplo n.º 39
0
def _assign_role(committer, assignee_id, new_role, activity_id, activity_type):
    """Assigns a new role to the user.

    Args:
        committer: UserActionsInfo. UserActionInfo object for the user
            who is performing the action.
        assignee_id: str. ID of the user whose role is being changed.
        new_role: str. The name of the new role: One of
            ROLE_OWNER,
            ROLE_EDITOR,
            ROLE_VOICE_ARTIST,
            ROLE_VIEWER.
        activity_id: str. ID of the activity.
        activity_type: str. The type of activity. Possible values:
            constants.ACTIVITY_TYPE_EXPLORATION,
            constants.ACTIVITY_TYPE_COLLECTION.

    Raises:
        Exception. The committer does not have rights to modify a role.
        Exception. The user already owns the activity.
        Exception. The user can already edit the activity.
        Exception. The user can already voiceover the activity.
        Exception. The activity is already publicly editable.
        Exception. The activity is already publicly translatable.
        Exception. The user can already view the activity.
        Exception. The activity is already publicly viewable.
        Exception. The role is invalid.
    """
    committer_id = committer.user_id
    activity_rights = _get_activity_rights(activity_type, activity_id)

    if not check_can_modify_activity_roles(committer, activity_rights):
        logging.error(
            'User %s tried to allow user %s to be a(n) %s of activity %s '
            'but was refused permission.' %
            (committer_id, assignee_id, new_role, activity_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    assignee_username = user_services.get_username(assignee_id)
    old_role = rights_domain.ROLE_NONE

    if new_role == rights_domain.ROLE_OWNER:
        if activity_rights.is_owner(assignee_id):
            raise Exception('This user already owns this %s.' % activity_type)

        activity_rights.owner_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VIEWER
        if assignee_id in activity_rights.editor_ids:
            activity_rights.editor_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_EDITOR
        if assignee_id in activity_rights.voice_artist_ids:
            activity_rights.voice_artist_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VOICE_ARTIST

    elif new_role == rights_domain.ROLE_EDITOR:
        if (activity_rights.is_editor(assignee_id)
                or activity_rights.is_owner(assignee_id)):
            raise Exception('This user already can edit this %s.' %
                            activity_type)

        activity_rights.editor_ids.append(assignee_id)

        if assignee_id in activity_rights.voice_artist_ids:
            activity_rights.voice_artist_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VOICE_ARTIST

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VIEWER

    elif new_role == rights_domain.ROLE_VOICE_ARTIST:
        if (activity_rights.is_editor(assignee_id)
                or activity_rights.is_voice_artist(assignee_id)
                or activity_rights.is_owner(assignee_id)):
            raise Exception('This user already can voiceover this %s.' %
                            activity_type)

        activity_rights.voice_artist_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VIEWER

    elif new_role == rights_domain.ROLE_VIEWER:
        if (activity_rights.is_owner(assignee_id)
                or activity_rights.is_editor(assignee_id)
                or activity_rights.is_viewer(assignee_id)):
            raise Exception('This user already can view this %s.' %
                            activity_type)

        if activity_rights.status != rights_domain.ACTIVITY_STATUS_PRIVATE:
            raise Exception('Public %ss can be viewed by anyone.' %
                            activity_type)

        activity_rights.viewer_ids.append(assignee_id)

    else:
        raise Exception('Invalid role: %s' % new_role)

    commit_message = 'Changed role of %s from %s to %s' % (assignee_username,
                                                           old_role, new_role)
    commit_cmds = [{
        'cmd': rights_domain.CMD_CHANGE_ROLE,
        'assignee_id': assignee_id,
        'old_role': old_role,
        'new_role': new_role
    }]

    _save_activity_rights(committer_id, activity_rights, activity_type,
                          commit_message, commit_cmds)
    _update_activity_summary(activity_type, activity_rights)
Ejemplo n.º 40
0
def _deassign_role(committer, removed_user_id, activity_id, activity_type):
    """Deassigns given user from their current role in the activity.

    Args:
        committer: UserActionsInfo. UserActionsInfo object for the user
            who is performing the action.
        removed_user_id: str. ID of the user who is being deassigned from
            the activity.
        activity_id: str. ID of the activity.
        activity_type: str. The type of activity. Possible values:
            constants.ACTIVITY_TYPE_EXPLORATION,
            constants.ACTIVITY_TYPE_COLLECTION.

    Raises:
        Exception. UnauthorizedUserException: Could not deassign role.
        Exception. This user does not have any role for the given activity.
    """
    committer_id = committer.user_id
    activity_rights = _get_activity_rights(activity_type, activity_id)

    if not check_can_modify_activity_roles(committer, activity_rights):
        logging.error(
            'User %s tried to remove user %s from an activity %s '
            'but was refused permission.' % (
                committer_id, removed_user_id, activity_id))
        raise Exception(
            'UnauthorizedUserException: Could not deassign role.')

    if activity_rights.is_owner(removed_user_id):
        old_role = rights_domain.ROLE_OWNER
        activity_rights.owner_ids.remove(removed_user_id)
    elif activity_rights.is_editor(removed_user_id):
        old_role = rights_domain.ROLE_EDITOR
        activity_rights.editor_ids.remove(removed_user_id)
    elif activity_rights.is_voice_artist(removed_user_id):
        old_role = rights_domain.ROLE_VOICE_ARTIST
        activity_rights.voice_artist_ids.remove(removed_user_id)
    elif activity_rights.is_viewer(removed_user_id):
        old_role = rights_domain.ROLE_VIEWER
        activity_rights.viewer_ids.remove(removed_user_id)
    else:
        raise Exception(
            'This user does not have any role in %s with ID %s'
            % (activity_type, activity_id))

    assignee_username = user_services.get_username(removed_user_id)
    commit_message = 'Remove %s from role %s for %s' % (
        assignee_username, old_role, activity_type)
    commit_cmds = [{
        'cmd': rights_domain.CMD_REMOVE_ROLE,
        'removed_user_id': removed_user_id,
        'old_role': old_role,
    }]

    _save_activity_rights(
        committer_id,
        activity_rights,
        activity_type,
        commit_message,
        commit_cmds
    )
    _update_activity_summary(activity_type, activity_rights)
Ejemplo n.º 41
0
def accept_suggestion(suggestion, reviewer_id, commit_message, review_message):
    """Accepts the given suggestion after validating it.

    Args:
        suggestion: Suggestion. The suggestion to be accepted.
        reviewer_id: str. The ID of the reviewer accepting the suggestion.
        commit_message: str. The commit message.
        review_message: str. The message provided by the reviewer while
            accepting the suggestion.

    Raises:
        Exception. The suggestion is already handled.
        Exception. The suggestion is not valid.
        Exception. The commit message is empty.
    """
    if suggestion.is_handled:
        raise Exception(
            'The suggestion with id %s has already been accepted/rejected.' % (
                suggestion.suggestion_id)
        )
    if not commit_message or not commit_message.strip():
        raise Exception('Commit message cannot be empty.')
    suggestion.pre_accept_validate()
    html_string = ''.join(suggestion.get_all_html_content_strings())
    error_list = (
        html_validation_service.
        validate_math_tags_in_html_with_attribute_math_content(
            html_string))
    if len(error_list) > 0:
        raise Exception(
            'Invalid math tags found in the suggestion with id %s.' % (
                suggestion.suggestion_id)
        )

    author_name = user_services.get_username(suggestion.author_id)
    commit_message = get_commit_message_for_suggestion(
        author_name, commit_message)
    mark_review_completed(
        suggestion, suggestion_models.STATUS_ACCEPTED, reviewer_id)
    suggestion.accept(commit_message)
    thread_id = suggestion.suggestion_id
    feedback_services.create_message(
        thread_id, reviewer_id, feedback_models.STATUS_CHOICES_FIXED,
        None, review_message)

    if feconf.ENABLE_RECORDING_OF_SCORES:
        increment_score_for_user(
            suggestion.author_id, suggestion.score_category,
            suggestion_models.INCREMENT_SCORE_OF_AUTHOR_BY)
        if feconf.SEND_SUGGESTION_REVIEW_RELATED_EMAILS:
            scores = get_all_scores_of_user(suggestion.author_id)
            if (
                    suggestion.score_category in scores and
                    scores[suggestion.score_category] >=
                    feconf.MINIMUM_SCORE_REQUIRED_TO_REVIEW):
                if not check_if_email_has_been_sent_to_user(
                        suggestion.author_id, suggestion.score_category):
                    email_manager.send_mail_to_onboard_new_reviewers(
                        suggestion.author_id, suggestion.score_category)
                    mark_email_has_been_sent_to_user(
                        suggestion.author_id, suggestion.score_category)
Ejemplo n.º 42
0
def assign_role(committer, assignee, new_role, story_id):
    """Assigns a new role to the user.

    Args:
        committer: UserActionsInfo. UserActionsInfo object for the user
            who is performing the action.
        assignee: UserActionsInfo. UserActionsInfo object for the user
            whose role is being changed.
        new_role: str. The name of the new role. Possible values are:
            ROLE_MANAGER
        story_id: str. ID of the story.

    Raises:
        Exception. The committer does not have rights to modify a role.
        Exception. The assignee is already a manager for the story.
        Exception. The assignee doesn't have enough rights to become a manager.
        Exception. The role is invalid.
    """
    committer_id = committer.user_id
    story_rights = get_story_rights(story_id)
    if (role_services.ACTION_MODIFY_ROLES_FOR_ANY_ACTIVITY
            not in committer.actions):
        logging.error('User %s tried to allow user %s to be a %s of story %s '
                      'but was refused permission.' %
                      (committer_id, assignee.user_id, new_role, story_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    assignee_username = user_services.get_username(assignee.user_id)
    if role_services.ACTION_EDIT_OWNED_STORY not in assignee.actions:
        raise Exception(
            'The assignee doesn\'t have enough rights to become a manager.')

    old_role = story_domain.ROLE_NONE
    if story_rights.is_manager(assignee.user_id):
        old_role = story_domain.ROLE_MANAGER

    if new_role == story_domain.ROLE_MANAGER:
        if story_rights.is_manager(assignee.user_id):
            raise Exception('This user already is a manager for this story')
        story_rights.manager_ids.append(assignee.user_id)
    elif new_role == story_domain.ROLE_NONE:
        if story_rights.is_manager(assignee.user_id):
            story_rights.manager_ids.remove(assignee.user_id)
        else:
            raise Exception('This user already has no role for this story')
    else:
        raise Exception('Invalid role: %s' % new_role)

    commit_message = 'Changed role of %s from %s to %s' % (assignee_username,
                                                           old_role, new_role)
    commit_cmds = [
        story_domain.StoryRightsChange({
            'cmd': story_domain.CMD_CHANGE_ROLE,
            'assignee_id': assignee.user_id,
            'old_role': old_role,
            'new_role': new_role
        })
    ]

    save_story_rights(story_rights, committer_id, commit_message, commit_cmds)
Ejemplo n.º 43
0
 def test_get_username_none(self):
     user_services._create_user('fakeUser', '*****@*****.**')
     self.assertEquals(None, user_services.get_username('fakeUser'))
Ejemplo n.º 44
0
def assign_role(committer_id, exploration_id, assignee_id, new_role):
    """Assign `assignee_id` to the given role.

    The caller should ensure that assignee_id corresponds to a valid user in
    the system.

    Args:
    - committer_id: str. The user_id of the user who is performing the action.
    - exploration_id: str. The exploration id.
    - assignee_id: str. The user_id of the user whose role is being changed.
    - new_role: str. The name of the new role: either 'owner', 'editor' or
        'viewer'.
    """

    if not Actor(committer_id).can_modify_roles(exploration_id):
        logging.error(
            'User %s tried to allow user %s to be a(n) %s of exploration %s '
            'but was refused permission.' % (
                committer_id, assignee_id, new_role, exploration_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    assignee_username = user_services.get_username(assignee_id)
    old_role = ROLE_NONE

    if new_role == ROLE_OWNER:
        if Actor(assignee_id).is_owner(exploration_id):
            raise Exception('This user already owns this exploration.')

        exp_rights = get_exploration_rights(exploration_id)
        exp_rights.owner_ids.append(assignee_id)

        if assignee_id in exp_rights.viewer_ids:
            exp_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER
        if assignee_id in exp_rights.editor_ids:
            exp_rights.editor_ids.remove(assignee_id)
            old_role = ROLE_EDITOR

    elif new_role == ROLE_EDITOR:
        if Actor(assignee_id).has_explicit_editing_rights(exploration_id):
            raise Exception('This user already can edit this exploration.')

        exp_rights = get_exploration_rights(exploration_id)
        if exp_rights.community_owned:
            raise Exception(
                'Community-owned explorations can be edited by anyone.')

        exp_rights.editor_ids.append(assignee_id)

        if assignee_id in exp_rights.viewer_ids:
            exp_rights.viewer_ids.remove(assignee_id)
            old_role = ROLE_VIEWER

    elif new_role == ROLE_VIEWER:
        if Actor(assignee_id).has_explicit_viewing_rights(exploration_id):
            raise Exception('This user already can view this exploration.')

        exp_rights = get_exploration_rights(exploration_id)
        if exp_rights.status != EXPLORATION_STATUS_PRIVATE:
            raise Exception(
                'Public explorations can be viewed by anyone.')

        exp_rights.viewer_ids.append(assignee_id)

    else:
        raise Exception('Invalid role: %s' % new_role)

    commit_message = 'Changed role of %s from %s to %s' % (
        assignee_username, old_role, new_role)
    commit_cmds = [{
        'cmd': CMD_CHANGE_ROLE,
        'assignee_id': assignee_id,
        'old_role': old_role,
        'new_role': new_role
    }]

    _save_exploration_rights(
        committer_id, exp_rights, commit_message, commit_cmds)
Ejemplo n.º 45
0
def _assign_role(committer,
                 assignee_id,
                 new_role,
                 activity_id,
                 activity_type,
                 allow_assigning_any_role=False):
    """Assigns a new role to the user.

    Args:
        committer: UserActionsInfo. UserActionInfo object for the user
            who is performing the action.
        assignee_id: str. ID of the user whose role is being changed.
        new_role: str. The name of the new role: One of
            ROLE_OWNER,
            ROLE_EDITOR,
            ROLE_VOICE_ARTIST,
            ROLE_VIEWER.
        activity_id: str. ID of the activity.
        activity_type: str. The type of activity. Possible values:
            constants.ACTIVITY_TYPE_EXPLORATION,
            constants.ACTIVITY_TYPE_COLLECTION.
        allow_assigning_any_role: bool. Whether to assign a role to the user
            irrespective of whether they have any existing role in the activity.
            The default value is false.

    Raises:
        Exception. The committer does not have rights to modify a role.
        Exception. The user already owns the activity.
        Exception. The user can already edit the activity.
        Exception. The user can already voiceover the activity.
        Exception. The activity is already publicly editable.
        Exception. The activity is already publicly translatable.
        Exception. The user can already view the activity.
        Exception. The activity is already publicly viewable.
        Exception. The role is invalid.
    """
    committer_id = committer.user_id
    activity_rights = _get_activity_rights(activity_type, activity_id)

    user_can_assign_role = False
    if new_role == rights_domain.ROLE_VOICE_ARTIST and (
            activity_type == constants.ACTIVITY_TYPE_EXPLORATION):
        user_can_assign_role = check_can_manage_voice_artist_in_activity(
            committer, activity_rights)
    else:
        user_can_assign_role = check_can_modify_core_activity_roles(
            committer, activity_rights)

    if not user_can_assign_role:
        logging.error(
            'User %s tried to allow user %s to be a(n) %s of activity %s '
            'but was refused permission.' %
            (committer_id, assignee_id, new_role, activity_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    assignee_username = user_services.get_username(assignee_id)
    old_role = rights_domain.ROLE_NONE

    if new_role not in [
            rights_domain.ROLE_OWNER, rights_domain.ROLE_EDITOR,
            rights_domain.ROLE_VOICE_ARTIST, rights_domain.ROLE_VIEWER
    ]:
        raise Exception('Invalid role: %s' % new_role)
    # TODO(#12369): Currently, only exploration allows reassigning users to
    # any role. We are expecting to remove the below check and allow this
    # function to assign any role in general once the collection is removed.
    if allow_assigning_any_role:
        old_role = activity_rights.assign_new_role(assignee_id, new_role)

    elif new_role == rights_domain.ROLE_OWNER:
        if activity_rights.is_owner(assignee_id):
            raise Exception('This user already owns this %s.' % activity_type)

        activity_rights.owner_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VIEWER
        if assignee_id in activity_rights.editor_ids:
            activity_rights.editor_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_EDITOR
        if assignee_id in activity_rights.voice_artist_ids:
            activity_rights.voice_artist_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VOICE_ARTIST

    elif new_role == rights_domain.ROLE_EDITOR:

        if (activity_rights.is_editor(assignee_id)
                or activity_rights.is_owner(assignee_id)):
            raise Exception('This user already can edit this %s.' %
                            activity_type)

        activity_rights.editor_ids.append(assignee_id)

        if assignee_id in activity_rights.voice_artist_ids:
            activity_rights.voice_artist_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VOICE_ARTIST

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VIEWER

    elif new_role == rights_domain.ROLE_VOICE_ARTIST:

        if (activity_rights.is_editor(assignee_id)
                or activity_rights.is_voice_artist(assignee_id)
                or activity_rights.is_owner(assignee_id)):
            raise Exception('This user already can voiceover this %s.' %
                            activity_type)

        activity_rights.voice_artist_ids.append(assignee_id)

        if assignee_id in activity_rights.viewer_ids:
            activity_rights.viewer_ids.remove(assignee_id)
            old_role = rights_domain.ROLE_VIEWER

    elif new_role == rights_domain.ROLE_VIEWER:

        if (activity_rights.is_owner(assignee_id)
                or activity_rights.is_editor(assignee_id)
                or activity_rights.is_viewer(assignee_id)):
            raise Exception('This user already can view this %s.' %
                            activity_type)

        if activity_rights.status != rights_domain.ACTIVITY_STATUS_PRIVATE:
            raise Exception('Public %ss can be viewed by anyone.' %
                            activity_type)

        activity_rights.viewer_ids.append(assignee_id)

    commit_message = rights_domain.ASSIGN_ROLE_COMMIT_MESSAGE_TEMPLATE % (
        assignee_username, old_role, new_role)
    commit_cmds = [{
        'cmd': rights_domain.CMD_CHANGE_ROLE,
        'assignee_id': assignee_id,
        'old_role': old_role,
        'new_role': new_role
    }]

    _save_activity_rights(committer_id, activity_rights, activity_type,
                          commit_message, commit_cmds)
    _update_activity_summary(activity_type, activity_rights)
Ejemplo n.º 46
0
 def test_get_username_none(self):
     user_services._create_user('fakeUser', '*****@*****.**')
     self.assertEquals(None, user_services.get_username('fakeUser'))
Ejemplo n.º 47
0
 def test_get_username_for_nonexistent_user(self):
     with self.assertRaisesRegexp(Exception, 'User not found.'):
         user_services.get_username('fakeUser')
Ejemplo n.º 48
0
 def get_author_name(self):
     return user_services.get_username(self.author_id)
Ejemplo n.º 49
0
def assign_role(committer, assignee, new_role, topic_id):
    """Assigns a new role to the user.

    Args:
        committer: UserActionsInfo. UserActionsInfo object for the user
            who is performing the action.
        assignee: UserActionsInfo. UserActionsInfo object for the user
            whose role is being changed.
        new_role: str. The name of the new role. Possible values are:
            ROLE_MANAGER.
        topic_id: str. ID of the topic.

    Raises:
        Exception. The committer does not have rights to modify a role.
        Exception. The assignee is already a manager for the topic.
        Exception. The assignee doesn't have enough rights to become a manager.
        Exception. The role is invalid.
    """
    committer_id = committer.user_id
    topic_rights = topic_fetchers.get_topic_rights(topic_id)
    if (role_services.ACTION_MODIFY_CORE_ROLES_FOR_ANY_ACTIVITY
            not in committer.actions):
        logging.error('User %s tried to allow user %s to be a %s of topic %s '
                      'but was refused permission.' %
                      (committer_id, assignee.user_id, new_role, topic_id))
        raise Exception(
            'UnauthorizedUserException: Could not assign new role.')

    assignee_username = user_services.get_username(assignee.user_id)
    if role_services.ACTION_EDIT_OWNED_TOPIC not in assignee.actions:
        raise Exception(
            'The assignee doesn\'t have enough rights to become a manager.')

    old_role = topic_domain.ROLE_NONE
    if topic_rights.is_manager(assignee.user_id):
        old_role = topic_domain.ROLE_MANAGER

    if new_role == topic_domain.ROLE_MANAGER:
        if topic_rights.is_manager(assignee.user_id):
            raise Exception('This user already is a manager for this topic')
        topic_rights.manager_ids.append(assignee.user_id)
    elif new_role == topic_domain.ROLE_NONE:
        if topic_rights.is_manager(assignee.user_id):
            topic_rights.manager_ids.remove(assignee.user_id)
        else:
            old_role = topic_domain.ROLE_NONE
    else:
        raise Exception('Invalid role: %s' % new_role)

    commit_message = rights_domain.ASSIGN_ROLE_COMMIT_MESSAGE_TEMPLATE % (
        assignee_username, old_role, new_role)
    commit_cmds = [
        topic_domain.TopicRightsChange({
            'cmd': topic_domain.CMD_CHANGE_ROLE,
            'assignee_id': assignee.user_id,
            'old_role': old_role,
            'new_role': new_role
        })
    ]

    save_topic_rights(topic_rights, committer_id, commit_message, commit_cmds)
Ejemplo n.º 50
0
    (lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_FEEDBACK_MESSAGE_NOTIFICATION:
    (lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_SUGGESTION_NOTIFICATION:
    (lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_SUBSCRIPTION_NOTIFICATION:
    (lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_QUERY_STATUS_NOTIFICATION:
    (lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_MARKETING:
    (lambda x: rights_manager.Actor(x).is_admin()),
    feconf.EMAIL_INTENT_DELETE_EXPLORATION:
    (lambda x: rights_manager.Actor(x).is_moderator()),
    feconf.EMAIL_INTENT_REPORT_BAD_CONTENT:
    (lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.BULK_EMAIL_INTENT_MARKETING: (lambda x: user_services.get_username(
        x) in config_domain.WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_IMPROVE_EXPLORATION:
    (lambda x: user_services.get_username(x) in config_domain.
     WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_CREATE_EXPLORATION:
    (lambda x: user_services.get_username(x) in config_domain.
     WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_CREATOR_REENGAGEMENT:
    (lambda x: user_services.get_username(x) in config_domain.
     WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_LEARNER_REENGAGEMENT:
    (lambda x: user_services.get_username(x) in config_domain.
     WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_TEST: (lambda x: user_services.get_username(
        x) in config_domain.WHITELISTED_EMAIL_SENDERS.value)
}
Ejemplo n.º 51
0
 def get_author_name(self):
     return user_services.get_username(self.author_id)
Ejemplo n.º 52
0
    feconf.EMAIL_INTENT_EDITOR_ROLE_NOTIFICATION: (
        lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_FEEDBACK_MESSAGE_NOTIFICATION: (
        lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_SUGGESTION_NOTIFICATION: (
        lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_QUERY_STATUS_NOTIFICATION: (
        lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.EMAIL_INTENT_MARKETING: (
        lambda x: rights_manager.Actor(x).is_admin()),
    feconf.EMAIL_INTENT_DELETE_EXPLORATION: (
        lambda x: rights_manager.Actor(x).is_moderator()),
    feconf.EMAIL_INTENT_REPORT_BAD_CONTENT: (
        lambda x: x == feconf.SYSTEM_COMMITTER_ID),
    feconf.BULK_EMAIL_INTENT_MARKETING: (
        lambda x: user_services.get_username(x) in
        config_domain.WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_IMPROVE_EXPLORATION: (
        lambda x: user_services.get_username(x) in
        config_domain.WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_CREATE_EXPLORATION: (
        lambda x: user_services.get_username(x) in
        config_domain.WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_CREATOR_REENGAGEMENT: (
        lambda x: user_services.get_username(x) in
        config_domain.WHITELISTED_EMAIL_SENDERS.value),
    feconf.BULK_EMAIL_INTENT_LEARNER_REENGAGEMENT: (
        lambda x: user_services.get_username(x) in
        config_domain.WHITELISTED_EMAIL_SENDERS.value)
}