perf: rename ad to ds

This commit is contained in:
ibuler 2025-04-07 19:10:12 +08:00 committed by 老广
parent 3f452daee8
commit acaa4cf2d5
35 changed files with 391 additions and 267 deletions

View File

@ -139,17 +139,25 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount, JSONFilterMixin):
return self.id
@lazyproperty
def ad_domain(self):
def ds_id(self):
if self.username.startswith('@'):
return None
if self.platform.category == 'ad':
return self.asset.ad.domain_name
if self.platform.category == 'ds':
return self.asset.directoryservice.id
return None
@lazyproperty
def ds_domain(self):
if self.username.startswith('@'):
return None
if self.ds_id:
return self.asset.ds.domain_name
return None
@lazyproperty
def full_username(self):
if self.ad_domain:
return '{}@{}'.format(self.username, self.ad_domain)
if self.ds_domain:
return '{}@{}'.format(self.username, self.ds_domain)
return self.username
@lazyproperty

View File

@ -241,7 +241,7 @@ class AccountSerializer(AccountCreateUpdateSerializerMixin, BaseAccountSerialize
'date_change_secret', 'change_secret_status'
]
fields = BaseAccountSerializer.Meta.fields + [
'su_from', 'asset', 'version', "ad_domain",
'su_from', 'asset', 'version', 'ds_domain',
'source', 'source_id', 'secret_reset',
] + AccountCreateUpdateSerializerMixin.Meta.fields + automation_fields
read_only_fields = BaseAccountSerializer.Meta.read_only_fields + automation_fields

View File

@ -87,7 +87,7 @@ class BaseAccountSerializer(
"username": {
"help_text": _(
"* If no username is required for authentication, enter null. "
"For AD accounts, use the format username@domain."
"For DS accounts, use the format username@domain."
)
},
}

View File

@ -21,7 +21,7 @@ class VirtualAccountSerializer(serializers.ModelSerializer):
'username': {'label': _('Username')},
'secret_from_login': {
'help_text': _(
'Current only support login from AD/LDAP. Secret priority: '
'Current only support login from DS/LDAP. Secret priority: '
'Same account in asset secret > Login secret > Manual input. <br/ >'
'For security, please set config CACHE_LOGIN_PASSWORD_ENABLED to true'
)

View File

@ -3,8 +3,8 @@ from .cloud import *
from .custom import *
from .database import *
from .device import *
from .ds import *
from .gpt import *
from .host import *
from .permission import *
from .web import *
from .ad import *

View File

@ -1,16 +0,0 @@
from assets.models import AD, Asset
from assets.serializers import ADSerializer
from .asset import AssetViewSet
__all__ = ['ADViewSet']
class ADViewSet(AssetViewSet):
model = AD
perm_model = Asset
def get_serializer_classes(self):
serializer_classes = super().get_serializer_classes()
serializer_classes['default'] = ADSerializer
return serializer_classes

View File

@ -0,0 +1,16 @@
from assets.models import DirectoryService, Asset
from assets.serializers import DSSerializer
from .asset import AssetViewSet
__all__ = ['DSViewSet']
class DSViewSet(AssetViewSet):
model = DirectoryService
perm_model = Asset
def get_serializer_classes(self):
serializer_classes = super().get_serializer_classes()
serializer_classes['default'] = DSSerializer
return serializer_classes

View File

@ -112,8 +112,7 @@ class BaseType(TextChoices):
@classmethod
def get_choices(cls):
if not settings.XPACK_LICENSE_IS_VALID:
choices = [(tp.value, tp.label) for tp in cls.get_community_types()]
else:
choices = cls.choices
if not settings.XPACK_LICENSE_IS_VALID and hasattr(cls, 'get_community_types'):
choices = [(tp.value, tp.label) for tp in cls.get_community_types()]
return choices

View File

@ -12,7 +12,7 @@ class Category(ChoicesMixin, models.TextChoices):
DATABASE = 'database', _("Database")
CLOUD = 'cloud', _("Cloud service")
WEB = 'web', _("Web")
AD = 'ad', _("Active Directory")
DS = 'ds', _("Directory service")
CUSTOM = 'custom', _("Custom type")
@classmethod

View File

@ -20,7 +20,7 @@ class DeviceTypes(BaseType):
'*': {
'charset_enabled': False,
'domain_enabled': True,
'ad_enabled': False,
'ds_enabled': False,
'su_enabled': True,
'su_methods': ['enable', 'super', 'super_level']
}

View File

@ -3,11 +3,13 @@ from django.utils.translation import gettext_lazy as _
from .base import BaseType
class ADTypes(BaseType):
AD = 'ad', _('Active Directory')
class DirectoryTypes(BaseType):
GENERAL = 'general', _('General')
# LDAP = 'ldap', _('LDAP')
# AD = 'ad', _('Active Directory')
WINDOWS_AD = 'windows_ad', _('Windows Active Directory')
LDAP = 'ldap', _('LDAP')
AZURE_AD = 'azure_ad', _('Azure Active Directory')
# AZURE_AD = 'azure_ad', _('Azure Active Directory')
@classmethod
def _get_base_constrains(cls) -> dict:
@ -15,7 +17,7 @@ class ADTypes(BaseType):
'*': {
'charset_enabled': False,
'domain_enabled': True,
'ad_enabled': False,
'ds_enabled': False,
'su_enabled': True,
}
}
@ -24,6 +26,9 @@ class ADTypes(BaseType):
def _get_automation_constrains(cls) -> dict:
constrains = {
'*': {
'ansible_enabled': False,
},
cls.WINDOWS_AD: {
'ansible_enabled': True,
'ping_enabled': True,
'gather_facts_enabled': False,
@ -38,36 +43,24 @@ class ADTypes(BaseType):
@classmethod
def _get_protocol_constrains(cls) -> dict:
return {
cls.GENERAL: {
'choices': ['ssh']
},
cls.WINDOWS_AD: {
'choices': ['rdp', 'ssh', 'vnc', 'winrm']
},
cls.LDAP: {
'choices': ['ssh', 'ldap']
},
cls.AZURE_AD: {
'choices': ['ldap']
}
}
@classmethod
def internal_platforms(cls):
return {
cls.AD: [
{'name': 'Active Directory'}
],
cls.WINDOWS_AD: [
{'name': 'Windows Active Directory'}
],
cls.LDAP: [
{'name': 'LDAP'}
],
cls.AZURE_AD: [
{'name': 'Azure Active Directory'}
],
}
@classmethod
def get_community_types(cls):
return [
cls.LDAP,
cls.GENERAL,
]

View File

@ -20,7 +20,7 @@ class HostTypes(BaseType):
'charset': 'utf-8', # default
'domain_enabled': True,
'su_enabled': True,
'ad_enabled': True,
'ds_enabled': True,
'su_methods': ['sudo', 'su', 'only_sudo', 'only_su'],
},
cls.WINDOWS: {

View File

@ -13,10 +13,10 @@ from .cloud import CloudTypes
from .custom import CustomTypes
from .database import DatabaseTypes
from .device import DeviceTypes
from .ds import DirectoryTypes
from .gpt import GPTTypes
from .host import HostTypes
from .web import WebTypes
from .ad import ADTypes
class AllTypes(ChoicesMixin):
@ -24,7 +24,7 @@ class AllTypes(ChoicesMixin):
includes = [
HostTypes, DeviceTypes, DatabaseTypes,
CloudTypes, WebTypes, CustomTypes,
ADTypes, GPTTypes
DirectoryTypes, GPTTypes
]
_category_constrains = {}
_automation_methods = None
@ -175,7 +175,7 @@ class AllTypes(ChoicesMixin):
(Category.DATABASE, DatabaseTypes),
(Category.WEB, WebTypes),
(Category.CLOUD, CloudTypes),
(Category.AD, ADTypes),
(Category.DS, DirectoryTypes),
(Category.CUSTOM, CustomTypes)
]
return types

View File

@ -0,0 +1,64 @@
# Generated by Django 4.1.13 on 2025-03-31 02:49
import json
import django
from django.db import migrations, models
from assets.const.types import AllTypes
class Migration(migrations.Migration):
dependencies = [
("assets", "0015_automationexecution_type"),
]
operations = [
migrations.RunPython(add_ad_host_type),
migrations.CreateModel(
name="DS",
fields=[
(
"asset_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="assets.asset",
),
),
(
"domain_name",
models.CharField(
blank=True,
default="",
max_length=128,
verbose_name="Domain name",
),
),
],
options={
"verbose_name": "Active Directory",
},
bases=("assets.asset",),
),
migrations.AddField(
model_name="platform",
name="ds",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="ad_platforms",
to="assets.ds",
verbose_name="Active Directory",
),
),
migrations.AddField(
model_name="platform",
name="ds_enabled",
field=models.BooleanField(default=False, verbose_name="DS enabled"),
),
]

View File

@ -1,166 +0,0 @@
# Generated by Django 4.1.13 on 2025-03-31 02:49
import json
import django
from django.db import migrations, models
from assets.const.types import AllTypes
def add_ad_host_type(apps, schema_editor):
data = """
[
{
"created_by": "system",
"updated_by": "system",
"comment": "",
"name": "Windows AD",
"category": "ad",
"type": "windows_ad",
"meta": {},
"internal": true,
"domain_enabled": true,
"su_enabled": false,
"su_method": null,
"custom_fields": [],
"automation": {
"ansible_enabled": true,
"ansible_config": {
"ansible_shell_type": "cmd",
"ansible_connection": "ssh"
},
"ping_enabled": true,
"ping_method": "ping_by_rdp",
"ping_params": {},
"gather_facts_enabled": true,
"gather_facts_method": "gather_facts_windows",
"gather_facts_params": {},
"change_secret_enabled": true,
"change_secret_method": "change_secret_ad_windows",
"change_secret_params": {},
"push_account_enabled": true,
"push_account_method": "push_account_ad_windows",
"push_account_params": {},
"verify_account_enabled": true,
"verify_account_method": "verify_account_by_rdp",
"verify_account_params": {},
"gather_accounts_enabled": true,
"gather_accounts_method": "gather_accounts_ad_windows",
"gather_accounts_params": {},
"remove_account_enabled": true,
"remove_account_method": "remove_account_ad_windows",
"remove_account_params": {}
},
"protocols": [
{
"name": "rdp",
"port": 3389,
"primary": true,
"required": false,
"default": false,
"public": true,
"setting": {
"console": false,
"security": "any"
}
},
{
"name": "ssh",
"port": 22,
"primary": false,
"required": false,
"default": false,
"public": true,
"setting": {
"sftp_enabled": true,
"sftp_home": "/tmp"
}
},
{
"name": "vnc",
"port": 5900,
"primary": false,
"required": false,
"default": false,
"public": true,
"setting": {}
},
{
"name": "winrm",
"port": 5985,
"primary": false,
"required": false,
"default": false,
"public": false,
"setting": {
"use_ssl": false
}
}
]
}
]
"""
platform_model = apps.get_model('assets', 'Platform')
automation_cls = apps.get_model('assets', 'PlatformAutomation')
platform_datas = json.loads(data)
for platform_data in platform_datas:
AllTypes.create_or_update_by_platform_data(platform_data, platform_cls=platform_model,
automation_cls=automation_cls)
class Migration(migrations.Migration):
dependencies = [
("assets", "0015_automationexecution_type"),
]
operations = [
migrations.RunPython(add_ad_host_type),
migrations.CreateModel(
name="AD",
fields=[
(
"asset_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="assets.asset",
),
),
(
"domain_name",
models.CharField(
blank=True,
default="",
max_length=128,
verbose_name="Domain name",
),
),
],
options={
"verbose_name": "Active Directory",
},
bases=("assets.asset",),
),
migrations.AddField(
model_name="platform",
name="ad",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="ad_platforms",
to="assets.ad",
verbose_name="Active Directory",
),
),
migrations.AddField(
model_name="platform",
name="ad_enabled",
field=models.BooleanField(default=False, verbose_name="AD enabled"),
),
]

View File

@ -0,0 +1,59 @@
# Generated by Django 4.1.13 on 2025-04-03 09:51
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("assets", "0015_automationexecution_type"),
]
operations = [
migrations.CreateModel(
name="DirectoryService",
fields=[
(
"asset_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="assets.asset",
),
),
(
"domain_name",
models.CharField(
blank=True,
default="",
max_length=128,
verbose_name="Domain name",
),
),
],
options={
"verbose_name": "Directory service",
},
bases=("assets.asset",),
),
migrations.AddField(
model_name="platform",
name="ds_enabled",
field=models.BooleanField(default=False, verbose_name="DS enabled"),
),
migrations.AddField(
model_name="platform",
name="ds",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="ds_platforms",
to="assets.directoryservice",
verbose_name="Active Directory",
),
),
]

View File

@ -0,0 +1,168 @@
# Generated by Django 4.1.13 on 2025-04-07 03:24
import json
from django.db import migrations
from assets.const import AllTypes
def add_ds_platforms(apps, schema_editor):
data = """
[
{
"created_by": "system",
"updated_by": "system",
"comment": "",
"name": "Windows active directory",
"category": "ds",
"type": "windows_ad",
"meta": {},
"internal": true,
"domain_enabled": true,
"su_enabled": false,
"su_method": null,
"custom_fields": [],
"automation": {
"ansible_enabled": true,
"ansible_config": {
"ansible_shell_type": "cmd",
"ansible_connection": "ssh"
},
"ping_enabled": true,
"ping_method": "ping_by_rdp",
"ping_params": {},
"gather_facts_enabled": true,
"gather_facts_method": "gather_facts_windows",
"gather_facts_params": {},
"change_secret_enabled": true,
"change_secret_method": "change_secret_ad_windows",
"change_secret_params": {
},
"push_account_enabled": true,
"push_account_method": "push_account_ad_windows",
"push_account_params": {},
"verify_account_enabled": true,
"verify_account_method": "verify_account_by_rdp",
"verify_account_params": {
},
"gather_accounts_enabled": true,
"gather_accounts_method": "gather_accounts_ad_windows",
"gather_accounts_params": {
},
"remove_account_enabled": true,
"remove_account_method": "remove_account_ad_windows",
"remove_account_params": {
}
},
"protocols": [
{
"name": "rdp",
"port": 3389,
"primary": true,
"required": false,
"default": false,
"public": true,
"setting": {
"console": false,
"security": "any"
}
},
{
"name": "ssh",
"port": 22,
"primary": false,
"required": false,
"default": false,
"public": true,
"setting": {
"sftp_enabled": true,
"sftp_home": "/tmp"
}
},
{
"name": "vnc",
"port": 5900,
"primary": false,
"required": false,
"default": false,
"public": true,
"setting": {
}
},
{
"name": "winrm",
"port": 5985,
"primary": false,
"required": false,
"default": false,
"public": false,
"setting": {
"use_ssl": false
}
}
]
},
{
"created_by": "system",
"updated_by": "system",
"comment": "",
"name": "General",
"category": "ds",
"type": "general",
"meta": {
},
"internal": true,
"domain_enabled": false,
"su_enabled": false,
"su_method": null,
"custom_fields": [
],
"automation": {
"ansible_enabled": false,
"ansible_config": {
}
},
"protocols": [
{
"name": "ssh",
"port": 22,
"primary": true,
"required": false,
"default": false,
"public": true,
"setting": {
"sftp_enabled": true,
"sftp_home": "/tmp"
}
}
]
}
]
"""
platform_model = apps.get_model('assets', 'Platform')
automation_cls = apps.get_model('assets', 'PlatformAutomation')
platform_datas = json.loads(data)
for platform_data in platform_datas:
AllTypes.create_or_update_by_platform_data(
platform_data, platform_cls=platform_model,
automation_cls=automation_cls
)
class Migration(migrations.Migration):
dependencies = [
("assets", "0016_directory_service"),
]
operations = [
migrations.RunPython(add_ds_platforms)
]

View File

@ -1,9 +1,9 @@
from .ad import *
from .cloud import *
from .common import *
from .custom import *
from .database import *
from .device import *
from .ds import *
from .gpt import *
from .host import *
from .web import *

View File

@ -247,10 +247,10 @@ class Asset(NodesRelationMixin, LabeledMixin, AbsConnectivity, JSONFilterMixin,
@property
def all_accounts(self):
if not self.joined_ad_id:
if not self.joined_dir_svc_id:
queryset = self.accounts.all()
else:
queryset = self.accounts.model.objects.filter(asset__in=[self.id, self.joined_ad_id])
queryset = self.accounts.model.objects.filter(asset__in=[self.id, self.joined_dir_svc_id])
return queryset
@lazyproperty
@ -273,15 +273,15 @@ class Asset(NodesRelationMixin, LabeledMixin, AbsConnectivity, JSONFilterMixin,
protocol = self.protocols.all().filter(name=protocol).first()
return protocol.port if protocol else 0
def is_ad(self):
return self.category == const.Category.AD
def is_dir_svc(self):
return self.category == const.Category.DS
@property
def joined_ad_id(self):
return self.platform.ad_id
def joined_dir_svc_id(self):
return self.platform.ds_id
def is_joined_ad(self):
if self.joined_ad_id:
if self.joined_dir_svc_id:
return True
else:
return False

View File

@ -3,11 +3,11 @@ from django.utils.translation import gettext_lazy as _
from .common import Asset
__all__ = ['AD']
__all__ = ['DirectoryService']
class AD(Asset):
class DirectoryService(Asset):
domain_name = models.CharField(max_length=128, blank=True, default='', verbose_name=_("Domain name"))
class Meta:
verbose_name = _("Active Directory")
verbose_name = _("Directory service")

View File

@ -102,10 +102,10 @@ class Platform(LabeledMixin, JMSBaseModel):
max_length=8, verbose_name=_("Charset")
)
domain_enabled = models.BooleanField(default=True, verbose_name=_("Gateway enabled"))
ad_enabled = models.BooleanField(default=False, verbose_name=_("AD enabled"))
ad = models.ForeignKey(
'assets.AD', on_delete=models.SET_NULL, null=True, blank=True,
verbose_name=_("Active Directory"), related_name='ad_platforms'
ds_enabled = models.BooleanField(default=False, verbose_name=_("DS enabled"))
ds = models.ForeignKey(
'DirectoryService', on_delete=models.SET_NULL, null=True, blank=True,
verbose_name=_("Directory service"), related_name='ds_platforms'
)
# 账号有关的
su_enabled = models.BooleanField(default=False, verbose_name=_("Su enabled"))
@ -121,8 +121,8 @@ class Platform(LabeledMixin, JMSBaseModel):
return self.assets.count()
def save(self, *args, **kwargs):
if not self.ad_enabled:
self.ad = None
if not self.ds_enabled:
self.ds = None
super().save(*args, **kwargs)
@classmethod

View File

@ -4,7 +4,7 @@ from .common import *
from .custom import *
from .database import *
from .device import *
from .ds import *
from .gpt import *
from .host import *
from .web import *
from .ad import *

View File

@ -1,15 +1,14 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from assets.models import AD
from assets.models import DirectoryService
from .common import AssetSerializer
__all__ = ['ADSerializer']
__all__ = ['DSSerializer']
class ADSerializer(AssetSerializer):
class DSSerializer(AssetSerializer):
class Meta(AssetSerializer.Meta):
model = AD
model = DirectoryService
fields = AssetSerializer.Meta.fields + [
'domain_name',
]

View File

@ -194,8 +194,8 @@ class PlatformSerializer(ResourceLabelsMixin, CommonSerializerMixin, WritableNes
]
fields_m2m = ['assets', 'assets_amount']
fields = fields_small + fields_m2m + [
"protocols", "domain_enabled", "su_enabled", "su_method", "ad_enabled", "ad",
"automation", "comment", "custom_fields", "labels"
"protocols", "domain_enabled", "su_enabled", "su_method",
"ds_enabled", "ds", "automation", "comment", "custom_fields", "labels"
] + read_only_fields
extra_kwargs = {
"su_enabled": {

View File

@ -16,7 +16,7 @@ router.register(r'databases', api.DatabaseViewSet, 'database')
router.register(r'webs', api.WebViewSet, 'web')
router.register(r'clouds', api.CloudViewSet, 'cloud')
router.register(r'gpts', api.GPTViewSet, 'gpt')
router.register(r'directories', api.ADViewSet, 'ad')
router.register(r'directories', api.DSViewSet, 'ds')
router.register(r'customs', api.CustomViewSet, 'custom')
router.register(r'platforms', api.AssetPlatformViewSet, 'platform')
router.register(r'nodes', api.NodeViewSet, 'node')

View File

@ -8,7 +8,6 @@ from django.db import models
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.forms.models import model_to_dict
from rest_framework.exceptions import PermissionDenied
from accounts.models import VirtualAccount
@ -267,7 +266,7 @@ class ConnectionToken(JMSOrgBaseModel):
input_secret=self.input_secret, from_permed=False
)
else:
account = self.asset.accounts.filter(name=self.account).first()
account = self.asset.all_valid_accounts.filter(id=self.account).first()
if not account.secret and self.input_secret:
account.secret = self.input_secret
return account

View File

@ -40,6 +40,7 @@ class _ConnectionTokenAssetSerializer(serializers.ModelSerializer):
class _SimpleAccountSerializer(serializers.ModelSerializer):
secret_type = LabeledChoiceField(choices=SecretType.choices, required=False, label=_('Secret type'))
username = serializers.CharField(label=_('Username'), source='full_username', read_only=True)
class Meta:
model = Account
@ -49,6 +50,7 @@ class _SimpleAccountSerializer(serializers.ModelSerializer):
class _ConnectionTokenAccountSerializer(serializers.ModelSerializer):
su_from = serializers.SerializerMethodField(label=_('Su from'))
secret_type = LabeledChoiceField(choices=SecretType.choices, required=False, label=_('Secret type'))
username = serializers.CharField(label=_('Username'), source='full_username', read_only=True)
class Meta:
model = Account

View File

@ -8,7 +8,7 @@ FILE_END_GUARD = ">>> Content End <<<"
celery_task_pre_key = "CELERY_"
KEY_CACHE_RESOURCE_IDS = "RESOURCE_IDS_{}"
# AD User AccountDisable
# DS User AccountDisable
# https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
LDAP_AD_ACCOUNT_DISABLE = 2
UUID_PATTERN = re.compile(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')

View File

@ -138,4 +138,3 @@ if CONFIG.SYSLOG_ADDR != '' and len(CONFIG.SYSLOG_ADDR.split(':')) == 2:
if not os.path.isdir(LOG_DIR):
os.makedirs(LOG_DIR, mode=0o755)

View File

@ -39,8 +39,8 @@ class TerminalSettingSerializer(serializers.Serializer):
help_text=_(
'* Allow users to log in to the KoKo component via Public key authentication'
'<br/>'
'If third-party authentication services, such as AD/LDAP, are enabled, you should '
'disable this option to prevent users from logging in after being deleted from the AD/LDAP server'
'If third-party authentication services, such as DS/LDAP, are enabled, you should '
'disable this option to prevent users from logging in after being deleted from the DS/LDAP server'
)
)
TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(

View File

@ -197,7 +197,7 @@ class LDAPServerUtil(object):
value = is_true(value)
if attr == 'groups' and mapping.lower() == 'memberof':
# AD: {'groups': 'memberOf'}
# DS: {'groups': 'memberOf'}
if isinstance(value, str) and value:
value = [value]
if not isinstance(value, list):
@ -366,7 +366,7 @@ class LDAPSyncUtil(object):
class LDAPImportUtil(object):
user_group_name_prefix = 'AD '
user_group_name_prefix = 'DS '
def __init__(self, category=User.Source.ldap.value, is_sync_all=True):
self.category = category
@ -399,7 +399,7 @@ class LDAPImportUtil(object):
continue
if not isinstance(group, str):
continue
# get group name for AD, Such as: CN=Users,CN=Builtin,DC=jms,DC=com
# get group name for DS, Such as: CN=Users,CN=Builtin,DC=jms,DC=com
group_name = group.split(',')[0].split('=')[-1]
group_name = f'{self.user_group_name_prefix}{group_name}'.strip()
group_names.append(group_name)

View File

@ -81,7 +81,7 @@ class Migration(migrations.Migration):
models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date password last updated')),
('need_update_password', models.BooleanField(default=False, verbose_name='Need update password')),
('source', models.CharField(
choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('ldap_ha', 'LDAP/AD (HA)'), ('openid', 'OpenID'),
choices=[('local', 'Local'), ('ldap', 'LDAP/DS'), ('ldap_ha', 'LDAP/DS (HA)'), ('openid', 'OpenID'),
('radius', 'Radius'), ('cas', 'CAS'), ('saml2', 'SAML2'), ('oauth2', 'OAuth2'),
('wecom', 'WeCom'), ('dingtalk', 'DingTalk'), ('feishu', 'FeiShu'), ('lark', 'Lark'),
('slack', 'Slack'), ('custom', 'Custom')], default='local', max_length=30,

View File

@ -9,8 +9,8 @@ from django.utils.translation import gettext_lazy as _
class Source(models.TextChoices):
local = "local", _("Local")
ldap = "ldap", "LDAP/AD"
ldap_ha = "ldap_ha", "LDAP/AD (HA)"
ldap = "ldap", "LDAP/DS"
ldap_ha = "ldap_ha", "LDAP/DS (HA)"
openid = "openid", "OpenID"
radius = "radius", "Radius"
cas = "cas", "CAS"

View File

@ -247,7 +247,7 @@ class UserSerializer(
},
"source": {
"help_text": _(
"User source identifies where the user was created, which could be AD or other sources."
"User source identifies where the user was created, which could be DS or other sources."
"There are security settings that can restrict users to log in to the system only from the sources."
),
},

View File

@ -53,7 +53,7 @@ REDIS_PORT: 6379
# REDIS_DB_CELERY: 3
# REDIS_DB_CACHE: 4
# LDAP/AD settings
# LDAP/DS settings
# LDAP 搜索分页数量
# AUTH_LDAP_SEARCH_PAGED_SIZE: 1000
#