From c940b24043ae0e3762e6392c415fbcfcf4441afc Mon Sep 17 00:00:00 2001 From: "m.shvets" Date: Fri, 30 Jan 2026 16:33:56 +0300 Subject: [PATCH 1/5] Add: introduce SamAccountType enum and update related attributes in constants and LDAP requests --- .../f4e6cd18a01d_add_samaccounttype.py | 86 +++++++++++++++++++ app/constants.py | 20 +++-- app/enums.py | 20 +++++ app/ldap_protocol/ldap_requests/add.py | 28 +++++- app/ldap_protocol/utils/queries.py | 3 +- tests/constants.py | 33 +++++-- .../test_main/test_router/test_add.py | 45 ++++++++++ 7 files changed, 219 insertions(+), 16 deletions(-) create mode 100644 app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py diff --git a/app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py b/app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py new file mode 100644 index 000000000..90a857acb --- /dev/null +++ b/app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py @@ -0,0 +1,86 @@ +"""Add sAMAccountType to existing user/group/computer entries. + +Revision ID: f4e6cd18a01d +Revises: 379fce54fb08 +Create Date: 2026-01-30 13:08:26.299158 + +""" + +from alembic import op +from dishka import AsyncContainer, Scope +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession +from sqlalchemy.orm import selectinload + +from entities import Attribute, Directory, EntityType +from enums import EntityTypeNames, SamAccountType +from repo.pg.tables import queryable_attr as qa + +revision: None | str = "f4e6cd18a01d" +down_revision: None | str = "379fce54fb08" +branch_labels: None | list[str] = None +depends_on: None | list[str] = None + +_SAM_ACCOUNT_TYPE_ATTR = "sAMAccountType" +_SECURITY_PRINCIPAL_TYPES = ( + EntityTypeNames.USER, + EntityTypeNames.GROUP, + EntityTypeNames.COMPUTER, +) +_ENTITY_TO_SAM: dict[str, SamAccountType] = { + EntityTypeNames.USER: SamAccountType.SAM_USER_OBJECT, + EntityTypeNames.GROUP: SamAccountType.SAM_GROUP_OBJECT, + EntityTypeNames.COMPUTER: SamAccountType.SAM_MACHINE_ACCOUNT, +} + + +def upgrade(container: AsyncContainer) -> None: + """Add sAMAccountType attributes for user/group/computer.""" + + async def _add_samaccounttype(connection: AsyncConnection) -> None: # noqa: ARG001 + async with container(scope=Scope.REQUEST) as cnt: + session = await cnt.get(AsyncSession) + + entity_types = await session.scalars( + select(EntityType).where( + qa(EntityType.name).in_(_SECURITY_PRINCIPAL_TYPES), + ), + ) + entity_type_ids = [et.id for et in entity_types] + if not entity_type_ids: + return + + has_sam = select(qa(Attribute.directory_id)).where( + qa(Attribute.name).ilike(_SAM_ACCOUNT_TYPE_ATTR.lower()), + ) + dirs_without_sam = await session.scalars( + select(Directory) + .where( + qa(Directory.entity_type_id).in_(entity_type_ids), + ~qa(Directory.id).in_(has_sam), + ) + .options(selectinload(qa(Directory.entity_type))), + ) + + for directory in dirs_without_sam: + if not directory.entity_type: + continue + sam_value = _ENTITY_TO_SAM.get(directory.entity_type.name) + if sam_value is None: + continue + + session.add( + Attribute( + name=_SAM_ACCOUNT_TYPE_ATTR, + value=str(sam_value), + directory_id=directory.id, + ), + ) + + await session.commit() + + op.run_async(_add_samaccounttype) + + +def downgrade(container: AsyncContainer) -> None: + """Downgrade.""" diff --git a/app/constants.py b/app/constants.py index 902a79f59..634a0d06a 100644 --- a/app/constants.py +++ b/app/constants.py @@ -6,7 +6,7 @@ from typing import TypedDict -from enums import EntityTypeNames +from enums import EntityTypeNames, SamAccountType GROUPS_CONTAINER_NAME = "Groups" COMPUTERS_CONTAINER_NAME = "Computers" @@ -24,7 +24,7 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": ["groups"], - "sAMAccountType": ["268435456"], + "sAMAccountType": [str(SamAccountType.SAM_GROUP_OBJECT.value)], } @@ -308,7 +308,9 @@ class EntityTypeData(TypedDict): "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": [DOMAIN_ADMIN_GROUP_NAME], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value) + ], "gidNumber": ["512"], }, "objectSid": 512, @@ -321,7 +323,9 @@ class EntityTypeData(TypedDict): "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": [DOMAIN_USERS_GROUP_NAME], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value) + ], "gidNumber": ["513"], }, "objectSid": 513, @@ -334,7 +338,9 @@ class EntityTypeData(TypedDict): "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": [READ_ONLY_GROUP_NAME], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value) + ], "gidNumber": ["521"], }, "objectSid": 521, @@ -347,7 +353,9 @@ class EntityTypeData(TypedDict): "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": [DOMAIN_COMPUTERS_GROUP_NAME], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value) + ], "gidNumber": ["515"], }, "objectSid": 515, diff --git a/app/enums.py b/app/enums.py index 264b6c16a..f866b448d 100644 --- a/app/enums.py +++ b/app/enums.py @@ -254,3 +254,23 @@ class DomainCodes(IntEnum): DHCP = 12 LDAP_SCHEMA = 13 SHADOW = 14 + + +class SamAccountType(IntEnum): + """SAM Account Type values.""" + + SAM_DOMAIN_OBJECT = 0 + SAM_GROUP_OBJECT = 268435456 + SAM_NON_SECURITY_GROUP_OBJECT = 268435457 + SAM_ALIAS_OBJECT = 536870912 + SAM_NON_SECURITY_ALIAS_OBJECT = 536870913 + SAM_USER_OBJECT = 805306368 + SAM_MACHINE_ACCOUNT = 805306369 + SAM_TRUST_ACCOUNT = 805306370 + SAM_APP_BASIC_GROUP = 1073741824 + SAM_APP_QUERY_GROUP = 1073741825 + + @staticmethod + def to_hex(value: int) -> str: + """Convert decimal value to hex string.""" + return hex(value) diff --git a/app/ldap_protocol/ldap_requests/add.py b/app/ldap_protocol/ldap_requests/add.py index a16c6b182..70d6425ee 100644 --- a/app/ldap_protocol/ldap_requests/add.py +++ b/app/ldap_protocol/ldap_requests/add.py @@ -13,7 +13,7 @@ from constants import DOMAIN_COMPUTERS_GROUP_NAME, DOMAIN_USERS_GROUP_NAME from entities import Attribute, Directory, Group, User -from enums import AceType, EntityTypeNames +from enums import AceType, EntityTypeNames, SamAccountType from ldap_protocol.asn1parser import ASN1Row from ldap_protocol.kerberos.exceptions import ( KRBAPIAddPrincipalError, @@ -426,6 +426,32 @@ async def handle( # noqa: C901 ), ) + if "samaccounttype" not in self.l_attrs_dict: + if is_user: + attributes.append( + Attribute( + name="sAMAccountType", + value=str(SamAccountType.SAM_USER_OBJECT), + directory_id=new_dir.id, + ), + ) + elif is_group: + attributes.append( + Attribute( + name="sAMAccountType", + value=str(SamAccountType.SAM_GROUP_OBJECT), + directory_id=new_dir.id, + ), + ) + elif is_computer: + attributes.append( + Attribute( + name="sAMAccountType", + value=str(SamAccountType.SAM_MACHINE_ACCOUNT), + directory_id=new_dir.id, + ), + ) + if not ctx.attribute_value_validator.is_directory_attributes_valid( entity_type.name if entity_type else "", attributes, diff --git a/app/ldap_protocol/utils/queries.py b/app/ldap_protocol/utils/queries.py index 368af23ec..f6fa50918 100644 --- a/app/ldap_protocol/utils/queries.py +++ b/app/ldap_protocol/utils/queries.py @@ -16,6 +16,7 @@ from sqlalchemy.sql.expression import ColumnElement from entities import Attribute, Directory, Group, User +from enums import SamAccountType from ldap_protocol.ldap_schema.attribute_value_validator import ( AttributeValueValidator, AttributeValueValidatorError, @@ -394,7 +395,7 @@ async def create_group( "instanceType": ["4"], "sAMAccountName": [dir_.name], dir_.rdname: [dir_.name], - "sAMAccountType": ["268435456"], + "sAMAccountType": [str(SamAccountType.SAM_GROUP_OBJECT.value)], "gidNumber": [str(create_integer_hash(dir_.name))], } diff --git a/tests/constants.py b/tests/constants.py index 5542e0742..c17b77096 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -11,6 +11,7 @@ GROUPS_CONTAINER_NAME, USERS_CONTAINER_NAME, ) +from enums import SamAccountType from ldap_protocol.objects import UserAccountControlFlag TEST_DATA = [ @@ -30,7 +31,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": [DOMAIN_ADMIN_GROUP_NAME], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, { @@ -42,7 +45,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": ["developers"], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, { @@ -53,7 +58,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": ["admin login only"], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, { @@ -64,7 +71,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": [DOMAIN_USERS_GROUP_NAME], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, { @@ -75,7 +84,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": [DOMAIN_COMPUTERS_GROUP_NAME], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, ], @@ -368,7 +379,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": ["testGroup1"], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, ], @@ -381,7 +394,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": ["testGroup2"], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, ], @@ -402,7 +417,9 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": ["testGroup3"], - "sAMAccountType": ["268435456"], + "sAMAccountType": [ + str(SamAccountType.SAM_GROUP_OBJECT.value), + ], }, }, ], diff --git a/tests/test_api/test_main/test_router/test_add.py b/tests/test_api/test_main/test_router/test_add.py index 3282305f1..9ccaca2ad 100644 --- a/tests/test_api/test_main/test_router/test_add.py +++ b/tests/test_api/test_main/test_router/test_add.py @@ -8,6 +8,7 @@ from fastapi import status from httpx import AsyncClient +from enums import SamAccountType from ldap_protocol.ldap_codes import LDAPCodes from ldap_protocol.objects import UserAccountControlFlag from tests.api_datasets import test_api_forbidden_chars_in_attr_value @@ -179,6 +180,50 @@ async def test_api_add_computer(http_client: AsyncClient) -> None: raise Exception("Computer without sAMAccountName") +@pytest.mark.asyncio +@pytest.mark.usefixtures("session") +async def test_add_user_samaccounttype( + http_client: AsyncClient, +) -> None: + """Add user without sAMAccountType: server sets SAM_USER_OBJECT.""" + entry = "cn=samuser,dc=md,dc=test" + await http_client.post( + "/entry/add", + json={ + "entry": entry, + "password": "P@ssw0rd", + "attributes": [ + {"type": "name", "vals": ["samuser"]}, + {"type": "cn", "vals": ["samuser"]}, + {"type": "objectClass", "vals": ["user", "top"]}, + {"type": "sAMAccountName", "vals": ["samuser"]}, + {"type": "userPrincipalName", "vals": ["samuser@md.test"]}, + ], + }, + ) + response = await http_client.post( + "entry/search", + json={ + "base_object": entry, + "scope": 0, + "deref_aliases": 0, + "size_limit": 1, + "time_limit": 10, + "types_only": True, + "filter": "(objectClass=*)", + "attributes": ["sAMAccountType"], + "page_number": 1, + }, + ) + data = response.json() + attrs = { + a["type"]: a for a in data["search_result"][0]["partial_attributes"] + } + assert attrs["sAMAccountType"]["vals"][0] == str( + SamAccountType.SAM_USER_OBJECT, + ) + + @pytest.mark.asyncio @pytest.mark.usefixtures("session") async def test_api_correct_add_double_member_of( From 54a3fda549b7089a23751300bff0a78263e3b13f Mon Sep 17 00:00:00 2001 From: "m.shvets" Date: Fri, 30 Jan 2026 16:38:37 +0300 Subject: [PATCH 2/5] Fix: add missing commas in sAMAccountType assignments in FIRST_SETUP_DATA --- app/constants.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/constants.py b/app/constants.py index 634a0d06a..4483d65ac 100644 --- a/app/constants.py +++ b/app/constants.py @@ -309,7 +309,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [DOMAIN_ADMIN_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value) + str(SamAccountType.SAM_GROUP_OBJECT.value), ], "gidNumber": ["512"], }, @@ -324,7 +324,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [DOMAIN_USERS_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value) + str(SamAccountType.SAM_GROUP_OBJECT.value), ], "gidNumber": ["513"], }, @@ -339,7 +339,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [READ_ONLY_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value) + str(SamAccountType.SAM_GROUP_OBJECT.value), ], "gidNumber": ["521"], }, @@ -354,7 +354,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [DOMAIN_COMPUTERS_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value) + str(SamAccountType.SAM_GROUP_OBJECT.value), ], "gidNumber": ["515"], }, From 6b7f15fbe1514c5c9e8e7b54287f8faa59c37f14 Mon Sep 17 00:00:00 2001 From: "m.shvets" Date: Fri, 30 Jan 2026 17:48:19 +0300 Subject: [PATCH 3/5] Add: set sAMAccountType to SAM_USER_OBJECT in SetupUseCase for user creation --- app/ldap_protocol/auth/use_cases.py | 4 ++++ interface | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/ldap_protocol/auth/use_cases.py b/app/ldap_protocol/auth/use_cases.py index b9a53414e..e52538bee 100644 --- a/app/ldap_protocol/auth/use_cases.py +++ b/app/ldap_protocol/auth/use_cases.py @@ -14,6 +14,7 @@ FIRST_SETUP_DATA, USERS_CONTAINER_NAME, ) +from enums import SamAccountType from ldap_protocol.auth.dto import SetupDTO from ldap_protocol.auth.setup_gateway import SetupGateway from ldap_protocol.identity.exceptions import ( @@ -114,6 +115,9 @@ def _create_user_data(self, dto: SetupDTO) -> dict: "userAccountControl": ["512"], "primaryGroupID": ["512"], "givenName": [dto.username], + "sAMAccountType": [ + str(SamAccountType.SAM_USER_OBJECT) + ], }, "objectSid": 500, }, diff --git a/interface b/interface index e1ca5656a..f31962020 160000 --- a/interface +++ b/interface @@ -1 +1 @@ -Subproject commit e1ca5656aeabc20a1862aeaf11ded72feaa97403 +Subproject commit f31962020a6689e6a4c61fb3349db5b5c7895f92 From 2c16d9310af5e968ed4dcbbd5aa756f41e541c33 Mon Sep 17 00:00:00 2001 From: "m.shvets" Date: Tue, 3 Feb 2026 15:09:16 +0300 Subject: [PATCH 4/5] Refactor: rename SamAccountType enum to SamAccountTypeCodes and update references throughout the codebase --- .../f4e6cd18a01d_add_samaccounttype.py | 33 ++++++++++--------- app/constants.py | 12 +++---- app/enums.py | 2 +- app/ldap_protocol/auth/use_cases.py | 4 +-- app/ldap_protocol/ldap_requests/add.py | 8 ++--- app/ldap_protocol/utils/queries.py | 4 +-- tests/constants.py | 20 ++++++----- .../test_main/test_router/test_add.py | 4 +-- 8 files changed, 46 insertions(+), 41 deletions(-) diff --git a/app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py b/app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py index 90a857acb..efb2d0af5 100644 --- a/app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py +++ b/app/alembic/versions/f4e6cd18a01d_add_samaccounttype.py @@ -10,10 +10,10 @@ from dishka import AsyncContainer, Scope from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession -from sqlalchemy.orm import selectinload +from sqlalchemy.orm import joinedload from entities import Attribute, Directory, EntityType -from enums import EntityTypeNames, SamAccountType +from enums import EntityTypeNames, SamAccountTypeCodes from repo.pg.tables import queryable_attr as qa revision: None | str = "f4e6cd18a01d" @@ -27,10 +27,10 @@ EntityTypeNames.GROUP, EntityTypeNames.COMPUTER, ) -_ENTITY_TO_SAM: dict[str, SamAccountType] = { - EntityTypeNames.USER: SamAccountType.SAM_USER_OBJECT, - EntityTypeNames.GROUP: SamAccountType.SAM_GROUP_OBJECT, - EntityTypeNames.COMPUTER: SamAccountType.SAM_MACHINE_ACCOUNT, +_ENTITY_TO_SAM: dict[str, SamAccountTypeCodes] = { + EntityTypeNames.USER: SamAccountTypeCodes.SAM_USER_OBJECT, + EntityTypeNames.GROUP: SamAccountTypeCodes.SAM_GROUP_OBJECT, + EntityTypeNames.COMPUTER: SamAccountTypeCodes.SAM_MACHINE_ACCOUNT, } @@ -42,15 +42,16 @@ async def _add_samaccounttype(connection: AsyncConnection) -> None: # noqa: ARG session = await cnt.get(AsyncSession) entity_types = await session.scalars( - select(EntityType).where( - qa(EntityType.name).in_(_SECURITY_PRINCIPAL_TYPES), - ), - ) + select(EntityType) + .where(qa(EntityType.name).in_(_SECURITY_PRINCIPAL_TYPES)), + ) # fmt: skip entity_type_ids = [et.id for et in entity_types] if not entity_type_ids: return - has_sam = select(qa(Attribute.directory_id)).where( + has_sam = select( + qa(Attribute.directory_id), + ).where( qa(Attribute.name).ilike(_SAM_ACCOUNT_TYPE_ATTR.lower()), ) dirs_without_sam = await session.scalars( @@ -59,13 +60,15 @@ async def _add_samaccounttype(connection: AsyncConnection) -> None: # noqa: ARG qa(Directory.entity_type_id).in_(entity_type_ids), ~qa(Directory.id).in_(has_sam), ) - .options(selectinload(qa(Directory.entity_type))), + .options(joinedload(qa(Directory.entity_type))), ) for directory in dirs_without_sam: - if not directory.entity_type: - continue - sam_value = _ENTITY_TO_SAM.get(directory.entity_type.name) + sam_value = ( + _ENTITY_TO_SAM.get(directory.entity_type.name) + if directory.entity_type + else None + ) if sam_value is None: continue diff --git a/app/constants.py b/app/constants.py index 4483d65ac..8a743ed5b 100644 --- a/app/constants.py +++ b/app/constants.py @@ -6,7 +6,7 @@ from typing import TypedDict -from enums import EntityTypeNames, SamAccountType +from enums import EntityTypeNames, SamAccountTypeCodes GROUPS_CONTAINER_NAME = "Groups" COMPUTERS_CONTAINER_NAME = "Computers" @@ -24,7 +24,7 @@ "groupType": ["-2147483646"], "instanceType": ["4"], "sAMAccountName": ["groups"], - "sAMAccountType": [str(SamAccountType.SAM_GROUP_OBJECT.value)], + "sAMAccountType": [str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value)], } @@ -309,7 +309,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [DOMAIN_ADMIN_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], "gidNumber": ["512"], }, @@ -324,7 +324,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [DOMAIN_USERS_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], "gidNumber": ["513"], }, @@ -339,7 +339,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [READ_ONLY_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], "gidNumber": ["521"], }, @@ -354,7 +354,7 @@ class EntityTypeData(TypedDict): "instanceType": ["4"], "sAMAccountName": [DOMAIN_COMPUTERS_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], "gidNumber": ["515"], }, diff --git a/app/enums.py b/app/enums.py index f866b448d..1f6e8f798 100644 --- a/app/enums.py +++ b/app/enums.py @@ -256,7 +256,7 @@ class DomainCodes(IntEnum): SHADOW = 14 -class SamAccountType(IntEnum): +class SamAccountTypeCodes(IntEnum): """SAM Account Type values.""" SAM_DOMAIN_OBJECT = 0 diff --git a/app/ldap_protocol/auth/use_cases.py b/app/ldap_protocol/auth/use_cases.py index e52538bee..136f2cf23 100644 --- a/app/ldap_protocol/auth/use_cases.py +++ b/app/ldap_protocol/auth/use_cases.py @@ -14,7 +14,7 @@ FIRST_SETUP_DATA, USERS_CONTAINER_NAME, ) -from enums import SamAccountType +from enums import SamAccountTypeCodes from ldap_protocol.auth.dto import SetupDTO from ldap_protocol.auth.setup_gateway import SetupGateway from ldap_protocol.identity.exceptions import ( @@ -116,7 +116,7 @@ def _create_user_data(self, dto: SetupDTO) -> dict: "primaryGroupID": ["512"], "givenName": [dto.username], "sAMAccountType": [ - str(SamAccountType.SAM_USER_OBJECT) + str(SamAccountTypeCodes.SAM_USER_OBJECT), ], }, "objectSid": 500, diff --git a/app/ldap_protocol/ldap_requests/add.py b/app/ldap_protocol/ldap_requests/add.py index 70d6425ee..75a498516 100644 --- a/app/ldap_protocol/ldap_requests/add.py +++ b/app/ldap_protocol/ldap_requests/add.py @@ -13,7 +13,7 @@ from constants import DOMAIN_COMPUTERS_GROUP_NAME, DOMAIN_USERS_GROUP_NAME from entities import Attribute, Directory, Group, User -from enums import AceType, EntityTypeNames, SamAccountType +from enums import AceType, EntityTypeNames, SamAccountTypeCodes from ldap_protocol.asn1parser import ASN1Row from ldap_protocol.kerberos.exceptions import ( KRBAPIAddPrincipalError, @@ -431,7 +431,7 @@ async def handle( # noqa: C901 attributes.append( Attribute( name="sAMAccountType", - value=str(SamAccountType.SAM_USER_OBJECT), + value=str(SamAccountTypeCodes.SAM_USER_OBJECT), directory_id=new_dir.id, ), ) @@ -439,7 +439,7 @@ async def handle( # noqa: C901 attributes.append( Attribute( name="sAMAccountType", - value=str(SamAccountType.SAM_GROUP_OBJECT), + value=str(SamAccountTypeCodes.SAM_GROUP_OBJECT), directory_id=new_dir.id, ), ) @@ -447,7 +447,7 @@ async def handle( # noqa: C901 attributes.append( Attribute( name="sAMAccountType", - value=str(SamAccountType.SAM_MACHINE_ACCOUNT), + value=str(SamAccountTypeCodes.SAM_MACHINE_ACCOUNT), directory_id=new_dir.id, ), ) diff --git a/app/ldap_protocol/utils/queries.py b/app/ldap_protocol/utils/queries.py index f6fa50918..39d93b016 100644 --- a/app/ldap_protocol/utils/queries.py +++ b/app/ldap_protocol/utils/queries.py @@ -16,7 +16,7 @@ from sqlalchemy.sql.expression import ColumnElement from entities import Attribute, Directory, Group, User -from enums import SamAccountType +from enums import SamAccountTypeCodes from ldap_protocol.ldap_schema.attribute_value_validator import ( AttributeValueValidator, AttributeValueValidatorError, @@ -395,7 +395,7 @@ async def create_group( "instanceType": ["4"], "sAMAccountName": [dir_.name], dir_.rdname: [dir_.name], - "sAMAccountType": [str(SamAccountType.SAM_GROUP_OBJECT.value)], + "sAMAccountType": [str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value)], "gidNumber": [str(create_integer_hash(dir_.name))], } diff --git a/tests/constants.py b/tests/constants.py index c17b77096..92e89e8bf 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -11,7 +11,7 @@ GROUPS_CONTAINER_NAME, USERS_CONTAINER_NAME, ) -from enums import SamAccountType +from enums import SamAccountTypeCodes from ldap_protocol.objects import UserAccountControlFlag TEST_DATA = [ @@ -32,7 +32,7 @@ "instanceType": ["4"], "sAMAccountName": [DOMAIN_ADMIN_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], }, }, @@ -46,7 +46,7 @@ "instanceType": ["4"], "sAMAccountName": ["developers"], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], }, }, @@ -59,7 +59,7 @@ "instanceType": ["4"], "sAMAccountName": ["admin login only"], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], }, }, @@ -72,7 +72,7 @@ "instanceType": ["4"], "sAMAccountName": [DOMAIN_USERS_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], }, }, @@ -85,7 +85,7 @@ "instanceType": ["4"], "sAMAccountName": [DOMAIN_COMPUTERS_GROUP_NAME], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], }, }, @@ -380,7 +380,9 @@ "instanceType": ["4"], "sAMAccountName": ["testGroup1"], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str( + SamAccountTypeCodes.SAM_GROUP_OBJECT.value + ), ], }, }, @@ -395,7 +397,7 @@ "instanceType": ["4"], "sAMAccountName": ["testGroup2"], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], }, }, @@ -418,7 +420,7 @@ "instanceType": ["4"], "sAMAccountName": ["testGroup3"], "sAMAccountType": [ - str(SamAccountType.SAM_GROUP_OBJECT.value), + str(SamAccountTypeCodes.SAM_GROUP_OBJECT.value), ], }, }, diff --git a/tests/test_api/test_main/test_router/test_add.py b/tests/test_api/test_main/test_router/test_add.py index 9ccaca2ad..f20d516d2 100644 --- a/tests/test_api/test_main/test_router/test_add.py +++ b/tests/test_api/test_main/test_router/test_add.py @@ -8,7 +8,7 @@ from fastapi import status from httpx import AsyncClient -from enums import SamAccountType +from enums import SamAccountTypeCodes from ldap_protocol.ldap_codes import LDAPCodes from ldap_protocol.objects import UserAccountControlFlag from tests.api_datasets import test_api_forbidden_chars_in_attr_value @@ -220,7 +220,7 @@ async def test_add_user_samaccounttype( a["type"]: a for a in data["search_result"][0]["partial_attributes"] } assert attrs["sAMAccountType"]["vals"][0] == str( - SamAccountType.SAM_USER_OBJECT, + SamAccountTypeCodes.SAM_USER_OBJECT, ) From b8ef04a8da0cf0f6dd74682895683a2cd12e14c9 Mon Sep 17 00:00:00 2001 From: "m.shvets" Date: Tue, 3 Feb 2026 15:14:53 +0300 Subject: [PATCH 5/5] Fix: add missing comma in sAMAccountType assignment in TEST_DATA --- tests/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/constants.py b/tests/constants.py index 92e89e8bf..2163898ed 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -381,7 +381,7 @@ "sAMAccountName": ["testGroup1"], "sAMAccountType": [ str( - SamAccountTypeCodes.SAM_GROUP_OBJECT.value + SamAccountTypeCodes.SAM_GROUP_OBJECT.value, ), ], },