Skip to content

Commit

Permalink
Remove team when sole owner and remove projects
Browse files Browse the repository at this point in the history
Fixes #6655
  • Loading branch information
laushinka committed Nov 16, 2021
1 parent f3ecc7f commit a52ad0a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
1 change: 1 addition & 0 deletions components/gitpod-db/src/team-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface TeamDB {
findTeamById(teamId: string): Promise<Team | undefined>;
findMembersByTeam(teamId: string): Promise<TeamMemberInfo[]>;
findTeamsByUser(userId: string): Promise<Team[]>;
findTeamsByUserAsSoleOwner(userId: string): Promise<Team[]>;
createTeam(userId: string, name: string): Promise<Team>;
addMemberToTeam(userId: string, teamId: string): Promise<void>;
setTeamMemberRole(userId: string, teamId: string, role: TeamMemberRole): Promise<void>;
Expand Down
17 changes: 16 additions & 1 deletion components/gitpod-db/src/typeorm/team-db-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,22 @@ export class TeamDBImpl implements TeamDB {
const membershipRepo = await this.getMembershipRepo();
const memberships = await membershipRepo.find({ userId, deleted: false });
const teams = await teamRepo.findByIds(memberships.map(m => m.teamId));
return teams.filter(t => !t.deleted);
return teams.filter(t => !t.markedDeleted);
}

public async findTeamsByUserAsSoleOwner(userId: string): Promise<Team[]> {
const teamRepo = await this.getTeamRepo();
const membershipRepo = await this.getMembershipRepo();

// Find the memberships of this user,
// and among the memberships, get the teams where the user is the sole owner
const soleOwnedTeamIds = await membershipRepo.query(`SELECT tm_2.teamId FROM d_b_team_membership tm_1
JOIN d_b_team_membership tm_2 ON tm_1.userId = ? AND tm_1.teamId=tm_2.teamId AND tm_1.role = 'owner' GROUP BY tm_2.teamId HAVING COUNT(tm_2.teamId) = 1;`, [userId]);

// @ts-ignore
const teams = await teamRepo.findByIds(soleOwnedTeamIds.map(m => m.teamId));

return teams.filter(t => !t.markedDeleted);
}

public async createTeam(userId: string, name: string): Promise<Team> {
Expand Down
24 changes: 23 additions & 1 deletion components/server/src/user/user-deletion-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { injectable, inject } from "inversify";
import { UserDB, WorkspaceDB, UserStorageResourcesDB, TeamDB } from '@gitpod/gitpod-db/lib';
import { UserDB, WorkspaceDB, UserStorageResourcesDB, TeamDB, ProjectDB } from '@gitpod/gitpod-db/lib';
import { User, Workspace } from "@gitpod/gitpod-protocol";
import { StorageClient } from "../storage/storage-client";
import { log } from '@gitpod/gitpod-protocol/lib/util/logging';
Expand All @@ -23,6 +23,7 @@ export class UserDeletionService {
@inject(WorkspaceDB) protected readonly workspaceDb: WorkspaceDB;
@inject(UserStorageResourcesDB) protected readonly userStorageResourcesDb: UserStorageResourcesDB;
@inject(TeamDB) protected readonly teamDb: TeamDB;
@inject(ProjectDB) protected readonly projectDb: ProjectDB;
@inject(StorageClient) protected readonly storageClient: StorageClient;
@inject(WorkspaceManagerClientProvider) protected readonly workspaceManagerClientProvider: WorkspaceManagerClientProvider;
@inject(WorkspaceDeletionService) protected readonly workspaceDeletionService: WorkspaceDeletionService;
Expand Down Expand Up @@ -74,8 +75,12 @@ export class UserDeletionService {
this.userStorageResourcesDb.deleteAllForUser(user.id),
// Bucket
this.deleteUserBucket(id),
// Owned teams
this.deleteTeams(id),
// Team memberships
this.deleteTeamMemberships(id),
// User projects
this.deleteUserProjects(id),
]);

// Track the deletion Event for Analytics Purposes
Expand Down Expand Up @@ -140,6 +145,23 @@ export class UserDeletionService {
await Promise.all(teams.map(t => this.teamDb.removeMemberFromTeam(userId, t.id)));
}

protected async deleteTeams(userId: string) {
const ownedTeams = await this.teamDb.findTeamsByUserAsSoleOwner(userId);

ownedTeams.forEach(async team => {
const teamProjects = this.projectDb.findTeamProjects(team.id);
(await teamProjects).forEach(project => this.projectDb.markDeleted(project.id));
})

await Promise.all(ownedTeams.map(t => this.teamDb.deleteTeam(t.id)));
}

protected async deleteUserProjects(id: string) {
const userProjects = await this.projectDb.findUserProjects(id);

await Promise.all(userProjects.map(project => this.projectDb.markDeleted(project.id)));
}

anonymizeWorkspace(ws: Workspace) {
ws.context.title = 'deleted-title';
ws.context.normalizedContextURL = 'deleted-normalizedContextURL';
Expand Down

0 comments on commit a52ad0a

Please sign in to comment.