Skip to content

Commit c3de5f8

Browse files
mustard-mhjeanp413
authored andcommitted
Update proto
1 parent e9cfedd commit c3de5f8

30 files changed

+2977
-770
lines changed

components/dashboard/src/admin/BlockedEmailDomains.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ import { ItemFieldContextMenu } from "../components/ItemsList";
1313
import Modal, { ModalBody, ModalFooter, ModalHeader } from "../components/Modal";
1414
import { CheckboxInputField } from "../components/forms/CheckboxInputField";
1515
import searchIcon from "../icons/search.svg";
16-
import { getGitpodService } from "../service/service";
1716
import { AdminPageHeader } from "./AdminPageHeader";
1817
import Pagination from "../Pagination/Pagination";
1918
import { Button } from "@podkit/buttons/Button";
19+
import { verificationClient } from "../service/public-api";
2020

2121
export function BlockedEmailDomains() {
2222
return (
@@ -27,7 +27,7 @@ export function BlockedEmailDomains() {
2727
}
2828

2929
function useBlockedEmailDomains() {
30-
return useQuery(["blockedEmailDomains"], () => getGitpodService().server.adminGetBlockedEmailDomains(), {
30+
return useQuery(["blockedEmailDomains"], () => verificationClient.listBlockedEmailDomains({}), {
3131
staleTime: 1000 * 60 * 5, // 5min
3232
});
3333
}
@@ -37,12 +37,15 @@ function useUpdateBlockedEmailDomainMutation() {
3737
const blockedEmailDomains = useBlockedEmailDomains();
3838
return useMutation(
3939
async (blockedDomain: EmailDomainFilterEntry) => {
40-
await getGitpodService().server.adminSaveBlockedEmailDomain(blockedDomain);
40+
await verificationClient.createBlockedEmailDomain({
41+
domain: blockedDomain.domain,
42+
negative: blockedDomain.negative,
43+
});
4144
},
4245
{
4346
onSuccess: (_, blockedDomain) => {
4447
const updated = [];
45-
for (const entry of blockedEmailDomains.data || []) {
48+
for (const entry of blockedEmailDomains.data?.blockedEmailDomains || []) {
4649
if (entry.domain !== blockedDomain.domain) {
4750
updated.push(entry);
4851
} else {
@@ -74,7 +77,7 @@ export function BlockedEmailDomainsList(props: Props) {
7477
if (!blockedEmailDomains.data) {
7578
return [];
7679
}
77-
return blockedEmailDomains.data.filter((entry) =>
80+
return blockedEmailDomains.data.blockedEmailDomains.filter((entry) =>
7881
entry.domain.toLowerCase().includes(searchTerm.toLowerCase()),
7982
);
8083
}, [blockedEmailDomains.data, searchTerm]);

components/dashboard/src/admin/BlockedRepositories.tsx

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44
* See License.AGPL.txt in the project root for license information.
55
*/
66

7-
import { AdminGetListResult } from "@gitpod/gitpod-protocol";
87
import { useCallback, useEffect, useRef, useState } from "react";
9-
import { getGitpodService } from "../service/service";
108
import { AdminPageHeader } from "./AdminPageHeader";
11-
import { BlockedRepository } from "@gitpod/gitpod-protocol/lib/blocked-repositories-protocol";
129
import ConfirmationModal from "../components/ConfirmationModal";
1310
import Modal, { ModalBody, ModalFooter, ModalHeader } from "../components/Modal";
1411
import { CheckboxInputField } from "../components/forms/CheckboxInputField";
@@ -18,6 +15,10 @@ import Alert from "../components/Alert";
1815
import { SpinnerLoader } from "../components/Loader";
1916
import searchIcon from "../icons/search.svg";
2017
import { Button } from "@podkit/buttons/Button";
18+
import { verificationClient } from "../service/public-api";
19+
import { Sort, SortOrder } from "@gitpod/public-api/lib/gitpod/v1/sorting_pb";
20+
import { BlockedRepository, ListBlockedRepositoriesResponse } from "@gitpod/public-api/lib/gitpod/v1/verification_pb";
21+
import { PartialMessage } from "@bufbuild/protobuf";
2122

2223
export function BlockedRepositories() {
2324
return (
@@ -27,20 +28,22 @@ export function BlockedRepositories() {
2728
);
2829
}
2930

30-
type NewBlockedRepository = Pick<BlockedRepository, "urlRegexp" | "blockUser">;
31-
type ExistingBlockedRepository = Pick<BlockedRepository, "id" | "urlRegexp" | "blockUser">;
31+
type NewBlockedRepository = Pick<PartialMessage<BlockedRepository>, "urlRegexp" | "blockUser">;
32+
type ExistingBlockedRepository = Pick<PartialMessage<BlockedRepository>, "id" | "urlRegexp" | "blockUser">;
3233

3334
interface Props {}
3435

3536
export function BlockedRepositoriesList(props: Props) {
36-
const [searchResult, setSearchResult] = useState<AdminGetListResult<BlockedRepository>>({ rows: [], total: 0 });
37+
const [searchResult, setSearchResult] = useState<PartialMessage<ListBlockedRepositoriesResponse>>({
38+
blockedRepositories: [],
39+
});
3740
const [queryTerm, setQueryTerm] = useState("");
3841
const [searching, setSearching] = useState(false);
3942

4043
const [isAddModalVisible, setAddModalVisible] = useState(false);
4144
const [isDeleteModalVisible, setDeleteModalVisible] = useState(false);
4245

43-
const [currentBlockedRepository, setCurrentBlockedRepository] = useState<ExistingBlockedRepository>({
46+
const [currentBlockedRepository, setCurrentBlockedRepository] = useState<PartialMessage<BlockedRepository>>({
4447
id: 0,
4548
urlRegexp: "",
4649
blockUser: false,
@@ -49,11 +52,18 @@ export function BlockedRepositoriesList(props: Props) {
4952
const search = async () => {
5053
setSearching(true);
5154
try {
52-
const result = await getGitpodService().server.adminGetBlockedRepositories({
53-
limit: 100,
54-
orderBy: "urlRegexp",
55-
offset: 0,
56-
orderDir: "asc",
55+
const result = await verificationClient.listBlockedRepositories({
56+
// Don't need, added it in json-rpc implement to make life easier.
57+
// pagination: new PaginationRequest({
58+
// token: Buffer.from(JSON.stringify({ offset: 0 })).toString("base64"),
59+
// pageSize: 100,
60+
// }),
61+
sort: [
62+
new Sort({
63+
field: "urlRegexp",
64+
order: SortOrder.ASC,
65+
}),
66+
],
5767
searchTerm: queryTerm,
5868
});
5969
setSearchResult(result);
@@ -76,10 +86,10 @@ export function BlockedRepositoriesList(props: Props) {
7686
};
7787

7888
const save = async (blockedRepository: NewBlockedRepository) => {
79-
await getGitpodService().server.adminCreateBlockedRepository(
80-
blockedRepository.urlRegexp,
81-
blockedRepository.blockUser,
82-
);
89+
await verificationClient.createBlockedRepository({
90+
urlRegexp: blockedRepository.urlRegexp ?? "",
91+
blockUser: blockedRepository.blockUser ?? false,
92+
});
8393
setAddModalVisible(false);
8494
search();
8595
};
@@ -91,11 +101,13 @@ export function BlockedRepositoriesList(props: Props) {
91101
};
92102

93103
const deleteBlockedRepository = async (blockedRepository: ExistingBlockedRepository) => {
94-
await getGitpodService().server.adminDeleteBlockedRepository(blockedRepository.id);
104+
await verificationClient.deleteBlockedRepository({
105+
blockedRepositoryId: blockedRepository.id,
106+
});
95107
search();
96108
};
97109

98-
const confirmDeleteBlockedRepository = (blockedRepository: ExistingBlockedRepository) => {
110+
const confirmDeleteBlockedRepository = (blockedRepository: PartialMessage<BlockedRepository>) => {
99111
setCurrentBlockedRepository(blockedRepository);
100112
setAddModalVisible(false);
101113
setDeleteModalVisible(true);
@@ -158,15 +170,18 @@ export function BlockedRepositoriesList(props: Props) {
158170
<div className="w-1/12">Block Users</div>
159171
<div className="w-1/12"></div>
160172
</div>
161-
{searchResult.rows.map((br) => (
173+
{searchResult.blockedRepositories!.map((br) => (
162174
<BlockedRepositoryEntry br={br} confirmedDelete={confirmDeleteBlockedRepository} />
163175
))}
164176
</div>
165177
</div>
166178
);
167179
}
168180

169-
function BlockedRepositoryEntry(props: { br: BlockedRepository; confirmedDelete: (br: BlockedRepository) => void }) {
181+
function BlockedRepositoryEntry(props: {
182+
br: PartialMessage<BlockedRepository>;
183+
confirmedDelete: (br: PartialMessage<BlockedRepository>) => void;
184+
}) {
170185
const menuEntries: ContextMenuEntry[] = [
171186
{
172187
title: "Delete",
@@ -295,7 +310,7 @@ function Details(props: {
295310
<CheckboxInputField
296311
label="Block Users"
297312
hint="Block any user that tries to open a workspace for a repository URL that matches this RegEx."
298-
checked={props.br.blockUser}
313+
checked={props.br.blockUser!}
299314
disabled={!props.update}
300315
onChange={(checked) => {
301316
if (!!props.update) {

components/dashboard/src/data/setup.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ import * as ConfigurationClasses from "@gitpod/public-api/lib/gitpod/v1/configur
2424
import * as AuthProviderClasses from "@gitpod/public-api/lib/gitpod/v1/authprovider_pb";
2525
import * as EnvVarClasses from "@gitpod/public-api/lib/gitpod/v1/envvar_pb";
2626
import * as PrebuildClasses from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";
27+
import * as VerificationClasses from "@gitpod/public-api/lib/gitpod/v1/verification_pb";
2728
import * as SCMClasses from "@gitpod/public-api/lib/gitpod/v1/scm_pb";
2829
import * as SSHClasses from "@gitpod/public-api/lib/gitpod/v1/ssh_pb";
2930

3031
// This is used to version the cache
3132
// If data we cache changes in a non-backwards compatible way, increment this version
3233
// That will bust any previous cache versions a client may have stored
33-
const CACHE_VERSION = "8";
34+
const CACHE_VERSION = "9";
3435

3536
export function noPersistence(queryKey: QueryKey): QueryKey {
3637
return [...queryKey, "no-persistence"];
@@ -152,6 +153,7 @@ function initializeMessages() {
152153
...Object.values(AuthProviderClasses),
153154
...Object.values(EnvVarClasses),
154155
...Object.values(PrebuildClasses),
156+
...Object.values(VerificationClasses),
155157
...Object.values(SCMClasses),
156158
...Object.values(SSHClasses),
157159
];
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { CallOptions, PromiseClient } from "@connectrpc/connect";
8+
import { PartialMessage } from "@bufbuild/protobuf";
9+
import { VerificationService } from "@gitpod/public-api/lib/gitpod/v1/verification_connect";
10+
import {
11+
SendPhoneNumberVerificationTokenRequest,
12+
SendPhoneNumberVerificationTokenResponse,
13+
VerifyPhoneNumberVerificationTokenRequest,
14+
VerifyPhoneNumberVerificationTokenResponse,
15+
ListBlockedRepositoriesRequest,
16+
ListBlockedRepositoriesResponse,
17+
CreateBlockedRepositoryRequest,
18+
CreateBlockedRepositoryResponse,
19+
DeleteBlockedRepositoryRequest,
20+
DeleteBlockedRepositoryResponse,
21+
ListBlockedEmailDomainsRequest,
22+
ListBlockedEmailDomainsResponse,
23+
CreateBlockedEmailDomainRequest,
24+
CreateBlockedEmailDomainResponse,
25+
} from "@gitpod/public-api/lib/gitpod/v1/verification_pb";
26+
import { ApplicationError, ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
27+
import { getGitpodService } from "./service";
28+
import { validate as uuidValidate } from "uuid";
29+
import { converter } from "./public-api";
30+
import { PaginationResponse } from "@gitpod/public-api/lib/gitpod/v1/pagination_pb";
31+
32+
export class JsonRpcVerificationClient implements PromiseClient<typeof VerificationService> {
33+
async sendPhoneNumberVerificationToken(
34+
request: PartialMessage<SendPhoneNumberVerificationTokenRequest>,
35+
_options?: CallOptions | undefined,
36+
): Promise<SendPhoneNumberVerificationTokenResponse> {
37+
if (!request.phoneNumber) {
38+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "phoneNumber is required");
39+
}
40+
const info = await getGitpodService().server.sendPhoneNumberVerificationToken(request.phoneNumber);
41+
return new SendPhoneNumberVerificationTokenResponse({
42+
verificationId: info.verificationId,
43+
});
44+
}
45+
46+
async verifyPhoneNumberVerificationToken(
47+
request: PartialMessage<VerifyPhoneNumberVerificationTokenRequest>,
48+
_options?: CallOptions | undefined,
49+
): Promise<VerifyPhoneNumberVerificationTokenResponse> {
50+
if (!request.phoneNumber) {
51+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "phoneNumber is required");
52+
}
53+
if (!request.verificationId || !uuidValidate(request.verificationId)) {
54+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "verificationId is required");
55+
}
56+
if (!request.token) {
57+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "token is required");
58+
}
59+
const info = await getGitpodService().server.verifyPhoneNumberVerificationToken(
60+
request.phoneNumber,
61+
request.token,
62+
request.verificationId,
63+
);
64+
return new VerifyPhoneNumberVerificationTokenResponse({
65+
verified: info,
66+
});
67+
}
68+
69+
async listBlockedRepositories(
70+
request: PartialMessage<ListBlockedRepositoriesRequest>,
71+
_options?: CallOptions | undefined,
72+
): Promise<ListBlockedRepositoriesResponse> {
73+
// dashboard params is constant, no need to implement
74+
const info = await getGitpodService().server.adminGetBlockedRepositories({
75+
limit: 100,
76+
offset: 0,
77+
orderBy: "urlRegexp",
78+
orderDir: "asc",
79+
searchTerm: request.searchTerm,
80+
});
81+
return new ListBlockedRepositoriesResponse({
82+
blockedRepositories: info.rows.map((item) => converter.toBlockedRepository(item)),
83+
pagination: new PaginationResponse(),
84+
});
85+
}
86+
87+
async createBlockedRepository(
88+
request: PartialMessage<CreateBlockedRepositoryRequest>,
89+
_options?: CallOptions | undefined,
90+
): Promise<CreateBlockedRepositoryResponse> {
91+
if (!request.urlRegexp) {
92+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "urlRegexp is required");
93+
}
94+
if (!request.blockUser) {
95+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "blockUser is required");
96+
}
97+
const info = await getGitpodService().server.adminCreateBlockedRepository(request.urlRegexp, request.blockUser);
98+
return new CreateBlockedRepositoryResponse({
99+
blockedRepository: converter.toBlockedRepository(info),
100+
});
101+
}
102+
103+
async deleteBlockedRepository(
104+
request: PartialMessage<DeleteBlockedRepositoryRequest>,
105+
_options?: CallOptions | undefined,
106+
): Promise<DeleteBlockedRepositoryResponse> {
107+
if (!request.blockedRepositoryId) {
108+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "blockedRepositoryId is required");
109+
}
110+
await getGitpodService().server.adminDeleteBlockedRepository(request.blockedRepositoryId);
111+
return new DeleteBlockedRepositoryResponse();
112+
}
113+
114+
async listBlockedEmailDomains(
115+
request: PartialMessage<ListBlockedEmailDomainsRequest>,
116+
_options?: CallOptions | undefined,
117+
): Promise<ListBlockedEmailDomainsResponse> {
118+
const info = await getGitpodService().server.adminGetBlockedEmailDomains();
119+
return new ListBlockedEmailDomainsResponse({
120+
blockedEmailDomains: info.map((item) => converter.toBlockedEmailDomain(item)),
121+
pagination: new PaginationResponse(),
122+
});
123+
}
124+
125+
async createBlockedEmailDomain(
126+
request: PartialMessage<CreateBlockedEmailDomainRequest>,
127+
_options?: CallOptions | undefined,
128+
): Promise<CreateBlockedEmailDomainResponse> {
129+
if (!request.domain) {
130+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "domain is required");
131+
}
132+
if (request.negative === undefined) {
133+
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "negative is required");
134+
}
135+
await getGitpodService().server.adminSaveBlockedEmailDomain({
136+
domain: request.domain,
137+
negative: request.negative,
138+
});
139+
// There's no way to get blockedEmailDomain, just ignore it since dashboard don't care about the response data
140+
return new CreateBlockedEmailDomainResponse({});
141+
}
142+
}

components/dashboard/src/service/public-api.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import { JsonRpcScmClient } from "./json-rpc-scm-client";
3636
import { SCMService } from "@gitpod/public-api/lib/gitpod/v1/scm_connect";
3737
import { SSHService } from "@gitpod/public-api/lib/gitpod/v1/ssh_connect";
3838
import { JsonRpcSSHClient } from "./json-rpc-ssh-client";
39+
import { JsonRpcVerificationClient } from "./json-rpc-verification-client";
40+
import { VerificationService } from "@gitpod/public-api/lib/gitpod/v1/verification_connect";
3941

4042
const transport = createConnectTransport({
4143
baseUrl: `${window.location.protocol}//${window.location.host}/public-api`,
@@ -64,6 +66,7 @@ export const organizationClient = createServiceClient(OrganizationService, {
6466
client: new JsonRpcOrganizationClient(),
6567
featureFlagSuffix: "organization",
6668
});
69+
6770
// No jsonrcp client for the configuration service as it's only used in new UI of the dashboard
6871
export const configurationClient = createServiceClient(ConfigurationService);
6972
export const prebuildClient = createServiceClient(PrebuildService, {
@@ -91,6 +94,11 @@ export const sshClient = createServiceClient(SSHService, {
9194
featureFlagSuffix: "ssh",
9295
});
9396

97+
export const verificationClient = createServiceClient(VerificationService, {
98+
client: new JsonRpcVerificationClient(),
99+
featureFlagSuffix: "verification",
100+
});
101+
94102
export async function listAllProjects(opts: { orgId: string }): Promise<ProtocolProject[]> {
95103
let pagination = {
96104
page: 1,

0 commit comments

Comments
 (0)