From 25d9c81075bfa3331524074cac21e1b28d9fb244 Mon Sep 17 00:00:00 2001 From: "m.shvets" Date: Fri, 23 Jan 2026 09:14:54 +0300 Subject: [PATCH 1/2] Add: Implement bulk modify DN endpoint and corresponding tests --- app/api/main/router.py | 12 +++ .../test_main/test_router/test_modify_dn.py | 78 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/app/api/main/router.py b/app/api/main/router.py index f4df578e8..4477d16ea 100644 --- a/app/api/main/router.py +++ b/app/api/main/router.py @@ -111,6 +111,18 @@ async def modify_dn( return await request.handle_api(req.state.dishka_container) +@entry_router.post("/update/dn_many", error_map=error_map) +async def modify_dn_many( + requests: list[ModifyDNRequest], + req: Request, +) -> list[LDAPResult]: + """LDAP MODIFY entry DN request.""" + results = [] + for request in requests: + results.append(await request.handle_api(req.state.dishka_container)) + return results + + @entry_router.delete("/delete", error_map=error_map) async def delete( request: DeleteRequest, diff --git a/tests/test_api/test_main/test_router/test_modify_dn.py b/tests/test_api/test_main/test_router/test_modify_dn.py index b27360dae..3b39ce771 100644 --- a/tests/test_api/test_main/test_router/test_modify_dn.py +++ b/tests/test_api/test_main/test_router/test_modify_dn.py @@ -540,3 +540,81 @@ async def test_api_update_dn_invalid_new_superior( assert isinstance(data, dict) assert data.get("resultCode") == LDAPCodes.INVALID_DN_SYNTAX + + +@pytest.mark.asyncio +@pytest.mark.usefixtures("adding_test_user") +@pytest.mark.usefixtures("setup_session") +@pytest.mark.usefixtures("session") +async def test_api_modify_dn_many(http_client: AsyncClient) -> None: + """Test API for bulk modify DN.""" + entry_dn_1 = "cn=test,dc=md,dc=test" + entry_dn_2 = "cn=test2,dc=md,dc=test" + + response = await http_client.post( + "/entry/add", + json={ + "entry": entry_dn_2, + "password": None, + "attributes": [ + {"type": "name", "vals": ["test2"]}, + {"type": "cn", "vals": ["test2"]}, + {"type": "objectClass", "vals": ["organization", "top"]}, + ], + }, + ) + assert response.json()["resultCode"] == LDAPCodes.SUCCESS + + response = await http_client.post( + "/entry/update/dn_many", + json=[ + { + "entry": entry_dn_1, + "newrdn": "cn=test", + "deleteoldrdn": True, + "new_superior": "ou=testModifyDn1,dc=md,dc=test", + }, + { + "entry": entry_dn_2, + "newrdn": "cn=test2", + "deleteoldrdn": True, + "new_superior": "ou=testModifyDn1,dc=md,dc=test", + }, + ], + ) + + data = response.json() + assert all( + result.get("resultCode") == LDAPCodes.SUCCESS for result in data + ) + + +@pytest.mark.asyncio +@pytest.mark.usefixtures("adding_test_user") +@pytest.mark.usefixtures("setup_session") +@pytest.mark.usefixtures("session") +async def test_api_modify_dn_many_with_error(http_client: AsyncClient) -> None: + """Test bulk modify DN with one invalid entry.""" + entry_dn = "cn=test,dc=md,dc=test" + + response = await http_client.post( + "/entry/update/dn_many", + json=[ + { + "entry": entry_dn, + "newrdn": "cn=test", + "deleteoldrdn": True, + "new_superior": "ou=testModifyDn1,dc=md,dc=test", + }, + { + "entry": "cn=nonExistent,dc=md,dc=test", + "newrdn": "cn=nonExistent", + "deleteoldrdn": True, + "new_superior": "dc=md,dc=test", + }, + ], + ) + + data = response.json() + assert data[0].get("resultCode") == LDAPCodes.SUCCESS + assert data[1].get("resultCode") == LDAPCodes.NO_SUCH_OBJECT From ab36312a9f70cd1df4805b8d4bced322399820e4 Mon Sep 17 00:00:00 2001 From: "m.shvets" Date: Fri, 23 Jan 2026 13:51:18 +0300 Subject: [PATCH 2/2] Refactor: Update endpoint path for bulk modify DN requests --- app/api/main/router.py | 2 +- interface | 2 +- tests/test_api/test_main/test_router/test_modify_dn.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/api/main/router.py b/app/api/main/router.py index 4477d16ea..f26881b38 100644 --- a/app/api/main/router.py +++ b/app/api/main/router.py @@ -111,7 +111,7 @@ async def modify_dn( return await request.handle_api(req.state.dishka_container) -@entry_router.post("/update/dn_many", error_map=error_map) +@entry_router.post("/update_many/dn", error_map=error_map) async def modify_dn_many( requests: list[ModifyDNRequest], req: Request, diff --git a/interface b/interface index 95ed5e191..f31962020 160000 --- a/interface +++ b/interface @@ -1 +1 @@ -Subproject commit 95ed5e191cdafa07b1dfac96a1659926679ead97 +Subproject commit f31962020a6689e6a4c61fb3349db5b5c7895f92 diff --git a/tests/test_api/test_main/test_router/test_modify_dn.py b/tests/test_api/test_main/test_router/test_modify_dn.py index 3b39ce771..950e1801c 100644 --- a/tests/test_api/test_main/test_router/test_modify_dn.py +++ b/tests/test_api/test_main/test_router/test_modify_dn.py @@ -566,7 +566,7 @@ async def test_api_modify_dn_many(http_client: AsyncClient) -> None: assert response.json()["resultCode"] == LDAPCodes.SUCCESS response = await http_client.post( - "/entry/update/dn_many", + "/entry/update_many/dn", json=[ { "entry": entry_dn_1, @@ -598,7 +598,7 @@ async def test_api_modify_dn_many_with_error(http_client: AsyncClient) -> None: entry_dn = "cn=test,dc=md,dc=test" response = await http_client.post( - "/entry/update/dn_many", + "/entry/update_many/dn", json=[ { "entry": entry_dn,