diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-16 19:45:42 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-16 19:45:42 +0200 |
| commit | 220ed6c7914f5977d36b7617e9c38999317f57e5 (patch) | |
| tree | 85508f95b1f5df52ff1edfd5530285278a00c839 /test | |
| parent | 45b130fd28f60a67552121b2dfab227279615a26 (diff) | |
Implement transparent password hash migration
Add has_secure_password and bcrypt while retaining compatibility with
legacy SHA-1 password hashes. Existing users are upgraded to
password_digest on their next successful login.
Add regression tests covering both legacy and modern authentication
paths.
Diffstat (limited to 'test')
| -rw-r--r-- | test/models/user_test.rb | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 049892e..514bdea 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb | |||
| @@ -62,6 +62,62 @@ class UserTest < ActiveSupport::TestCase | |||
| 62 | def test_should_not_authenticate_unknown_user | 62 | def test_should_not_authenticate_unknown_user |
| 63 | assert_nil User.authenticate("nosuchuser", "monkey") | 63 | assert_nil User.authenticate("nosuchuser", "monkey") |
| 64 | end | 64 | end |
| 65 | |||
| 66 | def test_user_with_crypted_password_is_migrated_on_login | ||
| 67 | user = users(:quentin) | ||
| 68 | |||
| 69 | assert_nil user.password_digest | ||
| 70 | |||
| 71 | assert User.authenticate("quentin", "monkey") | ||
| 72 | |||
| 73 | user.reload | ||
| 74 | |||
| 75 | assert_not_nil user.password_digest | ||
| 76 | assert_nil user.crypted_password | ||
| 77 | assert_nil user.salt | ||
| 78 | end | ||
| 79 | |||
| 80 | def test_new_user_uses_password_digest | ||
| 81 | user = create_user | ||
| 82 | |||
| 83 | assert_not_nil user.password_digest | ||
| 84 | assert_nil user.crypted_password | ||
| 85 | assert_nil user.salt | ||
| 86 | |||
| 87 | assert_equal user, User.authenticate("quire", "quire69") | ||
| 88 | end | ||
| 89 | |||
| 90 | def test_legacy_user_is_migrated_on_login | ||
| 91 | user = users(:quentin) | ||
| 92 | |||
| 93 | assert_nil user.password_digest | ||
| 94 | assert_not_nil user.crypted_password | ||
| 95 | assert_not_nil user.salt | ||
| 96 | |||
| 97 | assert_equal user, User.authenticate("quentin", "monkey") | ||
| 98 | |||
| 99 | user.reload | ||
| 100 | |||
| 101 | assert_not_nil user.password_digest | ||
| 102 | assert_nil user.crypted_password | ||
| 103 | assert_nil user.salt | ||
| 104 | end | ||
| 105 | |||
| 106 | def test_migrated_user_authenticates_using_password_digest | ||
| 107 | user = users(:quentin) | ||
| 108 | |||
| 109 | # Trigger automatic migration. | ||
| 110 | assert_equal user, User.authenticate("quentin", "monkey") | ||
| 111 | |||
| 112 | user.reload | ||
| 113 | |||
| 114 | assert_not_nil user.password_digest | ||
| 115 | assert_nil user.crypted_password | ||
| 116 | assert_nil user.salt | ||
| 117 | |||
| 118 | # Second login should now use password_digest. | ||
| 119 | assert_equal user, User.authenticate("quentin", "monkey") | ||
| 120 | end | ||
| 65 | 121 | ||
| 66 | protected | 122 | protected |
| 67 | def create_user(options = {}) | 123 | def create_user(options = {}) |
