USER_FILTER is parsed with jinja

This commit is contained in:
Éloi Rivard 2023-07-04 18:34:16 +02:00
parent f19cc8a497
commit fd66f86a72
9 changed files with 38 additions and 23 deletions

View file

@ -3,11 +3,19 @@ All notable changes to this project will be documented in this file.
The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_,
and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.
🚨Configuration files must be updated.🚨
Check the new format with ``git diff 0.0.29 0.0.30 canaille/conf/config.sample.toml``
Added
*****
- Configuration option to disable javascript :pr:`141`
Changed
*******
- ``USER_FILTER`` is parsed with jinja.
[0.0.29] - 2023-06-30
=====================
@ -28,7 +36,7 @@ Fixed
=====================
🚨Configuration files must be updated.🚨
Check the new format with ``git diff 0.0.27 0.0.26 canaille/conf/config.sample.toml``
Check the new format with ``git diff 0.0.26 0.0.27 canaille/conf/config.sample.toml``
Added
*****

View file

@ -219,13 +219,13 @@ class Backend(BaseBackend):
)
placeholders = []
if "cn={login}" in user_filter:
if "cn={{login" in user_filter.replace(" ", ""):
placeholders.append(_("John Doe"))
if "uid={login}" in user_filter:
if "uid={{login" in user_filter.replace(" ", ""):
placeholders.append(_("jdoe"))
if "mail={login}" in user_filter or not placeholders:
if "mail={{login" in user_filter.replace(" ", "") or not placeholders:
placeholders.append(_("john@doe.com"))
return _(" or ").join(placeholders)

View file

@ -44,11 +44,14 @@ class User(canaille.core.models.User, LDAPObject):
@classmethod
def get_from_login(cls, login=None, **kwargs):
raw_filter = current_app.config["BACKENDS"]["LDAP"].get(
"USER_FILTER", User.DEFAULT_FILTER
)
filter = (
(
current_app.config["BACKENDS"]["LDAP"]
.get("USER_FILTER", User.DEFAULT_FILTER)
.format(login=ldap.filter.escape_filter_chars(login))
current_app.jinja_env.from_string(raw_filter).render(
login=ldap.filter.escape_filter_chars(login)
)
)
if login
else None

View file

@ -81,9 +81,10 @@ USER_BASE = "ou=users,dc=mydomain,dc=tld"
# The attribute to identify an object in the User dn.
# USER_RDN = "uid"
# Filter to match users on sign in. Supports a variable
# {login} that can be used to compare against several fields:
# USER_FILTER = "(|(uid={login})(mail={login}))"
# Filter to match users on sign in. Jinja syntax is supported
# and a `login` variable is available containing the value
# passed in the login field.
# USER_FILTER = "(|(uid={{ login }})(mail={{ login }}))"
# Where to search for groups?
GROUP_BASE = "ou=groups,dc=mydomain,dc=tld"

View file

@ -82,9 +82,10 @@ USER_BASE = "ou=users,dc=mydomain,dc=tld"
# The attribute to identify an object in the User dn.
USER_RDN = "uid"
# Filter to match users on sign in. Supports a variable
# {login} that can be used to compare against several fields:
# USER_FILTER = "(|(uid={login})(mail={login}))"
# Filter to match users on sign in. Jinja syntax is supported
# and a `login` variable is available containing the value
# passed in the login field.
# USER_FILTER = "(|(uid={{ login }})(mail={{ login }}))"
# Where to search for groups?
GROUP_BASE = "ou=groups,dc=mydomain,dc=tld"

View file

@ -82,9 +82,10 @@ USER_BASE = "ou=users,dc=mydomain,dc=tld"
# The attribute to identify an object in the User dn.
# USER_RDN = "uid"
# Filter to match users on sign in. Supports a variable
# {login} that can be used to compare against several fields:
# USER_FILTER = "(|(uid={login})(mail={login}))"
# Filter to match users on sign in. Jinja syntax is supported
# and a `login` variable is available containing the value
# passed in the login field.
# USER_FILTER = "(|(uid={{ login }})(mail={{ login }}))"
# Where to search for groups?
GROUP_BASE = "ou=groups,dc=mydomain,dc=tld"

View file

@ -115,8 +115,9 @@ BACKENDS.LDAP
:USER_FILTER:
*Optional.* The filter to match users on sign in.
Supports a variable {login} that can be used to compare against several LDAP attributes.
Defaults to ``(|(uid={login})(mail={login}))``
Jinja syntax is supported and a `login` variable is available containing
the value passed in the login field.
Defaults to ``(|(uid={{ login }})(mail={{ login }}))``
:GROUP_BASE:
**Required.** The DN where of the node in which LDAP groups will be created and searched for.

View file

@ -35,7 +35,7 @@ def ldap_configuration(configuration, slapd_server):
"BIND_PW": slapd_server.root_pw,
"USER_BASE": "ou=users",
"USER_RDN": "uid",
"USER_FILTER": "(uid={login})",
"USER_FILTER": "(uid={{ login }})",
"GROUP_BASE": "ou=groups",
"TIMEOUT": 0.1,
},

View file

@ -280,20 +280,20 @@ def test_ldap_cannot_create_groups(testclient, configuration, backend):
def test_login_placeholder(testclient):
testclient.app.config["BACKENDS"]["LDAP"]["USER_FILTER"] = "(uid={login})"
testclient.app.config["BACKENDS"]["LDAP"]["USER_FILTER"] = "(uid={{ login }})"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "jdoe"
testclient.app.config["BACKENDS"]["LDAP"]["USER_FILTER"] = "(cn={login})"
testclient.app.config["BACKENDS"]["LDAP"]["USER_FILTER"] = "(cn={{ login }})"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "John Doe"
testclient.app.config["BACKENDS"]["LDAP"]["USER_FILTER"] = "(mail={login})"
testclient.app.config["BACKENDS"]["LDAP"]["USER_FILTER"] = "(mail={{ login }})"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "john@doe.com"
testclient.app.config["BACKENDS"]["LDAP"][
"USER_FILTER"
] = "(|(uid={login})(mail={login}))"
] = "(|(uid={{ login }})(mail={{ login }}))"
placeholder = testclient.get("/login").form["login"].attrs["placeholder"]
assert placeholder == "jdoe or john@doe.com"