diff --git a/app/alembic/versions/275222846605_initial_ldap_schema.py b/app/alembic/versions/275222846605_initial_ldap_schema.py index e9bcf6344..16d4ef991 100644 --- a/app/alembic/versions/275222846605_initial_ldap_schema.py +++ b/app/alembic/versions/275222846605_initial_ldap_schema.py @@ -218,6 +218,7 @@ async def _create_attribute_types(connection: AsyncConnection) -> None: # noqa: AttributeTypeDTO( oid=oid, name=name, + ldap_display_name=name, syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, diff --git a/app/api/ldap_schema/adapters/attribute_type.py b/app/api/ldap_schema/adapters/attribute_type.py index 9a12debf9..747290797 100644 --- a/app/api/ldap_schema/adapters/attribute_type.py +++ b/app/api/ldap_schema/adapters/attribute_type.py @@ -40,6 +40,7 @@ def _convert_update_uschema_to_dto( return AttributeTypeDTO[None]( oid="", name="", + ldap_display_name="", syntax=request.syntax, single_value=request.single_value, no_user_modification=request.no_user_modification, @@ -54,6 +55,10 @@ def _convert_update_uschema_to_dto( AttributeTypeDTO[None], recipe=[ allow_unlinked_optional(P[AttributeTypeDTO].id), + link_function( + lambda _: _.ldap_display_name or "", + P[AttributeTypeDTO].ldap_display_name, + ), link_function( lambda _: DEFAULT_ATTRIBUTE_TYPE_SYNTAX, P[AttributeTypeDTO].syntax, diff --git a/app/api/ldap_schema/schema.py b/app/api/ldap_schema/schema.py index d4c07c827..ad5e70a27 100644 --- a/app/api/ldap_schema/schema.py +++ b/app/api/ldap_schema/schema.py @@ -22,6 +22,7 @@ class AttributeTypeSchema(BaseModel, Generic[_IdT]): id: _IdT = Field(default=None) # type: ignore[assignment] oid: str = Field(pattern=OID_REGEX_PATTERN, max_length=128) name: str = Field(min_length=1, max_length=255) + ldap_display_name: str | None = Field(default=None, max_length=255) syntax: str single_value: bool no_user_modification: bool diff --git a/app/constants.py b/app/constants.py index 514f40557..a6192f314 100644 --- a/app/constants.py +++ b/app/constants.py @@ -295,6 +295,8 @@ ), ) +ATTRIBUTE_TYPE_OBJECT_CLASS_NAMES = ["top", "attributeSchema"] +OBJECT_CLASS_OBJECT_CLASS_NAMES = ["top", "classSchema"] # NOTE: Second time load ENTITY_TYPE_DTOS_V2: tuple[EntityTypeDTO, ...] = ( @@ -306,12 +308,12 @@ EntityTypeDTO( name=EntityTypeNames.ATTRIBUTE_TYPE, is_system=True, - object_class_names=["top", "attributeSchema"], + object_class_names=ATTRIBUTE_TYPE_OBJECT_CLASS_NAMES, ), EntityTypeDTO( name=EntityTypeNames.OBJECT_CLASS, is_system=True, - object_class_names=["top", "classSchema"], + object_class_names=OBJECT_CLASS_OBJECT_CLASS_NAMES, ), ) diff --git a/app/ldap_protocol/ldap_schema/_legacy/attribute_type/attribute_type_dao.py b/app/ldap_protocol/ldap_schema/_legacy/attribute_type/attribute_type_dao.py index 6f613621c..823df60fd 100644 --- a/app/ldap_protocol/ldap_schema/_legacy/attribute_type/attribute_type_dao.py +++ b/app/ldap_protocol/ldap_schema/_legacy/attribute_type/attribute_type_dao.py @@ -5,11 +5,7 @@ """ from adaptix import P -from adaptix.conversion import ( - allow_unlinked_optional, - get_converter, - link_function, -) +from adaptix.conversion import get_converter, link_function from entities_legacy import AttributeTypeLegacy, ObjectClassLegacy from sqlalchemy import delete, or_, select, update from sqlalchemy.exc import IntegrityError @@ -24,13 +20,27 @@ ) from repo.pg.tables import queryable_attr as qa -_convert_model_to_dto = get_converter( - AttributeTypeLegacy, - AttributeTypeDTO, - recipe=[ - allow_unlinked_optional(P[AttributeTypeDTO].object_class_names), - ], -) + +def _convert_model_to_dto( + attr_type: AttributeTypeLegacy, +) -> AttributeTypeDTO[int]: + """Convert AttributeTypeLegacy to AttributeTypeDTO.""" + ldap_display_name = ( + f"{attr_type.name[0].lower()}{attr_type.name.replace('-', '')[1:]}" + ) + return AttributeTypeDTO[int]( + oid=attr_type.oid, + name=ldap_display_name, + ldap_display_name=ldap_display_name, + syntax=attr_type.syntax, + single_value=attr_type.single_value, + no_user_modification=attr_type.no_user_modification, + is_system=attr_type.is_system, + system_flags=attr_type.system_flags, + is_included_anr=attr_type.is_included_anr, + ) + + _convert_dto_to_model = get_converter( AttributeTypeDTO, AttributeTypeLegacy, diff --git a/app/ldap_protocol/ldap_schema/_legacy/object_class/object_class_dao.py b/app/ldap_protocol/ldap_schema/_legacy/object_class/object_class_dao.py index 10e7ebf6b..322a0ac25 100644 --- a/app/ldap_protocol/ldap_schema/_legacy/object_class/object_class_dao.py +++ b/app/ldap_protocol/ldap_schema/_legacy/object_class/object_class_dao.py @@ -34,6 +34,10 @@ allow_unlinked_optional(P[ObjectClassDTO].id), allow_unlinked_optional(P[ObjectClassDTO].entity_type_names), allow_unlinked_optional(P[AttributeTypeDTO].object_class_names), + link_function( + lambda _: "", + P[AttributeTypeDTO].ldap_display_name, + ), link_function(lambda x: x.kind, P[ObjectClassDTO].kind), ], ) diff --git a/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_dao.py b/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_dao.py index 8b24ff403..937ee225b 100644 --- a/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_dao.py +++ b/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_dao.py @@ -22,7 +22,8 @@ def _convert_model_to_dto(directory: Directory) -> AttributeTypeDTO[int]: return AttributeTypeDTO[int]( id=directory.id, - name=directory.name, + name=directory.attributes_dict[Names.LDAP_DISPLAY_NAME][0], + ldap_display_name=directory.attributes_dict[Names.LDAP_DISPLAY_NAME][0], oid=directory.attributes_dict[Names.OID][0], syntax=directory.attributes_dict[Names.SYNTAX][0], single_value=directory.attributes_dict[Names.SINGLE_VALUE][0] == "True", # noqa: E501 diff --git a/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_use_case.py b/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_use_case.py index 4891f0c55..74625fb65 100644 --- a/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_use_case.py +++ b/app/ldap_protocol/ldap_schema/attribute_type/attribute_type_use_case.py @@ -9,6 +9,7 @@ from sqlalchemy.exc import IntegrityError from abstract_service import AbstractService +from constants import ATTRIBUTE_TYPE_OBJECT_CLASS_NAMES from enums import AuthorizationRules, EntityTypeNames from ldap_protocol.ldap_schema.attribute_type.attribute_type_dao import ( AttributeTypeDAO, @@ -71,12 +72,23 @@ async def get_all(self) -> list[AttributeTypeDTO[int]]: async def create(self, dto: AttributeTypeDTO) -> None: """Create Attribute Type.""" + if not dto.ldap_display_name: + dto.ldap_display_name = f"{dto.name[0].lower()}{dto.name.replace('-', '')[1:]}" # noqa: E501 # fmt: skip + _dto = CreateDirDTO( name=dto.name, entity_type_name=EntityTypeNames.ATTRIBUTE_TYPE, attributes=( AttributeDTO(name=Names.OID, values=[str(dto.oid)]), AttributeDTO(name=Names.NAME, values=[str(dto.name)]), + AttributeDTO( + name=Names.OBJECT_CLASS, + values=ATTRIBUTE_TYPE_OBJECT_CLASS_NAMES, + ), + AttributeDTO( + name=Names.LDAP_DISPLAY_NAME, + values=[str(dto.ldap_display_name)], + ), AttributeDTO(name=Names.SYNTAX, values=[str(dto.syntax)]), AttributeDTO( name=Names.SINGLE_VALUE, diff --git a/app/ldap_protocol/ldap_schema/attribute_type/constants.py b/app/ldap_protocol/ldap_schema/attribute_type/constants.py index a432570b3..5a8854717 100644 --- a/app/ldap_protocol/ldap_schema/attribute_type/constants.py +++ b/app/ldap_protocol/ldap_schema/attribute_type/constants.py @@ -8,6 +8,8 @@ class AttributeTypeAttributeNames(StrEnum): OID = "attributeID" NAME = "name" + OBJECT_CLASS = "objectClass" + LDAP_DISPLAY_NAME = "lDAPDisplayName" SYNTAX = "attributeSyntax" SINGLE_VALUE = "isSingleValued" NO_USER_MODIFICATION = "systemOnly" diff --git a/app/ldap_protocol/ldap_schema/dto.py b/app/ldap_protocol/ldap_schema/dto.py index ae4eef8f3..bb3e33cb2 100644 --- a/app/ldap_protocol/ldap_schema/dto.py +++ b/app/ldap_protocol/ldap_schema/dto.py @@ -18,6 +18,7 @@ class AttributeTypeDTO(Generic[_IdT]): oid: str name: str + ldap_display_name: str syntax: str single_value: bool no_user_modification: bool diff --git a/app/ldap_protocol/ldap_schema/object_class/object_class_use_case.py b/app/ldap_protocol/ldap_schema/object_class/object_class_use_case.py index 3bf63e43c..62f96ef5c 100644 --- a/app/ldap_protocol/ldap_schema/object_class/object_class_use_case.py +++ b/app/ldap_protocol/ldap_schema/object_class/object_class_use_case.py @@ -9,6 +9,7 @@ from sqlalchemy.exc import IntegrityError from abstract_service import AbstractService +from constants import OBJECT_CLASS_OBJECT_CLASS_NAMES from enums import AuthorizationRules, EntityTypeNames from ldap_protocol.ldap_schema.attribute_type.attribute_type_dao import ( AttributeTypeDAO, @@ -111,7 +112,7 @@ async def create(self, dto: ObjectClassDTO[None, str]) -> None: attributes=( AttributeDTO( name=Names.OBJECT_CLASS, - values=["top", "classSchema"], + values=OBJECT_CLASS_OBJECT_CLASS_NAMES, ), AttributeDTO(name=Names.OID, values=[str(dto.oid)]), AttributeDTO(name=Names.NAME, values=[str(dto.name)]), diff --git a/app/ldap_protocol/ldap_schema/raw_definition_parser.py b/app/ldap_protocol/ldap_schema/raw_definition_parser.py index 1cbc29a36..3170ae2d5 100644 --- a/app/ldap_protocol/ldap_schema/raw_definition_parser.py +++ b/app/ldap_protocol/ldap_schema/raw_definition_parser.py @@ -47,9 +47,11 @@ def collect_attribute_type_dto_from_raw( if not name: raise ValueError("Attribute Type name is required") + ldap_display_name = f"{name[0].lower()}{name.replace('-', '')[1:]}" return AttributeTypeDTO( oid=attribute_type_info.oid, name=name, + ldap_display_name=ldap_display_name, syntax=attribute_type_info.syntax, single_value=attribute_type_info.single_value, no_user_modification=attribute_type_info.no_user_modification, diff --git a/interface b/interface index 18c43136b..acaa37fa9 160000 --- a/interface +++ b/interface @@ -1 +1 @@ -Subproject commit 18c43136b1e52d343f70f75ac099b9010da9abfb +Subproject commit acaa37fa96534f2df4c8393a4d4f8acb77cf9722 diff --git a/tests/conftest.py b/tests/conftest.py index 5c8123b80..1f84db8a4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1116,6 +1116,7 @@ async def setup_session( AttributeTypeDTO[None]( oid="1.2.3.4.5.6.7.8", name="attr_with_bvalue", + ldap_display_name="attrWithBvalue", syntax="1.3.6.1.4.1.1466.115.121.1.40", # Octet String single_value=True, no_user_modification=False, @@ -1126,6 +1127,7 @@ async def setup_session( AttributeTypeDTO[None]( oid="1.2.3.4.5.6.7.8.9", name="testing_attr", + ldap_display_name="testingAttr", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, diff --git a/tests/test_api/test_ldap_schema/test_attribute_type_router.py b/tests/test_api/test_ldap_schema/test_attribute_type_router.py index b31790507..d7370cb9a 100644 --- a/tests/test_api/test_ldap_schema/test_attribute_type_router.py +++ b/tests/test_api/test_ldap_schema/test_attribute_type_router.py @@ -32,6 +32,7 @@ async def test_create_one_attribute_type( schema = AttributeTypeSchema[None]( oid="1.2.3.4", name="testAttribute", + ldap_display_name="testAttribute", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, @@ -57,6 +58,7 @@ async def test_create_attribute_type_conflict_when_already_exists( schema = AttributeTypeSchema( oid="1.2.3.4", name="testAttribute", + ldap_display_name="testAttribute", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, @@ -99,6 +101,7 @@ async def test_modify_one_attribute_type_raise_404( schema = AttributeTypeSchema( oid="1.2.3.4", name="testAttributeType1", + ldap_display_name="testAttributeType1", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, diff --git a/tests/test_api/test_ldap_schema/test_attribute_type_router_datasets.py b/tests/test_api/test_ldap_schema/test_attribute_type_router_datasets.py index 18dcac0d5..ee16ec622 100644 --- a/tests/test_api/test_ldap_schema/test_attribute_type_router_datasets.py +++ b/tests/test_api/test_ldap_schema/test_attribute_type_router_datasets.py @@ -13,6 +13,7 @@ "attribute_type_schema": AttributeTypeSchema( oid="1.2.3.4", name="testAttributeType0", + ldap_display_name="testAttributeType0", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=False, no_user_modification=False, @@ -32,6 +33,7 @@ "attribute_type_schema": AttributeTypeSchema( oid="1.2.3.4", name="testAttributeType1", + ldap_display_name="testAttributeType1", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, @@ -51,6 +53,7 @@ "attribute_type_schema": AttributeTypeSchema( oid="1.2.3.4", name="testAttributeType2", + ldap_display_name="testAttributeType2", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=False, no_user_modification=False, @@ -73,6 +76,7 @@ AttributeTypeSchema( oid="1.2.3.4", name="testAttributeType1", + ldap_display_name="testAttributeType1", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, @@ -82,6 +86,7 @@ AttributeTypeSchema( oid="1.2.3.4.5", name="testAttributeType2", + ldap_display_name="testAttributeType2", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, @@ -100,6 +105,7 @@ AttributeTypeSchema( oid="1.2.3.4", name="testAttributeType1", + ldap_display_name="testAttributeType1", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, diff --git a/tests/test_api/test_ldap_schema/test_entity_type_router.py b/tests/test_api/test_ldap_schema/test_entity_type_router.py index 3fb0bbddb..5d389e88b 100644 --- a/tests/test_api/test_ldap_schema/test_entity_type_router.py +++ b/tests/test_api/test_ldap_schema/test_entity_type_router.py @@ -132,6 +132,7 @@ async def test_get_entity_type_attributes(http_client: AsyncClient) -> None: AttributeTypeSchema( oid="1.2.3.100", name="testEntityTypeAttr1", + ldap_display_name="testEntityTypeAttr1", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, @@ -141,6 +142,7 @@ async def test_get_entity_type_attributes(http_client: AsyncClient) -> None: AttributeTypeSchema( oid="1.2.3.101", name="testEntityTypeAttr2", + ldap_display_name="testEntityTypeAttr2", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, diff --git a/tests/test_api/test_ldap_schema/test_object_class_router_datasets.py b/tests/test_api/test_ldap_schema/test_object_class_router_datasets.py index 1824cee7a..12a6e7ac9 100644 --- a/tests/test_api/test_ldap_schema/test_object_class_router_datasets.py +++ b/tests/test_api/test_ldap_schema/test_object_class_router_datasets.py @@ -8,6 +8,7 @@ { "oid": "1.2.3.4", "name": "testAttributeType1", + "ldap_display_name": "testAttributeType1", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -17,6 +18,7 @@ { "oid": "1.2.3.4.5", "name": "testAttributeType2", + "ldap_display_name": "testAttributeType2", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -26,6 +28,7 @@ { "oid": "1.2.3.4.5.6", "name": "testAttributeType3", + "ldap_display_name": "testAttributeType3", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -95,6 +98,7 @@ { "oid": "1.2.3.4", "name": "testAttributeType1", + "ldap_display_name": "testAttributeType1", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -121,6 +125,7 @@ { "oid": "1.2.3.4", "name": "testAttributeType1", + "ldap_display_name": "testAttributeType1", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -130,6 +135,7 @@ { "oid": "1.2.3.4.5", "name": "testAttributeType2", + "ldap_display_name": "testAttributeType2", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -159,6 +165,7 @@ { "oid": "1.2.3.4", "name": "testAttributeType1", + "ldap_display_name": "testAttributeType1", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -168,6 +175,7 @@ { "oid": "1.2.3.4.5", "name": "testAttributeType2", + "ldap_display_name": "testAttributeType2", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, @@ -177,6 +185,7 @@ { "oid": "1.2.3.4.5.6", "name": "testAttributeType3", + "ldap_display_name": "testAttributeType3", "syntax": "1.3.6.1.4.1.1466.115.121.1.15", "single_value": True, "no_user_modification": False, diff --git a/tests/test_ldap/test_ldap_schema/test_attribute_type_system_flags_use_case.py b/tests/test_ldap/test_ldap_schema/test_attribute_type_system_flags_use_case.py index e91b7ba8c..50cd75b46 100644 --- a/tests/test_ldap/test_ldap_schema/test_attribute_type_system_flags_use_case.py +++ b/tests/test_ldap/test_ldap_schema/test_attribute_type_system_flags_use_case.py @@ -23,6 +23,7 @@ async def test_attribute_type_system_flags_use_case_is_not_replicated( AttributeTypeDTO( oid="1.2.3.4", name="objectClass123", + ldap_display_name="objectClass123", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False, @@ -47,6 +48,7 @@ async def test_attribute_type_system_flags_use_case_is_replicated( AttributeTypeDTO( oid="1.2.3.4", name="objectClass123", + ldap_display_name="objectClass123", syntax="1.3.6.1.4.1.1466.115.121.1.15", single_value=True, no_user_modification=False,