View Source Runbox.Scenario.UserAction (runbox v22.0.0)
Toolbox for working with scenario user actions.
User action is action created by scenario and fired by user (usually from UI). Scenario is usually also a receiver of fired action. Assumed workflow is following:
Scenario creates actions to be fired in the future and Altworx stores them.
UI displays available actions.
User fires selected action from UI.
UI pushes the action to raw Kafka topic (defined in action) with extra data attached (usually empty).
Normalizer pipeline receives the action and sends it to target scenario via a runtime topic.
Currently, user actions can be attached only to incidents. This can be done either
via the user_actions field of Runbox.Scenario.OutputAction.V2.Incident and
Runbox.Scenario.OutputAction.V2.IncidentPatch or using Toolbox.Workflow.
Normalized user actions
Fired output actions are normalized into a %Runbox.Message{} with
%Runbox.Scenario.UserAction{} in its body. For example:
%Runbox.Message{
from: "N6_rt_camera_user_actions",
type: "close_incident",
timestamp: 1750857766412,
body: %Runbox.Scenario.UserAction{
type: "close_incident",
details: %{
"submit_text" => "Close the incident",
"type" => "button"
"incident_id" => "6157565f-8c9e-3e66-a5f6-2c4d6211a9c1",
},
user: "joe",
data: %{}
},
origin: %{offset: 2, partition: 0, topic: "camera_user_actions"}
}
Summary
Functions
Helper for UserAction forwarding to be used in normalizer.
Packs user action to JWT to be used (fired) later (from UI for example).
Parses string containing JSON to Runbox.Scenario.UserAction.
Types
@type t() :: %Runbox.Scenario.UserAction{ data: any(), details: map(), type: String.t(), user: String.t() }
Fired user action.
When action is fired by the user, it should be pushed to raw topic with current
timestamp to be correctly reordered by Normalizer. Properties type and details
should contain enough information for routing action to the target scenario. Property
user is ID of user who fired the action, data contains extra information attached
by environment where user fired the action (for example comment filled by the user on UI).
Functions
@spec normalizer_pipeline_step(Runbox.Message.t()) :: Runbox.Message.t()
Helper for UserAction forwarding to be used in normalizer.
If helper is used in normalizer pipeline configuration in config.ini like
[pipelines.some_pipeline]
definition = Runbox.Scenario.UserAction.normalizer_pipeline_stepthen Runbox.Message body will contain fired Runbox.Scenario.UserAction.
@spec pack(String.t(), String.t(), map(), [{:access_tags, [String.t()]}]) :: {:ok, Joken.bearer_token()} | {:error, Joken.error_reason()}
Packs user action to JWT to be used (fired) later (from UI for example).
Parameter details must be a map encodable to JSON. Because details can be (and it is!)
encoded/decoded to/from JSON during its life-cycle, atom keys in details are always converted
to string keys in fired action's details.
details must contain "type" which is currently always "button" and submit_text
which will be used as the user-facing label for the button. Other fields are up to you.
Optionally, access_tags can be given inside opts to control access to the action.
A user must have all of the specified access tags to be able to fire the action.
If access tags are not given, the default [] is used, which means that anyone can
fire the action.
Note this function depends on a signer, that must be defined in an application environment. Signer holds the secret keys and performs the signing process. A scenario can be executed or evaluated in various environments and the signers also differ between these envs.
- Altworx
- when you run a scenario in a full Altworx instance
- this uses Altworx master node as a signer
- keys are secret, usually a part of the deployment configuration
- Sandbox
- when you run the scenario in a Sandbox, e.g. in tests or in Livebook.
- Sandbox automatically set's up a testing signer -
Runbox.Runtime.Sandbox.UserActionSigner. - The signer uses a fixed key good enough for testing purposes.
- The module also offers a function to validate and unpack the tokens, so you can assert them in tests.
- No environment
- When you execute the code yourself directly, e.g. in a unit tests or in iex.
- You need to define a signer yourself. The simplest and preferred way is to use the Sandbox
signer. You can do so by adjusting the application env.
# config.exs config :runbox, :user_action_signer, {Node.self(), Runbox.Runtime.Sandbox.UserActionSigner, :sign}
Example
UserAction.pack("camera_user_actions", "close_incident", %{
"type" => "button",
"submit_text" => "Close the incident",
"incident_id" => "6157565f-8c9e-3e66-a5f6-2c4d6211a9c1"
}, access_tags: ["camera", "privileged"])
Parses string containing JSON to Runbox.Scenario.UserAction.