From 7b21b768ff6537d14287cc53e96821b89de9ff28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Goran=20Meki=C4=87?= Date: Thu, 8 Jan 2026 04:12:55 +0100 Subject: [PATCH] Get per domain users --- freenit/api/domain/ldap.py | 27 ++++++++++++++++++++++----- freenit/models/ldap/group.py | 2 ++ freenit/models/ldap/user.py | 21 +++++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/freenit/api/domain/ldap.py b/freenit/api/domain/ldap.py index 00370f6..6cb12dd 100644 --- a/freenit/api/domain/ldap.py +++ b/freenit/api/domain/ldap.py @@ -8,6 +8,7 @@ from freenit.models.ldap.group import Group, GroupCreate from freenit.models.pagination import Page from freenit.models.user import User +from freenit.models.safe import UserSafe from freenit.permissions import domain_perms, group_perms tags = ["domain"] @@ -25,8 +26,7 @@ async def get( ) -> Page[Domain]: data = await Domain.get_all() perpage = len(data) - data = Page(total=perpage, page=page, pages=1, perpage=perpage, data=data) - return data + return Page(total=perpage, page=page, pages=1, perpage=perpage, data=data) @staticmethod async def post(data: DomainCreate, _: User = Depends(domain_perms)) -> Domain: @@ -63,7 +63,7 @@ async def delete(name, _: User = Depends(domain_perms)) -> Domain: @route("/domains/{name}/groups", tags=tags) class DomainGroupListAPI: @staticmethod - @description("Get domain groups") + @description("Get groups") async def get( name, page: int = Header(default=1), @@ -73,10 +73,10 @@ async def get( domain = await Domain.get(name) data = await Group.get_all(domain.ou) total = len(data) - data = Page(total=total, page=1, pages=1, perpage=total, data=data) - return data + return Page(total=total, page=1, pages=1, perpage=total, data=data) @staticmethod + @description("Create group") async def post(name, data: GroupCreate, _: User = Depends(group_perms)) -> Group: domain = await Domain.get(name) if data.name == "": @@ -92,10 +92,12 @@ async def post(name, data: GroupCreate, _: User = Depends(group_perms)) -> Group @route("/domains/{name}/groups/{group}", tags=tags) class DomainGroupDetailAPI: @staticmethod + @description("Get group") async def get(name, group, _: User = Depends(group_perms)) -> Group: return await Group.get(group, name) @staticmethod + @description("Destroy group") async def delete(name, group, _: User = Depends(group_perms)) -> Group: domain = await Domain.get(name) gr = await Group.get(group, domain.ou) @@ -120,3 +122,18 @@ async def delete(name, group, uid, _: User = Depends(group_perms)) -> Group: gr = await Group.get(group, name) await gr.remove(user) return gr + + +@route("/domains/{name}/users", tags=tags) +class DomainUsersDetailAPI: + @staticmethod + @description("Get domain users") + async def get( + name, + page: int = Header(default=1), + perpage: int = Header(default=10), + _: User = Depends(group_perms), + ) -> Page[UserSafe]: + data = await User.get_by_domain(name) + perpage = len(data) + return Page(total=perpage, page=page, pages=1, perpage=perpage, data=data) diff --git a/freenit/models/ldap/group.py b/freenit/models/ldap/group.py index dc46b6c..8d52f92 100644 --- a/freenit/models/ldap/group.py +++ b/freenit/models/ldap/group.py @@ -10,6 +10,7 @@ class Group(LDAPBaseModel): cn: str = Field("", description=("Common name")) + gidNumber: int = Field(0, description=("Group ID number")) users: list = Field([], description=("Group members")) @classmethod @@ -18,6 +19,7 @@ def from_entry(cls, entry): cn=entry["cn"][0], dn=str(entry["dn"]), users=entry.get("memberUid", []), + gidNumber=entry["gidNumber"][0], ) return group diff --git a/freenit/models/ldap/user.py b/freenit/models/ldap/user.py index 636bf83..8d34a43 100644 --- a/freenit/models/ldap/user.py +++ b/freenit/models/ldap/user.py @@ -219,6 +219,27 @@ async def get_by_email(cls, email): await user._fill_groups() return user + @classmethod + async def get_by_domain(cls, domain: str): + client = get_client() + try: + async with client.connect(is_async=True) as conn: + res = await conn.search( + f"ou={domain},dc=account,dc=ldap", + LDAPSearchScope.SUB, + "objectClass=person", + ["*", "memberOf"], + ) + except errors.AuthenticationError: + raise HTTPException(status_code=403, detail="Failed to login") + + data = [] + for udata in res: + user = cls.from_entry(udata) + await user._fill_groups() + data.append(user) + return data + class User(UserSafe): password: str = Field("", description=("Password"))