From 6b05b55225bb9309b0973b87c820fb4a0e0c10bd Mon Sep 17 00:00:00 2001
From: Joseph Schorr <jschorr@gmail.com>
Date: Thu, 18 Sep 2014 17:36:26 -0400
Subject: [PATCH] Add unicode password support

---
 data/model/legacy.py   | 12 ++++++------
 test/test_api_usage.py |  6 ++++++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/data/model/legacy.py b/data/model/legacy.py
index 53ece0c8c..8f82ca9cd 100644
--- a/data/model/legacy.py
+++ b/data/model/legacy.py
@@ -86,6 +86,9 @@ class TooManyLoginAttemptsException(Exception):
     super(TooManyLoginAttemptsException, self).__init__(message)
     self.retry_after = retry_after
 
+def hash_password(password, salt=None):
+  salt = salt or bcrypt.gensalt()
+  return bcrypt.hashpw(password.encode('utf-8'), salt)
 
 def is_create_user_allowed():
   return True
@@ -101,7 +104,7 @@ def create_user(username, password, email):
   created = _create_user(username, email)
   
   # Store the password hash
-  pw_hash = bcrypt.hashpw(password, bcrypt.gensalt())
+  pw_hash = hash_password(password)
   created.password_hash = pw_hash
   
   created.save()
@@ -613,10 +616,7 @@ def verify_user(username_or_email, password):
       retry_after = can_retry_at - now
       raise TooManyLoginAttemptsException('Too many login attempts.', retry_after.total_seconds())
 
-  if (fetched.password_hash and 
-      bcrypt.hashpw(password, fetched.password_hash) ==
-      fetched.password_hash):
-
+  if (fetched.password_hash and hash_password(password, fetched.password_hash) == fetched.password_hash):
     if fetched.invalid_login_attempts > 0:
       fetched.invalid_login_attempts = 0
       fetched.save()
@@ -811,7 +811,7 @@ def change_password(user, new_password):
   if not validate_password(new_password):
     raise InvalidPasswordException(INVALID_PASSWORD_MESSAGE)
 
-  pw_hash = bcrypt.hashpw(new_password, bcrypt.gensalt())
+  pw_hash = hash_password(new_password)
   user.password_hash = pw_hash
   user.save()
 
diff --git a/test/test_api_usage.py b/test/test_api_usage.py
index 4a9f1fbdc..cbbb5baf4 100644
--- a/test/test_api_usage.py
+++ b/test/test_api_usage.py
@@ -339,6 +339,12 @@ class TestChangeUserDetails(ApiTestCase):
                          data=dict(password='newpasswordiscool'))
     self.login(READ_ACCESS_USER, password='newpasswordiscool')
 
+  def test_changepassword_unicode(self):
+    self.login(READ_ACCESS_USER)
+    self.putJsonResponse(User,
+                         data=dict(password='someunicode北京市pass'))
+    self.login(READ_ACCESS_USER, password='someunicode北京市pass')
+
   def test_changeeemail(self):
     self.login(READ_ACCESS_USER)