Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion freenit/api/domain/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from freenit.config import getConfig
from freenit.decorators import description
from freenit.models.ldap.domain import Domain, DomainCreate
from freenit.models.ldap.group import Group, GroupCreate
from freenit.models.pagination import Page
from freenit.models.user import User
from freenit.permissions import domain_perms
from freenit.permissions import domain_perms, group_perms

tags = ["domain"]
config = getConfig()
Expand Down Expand Up @@ -57,3 +58,65 @@ async def delete(name, _: User = Depends(domain_perms)) -> Domain:
return domain
except bonsai.errors.AuthenticationError:
raise HTTPException(status_code=403, detail="Failed to login")


@route("/domains/{name}/groups", tags=tags)
class DomainGroupListAPI:
@staticmethod
@description("Get domain groups")
async def get(
name,
page: int = Header(default=1),
perpage: int = Header(default=10),
_: User = Depends(group_perms),
) -> Page[Group]:
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

@staticmethod
async def post(name, data: GroupCreate, _: User = Depends(group_perms)) -> Group:
domain = await Domain.get(name)
if data.name == "":
raise HTTPException(status_code=409, detail="Name is mandatory")
group = Group.create(domain.ou, data.name)
try:
await group.save()
except bonsai.errors.AlreadyExists:
raise HTTPException(status_code=409, detail="Group already exists")
return group


@route("/domains/{name}/groups/{group}", tags=tags)
class DomainGroupDetailAPI:
@staticmethod
async def get(name, group, _: User = Depends(group_perms)) -> Group:
return await Group.get(group, name)

@staticmethod
async def delete(name, group, _: User = Depends(group_perms)) -> Group:
domain = await Domain.get(name)
gr = await Group.get(group, domain.ou)
gr.destroy()
return gr


@route("/domains/{name}/groups/{group}/{uid}", tags=tags)
class GroupUserAPI:
@staticmethod
@description("Assign user to group")
async def post(name, group, uid, _: User = Depends(group_perms)) -> Group:
user = await User.get_by_uid(uid)
gr = await Group.get(group, name)
await gr.add(user)
return gr

@staticmethod
@description("Remove user from group")
async def delete(name, group, uid, _: User = Depends(group_perms)) -> Group:
user = await User.get_by_uid(uid)
gr = await Group.get(group, name)
await gr.remove(user)
return gr
1 change: 0 additions & 1 deletion freenit/api/role/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
from .sql import RoleListAPI, RoleDetailAPI, RoleUserAPI
elif Role.dbtype() == "ldap":
from .ldap import RoleListAPI, RoleDetailAPI, RoleUserAPI
from .ldap_group import GroupListAPI, GroupDetailAPI, GroupUserAPI
4 changes: 3 additions & 1 deletion freenit/api/role/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ async def delete(role_name, id, _: User = Depends(role_perms)) -> RoleSafe:
role = await Role.get(role_name)
if len(role.users) == 1:
if role.users[0] == user.dn:
raise HTTPException(status_code=409, detail="Can not remove last member")
raise HTTPException(
status_code=409, detail="Can not remove last member"
)
await role.remove(user)
return role
77 changes: 0 additions & 77 deletions freenit/api/role/ldap_group.py

This file was deleted.

4 changes: 3 additions & 1 deletion freenit/api/role/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ async def get(id, _: User = Depends(role_perms)) -> RoleSafe:
return role

@staticmethod
async def patch(id, role_data: RoleOptional, _: User = Depends(role_perms)) -> RoleSafe:
async def patch(
id, role_data: RoleOptional, _: User = Depends(role_perms)
) -> RoleSafe:
if Role.dbtype() == "sql":
try:
role = await Role.objects.get(pk=id)
Expand Down
8 changes: 6 additions & 2 deletions freenit/models/ldap/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ async def get(cls, fqdn):
try:
async with client.connect(is_async=True) as conn:
dn = f"{config.ldap.domainDN},{config.ldap.userBase}"
res = await conn.search(dn.format(fqdn), LDAPSearchScope.SUB, f"(|{classes})")
res = await conn.search(
dn.format(fqdn), LDAPSearchScope.SUB, f"(|{classes})"
)
except errors.AuthenticationError:
raise HTTPException(status_code=403, detail="Failed to login")
if len(res) < 1:
Expand All @@ -49,7 +51,9 @@ async def get_rdomain(cls, fqdn):
try:
async with client.connect(is_async=True) as conn:
dn = f"{config.ldap.domainDN},{config.ldap.roleBase}"
res = await conn.search(dn.format(fqdn), LDAPSearchScope.SUB, f"(|{classes})")
res = await conn.search(
dn.format(fqdn), LDAPSearchScope.SUB, f"(|{classes})"
)
except errors.AuthenticationError:
raise HTTPException(status_code=403, detail="Failed to login")
if len(res) < 1:
Expand Down
5 changes: 3 additions & 2 deletions freenit/models/ldap/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def from_entry(cls, entry):

@classmethod
def create(cls, name, domain):
group = Group(dn=config.ldap.groupDn.format(name, domain), cn=name, users=[])
group = cls(dn=config.ldap.groupDn.format(name, domain), cn=name, users=[])
return group

@classmethod
Expand All @@ -50,7 +50,8 @@ async def get_all(cls, domain):
client = get_client()
try:
async with client.connect(is_async=True) as conn:
dn = config.ldap.roleBase.format(domain)
dom = config.ldap.domainDN.format(domain)
dn = f"{dom},{config.ldap.roleBase}"
res = await conn.search(dn, LDAPSearchScope.SUB, f"(|{classes})")
data = []
for gdata in res:
Expand Down
5 changes: 2 additions & 3 deletions freenit/models/ldap/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,16 @@ def from_entry(cls, entry):
users=entry[config.ldap.roleMemberAttr],
)


@classmethod
def create(cls, name):
dn=config.ldap.roleDN.format(name)
dn = config.ldap.roleDN.format(name)
return Role(dn=dn, cn=name, users=[])

@classmethod
async def get(cls, name):
classes = class2filter(config.ldap.roleClasses)
client = get_client()
dn=config.ldap.roleDN.format(name)
dn = config.ldap.roleDN.format(name)
try:
async with client.connect(is_async=True) as conn:
res = await conn.search(dn, LDAPSearchScope.SUB, f"(|{classes})")
Expand Down
5 changes: 3 additions & 2 deletions freenit/models/safe.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
auth = config.get_model("user")


if auth.User.dbtype() == 'sql':
if auth.User.dbtype() == "sql":
UserBase = auth.User.get_pydantic(exclude={"password"})
RoleBase = config.get_model("role").BaseRole
elif auth.User.dbtype() == 'ldap':
elif auth.User.dbtype() == "ldap":
UserBase = auth.UserSafe
RoleBase = config.get_model("role").Role


class UserSafe(UserBase):
pass


class RoleSafe(RoleBase):
users: List[str]
1 change: 1 addition & 0 deletions freenit/models/sql/role.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .base import BaseRole, ormar_config, make_optional


class Role(BaseRole):
ormar_config = ormar_config.copy()

Expand Down