Skip to content

Commit 58af78b

Browse files
committed
handle github noreply email addresses
1 parent b32a3e5 commit 58af78b

File tree

7 files changed

+83
-9
lines changed

7 files changed

+83
-9
lines changed

cla/events.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ async def handle_pull_request(event, gh, *args, **kwargs):
9999
signature = await Signature.objects.filter(
100100
Q(email_address__iexact=author.email) | Q(normalized_email__iexact=normalized_email)
101101
).afirst()
102+
103+
# Look for an existing signature from an un-masked email address
104+
if signature is None and author.email.endswith("@users.noreply.github.com"):
105+
signature = await Signature.objects.filter(github_login=author.login).afirst()
106+
102107
if signature is None:
103108
await PendingSignature.objects.aupdate_or_create(
104109
agreement=agreement,

clabot/forms.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django import forms
2+
3+
4+
class SignEmailForm(forms.Form):
5+
email = forms.ChoiceField(
6+
label="Select an email address for your signature.",
7+
help_text=(
8+
"Because you are using a GitHub noreply email address, "
9+
"we need you to choose one of your verified GitHub verified email addresses "
10+
"in order to sign."
11+
),
12+
widget=forms.Select,
13+
)

clabot/views.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from cla.events import handle_pull_request
1313
from cla.models import Agreement, PendingSignature, Signature
14+
from clabot.forms import SignEmailForm
1415

1516

1617
class HomePageView(TemplateView):
@@ -44,6 +45,16 @@ async def sign(request):
4445
agreement_id = request.GET.get("agreement_id")
4546
email_address = request.GET.get("email_address")
4647

48+
form = None
49+
if email_address.endswith("@users.noreply.github.com"):
50+
form = SignEmailForm(request.POST or None)
51+
_emails = await sync_to_async(request.session.get)("emails", [])
52+
form.fields["email"].choices = [("", "---")] + [
53+
(e["email"], e["email"])
54+
for e in _emails
55+
if e["verified"] and not e["email"].endswith("@users.noreply.github.com")
56+
]
57+
4758
pending_signatures = await sync_to_async(list)(
4859
PendingSignature.objects.filter(
4960
agreement_id=agreement_id, email_address__iexact=email_address
@@ -62,6 +73,20 @@ async def sign(request):
6273
return HttpResponseRedirect("/")
6374

6475
if request.method == "POST":
76+
if form:
77+
if form.is_valid():
78+
email_address = form.cleaned_data["email"]
79+
else:
80+
return render(
81+
request,
82+
"sign.html",
83+
context={
84+
"agreement": markdown.markdown(pending_signatures[0].agreement.document),
85+
"email_address": email_address,
86+
"form": form,
87+
},
88+
)
89+
6590
agreement = pending_signatures[0].agreement
6691
await Signature.objects.acreate(
6792
agreement=agreement,
@@ -116,5 +141,6 @@ async def sign(request):
116141
context={
117142
"agreement": markdown.markdown(pending_signatures[0].agreement.document),
118143
"email_address": email_address,
144+
"form": form,
119145
},
120146
)

github_auth/views.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,27 @@ def github_callback(request):
4545
user_data = requests.get(
4646
"https://api.github.com/user",
4747
headers={"Authorization": f'token {client.token["access_token"]}'},
48-
)
48+
).json()
4949
user_email_data = requests.get(
5050
"https://api.github.com/user/emails",
5151
headers={"Authorization": f'token {client.token["access_token"]}'},
52-
)
52+
).json()
5353

54-
request.session["username"] = user_data.json()["login"]
55-
request.session["emails"] = user_email_data.json()
54+
email_username = user_data["login"]
55+
email_user_id = user_data["id"]
56+
request.session["emails"] = user_email_data + [
57+
{
58+
"email": f"{email_user_id}+{email_username}@users.noreply.github.com",
59+
"verified": True,
60+
},
61+
{
62+
"email": f"{email_username}@users.noreply.github.com",
63+
"verified": True,
64+
},
65+
]
5666

57-
request.session["github_login"] = user_data.json()["login"]
58-
request.session["github_id"] = user_data.json()["id"]
59-
request.session["github_node_id"] = user_data.json()["node_id"]
67+
request.session["github_login"] = user_data["login"]
68+
request.session["github_id"] = user_data["id"]
69+
request.session["github_node_id"] = user_data["node_id"]
6070

6171
return HttpResponseRedirect("/awaiting/")

templates/awaiting_signature.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ <h2>{{ agreement.grouper }}</h2>
2828
</p>
2929
{% else %}
3030
<div class="button-container">
31-
<a class="button" href="/sign?agreement_id={{ agreement.grouper.id }}&email_address={{ email.grouper|urlencode }}">Review and Sign</a>
31+
<button>
32+
<a class="button" href="/sign?agreement_id={{ agreement.grouper.id }}&email_address={{ email.grouper|urlencode }}">Review and Sign</a>
33+
</button>
3234
</div>
3335
{% endif %}
3436
{% endfor %}

templates/base.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323
.button-container {
2424
text-align: center;
25-
margin: 3rem auto;
25+
margin: 1rem auto;
2626
}
2727
.button {
2828
padding: 1rem;
@@ -36,6 +36,8 @@
3636
}
3737
.sign-button {
3838
font-size: 2rem;
39+
padding-top: .5rem;
40+
padding-bottom: .5rem;
3941
padding-left: 3rem;
4042
padding-right: 3rem;
4143
}
@@ -48,8 +50,14 @@
4850
border-radius: .5rem;
4951
text-align: center;
5052
}
53+
.errorlist {
54+
margin-block-start: 0;
55+
margin-block-end: 0;
56+
color: #9e1b32;
57+
}
5158
button {
5259
-webkit-appearance: none;
60+
margin: 1rem;
5361
border-radius: 0;
5462
text-align: inherit;
5563
background: none;

templates/sign.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66

77
<form method="POST">
88
{% csrf_token %}
9+
{% if form %}
10+
<p>
11+
{{ form.email.label_tag }}
12+
{{ form.email }}<br>
13+
{% if form.email.errors %}{{ form.email.errors }}{% endif %}
14+
{% if form.email.help_text %}
15+
<small>{{ form.email.help_text }}</small>
16+
{% endif %}
17+
</p>
18+
{% endif %}
919
<div class="button-container">
1020
<button type="submit" class="button sign-button">Sign</button>
1121
<p>

0 commit comments

Comments
 (0)