Skip to content

Commit 4349b00

Browse files
committed
[server] Move some admin rpcs to non EE
1 parent 233ec94 commit 4349b00

File tree

2 files changed

+196
-291
lines changed

2 files changed

+196
-291
lines changed

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

Lines changed: 0 additions & 266 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,13 @@ import { injectable, inject } from "inversify";
88
import { GitpodServerImpl, traceAPIParams, traceWI, censor } from "../../../src/workspace/gitpod-server-impl";
99
import { TraceContext, TraceContextWithSpan } from "@gitpod/gitpod-protocol/lib/util/tracing";
1010
import {
11-
GitpodServer,
1211
GitpodClient,
1312
AdminGetListRequest,
1413
User,
1514
Team,
16-
TeamMemberInfo,
1715
AdminGetListResult,
1816
Permission,
1917
AdminBlockUserRequest,
20-
AdminModifyRoleOrPermissionRequest,
21-
RoleOrPermission,
22-
AdminModifyPermanentWorkspaceFeatureFlagRequest,
23-
UserFeatureSettings,
24-
AdminGetWorkspacesRequest,
25-
WorkspaceAndInstance,
2618
GetWorkspaceTimeoutResult,
2719
WorkspaceTimeoutDuration,
2820
SetWorkspaceTimeoutResult,
@@ -38,16 +30,13 @@ import {
3830
Project,
3931
StartPrebuildResult,
4032
ClientHeaderFields,
41-
Workspace,
4233
FindPrebuildsParams,
43-
TeamMemberRole,
4434
WORKSPACE_TIMEOUT_DEFAULT_SHORT,
4535
PrebuildEvent,
4636
OpenPrebuildContext,
4737
} from "@gitpod/gitpod-protocol";
4838
import { ResponseError } from "vscode-jsonrpc";
4939
import {
50-
TakeSnapshotRequest,
5140
AdmissionLevel,
5241
ControlAdmissionRequest,
5342
StopWorkspacePolicy,
@@ -59,7 +48,6 @@ import { log, LogContext } from "@gitpod/gitpod-protocol/lib/util/logging";
5948
import { LicenseValidationResult } from "@gitpod/gitpod-protocol/lib/license-protocol";
6049
import { PrebuildManager } from "../prebuilds/prebuild-manager";
6150
import { GuardedCostCenter, ResourceAccessGuard, ResourceAccessOp } from "../../../src/auth/resource-access";
62-
import { BlockedRepository } from "@gitpod/gitpod-protocol/lib/blocked-repositories-protocol";
6351
import { CostCenterJSON, ListUsageRequest, ListUsageResponse } from "@gitpod/gitpod-protocol/lib/usage";
6452
import {
6553
CostCenter,
@@ -530,260 +518,6 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
530518
return this.censorUser(targetUser);
531519
}
532520

533-
async adminVerifyUser(ctx: TraceContext, userId: string): Promise<User> {
534-
await this.guardAdminAccess("adminVerifyUser", { id: userId }, Permission.ADMIN_USERS);
535-
try {
536-
const user = await this.userDB.findUserById(userId);
537-
if (!user) {
538-
throw new ResponseError(ErrorCodes.NOT_FOUND, `No user with id ${userId} found.`);
539-
}
540-
this.verificationService.markVerified(user);
541-
await this.userDB.updateUserPartial(user);
542-
return user;
543-
} catch (e) {
544-
throw new ResponseError(ErrorCodes.INTERNAL_SERVER_ERROR, e.toString());
545-
}
546-
}
547-
548-
async adminDeleteUser(ctx: TraceContext, userId: string): Promise<void> {
549-
traceAPIParams(ctx, { userId });
550-
551-
await this.guardAdminAccess("adminDeleteUser", { id: userId }, Permission.ADMIN_USERS);
552-
553-
try {
554-
await this.userDeletionService.deleteUser(userId);
555-
} catch (e) {
556-
throw new ResponseError(ErrorCodes.INTERNAL_SERVER_ERROR, e.toString());
557-
}
558-
}
559-
560-
async adminGetBlockedRepositories(
561-
ctx: TraceContext,
562-
req: AdminGetListRequest<BlockedRepository>,
563-
): Promise<AdminGetListResult<BlockedRepository>> {
564-
traceAPIParams(ctx, { req: censor(req, "searchTerm") }); // searchTerm may contain PII
565-
566-
await this.guardAdminAccess("adminGetBlockedRepositories", { req }, Permission.ADMIN_USERS);
567-
568-
try {
569-
const res = await this.blockedRepostoryDB.findAllBlockedRepositories(
570-
req.offset,
571-
req.limit,
572-
req.orderBy,
573-
req.orderDir === "asc" ? "ASC" : "DESC",
574-
req.searchTerm,
575-
);
576-
return res;
577-
} catch (e) {
578-
throw new ResponseError(ErrorCodes.INTERNAL_SERVER_ERROR, e.toString());
579-
}
580-
}
581-
582-
async adminCreateBlockedRepository(
583-
ctx: TraceContext,
584-
urlRegexp: string,
585-
blockUser: boolean,
586-
): Promise<BlockedRepository> {
587-
traceAPIParams(ctx, { urlRegexp, blockUser });
588-
589-
await this.guardAdminAccess("adminCreateBlockedRepository", { urlRegexp, blockUser }, Permission.ADMIN_USERS);
590-
591-
return await this.blockedRepostoryDB.createBlockedRepository(urlRegexp, blockUser);
592-
}
593-
594-
async adminDeleteBlockedRepository(ctx: TraceContext, id: number): Promise<void> {
595-
traceAPIParams(ctx, { id });
596-
597-
await this.guardAdminAccess("adminDeleteBlockedRepository", { id }, Permission.ADMIN_USERS);
598-
599-
await this.blockedRepostoryDB.deleteBlockedRepository(id);
600-
}
601-
602-
async adminModifyRoleOrPermission(ctx: TraceContext, req: AdminModifyRoleOrPermissionRequest): Promise<User> {
603-
traceAPIParams(ctx, { req });
604-
605-
await this.guardAdminAccess("adminModifyRoleOrPermission", { req }, Permission.ADMIN_USERS);
606-
607-
const target = await this.userDB.findUserById(req.id);
608-
if (!target) {
609-
throw new ResponseError(ErrorCodes.NOT_FOUND, "not found");
610-
}
611-
612-
const rolesOrPermissions = new Set((target.rolesOrPermissions || []) as string[]);
613-
req.rpp.forEach((e) => {
614-
if (e.add) {
615-
rolesOrPermissions.add(e.r as string);
616-
} else {
617-
rolesOrPermissions.delete(e.r as string);
618-
}
619-
});
620-
target.rolesOrPermissions = Array.from(rolesOrPermissions.values()) as RoleOrPermission[];
621-
622-
await this.userDB.storeUser(target);
623-
// For some reason, neither returning the result of `this.userDB.storeUser(target)` nor returning `target` work.
624-
// The response never arrives the caller.
625-
// Returning the following works at the cost of an additional DB query:
626-
return this.censorUser((await this.userDB.findUserById(req.id))!);
627-
}
628-
629-
async adminModifyPermanentWorkspaceFeatureFlag(
630-
ctx: TraceContext,
631-
req: AdminModifyPermanentWorkspaceFeatureFlagRequest,
632-
): Promise<User> {
633-
traceAPIParams(ctx, { req });
634-
635-
await this.guardAdminAccess("adminModifyPermanentWorkspaceFeatureFlag", { req }, Permission.ADMIN_USERS);
636-
const target = await this.userDB.findUserById(req.id);
637-
if (!target) {
638-
throw new ResponseError(ErrorCodes.NOT_FOUND, "not found");
639-
}
640-
641-
const featureSettings: UserFeatureSettings = target.featureFlags || {};
642-
const featureFlags = new Set(featureSettings.permanentWSFeatureFlags || []);
643-
644-
req.changes.forEach((e) => {
645-
if (e.add) {
646-
featureFlags.add(e.featureFlag);
647-
} else {
648-
featureFlags.delete(e.featureFlag);
649-
}
650-
});
651-
featureSettings.permanentWSFeatureFlags = Array.from(featureFlags);
652-
target.featureFlags = featureSettings;
653-
654-
await this.userDB.storeUser(target);
655-
// For some reason, returning the result of `this.userDB.storeUser(target)` does not work. The response never arrives the caller.
656-
// Returning `target` instead (which should be equivalent).
657-
return this.censorUser(target);
658-
}
659-
660-
async adminGetTeamMembers(ctx: TraceContext, teamId: string): Promise<TeamMemberInfo[]> {
661-
await this.guardAdminAccess("adminGetTeamMembers", { teamId }, Permission.ADMIN_WORKSPACES);
662-
663-
const team = await this.teamDB.findTeamById(teamId);
664-
if (!team) {
665-
throw new ResponseError(ErrorCodes.NOT_FOUND, "Team not found");
666-
}
667-
const members = await this.teamDB.findMembersByTeam(team.id);
668-
return members;
669-
}
670-
671-
async adminGetTeams(ctx: TraceContext, req: AdminGetListRequest<Team>): Promise<AdminGetListResult<Team>> {
672-
await this.guardAdminAccess("adminGetTeams", { req }, Permission.ADMIN_WORKSPACES);
673-
674-
return await this.teamDB.findTeams(
675-
req.offset,
676-
req.limit,
677-
req.orderBy,
678-
req.orderDir === "asc" ? "ASC" : "DESC",
679-
req.searchTerm as string,
680-
);
681-
}
682-
683-
async adminGetTeamById(ctx: TraceContext, id: string): Promise<Team | undefined> {
684-
await this.guardAdminAccess("adminGetTeamById", { id }, Permission.ADMIN_WORKSPACES);
685-
return await this.teamDB.findTeamById(id);
686-
}
687-
688-
async adminSetTeamMemberRole(
689-
ctx: TraceContext,
690-
teamId: string,
691-
userId: string,
692-
role: TeamMemberRole,
693-
): Promise<void> {
694-
await this.guardAdminAccess("adminSetTeamMemberRole", { teamId, userId, role }, Permission.ADMIN_WORKSPACES);
695-
return this.teamDB.setTeamMemberRole(userId, teamId, role);
696-
}
697-
698-
async adminGetWorkspaces(
699-
ctx: TraceContext,
700-
req: AdminGetWorkspacesRequest,
701-
): Promise<AdminGetListResult<WorkspaceAndInstance>> {
702-
traceAPIParams(ctx, { req });
703-
704-
await this.guardAdminAccess("adminGetWorkspaces", { req }, Permission.ADMIN_WORKSPACES);
705-
706-
return await this.workspaceDb
707-
.trace(ctx)
708-
.findAllWorkspaceAndInstances(
709-
req.offset,
710-
req.limit,
711-
req.orderBy,
712-
req.orderDir === "asc" ? "ASC" : "DESC",
713-
req,
714-
);
715-
}
716-
717-
async adminGetWorkspace(ctx: TraceContext, workspaceId: string): Promise<WorkspaceAndInstance> {
718-
traceAPIParams(ctx, { workspaceId });
719-
720-
await this.guardAdminAccess("adminGetWorkspace", { id: workspaceId }, Permission.ADMIN_WORKSPACES);
721-
722-
const result = await this.workspaceDb.trace(ctx).findWorkspaceAndInstance(workspaceId);
723-
if (!result) {
724-
throw new ResponseError(ErrorCodes.NOT_FOUND, "not found");
725-
}
726-
return result;
727-
}
728-
729-
async adminForceStopWorkspace(ctx: TraceContext, workspaceId: string): Promise<void> {
730-
traceAPIParams(ctx, { workspaceId });
731-
732-
await this.guardAdminAccess("adminForceStopWorkspace", { id: workspaceId }, Permission.ADMIN_WORKSPACES);
733-
734-
const workspace = await this.workspaceDb.trace(ctx).findById(workspaceId);
735-
if (workspace) {
736-
await this.internalStopWorkspace(ctx, workspace, "stopped by admin", StopWorkspacePolicy.IMMEDIATELY, true);
737-
}
738-
}
739-
740-
async adminRestoreSoftDeletedWorkspace(ctx: TraceContext, workspaceId: string): Promise<void> {
741-
traceAPIParams(ctx, { workspaceId });
742-
743-
await this.guardAdminAccess(
744-
"adminRestoreSoftDeletedWorkspace",
745-
{ id: workspaceId },
746-
Permission.ADMIN_WORKSPACES,
747-
);
748-
749-
await this.workspaceDb.trace(ctx).transaction(async (db) => {
750-
const ws = await db.findById(workspaceId);
751-
if (!ws) {
752-
throw new ResponseError(ErrorCodes.NOT_FOUND, `No workspace with id '${workspaceId}' found.`);
753-
}
754-
if (!ws.softDeleted) {
755-
return;
756-
}
757-
if (!!ws.contentDeletedTime) {
758-
throw new ResponseError(ErrorCodes.NOT_FOUND, "The workspace content was already garbage-collected.");
759-
}
760-
// @ts-ignore
761-
ws.softDeleted = null;
762-
ws.softDeletedTime = "";
763-
ws.pinned = true;
764-
await db.store(ws);
765-
});
766-
}
767-
768-
async adminGetProjectsBySearchTerm(
769-
ctx: TraceContext,
770-
req: AdminGetListRequest<Project>,
771-
): Promise<AdminGetListResult<Project>> {
772-
await this.guardAdminAccess("adminGetProjectsBySearchTerm", { req }, Permission.ADMIN_PROJECTS);
773-
return await this.projectDB.findProjectsBySearchTerm(
774-
req.offset,
775-
req.limit,
776-
req.orderBy,
777-
req.orderDir === "asc" ? "ASC" : "DESC",
778-
req.searchTerm as string,
779-
);
780-
}
781-
782-
async adminGetProjectById(ctx: TraceContext, id: string): Promise<Project | undefined> {
783-
await this.guardAdminAccess("adminGetProjectById", { id }, Permission.ADMIN_PROJECTS);
784-
return await this.projectDB.findProjectById(id);
785-
}
786-
787521
protected async findPrebuiltWorkspace(
788522
parentCtx: TraceContext,
789523
user: User,

0 commit comments

Comments
 (0)