Skip to content

Commit

Permalink
openapi/permissions: introduce OkayToIgnorePerm
Browse files Browse the repository at this point in the history
Change-Id: I3fe82638ae8607c805d1d00e919588060581138b
  • Loading branch information
anthonyh209 committed Oct 19, 2023
1 parent a610374 commit 705cd53
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 11 deletions.
18 changes: 14 additions & 4 deletions cmk/gui/openapi/restful_objects/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,10 @@ def to_operation_dict( # pylint: disable=too-many-branches
if self.permissions_required is not None:
# Check that all the names are known to the system.
for perm in self.permissions_required.iter_perms():
if perm not in permission_registry:
if isinstance(perm, permissions.OkayToIgnorePerm):
continue

if perm.name not in permission_registry:
# NOTE:
# See rest_api.py. dynamic_permission() have to be loaded before request
# for this to work reliably.
Expand Down Expand Up @@ -1596,16 +1599,23 @@ def _permission_descriptions(
def _count_perms(_perms):
return len([p for p in _perms if not isinstance(p, permissions.Undocumented)])

def _add_desc(permission: permissions.BasePerm, indent: int, desc_list: list[str]) -> None:
def _add_desc( # pylint: disable=too-many-branches
permission: permissions.BasePerm, indent: int, desc_list: list[str]
) -> None:
if isinstance(permission, permissions.Undocumented):
# Don't render
return

# We indent by two spaces, as is required by markdown.
prefix = " " * indent
if isinstance(permission, permissions.Perm):
if isinstance(permission, (permissions.Perm, permissions.OkayToIgnorePerm)):
perm_name = permission.name
desc = description_map.get(perm_name) or permission_registry[perm_name].description
try:
desc = description_map.get(perm_name) or permission_registry[perm_name].description
except KeyError:
if isinstance(permission, permissions.OkayToIgnorePerm):
return
raise
_description.append(f"{prefix} * `{perm_name}`: {desc}")
elif isinstance(permission, permissions.AllPerm):
# If AllOf only contains one permission, we don't need to show the AllOf
Expand Down
28 changes: 21 additions & 7 deletions cmk/gui/openapi/restful_objects/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ def has_permission(self, user: UserLike) -> bool:
raise NotImplementedError()

@abc.abstractmethod
def iter_perms(self) -> Iterable[str]:
def iter_perms(self) -> Iterable[Perm]:
raise NotImplementedError

def validate(self, permissions: Sequence[str]) -> bool:
"""Verify that a user with these permissions fulfills the requirements."""
return self.has_permission(FakeUser(permissions))

def __contains__(self, item):
return item in list(self.iter_perms())
return item in (p.name for p in self.iter_perms())


class Optional(BasePerm):
Expand All @@ -86,7 +86,7 @@ def has_permission(self, user: UserLike) -> bool:
It's okay if we don't have the permission, so we accept it all the time."""
return True

def iter_perms(self) -> Iterable[str]:
def iter_perms(self) -> Iterable[Perm]:
return self.perm.iter_perms()


Expand All @@ -103,7 +103,7 @@ def __init__(self, perms: list[BasePerm]) -> None:
def __repr__(self) -> str:
return f"{self.__class__.__name__}([{', '.join([repr(o) for o in self.perms])})"

def iter_perms(self) -> Iterable[str]:
def iter_perms(self) -> Iterable[Perm]:
return itertools.chain(*[perm.iter_perms() for perm in self.perms])


Expand All @@ -120,7 +120,7 @@ def has_permission(self, user: UserLike) -> bool:
"""
return False

def iter_perms(self) -> Iterable[str]:
def iter_perms(self) -> Iterable[Perm]:
return iter([])


Expand All @@ -139,8 +139,8 @@ def has_permission(self, user: UserLike) -> bool:
This method asks the user object if it has said permission."""
return user.has_permission(self.name)

def iter_perms(self) -> Iterable[str]:
return iter([self.name])
def iter_perms(self) -> Iterable[Perm]:
return iter([self])


class AllPerm(MultiPerm):
Expand Down Expand Up @@ -219,3 +219,17 @@ def has_permission(self, user: UserLike) -> bool:
Is verified if any one of the child permissions is verified."""
return any(perm.has_permission(user) for perm in self.perms)


class OkayToIgnorePerm(Perm):
"""A permission which does not raise an error if it is not present in Checkmk during built-time.
Introduced mainly since some components were removed in the CSE edition. Removing a
component also removes the associating permissions. Some general endpoints make use of
those permissions beyond its component specific endpoints and this would lead to an error
if the permission is not present. This permission will also not get rendered in the
documentation.
Consider this as a workaround since clear separation of edition specific permissions would
require a restructure of the entire endpoint specific permissions specification system.
"""

0 comments on commit 705cd53

Please sign in to comment.