Skip to content

Commit b92b12d

Browse files
committed
[dashboard] Allow restoring a soft-deleted workspace from the admin dashboard
1 parent ce05f58 commit b92b12d

File tree

5 files changed

+34
-1
lines changed

5 files changed

+34
-1
lines changed

components/dashboard/src/admin/WorkspaceDetail.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ export default function WorkspaceDetail(props: { workspace: WorkspaceAndInstance
6262
<div className="flex w-full mt-6">
6363
<Property name="User"><Link className="text-blue-400 dark:text-blue-600 hover:text-blue-600 dark:hover:text-blue-400" to={"/admin/users/" + props.workspace.ownerId}>{user?.name || props.workspace.ownerId}</Link></Property>
6464
<Property name="Sharing">{workspace.shareable ? 'Enabled' : 'Disabled'}</Property>
65-
<Property name=""><div></div></Property>
65+
<Property name="Soft Deleted" actions={(!!workspace.softDeleted && !workspace.contentDeletedTime) && [{
66+
label: 'Restore & Pin',
67+
onClick: () => {
68+
getGitpodService().server.adminRestoreSoftDeletedWorkspace(workspace.workspaceId);
69+
}
70+
}] || undefined}>{workspace.softDeleted ? `'${workspace.softDeleted}' ${moment(workspace.softDeletedTime).fromNow()}` : 'No'}</Property>
6671
</div>
6772
<div className="flex w-full mt-12">
6873
<Property name="Latest Instance ID">

components/gitpod-protocol/src/admin-protocol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface AdminServer {
2121
adminGetWorkspaces(req: AdminGetWorkspacesRequest): Promise<AdminGetListResult<WorkspaceAndInstance>>;
2222
adminGetWorkspace(id: string): Promise<WorkspaceAndInstance>;
2323
adminForceStopWorkspace(id: string): Promise<void>;
24+
adminRestoreSoftDeletedWorkspace(id: string): Promise<void>;
2425

2526
adminSetLicense(key: string): Promise<void>;
2627

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,28 @@ export class GitpodServerEEImpl<C extends GitpodClient, S extends GitpodServer>
506506
await this.internalStopWorkspace({ span }, id, undefined, StopWorkspacePolicy.IMMEDIATELY);
507507
}
508508

509+
async adminRestoreSoftDeletedWorkspace(id: string): Promise<void> {
510+
this.requireEELicense(Feature.FeatureAdminDashboard);
511+
512+
await this.guardAdminAccess("adminRestoreSoftDeletedWorkspace", {id}, Permission.ADMIN_WORKSPACES);
513+
514+
const span = opentracing.globalTracer().startSpan("adminRestoreSoftDeletedWorkspace");
515+
await this.workspaceDb.trace({ span }).transaction(async db => {
516+
const ws = await this.internalGetWorkspace(id, db);
517+
if (!ws.softDeleted) {
518+
return;
519+
}
520+
if (!!ws.contentDeletedTime) {
521+
throw new ResponseError(ErrorCodes.NOT_FOUND, "The workspace content was already garbage-collected.");
522+
}
523+
// @ts-ignore
524+
ws.softDeleted = null;
525+
ws.softDeletedTime = '';
526+
ws.pinned = true;
527+
await db.store(ws);
528+
});
529+
}
530+
509531
protected async guardAdminAccess(method: string, params: any, requiredPermission: PermissionName) {
510532
const user = this.checkAndBlockUser(method);
511533
if (!this.authorizationService.hasPermission(user, requiredPermission)) {

components/server/src/auth/rate-limiter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ function readConfig(): RateLimiterConfig {
106106
"adminGetWorkspaces": { group: "default", points: 1 },
107107
"adminGetWorkspace": { group: "default", points: 1 },
108108
"adminForceStopWorkspace": { group: "default", points: 1 },
109+
"adminRestoreSoftDeletedWorkspace": { group: "default", points: 1 },
109110
"adminSetLicense": { group: "default", points: 1 },
110111

111112
"validateLicense": { group: "default", points: 1 },

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,10 @@ export class GitpodServerImpl<Client extends GitpodClient, Server extends Gitpod
15071507
throw new ResponseError(ErrorCodes.EE_FEATURE, `Admin support is implemented in Gitpod's Enterprise Edition`);
15081508
}
15091509

1510+
async adminRestoreSoftDeletedWorkspace(id: string): Promise<void> {
1511+
throw new ResponseError(ErrorCodes.EE_FEATURE, `Admin support is implemented in Gitpod's Enterprise Edition`);
1512+
}
1513+
15101514
async adminSetLicense(key: string): Promise<void> {
15111515
throw new ResponseError(ErrorCodes.EE_FEATURE, `Admin support is implemented in Gitpod's Enterprise Edition`);
15121516
}

0 commit comments

Comments
 (0)