Skip to content

Commit e105231

Browse files
feat(api): remove user from org (#211)
## 📝 Description Http api for removing a user from the org (clevertap): renderedtext/tasks#7779 Changes made to RBAC are only here so that the endpoint for retracting roles would not crash if the user is already not part of the organization I made changes to the plumber Dockerfile, Makefile and test_helper in order to be able to run tests both locally (using make test.ex) and on CI ## ✅ Checklist - [x] I have tested this change - [x] This change requires documentation update (for now we will only have private docs for clevertap)
1 parent 5ed13e3 commit e105231

File tree

17 files changed

+506
-73
lines changed

17 files changed

+506
-73
lines changed

ee/rbac/lib/rbac/grpc_servers/rbac_server.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ defmodule Rbac.GrpcServers.RbacServer do
289289
is_owner? =
290290
Rbac.RoleManagement.fetch_subject_role_bindings(rbi)
291291
|> elem(0)
292-
|> List.first()
293-
|> Map.get(:role_bindings)
292+
|> List.first(%{})
293+
|> Map.get(:role_bindings, [])
294294
|> Enum.map(&Rbac.Repo.RbacRole.get_role_by_id(&1["role_id"]))
295295
|> Enum.any?(&(&1.name == "Owner"))
296296

public-api/v1alpha/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ RUN ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
2121
RUN mix local.hex --force && mix local.rebar --force
2222

2323
RUN mkdir api
24-
WORKDIR /app/api
24+
WORKDIR /app
2525

2626
# install mix dependencies
2727
COPY public-api/v1alpha/mix.exs public-api/v1alpha/mix.lock ./
@@ -86,7 +86,7 @@ RUN \
8686
USER "${USER}"
8787

8888
# copy release executables
89-
COPY --from=builder --chown="${USER}":"${USER}" /app/api/_build/"${MIX_ENV}"/rel/pipelines_api ./
89+
COPY --from=builder --chown="${USER}":"${USER}" /app/_build/"${MIX_ENV}"/rel/pipelines_api ./
9090

9191
ENTRYPOINT ["bin/pipelines_api"]
9292

public-api/v1alpha/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ export MIX_ENV?=dev
33
include ../../Makefile
44

55
DOCKER_BUILD_PATH=../..
6-
OUT_VOLUME=$(PWD)/out:/app/api/out
76
INTERNAL_API_BRANCH?=master
87
TMP_INTERNAL_REPO_DIR?=/tmp/internal_api
98
RELATIVE_INTERNAL_PB_OUTPUT_DIR=lib/internal_api
@@ -33,6 +32,7 @@ PROJECTHUB_API_GRPC_URL?=127.0.0.1:50052
3332
LOG_LEVEL?=debug
3433
API_VERSION?=v1alpha
3534
ON_PREM?="false"
35+
TMP_REPO_DIR ?= /tmp/internal_api
3636

3737
CONTAINER_ENV_VARS= \
3838
-e IN_DOCKER=$(IN_DOCKER) \
@@ -62,7 +62,7 @@ test.ex.setup: export MIX_ENV=test
6262
test.ex.setup:
6363
ifeq ($(CI),)
6464
# Localy we use database supplied by docker-compose
65-
docker compose $(DOCKER_COMPOSE_OPTS) run -e MIX_ENV=$(MIX_ENV) --build app mix do deps.get, test $(FILE)
65+
docker compose $(DOCKER_COMPOSE_OPTS) run -e MIX_ENV=$(MIX_ENV) --build app mix do deps.get
6666
else
6767
docker run --network host -v $(PWD)/out:/app/out $(CONTAINER_ENV_VARS) $(IMAGE):$(IMAGE_TAG) sh
6868
endif

public-api/v1alpha/lib/internal_api/rbac.pb.ex

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,30 @@ defmodule InternalApi.RBAC.ListMembersResponse.Member do
306306
field(:subject_role_bindings, 3, repeated: true, type: InternalApi.RBAC.SubjectRoleBinding)
307307
end
308308

309+
defmodule InternalApi.RBAC.CountMembersRequest do
310+
@moduledoc false
311+
use Protobuf, syntax: :proto3
312+
313+
@type t :: %__MODULE__{
314+
org_id: String.t()
315+
}
316+
defstruct [:org_id]
317+
318+
field(:org_id, 1, type: :string)
319+
end
320+
321+
defmodule InternalApi.RBAC.CountMembersResponse do
322+
@moduledoc false
323+
use Protobuf, syntax: :proto3
324+
325+
@type t :: %__MODULE__{
326+
members: integer
327+
}
328+
defstruct [:members]
329+
330+
field(:members, 1, type: :int32)
331+
end
332+
309333
defmodule InternalApi.RBAC.SubjectRoleBinding do
310334
@moduledoc false
311335
use Protobuf, syntax: :proto3
@@ -406,6 +430,25 @@ defmodule InternalApi.RBAC.Subject do
406430
field(:display_name, 3, type: :string)
407431
end
408432

433+
defmodule InternalApi.RBAC.RefreshCollaboratorsRequest do
434+
@moduledoc false
435+
use Protobuf, syntax: :proto3
436+
437+
@type t :: %__MODULE__{
438+
org_id: String.t()
439+
}
440+
defstruct [:org_id]
441+
442+
field(:org_id, 1, type: :string)
443+
end
444+
445+
defmodule InternalApi.RBAC.RefreshCollaboratorsResponse do
446+
@moduledoc false
447+
use Protobuf, syntax: :proto3
448+
449+
defstruct []
450+
end
451+
409452
defmodule InternalApi.RBAC.Role do
410453
@moduledoc false
411454
use Protobuf, syntax: :proto3
@@ -493,6 +536,7 @@ defmodule InternalApi.RBAC.RoleBindingSource do
493536
field(:ROLE_BINDING_SOURCE_GITLAB, 4)
494537
field(:ROLE_BINDING_SOURCE_SCIM, 5)
495538
field(:ROLE_BINDING_SOURCE_INHERITED_FROM_ORG_ROLE, 6)
539+
field(:ROLE_BINDING_SOURCE_SAML_JIT, 7)
496540
end
497541

498542
defmodule InternalApi.RBAC.RBAC.Service do
@@ -525,6 +569,7 @@ defmodule InternalApi.RBAC.RBAC.Service do
525569
rpc(:ModifyRole, InternalApi.RBAC.ModifyRoleRequest, InternalApi.RBAC.ModifyRoleResponse)
526570
rpc(:DestroyRole, InternalApi.RBAC.DestroyRoleRequest, InternalApi.RBAC.DestroyRoleResponse)
527571
rpc(:ListMembers, InternalApi.RBAC.ListMembersRequest, InternalApi.RBAC.ListMembersResponse)
572+
rpc(:CountMembers, InternalApi.RBAC.CountMembersRequest, InternalApi.RBAC.CountMembersResponse)
528573

529574
rpc(
530575
:ListAccessibleOrgs,
@@ -537,6 +582,12 @@ defmodule InternalApi.RBAC.RBAC.Service do
537582
InternalApi.RBAC.ListAccessibleProjectsRequest,
538583
InternalApi.RBAC.ListAccessibleProjectsResponse
539584
)
585+
586+
rpc(
587+
:RefreshCollaborators,
588+
InternalApi.RBAC.RefreshCollaboratorsRequest,
589+
InternalApi.RBAC.RefreshCollaboratorsResponse
590+
)
540591
end
541592

542593
defmodule InternalApi.RBAC.RBAC.Stub do

public-api/v1alpha/lib/internal_api/user.pb.ex

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ defmodule InternalApi.User.DescribeResponse do
101101
github_token: String.t(),
102102
github_scope: integer,
103103
github_uid: String.t(),
104-
api_token: String.t(),
105104
name: String.t(),
106105
github_login: String.t(),
107106
company: String.t(),
@@ -119,7 +118,6 @@ defmodule InternalApi.User.DescribeResponse do
119118
:github_token,
120119
:github_scope,
121120
:github_uid,
122-
:api_token,
123121
:name,
124122
:github_login,
125123
:company,
@@ -137,7 +135,6 @@ defmodule InternalApi.User.DescribeResponse do
137135
field(:github_token, 7, type: :string)
138136
field(:github_scope, 12, type: InternalApi.User.DescribeResponse.RepoScope, enum: true)
139137
field(:github_uid, 8, type: :string)
140-
field(:api_token, 9, type: :string)
141138
field(:name, 10, type: :string)
142139
field(:github_login, 11, type: :string)
143140
field(:company, 13, type: :string)
@@ -180,6 +177,7 @@ defmodule InternalApi.User.RepositoryProvider.Type do
180177

181178
field(:GITHUB, 0)
182179
field(:BITBUCKET, 1)
180+
field(:GITLAB, 2)
183181
end
184182

185183
defmodule InternalApi.User.RepositoryProvider.Scope do
@@ -314,40 +312,12 @@ defmodule InternalApi.User.RegenerateTokenResponse do
314312

315313
@type t :: %__MODULE__{
316314
status: Google.Rpc.Status.t(),
317-
user: InternalApi.User.User.t()
315+
api_token: String.t()
318316
}
319-
defstruct [:status, :user]
317+
defstruct [:status, :api_token]
320318

321319
field(:status, 1, type: Google.Rpc.Status)
322-
field(:user, 2, type: InternalApi.User.User)
323-
end
324-
325-
defmodule InternalApi.User.RefererRequest do
326-
@moduledoc false
327-
use Protobuf, syntax: :proto3
328-
329-
@type t :: %__MODULE__{
330-
user_id: String.t()
331-
}
332-
defstruct [:user_id]
333-
334-
field(:user_id, 1, type: :string)
335-
end
336-
337-
defmodule InternalApi.User.RefererResponse do
338-
@moduledoc false
339-
use Protobuf, syntax: :proto3
340-
341-
@type t :: %__MODULE__{
342-
user_id: String.t(),
343-
entry_url: String.t(),
344-
http_referer: String.t()
345-
}
346-
defstruct [:user_id, :entry_url, :http_referer]
347-
348-
field(:user_id, 1, type: :string)
349-
field(:entry_url, 2, type: :string)
350-
field(:http_referer, 3, type: :string)
320+
field(:api_token, 3, type: :string)
351321
end
352322

353323
defmodule InternalApi.User.CheckGithubTokenRequest do
@@ -442,6 +412,18 @@ defmodule InternalApi.User.DescribeByRepositoryProviderRequest do
442412
field(:provider, 1, type: InternalApi.User.RepositoryProvider)
443413
end
444414

415+
defmodule InternalApi.User.DescribeByEmailRequest do
416+
@moduledoc false
417+
use Protobuf, syntax: :proto3
418+
419+
@type t :: %__MODULE__{
420+
email: String.t()
421+
}
422+
defstruct [:email]
423+
424+
field(:email, 1, type: :string)
425+
end
426+
445427
defmodule InternalApi.User.RefreshRepositoryProviderRequest do
446428
@moduledoc false
447429
use Protobuf, syntax: :proto3
@@ -470,6 +452,26 @@ defmodule InternalApi.User.RefreshRepositoryProviderResponse do
470452
field(:repository_provider, 2, type: InternalApi.User.RepositoryProvider)
471453
end
472454

455+
defmodule InternalApi.User.CreateRequest do
456+
@moduledoc false
457+
use Protobuf, syntax: :proto3
458+
459+
@type t :: %__MODULE__{
460+
email: String.t(),
461+
name: String.t(),
462+
password: String.t(),
463+
repository_providers: [InternalApi.User.RepositoryProvider.t()],
464+
skip_password_change: boolean
465+
}
466+
defstruct [:email, :name, :password, :repository_providers, :skip_password_change]
467+
468+
field(:email, 1, type: :string)
469+
field(:name, 2, type: :string)
470+
field(:password, 3, type: :string)
471+
field(:repository_providers, 4, repeated: true, type: InternalApi.User.RepositoryProvider)
472+
field(:skip_password_change, 5, type: :bool)
473+
end
474+
473475
defmodule InternalApi.User.User do
474476
@moduledoc false
475477
use Protobuf, syntax: :proto3
@@ -479,7 +481,6 @@ defmodule InternalApi.User.User do
479481
avatar_url: String.t(),
480482
github_uid: String.t(),
481483
name: String.t(),
482-
api_token: String.t(),
483484
github_login: String.t(),
484485
company: String.t(),
485486
email: String.t(),
@@ -497,7 +498,6 @@ defmodule InternalApi.User.User do
497498
:avatar_url,
498499
:github_uid,
499500
:name,
500-
:api_token,
501501
:github_login,
502502
:company,
503503
:email,
@@ -515,7 +515,6 @@ defmodule InternalApi.User.User do
515515
field(:avatar_url, 3, type: :string)
516516
field(:github_uid, 4, type: :string)
517517
field(:name, 5, type: :string)
518-
field(:api_token, 6, type: :string)
519518
field(:github_login, 7, type: :string)
520519
field(:company, 8, type: :string)
521520
field(:email, 9, type: :string)
@@ -581,22 +580,6 @@ defmodule InternalApi.User.UserUpdated do
581580
field(:timestamp, 2, type: Google.Protobuf.Timestamp)
582581
end
583582

584-
defmodule InternalApi.User.UserRefererCreated do
585-
@moduledoc false
586-
use Protobuf, syntax: :proto3
587-
588-
@type t :: %__MODULE__{
589-
user_id: String.t(),
590-
entry_url: String.t(),
591-
http_referer: String.t()
592-
}
593-
defstruct [:user_id, :entry_url, :http_referer]
594-
595-
field(:user_id, 1, type: :string)
596-
field(:entry_url, 2, type: :string)
597-
field(:http_referer, 3, type: :string)
598-
end
599-
600583
defmodule InternalApi.User.UserJoinedOrganization do
601584
@moduledoc false
602585
use Protobuf, syntax: :proto3
@@ -731,6 +714,7 @@ defmodule InternalApi.User.UserService.Service do
731714
InternalApi.User.User
732715
)
733716

717+
rpc(:DescribeByEmail, InternalApi.User.DescribeByEmailRequest, InternalApi.User.User)
734718
rpc(:SearchUsers, InternalApi.User.SearchUsersRequest, InternalApi.User.SearchUsersResponse)
735719
rpc(:DescribeMany, InternalApi.User.DescribeManyRequest, InternalApi.User.DescribeManyResponse)
736720
rpc(:Update, InternalApi.User.UpdateRequest, InternalApi.User.UpdateResponse)
@@ -750,7 +734,6 @@ defmodule InternalApi.User.UserService.Service do
750734

751735
rpc(:CreateFavorite, InternalApi.User.Favorite, InternalApi.User.Favorite)
752736
rpc(:DeleteFavorite, InternalApi.User.Favorite, InternalApi.User.Favorite)
753-
rpc(:Referer, InternalApi.User.RefererRequest, InternalApi.User.RefererResponse)
754737

755738
rpc(
756739
:CheckGithubToken,
@@ -772,6 +755,8 @@ defmodule InternalApi.User.UserService.Service do
772755
InternalApi.User.RefreshRepositoryProviderRequest,
773756
InternalApi.User.RefreshRepositoryProviderResponse
774757
)
758+
759+
rpc(:Create, InternalApi.User.CreateRequest, InternalApi.User.User)
775760
end
776761

777762
defmodule InternalApi.User.UserService.Stub do

public-api/v1alpha/lib/pipelines_api/rbac_client.ex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,15 @@ defmodule PipelinesAPI.RBACClient do
3838
)
3939
end)
4040
end
41+
42+
def retract_role(params) do
43+
LogTee.debug(params, "RBACClient.retract_role")
44+
45+
Metrics.benchmark("PipelinesAPI.RBAC_client", ["retract_role"], fn ->
46+
params
47+
|> RequestFormatter.form_retract_role_request()
48+
|> GrpcClient.retract_role()
49+
|> ResponseFormatter.process_retract_role_response()
50+
end)
51+
end
4152
end

public-api/v1alpha/lib/pipelines_api/rbac_client/grpc_client.ex

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,33 @@ defmodule PipelinesAPI.RBACClient.GrpcClient do
114114
|> RBAC.Stub.list_roles(list_roles_request, opts())
115115
end)
116116
end
117+
118+
def retract_role({:ok, retract_role_request = %{role_assignment: _, requester_id: _}}) do
119+
LogTee.debug(retract_role_request, "RBACClient.GrpcClient.retract_role")
120+
121+
result =
122+
Wormhole.capture(__MODULE__, :retract_role_, [retract_role_request],
123+
stacktrace: true,
124+
skip_log: true,
125+
timeout_ms: @wormhole_timeout
126+
)
127+
128+
case result do
129+
{:ok, result} -> result
130+
{:error, reason} -> Log.internal_error(reason, "retract_role")
131+
end
132+
end
133+
134+
def retract_role({:ok, _}), do: ToTuple.user_error("invalid retract role request")
135+
136+
def retract_role(error), do: error
137+
138+
def retract_role_(retract_role_request) do
139+
{:ok, channel} = GRPC.Stub.connect(url())
140+
141+
Metrics.benchmark("PipelinesAPI.RBAC_client", ["retract_role_"], fn ->
142+
channel
143+
|> RBAC.Stub.retract_role(retract_role_request, opts())
144+
end)
145+
end
117146
end

0 commit comments

Comments
 (0)