diff --git a/lib/accounts/user.ex b/lib/accounts/user.ex index 2f35ce4..92b9ef2 100644 --- a/lib/accounts/user.ex +++ b/lib/accounts/user.ex @@ -271,15 +271,24 @@ defmodule Mv.Accounts.User do filter expr(oidc_id == get_path(^arg(:user_info), [:sub])) # Sync role from OIDC groups after sign-in (e.g. admin group → Admin role) - prepare Ash.Resource.Preparation.Builtins.after_action(fn query, records, _context -> + # get? true can return nil, a single %User{}, or a list; normalize to list for Enum.each + prepare Ash.Resource.Preparation.Builtins.after_action(fn query, result, _context -> user_info = Ash.Query.get_argument(query, :user_info) || %{} oauth_tokens = Ash.Query.get_argument(query, :oauth_tokens) || %{} - Enum.each(records, fn user -> + users = + case result do + nil -> [] + u when is_struct(u, User) -> [u] + list when is_list(list) -> list + _ -> [] + end + + Enum.each(users, fn user -> Mv.OidcRoleSync.apply_admin_role_from_user_info(user, user_info, oauth_tokens) end) - {:ok, records} + {:ok, result} end) end diff --git a/lib/mv/oidc_role_sync.ex b/lib/mv/oidc_role_sync.ex index 9073409..f268154 100644 --- a/lib/mv/oidc_role_sync.ex +++ b/lib/mv/oidc_role_sync.ex @@ -132,11 +132,17 @@ defmodule Mv.OidcRoleSync do end defp do_set_role(user, role) do - user - |> Ash.Changeset.for_update(:set_role_from_oidc_sync, %{role_id: role.id}) - |> Ash.Changeset.set_context(%{private: %{oidc_role_sync: true}}) - |> Ash.update!(domain: Mv.Accounts, context: %{private: %{oidc_role_sync: true}}) - - :ok + if user.role_id == role.id do + :ok + else + user + |> Ash.Changeset.for_update(:set_role_from_oidc_sync, %{role_id: role.id}) + |> Ash.Changeset.set_context(%{private: %{oidc_role_sync: true}}) + |> Ash.update(domain: Mv.Accounts, context: %{private: %{oidc_role_sync: true}}) + |> case do + {:ok, _} -> :ok + {:error, _} -> :ok + end + end end end