Skip to content

Commit fa19c09

Browse files
committed
Merge PR OCA#596 into 16.0
Signed-off-by pedrobaeza
2 parents fc90688 + 6a92b3a commit fa19c09

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

users_ldap_groups/models/res_company_ldap_operator.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright 2012-2018 Therp BV <https://therp.nl>
22
# Copyright 2018 Brainbean Apps <https://brainbeanapps.com>
33
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
4+
import base64
45
from logging import getLogger
56
from string import Template
67

@@ -32,10 +33,27 @@ def _equals(self, ldap_entry, mapping):
3233

3334
def _query(self, ldap_entry, mapping):
3435
query_string = Template(mapping.value).safe_substitute(
35-
{attr: ldap_entry[1][attr][0].decode() for attr in ldap_entry[1]}
36+
{
37+
attr: self.safe_ldap_decode(ldap_entry[1][attr][0])
38+
for attr in ldap_entry[1]
39+
}
3640
)
3741

3842
results = mapping.ldap_id._query(mapping.ldap_id.read()[0], query_string)
3943
_logger.debug('Performed LDAP query "%s" results: %s', query_string, results)
4044

4145
return bool(results)
46+
47+
def safe_ldap_decode(self, attr):
48+
"""Safe LDAP decode; Base64 encode attributes containing binary data.
49+
Binary data can be stored in Active Directory, e.g., thumbnailPhoto is
50+
stored as binary. As Str.decoce() cannot handle binary, this method
51+
Base64 encodes the data in the attribute, instead, if decode fails.
52+
Using Base64 should be a suitable fallback, because the use cases of
53+
users_ldap_groups do not really require comparing binary attributes.
54+
"""
55+
56+
try:
57+
return attr.decode()
58+
except UnicodeDecodeError:
59+
return base64.b64encode(attr)

users_ldap_groups/tests/test_users_ldap_groups.py

+67
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,70 @@ def _test_users_ldap_groups_not_user_type(self):
225225
self.env["res.users"].sudo().authenticate(
226226
self.env.cr.dbname, "users_ldap_groups-username", "password", {}
227227
)
228+
229+
def test_users_ldap_groups_ldap_returns_binary_data(self):
230+
self._create_ldap_config(
231+
groups=[
232+
{
233+
"ldap_attribute": "name",
234+
"operator": "contains",
235+
"value": "hello3",
236+
"group_id": self.group_system.id,
237+
},
238+
{
239+
"ldap_attribute": "name",
240+
"operator": "contains",
241+
"value": "hello",
242+
"group_id": self.group_user.id,
243+
},
244+
{
245+
"ldap_attribute": "name",
246+
"operator": "contains",
247+
"value": "hello2",
248+
"group_id": self.group_contains.id,
249+
},
250+
{
251+
"ldap_attribute": "name",
252+
"operator": "equals",
253+
"value": "hello",
254+
"group_id": self.group_equals.id,
255+
},
256+
{
257+
"ldap_attribute": "",
258+
"operator": "query",
259+
"value": "is not run because of patching",
260+
"group_id": self.group_query.id,
261+
},
262+
],
263+
only_ldap_groups=True,
264+
)
265+
with mock.patch(
266+
_company_ldap_class + "._connect",
267+
return_value=FakeLdapConnection(
268+
{
269+
"dc=users_ldap_groups,dc=example,dc=com": {
270+
"cn": [b"User Name"],
271+
"name": [b"hello", b"hello2"],
272+
"thumbnailPhoto": [
273+
b"GIF89a\x01\x00\x01\x00\x00\xff\x00,"
274+
b"\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x00;"
275+
],
276+
}
277+
}
278+
),
279+
), mock_cursor(self.cr):
280+
user_id = (
281+
self.env["res.users"]
282+
.sudo()
283+
.authenticate(
284+
self.env.cr.dbname, "users_ldap_groups-username", "password", {}
285+
)
286+
)
287+
# this asserts group mappings from demo data
288+
user = self.env["res.users"].sudo().browse(user_id)
289+
groups = user.groups_id
290+
self.assertIn(self.group_contains, groups)
291+
self.assertIn(self.group_user, groups)
292+
self.assertNotIn(self.group_equals, groups)
293+
self.assertIn(self.group_query, groups)
294+
self.assertNotIn(self.group_system, groups)

0 commit comments

Comments
 (0)