diff --git a/.gitignore b/.gitignore index 8a8a91d..2a3c3b8 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ td_cache-*.tar .iex.exs .tool-versions +CLAUDE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index c79adc7..d87af8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [8.6.2] 2026-06-05 + +### Added + +- [TD-8083] Add processed_groups_details + ## [8.6.1] 2026-05-20 ### Fixed diff --git a/lib/td_cache/templates/field_formatter.ex b/lib/td_cache/templates/field_formatter.ex index d2a8b52..d34be57 100644 --- a/lib/td_cache/templates/field_formatter.ex +++ b/lib/td_cache/templates/field_formatter.ex @@ -83,7 +83,13 @@ defmodule TdCache.Templates.FieldFormatter do when not is_nil(role_name) do groups = Map.get(user_group_roles, role_name, []) names = Enum.map(groups, &group_name_or_alias/1) - values = Map.put(values, "processed_groups", names) + details = Enum.map(groups, &group_details/1) + + values = + values + |> Map.put("processed_groups", names) + |> Map.put("processed_groups_details", details) + Map.put(field, "values", values) end @@ -93,4 +99,15 @@ defmodule TdCache.Templates.FieldFormatter do do: name defp group_name_or_alias(%{alias: group_alias}), do: group_alias + + defp group_details(%{id: id, name: name, alias: group_alias}) do + %{ + "id" => id, + "name" => name, + "alias" => normalize_group_alias(group_alias) + } + end + + defp normalize_group_alias(group_alias) when group_alias in [nil, ""], do: nil + defp normalize_group_alias(group_alias), do: group_alias end diff --git a/lib/td_cache/user_cache.ex b/lib/td_cache/user_cache.ex index 9c24142..8f65890 100644 --- a/lib/td_cache/user_cache.ex +++ b/lib/td_cache/user_cache.ex @@ -124,6 +124,10 @@ defmodule TdCache.UserCache do GenServer.call(__MODULE__, {:get_group_by_name, name}) end + def list_groups do + GenServer.call(__MODULE__, :list_groups) + end + def put(user) do GenServer.call(__MODULE__, {:put, user}) end @@ -210,6 +214,16 @@ defmodule TdCache.UserCache do {:reply, {:ok, group}, state} end + def handle_call(:list_groups, _from, state) do + groups = + case Redix.command(["SMEMBERS", Keys.group_ids()]) do + {:ok, ids} -> ids |> Enum.map(&read_group/1) |> Enum.reject(&is_nil/1) + _ -> [] + end + + {:reply, {:ok, groups}, state} + end + def handle_call({:put, user}, _from, state) do reply = put_user(user) {:reply, reply, state} diff --git a/mix.exs b/mix.exs index e8f0e76..070cc06 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule TdCache.MixProject do def project do [ app: :td_cache, - version: "8.6.1", + version: "8.6.2", elixir: "~> 1.18", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, diff --git a/test/td_cache/templates/field_formatter_test.exs b/test/td_cache/templates/field_formatter_test.exs index 19670fd..681ae25 100644 --- a/test/td_cache/templates/field_formatter_test.exs +++ b/test/td_cache/templates/field_formatter_test.exs @@ -47,5 +47,53 @@ defmodule TdCache.Templates.FieldFormatterTest do assert FieldFormatter.format(field, ctx) == field end + + test "format/2 applies user group metadata with group details" do + field = %{"name" => "foo", "type" => "user_group", "values" => %{"role_groups" => "owner"}} + + groups = [ + %{id: 1, name: "group_1", alias: "Group 1"}, + %{id: 2, name: "group_2", alias: nil} + ] + + user_group_roles = %{"owner" => groups} + ctx = %{user_group_roles: user_group_roles} + + expected = %{ + "name" => "foo", + "type" => "user_group", + "values" => %{ + "role_groups" => "owner", + "processed_groups" => ["Group 1", "group_2"], + "processed_groups_details" => [ + %{"id" => 1, "name" => "group_1", "alias" => "Group 1"}, + %{"id" => 2, "name" => "group_2", "alias" => nil} + ] + } + } + + assert FieldFormatter.format(field, ctx) == expected + end + + test "format/2 normalizes empty group alias to nil in processed_groups_details" do + field = %{"name" => "foo", "type" => "user_group", "values" => %{"role_groups" => "owner"}} + groups = [%{id: 1, name: "group_1", alias: ""}] + user_group_roles = %{"owner" => groups} + ctx = %{user_group_roles: user_group_roles} + + expected = %{ + "name" => "foo", + "type" => "user_group", + "values" => %{ + "role_groups" => "owner", + "processed_groups" => ["group_1"], + "processed_groups_details" => [ + %{"id" => 1, "name" => "group_1", "alias" => nil} + ] + } + } + + assert FieldFormatter.format(field, ctx) == expected + end end end diff --git a/test/td_cache/templates/preprocessor_test.exs b/test/td_cache/templates/preprocessor_test.exs index af21ee2..46d7659 100644 --- a/test/td_cache/templates/preprocessor_test.exs +++ b/test/td_cache/templates/preprocessor_test.exs @@ -52,7 +52,7 @@ defmodule TdCache.Templates.PreprocessorTest do test "preprocess_template/2 enriches user_group role fields" do %{id: domain_id} = CacheHelpers.insert_domain() %{id: user_id, full_name: full_name} = CacheHelpers.insert_user() - %{id: group_id, alias: group_alias} = CacheHelpers.insert_group() + %{id: group_id, alias: group_alias, name: group_name} = CacheHelpers.insert_group() AclCache.set_acl_roles("domain", domain_id, [@role_name]) AclCache.set_acl_group_roles("domain", domain_id, [@role_name]) @@ -83,7 +83,14 @@ defmodule TdCache.Templates.PreprocessorTest do "values" => %{ "role_groups" => @role_name, "processed_users" => [full_name], - "processed_groups" => [group_alias] + "processed_groups" => [group_alias], + "processed_groups_details" => [ + %{ + "id" => group_id, + "name" => group_name, + "alias" => group_alias + } + ] } } @@ -131,7 +138,7 @@ defmodule TdCache.Templates.PreprocessorTest do test "preprocess_template/2 process dynamic table type fields" do %{id: domain_id} = CacheHelpers.insert_domain() %{id: user_id, full_name: full_name} = CacheHelpers.insert_user() - %{id: group_id, alias: group_alias} = CacheHelpers.insert_group() + %{id: group_id, alias: group_alias, name: group_name} = CacheHelpers.insert_group() AclCache.set_acl_roles("domain", domain_id, [@role_name]) AclCache.set_acl_group_roles("domain", domain_id, [@role_name]) @@ -207,6 +214,13 @@ defmodule TdCache.Templates.PreprocessorTest do "type" => "user_group", "values" => %{ "processed_groups" => [group_alias], + "processed_groups_details" => [ + %{ + "id" => group_id, + "name" => group_name, + "alias" => group_alias + } + ], "processed_users" => [full_name], "role_groups" => "foo_role" } @@ -216,7 +230,7 @@ defmodule TdCache.Templates.PreprocessorTest do test "preprocess_template/2 enriches group role fields with groups only" do %{id: domain_id} = CacheHelpers.insert_domain() %{id: user_id} = CacheHelpers.insert_user() - %{id: group_id, alias: group_alias} = CacheHelpers.insert_group() + %{id: group_id, alias: group_alias, name: group_name} = CacheHelpers.insert_group() AclCache.set_acl_roles("domain", domain_id, [@role_name]) AclCache.set_acl_group_roles("domain", domain_id, [@role_name]) @@ -243,7 +257,14 @@ defmodule TdCache.Templates.PreprocessorTest do "type" => "group", "values" => %{ "role_groups" => @role_name, - "processed_groups" => [group_alias] + "processed_groups" => [group_alias], + "processed_groups_details" => [ + %{ + "id" => group_id, + "name" => group_name, + "alias" => group_alias + } + ] } } end diff --git a/test/td_cache/user_cache_test.exs b/test/td_cache/user_cache_test.exs index da07d13..189fbf7 100644 --- a/test/td_cache/user_cache_test.exs +++ b/test/td_cache/user_cache_test.exs @@ -290,14 +290,14 @@ defmodule TdCache.UserCacheTest do group = build(:group) put_user_group(group) {:ok, g} = UserCache.get_group(group.id) - assert g == Map.take(group, [:name, :alias, :id]) + assert g == expected_group_cache(group) end test "get_group_by_name returns a map with name and alias " do group = build(:group) put_user_group(group) {:ok, g} = UserCache.get_group_by_name(group.name) - assert g == Map.take(group, [:name, :alias, :id]) + assert g == expected_group_cache(group) end test "get_group_by_name returns a group by alias" do @@ -306,7 +306,7 @@ defmodule TdCache.UserCacheTest do {:ok, g} = UserCache.get_group_by_name(group.alias) - assert g == Map.take(group, [:name, :alias, :id]) + assert g == expected_group_cache(group) end test "get_group_by_name returns groups from a list of names" do @@ -318,8 +318,8 @@ defmodule TdCache.UserCacheTest do {:ok, groups} = UserCache.get_group_by_name([group1.name, group2.name]) assert groups == [ - Map.take(group1, [:name, :alias, :id]), - Map.take(group2, [:name, :alias, :id]) + expected_group_cache(group1), + expected_group_cache(group2) ] end @@ -338,8 +338,8 @@ defmodule TdCache.UserCacheTest do UserCache.get_group_by_name([group1.name, group2.name, user1.user_name, user2.user_name]) assert groups == [ - Map.take(group1, [:name, :alias, :id]), - Map.take(group2, [:name, :alias, :id]), + expected_group_cache(group1), + expected_group_cache(group2), nil, nil ] @@ -468,4 +468,8 @@ defmodule TdCache.UserCacheTest do on_exit(fn -> UserCache.delete_group(id) end) UserCache.put_group(group) end + + defp expected_group_cache(%{id: id, name: name, alias: group_alias}) do + %{id: id, name: name, alias: group_alias} + end end