From d2b2f06f57762e45fd7ffa18a8824294a0ef3e59 Mon Sep 17 00:00:00 2001 From: Mikhail Opryshko Date: Fri, 11 Sep 2026 15:58:47 +0300 Subject: [PATCH 1/2] updated method /api/v3/botx/users/users_as_csv --- pybotx/client/users_api/user_from_csv.py | 24 +++-- pybotx/models/users.py | 8 ++ tests/client/users_api/test_users_as_csv.py | 110 +++++++++++--------- 3 files changed, 85 insertions(+), 57 deletions(-) diff --git a/pybotx/client/users_api/user_from_csv.py b/pybotx/client/users_api/user_from_csv.py index 88b9bb38..f764c53d 100644 --- a/pybotx/client/users_api/user_from_csv.py +++ b/pybotx/client/users_api/user_from_csv.py @@ -15,25 +15,29 @@ class BotXAPIUserFromCSVResult(VerifiedPayloadBaseModel): huid: UUID = Field(alias="HUID") ad_login: str = Field(alias="AD Login") ad_domain: str = Field(alias="Domain") - email: str | None = Field(alias="AD E-mail") + email: str | None = Field(default=None, alias="AD E-mail") name: str = Field(alias="Name") sync_source: APISyncSourceTypes | str = Field(alias="Sync source") active: bool = Field(alias="Active") user_kind: APIUserKinds = Field(alias="Kind") - company: str | None = Field(alias="Company") - department: str | None = Field(alias="Department") - position: str | None = Field(alias="Position") + user_dn: str | None = Field(default=None, alias="User DN") + company: str | None = Field(default=None, alias="Company") + department: str | None = Field(default=None, alias="Department") + position: str | None = Field(default=None, alias="Position") avatar: str | None = Field(default=None, alias="Avatar") avatar_preview: str | None = Field(default=None, alias="Avatar preview") office: str | None = Field(default=None, alias="Office") - manager: str | None = Field(alias="Manager") - manager_huid: UUID | None = Field(alias="Manager HUID") + manager: str | None = Field(default=None, alias="Manager") + manager_huid: UUID | None = Field(default=None, alias="Manager HUID") + manager_dn: str | None = Field(default=None, alias="Manager DN") description: str | None = Field(default=None, alias="Description") phone: str | None = Field(default=None, alias="Phone") other_phone: str | None = Field(default=None, alias="Other phone") ip_phone: str | None = Field(default=None, alias="IP phone") other_ip_phone: str | None = Field(default=None, alias="Other IP phone") personnel_number: str | None = Field(default=None, alias="Personnel number") + ad_groups: str | None = Field(default=None, alias="AD Groups") + openid_roles: str | None = Field(default=None, alias="OpenID Roles") @field_validator( "email", @@ -51,6 +55,10 @@ class BotXAPIUserFromCSVResult(VerifiedPayloadBaseModel): "ip_phone", "other_ip_phone", "personnel_number", + "user_dn", + "manager_dn", + "ad_groups", + "openid_roles", mode="before", ) @classmethod @@ -70,6 +78,7 @@ def to_domain(self) -> UserFromCSV: sync_source=convert_sync_source_type_to_domain(self.sync_source), active=self.active, user_kind=convert_user_kind_to_domain(self.user_kind), + user_dn=self.user_dn, company=self.company, department=self.department, position=self.position, @@ -78,10 +87,13 @@ def to_domain(self) -> UserFromCSV: office=self.office, manager=self.manager, manager_huid=self.manager_huid, + manager_dn=self.manager_dn, description=self.description, phone=self.phone, other_phone=self.other_phone, ip_phone=self.ip_phone, other_ip_phone=self.other_ip_phone, personnel_number=self.personnel_number, + ad_groups=self.ad_groups, + openid_roles=self.openid_roles, ) diff --git a/pybotx/models/users.py b/pybotx/models/users.py index b0ca61ca..0527fa10 100644 --- a/pybotx/models/users.py +++ b/pybotx/models/users.py @@ -74,6 +74,7 @@ class UserFromCSV: sync_source: Synchronization source. active: Is the user active or not. email: User email. + user_dn: User LDAP Distinguished Name. company: User company. department: User department. position: User position. @@ -82,12 +83,15 @@ class UserFromCSV: office: Office info. manager: User's manager full name. manager_huid: User's manager huid. + manager_dn: User's manager LDAP Distinguished Name. description: Description. phone: Phone number. other_phone: Extra phone number. ip_phone: Ip phone info. other_ip_phone: Extra ip phone. personnel_number: User's tabel number. + ad_groups: AD group names separated by semicolons. + openid_roles: OpenID role names separated by semicolons. """ huid: UUID @@ -98,6 +102,7 @@ class UserFromCSV: active: bool user_kind: UserKinds email: str | None = None + user_dn: str | None = None company: str | None = None department: str | None = None position: str | None = None @@ -106,9 +111,12 @@ class UserFromCSV: office: str | None = None manager: str | None = None manager_huid: UUID | None = None + manager_dn: str | None = None description: str | None = None phone: str | None = None other_phone: str | None = None ip_phone: str | None = None other_ip_phone: str | None = None personnel_number: str | None = None + ad_groups: str | None = None + openid_roles: str | None = None diff --git a/tests/client/users_api/test_users_as_csv.py b/tests/client/users_api/test_users_as_csv.py index 95b98fdc..1a1855be 100644 --- a/tests/client/users_api/test_users_as_csv.py +++ b/tests/client/users_api/test_users_as_csv.py @@ -70,9 +70,9 @@ async def test__users_as_csv__succeed( response_json=None, status=HTTPStatus.OK, response_content=( - b"HUID,AD Login,Domain,AD E-mail,Name,Sync source,Active,Kind,Company,Department,Position,Manager,Manager HUID,Personnel number,Description,IP phone,Other IP phone,Phone,Other phone,Avatar,Office,Avatar preview\n" - b"dbc8934f-d0d7-4a9e-89df-d45c137a851c,test_user_17,cts.example.com,,test_user_17,ad,false,cts_user,Company,Department,Position,Manager John,13a6909c-bce1-4dbf-8359-efb7ef8e5b34,Some number,Description,IP phone,Other IP phone,Phone,Other_phone,Avatar,Office,Avatar_preview\n" - b"13a6909c-bce1-4dbf-8359-efb7ef8e5b34,test_user_18,cts.example.com,,test_user_18,unsupported,true,cts_user,,,,,,,,,,,,,," + b"HUID,AD Login,Domain,AD E-mail,Name,Sync source,Active,Kind,User DN,Company,Department,Position,Manager,Manager HUID,Manager DN,Personnel number,Description,IP phone,Other IP phone,Phone,Other phone,Avatar,Office,Avatar preview,AD Groups,OpenID Roles\n" + b"dbc8934f-d0d7-4a9e-89df-d45c137a851c,test_user_17,cts.example.com,,test_user_17,ad,false,cts_user,cn=test_user_17;ou=users;dc=example;dc=com,Company,Department,Position,Manager John,13a6909c-bce1-4dbf-8359-efb7ef8e5b34,cn=manager;ou=users;dc=example;dc=com,Some number,Description,IP phone,Other IP phone,Phone,Other_phone,Avatar,Office,Avatar_preview,employees;developers;vpn-users,openid_user;openid_profile\n" + b"13a6909c-bce1-4dbf-8359-efb7ef8e5b34,test_user_18,cts.example.com,,test_user_18,unsupported,true,cts_user,,,,,,,,,,,,,,,,,," ), ) users_from_csv = [] @@ -88,54 +88,62 @@ async def test__users_as_csv__succeed( assert_deep_equal( users_from_csv, [ - UserFromCSV( - huid=UUID("dbc8934f-d0d7-4a9e-89df-d45c137a851c"), - ad_login="test_user_17", - ad_domain="cts.example.com", - username="test_user_17", - sync_source=SyncSourceTypes.AD, - active=False, - user_kind=UserKinds.CTS_USER, - email=None, - company="Company", - department="Department", - position="Position", - personnel_number="Some number", - manager="Manager John", - manager_huid=UUID("13a6909c-bce1-4dbf-8359-efb7ef8e5b34"), - description="Description", - ip_phone="IP phone", - other_ip_phone="Other IP phone", - phone="Phone", - other_phone="Other_phone", - avatar="Avatar", - office="Office", - avatar_preview="Avatar_preview", - ), - UserFromCSV( - huid=UUID("13a6909c-bce1-4dbf-8359-efb7ef8e5b34"), - ad_login="test_user_18", - ad_domain="cts.example.com", - username="test_user_18", - sync_source="UNSUPPORTED", - active=True, - user_kind=UserKinds.CTS_USER, - email=None, - company=None, - department=None, - position=None, - manager=None, - manager_huid=None, - personnel_number=None, - description=None, - ip_phone=None, - other_ip_phone=None, - phone=None, - other_phone=None, - avatar=None, - office=None, - avatar_preview=None, - ), + UserFromCSV( + huid=UUID("dbc8934f-d0d7-4a9e-89df-d45c137a851c"), + ad_login="test_user_17", + ad_domain="cts.example.com", + username="test_user_17", + sync_source=SyncSourceTypes.AD, + active=False, + user_kind=UserKinds.CTS_USER, + email=None, + user_dn="cn=test_user_17;ou=users;dc=example;dc=com", + company="Company", + department="Department", + position="Position", + personnel_number="Some number", + manager="Manager John", + manager_huid=UUID("13a6909c-bce1-4dbf-8359-efb7ef8e5b34"), + manager_dn="cn=manager;ou=users;dc=example;dc=com", + description="Description", + ip_phone="IP phone", + other_ip_phone="Other IP phone", + phone="Phone", + other_phone="Other_phone", + avatar="Avatar", + office="Office", + avatar_preview="Avatar_preview", + ad_groups="employees;developers;vpn-users", + openid_roles="openid_user;openid_profile", + ), + UserFromCSV( + huid=UUID("13a6909c-bce1-4dbf-8359-efb7ef8e5b34"), + ad_login="test_user_18", + ad_domain="cts.example.com", + username="test_user_18", + sync_source="UNSUPPORTED", + active=True, + user_kind=UserKinds.CTS_USER, + email=None, + user_dn=None, + company=None, + department=None, + position=None, + manager=None, + manager_huid=None, + manager_dn=None, + personnel_number=None, + description=None, + ip_phone=None, + other_ip_phone=None, + phone=None, + other_phone=None, + avatar=None, + office=None, + avatar_preview=None, + ad_groups=None, + openid_roles=None, + ), ], ) From 3432e262b419a5e9731e8cb161dead2e8cfeca49 Mon Sep 17 00:00:00 2001 From: Mikhail Opryshko Date: Fri, 11 Sep 2026 16:11:22 +0300 Subject: [PATCH 2/2] updated version 0.76.6 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b635e579..a4e789fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pybotx" -version = "0.76.5" +version = "0.76.6" description = "A python library for interacting with eXpress BotX API" authors = [ "Sidnev Nikolay ",