Skip to content

Commit

Permalink
[dashboard] Allow restoring a soft-deleted workspace from the admin d…
Browse files Browse the repository at this point in the history
…ashboard
  • Loading branch information
jankeromnes committed Apr 16, 2021
1 parent ce05f58 commit b92b12d
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 1 deletion.
7 changes: 6 additions & 1 deletion components/dashboard/src/admin/WorkspaceDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ export default function WorkspaceDetail(props: { workspace: WorkspaceAndInstance
<div className="flex w-full mt-6">
<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>
<Property name="Sharing">{workspace.shareable ? 'Enabled' : 'Disabled'}</Property>
<Property name=""><div></div></Property>
<Property name="Soft Deleted" actions={(!!workspace.softDeleted && !workspace.contentDeletedTime) && [{
label: 'Restore & Pin',
onClick: () => {
getGitpodService().server.adminRestoreSoftDeletedWorkspace(workspace.workspaceId);
}
}] || undefined}>{workspace.softDeleted ? `'${workspace.softDeleted}' ${moment(workspace.softDeletedTime).fromNow()}` : 'No'}</Property>
</div>
<div className="flex w-full mt-12">
<Property name="Latest Instance ID">
Expand Down
1 change: 1 addition & 0 deletions components/gitpod-protocol/src/admin-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface AdminServer {
adminGetWorkspaces(req: AdminGetWorkspacesRequest): Promise<AdminGetListResult<WorkspaceAndInstance>>;
adminGetWorkspace(id: string): Promise<WorkspaceAndInstance>;
adminForceStopWorkspace(id: string): Promise<void>;
adminRestoreSoftDeletedWorkspace(id: string): Promise<void>;

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

Expand Down
22 changes: 22 additions & 0 deletions components/server/ee/src/workspace/gitpod-server-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,28 @@ export class GitpodServerEEImpl<C extends GitpodClient, S extends GitpodServer>
await this.internalStopWorkspace({ span }, id, undefined, StopWorkspacePolicy.IMMEDIATELY);
}

async adminRestoreSoftDeletedWorkspace(id: string): Promise<void> {
this.requireEELicense(Feature.FeatureAdminDashboard);

await this.guardAdminAccess("adminRestoreSoftDeletedWorkspace", {id}, Permission.ADMIN_WORKSPACES);

const span = opentracing.globalTracer().startSpan("adminRestoreSoftDeletedWorkspace");
await this.workspaceDb.trace({ span }).transaction(async db => {
const ws = await this.internalGetWorkspace(id, db);
if (!ws.softDeleted) {
return;
}
if (!!ws.contentDeletedTime) {
throw new ResponseError(ErrorCodes.NOT_FOUND, "The workspace content was already garbage-collected.");
}
// @ts-ignore
ws.softDeleted = null;
ws.softDeletedTime = '';
ws.pinned = true;
await db.store(ws);
});
}

protected async guardAdminAccess(method: string, params: any, requiredPermission: PermissionName) {
const user = this.checkAndBlockUser(method);
if (!this.authorizationService.hasPermission(user, requiredPermission)) {
Expand Down
1 change: 1 addition & 0 deletions components/server/src/auth/rate-limiter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ function readConfig(): RateLimiterConfig {
"adminGetWorkspaces": { group: "default", points: 1 },
"adminGetWorkspace": { group: "default", points: 1 },
"adminForceStopWorkspace": { group: "default", points: 1 },
"adminRestoreSoftDeletedWorkspace": { group: "default", points: 1 },
"adminSetLicense": { group: "default", points: 1 },

"validateLicense": { group: "default", points: 1 },
Expand Down
4 changes: 4 additions & 0 deletions components/server/src/workspace/gitpod-server-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1507,6 +1507,10 @@ export class GitpodServerImpl<Client extends GitpodClient, Server extends Gitpod
throw new ResponseError(ErrorCodes.EE_FEATURE, `Admin support is implemented in Gitpod's Enterprise Edition`);
}

async adminRestoreSoftDeletedWorkspace(id: string): Promise<void> {
throw new ResponseError(ErrorCodes.EE_FEATURE, `Admin support is implemented in Gitpod's Enterprise Edition`);
}

async adminSetLicense(key: string): Promise<void> {
throw new ResponseError(ErrorCodes.EE_FEATURE, `Admin support is implemented in Gitpod's Enterprise Edition`);
}
Expand Down

0 comments on commit b92b12d

Please sign in to comment.