Skip to content

hg: add email validation for hg users (bug 1691635) - #217

Open
grottohub wants to merge 4 commits into
mainfrom
validate-hg-emails
Open

hg: add email validation for hg users (bug 1691635)#217
grottohub wants to merge 4 commits into
mainfrom
validate-hg-emails

Conversation

@grottohub

Copy link
Copy Markdown
Contributor

while moz-phab will hopefully catch invalid emails before they make it to lando now, this PR adds an extra safeguard against incorrectly configured mercurial users' commits landing in a repo

Bug 1691635 - Lando landed a commit without a valid email address

@grottohub
grottohub requested a review from zzzeid September 15, 2022 20:28
@grottohub
grottohub marked this pull request as ready for review September 15, 2022 20:28
Comment thread landoapi/hg.py Outdated
return f.read()

@staticmethod
def extract_email_from_username(username: Union[str, bytes]) -> str:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
def extract_email_from_username(username: Union[str, bytes]) -> str:
def extract_email_from_username(username: str | bytes) -> str:

Comment thread landoapi/hg.py Outdated

email = self.extract_email_from_username(user)
if not is_valid_email(email):
raise ValueError("Invalid email configured for Mercurial user!")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be helpful to include the email address here in the output.

Comment thread landoapi/hg.py Outdated
def extract_email_from_username(username: Union[str, bytes]) -> str:
"""Extracts an email from a Mercurial username, if it exists.
Not guaranteed to return a valid email, make sure to validate."""
return str(username).split("<").pop().replace(">", "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a regular expression. It would be good to add a unit test for this method as well.

Comment thread tests/test_validation.py
revision_id_to_int(123)


def test_is_valid_email():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More test cases can be added here (for example test <test> and test <test@test>. And perhaps a few malformed ones.

Comment thread landoapi/validation.py Outdated
from connexion import ProblemException

REVISION_ID_RE = re.compile(r"^D(?P<id>[1-9][0-9]*)$")
VALID_EMAIL_RE = re.compile(r"[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n]+")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be a misnomer since it could catch invalid email addresses too. Maybe ACCEPTED_EMAIL_RE is a better name. There probably is a more suitable regex that is available on the internet.

An example of an invalid email that will pass the above: -@...

Comment thread landoapi/validation.py Outdated


def is_valid_email(email: str) -> bool:
"""Given a string, determines if it is a valid email."""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can probably put the regex pattern here, and describe in more detail in the docstring what it's doing.

Comment thread landoapi/hg.py
Comment on lines +529 to +530
"""Extracts an email from a Mercurial username, if it exists.
Not guaranteed to return a valid email, make sure to validate."""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See pep 257.

Suggested change
"""Extracts an email from a Mercurial username, if it exists.
Not guaranteed to return a valid email, make sure to validate."""
"""Extracts an email from a Mercurial username, if it exists.
Not guaranteed to return a valid email, make sure to validate."""

@grottohub
grottohub requested a review from zzzeid September 28, 2022 17:15

@zzzeid zzzeid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought I would leave the comments here explicitly (though we chatted about them a while ago over Zoom). Main comment is re: the use of replace.

Comment thread landoapi/hg.py
def extract_email_from_username(username: str | bytes) -> str:
"""Extracts an email from a Mercurial username, if it exists.

Not guaranteed to return a valid email, make sure to validate."""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Not guaranteed to return a valid email, make sure to validate."""
Not guaranteed to return a valid email, make sure to validate.
"""

Comment thread landoapi/hg.py
Comment on lines +536 to +538
email = search(r"<.*?>", str(username))
if email:
return email.group(0).replace("<", "").replace(">", "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified/cleaned up using grouping.

Comment thread tests/test_validation.py
Comment on lines +46 to +47
assert True not in [is_valid_email(value) for value in invalid_emails]
assert False not in [is_valid_email(value) for value in valid_emails]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: more of a personal preference than anything else, but could be a little more human readable.

Suggested change
assert True not in [is_valid_email(value) for value in invalid_emails]
assert False not in [is_valid_email(value) for value in valid_emails]
assert not any(is_valid_email(value) for value in invalid_emails)
assert all(is_valid_email(value) for value in valid_emails)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants