Skip to content

Commit ee6ed22

Browse files
committed
Add "add email" button to admin user profile
1 parent 1272b0e commit ee6ed22

File tree

5 files changed

+64
-1
lines changed

5 files changed

+64
-1
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{% if perms.osf.change_osfuser %}
2+
<a data-toggle="modal" data-target="#addEmailModal" class="btn btn-default">Add email</a>
3+
<div class="modal" id="addEmailModal">
4+
<div class="modal-dialog">
5+
<div class="modal-content">
6+
<form class="well" method="post" action="{% url 'users:add-email' guid=user.guid %}">
7+
<div class="modal-header">
8+
<button type="button" class="close" data-dismiss="modal">x</button>
9+
<h3>Add email to user</h3>
10+
</div>
11+
<div class="modal-body">
12+
<h4>User: {{ user.guid }}</h4>
13+
{% csrf_token %}
14+
<label for="id_new_email">Email address</label>
15+
<input type="email" name="new_email" id="id_new_email" class="form-control" required />
16+
</div>
17+
<div class="modal-footer">
18+
<input class="btn btn-primary" type="submit" value="Add and send confirmation" />
19+
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
20+
</div>
21+
</form>
22+
</div>
23+
</div>
24+
</div>
25+
{% endif %}
26+
27+

admin/templates/users/user.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<div class="btn-group" role="group">
2121
<a href="{% url 'users:search' %}" class="btn btn-default"><i class="fa fa-search"></i></a>
2222
{% include "users/reset_password.html" with user=user %}
23+
{% include "users/add_email.html" with user=user %}
2324
{% if perms.osf.change_osfuser %}
2425
<a href="{% url 'users:get-reset-password' guid=user.guid %}" data-toggle="modal" data-target="#getResetModal" class="btn btn-default">Get password reset link</a>
2526
{% if user.confirmed %}

admin/users/forms.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ class MergeUserForm(forms.Form):
2323

2424
class AddSystemTagForm(forms.Form):
2525
system_tag_to_add = forms.CharField(label='system_tag_to_add', min_length=1, max_length=1024, required=True)
26+
27+
28+
class AddEmailForm(forms.Form):
29+
new_email = forms.EmailField(label='new_email', required=True)

admin/users/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
re_path(r'^(?P<guid>[a-z0-9]+)/get_reset_password/$', views.GetPasswordResetLink.as_view(), name='get-reset-password'),
2626
re_path(r'^(?P<guid>[a-z0-9]+)/reindex_elastic_user/$', views.UserReindexElastic.as_view(),
2727
name='reindex-elastic-user'),
28+
re_path(r'^(?P<guid>[a-z0-9]+)/add_email/$', views.UserAddEmail.as_view(), name='add-email'),
2829
re_path(r'^(?P<guid>[a-z0-9]+)/merge_accounts/$', views.UserMergeAccounts.as_view(), name='merge-accounts'),
2930
re_path(r'^(?P<guid>[a-z0-9]+)/draft_registrations/$', views.UserDraftRegistrationsList.as_view(), name='draft-registrations'),
3031
]

admin/users/views.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
EmailResetForm,
4444
UserSearchForm,
4545
MergeUserForm,
46-
AddSystemTagForm
46+
AddSystemTagForm,
47+
AddEmailForm
4748
)
4849
from admin.base.views import GuidView
4950
from api.users.services import send_password_reset_email
@@ -399,6 +400,35 @@ def form_valid(self, form):
399400
return super().form_valid(form)
400401

401402

403+
class UserAddEmail(UserMixin, FormView):
404+
"""Allows authorized users to add an email to a user's account and trigger confirmation."""
405+
permission_required = 'osf.change_osfuser'
406+
raise_exception = True
407+
form_class = AddEmailForm
408+
409+
def form_valid(self, form):
410+
from osf.exceptions import BlockedEmailError
411+
from django.core.exceptions import ValidationError as DjangoValidationError
412+
from framework.auth.views import send_confirm_email_async
413+
from django.utils import timezone
414+
415+
user = self.get_object()
416+
address = form.cleaned_data['new_email'].strip().lower()
417+
try:
418+
user.add_unconfirmed_email(address)
419+
420+
send_confirm_email_async(user, email=address)
421+
user.email_last_sent = timezone.now()
422+
user.save()
423+
messages.success(self.request, f'Added unconfirmed email {address} and sent confirmation email.')
424+
except (DjangoValidationError, ValueError) as e:
425+
messages.error(self.request, f'Invalid email: {getattr(e, "message", str(e))}')
426+
except BlockedEmailError:
427+
messages.error(self.request, 'This email address domain is blocked.')
428+
429+
return super().form_valid(form)
430+
431+
402432
class UserMergeAccounts(UserMixin, FormView):
403433
""" Allows authorized users to merge a user's accounts using their guid.
404434
"""

0 commit comments

Comments
 (0)