feat: implement LDAP auth fallback in authenticate_user
This commit is contained in:
parent
c92351786a
commit
21574d3a57
@ -21,22 +21,41 @@ def get_user(db: Session, username: str) -> Optional[User]:
|
|||||||
return db.query(User).filter(User.username == username).first()
|
return db.query(User).filter(User.username == username).first()
|
||||||
|
|
||||||
|
|
||||||
|
def upsert_ldap_user(db: Session, attrs: dict) -> User:
|
||||||
|
"""Create or update a User from LDAP attribute dict, commit and return."""
|
||||||
|
from app.modules.auth.ldap import _upsert_from_attrs
|
||||||
|
_upsert_from_attrs(db, attrs)
|
||||||
|
db.commit()
|
||||||
|
return get_user(db, attrs["username"])
|
||||||
|
|
||||||
|
|
||||||
def authenticate_user(
|
def authenticate_user(
|
||||||
db: Session, username: str, password: str, ldap_enabled: bool
|
db: Session, username: str, password: str, ldap_enabled: bool
|
||||||
) -> Optional[User]:
|
) -> Optional[User]:
|
||||||
user = get_user(db, username)
|
user = get_user(db, username)
|
||||||
if user is None or not user.is_active:
|
|
||||||
|
# Explicitly deactivated users are always blocked
|
||||||
|
if user is not None and not user.is_active:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
local_ok = user.pw_hash is not None and verify_password(password, user.pw_hash)
|
# Local auth
|
||||||
if local_ok:
|
if user is not None and user.pw_hash is not None:
|
||||||
|
if verify_password(password, user.pw_hash):
|
||||||
|
_touch_last_login(db, user)
|
||||||
|
return user
|
||||||
|
|
||||||
|
# LDAP auth
|
||||||
|
if ldap_enabled:
|
||||||
|
from app.core.config import get_settings
|
||||||
|
from app.modules.auth.ldap import ldap_authenticate
|
||||||
|
s = get_settings()
|
||||||
|
attrs = ldap_authenticate(username, password, s.LDAP_SERVER, s.LDAP_DOMAIN)
|
||||||
|
if attrs is None:
|
||||||
|
return None
|
||||||
|
user = upsert_ldap_user(db, attrs)
|
||||||
_touch_last_login(db, user)
|
_touch_last_login(db, user)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
if ldap_enabled:
|
|
||||||
# LDAP auth implemented in Part 2
|
|
||||||
pass
|
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -67,3 +67,56 @@ def test_authenticate_no_pw_hash_no_ldap(db):
|
|||||||
db.add(user)
|
db.add(user)
|
||||||
db.commit()
|
db.commit()
|
||||||
assert authenticate_user(db, "ldaponly", "any", ldap_enabled=False) is None
|
assert authenticate_user(db, "ldaponly", "any", ldap_enabled=False) is None
|
||||||
|
|
||||||
|
|
||||||
|
# --- LDAP auth integration (uses mocked ldap_authenticate) ---
|
||||||
|
|
||||||
|
from unittest.mock import patch as mock_patch
|
||||||
|
|
||||||
|
|
||||||
|
def test_authenticate_creates_user_on_ldap_success(db):
|
||||||
|
ldap_attrs = {
|
||||||
|
"username": "newldap",
|
||||||
|
"full_name": "New LDAP User",
|
||||||
|
"department": "EFI",
|
||||||
|
"role": "ST",
|
||||||
|
"account_expires": None,
|
||||||
|
}
|
||||||
|
with mock_patch("app.modules.auth.ldap.ldap_authenticate", return_value=ldap_attrs):
|
||||||
|
user = authenticate_user(db, "newldap", "password", ldap_enabled=True)
|
||||||
|
assert user is not None
|
||||||
|
assert user.username == "newldap"
|
||||||
|
assert user.full_name == "New LDAP User"
|
||||||
|
assert user.last_login is not None
|
||||||
|
|
||||||
|
|
||||||
|
def test_authenticate_updates_existing_user_on_ldap_success(db):
|
||||||
|
existing = User(username="existing", full_name="Old Name", pw_hash=None)
|
||||||
|
db.add(existing)
|
||||||
|
db.commit()
|
||||||
|
ldap_attrs = {
|
||||||
|
"username": "existing",
|
||||||
|
"full_name": "New Name",
|
||||||
|
"department": "EFI",
|
||||||
|
"role": "PF",
|
||||||
|
"account_expires": None,
|
||||||
|
}
|
||||||
|
with mock_patch("app.modules.auth.ldap.ldap_authenticate", return_value=ldap_attrs):
|
||||||
|
user = authenticate_user(db, "existing", "password", ldap_enabled=True)
|
||||||
|
assert user.full_name == "New Name"
|
||||||
|
|
||||||
|
|
||||||
|
def test_authenticate_returns_none_on_ldap_failure(db):
|
||||||
|
with mock_patch("app.modules.auth.ldap.ldap_authenticate", return_value=None):
|
||||||
|
result = authenticate_user(db, "anyone", "wrong", ldap_enabled=True)
|
||||||
|
assert result is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_authenticate_blocked_user_not_bypassed_by_ldap(db):
|
||||||
|
blocked = User(username="blocked", full_name="B", pw_hash=None, is_active=False)
|
||||||
|
db.add(blocked)
|
||||||
|
db.commit()
|
||||||
|
ldap_attrs = {"username": "blocked", "full_name": "B", "department": "", "role": "", "account_expires": None}
|
||||||
|
with mock_patch("app.modules.auth.ldap.ldap_authenticate", return_value=ldap_attrs):
|
||||||
|
result = authenticate_user(db, "blocked", "any", ldap_enabled=True)
|
||||||
|
assert result is None
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user