Commit bb3046bd by David Ormsbee

Merge pull request #897 from MITx/feature/dave/email_bugfixes

Login/Profile changes
parents 4cadbcc5 9fbdeeb6
......@@ -262,10 +262,15 @@ def login_user(request, error=""):
try_change_enrollment(request)
return HttpResponse(json.dumps({'success': True}))
log.warning("Login failed - Account not active for user {0}".format(username))
log.warning("Login failed - Account not active for user {0}, resending activation".format(username))
reactivation_email_for_user(user)
not_activated_msg = "This account has not been activated. We have " + \
"sent another activation message. Please check your " + \
"e-mail for the activation instructions."
return HttpResponse(json.dumps({'success': False,
'value': 'This account has not been activated. Please check your e-mail for the activation instructions.'}))
'value': not_activated_msg}))
@ensure_csrf_cookie
......@@ -517,6 +522,17 @@ def password_reset(request):
''' Attempts to send a password reset e-mail. '''
if request.method != "POST":
raise Http404
# By default, Django doesn't allow Users with is_active = False to reset their passwords,
# but this bites people who signed up a long time ago, never activated, and forgot their
# password. So for their sake, we'll auto-activate a user for whome password_reset is called.
try:
user = User.objects.get(email=request.POST['email'])
user.is_active = True
user.save()
except:
log.exception("Tried to auto-activate user to enable password reset, but failed.")
form = PasswordResetForm(request.POST)
if form.is_valid():
form.save(use_https = request.is_secure(),
......@@ -529,7 +545,6 @@ def password_reset(request):
return HttpResponse(json.dumps({'success': False,
'error': 'Invalid e-mail'}))
@ensure_csrf_cookie
def reactivation_email(request):
''' Send an e-mail to reactivate a deactivated account, or to
......@@ -540,25 +555,22 @@ def reactivation_email(request):
except User.DoesNotExist:
return HttpResponse(json.dumps({'success': False,
'error': 'No inactive user with this e-mail exists'}))
return reactivation_email_for_user(user)
if user.is_active:
return HttpResponse(json.dumps({'success': False,
'error': 'User is already active'}))
def reactivation_email_for_user(user):
reg = Registration.objects.get(user=user)
reg.register(user)
d = {'name': UserProfile.get(user=user).name,
'key': r.activation_key}
d = {'name': user.profile.name,
'key': reg.activation_key}
subject = render_to_string('reactivation_email_subject.txt', d)
subject = render_to_string('emails/activation_email_subject.txt', d)
subject = ''.join(subject.splitlines())
message = render_to_string('reactivation_email.txt', d)
message = render_to_string('emails/activation_email.txt', d)
res = user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
return HttpResponse(json.dumps({'success': True}))
@ensure_csrf_cookie
def change_email_request(request):
......@@ -642,9 +654,12 @@ def confirm_email_change(request, key):
meta['old_emails'].append([user.email, datetime.datetime.now().isoformat()])
up.set_meta(meta)
up.save()
# Send it to the old email...
user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
user.email = pec.new_email
user.save()
pec.delete()
# And send it to the new email...
user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
return render_to_response("email_change_successful.html", d)
......@@ -665,9 +680,12 @@ def change_name_request(request):
pnc.rationale = request.POST['rationale']
if len(pnc.new_name) < 2:
return HttpResponse(json.dumps({'success': False, 'error': 'Name required'}))
if len(pnc.rationale) < 2:
return HttpResponse(json.dumps({'success': False, 'error': 'Rationale required'}))
pnc.save()
# The following automatically accepts name change requests. Remove this to
# go back to the old system where it gets queued up for admin approval.
accept_name_change_by_id(pnc.id)
return HttpResponse(json.dumps({'success': True}))
......@@ -702,14 +720,9 @@ def reject_name_change(request):
return HttpResponse(json.dumps({'success': True}))
@ensure_csrf_cookie
def accept_name_change(request):
''' JSON: Name change process. Course staff clicks 'accept' on a given name change '''
if not request.user.is_staff:
raise Http404
def accept_name_change_by_id(id):
try:
pnc = PendingNameChange.objects.get(id=int(request.POST['id']))
pnc = PendingNameChange.objects.get(id=id)
except PendingNameChange.DoesNotExist:
return HttpResponse(json.dumps({'success': False, 'error': 'Invalid ID'}))
......@@ -728,3 +741,17 @@ def accept_name_change(request):
pnc.delete()
return HttpResponse(json.dumps({'success': True}))
@ensure_csrf_cookie
def accept_name_change(request):
''' JSON: Name change process. Course staff clicks 'accept' on a given name change
We used this during the prototype but now we simply record name changes instead
of manually approving them. Still keeping this around in case we want to go
back to this approval method.
'''
if not request.user.is_staff:
raise Http404
return accept_name_change_by_id(int(request.POST['id']))
......@@ -16,19 +16,63 @@
$(".unenroll").click(function(event) {
$("#unenroll_course_id").val( $(event.target).data("course-id") );
$("#unenroll_course_number").text( $(event.target).data("course-number") );
});
$(document).delegate('#unenroll_form', 'ajax:success', function(data, json, xhr) {
if(json.success) {
location.href="${reverse('dashboard')}";
} else {
if($('#unenroll_error').length == 0) {
$('#unenroll_form').prepend('<div id="unenroll_error" class="modal-form-error"></div>');
}
$('#unenroll_error').text(json.error).stop().css("display", "block");
}
});
$('#pwd_reset_button').click(function() {
$.post('${reverse("password_reset")}',
{"email" : $('#id_email').val()},
function(data){
$("#password_reset_complete_link").click();
});
});
$("#change_email_form").submit(function(){
var new_email = $('#new_email_field').val();
var new_password = $('#new_email_password').val();
$.post('${reverse("change_email")}',
{"new_email" : new_email, "password" : new_password},
function(data) {
if (data.success) {
$("#change_email_title").html("Please verify your new email");
$("#change_email_form").html("<p>You'll receive a confirmation in your " +
"in-box. Please click the link in the " +
"email to confirm the email change.</p>");
} else {
$("#change_email_error").html(data.error).stop().css("display", "block");
}
});
return false;
});
$("#change_name_form").submit(function(){
var new_name = $('#new_name_field').val();
var rationale = $('#name_rationale_field').val();
$.post('${reverse("change_name")}',
{"new_name":new_name, "rationale":rationale},
function(data) {
if(data.success) {
location.reload();
// $("#change_name_body").html("<p>Name changed.</p>");
} else {
$("#change_name_error").html(data.error).stop().css("display", "block");
}
});
return false;
});
$(document).delegate('#unenroll_form', 'ajax:success', function(data, json, xhr) {
if(json.success) {
location.href="${reverse('dashboard')}";
} else {
if($('#unenroll_error').length == 0) {
$('#unenroll_form').prepend('<div id="unenroll_error" class="modal-form-error"></div>');
}
$('#unenroll_error').text(json.error).stop().css("display", "block");
}
});
})(this)
</script>
</%block>
......@@ -48,10 +92,17 @@
<section class="user-info">
<ul>
<li>
<span class="title"><div class="icon name-icon"></div>Full Name</span><span class="data">${ user.profile.name | h }</span>
<span class="title"><div class="icon name-icon"></div>Full Name (<a href="#apply_name_change" rel="leanModal" class="edit-name">edit</a>)</span> <span class="data">${ user.profile.name | h }</span>
</li>
<li>
<span class="title"><div class="icon email-icon"></div>Email</span><span class="data">${ user.email | h }</span>
<span class="title"><div class="icon email-icon"></div>Email (<a href="#change_email" rel="leanModal" class="edit-email">edit</a>)</span> <span class="data">${ user.email | h }</span>
</li>
<li>
<span class="title"><a href="#password_reset_complete" rel="leanModal" id="pwd_reset_button">Reset Password</a></span>
<form id="password_reset_form" method="post" data-remote="true" action="${reverse('password_reset')}">
<input id="id_email" type="hidden" name="email" maxlength="75" value="${user.email}" />
<!-- <input type="submit" id="pwd_reset_button" value="Reset Password" /> -->
</form>
</li>
</ul>
</section>
......@@ -121,13 +172,11 @@
</section>
</section>
<section id="unenroll-modal" class="modal unenroll-modal">
<div class="inner-wrapper">
<header>
<h2>Are you sure you want to unregister from <span id="unenroll_course_number"></span>?</h2>
<hr>
<hr/>
</header>
<form id="unenroll_form" method="post" data-remote="true" action="${reverse('change_enrollment')}">
......@@ -146,4 +195,89 @@
</div>
</section>
<section id="password_reset_complete" class="modal">
<div class="inner-wrapper">
<header>
<h2>Password Reset Email Sent</h2>
<hr/>
</header>
<div>
<form> <!-- Here for styling reasons -->
<section>
<p>An email has been sent to ${user.email}. Follow the link in the email to change your password.</p>
</section>
</form>
</div>
<div class="close-modal">
<div class="inner">
<p>&#10005;</p>
</div>
</div>
</div>
</section>
<section id="change_email" class="modal">
<div class="inner-wrapper">
<header>
<h2><span id="change_email_title">Change Email</span></h2>
<hr/>
</header>
<div id="change_email_body">
<form id="change_email_form">
<div id="change_email_error" class="modal-form-error"> </div>
<fieldset>
<div class="input-group">
<label>Please enter your new email address:</label>
<input id="new_email_field" type="email" value="" />
<label>Please confirm your password:</label>
<input id="new_email_password" value="" type="password" />
</div>
<section>
<p>We will send a confirmation to both ${user.email} and your new email as part of the process.</p>
</section>
<div class="submit">
<input type="submit" id="submit_email_change" value="Change Email"/>
</div>
</fieldset>
</form>
</div>
<div class="close-modal">
<div class="inner">
<p>&#10005;</p>
</div>
</div>
</div>
</section>
<section id="apply_name_change" class="modal">
<div class="inner-wrapper">
<header>
<h2>Change your name</h2>
<hr/>
</header>
<div id="change_name_body">
<form id="change_name_form">
<div id="change_name_error" class="modal-form-error"> </div>
<p>To uphold the credibility of edX certificates, all name changes will be logged and recorded.</p>
<br/>
<fieldset>
<div class="input-group">
<label>Enter your desired full name, as it will appear on the edX certificates: </label>
<input id="new_name_field" value="" type="text" />
<label>Reason for name change:</label>
<textarea id="name_rationale_field" value=""></textarea>
</div>
<div class="submit">
<input type="submit" id="submit" value="Change My Name">
</div>
</fieldset>
</form>
</div>
<div class="close-modal">
<div class="inner">
<p>&#10005;</p>
</div>
</div>
</div>
</section>
<h1>E-mail change successful!</h1>
<p> You should see your new name in your profile.
<p>You should see your new email in your <a href="/dashboard">dashboard</a>.</p>
\ No newline at end of file
<%! from django.core.urlresolvers import reverse %>
This is to confirm that you changed the e-mail associated with edX
from ${old_email} to ${new_email}. If you did not make this request,
please contact the course staff immediately. Contact information is
listed at:
please contact us immediately. Contact information is listed at:
% if is_secure:
https://${ site }${reverse('contact')}
......
......@@ -5,7 +5,8 @@
{% block reset_link %}
https://{{domain}}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }}
If you didn't request this change, you can disregard this email - we have not yet reset your password.
{% trans "Thanks for using our site!" %}
......
......@@ -19,9 +19,9 @@ urlpatterns = ('',
# (specifically missing get parameters in certain cases)
url(r'^debug_request$', 'util.views.debug_request'),
url(r'^change_email$', 'student.views.change_email_request'),
url(r'^change_email$', 'student.views.change_email_request', name="change_email"),
url(r'^email_confirm/(?P<key>[^/]*)$', 'student.views.confirm_email_change'),
url(r'^change_name$', 'student.views.change_name_request'),
url(r'^change_name$', 'student.views.change_name_request', name="change_name"),
url(r'^accept_name_change$', 'student.views.accept_name_change'),
url(r'^reject_name_change$', 'student.views.reject_name_change'),
url(r'^pending_name_changes$', 'student.views.pending_name_changes'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment