jcloude/press/guards/team_guard.py
2025-12-23 22:53:43 +08:00

98 lines
2.9 KiB
Python

import functools
import inspect
from collections import OrderedDict
from collections.abc import Callable
import jingrow
from jingrow import TYPE_CHECKING, _
from jingrow.model.document import Page
from jcloude.utils import user as utils_user
if TYPE_CHECKING:
from jcloude.jcloude.pagetype.team.team import Team
def only_owner(team: Callable[[Page, OrderedDict], str] = lambda document, _: str(document.team)):
"""
This guard can only be used for a class method. No other options are
supported.
"""
def wrapper(fn):
@functools.wraps(fn)
def inner(self, *args, **kwargs):
if utils_user.is_system_manager():
return fn(self, *args, **kwargs)
bound_args = inspect.signature(fn).bind(self, *args, **kwargs)
bound_args.apply_defaults()
t = team(self, bound_args.arguments)
d: Team = jingrow.get_cached_pg("Team", t)
if not d.is_team_owner():
message = _("Only team owner can perform this action.")
jingrow.throw(message, jingrow.PermissionError)
return fn(self, *args, **kwargs)
return inner
return wrapper
def only_admin(
team: Callable[[Page, OrderedDict], str] = lambda document, _: str(document.team),
skip: Callable[[Page, OrderedDict], bool] = lambda _, __: False,
):
"""
This guard can only be used for a class method. No other options are
supported. Team owner is considered as admin.
"""
def wrapper(fn):
@functools.wraps(fn)
def inner(self, *args, **kwargs):
if utils_user.is_system_manager():
return fn(self, *args, **kwargs)
bound_args = inspect.signature(fn).bind(self, *args, **kwargs)
bound_args.apply_defaults()
if skip(self, bound_args.arguments):
return fn(self, *args, **kwargs)
t = team(self, bound_args.arguments)
d: Team = jingrow.get_cached_pg("Team", t)
if not (d.is_team_owner() or d.is_admin_user()):
message = _("Only team admin can perform this action.")
jingrow.throw(message, jingrow.PermissionError)
return fn(self, *args, **kwargs)
return inner
return wrapper
def only_member(
team: Callable[[Page, OrderedDict], str] = lambda document, _: str(document.team),
user: Callable[[Page, OrderedDict], str] = lambda _, __: str(jingrow.session.user),
error_message: str | None = None,
):
"""
This guard can only be used for a class method. No other options are
supported.
"""
def wrapper(fn):
@functools.wraps(fn)
def inner(self, *args, **kwargs):
if utils_user.is_system_manager():
return fn(self, *args, **kwargs)
bound_args = inspect.signature(fn).bind(self, *args, **kwargs)
bound_args.apply_defaults()
t = team(self, bound_args.arguments)
u = user(self, bound_args.arguments)
if not bool(jingrow.db.exists({"pagetype": "Team Member", "parent": t, "user": u})):
message = error_message or _("Only team member can perform this action.")
jingrow.throw(message, jingrow.PermissionError)
return fn(self, *args, **kwargs)
return inner
return wrapper