Confirm login and allow reset

This commit is contained in:
Jay McCarthy 2013-10-14 15:05:25 -06:00
parent 6380adeed3
commit c53fa19f1f
4 changed files with 115 additions and 76 deletions

View File

@ -116,45 +116,69 @@
['email email] ['email email]
['passwd passwd] ['passwd passwd]
['code email-code]) ['code email-code])
(match (ensure-authenticate email passwd (λ () #t))
["failed" #f]
["new-user"
(define passwd-path (build-path users.new-path email))
(define passwd-path (build-path users.new-path email))
(define (generate-a-code email)
(define correct-email-code
(number->string (random (expt 10 8))))
(hash-set! email-codes email correct-email-code)
correct-email-code)
(define (check-code-or true false)
(cond (cond
[(and (not (string=? "" email-code)) [(and (not (string=? "" email-code))
(hash-ref email-codes email #f)) (hash-ref email-codes email #f))
=> (λ (correct-email-code) => (λ (correct-email-code)
(cond (cond
[(equal? correct-email-code email-code) [(equal? correct-email-code email-code)
(when (not (file-exists? passwd-path))
(display-to-file (bcrypt-encode (string->bytes/utf-8 passwd)) (display-to-file (bcrypt-encode (string->bytes/utf-8 passwd))
passwd-path)) passwd-path
#:exists 'replace)
(hash-remove! email-codes email) (hash-remove! email-codes email)
#t] (true)]
[else [else
"wrong-code"]))] "wrong-code"]))]
[else [else
(define correct-email-code (false)
(number->string (random (expt 10 8))))
(hash-set! email-codes email correct-email-code) #f]))
(match (ensure-authenticate email passwd (λ () #t))
["failed"
(check-code-or
(λ () (hasheq 'curation (curation-administrator? email)))
(λ ()
(send-mail-message (send-mail-message
"pkg@racket-lang.org" "pkg@racket-lang.org"
"Account confirmation for Racket PNR" "Account password reset for Racket Package Catalog"
(list email) (list email)
empty empty empty empty
(list "Someone tried to register your email address for an account on the Racket Package Catalog." (list
"Someone tried to login with your email address for an account on the Racket Package Catalog, but failed."
"If you this was you, please use this code to reset your password:"
""
(generate-a-code email)
""
"This code will expire, so if it is not available, you'll have to try to again."))))]
["new-user"
(check-code-or
(λ () #t)
(λ ()
(send-mail-message
"pkg@racket-lang.org"
"Account confirmation for Racket Package Catalog"
(list email)
empty empty
(list
"Someone tried to register your email address for an account on the Racket Package Catalog."
"If you want to proceed, use this code:" "If you want to proceed, use this code:"
"" ""
correct-email-code (generate-a-code email)
"" ""
"This code will expire, so if it is not available, you'll have to try to register again.")) "This code will expire, so if it is not available, you'll have to try to register again."))))]
"emailed"])]
[#t [#t
(hasheq 'curation (curation-administrator? email))])) (hasheq 'curation (curation-administrator? email))]))

View File

@ -19,15 +19,26 @@
<div id="login" class="package"> <div id="login" class="package">
<table> <table>
<tr><td>Email Address:</td><td><input id="login_email_text" type="text"></td></tr> <tr><td>Email Address:</td><td><input id="login_email_text" type="text"></td></tr>
<tr><td id="login_passwd_label">Password:</td><td><input id="login_passwd_text" type="password"></td></tr> <tr><td>Password:</td><td><input id="login_passwd_text" type="password"></td></tr>
<tr id="login_confirm_row"><td>Confirm Password:</td><td><input id="login_confirm_text" type="password"></td></tr>
<tr id="login_code_row"><td>Email Code:</td><td><input id="login_code_text" type="password"></td></tr>
<tr><td colspan="2" id="login_error"></td></tr> <tr><td colspan="2" id="login_error"></td></tr>
</table> </table>
<button id="login_button">Log In</button> <button id="login_button">Log In</button>
<p>If you enter an unclaimed email address, then an account will <p>If you enter an unclaimed email address, then we will email
be created with the password you type in, after you confirm you a code. If you type in that code and confirm the password
the email address.</p> you typed in, then we will create an account for you with the
<p>Passwords are stored in the delicious bcrypt format, but given password.</p>
transferred as plain-text over an HTTPS connection.</p> <p>If you enter an claimed email address, but an incorrect
password, then we will email you a code. If you type in that
code and confirm the password you typed in, then we will change
your password to the one you typed in.</p>
<p>Passwords are transferred over an HTTPS connection, but not
the same connection you got this page from. The passwords are
transferred in plain-text, but stored on the server in the
delicious bcrypt format. This means that someone could hack
our server and watch you transmit your password live but not
be able to use our password database.</p>
</div> </div>
<div id="package_info" class="package"> <div id="package_info" class="package">

View File

@ -399,39 +399,36 @@ $( document ).ready(function() {
position: { my: "center", at: "center", of: "#search_menu" }, position: { my: "center", at: "center", of: "#search_menu" },
modal: true }); modal: true });
var saved_password = false;
function login_submit () { function login_submit () {
$( "#login_error" ).html( "" ); $( "#login_error" ).html( "" );
var et = $( "#login_email_text" ); var e = $( "#login_email_text" ).val();
var pt = $( "#login_passwd_text" ); var p = $( "#login_passwd_text" ).val();
var cp = $( "#login_confirm_text" ).val();
var c = $( "#login_code_text" ).val();
var e = et.val(); if ( c && p != cp ) {
var p; $( "#login_error" ).html( "You did not type in the same password." ); }
var c;
if ( saved_password ) {
p = saved_password;
c = pt.val(); }
else { else {
p = pt.val();
c = ""; }
$.getJSON( dynamic_url("/jsonp/authenticate"), $.getJSON( dynamic_url("/jsonp/authenticate"),
{ email: e, passwd: p, code: c }, { email: e, passwd: p, code: c },
function( resp ) { function( resp ) {
if ( resp == "emailed" ) { if ( resp == "emailed" ) {
saved_password = p; $( "#login_confirm_row" ).show();
$( "#login_passwd_label" ).html( "Code:" ); $( "#login_code_row" ).show();
pt.val("");
$( "#login_error" ).html( "Check your email for an email code." ); } $( "#login_error" ).html( "Check your email for an email code." ); }
else if ( resp == "wrong-code" ) { else if ( resp == "wrong-code" ) {
pt.val(""); $( "#login_code_text" ).val("");
$( "#login_error" ).html( "That is not the correct code." ); } $( "#login_error" ).html( "That is not the correct code." ); }
else if ( resp ) { else if ( resp ) {
$( "#login_passwd_label" ).html( "Password:" ); $( "#login_email_text" ).val("");
$( "#login_passwd_text" ).val("");
$( "#login_confirm_text" ).val("");
$( "#login_code_text" ).val("");
et.val(""); $( "#login_confirm_row" ).hide();
pt.val(""); $( "#login_code_row" ).hide();
localStorage['email'] = e; localStorage['email'] = e;
localStorage['passwd'] = p; localStorage['passwd'] = p;
@ -440,12 +437,19 @@ $( document ).ready(function() {
initial_login(); } initial_login(); }
else { else {
pt.val(""); $( "#login_confirm_row" ).show();
$( "#login_error" ).html( "Incorrect password, please retry" ); }; } ); } $( "#login_code_row" ).show();
$( "#login_error" ).html( "Incorrect password, please retry or check your email for a change password code." ); }; } ); } }
$( "#login_passwd_text" ).keypress( function (e) { $( "#login_passwd_text" ).keypress( function (e) {
if (e.which == 13) { login_submit (); } } ); if (e.which == 13) { login_submit (); } } );
$( "#login_code_text" ).keypress( function (e) {
if (e.which == 13) { login_submit (); } } );
$( "#login_button" ).click( function (e) { login_submit (); } ); $( "#login_button" ).click( function (e) { login_submit (); } );
$( "#login_confirm_row" ).hide();
$( "#login_code_row" ).hide();
function menu_logout () { function menu_logout () {
$("#logout").html( jslink( "login", function () { $( "#login" ).dialog( "open" ); } ) ); } $("#logout").html( jslink( "login", function () { $( "#login" ).dialog( "open" ); } ) ); }
function menu_loggedin ( curate_p ) { function menu_loggedin ( curate_p ) {

View File

@ -146,7 +146,7 @@ a.inactive {
a.possible { a.possible {
} }
#login table tr:nth-child(3) td { #login table tr:nth-child(5) td {
text-align: center; text-align: center;
color: red; color: red;
} }