@gitpod/gitpod-protocol 0.1.5-server-vscode-ouath2.18 → 0.1.5-server-vscode-oauth2.11
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.
- package/lib/accounting-protocol.js +6 -6
- package/lib/accounting-protocol.js.map +1 -1
- package/lib/admin-protocol.d.ts +8 -2
- package/lib/admin-protocol.d.ts.map +1 -1
- package/lib/admin-protocol.js +2 -13
- package/lib/admin-protocol.js.map +1 -1
- package/lib/analytics.d.ts +12 -1
- package/lib/analytics.d.ts.map +1 -1
- package/lib/context-url.js +4 -4
- package/lib/context-url.js.map +1 -1
- package/lib/context-url.spec.js +45 -48
- package/lib/context-url.spec.js.map +1 -1
- package/lib/email-protocol.js +3 -3
- package/lib/email-protocol.js.map +1 -1
- package/lib/encryption/container-module.js +4 -4
- package/lib/encryption/container-module.js.map +1 -1
- package/lib/encryption/encryption-engine.js +19 -20
- package/lib/encryption/encryption-engine.js.map +1 -1
- package/lib/encryption/encryption-engine.spec.js +29 -36
- package/lib/encryption/encryption-engine.spec.js.map +1 -1
- package/lib/encryption/encryption-service.js +29 -43
- package/lib/encryption/encryption-service.js.map +1 -1
- package/lib/encryption/key-provider.js +25 -30
- package/lib/encryption/key-provider.js.map +1 -1
- package/lib/env.d.ts +0 -1
- package/lib/env.d.ts.map +1 -1
- package/lib/env.js +12 -14
- package/lib/env.js.map +1 -1
- package/lib/gitpod-file-parser.js +25 -41
- package/lib/gitpod-file-parser.js.map +1 -1
- package/lib/gitpod-file-parser.spec.js +116 -116
- package/lib/gitpod-file-parser.spec.js.map +1 -1
- package/lib/gitpod-service.d.ts +12 -2
- package/lib/gitpod-service.d.ts.map +1 -1
- package/lib/gitpod-service.js +148 -294
- package/lib/gitpod-service.js.map +1 -1
- package/lib/messaging/browser/connection.d.ts +3 -3
- package/lib/messaging/browser/connection.d.ts.map +1 -1
- package/lib/messaging/browser/connection.js +172 -35
- package/lib/messaging/browser/connection.js.map +1 -1
- package/lib/messaging/browser/window-connection.js +34 -54
- package/lib/messaging/browser/window-connection.js.map +1 -1
- package/lib/messaging/client-call-metrics.js +17 -18
- package/lib/messaging/client-call-metrics.js.map +1 -1
- package/lib/messaging/connection-error-handler.js +11 -23
- package/lib/messaging/connection-error-handler.js.map +1 -1
- package/lib/messaging/handler.d.ts +10 -0
- package/lib/messaging/handler.d.ts.map +1 -1
- package/lib/messaging/node/connection.js +20 -20
- package/lib/messaging/node/connection.js.map +1 -1
- package/lib/messaging/proxy-factory.d.ts +2 -0
- package/lib/messaging/proxy-factory.d.ts.map +1 -1
- package/lib/messaging/proxy-factory.js +73 -160
- package/lib/messaging/proxy-factory.js.map +1 -1
- package/lib/permission.d.ts +1 -2
- package/lib/permission.d.ts.map +1 -1
- package/lib/permission.js +12 -13
- package/lib/permission.js.map +1 -1
- package/lib/plans.js +38 -57
- package/lib/plans.js.map +1 -1
- package/lib/protocol.js +44 -114
- package/lib/protocol.js.map +1 -1
- package/lib/team-subscription-protocol.js +11 -11
- package/lib/team-subscription-protocol.js.map +1 -1
- package/lib/teams-projects-protocol.d.ts +3 -1
- package/lib/teams-projects-protocol.d.ts.map +1 -1
- package/lib/teams-projects-protocol.js +4 -15
- package/lib/teams-projects-protocol.js.map +1 -1
- package/lib/util/analytics.d.ts.map +1 -1
- package/lib/util/analytics.js +35 -26
- package/lib/util/analytics.js.map +1 -1
- package/lib/util/async-iterator.js +55 -133
- package/lib/util/async-iterator.js.map +1 -1
- package/lib/util/cancelable.js +17 -59
- package/lib/util/cancelable.js.map +1 -1
- package/lib/util/date-time.js +8 -8
- package/lib/util/date-time.js.map +1 -1
- package/lib/util/deferred.js +10 -12
- package/lib/util/deferred.js.map +1 -1
- package/lib/util/disposable.js +26 -39
- package/lib/util/disposable.js.map +1 -1
- package/lib/util/event.js +58 -74
- package/lib/util/event.js.map +1 -1
- package/lib/util/garbage-collected-cache.js +22 -46
- package/lib/util/garbage-collected-cache.js.map +1 -1
- package/lib/util/generate-workspace-id.js +11 -67
- package/lib/util/generate-workspace-id.js.map +1 -1
- package/lib/util/generate-workspace-id.spec.js +34 -79
- package/lib/util/generate-workspace-id.spec.js.map +1 -1
- package/lib/util/gitpod-cookie.d.ts +20 -0
- package/lib/util/gitpod-cookie.d.ts.map +1 -0
- package/lib/util/gitpod-cookie.js +44 -0
- package/lib/util/gitpod-cookie.js.map +1 -0
- package/lib/util/gitpod-host-url.js +93 -103
- package/lib/util/gitpod-host-url.js.map +1 -1
- package/lib/util/gitpod-host-url.spec.js +87 -135
- package/lib/util/gitpod-host-url.spec.js.map +1 -1
- package/lib/util/grpc.js +3 -3
- package/lib/util/grpc.js.map +1 -1
- package/lib/util/logging.d.ts.map +1 -1
- package/lib/util/logging.js +68 -109
- package/lib/util/logging.js.map +1 -1
- package/lib/util/make-link.js +2 -2
- package/lib/util/make-link.js.map +1 -1
- package/lib/util/parse-workspace-id.d.ts +10 -0
- package/lib/util/parse-workspace-id.d.ts.map +1 -1
- package/lib/util/parse-workspace-id.js +31 -7
- package/lib/util/parse-workspace-id.js.map +1 -1
- package/lib/util/parse-workspace-id.spec.d.ts +4 -0
- package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
- package/lib/util/parse-workspace-id.spec.js +123 -84
- package/lib/util/parse-workspace-id.spec.js.map +1 -1
- package/lib/util/queue.js +16 -55
- package/lib/util/queue.js.map +1 -1
- package/lib/util/queue.spec.js +144 -288
- package/lib/util/queue.spec.js.map +1 -1
- package/lib/util/repeater.js +35 -88
- package/lib/util/repeater.js.map +1 -1
- package/lib/util/safe-promise.js +9 -12
- package/lib/util/safe-promise.js.map +1 -1
- package/lib/util/semaphore.js +15 -46
- package/lib/util/semaphore.js.map +1 -1
- package/lib/util/skip-if.js +6 -6
- package/lib/util/skip-if.js.map +1 -1
- package/lib/util/timeutil.js +16 -16
- package/lib/util/timeutil.js.map +1 -1
- package/lib/util/timeutil.spec.js +21 -24
- package/lib/util/timeutil.spec.js.map +1 -1
- package/lib/util/tracing.js +43 -47
- package/lib/util/tracing.js.map +1 -1
- package/lib/util/workspace-port-authentication.js +2 -2
- package/lib/util/workspace-port-authentication.js.map +1 -1
- package/lib/workspace-cluster.d.ts +11 -1
- package/lib/workspace-cluster.d.ts.map +1 -1
- package/lib/workspace-cluster.js +3 -3
- package/lib/workspace-cluster.js.map +1 -1
- package/lib/workspace-instance.d.ts +2 -0
- package/lib/workspace-instance.d.ts.map +1 -1
- package/package.json +3 -1
- package/pkg-yarn.lock +2 -1
- package/src/admin-protocol.ts +9 -3
- package/src/analytics.ts +14 -1
- package/src/env.ts +0 -1
- package/src/gitpod-service.ts +13 -2
- package/src/messaging/browser/connection.ts +176 -10
- package/src/messaging/handler.ts +12 -0
- package/src/messaging/proxy-factory.ts +10 -4
- package/src/permission.ts +0 -1
- package/src/teams-projects-protocol.ts +3 -1
- package/src/util/analytics.ts +17 -1
- package/src/util/gitpod-cookie.ts +39 -0
- package/src/util/grpc.ts +3 -3
- package/src/util/logging.ts +33 -20
- package/src/util/parse-workspace-id.spec.ts +21 -1
- package/src/util/parse-workspace-id.ts +32 -6
- package/src/workspace-cluster.ts +8 -1
- package/src/workspace-instance.ts +6 -0
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"ajv": "^6.5.4",
|
|
4
4
|
"analytics-node": "^4.0.1",
|
|
5
|
+
"cookie": "^0.4.1",
|
|
5
6
|
"inversify": "^5.0.1",
|
|
6
7
|
"jaeger-client": "3.17.2",
|
|
7
8
|
"js-yaml": "^3.10.0",
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
"devDependencies": {
|
|
21
22
|
"@types/analytics-node": "^3.1.4",
|
|
22
23
|
"@types/chai-subset": "^1.3.1",
|
|
24
|
+
"@types/cookie": "^0.4.1",
|
|
23
25
|
"@types/js-yaml": "^3.10.1",
|
|
24
26
|
"@types/mocha": "^5.2.7",
|
|
25
27
|
"@types/random-number-csprng": "^1.0.0",
|
|
@@ -52,5 +54,5 @@
|
|
|
52
54
|
"watch": "leeway exec --package .:lib --transitive-dependencies --filter-type yarn --components --parallel -- tsc -w --preserveWatchOutput"
|
|
53
55
|
},
|
|
54
56
|
"types": "./lib/index.d.ts",
|
|
55
|
-
"version": "0.1.5-server-vscode-
|
|
57
|
+
"version": "0.1.5-server-vscode-oauth2.11"
|
|
56
58
|
}
|
package/pkg-yarn.lock
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
"@gitpod/gitpod-protocol@0.1.5":
|
|
6
6
|
version "0.1.5"
|
|
7
|
-
resolved "file:///tmp/cache/
|
|
7
|
+
resolved "file:///tmp/cache/e6ff35b3336fea858846625b6cfeaf6534895151.tar.gz"
|
|
8
8
|
dependencies:
|
|
9
9
|
ajv "^6.5.4"
|
|
10
10
|
analytics-node "^4.0.1"
|
|
11
|
+
cookie "^0.4.1"
|
|
11
12
|
inversify "^5.0.1"
|
|
12
13
|
jaeger-client "3.17.2"
|
|
13
14
|
js-yaml "^3.10.0"
|
package/src/admin-protocol.ts
CHANGED
|
@@ -94,6 +94,12 @@ export namespace WorkspaceAndInstance {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
export
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
export type AdminGetWorkspacesRequest = AdminGetListRequest<WorkspaceAndInstance> & AdminGetWorkspacesQuery;
|
|
98
|
+
/** The fields are meant to be used either OR (not combined) */
|
|
99
|
+
export type AdminGetWorkspacesQuery = {
|
|
100
|
+
/** we use this field in case we have a UUIDv4 and don't know whether it's an (old) workspace or instance id */
|
|
101
|
+
instanceIdOrWorkspaceId?: string;
|
|
102
|
+
instanceId?: string;
|
|
103
|
+
workspaceId?: string;
|
|
104
|
+
ownerId?: string;
|
|
105
|
+
};
|
package/src/analytics.ts
CHANGED
|
@@ -28,7 +28,18 @@ export type TrackMessage = Message & Identity & {
|
|
|
28
28
|
context?: any;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
export type
|
|
31
|
+
export type PageMessage = Message & Identity & {
|
|
32
|
+
properties?: any;
|
|
33
|
+
timestamp?: Date;
|
|
34
|
+
context?: any;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type RemoteTrackMessage = Omit<TrackMessage, "timestamp" | "userId" | "anonymousId"> & {
|
|
38
|
+
anonymousId?: string | number;
|
|
39
|
+
};
|
|
40
|
+
export type RemotePageMessage = Omit<PageMessage, "timestamp" | "userId"> & {
|
|
41
|
+
anonymousId?: string | number;
|
|
42
|
+
};
|
|
32
43
|
|
|
33
44
|
export interface IAnalyticsWriter {
|
|
34
45
|
|
|
@@ -36,4 +47,6 @@ export interface IAnalyticsWriter {
|
|
|
36
47
|
|
|
37
48
|
track(msg: TrackMessage): void;
|
|
38
49
|
|
|
50
|
+
page(msg: PageMessage): void;
|
|
51
|
+
|
|
39
52
|
}
|
package/src/env.ts
CHANGED
|
@@ -25,7 +25,6 @@ export function translateLegacyStagename(kubeStage: string): KubeStage {
|
|
|
25
25
|
@injectable()
|
|
26
26
|
export abstract class AbstractComponentEnv {
|
|
27
27
|
readonly kubeStage: KubeStage = getEnvVarParsed('KUBE_STAGE', translateLegacyStagename);
|
|
28
|
-
readonly kubeNamespace: string = getEnvVar('KUBE_NAMESPACE');
|
|
29
28
|
|
|
30
29
|
readonly installationLongname: string = getEnvVar("GITPOD_INSTALLATION_LONGNAME")
|
|
31
30
|
readonly installationShortname: string = getEnvVar("GITPOD_INSTALLATION_SHORTNAME")
|
package/src/gitpod-service.ts
CHANGED
|
@@ -28,7 +28,7 @@ import { Emitter } from './util/event';
|
|
|
28
28
|
import { AccountStatement, CreditAlert } from './accounting-protocol';
|
|
29
29
|
import { GithubUpgradeURL, PlanCoupon } from './payment-protocol';
|
|
30
30
|
import { TeamSubscription, TeamSubscriptionSlot, TeamSubscriptionSlotResolved } from './team-subscription-protocol';
|
|
31
|
-
import { RemoteTrackMessage } from './analytics';
|
|
31
|
+
import { RemotePageMessage, RemoteTrackMessage } from './analytics';
|
|
32
32
|
|
|
33
33
|
export interface GitpodClient {
|
|
34
34
|
onInstanceUpdate(instance: WorkspaceInstance): void;
|
|
@@ -123,6 +123,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
|
|
|
123
123
|
removeTeamMember(teamId: string, userId: string): Promise<void>;
|
|
124
124
|
getGenericInvite(teamId: string): Promise<TeamMembershipInvite>;
|
|
125
125
|
resetGenericInvite(inviteId: string): Promise<TeamMembershipInvite>;
|
|
126
|
+
deleteTeam(teamId: string, userId: string): Promise<void>;
|
|
126
127
|
|
|
127
128
|
// Projects
|
|
128
129
|
getProviderRepositoriesForUser(params: GetProviderRepositoriesParams): Promise<ProviderRepository[]>;
|
|
@@ -133,6 +134,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
|
|
|
133
134
|
getProjectOverview(projectId: string): Promise<Project.Overview | undefined>;
|
|
134
135
|
findPrebuilds(params: FindPrebuildsParams): Promise<PrebuildWithStatus[]>;
|
|
135
136
|
triggerPrebuild(projectId: string, branchName: string | null): Promise<StartPrebuildResult>;
|
|
137
|
+
cancelPrebuild(projectId: string, prebuildId: string): Promise<void>;
|
|
136
138
|
setProjectConfiguration(projectId: string, configString: string): Promise<void>;
|
|
137
139
|
fetchProjectRepositoryConfiguration(projectId: string): Promise<string | undefined>;
|
|
138
140
|
guessProjectConfiguration(projectId: string): Promise<string | undefined>;
|
|
@@ -227,6 +229,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
|
|
|
227
229
|
* Analytics
|
|
228
230
|
*/
|
|
229
231
|
trackEvent(event: RemoteTrackMessage): Promise<void>;
|
|
232
|
+
trackLocation(event: RemotePageMessage): Promise<void>;
|
|
230
233
|
}
|
|
231
234
|
|
|
232
235
|
export interface CreateProjectParams {
|
|
@@ -262,6 +265,13 @@ export interface ProviderRepository {
|
|
|
262
265
|
inUse?: boolean;
|
|
263
266
|
}
|
|
264
267
|
|
|
268
|
+
export interface ClientHeaderFields{
|
|
269
|
+
ip?:string;
|
|
270
|
+
userAgent?:string;
|
|
271
|
+
dnt?:number;
|
|
272
|
+
clientRegion?:string;
|
|
273
|
+
}
|
|
274
|
+
|
|
265
275
|
export const WorkspaceTimeoutValues = ["30m", "60m", "180m"] as const;
|
|
266
276
|
|
|
267
277
|
export const createServiceMock = function <C extends GitpodClient, S extends GitpodServer>(methods: Partial<JsonRpcProxy<S>>): GitpodServiceImpl<C, S> {
|
|
@@ -305,7 +315,8 @@ export namespace GitpodServer {
|
|
|
305
315
|
limit?: number;
|
|
306
316
|
searchString?: string;
|
|
307
317
|
pinnedOnly?: boolean;
|
|
308
|
-
projectId?: string;
|
|
318
|
+
projectId?: string | string[];
|
|
319
|
+
includeWithoutProject?: boolean;
|
|
309
320
|
}
|
|
310
321
|
export interface GetAccountStatementOptions {
|
|
311
322
|
date?: string;
|
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { Logger, ConsoleLogger, toSocket, IWebSocket } from "vscode-ws-jsonrpc";
|
|
9
|
+
import { createMessageConnection } from "vscode-jsonrpc";
|
|
10
|
+
import { AbstractMessageWriter } from "vscode-jsonrpc/lib/messageWriter";
|
|
11
|
+
import { AbstractMessageReader } from "vscode-jsonrpc/lib/messageReader";
|
|
9
12
|
import { JsonRpcProxyFactory, JsonRpcProxy } from "../proxy-factory";
|
|
10
|
-
import { ConnectionHandler } from "../handler";
|
|
11
|
-
import ReconnectingWebSocket from 'reconnecting-websocket';
|
|
13
|
+
import { ConnectionEventHandler, ConnectionHandler } from "../handler";
|
|
14
|
+
import ReconnectingWebSocket, { Event } from 'reconnecting-websocket';
|
|
12
15
|
|
|
13
16
|
export interface WebSocketOptions {
|
|
14
17
|
onerror?: (event: Event) => void;
|
|
@@ -29,7 +32,10 @@ export class WebSocketConnectionProvider {
|
|
|
29
32
|
const startListening = (path: string) => {
|
|
30
33
|
const socket = this.listen({
|
|
31
34
|
path,
|
|
32
|
-
onConnection: c => factory.listen(c)
|
|
35
|
+
onConnection: c => factory.listen(c),
|
|
36
|
+
}, {
|
|
37
|
+
onTransportDidClose: () => factory.fireConnectionClosed(),
|
|
38
|
+
onTransportDidOpen: () => factory.fireConnectionOpened(),
|
|
33
39
|
},
|
|
34
40
|
options
|
|
35
41
|
);
|
|
@@ -49,7 +55,7 @@ export class WebSocketConnectionProvider {
|
|
|
49
55
|
/**
|
|
50
56
|
* Install a connection handler for the given path.
|
|
51
57
|
*/
|
|
52
|
-
listen(handler: ConnectionHandler, options?: WebSocketOptions): WebSocket {
|
|
58
|
+
listen(handler: ConnectionHandler, eventHandler: ConnectionEventHandler, options?: WebSocketOptions): WebSocket {
|
|
53
59
|
const url = handler.path;
|
|
54
60
|
const webSocket = this.createWebSocket(url);
|
|
55
61
|
|
|
@@ -64,11 +70,12 @@ export class WebSocketConnectionProvider {
|
|
|
64
70
|
logger.error(JSON.stringify(error));
|
|
65
71
|
});
|
|
66
72
|
}
|
|
67
|
-
doListen(
|
|
68
|
-
webSocket,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
doListen(
|
|
74
|
+
webSocket as any as ReconnectingWebSocket,
|
|
75
|
+
handler,
|
|
76
|
+
eventHandler,
|
|
77
|
+
logger,
|
|
78
|
+
);
|
|
72
79
|
return webSocket;
|
|
73
80
|
}
|
|
74
81
|
|
|
@@ -91,3 +98,162 @@ export class WebSocketConnectionProvider {
|
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
}
|
|
101
|
+
|
|
102
|
+
// The following was extracted from vscode-ws-jsonrpc to make these changes:
|
|
103
|
+
// - switch from WebSocket to ReconnectingWebSocket
|
|
104
|
+
// - webSocket.onopen: making sure it's only ever called once so we're re-using MessageConnection
|
|
105
|
+
// - WebSocketMessageWriter: buffer and re-try messages instead of throwing an error immidiately
|
|
106
|
+
// - WebSocketMessageReader: don't close MessageConnection on 'socket.onclose'
|
|
107
|
+
function doListen(resocket: ReconnectingWebSocket, handler: ConnectionHandler, eventHandler: ConnectionEventHandler, logger: Logger) {
|
|
108
|
+
resocket.addEventListener("close", () => eventHandler.onTransportDidClose());
|
|
109
|
+
|
|
110
|
+
let alreadyOpened = false;
|
|
111
|
+
resocket.onopen = () => {
|
|
112
|
+
// trigerr "open" every time we re-open the underlying websocket
|
|
113
|
+
eventHandler.onTransportDidOpen();
|
|
114
|
+
|
|
115
|
+
// make sure we're only ever creating one MessageConnection, irregardless of how many times we have to re-open the underlying (reconnecting) websocket
|
|
116
|
+
if (alreadyOpened) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
alreadyOpened = true;
|
|
120
|
+
|
|
121
|
+
const connection = createWebSocketConnection(resocket, logger);
|
|
122
|
+
handler.onConnection(connection);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function createWebSocketConnection(resocket: ReconnectingWebSocket, logger: Logger) {
|
|
127
|
+
const socket = toSocket(resocket as any);
|
|
128
|
+
const messageReader = new NonClosingWebSocketMessageReader(socket);
|
|
129
|
+
const messageWriter = new BufferingWebSocketMessageWriter(resocket, logger);
|
|
130
|
+
const connection = createMessageConnection(messageReader, messageWriter, logger);
|
|
131
|
+
connection.onClose(() => connection.dispose());
|
|
132
|
+
return connection;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* This takes vscode-ws-jsonrpc/lib/socket/writer/WebSocketMessageWriter and adds a buffer
|
|
137
|
+
*/
|
|
138
|
+
class BufferingWebSocketMessageWriter extends AbstractMessageWriter {
|
|
139
|
+
protected readonly socket: ReconnectingWebSocket;
|
|
140
|
+
protected readonly logger: Logger;
|
|
141
|
+
protected errorCount: number = 0;
|
|
142
|
+
|
|
143
|
+
protected buffer: any[] = [];
|
|
144
|
+
|
|
145
|
+
constructor(socket: ReconnectingWebSocket, logger: Logger) {
|
|
146
|
+
super();
|
|
147
|
+
this.socket = socket;
|
|
148
|
+
this.logger = logger;
|
|
149
|
+
|
|
150
|
+
socket.addEventListener("open", (event: Event) => this.flushBuffer());
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
write(msg: any) {
|
|
154
|
+
if (this.socket.readyState !== ReconnectingWebSocket.OPEN) {
|
|
155
|
+
this.bufferMsg(msg);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
const content = JSON.stringify(msg);
|
|
161
|
+
this.socket.send(content);
|
|
162
|
+
} catch (e) {
|
|
163
|
+
this.errorCount++;
|
|
164
|
+
this.fireError(e, msg, this.errorCount);
|
|
165
|
+
|
|
166
|
+
this.bufferMsg(msg);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
protected flushBuffer() {
|
|
171
|
+
if (this.buffer.length === 0) {
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const buffer = [...this.buffer];
|
|
176
|
+
this.buffer = [];
|
|
177
|
+
for (const msg of buffer) {
|
|
178
|
+
this.write(msg);
|
|
179
|
+
}
|
|
180
|
+
//this.logger.info(`flushed buffer (${this.buffer.length})`)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
protected bufferMsg(msg: any) {
|
|
184
|
+
this.buffer.push(msg);
|
|
185
|
+
//this.logger.info(`buffered message (${this.buffer.length})`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* This takes vscode-ws-jsonrpc/lib/socket/reader/WebSocketMessageReader and removes the "onClose -> fireClose" connection
|
|
192
|
+
*/
|
|
193
|
+
class NonClosingWebSocketMessageReader extends AbstractMessageReader {
|
|
194
|
+
protected readonly socket: IWebSocket;
|
|
195
|
+
protected readonly events: any[] = [];
|
|
196
|
+
protected state: 'initial' | 'listening' | 'closed' = 'initial';
|
|
197
|
+
protected callback: (message: any) => void = () => {};
|
|
198
|
+
|
|
199
|
+
constructor(socket: IWebSocket) {
|
|
200
|
+
super();
|
|
201
|
+
this.socket = socket;
|
|
202
|
+
this.socket.onMessage(message => this.readMessage(message));
|
|
203
|
+
this.socket.onError(error => this.fireError(error));
|
|
204
|
+
this.socket.onClose((code, reason) => {
|
|
205
|
+
if (code !== 1000) {
|
|
206
|
+
const error = {
|
|
207
|
+
name: '' + code,
|
|
208
|
+
message: `Error during socket reconnect: code = ${code}, reason = ${reason}`
|
|
209
|
+
};
|
|
210
|
+
this.fireError(error);
|
|
211
|
+
}
|
|
212
|
+
// this.fireClose(); // <-- reason for this class to be copied over
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
listen(callback: (message: any) => void) {
|
|
216
|
+
if (this.state === 'initial') {
|
|
217
|
+
this.state = 'listening';
|
|
218
|
+
this.callback = callback;
|
|
219
|
+
while (this.events.length !== 0) {
|
|
220
|
+
const event = this.events.pop();
|
|
221
|
+
if (event.message) {
|
|
222
|
+
this.readMessage(event.message);
|
|
223
|
+
}
|
|
224
|
+
else if (event.error) {
|
|
225
|
+
this.fireError(event.error);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
this.fireClose();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
readMessage(message: any) {
|
|
234
|
+
if (this.state === 'initial') {
|
|
235
|
+
this.events.splice(0, 0, { message });
|
|
236
|
+
}
|
|
237
|
+
else if (this.state === 'listening') {
|
|
238
|
+
const data = JSON.parse(message);
|
|
239
|
+
this.callback(data);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
fireError(error: any) {
|
|
243
|
+
if (this.state === 'initial') {
|
|
244
|
+
this.events.splice(0, 0, { error });
|
|
245
|
+
}
|
|
246
|
+
else if (this.state === 'listening') {
|
|
247
|
+
super.fireError(error);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
fireClose() {
|
|
251
|
+
if (this.state === 'initial') {
|
|
252
|
+
this.events.splice(0, 0, {});
|
|
253
|
+
}
|
|
254
|
+
else if (this.state === 'listening') {
|
|
255
|
+
super.fireClose();
|
|
256
|
+
}
|
|
257
|
+
this.state = 'closed';
|
|
258
|
+
}
|
|
259
|
+
}
|
package/src/messaging/handler.ts
CHANGED
|
@@ -13,3 +13,15 @@ export interface ConnectionHandler {
|
|
|
13
13
|
readonly path: string;
|
|
14
14
|
onConnection(connection: MessageConnection, session?: object): void;
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
export interface ConnectionEventHandler {
|
|
18
|
+
/**
|
|
19
|
+
* Called when the transport underpinning the connection got closed
|
|
20
|
+
*/
|
|
21
|
+
onTransportDidClose(): void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Called when the transport underpinning the connection is (re-)opened
|
|
25
|
+
*/
|
|
26
|
+
onTransportDidOpen(): void;
|
|
27
|
+
}
|
|
@@ -105,13 +105,19 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
|
|
|
105
105
|
this.connectionPromiseResolve = resolve
|
|
106
106
|
);
|
|
107
107
|
this.connectionPromise.then(connection => {
|
|
108
|
-
connection.onClose(() =>
|
|
109
|
-
|
|
110
|
-
);
|
|
111
|
-
this.onDidOpenConnectionEmitter.fire(undefined);
|
|
108
|
+
connection.onClose(() => this.fireConnectionClosed());
|
|
109
|
+
this.fireConnectionOpened();
|
|
112
110
|
});
|
|
113
111
|
}
|
|
114
112
|
|
|
113
|
+
fireConnectionClosed() {
|
|
114
|
+
this.onDidCloseConnectionEmitter.fire(undefined)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
fireConnectionOpened() {
|
|
118
|
+
this.onDidOpenConnectionEmitter.fire(undefined);
|
|
119
|
+
}
|
|
120
|
+
|
|
115
121
|
/**
|
|
116
122
|
* Connect a MessageConnection to the factory.
|
|
117
123
|
*
|
package/src/permission.ts
CHANGED
|
@@ -16,7 +16,6 @@ export const Permissions = {
|
|
|
16
16
|
"admin-api": undefined,
|
|
17
17
|
"ide-settings": undefined,
|
|
18
18
|
"new-workspace-cluster": undefined,
|
|
19
|
-
"teams-and-projects": undefined,
|
|
20
19
|
};
|
|
21
20
|
export type PermissionName = keyof (typeof Permissions);
|
|
22
21
|
export const Roles = {"devops": undefined, "viewer": undefined, "admin": undefined };
|
|
@@ -57,6 +57,7 @@ export namespace Project {
|
|
|
57
57
|
export interface PrebuildWithStatus {
|
|
58
58
|
info: PrebuildInfo;
|
|
59
59
|
status: PrebuiltWorkspaceState;
|
|
60
|
+
error?: string;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
export interface PrebuildInfo {
|
|
@@ -91,9 +92,9 @@ export namespace PrebuildInfo {
|
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
export interface StartPrebuildResult {
|
|
95
|
+
prebuildId: string;
|
|
94
96
|
wsid: string;
|
|
95
97
|
done: boolean;
|
|
96
|
-
didFinish?: boolean;
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
export interface Team {
|
|
@@ -101,6 +102,7 @@ export interface Team {
|
|
|
101
102
|
name: string;
|
|
102
103
|
slug: string;
|
|
103
104
|
creationTime: string;
|
|
105
|
+
markedDeleted?: boolean;
|
|
104
106
|
/** This is a flag that triggers the HARD DELETION of this entity */
|
|
105
107
|
deleted?: boolean;
|
|
106
108
|
}
|
package/src/util/analytics.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import Analytics = require("analytics-node");
|
|
8
|
-
import { IAnalyticsWriter, IdentifyMessage, TrackMessage } from "../analytics";
|
|
8
|
+
import { IAnalyticsWriter, IdentifyMessage, TrackMessage, PageMessage } from "../analytics";
|
|
9
9
|
import { log } from './logging';
|
|
10
10
|
|
|
11
11
|
|
|
@@ -52,6 +52,18 @@ class SegmentAnalyticsWriter implements IAnalyticsWriter {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
page(msg: PageMessage) {
|
|
56
|
+
try{
|
|
57
|
+
this.analytics.page(msg, (err: Error) => {
|
|
58
|
+
if (err) {
|
|
59
|
+
log.warn("analytics.page failed", err);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
} catch (err) {
|
|
63
|
+
log.warn("analytics.page failed", err);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
}
|
|
56
68
|
|
|
57
69
|
class LogAnalyticsWriter implements IAnalyticsWriter {
|
|
@@ -62,10 +74,14 @@ class LogAnalyticsWriter implements IAnalyticsWriter {
|
|
|
62
74
|
track(msg: TrackMessage): void {
|
|
63
75
|
log.debug("analytics track", msg);
|
|
64
76
|
}
|
|
77
|
+
page(msg: PageMessage): void {
|
|
78
|
+
log.debug("analytics page", msg);
|
|
79
|
+
}
|
|
65
80
|
|
|
66
81
|
}
|
|
67
82
|
|
|
68
83
|
class NoAnalyticsWriter implements IAnalyticsWriter {
|
|
69
84
|
identify(msg: IdentifyMessage): void {}
|
|
70
85
|
track(msg: TrackMessage): void {}
|
|
86
|
+
page(msg: PageMessage): void {}
|
|
71
87
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2021 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
|
+
import * as cookie from 'cookie';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This cookie indicates whether the connected client is a Gitpod user (= "has logged in within the last year") or not.
|
|
11
|
+
* This is used by "gitpod.io" and "www.gitpod.io" to display different content/buttons.
|
|
12
|
+
*/
|
|
13
|
+
export const NAME = "gitpod-user";
|
|
14
|
+
export const VALUE = "true";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param domain The domain the Gitpod installation is installed onto
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
export function options(domain: string): cookie.CookieSerializeOptions {
|
|
21
|
+
// Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
|
|
22
|
+
return {
|
|
23
|
+
path: "/", // make sure we send the cookie to all sub-pages
|
|
24
|
+
httpOnly: false,
|
|
25
|
+
secure: false,
|
|
26
|
+
maxAge: 60 * 60 * 24 * 365, // 1 year
|
|
27
|
+
sameSite: "lax", // default: true. "Lax" needed to ensure we see cookies from users that neavigate to gitpod.io from external sites
|
|
28
|
+
domain: `.${domain}`, // explicilty include subdomains to not only cover "gitpod.io", but also "www.gitpod.io" or workspaces
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function generateCookie(domain: string): string {
|
|
33
|
+
return cookie.serialize(NAME, VALUE, options(domain));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function isPresent(cookies: string): boolean {
|
|
37
|
+
// needs to match the old (gitpod-user=loggedIn) and new (gitpod-user=true) values to ensure a smooth transition during rollout.
|
|
38
|
+
return !!cookies.match(`${NAME}=`);
|
|
39
|
+
};
|
package/src/util/grpc.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export const defaultGRPCOptions = {
|
|
8
|
-
"grpc.keepalive_timeout_ms":
|
|
9
|
-
"grpc.keepalive_time_ms":
|
|
10
|
-
"grpc.http2.min_time_between_pings_ms":
|
|
8
|
+
"grpc.keepalive_timeout_ms": 10000,
|
|
9
|
+
"grpc.keepalive_time_ms": 60000,
|
|
10
|
+
"grpc.http2.min_time_between_pings_ms": 10000,
|
|
11
11
|
"grpc.keepalive_permit_without_calls": 1,
|
|
12
12
|
"grpc-node.max_session_memory": 50,
|
|
13
13
|
"grpc.max_reconnect_backoff_ms": 5000,
|
package/src/util/logging.ts
CHANGED
|
@@ -107,24 +107,32 @@ export namespace log {
|
|
|
107
107
|
export function setLogLevel(logLevel: LogrusLogLevel | undefined) {
|
|
108
108
|
jsonLogging = true;
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
console.warn = setLog(warnLog, "warning");
|
|
123
|
-
console.info = setLog(infoLog, "info");
|
|
124
|
-
console.debug = setLog(debugLog, "debug");
|
|
110
|
+
console.error = function (...args: any[]): void {
|
|
111
|
+
errorLog(true, args);
|
|
112
|
+
}
|
|
113
|
+
console.warn = function (...args: any[]): void {
|
|
114
|
+
warnLog(true, args);
|
|
115
|
+
}
|
|
116
|
+
console.info = function (...args: any[]): void {
|
|
117
|
+
infoLog(true, args);
|
|
118
|
+
}
|
|
119
|
+
console.debug = function (...args: any[]): void {
|
|
120
|
+
debugLog(true, args);
|
|
121
|
+
}
|
|
125
122
|
|
|
126
123
|
console.log = console.info;
|
|
127
124
|
// FIXME wrap also other console methods (e.g. trace())
|
|
125
|
+
|
|
126
|
+
// set/unset log functions based on loglevel so we only have to evaluate once, not every call
|
|
127
|
+
const noop = () => {};
|
|
128
|
+
const setLog = (logFunc: DoLogFunction, funcLevel: LogrusLogLevel): DoLogFunction => {
|
|
129
|
+
return LogrusLogLevel.isGreatherOrEqual(funcLevel, logLevel) ? logFunc : noop;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
errorLog = setLog(doErrorLog, "error");
|
|
133
|
+
warnLog = setLog(doWarnLog, "warning");
|
|
134
|
+
infoLog = setLog(doInfoLog, "info");
|
|
135
|
+
debugLog = setLog(doDebugLog, "debug");
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
export function resetToDefaultLogging(): void {
|
|
@@ -142,19 +150,25 @@ export namespace log {
|
|
|
142
150
|
}
|
|
143
151
|
}
|
|
144
152
|
|
|
145
|
-
|
|
153
|
+
type DoLogFunction = (calledViaConsole: boolean, args: any[]) => void;
|
|
154
|
+
|
|
155
|
+
let errorLog = doErrorLog;
|
|
156
|
+
function doErrorLog(calledViaConsole: boolean, args: any[]): void {
|
|
146
157
|
doLog(calledViaConsole, errorConsoleLog, 'ERROR', args);
|
|
147
158
|
}
|
|
148
159
|
|
|
149
|
-
|
|
160
|
+
let warnLog = doWarnLog;
|
|
161
|
+
function doWarnLog(calledViaConsole: boolean, args: any[]): void {
|
|
150
162
|
doLog(calledViaConsole, warnConsoleLog, 'WARNING', args);
|
|
151
163
|
}
|
|
152
164
|
|
|
153
|
-
|
|
165
|
+
let infoLog = doInfoLog;
|
|
166
|
+
function doInfoLog(calledViaConsole: boolean, args: any[]): void {
|
|
154
167
|
doLog(calledViaConsole, infoConsoleLog, 'INFO', args);
|
|
155
168
|
}
|
|
156
169
|
|
|
157
|
-
|
|
170
|
+
let debugLog = doDebugLog;
|
|
171
|
+
function doDebugLog(calledViaConsole: boolean, args: any[]): void {
|
|
158
172
|
doLog(calledViaConsole, debugConsoleLog, 'DEBUG', args);
|
|
159
173
|
}
|
|
160
174
|
|
|
@@ -294,7 +308,6 @@ function makeLogItem(severity: GoogleLogSeverity, context: LogContext | undefine
|
|
|
294
308
|
severity,
|
|
295
309
|
time: new Date().toISOString(),
|
|
296
310
|
environment: process.env.KUBE_STAGE,
|
|
297
|
-
region: process.env.GITPOD_REGION,
|
|
298
311
|
context,
|
|
299
312
|
message,
|
|
300
313
|
error,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import * as chai from 'chai';
|
|
8
8
|
import { suite, test } from 'mocha-typescript';
|
|
9
|
-
import { parseWorkspaceIdFromHostname } from './parse-workspace-id';
|
|
9
|
+
import { matchesInstanceIdOrLegacyWorkspaceIdExactly, matchesNewWorkspaceIdExactly, parseWorkspaceIdFromHostname } from './parse-workspace-id';
|
|
10
10
|
const expect = chai.expect;
|
|
11
11
|
|
|
12
12
|
@suite
|
|
@@ -52,5 +52,25 @@ export class ParseWorkspaceIdTest {
|
|
|
52
52
|
const actual = parseWorkspaceIdFromHostname("webview-3000-ca81a50f-09d7-465c-acd9-264a747d5351.ws-eu01.some.subdomain.somehost.com");
|
|
53
53
|
expect(actual).to.equal("ca81a50f-09d7-465c-acd9-264a747d5351");
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
// match - instance ID
|
|
57
|
+
@test public matchesInstanceIdOrLegacyWorkspaceIdExactly_positive() {
|
|
58
|
+
const actual = matchesInstanceIdOrLegacyWorkspaceIdExactly("b7e0eaf8-ec73-44ec-81ea-04859263b656");
|
|
59
|
+
expect(actual).to.be.true;
|
|
60
|
+
}
|
|
61
|
+
@test public matchesInstanceIdOrLegacyWorkspaceIdExactly_negative() {
|
|
62
|
+
const actual = matchesInstanceIdOrLegacyWorkspaceIdExactly("b7e0eaf8-ec73-44ec-81a-04859263b656");
|
|
63
|
+
expect(actual).to.be.false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// match - new workspace ID
|
|
67
|
+
@test public matchesWorkspaceIdExactly_new_positive() {
|
|
68
|
+
const actual = matchesNewWorkspaceIdExactly("moccasin-ferret-155799b3");
|
|
69
|
+
expect(actual).to.be.true;
|
|
70
|
+
}
|
|
71
|
+
@test public matchesWorkspaceIdExactly_new_negative() {
|
|
72
|
+
const actual = matchesNewWorkspaceIdExactly("moccasin-ferret-15599b3");
|
|
73
|
+
expect(actual).to.be.false;
|
|
74
|
+
}
|
|
55
75
|
}
|
|
56
76
|
module.exports = new ParseWorkspaceIdTest()
|