From c5a36014458189e6331fd6e7bc1f33cda45a7328 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Tue, 23 Apr 2024 14:21:59 -0400 Subject: [PATCH] chore: add audit refactor: clean up state transition code --- lib/ash_state_machine.ex | 42 ++++++++++++++----------- lib/builtin_changes/transition_state.ex | 6 +--- mix.exs | 3 +- mix.lock | 3 ++ 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lib/ash_state_machine.ex b/lib/ash_state_machine.ex index 453eb74..e06325d 100644 --- a/lib/ash_state_machine.ex +++ b/lib/ash_state_machine.ex @@ -127,29 +127,11 @@ defmodule AshStateMachine do A utility to transition the state of a changeset, honoring the rules of the resource. """ def transition_state(%{action_type: :update} = changeset, target) do - transitions = - AshStateMachine.Info.state_machine_transitions(changeset.resource, changeset.action.name) - attribute = AshStateMachine.Info.state_machine_state_attribute!(changeset.resource) old_state = Map.get(changeset.data, attribute) if target in AshStateMachine.Info.state_machine_all_states(changeset.resource) do - case Enum.find(transitions, fn transition -> - old_state in List.wrap(transition.from) and target in List.wrap(transition.to) - end) do - nil -> - Ash.Changeset.add_error( - changeset, - AshStateMachine.Errors.NoMatchingTransition.exception( - old_state: old_state, - target: target, - action: changeset.action.name - ) - ) - - _transition -> - Ash.Changeset.force_change_attribute(changeset, attribute, target) - end + find_and_perform_transition(changeset, old_state, attribute, target) else no_such_state(changeset, target) end @@ -175,6 +157,28 @@ defmodule AshStateMachine do Ash.Changeset.add_error(other, "Can't transition states on destroy actions") end + defp find_and_perform_transition(changeset, old_state, attribute, target) do + changeset.resource + |> AshStateMachine.Info.state_machine_transitions(changeset.action.name) + |> Enum.find(fn transition -> + old_state in List.wrap(transition.from) and target in List.wrap(transition.to) + end) + |> case do + nil -> + Ash.Changeset.add_error( + changeset, + AshStateMachine.Errors.NoMatchingTransition.exception( + old_state: old_state, + target: target, + action: changeset.action.name + ) + ) + + _transition -> + Ash.Changeset.force_change_attribute(changeset, attribute, target) + end + end + @doc false def no_such_state(changeset, target, old_state \\ nil) do Logger.error(""" diff --git a/lib/builtin_changes/transition_state.ex b/lib/builtin_changes/transition_state.ex index d44d265..2cf84ad 100644 --- a/lib/builtin_changes/transition_state.ex +++ b/lib/builtin_changes/transition_state.ex @@ -25,11 +25,7 @@ defmodule AshStateMachine.BuiltinChanges.TransitionState do ^old_state in ^List.wrap(transition.from) and ^target in ^List.wrap(transition.to) ) - if is_nil(expr) do - state_expr - else - expr(state_expr or ^expr) - end + expr(^state_expr or ^expr) end) new_state_value = diff --git a/mix.exs b/mix.exs index 9884aaa..4fcecd8 100644 --- a/mix.exs +++ b/mix.exs @@ -124,7 +124,8 @@ defmodule AshStateMachine.MixProject do {:credo, ">= 0.0.0", only: [:dev, :test], runtime: false}, {:dialyxir, ">= 0.0.0", only: [:dev, :test], runtime: false}, {:sobelow, ">= 0.0.0", only: [:dev, :test], runtime: false}, - {:git_ops, "~> 2.5", only: [:dev, :test]} + {:git_ops, "~> 2.5", only: [:dev, :test]}, + {:mix_audit, ">= 0.0.0", only: [:dev, :test], runtime: false} ] end diff --git a/mix.lock b/mix.lock index f7dfe91..532f338 100644 --- a/mix.lock +++ b/mix.lock @@ -19,6 +19,7 @@ "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"}, + "mix_audit": {:hex, :mix_audit, "2.1.3", "c70983d5cab5dca923f9a6efe559abfb4ec3f8e87762f02bab00fa4106d17eda", [:make, :mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.9", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "8c3987100b23099aea2f2df0af4d296701efd031affb08d0746b2be9e35988ec"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, "reactor": {:hex, :reactor, "0.8.1", "1aec71d16083901277727c8162f6dd0f07e80f5ca98911b6ef4f2c95e6e62758", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ae3936d97a3e4a316744f70c77b85345b08b70da334024c26e6b5eb8ede1246b"}, "sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"}, @@ -28,4 +29,6 @@ "stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "typable": {:hex, :typable, "0.3.0", "0431e121d124cd26f312123e313d2689b9a5322b15add65d424c07779eaa3ca1", [:mix], [], "hexpm", "880a0797752da1a4c508ac48f94711e04c86156f498065a83d160eef945858f8"}, + "yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"}, + "yaml_elixir": {:hex, :yaml_elixir, "2.9.0", "9a256da867b37b8d2c1ffd5d9de373a4fda77a32a45b452f1708508ba7bbcb53", [:mix], [{:yamerl, "~> 0.10", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "0cb0e7d4c56f5e99a6253ed1a670ed0e39c13fc45a6da054033928607ac08dfc"}, }