@gitpod/gitpod-protocol 0.1.5-se-cancel-reason.0 → 0.1.5-se-usage-view.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/data/gitpod-schema.json +44 -129
  2. package/lib/accounting-protocol.d.ts +1 -0
  3. package/lib/accounting-protocol.d.ts.map +1 -1
  4. package/lib/accounting-protocol.js +4 -0
  5. package/lib/accounting-protocol.js.map +1 -1
  6. package/lib/admin-protocol.d.ts +5 -0
  7. package/lib/admin-protocol.d.ts.map +1 -1
  8. package/lib/admin-protocol.js.map +1 -1
  9. package/lib/attribution.d.ts +20 -0
  10. package/lib/attribution.d.ts.map +1 -0
  11. package/lib/attribution.js +40 -0
  12. package/lib/attribution.js.map +1 -0
  13. package/lib/billing-mode.d.ts +40 -0
  14. package/lib/billing-mode.d.ts.map +1 -0
  15. package/lib/billing-mode.js +36 -0
  16. package/lib/billing-mode.js.map +1 -0
  17. package/lib/blocked-repositories-protocol.d.ts +13 -0
  18. package/lib/blocked-repositories-protocol.d.ts.map +1 -0
  19. package/lib/blocked-repositories-protocol.js +8 -0
  20. package/lib/blocked-repositories-protocol.js.map +1 -0
  21. package/lib/experiments/configcat-server.d.ts +2 -0
  22. package/lib/experiments/configcat-server.d.ts.map +1 -1
  23. package/lib/experiments/configcat-server.js +3 -1
  24. package/lib/experiments/configcat-server.js.map +1 -1
  25. package/lib/experiments/configcat.d.ts +3 -2
  26. package/lib/experiments/configcat.d.ts.map +1 -1
  27. package/lib/experiments/configcat.js +9 -3
  28. package/lib/experiments/configcat.js.map +1 -1
  29. package/lib/experiments/types.d.ts +7 -3
  30. package/lib/experiments/types.d.ts.map +1 -1
  31. package/lib/experiments/types.js +2 -0
  32. package/lib/experiments/types.js.map +1 -1
  33. package/lib/gitpod-service.d.ts +26 -4
  34. package/lib/gitpod-service.d.ts.map +1 -1
  35. package/lib/gitpod-service.js +1 -1
  36. package/lib/gitpod-service.js.map +1 -1
  37. package/lib/ide-protocol.d.ts +8 -0
  38. package/lib/ide-protocol.d.ts.map +1 -1
  39. package/lib/index.d.ts +1 -0
  40. package/lib/index.d.ts.map +1 -1
  41. package/lib/index.js +1 -0
  42. package/lib/index.js.map +1 -1
  43. package/lib/messaging/client-call-metrics.d.ts +1 -17
  44. package/lib/messaging/client-call-metrics.d.ts.map +1 -1
  45. package/lib/messaging/client-call-metrics.js +1 -2
  46. package/lib/messaging/client-call-metrics.js.map +1 -1
  47. package/lib/messaging/error.d.ts +4 -1
  48. package/lib/messaging/error.d.ts.map +1 -1
  49. package/lib/messaging/error.js +9 -3
  50. package/lib/messaging/error.js.map +1 -1
  51. package/lib/plans.d.ts +1 -0
  52. package/lib/plans.d.ts.map +1 -1
  53. package/lib/plans.js +4 -0
  54. package/lib/plans.js.map +1 -1
  55. package/lib/protocol.d.ts +61 -3
  56. package/lib/protocol.d.ts.map +1 -1
  57. package/lib/protocol.js +104 -3
  58. package/lib/protocol.js.map +1 -1
  59. package/lib/protocol.spec.d.ts +7 -0
  60. package/lib/protocol.spec.d.ts.map +1 -0
  61. package/lib/protocol.spec.js +127 -0
  62. package/lib/protocol.spec.js.map +1 -0
  63. package/lib/team-subscription-protocol.d.ts +1 -0
  64. package/lib/team-subscription-protocol.d.ts.map +1 -1
  65. package/lib/team-subscription-protocol.js +4 -0
  66. package/lib/team-subscription-protocol.js.map +1 -1
  67. package/lib/teams-projects-protocol.d.ts +12 -0
  68. package/lib/teams-projects-protocol.d.ts.map +1 -1
  69. package/lib/teams-projects-protocol.js.map +1 -1
  70. package/lib/usage.d.ts +97 -0
  71. package/lib/usage.d.ts.map +1 -0
  72. package/lib/usage.js +14 -0
  73. package/lib/usage.js.map +1 -0
  74. package/lib/util/garbage-collected-cache.d.ts.map +1 -1
  75. package/lib/util/garbage-collected-cache.js +5 -0
  76. package/lib/util/garbage-collected-cache.js.map +1 -1
  77. package/lib/util/gitpod-host-url.d.ts +3 -0
  78. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  79. package/lib/util/gitpod-host-url.js +18 -0
  80. package/lib/util/gitpod-host-url.js.map +1 -1
  81. package/lib/util/grpc.d.ts +19 -0
  82. package/lib/util/grpc.d.ts.map +1 -1
  83. package/lib/util/grpc.js +73 -1
  84. package/lib/util/grpc.js.map +1 -1
  85. package/lib/util/logging.spec.d.ts +7 -0
  86. package/lib/util/logging.spec.d.ts.map +1 -0
  87. package/lib/util/logging.spec.js +52 -0
  88. package/lib/util/logging.spec.js.map +1 -0
  89. package/lib/util/timeutil.d.ts +1 -0
  90. package/lib/util/timeutil.d.ts.map +1 -1
  91. package/lib/util/timeutil.js +7 -1
  92. package/lib/util/timeutil.js.map +1 -1
  93. package/lib/util/timeutil.spec.d.ts +1 -0
  94. package/lib/util/timeutil.spec.d.ts.map +1 -1
  95. package/lib/util/timeutil.spec.js +10 -0
  96. package/lib/util/timeutil.spec.js.map +1 -1
  97. package/lib/webhook-event.d.ts +44 -0
  98. package/lib/webhook-event.d.ts.map +1 -0
  99. package/lib/webhook-event.js +8 -0
  100. package/lib/webhook-event.js.map +1 -0
  101. package/lib/workspace-class.d.ts +14 -0
  102. package/lib/workspace-class.d.ts.map +1 -0
  103. package/lib/workspace-class.js +8 -0
  104. package/lib/workspace-class.js.map +1 -0
  105. package/lib/workspace-cluster.d.ts +5 -7
  106. package/lib/workspace-cluster.d.ts.map +1 -1
  107. package/lib/workspace-cluster.js.map +1 -1
  108. package/lib/workspace-instance.d.ts +2 -0
  109. package/lib/workspace-instance.d.ts.map +1 -1
  110. package/lib/wsready.d.ts +3 -3
  111. package/lib/wsready.d.ts.map +1 -1
  112. package/lib/wsready.js +0 -2
  113. package/lib/wsready.js.map +1 -1
  114. package/package.json +5 -2
  115. package/pkg-yarn.lock +3 -2
  116. package/provenance-bundle.jsonl +1 -1
  117. package/src/accounting-protocol.ts +3 -0
  118. package/src/admin-protocol.ts +8 -0
  119. package/src/attribution.ts +48 -0
  120. package/src/billing-mode.ts +67 -0
  121. package/src/blocked-repositories-protocol.ts +13 -0
  122. package/src/experiments/configcat-server.ts +4 -0
  123. package/src/experiments/configcat.ts +10 -5
  124. package/src/experiments/types.ts +10 -7
  125. package/src/gitpod-service.ts +35 -3
  126. package/src/ide-protocol.ts +10 -0
  127. package/src/index.ts +1 -0
  128. package/src/messaging/client-call-metrics.ts +1 -20
  129. package/src/messaging/error.ts +13 -4
  130. package/src/plans.ts +4 -0
  131. package/src/protocol.spec.ts +97 -0
  132. package/src/protocol.ts +163 -5
  133. package/src/team-subscription-protocol.ts +3 -0
  134. package/src/teams-projects-protocol.ts +13 -0
  135. package/src/usage.ts +128 -0
  136. package/src/util/garbage-collected-cache.ts +5 -0
  137. package/src/util/gitpod-host-url.ts +21 -0
  138. package/src/util/grpc.ts +89 -0
  139. package/src/util/logging.spec.ts +23 -0
  140. package/src/util/timeutil.spec.ts +7 -1
  141. package/src/util/timeutil.ts +6 -0
  142. package/src/webhook-event.ts +55 -0
  143. package/src/workspace-class.ts +14 -0
  144. package/src/workspace-cluster.ts +2 -4
  145. package/src/workspace-instance.ts +8 -0
  146. package/src/wsready.ts +5 -4
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Copyright (c) 2022 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
+ export type AttributionId = UserAttributionId | TeamAttributionId;
8
+ export type AttributionTarget = "user" | "team";
9
+
10
+ export interface UserAttributionId {
11
+ kind: "user";
12
+ userId: string;
13
+ }
14
+ export interface TeamAttributionId {
15
+ kind: "team";
16
+ teamId: string;
17
+ }
18
+
19
+ export namespace AttributionId {
20
+ const SEPARATOR = ":";
21
+
22
+ export function parse(s: string): UserAttributionId | TeamAttributionId | undefined {
23
+ if (!s) {
24
+ return undefined;
25
+ }
26
+ const parts = s.split(":");
27
+ if (parts.length !== 2) {
28
+ return undefined;
29
+ }
30
+ switch (parts[0]) {
31
+ case "user":
32
+ return { kind: "user", userId: parts[1] };
33
+ case "team":
34
+ return { kind: "team", teamId: parts[1] };
35
+ default:
36
+ return undefined;
37
+ }
38
+ }
39
+
40
+ export function render(id: AttributionId): string {
41
+ switch (id.kind) {
42
+ case "user":
43
+ return `user${SEPARATOR}${id.userId}`;
44
+ case "team":
45
+ return `team${SEPARATOR}${id.teamId}`;
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Copyright (c) 2022 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
+ /**
8
+ * BillingMode is used to answer the following questions:
9
+ * - Should UI piece x be displayed for this user/team? (getBillingModeForUser/Team)
10
+ * - What model should be used to limit this workspace's capabilities (mayStartWorkspace, setTimeout, workspace class, etc...) (getBillingMode(workspaceInstance.attributionId))
11
+ * - How is a workspace session charged for? (getBillingMode(workspaceInstance.attributionId))
12
+ */
13
+ export type BillingMode = None | Chargebee | UsageBased;
14
+ export namespace BillingMode {
15
+ export const NONE: None = {
16
+ mode: "none",
17
+ };
18
+
19
+ /** Incl. upgrade and status */
20
+ export function showUsageBasedBilling(billingMode?: BillingMode): boolean {
21
+ if (!billingMode) {
22
+ return false;
23
+ }
24
+ return (
25
+ billingMode.mode === "usage-based" || (billingMode.mode === "chargebee" && !!billingMode.canUpgradeToUBB)
26
+ );
27
+ }
28
+
29
+ export function canSetWorkspaceClass(billingMode?: BillingMode): boolean {
30
+ if (!billingMode) {
31
+ return false;
32
+ }
33
+
34
+ // if has any Stripe subscription, either directly or per team
35
+ return billingMode.mode === "usage-based";
36
+ }
37
+
38
+ export function canSetCostCenter(billingMode: BillingMode): boolean {
39
+ // if has any Stripe Subscription, either directly or per team
40
+ return billingMode.mode === "usage-based";
41
+ }
42
+ }
43
+
44
+ /** Payment is disabled */
45
+ interface None {
46
+ mode: "none";
47
+ }
48
+
49
+ /** Sessions is handled with old subscription logic based on Chargebee */
50
+ interface Chargebee {
51
+ mode: "chargebee";
52
+ canUpgradeToUBB?: boolean;
53
+ }
54
+
55
+ /** Session is handld with new usage-based logic */
56
+ interface UsageBased {
57
+ mode: "usage-based";
58
+
59
+ /** True iff this is a team, and is based on a paid plan. Currently only set for teams! */
60
+ paid?: boolean;
61
+
62
+ /** User is already converted, but is member with at least one Chargebee-based "Team Plan" */
63
+ hasChargebeeTeamPlan?: boolean;
64
+
65
+ /** User is already converted, but is member in at least one Chargebee-based "Team Subscription" */
66
+ hasChargebeeTeamSubscription?: boolean;
67
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) 2022 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
+ export interface BlockedRepository {
8
+ id: number;
9
+ urlRegexp: string;
10
+ blockUser: boolean;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ }
@@ -12,6 +12,9 @@ import { newAlwaysReturningDefaultValueClient } from "./always-default";
12
12
 
13
13
  let client: Client | undefined;
14
14
 
15
+ export type ConfigCatClientFactory = () => Client;
16
+ export const ConfigCatClientFactory = Symbol("ConfigCatClientFactory");
17
+
15
18
  export function getExperimentsClientForBackend(): Client {
16
19
  // We have already instantiated a client, we can just re-use it.
17
20
  if (client !== undefined) {
@@ -28,6 +31,7 @@ export function getExperimentsClientForBackend(): Client {
28
31
  }
29
32
 
30
33
  const configCatClient = configcat.createClient(sdkKey, {
34
+ pollIntervalSeconds: 3 * 60, // 3 minutes
31
35
  logger: configcat.createConsoleLogger(LogLevel.Error),
32
36
  maxInitWaitTimeSeconds: 0,
33
37
  });
@@ -5,9 +5,11 @@
5
5
  */
6
6
 
7
7
  import { Attributes, Client } from "./types";
8
- import { User } from "configcat-common/lib/RolloutEvaluator";
8
+ import { User as ConfigCatUser } from "configcat-common/lib/RolloutEvaluator";
9
9
  import { IConfigCatClient } from "configcat-common/lib/ConfigCatClient";
10
+ import { User } from "../protocol";
10
11
 
12
+ export const USER_ID_ATTRIBUTE = "user_id";
11
13
  export const PROJECT_ID_ATTRIBUTE = "project_id";
12
14
  export const TEAM_ID_ATTRIBUTE = "team_id";
13
15
  export const TEAM_IDS_ATTRIBUTE = "team_ids";
@@ -30,11 +32,14 @@ export class ConfigCatClient implements Client {
30
32
  }
31
33
  }
32
34
 
33
- export function attributesToUser(attributes: Attributes): User {
34
- const userId = attributes.userId || "";
35
- const email = attributes.email || "";
35
+ export function attributesToUser(attributes: Attributes): ConfigCatUser {
36
+ const userId = attributes.user?.id || "";
37
+ const email = User.is(attributes.user) ? User.getPrimaryEmail(attributes.user) : attributes.user?.email || "";
36
38
 
37
39
  const custom: { [key: string]: string } = {};
40
+ if (userId) {
41
+ custom[USER_ID_ATTRIBUTE] = userId;
42
+ }
38
43
  if (attributes.projectId) {
39
44
  custom[PROJECT_ID_ATTRIBUTE] = attributes.projectId;
40
45
  }
@@ -49,5 +54,5 @@ export function attributesToUser(attributes: Attributes): User {
49
54
  custom[TEAM_IDS_ATTRIBUTE] = attributes.teams.map((t) => t.id).join(",");
50
55
  }
51
56
 
52
- return new User(userId, email, "", custom);
57
+ return new ConfigCatUser(userId, email, "", custom);
53
58
  }
@@ -4,24 +4,27 @@
4
4
  * See License-AGPL.txt in the project root for license information.
5
5
  */
6
6
 
7
+ import { User } from "../protocol";
7
8
  import { Team } from "../teams-projects-protocol";
8
9
 
10
+ export const Client = Symbol("Client");
11
+
9
12
  // Attributes define attributes which can be used to segment audiences.
10
13
  // Set the attributes which you want to use to group audiences into.
11
14
  export interface Attributes {
12
- userId?: string;
13
- email?: string;
15
+ // user.id is mapped to ConfigCat's "identifier" + "custom.user_id"
16
+ user?: User | { id: string; email?: string };
14
17
 
15
- // Currently selected Gitpod Project ID
18
+ // Currently selected Gitpod Project ID (mapped to "custom.project_id")
16
19
  projectId?: string;
17
20
 
18
- // Currently selected Gitpod Team ID
21
+ // Currently selected Gitpod Team ID (mapped to "custom.team_id")
19
22
  teamId?: string;
20
- // Currently selected Gitpod Team Name
23
+ // Currently selected Gitpod Team Name (mapped to "custom.team_name")
21
24
  teamName?: string;
22
25
 
23
- // All the Gitpod Teams that the user is a member (or owner) of
24
- teams?: Array<Team>;
26
+ // All the Gitpod Teams that the user is a member (or owner) of (mapped to "custom.team_names" and "custom.team_ids")
27
+ teams?: Team[];
25
28
  }
26
29
 
27
30
  export interface Client {
@@ -25,6 +25,8 @@ import {
25
25
  GuessedGitTokenScopes,
26
26
  ProjectEnvVar,
27
27
  PrebuiltWorkspace,
28
+ UserSSHPublicKeyValue,
29
+ SSHPublicKeyValue,
28
30
  } from "./protocol";
29
31
  import {
30
32
  Team,
@@ -35,6 +37,7 @@ import {
35
37
  PrebuildWithStatus,
36
38
  StartPrebuildResult,
37
39
  PartialProject,
40
+ PrebuildEvent,
38
41
  } from "./teams-projects-protocol";
39
42
  import { JsonRpcProxy, JsonRpcServer } from "./messaging/proxy-factory";
40
43
  import { Disposable, CancellationTokenSource } from "vscode-jsonrpc";
@@ -57,7 +60,9 @@ import {
57
60
  import { RemotePageMessage, RemoteTrackMessage, RemoteIdentifyMessage } from "./analytics";
58
61
  import { IDEServer } from "./ide-protocol";
59
62
  import { InstallationAdminSettings, TelemetryData } from "./installation-admin-protocol";
60
- import { Currency } from "./plans";
63
+ import { ListBilledUsageResponse, ListBilledUsageRequest, ListUsageRequest, ListUsageResponse } from "./usage";
64
+ import { SupportedWorkspaceClass } from "./workspace-class";
65
+ import { BillingMode } from "./billing-mode";
61
66
 
62
67
  export interface GitpodClient {
63
68
  onInstanceUpdate(instance: WorkspaceInstance): void;
@@ -79,6 +84,8 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
79
84
  getLoggedInUser(): Promise<User>;
80
85
  getTerms(): Promise<Terms>;
81
86
  updateLoggedInUser(user: Partial<User>): Promise<User>;
87
+ sendPhoneNumberVerificationToken(phoneNumber: string): Promise<void>;
88
+ verifyPhoneNumberVerificationToken(phoneNumber: string, token: string): Promise<boolean>;
82
89
  getAuthProviders(): Promise<AuthProviderInfo[]>;
83
90
  getOwnAuthProviders(): Promise<AuthProviderEntry[]>;
84
91
  updateOwnAuthProvider(params: GitpodServer.UpdateOwnAuthProviderParams): Promise<AuthProviderEntry>;
@@ -149,6 +156,12 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
149
156
  setEnvVar(variable: UserEnvVarValue): Promise<void>;
150
157
  deleteEnvVar(variable: UserEnvVarValue): Promise<void>;
151
158
 
159
+ // User SSH Keys
160
+ hasSSHPublicKey(): Promise<boolean>;
161
+ getSSHPublicKeys(): Promise<UserSSHPublicKeyValue[]>;
162
+ addSSHPublicKey(value: SSHPublicKeyValue): Promise<UserSSHPublicKeyValue>;
163
+ deleteSSHPublicKey(id: string): Promise<void>;
164
+
152
165
  // Teams
153
166
  getTeams(): Promise<Team[]>;
154
167
  getTeamMembers(teamId: string): Promise<TeamMemberInfo[]>;
@@ -172,6 +185,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
172
185
  getTeamProjects(teamId: string): Promise<Project[]>;
173
186
  getUserProjects(): Promise<Project[]>;
174
187
  getProjectOverview(projectId: string): Promise<Project.Overview | undefined>;
188
+ getPrebuildEvents(projectId: string): Promise<PrebuildEvent[]>;
175
189
  findPrebuilds(params: FindPrebuildsParams): Promise<PrebuildWithStatus[]>;
176
190
  findPrebuildByWorkspaceID(workspaceId: string): Promise<PrebuiltWorkspace | undefined>;
177
191
  getPrebuild(prebuildId: string): Promise<PrebuildWithStatus | undefined>;
@@ -277,8 +291,19 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
277
291
  getStripePublishableKey(): Promise<string>;
278
292
  getStripeSetupIntentClientSecret(): Promise<string>;
279
293
  findStripeSubscriptionIdForTeam(teamId: string): Promise<string | undefined>;
280
- subscribeTeamToStripe(teamId: string, setupIntentId: string, currency: Currency): Promise<void>;
294
+ createOrUpdateStripeCustomerForTeam(teamId: string, currency: string): Promise<void>;
295
+ subscribeTeamToStripe(teamId: string, setupIntentId: string): Promise<void>;
281
296
  getStripePortalUrlForTeam(teamId: string): Promise<string>;
297
+ getSpendingLimitForTeam(teamId: string): Promise<number | undefined>;
298
+ setSpendingLimitForTeam(teamId: string, spendingLimit: number): Promise<void>;
299
+
300
+ listBilledUsage(req: ListBilledUsageRequest): Promise<ListBilledUsageResponse>;
301
+ listUsage(req: ListUsageRequest): Promise<ListUsageResponse>;
302
+
303
+ setUsageAttribution(usageAttribution: string): Promise<void>;
304
+
305
+ getBillingModeForUser(): Promise<BillingMode>;
306
+ getBillingModeForTeam(teamId: string): Promise<BillingMode>;
282
307
 
283
308
  /**
284
309
  * Analytics
@@ -286,6 +311,13 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
286
311
  trackEvent(event: RemoteTrackMessage): Promise<void>;
287
312
  trackLocation(event: RemotePageMessage): Promise<void>;
288
313
  identifyUser(event: RemoteIdentifyMessage): Promise<void>;
314
+
315
+ /**
316
+ * Frontend notifications
317
+ */
318
+ getNotifications(): Promise<string[]>;
319
+
320
+ getSupportedWorkspaceClasses(): Promise<SupportedWorkspaceClass[]>;
289
321
  }
290
322
 
291
323
  export interface RateLimiterError {
@@ -367,7 +399,7 @@ export const createServerMock = function <C extends GitpodClient, S extends Gitp
367
399
  get: (target: S, property: keyof S) => {
368
400
  const result = target[property];
369
401
  if (!result) {
370
- throw new Error(`Method ${property} not implemented`);
402
+ throw new Error(`Method ${String(property)} not implemented`);
371
403
  }
372
404
  return result;
373
405
  },
@@ -116,4 +116,14 @@ export interface IDEOption {
116
116
  * we resolve the tag regularly to the most recent image version.
117
117
  */
118
118
  resolveImageDigest?: boolean;
119
+
120
+ /**
121
+ * The plugin image ref for the IDE image, this image ref always resolve to digest.
122
+ */
123
+ pluginImage?: string;
124
+
125
+ /**
126
+ * The latest plugin image ref for the latest IDE image, this image ref always resolve to digest.
127
+ */
128
+ pluginLatestImage?: string;
119
129
  }
package/src/index.ts CHANGED
@@ -20,3 +20,4 @@ export * from "./teams-projects-protocol";
20
20
  export * from "./snapshot-url";
21
21
  export * from "./oss-allowlist";
22
22
  export * from "./installation-admin-protocol";
23
+ export * from "./webhook-event";
@@ -6,26 +6,7 @@
6
6
 
7
7
  import { injectable } from "inversify";
8
8
  import * as prometheusClient from "prom-client";
9
-
10
- type GrpcMethodType = "unary" | "client_stream" | "server_stream" | "bidi_stream";
11
- export interface IGrpcCallMetricsLabels {
12
- service: string;
13
- method: string;
14
- type: GrpcMethodType;
15
- }
16
-
17
- export interface IGrpcCallMetricsLabelsWithCode extends IGrpcCallMetricsLabels {
18
- code: string;
19
- }
20
-
21
- export const IClientCallMetrics = Symbol("IClientCallMetrics");
22
-
23
- export interface IClientCallMetrics {
24
- started(labels: IGrpcCallMetricsLabels): void;
25
- sent(labels: IGrpcCallMetricsLabels): void;
26
- received(labels: IGrpcCallMetricsLabels): void;
27
- handled(labels: IGrpcCallMetricsLabelsWithCode): void;
28
- }
9
+ import { IClientCallMetrics, IGrpcCallMetricsLabels, IGrpcCallMetricsLabelsWithCode } from "../util/grpc";
29
10
 
30
11
  @injectable()
31
12
  export class PrometheusClientCallMetrics implements IClientCallMetrics {
@@ -26,21 +26,30 @@ export namespace ErrorCodes {
26
26
  // 410 No User
27
27
  export const SETUP_REQUIRED = 410;
28
28
 
29
+ // 411 No User
30
+ export const NEEDS_VERIFICATION = 411;
31
+
29
32
  // 429 Too Many Requests
30
33
  export const TOO_MANY_REQUESTS = 429;
31
34
 
32
35
  // 430 Repository not whitelisted (custom status code)
33
36
  export const REPOSITORY_NOT_WHITELISTED = 430;
34
37
 
38
+ // 450 Payment error
39
+ export const PAYMENT_ERROR = 450;
40
+
41
+ // 451 Out of credits
42
+ export const PAYMENT_SPENDING_LIMIT_REACHED = 451;
43
+
44
+ // 455 Invalid cost center (custom status code)
45
+ export const INVALID_COST_CENTER = 455;
46
+
35
47
  // 460 Context Parse Error (custom status code)
36
48
  export const CONTEXT_PARSE_ERROR = 460;
37
49
 
38
- // 461 Invalid gitpod yml
50
+ // 461 Invalid gitpod yml (custom status code)
39
51
  export const INVALID_GITPOD_YML = 461;
40
52
 
41
- // 450 Payment error
42
- export const PAYMENT_ERROR = 450;
43
-
44
53
  // 470 User Blocked (custom status code)
45
54
  export const USER_BLOCKED = 470;
46
55
 
package/src/plans.ts CHANGED
@@ -482,6 +482,10 @@ export namespace Plans {
482
482
  );
483
483
  }
484
484
 
485
+ export function isFreeTier(chargebeeId: string | undefined): boolean {
486
+ return chargebeeId === Plans.FREE.chargebeeId || chargebeeId === Plans.FREE_50.chargebeeId;
487
+ }
488
+
485
489
  export function isFreeNonTransientPlan(chargebeeId: string | undefined): boolean {
486
490
  return chargebeeId === Plans.FREE_OPEN_SOURCE.chargebeeId;
487
491
  }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright (c) 2020 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 { suite, test } from "mocha-typescript";
8
+ import * as chai from "chai";
9
+ import { SSHPublicKeyValue } from ".";
10
+
11
+ const expect = chai.expect;
12
+
13
+ @suite
14
+ class TestSSHPublicKeyValue {
15
+ private key =
16
+ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDCnrN9UdK1bNGPmZfenTWXLuYYDjlYvZE8S+WOfP08WpR1GETzX5ZvgYOEZGwEE8KUPHC9cge4Hvo/ydIS9aqbZ5MiVGJ8cAIq1Ic89SjlDWU6fl8TwIqOPCi2imAASlEDP4q8vMLK1N6UOW1EVbxyL3uybGd10ysC1t1FxFPveIGNsYE/MOQeuEWS16AplpXYXIfVRSlgAskeBft2w8Ud3B4gNe8ECLA/FXu96UpvZkdtOarA3JZ9Z27GveNJg9Mtmmw0+US0KXiO9x9NyH7G8+mqVDwDY+nNvaFA5gtQxkkl/uY2oz9k/B4Rjlj3jOiUXe5uQs3XUm5m8g9a9fh62DabLpA2fEvtfg+a/VqNe52dNa5YjupwvBd6Inb5uMW/TYjNl6bNHPlXFKw/nwLOVzukpkjxMZUKS6+4BGkpoasj6y2rTU/wkpbdD8J7yjI1p6J9aKkC6KksIWgN7xGmHkv2PCGDqMHTNbnQyowtNKMgA/667vAYJ0qW7HAHBFXJRs6uRi/DI3+c1QV2s4wPCpEHDIYApovQ0fbON4WDPoGMyHd7kPh9xB/bX7Dj0uMXImu1pdTd62fQ/1XXX64+vjAAXS/P9RSCD0RCRt/K3LPKl2m7GPI3y1niaE52XhxZw+ms9ays6NasNVMw/ZC+f02Ti+L5FBEVf8230RVVRQ== notfound@gitpod.io";
17
+
18
+ @test public testValidate() {
19
+ const key = this.key;
20
+ const [t, k, e] = key.split(" ");
21
+ expect(
22
+ SSHPublicKeyValue.getData({
23
+ key,
24
+ name: "NiceName",
25
+ }),
26
+ ).to.deep.equal({ type: t, key: k, email: e });
27
+ }
28
+
29
+ @test public testValidateWithDiffType() {
30
+ const key = this.key;
31
+ const [_, k, e] = key.split(" ");
32
+ expect(
33
+ SSHPublicKeyValue.getData({
34
+ key: key.replace("ssh-rsa", "sk-ecdsa-sha2-nistp256@openssh.com"),
35
+ name: "NiceName",
36
+ }),
37
+ ).to.deep.equal({ type: "sk-ecdsa-sha2-nistp256@openssh.com", key: k, email: e });
38
+ }
39
+
40
+ @test public testValidateWithoutEmail() {
41
+ const key = this.key;
42
+ const [t, k, _] = key.split(" ");
43
+ expect(
44
+ SSHPublicKeyValue.getData({
45
+ key: key.replace(" notfound@gitpod.io", ""),
46
+ name: "NiceName",
47
+ }),
48
+ ).to.deep.equal({ type: t, key: k, email: undefined });
49
+ }
50
+
51
+ @test public testValidateWithoutEmailButEndsWithSpaces() {
52
+ const key = this.key;
53
+ const [t, k, _] = key.split(" ");
54
+ expect(
55
+ SSHPublicKeyValue.getData({
56
+ key: key.replace("notfound@gitpod.io", " "),
57
+ name: "NiceName",
58
+ }),
59
+ ).to.deep.equal({ type: t, key: k, email: undefined });
60
+ }
61
+
62
+ @test public testValidateWithError() {
63
+ expect(() =>
64
+ SSHPublicKeyValue.getData({
65
+ key: "Hello World",
66
+ name: "NiceName",
67
+ }),
68
+ ).throw("Key is invalid");
69
+
70
+ expect(() =>
71
+ SSHPublicKeyValue.getData({
72
+ key: "",
73
+ name: "NiceName",
74
+ }),
75
+ ).throw("Key is invalid");
76
+ }
77
+
78
+ @test public testGetFingerprint() {
79
+ const key = this.key;
80
+ expect(
81
+ SSHPublicKeyValue.getFingerprint({
82
+ key,
83
+ name: "NiceName",
84
+ }),
85
+ ).to.equal("ykjP/b5aqoa3envmXzWpPMCGgEFMu3QvubfSTNrJCMA=");
86
+ }
87
+
88
+ @test public testGetFingerprintWithIncorrectPublicKey() {
89
+ expect(() =>
90
+ SSHPublicKeyValue.getFingerprint({
91
+ key: "Hello World",
92
+ name: "NiceName",
93
+ }),
94
+ ).to.throw("Key is invalid");
95
+ }
96
+ }
97
+ module.exports = new TestSSHPublicKeyValue(); // Only to circumvent no usage warning :-/