mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
fix: Fix bugs with account locking (#2580)
* fix(security): reset login attempts after successful login Enforce a maximum number of consecutive failed logins. Successfully logging in should reset the count. #2569 * fix(security): fix when user is unlocked The user should be unlocked when locked_at is set, but the lock has expired. #2569
This commit is contained in:
parent
484c60c7ea
commit
4bd7bda60d
@ -72,7 +72,9 @@ def authenticate_user(session, email: str, password: str) -> PrivateUser | bool:
|
|||||||
user_service.lock_user(user)
|
user_service.lock_user(user)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
return user
|
|
||||||
|
user.login_attemps = 0
|
||||||
|
return db.users.update(user.id, user)
|
||||||
|
|
||||||
|
|
||||||
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
||||||
|
@ -23,7 +23,7 @@ class UserService(BaseService):
|
|||||||
unlocked = 0
|
unlocked = 0
|
||||||
|
|
||||||
for user in locked_users:
|
for user in locked_users:
|
||||||
if force or user.is_locked and user.locked_at is not None:
|
if force or not user.is_locked and user.locked_at is not None:
|
||||||
self.unlock_user(user)
|
self.unlock_user(user)
|
||||||
unlocked += 1
|
unlocked += 1
|
||||||
|
|
||||||
|
@ -61,3 +61,34 @@ def test_lock_unlocker_user(database: AllRepositories, unique_user: TestUser) ->
|
|||||||
# Sanity check that the is_locked property is working
|
# Sanity check that the is_locked property is working
|
||||||
user.locked_at = datetime.now() - timedelta(days=2)
|
user.locked_at = datetime.now() - timedelta(days=2)
|
||||||
assert not user.is_locked
|
assert not user.is_locked
|
||||||
|
|
||||||
|
|
||||||
|
def test_reset_locked_users(database: AllRepositories, unique_user: TestUser) -> None:
|
||||||
|
user_service = UserService(database)
|
||||||
|
|
||||||
|
# Test that the user is unlocked
|
||||||
|
user = database.users.get_one(unique_user.user_id)
|
||||||
|
assert not user.is_locked
|
||||||
|
assert not user.locked_at
|
||||||
|
|
||||||
|
# Test that the user is locked
|
||||||
|
user.login_attemps = 5
|
||||||
|
user = user_service.lock_user(user)
|
||||||
|
assert user.is_locked
|
||||||
|
assert user.login_attemps == 5
|
||||||
|
|
||||||
|
# Test that the locked user is not unlocked by reset
|
||||||
|
unlocked = user_service.reset_locked_users()
|
||||||
|
user = database.users.get_one(unique_user.user_id)
|
||||||
|
assert unlocked == 0
|
||||||
|
assert user.is_locked
|
||||||
|
assert user.login_attemps == 5
|
||||||
|
|
||||||
|
# Test that the locked user is unlocked by reset
|
||||||
|
user.locked_at = datetime.now() - timedelta(days=2)
|
||||||
|
database.users.update(user.id, user)
|
||||||
|
unlocked = user_service.reset_locked_users()
|
||||||
|
user = database.users.get_one(unique_user.user_id)
|
||||||
|
assert unlocked == 1
|
||||||
|
assert not user.is_locked
|
||||||
|
assert user.login_attemps == 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user