Skip to content

Commit 5748458

Browse files
committed
feat: add role_id to assign to the service account
1 parent d686586 commit 5748458

File tree

5 files changed

+90
-16
lines changed

5 files changed

+90
-16
lines changed

guard/lib/guard/service_account/actions.ex

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ defmodule Guard.ServiceAccount.Actions do
1616
org_id: String.t(),
1717
name: String.t(),
1818
description: String.t(),
19-
creator_id: String.t()
19+
creator_id: String.t(),
20+
role_id: String.t()
2021
}
2122

2223
@doc """
@@ -28,15 +29,21 @@ defmodule Guard.ServiceAccount.Actions do
2829
3. Creates a service_account record
2930
4. Generates an API token
3031
5. Creates RBAC user record
31-
6. Publishes UserCreated event
32+
6. Assigns the specified role to the service account
33+
7. Publishes UserCreated event
3234
3335
Returns {:ok, %{service_account: service_account, api_token: api_token}} or {:error, reason}
3436
"""
3537
@spec create(service_account_params()) ::
3638
{:ok, %{service_account: map(), api_token: String.t()}} | {:error, atom() | list()}
3739
def create(
38-
%{org_id: _org_id, name: _name, description: _description, creator_id: _creator_id} =
39-
params
40+
%{
41+
org_id: _org_id,
42+
name: _name,
43+
description: _description,
44+
creator_id: _creator_id,
45+
role_id: _role_id
46+
} = params
4047
) do
4148
case _create(params) do
4249
{:ok, {service_account, api_token}} ->
@@ -124,7 +131,13 @@ defmodule Guard.ServiceAccount.Actions do
124131
defp _create(params) do
125132
FrontRepo.transaction(fn ->
126133
with {:ok, result} <- ServiceAccount.create(params),
127-
{:ok, _rbac_user} <- create_rbac_user(result.service_account) do
134+
{:ok, _rbac_user} <- create_rbac_user(result.service_account),
135+
:ok <-
136+
Guard.Api.Rbac.assign_role(
137+
result.service_account.org_id,
138+
result.service_account.id,
139+
params.role_id
140+
) do
128141
# Return the service account data and API token
129142
{result.service_account, result.api_token}
130143
else

guard/lib/guard/store/service_account.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,8 @@ defmodule Guard.Store.ServiceAccount do
384384
user_id: user.id,
385385
email: user.email,
386386
user: user,
387-
created_at: service_account.created_at,
388-
updated_at: service_account.updated_at
387+
created_at: user.created_at,
388+
updated_at: user.updated_at
389389
}
390390
end
391391
end

guard/lib/internal_api/service_account.pb.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ defmodule InternalApi.ServiceAccount.CreateRequest do
66
org_id: String.t(),
77
name: String.t(),
88
description: String.t(),
9-
creator_id: String.t()
9+
creator_id: String.t(),
10+
role_id: String.t()
1011
}
1112

12-
defstruct [:org_id, :name, :description, :creator_id]
13+
defstruct [:org_id, :name, :description, :creator_id, :role_id]
1314
field(:org_id, 1, type: :string)
1415
field(:name, 2, type: :string)
1516
field(:description, 3, type: :string)
1617
field(:creator_id, 4, type: :string)
18+
field(:role_id, 5, type: :string)
1719
end
1820

1921
defmodule InternalApi.ServiceAccount.CreateResponse do

guard/test/guard/service_account/actions_test.exs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ defmodule Guard.ServiceAccount.ActionsTest do
3434
create: fn _, _, _, _ -> :ok end,
3535
fetch: fn _ -> %{id: "rbac-user-id", user_id: "user-id"} end
3636
]},
37+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]},
3738
{Guard.Events.UserCreated, [:passthrough], [publish: fn _, _ -> :ok end]}
3839
]) do
3940
params = ServiceAccountFactory.build_params()
@@ -80,6 +81,7 @@ defmodule Guard.ServiceAccount.ActionsTest do
8081
end,
8182
fetch: fn _ -> %{id: "rbac-user-id", user_id: "user-id"} end
8283
]},
84+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]},
8385
{Guard.Events.UserCreated, [:passthrough], [publish: fn _, _ -> :ok end]}
8486
]) do
8587
params = ServiceAccountFactory.build_params()
@@ -95,11 +97,17 @@ defmodule Guard.ServiceAccount.ActionsTest do
9597
"Test SA"
9698
)
9799
)
100+
101+
# Verify role assignment was called
102+
assert_called(Guard.Api.Rbac.assign_role("org-id", "user-id", :_))
98103
end
99104
end
100105

101106
test "handles service account creation failure" do
102-
with_mock ServiceAccount, [:passthrough], create: fn _ -> {:error, :creation_failed} end do
107+
with_mocks([
108+
{ServiceAccount, [:passthrough], [create: fn _ -> {:error, :creation_failed} end]},
109+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]}
110+
]) do
103111
params = ServiceAccountFactory.build_params()
104112

105113
{:error, :creation_failed} = Actions.create(params)
@@ -131,6 +139,7 @@ defmodule Guard.ServiceAccount.ActionsTest do
131139
[
132140
create: fn _, _, _, _ -> :error end
133141
]},
142+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]},
134143
{Guard.Events.UserCreated, [:passthrough], [publish: fn _, _ -> :ok end]}
135144
]) do
136145
params = ServiceAccountFactory.build_params()
@@ -167,16 +176,59 @@ defmodule Guard.ServiceAccount.ActionsTest do
167176
[
168177
create: fn _, _, _, _ -> :ok end,
169178
fetch: fn _ -> nil end
170-
]}
179+
]},
180+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]}
171181
]) do
172182
params = ServiceAccountFactory.build_params()
173183

174184
{:error, :rbac_user_not_found} = Actions.create(params)
175185
end
176186
end
177187

188+
test "handles role assignment failure" do
189+
with_mocks([
190+
{ServiceAccount, [:passthrough],
191+
[
192+
create: fn _ ->
193+
{:ok,
194+
%{
195+
service_account: %{
196+
id: "user-id",
197+
user_id: "user-id",
198+
name: "Test SA",
199+
description: "Test Description",
200+
org_id: "org-id",
201+
creator_id: "creator-id",
202+
deactivated: false,
203+
204+
},
205+
api_token: "test-token"
206+
}}
207+
end
208+
]},
209+
{Guard.Store.RbacUser, [:passthrough],
210+
[
211+
create: fn _, _, _, _ -> :ok end,
212+
fetch: fn _ -> %{id: "rbac-user-id", user_id: "user-id"} end
213+
]},
214+
{Guard.Api.Rbac, [:passthrough],
215+
[assign_role: fn _, _, _ -> {:error, :assignment_failed} end]},
216+
{Guard.Events.UserCreated, [:passthrough], [publish: fn _, _ -> :ok end]}
217+
]) do
218+
params = ServiceAccountFactory.build_params()
219+
220+
{:error, :assignment_failed} = Actions.create(params)
221+
222+
# Verify event was NOT published on failure
223+
refute called(Guard.Events.UserCreated.publish(:_, :_))
224+
end
225+
end
226+
178227
test "handles service account store creation failure" do
179-
with_mock ServiceAccount, [:passthrough], create: fn _ -> {:error, :creation_failed} end do
228+
with_mocks([
229+
{ServiceAccount, [:passthrough], [create: fn _ -> {:error, :creation_failed} end]},
230+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]}
231+
]) do
180232
params = ServiceAccountFactory.build_params()
181233

182234
{:error, :creation_failed} = Actions.create(params)
@@ -335,9 +387,10 @@ defmodule Guard.ServiceAccount.ActionsTest do
335387
[reset_auth_token: fn _ -> {:ok, "test-token"} end]},
336388
{Guard.Store.RbacUser, [:passthrough],
337389
[
338-
create: fn _, _, _ -> :ok end,
390+
create: fn _, _, _, _ -> :ok end,
339391
fetch: fn _ -> %{id: "rbac-user-id"} end
340392
]},
393+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]},
341394
{Guard.Events.UserCreated, [:passthrough], [publish: fn _, _ -> :ok end]}
342395
]) do
343396
params =
@@ -372,9 +425,10 @@ defmodule Guard.ServiceAccount.ActionsTest do
372425
[reset_auth_token: fn _ -> {:ok, "test-token"} end]},
373426
{Guard.Store.RbacUser, [:passthrough],
374427
[
375-
create: fn _, _, _ -> :ok end,
428+
create: fn _, _, _, _ -> :ok end,
376429
fetch: fn _ -> %{id: "rbac-user-id"} end
377430
]},
431+
{Guard.Api.Rbac, [:passthrough], [assign_role: fn _, _, _ -> :ok end]},
378432
{Guard.Events.UserCreated, [:passthrough], [publish: fn _, _ -> :ok end]}
379433
]) do
380434
# Create service account first

guard/test/support/factories/service_account_factory.ex

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ defmodule Support.Factories.ServiceAccountFactory do
6060
org_id: get_org_id(options[:org_id]),
6161
name: get_name(options[:name]),
6262
description: get_description(options[:description]),
63-
creator_id: get_creator_id(options[:creator_id])
63+
creator_id: get_creator_id(options[:creator_id]),
64+
role_id: get_role_id(options[:role_id])
6465
}
6566
end
6667

@@ -75,7 +76,8 @@ defmodule Support.Factories.ServiceAccountFactory do
7576
org_id: get_org_id(options[:org_id]),
7677
name: get_name(options[:name]),
7778
description: get_description(options[:description]),
78-
creator_id: creator_user.id
79+
creator_id: creator_user.id,
80+
role_id: get_role_id(options[:role_id])
7981
}
8082
end
8183

@@ -110,6 +112,9 @@ defmodule Support.Factories.ServiceAccountFactory do
110112
"#{sanitized_name}@sa.test-org.#{Application.fetch_env!(:guard, :base_domain)}"
111113
end
112114

115+
defp get_role_id(nil), do: UUID.generate()
116+
defp get_role_id(role_id), do: role_id
117+
113118
defp generate_token_hash do
114119
# Generate a simple hash for testing
115120
:crypto.hash(:sha256, UUID.generate()) |> Base.encode64()

0 commit comments

Comments
 (0)