Skip to content

Commit 2dffc8f

Browse files
committed
Move more ldapauth stuff to ldap.py
1 parent 9e64078 commit 2dffc8f

File tree

3 files changed

+67
-40
lines changed

3 files changed

+67
-40
lines changed

python/nav/web/auth/__init__.py

+5-34
Original file line numberDiff line numberDiff line change
@@ -55,33 +55,22 @@ def authenticate(username, password):
5555
try:
5656
account = Account.objects.get(login__iexact=username)
5757
except Account.DoesNotExist:
58-
if ldap.available:
59-
ldap_user = ldap.authenticate(username, password)
60-
# If we authenticated, store the user in database.
61-
if ldap_user:
62-
account = Account(
63-
login=ldap_user.username,
64-
name=ldap_user.get_real_name(),
65-
ext_sync='ldap',
66-
)
67-
account = update_ldap_user(ldap_user, account, password)
68-
# We're authenticated now
69-
return account
70-
# No account, bail out
71-
return None
58+
# account autocreated if username is authenticated
59+
account = ldap.authenticate(username, password)
60+
return account
7261

7362
if account.locked:
7463
_logger.info("Locked user %s tried to log in", account.login)
7564
return None
7665

7766
if account.ext_sync == 'ldap' and ldap.available:
7867
try:
79-
ldap_user = ldap.authenticate(username, password)
68+
ldap_user = ldap.get_ldap_user(username, password)
8069
except ldap.NoAnswerError:
8170
pass
8271
else:
8372
if ldap_user:
84-
account = update_ldap_user(ldap_user, account, password)
73+
account = ldap.update_ldap_user(ldap_user, account, password)
8574
return account
8675
return None
8776
# Fallback to stored password if ldap is unavailable
@@ -91,24 +80,6 @@ def authenticate(username, password):
9180
return None
9281

9382

94-
def update_ldap_user(ldap_user, account, password):
95-
account.set_password(password)
96-
account.save()
97-
_handle_ldap_admin_status(ldap_user, account)
98-
return account
99-
100-
101-
def _handle_ldap_admin_status(ldap_user, nav_account):
102-
is_admin = ldap_user.is_admin()
103-
# Only modify admin status if an entitlement is configured in webfront.conf
104-
if is_admin is not None:
105-
admin_group = AccountGroup.objects.get(id=AccountGroup.ADMIN_GROUP)
106-
if is_admin:
107-
nav_account.groups.add(admin_group)
108-
else:
109-
nav_account.groups.remove(admin_group)
110-
111-
11283
def get_login_url(request):
11384
"""Calculate which login_url to use"""
11485
path = parse.quote(request.get_full_path())

python/nav/web/auth/ldap.py

+60-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import nav.errors
2626
from nav.config import NAVConfigParser
27+
from nav.models.profiles import Account, AccountGroup
2728

2829
_logger = logging.getLogger(__name__)
2930

@@ -121,11 +122,66 @@ def open_ldap():
121122
return lconn
122123

123124

124-
def authenticate(login, password):
125+
def authenticate(username, password):
125126
"""
126-
Attempt to authenticate the login name with password against the
127-
configured LDAP server. If the user is authenticated, required
128-
group memberships are also verified.
127+
Authenticate the username and password against the configured LDAP server.
128+
129+
Required group memberships are also verified.
130+
131+
Returns an authenticated Account with updated groups, or None.
132+
"""
133+
if not available:
134+
return None
135+
ldap_user = get_ldap_user(username, password)
136+
try:
137+
account = Account.objects.get(login__iexact=username, ext_sync='ldap')
138+
except Account.DoesNotExist:
139+
if ldap_user:
140+
account = autocreate_ldap_user(ldap_user, password)
141+
return account
142+
if account.locked:
143+
_logger.info("Locked user %s tried to log in", account.login)
144+
return None
145+
if account.check_password(password):
146+
account = update_ldap_user(ldap_user, account, password)
147+
return account
148+
return None
149+
150+
151+
def autocreate_ldap_user(ldap_user, password):
152+
account = Account(
153+
login=ldap_user.username,
154+
name=ldap_user.get_real_name(),
155+
ext_sync='ldap',
156+
)
157+
account = update_ldap_user(ldap_user, account, password)
158+
return account
159+
160+
161+
def update_ldap_user(ldap_user, account, password):
162+
account.set_password(password)
163+
account.save()
164+
_handle_ldap_admin_status(ldap_user, account)
165+
return account
166+
167+
168+
def _handle_ldap_admin_status(ldap_user, nav_account):
169+
is_admin = ldap_user.is_admin()
170+
# Only modify admin status if an entitlement is configured in webfront.conf
171+
if is_admin is not None:
172+
admin_group = AccountGroup.objects.get(id=AccountGroup.ADMIN_GROUP)
173+
if is_admin:
174+
nav_account.groups.add(admin_group)
175+
else:
176+
nav_account.groups.remove(admin_group)
177+
178+
179+
def get_ldap_user(login, password):
180+
"""
181+
Fetch an LDAPUser from an ldap server if login and password matches.
182+
183+
Returns an autenticated LDAPUser of a specific group or with specific
184+
entitlements, or False.
129185
"""
130186
lconn = open_ldap()
131187
server = _config.get('ldap', 'server')

tests/unittests/general/webfront_test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ def test_authenticate_should_return_account_when_ldap_says_yes(self):
3131
ldap_user = Mock()
3232
ldap_user.is_admin.return_value = None # mock to avoid database access
3333
with patch("nav.web.auth.ldap.available", new=True):
34-
with patch("nav.web.auth.ldap.authenticate", return_value=ldap_user):
34+
with patch("nav.web.auth.ldap.get_ldap_user", return_value=ldap_user):
3535
assert auth.authenticate('knight', 'shrubbery') == LDAP_ACCOUNT
3636

3737
def test_authenticate_should_return_false_when_ldap_says_no(self):
3838
with patch("nav.web.auth.ldap.available", new=True):
39-
with patch("nav.web.auth.ldap.authenticate", return_value=False):
39+
with patch("nav.web.auth.ldap.get_ldap_user", return_value=False):
4040
assert not auth.authenticate('knight', 'shrubbery')
4141

4242
def test_authenticate_should_fallback_when_ldap_is_disabled(self):

0 commit comments

Comments
 (0)