Skip to content
Merged
6 changes: 6 additions & 0 deletions framework/py/flwr/supercore/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ class InvitationStatus(str, Enum):
EXPIRED = "expired"


class ActionType(str, Enum):
"""Supported control action types."""

START_RUN = "start_run"


class RunType(str, Enum):
"""Supported run types."""

Expand Down
24 changes: 24 additions & 0 deletions framework/py/flwr/superlink/federation/federation_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from flwr.common.typing import Federation
from flwr.proto.federation_config_pb2 import SimulationConfig # pylint: disable=E0611
from flwr.proto.federation_pb2 import Invitation # pylint: disable=E0611
from flwr.supercore.constant import ActionType, RunType

if TYPE_CHECKING:
from flwr.server.superlink.linkstate.linkstate import LinkState
Expand Down Expand Up @@ -321,3 +322,26 @@ def revoke_invitation(
PermissionError
If the caller is not an owner of the federation.
"""

@abstractmethod
def can_execute(
self, flwr_aid: str, action: ActionType, federation: str, run_type: RunType
) -> bool:
"""Check if an account can execute an action under a given context.

Parameters
----------
flwr_aid : str
Flower account ID of the subject.
action : ActionType
The action to authorize.
federation : str
Target federation name.
run_type : RunType
The run type relevant to the action.

Returns
-------
bool
``True`` if the action is allowed, otherwise ``False``.
"""
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
DEFAULT_SIMULATION_CONFIG,
NOOP_FEDERATION,
NOOP_FEDERATION_DESCRIPTION,
ActionType,
RunType,
)
from flwr.supercore.error import ApiErrorCode, FlowerError

Expand Down Expand Up @@ -215,3 +217,10 @@ def revoke_invitation(
raise UnsupportedError(
"`revoke_invitation` is not supported by NoOpFederationManager."
)

def can_execute(
self, flwr_aid: str, action: ActionType, federation: str, run_type: RunType
) -> bool:
"""Allow all actions in no-op mode."""
_ = (flwr_aid, action, federation, run_type)
return True
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
DEFAULT_SIMULATION_CONFIG,
NOOP_FEDERATION,
NOOP_FEDERATION_DESCRIPTION,
ActionType,
RunType,
)
from flwr.supercore.error import ApiErrorCode, FlowerError

Expand Down Expand Up @@ -234,6 +236,20 @@ def test_has_node() -> None:
manager.has_node(999, "any_federation")


def test_can_execute() -> None:
"""Test can_execute method always returns True."""
manager = NoOpFederationManager()

allowed = manager.can_execute(
NOOP_FLWR_AID,
ActionType.START_RUN,
NOOP_FEDERATION,
RunType.SERVER_APP,
)

assert allowed is True


def test_get_federations() -> None:
"""Test get_federations method returns NOOP_FEDERATION."""
# Prepare
Expand Down
Loading