Skip to content

Commit e80ddd4

Browse files
feat(rbac): disable repo to role sync (#655)
## πŸ“ Description https://github.com/renderedtext/tasks/issues/8769 ## βœ… Checklist - [x] I have tested this change - [ ] This change requires documentation update
1 parent 0cc176d commit e80ddd4

File tree

7 files changed

+207
-17
lines changed

7 files changed

+207
-17
lines changed

β€Žee/rbac/lib/rbac/collaborators_refresher.exβ€Ž

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,16 @@ defmodule Rbac.CollaboratorsRefresher do
110110
collaborator["permissions"]["pull"]
111111
)
112112

113-
Rbac.Repo.RbacRefreshProjectAccessRequest.add_request(
114-
project.org_id,
115-
user_id,
116-
project_id,
117-
:add,
118-
source,
119-
role_to_be_assigned
120-
)
113+
if role_to_be_assigned do
114+
Rbac.Repo.RbacRefreshProjectAccessRequest.add_request(
115+
project.org_id,
116+
user_id,
117+
project_id,
118+
:add,
119+
source,
120+
role_to_be_assigned
121+
)
122+
end
121123
end
122124
end)
123125
end

β€Žee/rbac/lib/rbac/okta/scim/api.exβ€Ž

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,9 @@ defmodule Rbac.Okta.Scim.Api do
258258
end
259259

260260
defp json(conn, status, payload) do
261-
send_resp(conn, status, Jason.encode!(payload))
261+
conn
262+
|> put_resp_content_type("application/json")
263+
|> send_resp(status, Jason.encode!(payload))
262264
end
263265

264266
defp serialize_user(okta_user) do

β€Žee/rbac/lib/rbac/repo/repo_to_role_mapping.exβ€Ž

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@ defmodule Rbac.Repo.RepoToRoleMapping do
2323
- pull_acess (boolean) Whehter you have pull access on specific repo
2424
"""
2525
@spec get_project_role_from_repo_access_rights(String.t(), boolean(), boolean(), boolean()) ::
26-
String.t()
26+
String.t() | nil
2727
def get_project_role_from_repo_access_rights(org_id, admin_access, push_access, pull_access) do
28-
repo_to_role_mapping = get_repo_to_role_mapping(org_id)
28+
case get_repo_to_role_mapping(org_id) do
29+
nil ->
30+
nil
2931

30-
case {admin_access, push_access, pull_access} do
31-
{true, _, _} -> Map.get(repo_to_role_mapping, :admin_access_role_id)
32-
{false, true, _} -> Map.get(repo_to_role_mapping, :push_access_role_id)
33-
{false, false, true} -> Map.get(repo_to_role_mapping, :pull_access_role_id)
32+
mapping ->
33+
case {admin_access, push_access, pull_access} do
34+
{true, _, _} -> mapping.admin_access_role_id
35+
{false, true, _} -> mapping.push_access_role_id
36+
{false, false, true} -> mapping.pull_access_role_id
37+
end
3438
end
3539
end
3640

β€Žee/rbac/lib/rbac/role_management.exβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,12 +315,12 @@ defmodule Rbac.RoleManagement do
315315
"[Role Management] Assigning roles based of collaborators list for RBI: #{inspect(rbi)}"
316316
)
317317

318-
roles_to_be_assign =
318+
roles_to_be_assigned =
319319
gen_query_to_assign_roles_to_collaborators(rbi)
320320
|> Rbac.Repo.all()
321321

322322
list_of_subject_role_bindings =
323-
Enum.map(roles_to_be_assign, fn binding ->
323+
Enum.map(roles_to_be_assigned, fn binding ->
324324
%{
325325
role_id:
326326
Rbac.Repo.RepoToRoleMapping.get_project_role_from_repo_access_rights(
@@ -335,6 +335,7 @@ defmodule Rbac.RoleManagement do
335335
binding_source: String.to_atom(binding[:provider])
336336
}
337337
end)
338+
|> Enum.filter(fn binding -> binding.role_id != nil end)
338339

339340
assign_roles(list_of_subject_role_bindings, rbi)
340341
end

β€Žee/rbac/test/rbac/collaborators_refresher_test.exsβ€Ž

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,5 +227,93 @@ defmodule Rbac.CollaboratorsRefresher.Test do
227227
|> Rbac.Repo.one() == nil
228228
end
229229
end
230+
231+
test "does not create refresh requests when org has no RepoToRoleMapping" do
232+
alias InternalApi.Repository.Collaborator
233+
234+
list_collaborators = %InternalApi.Repository.ListCollaboratorsResponse{
235+
next_page_token: "",
236+
collaborators: [
237+
%Collaborator{id: "3", login: "baz", permission: :WRITE},
238+
%Collaborator{id: "4", login: "bam", permission: :READ}
239+
]
240+
}
241+
242+
GrpcMock.stub(RepositoryMock, :list_collaborators, fn _, _ ->
243+
list_collaborators
244+
end)
245+
246+
project = Support.Factories.project()
247+
248+
response = %InternalApi.Projecthub.DescribeResponse{
249+
metadata: Support.Factories.response_meta(),
250+
project: project
251+
}
252+
253+
GrpcMock.stub(ProjecthubMock, :describe, fn _, _ -> response end)
254+
255+
{:ok, project} =
256+
Rbac.Store.Project.update(
257+
project.metadata.id,
258+
"renderedtext/semaphore2",
259+
"15324ba0-1b20-49d0-8ff9-a2d91fa451e0",
260+
"github",
261+
"private"
262+
)
263+
264+
[user1, user2, user3, user4] =
265+
rbac_users =
266+
1..4
267+
|> Enum.map(fn _ ->
268+
{:ok, user} = Support.Factories.RbacUser.insert()
269+
user
270+
end)
271+
272+
Enum.each(rbac_users, fn user ->
273+
Support.Members.insert_user(
274+
id: user.id,
275+
email: user.email,
276+
name: user.name
277+
)
278+
end)
279+
280+
{:ok, _org_scope} = Support.Factories.Scope.insert("org_scope")
281+
282+
Support.Factories.SubjectRoleBinding.insert(
283+
subject_id: user3.id,
284+
org_id: project.org_id,
285+
binding_source: :manually_assigned
286+
)
287+
288+
Support.Factories.SubjectRoleBinding.insert(
289+
subject_id: user4.id,
290+
org_id: project.org_id,
291+
binding_source: :manually_assigned
292+
)
293+
294+
with_mocks [
295+
{Rbac.Store.User, [],
296+
[
297+
find_id_by_provider_uid: fn github_uid, _ ->
298+
case github_uid do
299+
"1" -> user1.id
300+
"2" -> user2.id
301+
"3" -> user3.id
302+
"4" -> user4.id
303+
end
304+
end
305+
]}
306+
] do
307+
assert :ok = Rbac.CollaboratorsRefresher.refresh(project)
308+
309+
# Giving time for message broker to process
310+
:timer.sleep(500)
311+
Rbac.Workers.RefreshProjectAccess.perform_now()
312+
:timer.sleep(1000)
313+
314+
refresh_requests = Rbac.Repo.RbacRefreshProjectAccessRequest |> Rbac.Repo.all()
315+
assert refresh_requests == []
316+
end
317+
end
230318
end
231319
end

β€Žee/rbac/test/rbac/repo/repo_to_role_mapping_test.exsβ€Ž

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,78 @@ defmodule Rbac.Repo.RepoToRoleMapping.Test do
2727
assert state[:mapping_for_specific_org] === mapper
2828
end
2929
end
30+
31+
describe "get_project_role_from_repo_access_rights/4" do
32+
test "returns nil when org has no RepoToRoleMapping for admin access" do
33+
role_id =
34+
RepoToRoleMapping.get_project_role_from_repo_access_rights(
35+
@non_existant_org_id,
36+
true,
37+
false,
38+
false
39+
)
40+
41+
assert role_id === nil
42+
end
43+
44+
test "returns admin role when user has admin access", state do
45+
role_id =
46+
RepoToRoleMapping.get_project_role_from_repo_access_rights(
47+
@org_id,
48+
true,
49+
false,
50+
false
51+
)
52+
53+
assert role_id === state[:mapping_for_specific_org].admin_access_role_id
54+
end
55+
56+
test "returns admin role when user has admin, push, and pull access", state do
57+
role_id =
58+
RepoToRoleMapping.get_project_role_from_repo_access_rights(
59+
@org_id,
60+
true,
61+
true,
62+
true
63+
)
64+
65+
assert role_id === state[:mapping_for_specific_org].admin_access_role_id
66+
end
67+
68+
test "returns push role when user has push access only", state do
69+
role_id =
70+
RepoToRoleMapping.get_project_role_from_repo_access_rights(
71+
@org_id,
72+
false,
73+
true,
74+
false
75+
)
76+
77+
assert role_id === state[:mapping_for_specific_org].push_access_role_id
78+
end
79+
80+
test "returns push role when user has push and pull access", state do
81+
role_id =
82+
RepoToRoleMapping.get_project_role_from_repo_access_rights(
83+
@org_id,
84+
false,
85+
true,
86+
true
87+
)
88+
89+
assert role_id === state[:mapping_for_specific_org].push_access_role_id
90+
end
91+
92+
test "returns pull role when user has pull access only", state do
93+
role_id =
94+
RepoToRoleMapping.get_project_role_from_repo_access_rights(
95+
@org_id,
96+
false,
97+
false,
98+
true
99+
)
100+
101+
assert role_id === state[:mapping_for_specific_org].pull_access_role_id
102+
end
103+
end
30104
end

β€Žee/rbac/test/rbac/role_management_test.exsβ€Ž

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,25 @@ defmodule Rbac.RoleManagement.Test do
298298

299299
assert user_has_access_to_projects?(@user_id, @org_id, [@project_id])
300300
end
301+
302+
test "Organization does not have RepoToRoleMapping" do
303+
Support.Rbac.assign_org_role_by_name(@org_id, @user_id, "Member")
304+
Collaborators.insert_user(user_id: @user_id, github_uid: "1")
305+
Collaborators.insert(github_uid: "1", project_id: @project_id)
306+
Support.Projects.insert(project_id: @project_id, org_id: @org_id)
307+
308+
# Note: We deliberately do NOT create a RepoToRoleMapping for this org
309+
310+
{:ok, project_rbi} = RBI.new(org_id: @org_id, project_id: @project_id)
311+
312+
# Should succeed but skip role assignment due to missing RepoToRoleMapping
313+
{:ok, _} = RoleManagement.assign_project_roles_to_repo_collaborators(project_rbi)
314+
315+
# Verify no project role was assigned to the collaborator
316+
{:ok, admin} = Rbac.Repo.RbacRole.get_role_by_name("Admin", "project_scope", @org_id)
317+
refute has_role_binding?(@user_id, @org_id, @project_id, admin.id, :github)
318+
refute user_has_access_to_projects?(@user_id, @org_id, [@project_id])
319+
end
301320
end
302321

303322
describe "retract_role/2" do

0 commit comments

Comments
Β (0)