Beispiel #1
0
  def testIsValidEmail(self):
    """Tests the Email validator class."""
    for email in self.GOOD_EMAIL_ADDRESSES:
      self.assertTrue(validate.IsValidEmail(email), msg='Rejected:%r' % email)

    for email in self.BAD_EMAIL_ADDRESSES:
      self.assertFalse(validate.IsValidEmail(email), msg='Accepted:%r' % email)
Beispiel #2
0
def LinkifyEmail(_mr, autolink_regex_match, component_ref_artifacts):
    """Examine a textual reference and replace it with a hyperlink or not.

  This is a callback for use with the autolink feature.  The function
  parameters are standard for this type of callback.

  Args:
    _mr: unused information parsed from the HTTP request.
    autolink_regex_match: regex match for the textual reference.
    component_ref_artifacts: result of call to GetReferencedUsers.

  Returns:
    A list of TextRuns with tag=a linking to the user profile page of
    any defined users, otherwise a mailto: link is generated.
  """
    email = autolink_regex_match.group(0)

    if not validate.IsValidEmail(email):
        return [template_helpers.TextRun(email)]

    if component_ref_artifacts and email in component_ref_artifacts:
        href = '/u/%s' % email
    else:
        href = 'mailto:' + email

    result = [template_helpers.TextRun(email, tag='a', href=href)]
    return result
Beispiel #3
0
    def LookupUserIDs(self, cnxn, emails, autocreate=False, allowgroups=False):
        """Return a dict of user IDs for the given emails.

    Args:
      cnxn: connection to SQL database.
      emails: list of string email addresses.
      autocreate: set to True to create users that were not found.
      allowgroups: set to True to allow non-email user name for group
      creation.

    Returns:
      A dict {email_addr: user_id} for the requested emails.

    Raises:
      exceptions.NoSuchUserException: if some users were not found and
          autocreate is False.
    """
        # Skip any addresses that look like "--" or are empty,
        # because that means "no user".
        # Also, make sure all email addresses are lower case.
        needed_emails = [
            email.lower() for email in emails
            if email and not framework_constants.NO_VALUE_RE.match(email)
        ]

        # Look up these users in the RAM cache
        user_id_dict = self.LookupExistingUserIDs(cnxn, needed_emails)
        if len(needed_emails) == len(user_id_dict):
            logging.info('found all %d emails', len(user_id_dict))
            return user_id_dict

        # If any were not found in the DB, create them or raise an exception.
        nonexist_emails = [
            email for email in needed_emails if email not in user_id_dict
        ]
        logging.info('nonexist_emails: %r, autocreate is %r', nonexist_emails,
                     autocreate)
        if not autocreate:
            raise exceptions.NoSuchUserException('%r' % nonexist_emails)

        if not allowgroups:
            # Only create accounts for valid email addresses.
            nonexist_emails = [
                email for email in nonexist_emails
                if validate.IsValidEmail(email)
            ]
            if not nonexist_emails:
                return user_id_dict

        self._CreateUsers(cnxn, nonexist_emails)
        created_rows = self.user_tbl.Select(cnxn,
                                            cols=['email', 'user_id'],
                                            email=nonexist_emails)
        created_dict = dict(created_rows)
        # Cache all the user IDs that we retrieved to make later requests faster.
        self.user_id_cache.CacheAll(created_dict)
        user_id_dict.update(created_dict)

        logging.info('looked up User IDs %r', user_id_dict)
        return user_id_dict
Beispiel #4
0
def _ParseOneRule(cnxn, predicate, action_type, action_value, user_service,
                  rule_num, error_list):
    """Parse one FilterRule based on the action type."""
    if action_type == 'default_status':
        status = framework_bizobj.CanonicalizeLabel(action_value)
        rule = MakeRule(predicate, default_status=status)

    elif action_type == 'default_owner':
        if action_value:
            try:
                user_id = user_service.LookupUserID(cnxn, action_value)
            except user_svc.NoSuchUserException:
                user_id = framework_constants.NO_USER_SPECIFIED
                error_list.append('Rule %d: No such user: %s' %
                                  (rule_num, action_value))
        else:
            user_id = framework_constants.NO_USER_SPECIFIED
        rule = MakeRule(predicate, default_owner_id=user_id)

    elif action_type == 'add_ccs':
        cc_ids = []
        for email in re.split('[,;\s]+', action_value):
            if not email.strip():
                continue
            try:
                user_id = user_service.LookupUserID(cnxn,
                                                    email.strip(),
                                                    autocreate=True)
                cc_ids.append(user_id)
            except user_svc.NoSuchUserException:
                error_list.append('Rule %d: No such user: %s' %
                                  (rule_num, email.strip()))

        rule = MakeRule(predicate, add_cc_ids=cc_ids)

    elif action_type == 'add_labels':
        add_labels = framework_constants.IDENTIFIER_RE.findall(action_value)
        rule = MakeRule(predicate, add_labels=add_labels)

    elif action_type == 'also_notify':
        add_notify = []
        for addr in re.split('[,;\s]+', action_value):
            if validate.IsValidEmail(addr.strip()):
                add_notify.append(addr.strip())
            else:
                error_list.append('Rule %d: Invalid email address: %s' %
                                  (rule_num, addr.strip()))

        rule = MakeRule(predicate, add_notify=add_notify)

    else:
        logging.info('unexpected action type, probably tampering:%r',
                     action_type)
        raise monorailrequest.InputException()

    return rule
Beispiel #5
0
def Linkify(_mr, autolink_regex_match, _component_ref_artifacts):
    """Examine a textual reference and replace it with a hyperlink or not.

  This is a callback for use with the autolink feature.  The function
  parameters are standard for this type of callback.

  Args:
    _mr: unused information parsed from the HTTP request.
    autolink_regex_match: regex match for the textual reference.
    _component_ref_artifacts: unused result of call to GetReferencedIssues.

  Returns:
    A list of TextRuns with tag=a for all matched ftp, http, https and mailto
    links converted into HTML hyperlinks.
  """
    hyperlink = autolink_regex_match.group(0)

    trailing = ''
    for begin, end in _LINK_TRAILING_CHARS:
        if hyperlink.endswith(end):
            if not begin or hyperlink[:-len(end)].find(begin) == -1:
                trailing = end + trailing
                hyperlink = hyperlink[:-len(end)]

    tag_match = _CLOSING_TAG_RE.search(hyperlink)
    if tag_match:
        trailing = hyperlink[tag_match.start(0):] + trailing
        hyperlink = hyperlink[:tag_match.start(0)]

    href = hyperlink
    if not href.lower().startswith(('http', 'ftp', 'mailto')):
        # We use http because redirects for https are not all set up.
        href = 'http://' + href

    if (not validate.IsValidURL(href)
            and not (href.startswith('mailto')
                     and validate.IsValidEmail(href[7:]))):
        return [template_helpers.TextRun(autolink_regex_match.group(0))]

    result = [template_helpers.TextRun(hyperlink, tag='a', href=href)]
    if trailing:
        result.append(template_helpers.TextRun(trailing))

    return result
    def ProcessFormData(self, mr, post_data):
        """Process the posted form."""
        # 1. Parse and validate user input.
        summary, description = self._ParseMeta(post_data, mr.errors)
        access = project_helpers.ParseProjectAccess(mr.project,
                                                    post_data.get('access'))

        only_owners_remove_restrictions = ('only_owners_remove_restrictions'
                                           in post_data)
        only_owners_see_contributors = 'only_owners_see_contributors' in post_data

        issue_notify = post_data['issue_notify']
        if issue_notify and not validate.IsValidEmail(issue_notify):
            mr.errors.issue_notify = _MSG_INVALID_EMAIL_ADDRESS

        process_inbound_email = 'process_inbound_email' in post_data
        home_page = post_data.get('project_home')
        if home_page and not (home_page.startswith('http:')
                              or home_page.startswith('https:')):
            mr.errors.project_home = 'Home page link must start with http: or https:'
        docs_url = post_data.get('docs_url')
        if docs_url and not (docs_url.startswith('http:')
                             or docs_url.startswith('https:')):
            mr.errors.docs_url = 'Documentation link must start with http: or https:'
        source_url = post_data.get('source_url')
        if source_url and not (source_url.startswith('http:')
                               or source_url.startswith('https:')):
            mr.errors.source_url = 'Source link must start with http: or https:'

        logo_gcs_id = ''
        logo_file_name = ''
        if 'logo' in post_data and not isinstance(post_data['logo'],
                                                  basestring):
            item = post_data['logo']
            logo_file_name = item.filename
            try:
                logo_gcs_id = gcs_helpers.StoreLogoInGCS(
                    logo_file_name, item.value, mr.project.project_id)
            except gcs_helpers.UnsupportedMimeType, e:
                mr.errors.logo = e.message
Beispiel #7
0
def _Linkify(autolink_regex_match, shorthand=False):
    """Examine a textual reference and replace it with a hyperlink or not.

  This is a callback for use with the autolink feature.

  Args:
    autolink_regex_match: regex match for the textual reference.
    shorthand: Set to True to allow shorthand links without "http".

  Returns:
    A list of TextRuns with tag=a for all matched ftp, http, https and mailto
    links converted into HTML hyperlinks.
  """
    hyperlink = autolink_regex_match.group(0)

    trailing = ''
    for begin, end in _LINK_TRAILING_CHARS:
        if hyperlink.endswith(end):
            if not begin or hyperlink[:-len(end)].find(begin) == -1:
                trailing = end + trailing
                hyperlink = hyperlink[:-len(end)]

    tag_match = _CLOSING_TAG_RE.search(hyperlink)
    if tag_match:
        trailing = hyperlink[tag_match.start(0):] + trailing
        hyperlink = hyperlink[:tag_match.start(0)]

    href = hyperlink
    if shorthand and not href.lower().startswith('http'):
        # We use http because redirects for https are not all set up.
        href = 'http://' + href

    if (not validate.IsValidURL(href) and not validate.IsValidEmail(href)):
        return [template_helpers.TextRun(autolink_regex_match.group(0))]

    result = [template_helpers.TextRun(hyperlink, tag='a', href=href)]
    if trailing:
        result.append(template_helpers.TextRun(trailing))

    return result
Beispiel #8
0
def IngestUserRefs(cnxn, user_refs, user_service, autocreate=False):
    """Return IDs of specified users or raise NoSuchUserException."""

    # Filter out user_refs with invalid display_names.
    # Invalid emails won't get auto-created in LookupUserIds, but un-specified
    # user_ref.user_id values have the zero-value 0. So invalid user_ref's
    # need to be filtered out here to prevent these resulting in '0's in
    # the 'result' array.
    if autocreate:
        user_refs = [
            user_ref for user_ref in user_refs if (not user_ref.display_name)
            or validate.IsValidEmail(user_ref.display_name)
        ]

    # 1. Verify that all specified user IDs actually match existing users.
    user_ids_to_verify = [
        user_ref.user_id for user_ref in user_refs if user_ref.user_id
    ]
    user_service.LookupUserEmails(cnxn, user_ids_to_verify)

    # 2. Lookup or create any users that are specified by email address.
    needed_emails = [
        user_ref.display_name for user_ref in user_refs
        if not user_ref.user_id and user_ref.display_name
    ]
    emails_to_ids = user_service.LookupUserIDs(cnxn,
                                               needed_emails,
                                               autocreate=autocreate)

    # 3. Build the result from emails_to_ids or straight from user_ref's
    # user_id.
    # Note: user_id can be specified as 0 to clear the issue owner.
    result = [
        emails_to_ids.get(user_ref.display_name, user_ref.user_id)
        for user_ref in user_refs
    ]
    return result