Skip to content

Commit ffb60d1

Browse files
committed
[public-api] align with API guidelines
1 parent 2e3429a commit ffb60d1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+908
-648
lines changed

components/dashboard/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"version": "0.0.0",
55
"private": true,
66
"dependencies": {
7+
"@bufbuild/protobuf": "^1.3.3",
78
"@connectrpc/connect": "1.1.2",
89
"@connectrpc/connect-web": "1.1.2",
910
"@gitpod/gitpod-protocol": "0.1.5",

components/dashboard/src/components/PrebuildLogs.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ export default function PrebuildLogs(props: PrebuildLogsProps) {
6767
// Try get hold of a recent WorkspaceInfo
6868
try {
6969
const request = new GetWorkspaceRequest();
70-
request.id = props.workspaceId;
70+
request.workspaceId = props.workspaceId;
7171
const response = await workspaceClient.getWorkspace(request);
7272
setWorkspace({
73-
instanceId: response.item?.status?.instanceId,
74-
phase: response.item?.status?.phase?.name,
73+
instanceId: response.workspace?.status?.instanceId,
74+
phase: response.workspace?.status?.phase?.name,
7575
});
7676
} catch (err) {
7777
console.error(err);

components/dashboard/src/data/organizations/update-org-settings-mutation.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import { useMutation } from "@tanstack/react-query";
88
import { useOrgSettingsQueryInvalidator } from "./org-settings-query";
99
import { useCurrentOrg } from "./orgs-query";
1010
import { organizationClient } from "../../service/public-api";
11-
import { OrganizationSettings } from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
11+
import {
12+
OrganizationSettings,
13+
UpdateOrganizationSettingsRequest,
14+
} from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
15+
import { FieldMask } from "@bufbuild/protobuf";
1216

1317
type UpdateOrganizationSettingsArgs = Partial<
1418
Pick<OrganizationSettings, "workspaceSharingDisabled" | "defaultWorkspaceImage">
@@ -17,17 +21,23 @@ type UpdateOrganizationSettingsArgs = Partial<
1721
export const useUpdateOrgSettingsMutation = () => {
1822
const org = useCurrentOrg().data;
1923
const invalidator = useOrgSettingsQueryInvalidator();
20-
const teamId = org?.id || "";
24+
const organizationId = org?.id || "";
2125

2226
return useMutation<OrganizationSettings, Error, UpdateOrganizationSettingsArgs>({
2327
mutationFn: async ({ workspaceSharingDisabled, defaultWorkspaceImage }) => {
24-
const settings = await organizationClient.updateOrganizationSettings({
25-
organizationId: teamId,
26-
settings: {
27-
workspaceSharingDisabled: workspaceSharingDisabled || false,
28-
defaultWorkspaceImage,
29-
},
28+
const request = new UpdateOrganizationSettingsRequest({
29+
organizationId,
30+
workspaceSharingDisabled,
3031
});
32+
defaultWorkspaceImage = defaultWorkspaceImage?.trim();
33+
if (defaultWorkspaceImage) {
34+
request.defaultWorkspaceImage = defaultWorkspaceImage;
35+
} else if (defaultWorkspaceImage === "") {
36+
request.resetMask = new FieldMask({
37+
paths: ["defaultWorkspaceImage"],
38+
});
39+
}
40+
const settings = await organizationClient.updateOrganizationSettings(request);
3141
return settings.settings || new OrganizationSettings();
3242
},
3343
onSuccess: invalidator,

components/dashboard/src/service/json-rpc-organization-client.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
} from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
3838
import { getGitpodService } from "./service";
3939
import { converter } from "./public-api";
40+
import { OrganizationSettings } from "@gitpod/gitpod-protocol";
4041

4142
export class JsonRpcOrganizationClient implements PromiseClient<typeof OrganizationService> {
4243
async createOrganization(
@@ -71,7 +72,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
7172
options?: CallOptions | undefined,
7273
): Promise<UpdateOrganizationResponse> {
7374
if (!request.organizationId) {
74-
throw new ConnectError("id is required", Code.InvalidArgument);
75+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
7576
}
7677
if (!request.name) {
7778
throw new ConnectError("name is required", Code.InvalidArgument);
@@ -97,7 +98,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
9798
options?: CallOptions | undefined,
9899
): Promise<DeleteOrganizationResponse> {
99100
if (!request.organizationId) {
100-
throw new ConnectError("id is required", Code.InvalidArgument);
101+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
101102
}
102103
await getGitpodService().server.deleteTeam(request.organizationId);
103104
return new DeleteOrganizationResponse();
@@ -108,7 +109,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
108109
options?: CallOptions | undefined,
109110
): Promise<GetOrganizationInvitationResponse> {
110111
if (!request.organizationId) {
111-
throw new ConnectError("id is required", Code.InvalidArgument);
112+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
112113
}
113114
const result = await getGitpodService().server.getGenericInvite(request.organizationId);
114115
return new GetOrganizationInvitationResponse({
@@ -134,7 +135,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
134135
options?: CallOptions | undefined,
135136
): Promise<ResetOrganizationInvitationResponse> {
136137
if (!request.organizationId) {
137-
throw new ConnectError("id is required", Code.InvalidArgument);
138+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
138139
}
139140
const newInvite = await getGitpodService().server.resetGenericInvite(request.organizationId);
140141
return new ResetOrganizationInvitationResponse({
@@ -147,7 +148,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
147148
options?: CallOptions | undefined,
148149
): Promise<ListOrganizationMembersResponse> {
149150
if (!request.organizationId) {
150-
throw new ConnectError("id is required", Code.InvalidArgument);
151+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
151152
}
152153
const result = await getGitpodService().server.getTeamMembers(request.organizationId);
153154
return new ListOrganizationMembersResponse({
@@ -160,7 +161,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
160161
options?: CallOptions | undefined,
161162
): Promise<UpdateOrganizationMemberResponse> {
162163
if (!request.organizationId) {
163-
throw new ConnectError("id is required", Code.InvalidArgument);
164+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
164165
}
165166
if (!request.userId) {
166167
throw new ConnectError("userId is required", Code.InvalidArgument);
@@ -181,7 +182,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
181182
options?: CallOptions | undefined,
182183
): Promise<DeleteOrganizationMemberResponse> {
183184
if (!request.organizationId) {
184-
throw new ConnectError("id is required", Code.InvalidArgument);
185+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
185186
}
186187
if (!request.userId) {
187188
throw new ConnectError("userId is required", Code.InvalidArgument);
@@ -195,7 +196,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
195196
options?: CallOptions | undefined,
196197
): Promise<GetOrganizationSettingsResponse> {
197198
if (!request.organizationId) {
198-
throw new ConnectError("id is required", Code.InvalidArgument);
199+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
199200
}
200201
const result = await getGitpodService().server.getOrgSettings(request.organizationId);
201202
return new GetOrganizationSettingsResponse({
@@ -208,12 +209,18 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
208209
options?: CallOptions | undefined,
209210
): Promise<UpdateOrganizationSettingsResponse> {
210211
if (!request.organizationId) {
211-
throw new ConnectError("id is required", Code.InvalidArgument);
212-
}
213-
await getGitpodService().server.updateOrgSettings(request.organizationId, {
214-
workspaceSharingDisabled: request.settings?.workspaceSharingDisabled,
215-
defaultWorkspaceImage: request.settings?.defaultWorkspaceImage,
216-
});
212+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
213+
}
214+
const update: Partial<OrganizationSettings> = {
215+
workspaceSharingDisabled: request?.workspaceSharingDisabled,
216+
};
217+
const resetDefaultWorkspaceImage = request.resetMask?.paths?.includes("defaultWorkspaceImage");
218+
if (resetDefaultWorkspaceImage) {
219+
update.defaultWorkspaceImage = null;
220+
} else if (typeof request?.defaultWorkspaceImage === "string") {
221+
update.defaultWorkspaceImage = request.defaultWorkspaceImage;
222+
}
223+
await getGitpodService().server.updateOrgSettings(request.organizationId, update);
217224
return new UpdateOrganizationSettingsResponse();
218225
}
219226
}

components/dashboard/src/service/json-rpc-workspace-client.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ import { WorkspaceInstance } from "@gitpod/gitpod-protocol";
2020

2121
export class JsonRpcWorkspaceClient implements PromiseClient<typeof WorkspaceService> {
2222
async getWorkspace(request: PartialMessage<GetWorkspaceRequest>): Promise<GetWorkspaceResponse> {
23-
if (!request.id) {
24-
throw new ConnectError("id is required", Code.InvalidArgument);
23+
if (!request.workspaceId) {
24+
throw new ConnectError("workspaceId is required", Code.InvalidArgument);
2525
}
26-
const info = await getGitpodService().server.getWorkspace(request.id);
26+
const info = await getGitpodService().server.getWorkspace(request.workspaceId);
2727
const workspace = converter.toWorkspace(info);
2828
const result = new GetWorkspaceResponse();
29-
result.item = workspace;
29+
result.workspace = workspace;
3030
return result;
3131
}
3232

@@ -38,11 +38,11 @@ export class JsonRpcWorkspaceClient implements PromiseClient<typeof WorkspaceSer
3838
throw new ConnectError("signal is required", Code.InvalidArgument);
3939
}
4040
if (request.workspaceId) {
41-
const resp = await this.getWorkspace({ id: request.workspaceId });
42-
if (resp.item?.status) {
41+
const resp = await this.getWorkspace({ workspaceId: request.workspaceId });
42+
if (resp.workspace?.status) {
4343
const response = new WatchWorkspaceStatusResponse();
44-
response.workspaceId = resp.item.id;
45-
response.status = resp.item.status;
44+
response.workspaceId = resp.workspace.id;
45+
response.status = resp.workspace.status;
4646
yield response;
4747
}
4848
}

components/dashboard/src/start/StartWorkspace.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,14 @@ export default class StartWorkspace extends React.Component<StartWorkspaceProps,
272272
const { workspaceId } = this.props;
273273
try {
274274
const request = new GetWorkspaceRequest();
275-
request.id = workspaceId;
275+
request.workspaceId = workspaceId;
276276
const response = await workspaceClient.getWorkspace(request);
277-
if (response.item?.status?.instanceId) {
277+
if (response.workspace?.status?.instanceId) {
278278
this.setState((s) => ({
279-
workspace: response.item,
280-
startedInstanceId: s.startedInstanceId || response.item?.status?.instanceId, // note: here's a potential mismatch between startedInstanceId and instance.id. TODO(gpl) How to handle this?
279+
workspace: response.workspace,
280+
startedInstanceId: s.startedInstanceId || response.workspace?.status?.instanceId, // note: here's a potential mismatch between startedInstanceId and instance.id. TODO(gpl) How to handle this?
281281
}));
282-
this.onWorkspaceUpdate(response.item);
282+
this.onWorkspaceUpdate(response.workspace);
283283
}
284284
} catch (error) {
285285
console.error(error);

components/dashboard/src/teams/TeamSettings.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ function OrgSettingsForm(props: { org?: Organization; isOwner: boolean }) {
204204
<form
205205
onSubmit={(e) => {
206206
e.preventDefault();
207-
// handleUpdateTeamSettings({ defaultWorkspaceImage });
208207
}}
209208
>
210209
{props.org && (
@@ -282,7 +281,7 @@ function WorkspaceImageButton(props: {
282281
};
283282
}
284283

285-
const image = props.settings?.defaultWorkspaceImage ?? props.defaultWorkspaceImage ?? "";
284+
const image = props.settings?.defaultWorkspaceImage || props.defaultWorkspaceImage || "";
286285

287286
const descList = useMemo(() => {
288287
const arr: ReactNode[] = [<span>Default image</span>];
@@ -348,7 +347,7 @@ interface OrgDefaultWorkspaceImageModalProps {
348347

349348
function OrgDefaultWorkspaceImageModal(props: OrgDefaultWorkspaceImageModalProps) {
350349
const [errorMsg, setErrorMsg] = useState("");
351-
const [defaultWorkspaceImage, setDefaultWorkspaceImage] = useState(props.settings?.defaultWorkspaceImage ?? "");
350+
const [defaultWorkspaceImage, setDefaultWorkspaceImage] = useState(props.settings?.defaultWorkspaceImage || "");
352351
const updateTeamSettings = useUpdateOrgSettingsMutation();
353352

354353
const handleUpdateTeamSettings = useCallback(

components/gitpod-db/src/team-db.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export interface TeamDB extends TransactionalDB<TeamDB> {
4040
deleteTeam(teamId: string): Promise<void>;
4141

4242
findOrgSettings(teamId: string): Promise<OrganizationSettings | undefined>;
43-
setOrgSettings(teamId: string, settings: Partial<OrganizationSettings>): Promise<void>;
43+
setOrgSettings(teamId: string, settings: Partial<OrganizationSettings>): Promise<OrganizationSettings>;
4444

4545
hasActiveSSO(organizationId: string): Promise<boolean>;
4646
}

components/gitpod-db/src/typeorm/team-db-impl.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -366,28 +366,19 @@ export class TeamDBImpl extends TransactionalDBImpl<TeamDB> implements TeamDB {
366366
});
367367
}
368368

369-
public async setOrgSettings(orgId: string, settings: Partial<OrganizationSettings>): Promise<void> {
369+
public async setOrgSettings(orgId: string, settings: Partial<OrganizationSettings>): Promise<OrganizationSettings> {
370370
const repo = await this.getOrgSettingsRepo();
371371
const team = await repo.findOne({ where: { orgId, deleted: false } });
372-
const update: Partial<OrganizationSettings> = {
373-
defaultWorkspaceImage: settings.defaultWorkspaceImage,
374-
workspaceSharingDisabled: settings.workspaceSharingDisabled,
375-
};
376-
// Set to null if defaultWorkspaceImage is empty string, so that it can fallback to default image
377-
if (update.defaultWorkspaceImage?.trim() === "") {
378-
update.defaultWorkspaceImage = null;
379-
}
380372
if (!team) {
381-
await repo.insert({
382-
...update,
373+
return await repo.save({
374+
...settings,
383375
orgId,
384376
});
385-
} else {
386-
await repo.save({
387-
...team,
388-
...update,
389-
});
390377
}
378+
return await repo.save({
379+
...team,
380+
...settings,
381+
});
391382
}
392383

393384
public async hasActiveSSO(organizationId: string): Promise<boolean> {

components/gitpod-protocol/src/messaging/error.ts

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66

77
import { scrubber } from "../util/scrubbing";
8-
import { Status } from "nice-grpc-common";
98

109
export class ApplicationError extends Error {
1110
constructor(public readonly code: ErrorCode, message: string, public readonly data?: any) {
@@ -24,7 +23,7 @@ export class ApplicationError extends Error {
2423

2524
export namespace ApplicationError {
2625
export function hasErrorCode(e: any): e is Error & { code: ErrorCode; data?: any } {
27-
return e && e.code !== undefined;
26+
return ErrorCode.is(e["code"]);
2827
}
2928

3029
export async function notFoundToUndefined<T>(p: Promise<T>): Promise<T | undefined> {
@@ -37,41 +36,18 @@ export namespace ApplicationError {
3736
throw e;
3837
}
3938
}
40-
41-
export function fromGRPCError(e: any, data?: any): ApplicationError {
42-
// Argument e should be ServerErrorResponse
43-
// But to reduce dependency requirement, we use Error here
44-
45-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
46-
return new ApplicationError(categorizeRPCError(e.code), e.message, data);
47-
}
48-
49-
export function categorizeRPCError(code?: Status): ErrorCode {
50-
// Mostly align to https://github.com/gitpod-io/gitpod/blob/ef95e6f3ca0bf314c40da1b83251423c2208d175/components/public-api-server/pkg/proxy/errors.go#L25
51-
switch (code) {
52-
case Status.INVALID_ARGUMENT:
53-
return ErrorCodes.BAD_REQUEST;
54-
case Status.UNAUTHENTICATED:
55-
return ErrorCodes.NOT_AUTHENTICATED;
56-
case Status.PERMISSION_DENIED:
57-
return ErrorCodes.PERMISSION_DENIED; // or UserBlocked
58-
case Status.NOT_FOUND:
59-
return ErrorCodes.NOT_FOUND;
60-
case Status.ALREADY_EXISTS:
61-
return ErrorCodes.CONFLICT;
62-
case Status.FAILED_PRECONDITION:
63-
return ErrorCodes.PRECONDITION_FAILED;
64-
case Status.RESOURCE_EXHAUSTED:
65-
return ErrorCodes.TOO_MANY_REQUESTS;
66-
}
67-
return ErrorCodes.INTERNAL_SERVER_ERROR;
68-
}
6939
}
7040

7141
export namespace ErrorCode {
7242
export function isUserError(code: number | ErrorCode) {
7343
return code >= 400 && code < 500;
7444
}
45+
export function is(code: any): code is ErrorCode {
46+
if (typeof code !== "number") {
47+
return false;
48+
}
49+
return Object.values(ErrorCodes).includes(code as ErrorCode);
50+
}
7551
}
7652

7753
export type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];

components/gitpod-protocol/src/public-api-converter.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ describe("PublicAPIConverter", () => {
233233
},
234234
additionalEnvironmentVariables: [],
235235
region: "dev",
236+
prebuildId: "",
236237
workspaceClass: "g1-standard",
237238
editor: {
238239
name: "code",
@@ -362,6 +363,7 @@ describe("PublicAPIConverter", () => {
362363
},
363364
additionalEnvironmentVariables: [],
364365
region: "dev",
366+
prebuildId: "",
365367
workspaceClass: "g1-standard",
366368
editor: {
367369
name: "code",
@@ -502,6 +504,7 @@ describe("PublicAPIConverter", () => {
502504
},
503505
additionalEnvironmentVariables: [],
504506
region: "dev",
507+
prebuildId: "",
505508
workspaceClass: "g1-standard",
506509
editor: {
507510
name: "code",
@@ -617,6 +620,7 @@ describe("PublicAPIConverter", () => {
617620
},
618621
additionalEnvironmentVariables: [],
619622
region: "dev",
623+
prebuildId: "",
620624
workspaceClass: "g1-standard",
621625
editor: {
622626
name: "code",

0 commit comments

Comments
 (0)