Skip to content

Commit 5777c75

Browse files
committed
[server] WorkspaceService.getOwnerToken + .getIDECredentials
1 parent 30a9453 commit 5777c75

File tree

4 files changed

+78
-18
lines changed

4 files changed

+78
-18
lines changed

components/server/src/test/expect-utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ export async function expectError(errorCode: ErrorCode, code: Promise<any> | (()
1111
const msg = "expected error: " + errorCode + (message ? " - " + message : "");
1212
try {
1313
await (code instanceof Function ? code() : code);
14-
expect.fail(msg);
14+
expect.fail(msg + " - succeeded");
1515
} catch (err) {
1616
if (!ApplicationError.hasErrorCode(err)) {
1717
throw err;
1818
}
19-
expect(err && ApplicationError.hasErrorCode(err) && err.code, msg).to.equal(errorCode);
19+
const actual = err && ApplicationError.hasErrorCode(err) && err.code;
20+
expect(actual, msg + " - got: " + actual).to.equal(errorCode);
2021
}
2122
}

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
884884
traceAPIParams(ctx, { workspaceId });
885885
traceWI(ctx, { workspaceId });
886886

887-
await this.checkAndBlockUser("getOwnerToken");
887+
const user = await this.checkAndBlockUser("getOwnerToken");
888888

889889
const workspace = await this.workspaceDb.trace(ctx).findById(workspaceId);
890890
if (!workspace) {
@@ -895,11 +895,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
895895
const latestInstance = await this.workspaceDb.trace(ctx).findCurrentInstance(workspaceId);
896896
await this.guardAccess({ kind: "workspaceInstance", subject: latestInstance, workspace }, "get");
897897

898-
const ownerToken = latestInstance?.status.ownerToken;
899-
if (!ownerToken) {
900-
throw new Error("owner token not found");
901-
}
902-
return ownerToken;
898+
return await this.workspaceService.getOwnerToken(user.id, workspaceId);
903899
}
904900

905901
public async getIDECredentials(ctx: TraceContext, workspaceId: string): Promise<string> {
@@ -910,15 +906,8 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
910906

911907
const workspace = await this.workspaceService.getWorkspace(user.id, workspaceId);
912908
await this.guardAccess({ kind: "workspace", subject: workspace }, "get");
913-
if (workspace.config.ideCredentials) {
914-
return workspace.config.ideCredentials;
915-
}
916-
return this.workspaceDb.trace(ctx).transaction(async (db) => {
917-
const ws = await this.workspaceService.getWorkspace(user.id, workspaceId);
918-
ws.config.ideCredentials = crypto.randomBytes(32).toString("base64");
919-
await db.store(ws);
920-
return ws.config.ideCredentials;
921-
});
909+
910+
return await this.workspaceService.getIDECredentials(user.id, workspaceId);
922911
}
923912

924913
public async startWorkspace(

components/server/src/workspace/workspace-service.spec.db.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,37 @@ describe("WorkspaceService", async () => {
9898
await expectError(ErrorCodes.NOT_FOUND, () => svc.getWorkspace(stranger.id, ws.id));
9999
});
100100

101+
it("should getOwnerToken", async () => {
102+
const svc = container.get(WorkspaceService);
103+
const ws = await createTestWorkspace(svc, org, owner, project);
104+
105+
await expectError(
106+
ErrorCodes.NOT_FOUND,
107+
() => svc.getOwnerToken(owner.id, ws.id),
108+
"NOT_FOUND for non-running workspace",
109+
);
110+
111+
await expectError(
112+
ErrorCodes.NOT_FOUND,
113+
() => svc.getOwnerToken(stranger.id, ws.id),
114+
"NOT_FOUND if stranger asks for the owner token",
115+
);
116+
});
117+
118+
it("should getIDECredentials", async () => {
119+
const svc = container.get(WorkspaceService);
120+
const ws = await createTestWorkspace(svc, org, owner, project);
121+
122+
const ideCredentials = await svc.getIDECredentials(owner.id, ws.id);
123+
expect(ideCredentials, "IDE credentials should be present").to.not.be.undefined;
124+
125+
await expectError(
126+
ErrorCodes.NOT_FOUND,
127+
() => svc.getIDECredentials(stranger.id, ws.id),
128+
"NOT_FOUND if stranger asks for the IDE credentials",
129+
);
130+
});
131+
101132
it("should stopWorkspace", async () => {
102133
const svc = container.get(WorkspaceService);
103134
const ws = await createTestWorkspace(svc, org, owner, project);

components/server/src/workspace/workspace-service.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { WorkspaceFactory } from "./workspace-factory";
1414
import { StopWorkspacePolicy } from "@gitpod/ws-manager/lib";
1515
import { WorkspaceStarter } from "./workspace-starter";
1616
import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
17+
import * as crypto from "crypto";
1718

1819
@injectable()
1920
export class WorkspaceService {
@@ -59,9 +60,14 @@ export class WorkspaceService {
5960
}
6061

6162
async getWorkspace(userId: string, workspaceId: string): Promise<Workspace> {
63+
return this.doGetWorkspace(userId, workspaceId);
64+
}
65+
66+
// Internal method for allowing for additional DBs to be passed in
67+
private async doGetWorkspace(userId: string, workspaceId: string, db: WorkspaceDB = this.db): Promise<Workspace> {
6268
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId);
6369

64-
const workspace = await this.db.findById(workspaceId);
70+
const workspace = await db.findById(workspaceId);
6571
// TODO(gpl) We might want to add || !!workspace.softDeleted here in the future, but we were unsure how that would affect existing clients
6672
// In order to reduce risk, we leave it for a future changeset.
6773
if (!workspace || workspace.deleted) {
@@ -70,6 +76,39 @@ export class WorkspaceService {
7076
return workspace;
7177
}
7278

79+
async getOwnerToken(userId: string, workspaceId: string): Promise<string> {
80+
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId);
81+
82+
// Check: is deleted?
83+
await this.getWorkspace(userId, workspaceId);
84+
85+
const latestInstance = await this.db.findCurrentInstance(workspaceId);
86+
const ownerToken = latestInstance?.status.ownerToken;
87+
if (!ownerToken) {
88+
throw new ApplicationError(ErrorCodes.NOT_FOUND, "owner token not found");
89+
}
90+
return ownerToken;
91+
}
92+
93+
async getIDECredentials(userId: string, workspaceId: string): Promise<string> {
94+
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId);
95+
96+
const ws = await this.getWorkspace(userId, workspaceId);
97+
if (ws.config.ideCredentials) {
98+
return ws.config.ideCredentials;
99+
}
100+
101+
return this.db.transaction(async (db) => {
102+
const ws = await this.doGetWorkspace(userId, workspaceId, db);
103+
if (ws.config.ideCredentials) {
104+
return ws.config.ideCredentials;
105+
}
106+
ws.config.ideCredentials = crypto.randomBytes(32).toString("base64");
107+
await db.store(ws);
108+
return ws.config.ideCredentials;
109+
});
110+
}
111+
73112
async stopWorkspace(
74113
userId: string,
75114
workspaceId: string,

0 commit comments

Comments
 (0)