2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-15 03:25:42 +00:00

configurable ldap group classes (#8475)

* configurable ldap group classes

* remove accidental duplicate line

* fix style issues

---------

Co-authored-by: Matthias Mair <code@mjmair.com>
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
Jacob Felknor
2024-11-15 15:08:27 -07:00
committed by GitHub
parent 6fcd691070
commit f9d3f43b02
14 changed files with 59 additions and 30 deletions

View File

@ -62,7 +62,7 @@ class ClassValidationMixin:
if len(missing_attributes) > 0:
errors.append(
f"did not provide the following attributes: {', '.join(missing_attributes)}"
f'did not provide the following attributes: {", ".join(missing_attributes)}'
)
if len(missing_overrides) > 0:
missing_overrides_list = []
@ -75,7 +75,7 @@ class ClassValidationMixin:
else:
missing_overrides_list.append(base_implementation.__name__)
errors.append(
f"did not override the required attributes: {', '.join(missing_overrides_list)}"
f'did not override the required attributes: {", ".join(missing_overrides_list)}'
)
if len(errors) > 0:

View File

@ -360,8 +360,8 @@ AUTHENTICATION_BACKENDS = CONFIG.get(
# LDAP support
LDAP_AUTH = get_boolean_setting('INVENTREE_LDAP_ENABLED', 'ldap.enabled', False)
if LDAP_AUTH:
import django_auth_ldap.config
import ldap
from django_auth_ldap.config import GroupOfUniqueNamesType, LDAPSearch
AUTHENTICATION_BACKENDS.append('django_auth_ldap.backend.LDAPBackend')
@ -412,7 +412,7 @@ if LDAP_AUTH:
AUTH_LDAP_BIND_PASSWORD = get_setting(
'INVENTREE_LDAP_BIND_PASSWORD', 'ldap.bind_password'
)
AUTH_LDAP_USER_SEARCH = LDAPSearch(
AUTH_LDAP_USER_SEARCH = django_auth_ldap.config.LDAPSearch(
get_setting('INVENTREE_LDAP_SEARCH_BASE_DN', 'ldap.search_base_dn'),
ldap.SCOPE_SUBTREE,
str(
@ -439,12 +439,38 @@ if LDAP_AUTH:
'INVENTREE_LDAP_CACHE_TIMEOUT', 'ldap.cache_timeout', 3600, int
)
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
AUTH_LDAP_MIRROR_GROUPS = get_boolean_setting(
'INVENTREE_LDAP_MIRROR_GROUPS', 'ldap.mirror_groups', False
)
AUTH_LDAP_GROUP_OBJECT_CLASS = get_setting(
'INVENTREE_LDAP_GROUP_OBJECT_CLASS',
'ldap.group_object_class',
'groupOfUniqueNames',
str,
)
AUTH_LDAP_GROUP_SEARCH = django_auth_ldap.config.LDAPSearch(
get_setting('INVENTREE_LDAP_GROUP_SEARCH', 'ldap.group_search'),
ldap.SCOPE_SUBTREE,
'(objectClass=groupOfUniqueNames)',
f'(objectClass={AUTH_LDAP_GROUP_OBJECT_CLASS})',
)
AUTH_LDAP_GROUP_TYPE_CLASS = get_setting(
'INVENTREE_LDAP_GROUP_TYPE_CLASS',
'ldap.group_type_class',
'GroupOfUniqueNamesType',
str,
)
AUTH_LDAP_GROUP_TYPE_CLASS_ARGS = get_setting(
'INVENTREE_LDAP_GROUP_TYPE_CLASS_ARGS', 'ldap.group_type_class_args', [], list
)
AUTH_LDAP_GROUP_TYPE_CLASS_KWARGS = get_setting(
'INVENTREE_LDAP_GROUP_TYPE_CLASS_KWARGS',
'ldap.group_type_class_kwargs',
{'name_attr': 'cn'},
dict,
)
AUTH_LDAP_GROUP_TYPE = getattr(django_auth_ldap.config, AUTH_LDAP_GROUP_TYPE_CLASS)(
*AUTH_LDAP_GROUP_TYPE_CLASS_ARGS, **AUTH_LDAP_GROUP_TYPE_CLASS_KWARGS
)
AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType(name_attr='cn')
AUTH_LDAP_REQUIRE_GROUP = get_setting(
'INVENTREE_LDAP_REQUIRE_GROUP', 'ldap.require_group'
)

View File

@ -1034,14 +1034,14 @@ class TestVersionNumber(TestCase):
# Check that the current .git values work too
git_hash = str(
subprocess.check_output('git rev-parse --short HEAD'.split()), 'utf-8'
subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']), 'utf-8'
).strip()
# On some systems the hash is a different length, so just check the first 6 characters
self.assertEqual(git_hash[:6], version.inventreeCommitHash()[:6])
d = (
str(subprocess.check_output('git show -s --format=%ci'.split()), 'utf-8')
str(subprocess.check_output(['git', 'show', '-s', '--format=%ci']), 'utf-8')
.strip()
.split(' ')[0]
)

View File

@ -260,7 +260,7 @@ class BaseMachineType(
error_parts.append(
f'{config_type.name} settings: ' + ', '.join(missing)
)
self.handle_error(f"Missing {' and '.join(error_parts)}")
self.handle_error(f'Missing {" and ".join(error_parts)}')
return
try:

View File

@ -112,7 +112,7 @@ class MachineConfig(models.Model):
"""Get machine errors for django admin interface."""
return format_html_join(
mark_safe('<br>'), '{}', ((str(error),) for error in self.errors)
) or mark_safe(f"<i>{_('No errors')}</i>")
) or mark_safe(f'<i>{_("No errors")}</i>')
@admin.display(description=_('Machine status'))
def get_machine_status(self):

View File

@ -470,7 +470,7 @@ class PurchaseOrder(TotalPriceMixin, Order):
def __str__(self):
"""Render a string representation of this PurchaseOrder."""
return f"{self.reference} - {self.supplier.name if self.supplier else _('deleted')}"
return f'{self.reference} - {self.supplier.name if self.supplier else _("deleted")}'
reference = models.CharField(
unique=True,
@ -996,7 +996,7 @@ class SalesOrder(TotalPriceMixin, Order):
def __str__(self):
"""Render a string representation of this SalesOrder."""
return f"{self.reference} - {self.customer.name if self.customer else _('deleted')}"
return f'{self.reference} - {self.customer.name if self.customer else _("deleted")}'
reference = models.CharField(
unique=True,
@ -2194,7 +2194,7 @@ class ReturnOrder(TotalPriceMixin, Order):
def __str__(self):
"""Render a string representation of this ReturnOrder."""
return f"{self.reference} - {self.customer.name if self.customer else _('no customer')}"
return f'{self.reference} - {self.customer.name if self.customer else _("no customer")}'
reference = models.CharField(
unique=True,

View File

@ -295,7 +295,7 @@ class PartImport(FileManagementFormView):
# Set alerts
if import_done:
alert = f"<strong>{_('Part-Import')}</strong><br>{_(f'Imported {import_done} parts')}"
alert = f'<strong>{_("Part-Import")}</strong><br>{_(f"Imported {import_done} parts")}'
messages.success(self.request, alert)
if import_error:
error_text = '\n'.join([
@ -304,7 +304,7 @@ class PartImport(FileManagementFormView):
])
messages.error(
self.request,
f"<strong>{_('Some errors occurred:')}</strong><br><ul>{error_text}</ul>",
f'<strong>{_("Some errors occurred:")}</strong><br><ul>{error_text}</ul>',
)
return HttpResponseRedirect(reverse('part-index'))

View File

@ -31,7 +31,7 @@ class SampleLabelPrinter(LabelPrintingMixin, InvenTreePlugin):
Normally here the connection to the printer and transfer of the label would take place.
"""
# Test that the expected kwargs are present
print(f"Printing Label: {kwargs['filename']} (User: {kwargs['user']})")
print(f'Printing Label: {kwargs["filename"]} (User: {kwargs["user"]})')
pdf_data = kwargs['pdf_data']
png_file = self.render_to_png(

View File

@ -252,7 +252,7 @@ class RegistryTests(TestCase):
def test_package_loading(self):
"""Test that package distributed plugins work."""
# Install sample package
subprocess.check_output('pip install inventree-zapier'.split())
subprocess.check_output(['pip', 'install', 'inventree-zapier'])
# Reload to discover plugin
registry.reload_plugins(full_reload=True, collect=True)

View File

@ -62,7 +62,7 @@ if __name__ == '__main__':
percentage = int(covered / total * 100) if total > 0 else 0
if verbose:
print(f"| {locale.ljust(4, ' ')} : {str(percentage).rjust(4, ' ')}% |")
print(f'| {locale.ljust(4, " ")} : {str(percentage).rjust(4, " ")}% |')
locales_perc[locale] = percentage

View File

@ -18,7 +18,7 @@ class RedirectAssetView(TemplateView):
def get(self, request, *args, **kwargs):
"""Redirect to static asset."""
return redirect(
f"{settings.STATIC_URL}web/assets/{kwargs['path']}", permanent=True
f'{settings.STATIC_URL}web/assets/{kwargs["path"]}', permanent=True
)