ad/mattermost: сопоставление и OU в админке, доступы к командам и каналам по отделам и группам.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+74
-1
@@ -94,6 +94,15 @@ class DirectoryTypeAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
class DirectoryForm(TreeNodeForm):
|
||||
"""Кастомная форма с дополнительными проверками"""
|
||||
|
||||
create_ou_in_ad = forms.BooleanField(
|
||||
label=_('Создать OU в AD автоматически'), required=False,
|
||||
help_text=_(
|
||||
'Если включено и поле «OU в Active Directory» ниже не задано — при сохранении '
|
||||
'будет создана новая OU с названием справочника (вложенная в OU родителя, '
|
||||
'если он привязан; иначе — в users_ou коннектора).'
|
||||
),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Directory
|
||||
fields = '__all__'
|
||||
@@ -111,6 +120,30 @@ class DirectoryForm(TreeNodeForm):
|
||||
if 'parent' in self.fields and self.instance.directory_type_id:
|
||||
self.fields['parent'].queryset = self._get_allowed_parents()
|
||||
|
||||
if 'ad_ou_dn' in self.fields:
|
||||
try:
|
||||
from apps.ad_connector.ad_service import ADService
|
||||
service = ADService()
|
||||
try:
|
||||
ous = service.list_ous()
|
||||
root = service.users_ou
|
||||
finally:
|
||||
service.unbind()
|
||||
choices = [('', '— не задано (users_ou коннектора) —')]
|
||||
if root:
|
||||
choices.append((root, f'{root} (корень)'))
|
||||
choices += [(ou['dn'], ou['dn']) for ou in ous if ou['dn'] != root]
|
||||
self.fields['ad_ou_dn'].widget = forms.Select(choices=choices)
|
||||
self.fields['ad_ou_dn'].required = False
|
||||
except Exception:
|
||||
pass
|
||||
manage_url = reverse('admin:ad_connector_ou_manage')
|
||||
self.fields['ad_ou_dn'].help_text = format_html(
|
||||
'{} <a href="{}" target="_blank">Управлять деревом OU в AD →</a>',
|
||||
self.fields['ad_ou_dn'].help_text or '',
|
||||
manage_url,
|
||||
)
|
||||
|
||||
def _get_allowed_parents(self):
|
||||
"""Получить разрешенных родителей для текущего типа"""
|
||||
current_type = self.instance.directory_type
|
||||
@@ -150,7 +183,7 @@ class DirectoryAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
'fields': ('directory_type', 'parent', 'code', 'name', 'description', 'is_active')
|
||||
}),
|
||||
(_('Должности и локации'), {
|
||||
'fields': ('location_types', 'ad_group_dn', 'ad_ou_dn'),
|
||||
'fields': ('location_types', 'ad_group_dn', 'ad_ou_dn', 'create_ou_in_ad'),
|
||||
'description': 'location_types — для должностей: в каких локациях доступна. '
|
||||
'ad_group_dn, ad_ou_dn — для отделов.',
|
||||
'classes': ('collapse',)
|
||||
@@ -162,6 +195,46 @@ class DirectoryAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
)
|
||||
filter_horizontal = ['location_types']
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
old = None
|
||||
if change:
|
||||
old = Directory.objects.filter(pk=obj.pk).values('parent_id', 'ad_ou_dn').first()
|
||||
|
||||
if form.cleaned_data.get('create_ou_in_ad') and not obj.ad_ou_dn:
|
||||
parent_dn = obj.parent.ad_ou_dn if obj.parent_id and obj.parent.ad_ou_dn else None
|
||||
try:
|
||||
from apps.ad_connector.ad_service import ADService
|
||||
service = ADService()
|
||||
try:
|
||||
obj.ad_ou_dn = service.create_ou(obj.name, parent_dn)
|
||||
finally:
|
||||
service.unbind()
|
||||
except Exception as exc:
|
||||
messages.error(request, _('Не удалось создать OU в AD: %s') % exc)
|
||||
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
if old and old['ad_ou_dn'] and obj.ad_ou_dn == old['ad_ou_dn'] and old['parent_id'] != obj.parent_id:
|
||||
from apps.ad_connector.ad_service import ADService
|
||||
from apps.ad_connector.services.sync_service import relocate_ou_references
|
||||
try:
|
||||
service = ADService()
|
||||
try:
|
||||
desired_parent = (
|
||||
obj.parent.ad_ou_dn
|
||||
if obj.parent_id and obj.parent.ad_ou_dn
|
||||
else service.users_ou
|
||||
)
|
||||
current_parent = old['ad_ou_dn'].split(',', 1)[1]
|
||||
if desired_parent and desired_parent != current_parent:
|
||||
new_dn = service.move_ou(old['ad_ou_dn'], desired_parent)
|
||||
relocate_ou_references(old['ad_ou_dn'], new_dn)
|
||||
messages.success(request, _('OU перенесена в AD: %s') % new_dn)
|
||||
finally:
|
||||
service.unbind()
|
||||
except Exception as exc:
|
||||
messages.error(request, _('Не удалось перенести OU в AD: %s') % exc)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).select_related(
|
||||
'parent', 'directory_type'
|
||||
|
||||
Reference in New Issue
Block a user