forked from Github-Mirrors/canaille
Merge branch 'ldapobject-refactor' into 'main'
Miscellaneous refactoring See merge request yaal/canaille!69
This commit is contained in:
commit
7a74df2c67
6 changed files with 72 additions and 48 deletions
|
@ -1,9 +1,19 @@
|
|||
import datetime
|
||||
from enum import Enum
|
||||
|
||||
import ldap.dn
|
||||
import ldap.filter
|
||||
from flask import g
|
||||
|
||||
LDAP_NULL_DATE = "000001010000Z"
|
||||
|
||||
|
||||
class Syntax(str, Enum):
|
||||
GENERALIZED_TIME = "1.3.6.1.4.1.1466.115.121.1.24"
|
||||
INTEGER = "1.3.6.1.4.1.1466.115.121.1.27"
|
||||
JPEG = "1.3.6.1.4.1.1466.115.121.1.28"
|
||||
BOOLEAN = "1.3.6.1.4.1.1466.115.121.1.7"
|
||||
|
||||
|
||||
class LDAPObject:
|
||||
_object_class_by_name = None
|
||||
|
@ -175,17 +185,25 @@ class LDAPObject:
|
|||
except KeyError:
|
||||
return value
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.24": # Generalized Time
|
||||
if syntax == Syntax.GENERALIZED_TIME:
|
||||
value = value.decode("utf-8")
|
||||
return datetime.datetime.strptime(value, "%Y%m%d%H%M%SZ") if value else None
|
||||
if value == LDAP_NULL_DATE:
|
||||
# python cannot represent datetimes with year 0
|
||||
return datetime.datetime.min
|
||||
else:
|
||||
return (
|
||||
datetime.datetime.strptime(value, "%Y%m%d%H%M%SZ")
|
||||
if value
|
||||
else None
|
||||
)
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.27": # Integer
|
||||
if syntax == Syntax.INTEGER:
|
||||
return int(value.decode("utf-8"))
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.28": # JPEG
|
||||
if syntax == Syntax.JPEG:
|
||||
return value
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.7": # Boolean
|
||||
if syntax == Syntax.BOOLEAN:
|
||||
return value.decode("utf-8").upper() == "TRUE"
|
||||
|
||||
return value.decode("utf-8")
|
||||
|
@ -197,16 +215,19 @@ class LDAPObject:
|
|||
except KeyError:
|
||||
return value
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.24": # Generalized Time
|
||||
if syntax == Syntax.GENERALIZED_TIME and isinstance(value, datetime.datetime):
|
||||
if value == datetime.datetime.min:
|
||||
return LDAP_NULL_DATE.encode("utf-8")
|
||||
else:
|
||||
return value.strftime("%Y%m%d%H%M%SZ").encode("utf-8")
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.27": # Integer
|
||||
if syntax == Syntax.INTEGER and isinstance(value, int):
|
||||
return str(value).encode("utf-8")
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.28": # JPEG
|
||||
if syntax == Syntax.JPEG:
|
||||
return value
|
||||
|
||||
if syntax == "1.3.6.1.4.1.1466.115.121.1.7": # Boolean
|
||||
if syntax == Syntax.BOOLEAN and isinstance(value, bool):
|
||||
return ("TRUE" if value else "FALSE").encode("utf-8")
|
||||
|
||||
return value.encode("utf-8")
|
||||
|
@ -243,7 +264,7 @@ class LDAPObject:
|
|||
deletions = [
|
||||
name
|
||||
for name, value in self.changes.items()
|
||||
if value is None and name in self.attrs
|
||||
if (value is None or value == [None]) and name in self.attrs
|
||||
]
|
||||
changes = {
|
||||
name: value
|
||||
|
@ -333,20 +354,18 @@ class LDAPObject:
|
|||
else name
|
||||
)
|
||||
|
||||
if (not self.may or attribute_name not in self.may) and (
|
||||
not self.must or attribute_name not in self.must
|
||||
):
|
||||
return super().__getattribute__(attribute_name)
|
||||
|
||||
if attribute_name in self.ldap_object_attributes():
|
||||
if (
|
||||
not self.ldap_object_attributes()
|
||||
or not self.ldap_object_attributes()[attribute_name].single_value
|
||||
):
|
||||
return self.changes.get(name, self.attrs.get(attribute_name, []))
|
||||
else:
|
||||
return self.changes.get(
|
||||
attribute_name, self.attrs.get(attribute_name, [None])
|
||||
)[0]
|
||||
|
||||
return self.changes.get(attribute_name, self.attrs.get(attribute_name, [None]))[
|
||||
0
|
||||
]
|
||||
return super().__getattribute__(attribute_name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
attribute_name = (
|
||||
|
@ -357,9 +376,7 @@ class LDAPObject:
|
|||
|
||||
super().__setattr__(attribute_name, value)
|
||||
|
||||
if (self.may and attribute_name in self.may) or (
|
||||
self.must and attribute_name in self.must
|
||||
):
|
||||
if attribute_name in self.ldap_object_attributes():
|
||||
if self.ldap_object_attributes()[attribute_name].single_value:
|
||||
self.changes[attribute_name] = [value]
|
||||
else:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
$('.confirm').click(function(e){
|
||||
e.preventDefault();
|
||||
$('.ui.modal')
|
||||
$('#modal-' + e.target.id + '.ui.modal')
|
||||
.modal({
|
||||
onApprove : function() {
|
||||
$('.confirm').unbind('click').click();
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
{% block content %}
|
||||
{% if self_deletion or (user.can_manage_users and edited_user) %}
|
||||
<div class="ui basic modal">
|
||||
<div id="modal-delete" class="ui basic modal">
|
||||
<div class="ui icon header">
|
||||
<i class="user minus icon"></i>
|
||||
{% trans %}Account deletion{% endtrans %}
|
||||
|
|
|
@ -15,7 +15,7 @@ slapd = slapd.Slapd(
|
|||
"nis.ldif",
|
||||
"inetorgperson.ldif",
|
||||
"../canaille/ldap_backend/schemas/oauth2-openldap.ldif",
|
||||
"ldif/memberof.ldif",
|
||||
"ldif/memberof-config.ldif",
|
||||
),
|
||||
)
|
||||
slapd.start()
|
||||
|
@ -39,13 +39,11 @@ try:
|
|||
+ "\n"
|
||||
)
|
||||
|
||||
with open("ldif/bootstrap-tree.ldif") as fd:
|
||||
try:
|
||||
slapd.ldapadd(fd.read())
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
with open("ldif/bootstrap-data.ldif") as fd:
|
||||
for ldif in (
|
||||
"ldif/bootstrap-tree.ldif",
|
||||
"ldif/bootstrap-data.ldif",
|
||||
):
|
||||
with open(ldif) as fd:
|
||||
try:
|
||||
slapd.ldapadd(fd.read())
|
||||
except RuntimeError:
|
||||
|
|
|
@ -27,6 +27,7 @@ class CustomSlapdObject(slapd.Slapd):
|
|||
"nis.ldif",
|
||||
"inetorgperson.ldif",
|
||||
"canaille/ldap_backend/schemas/oauth2-openldap.ldif",
|
||||
"demo/ldif/memberof-config.ldif",
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -80,7 +81,7 @@ def keypair_path(keypair, tmp_path):
|
|||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def slapd_server():
|
||||
def raw_slapd_server():
|
||||
slapd = CustomSlapdObject()
|
||||
try:
|
||||
slapd.start()
|
||||
|
@ -110,15 +111,23 @@ def slapd_server():
|
|||
+ "\n"
|
||||
)
|
||||
|
||||
LDAPObject.root_dn = slapd.suffix
|
||||
yield slapd
|
||||
finally:
|
||||
slapd.stop()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def slapd_server(raw_slapd_server):
|
||||
for ldif in ("demo/ldif/bootstrap-tree.ldif",):
|
||||
with open(ldif) as fd:
|
||||
raw_slapd_server.ldapadd(fd.read())
|
||||
|
||||
LDAPObject.root_dn = raw_slapd_server.suffix
|
||||
User.base = "ou=users"
|
||||
User.object_class = ["inetOrgPerson"]
|
||||
Group.base = "ou=groups"
|
||||
Group.object_class = ["groupOfNames"]
|
||||
|
||||
yield slapd
|
||||
finally:
|
||||
slapd.stop()
|
||||
yield raw_slapd_server
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
Loading…
Reference in a new issue