forked from Github-Mirrors/canaille
feat: ldap connection is lazilly opened
This commit is contained in:
parent
d0dbaa588c
commit
5c11ebf0d3
3 changed files with 52 additions and 85 deletions
|
@ -44,14 +44,12 @@ class BaseBackend:
|
||||||
This method will be called before each http request,
|
This method will be called before each http request,
|
||||||
it should open the connection to the backend.
|
it should open the connection to the backend.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
"""
|
"""
|
||||||
This method will be called after each http request,
|
This method will be called after each http request,
|
||||||
it should close the connections to the backend.
|
it should close the connections to the backend.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate(cls, config):
|
def validate(cls, config):
|
||||||
|
|
|
@ -10,7 +10,6 @@ from canaille.app.configuration import ConfigurationException
|
||||||
from canaille.app.i18n import gettext as _
|
from canaille.app.i18n import gettext as _
|
||||||
from canaille.backends import BaseBackend
|
from canaille.backends import BaseBackend
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from flask import request
|
|
||||||
|
|
||||||
from .utils import listify
|
from .utils import listify
|
||||||
|
|
||||||
|
@ -51,7 +50,7 @@ def install_schema(config, schema_path):
|
||||||
class Backend(BaseBackend):
|
class Backend(BaseBackend):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
self.connection = None
|
self._connection = None
|
||||||
setup_ldap_models(config)
|
setup_ldap_models(config)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -74,23 +73,18 @@ class Backend(BaseBackend):
|
||||||
os.path.dirname(__file__) + "/schemas/oauth2-openldap.ldif",
|
os.path.dirname(__file__) + "/schemas/oauth2-openldap.ldif",
|
||||||
)
|
)
|
||||||
|
|
||||||
def setup(self):
|
@property
|
||||||
if self.connection:
|
def connection(self):
|
||||||
return
|
if self._connection:
|
||||||
|
return self._connection
|
||||||
try: # pragma: no cover
|
|
||||||
if request.endpoint == "static":
|
|
||||||
return
|
|
||||||
except RuntimeError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.connection = ldap.initialize(self.config["BACKENDS"]["LDAP"]["URI"])
|
self._connection = ldap.initialize(self.config["BACKENDS"]["LDAP"]["URI"])
|
||||||
self.connection.set_option(
|
self._connection.set_option(
|
||||||
ldap.OPT_NETWORK_TIMEOUT,
|
ldap.OPT_NETWORK_TIMEOUT,
|
||||||
self.config["BACKENDS"]["LDAP"].get("TIMEOUT"),
|
self.config["BACKENDS"]["LDAP"].get("TIMEOUT"),
|
||||||
)
|
)
|
||||||
self.connection.simple_bind_s(
|
self._connection.simple_bind_s(
|
||||||
self.config["BACKENDS"]["LDAP"]["BIND_DN"],
|
self.config["BACKENDS"]["LDAP"]["BIND_DN"],
|
||||||
self.config["BACKENDS"]["LDAP"]["BIND_PW"],
|
self.config["BACKENDS"]["LDAP"]["BIND_PW"],
|
||||||
)
|
)
|
||||||
|
@ -109,36 +103,18 @@ class Backend(BaseBackend):
|
||||||
logging.error(message)
|
logging.error(message)
|
||||||
raise ConfigurationException(message) from exc
|
raise ConfigurationException(message) from exc
|
||||||
|
|
||||||
def teardown(self):
|
return self._connection
|
||||||
try: # pragma: no cover
|
|
||||||
if request.endpoint == "static":
|
|
||||||
return
|
|
||||||
except RuntimeError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
if self.connection: # pragma: no branch
|
def teardown(self):
|
||||||
self.connection.unbind_s()
|
if self._connection: # pragma: no branch
|
||||||
self.connection = None
|
self._connection.unbind_s()
|
||||||
|
self._connection = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate(cls, config):
|
def validate(cls, config):
|
||||||
from canaille.app import models
|
from canaille.app import models
|
||||||
|
|
||||||
backend = cls(config)
|
with cls(config).session():
|
||||||
try:
|
|
||||||
backend.setup()
|
|
||||||
models.User.ldap_object_classes()
|
|
||||||
|
|
||||||
except ldap.SERVER_DOWN as exc:
|
|
||||||
raise ConfigurationException(
|
|
||||||
f'Could not connect to the LDAP server \'{config["BACKENDS"]["LDAP"]["URI"]}\''
|
|
||||||
) from exc
|
|
||||||
|
|
||||||
except ldap.INVALID_CREDENTIALS as exc:
|
|
||||||
raise ConfigurationException(
|
|
||||||
f'LDAP authentication failed with user \'{config["BACKENDS"]["LDAP"]["BIND_DN"]}\''
|
|
||||||
) from exc
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = models.User(
|
user = models.User(
|
||||||
formatted_name=f"canaille_{uuid.uuid4()}",
|
formatted_name=f"canaille_{uuid.uuid4()}",
|
||||||
|
@ -184,8 +160,6 @@ class Backend(BaseBackend):
|
||||||
finally:
|
finally:
|
||||||
user.delete()
|
user.delete()
|
||||||
|
|
||||||
backend.teardown()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def login_placeholder(cls):
|
def login_placeholder(cls):
|
||||||
user_filter = current_app.config["BACKENDS"]["LDAP"].get(
|
user_filter = current_app.config["BACKENDS"]["LDAP"].get(
|
||||||
|
|
|
@ -10,11 +10,6 @@ def test_required_methods(testclient):
|
||||||
BaseBackend.validate({})
|
BaseBackend.validate({})
|
||||||
|
|
||||||
backend = BaseBackend(testclient.app.config)
|
backend = BaseBackend(testclient.app.config)
|
||||||
with pytest.raises(NotImplementedError):
|
|
||||||
backend.setup()
|
|
||||||
|
|
||||||
with pytest.raises(NotImplementedError):
|
|
||||||
backend.teardown()
|
|
||||||
|
|
||||||
with pytest.raises(NotImplementedError):
|
with pytest.raises(NotImplementedError):
|
||||||
backend.has_account_lockability()
|
backend.has_account_lockability()
|
||||||
|
|
Loading…
Reference in a new issue