From 46cfd1322250728d3cdf7e5d4ce724a4a9e8c569 Mon Sep 17 00:00:00 2001 From: sezanzeb <28510156+sezanzeb@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:08:07 +0200 Subject: [PATCH 1/2] Creating a team clears your request --- backend/src/services/team-service.ts | 5 +---- backend/test/services/team-service.spec.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/src/services/team-service.ts b/backend/src/services/team-service.ts index 66b90a3..b8603f5 100644 --- a/backend/src/services/team-service.ts +++ b/backend/src/services/team-service.ts @@ -167,10 +167,6 @@ export class TeamService implements ITeamService { throw new Error("Team description cannot be empty"); } - // TODO leaving team should make someone else owner - // TODO order of team.users not guaranteed anymore I guess, - // - you can only own one team, just like you can only be part of one team - if (user.team) { throw new Error("You are already part of a team"); } @@ -185,6 +181,7 @@ export class TeamService implements ITeamService { const createdTeam = await this._teams.save(team); user.team = createdTeam; + user.teamRequest = null; await this._users.save(user); // Every team gets one project by default diff --git a/backend/test/services/team-service.spec.ts b/backend/test/services/team-service.spec.ts index 6d59c61..81fd546 100644 --- a/backend/test/services/team-service.spec.ts +++ b/backend/test/services/team-service.spec.ts @@ -77,6 +77,21 @@ describe("TeamService", () => { expect(foundTeam!.owner.id).toEqual(user.id); }); + it("clears the users team request", async () => { + expect.assertions(1); + + const team = await teamRepo.save(makeTeam("Team 1")); + + const user = await userRepo.save({ + ...makeUser("member@test.com"), + teamRequest: team, + }); + await teamService.createTeam(makeTeam(), user); + + const updatedUser = await userRepo.findOne({ where: { id: user.id } }); + expect(updatedUser!.teamRequest).toBeNull(); + }); + it("assigns the newly created team to the user", async () => { expect.assertions(1); From bcb7f0c7da3623a63030d388624fe97cc4c0d4b9 Mon Sep 17 00:00:00 2001 From: sezanzeb <28510156+sezanzeb@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:22:22 +0200 Subject: [PATCH 2/2] Prevent perople from accepting requests that would abandon other teams --- backend/src/services/team-service.ts | 13 ++++++++++++- backend/test/services/team-service.spec.ts | 20 +++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/backend/src/services/team-service.ts b/backend/src/services/team-service.ts index b8603f5..e037522 100644 --- a/backend/src/services/team-service.ts +++ b/backend/src/services/team-service.ts @@ -313,7 +313,18 @@ export class TeamService implements ITeamService { } if (!team.requestUserIds().includes(userId)) { - throw new Error(`user ${userId} did not request to join team ${teamId}`); + throw new Error(`User ${userId} did not request to join team ${teamId}`); + } + + const oldTeam = await this._teams.findOne({ + where: { id: userId }, + relations: ["users", "requests", "owner"], + }); + + if (oldTeam?.owner?.id === userId) { + throw new Error( + "The user needs to select a new owner for their old team first", + ); } await this._users.update({ id: userId }, { team, teamRequest: null }); diff --git a/backend/test/services/team-service.spec.ts b/backend/test/services/team-service.spec.ts index 81fd546..bd19a8d 100644 --- a/backend/test/services/team-service.spec.ts +++ b/backend/test/services/team-service.spec.ts @@ -121,7 +121,7 @@ describe("TeamService", () => { }); describe("acceptUserToTeam", () => { - it("throws when the requester is neither owner nor admin", async () => { + it("throws when the accepting user is neither owner nor admin", async () => { expect.assertions(1); const owner = await userRepo.save(makeUser("owner@test.com")); @@ -141,6 +141,24 @@ describe("TeamService", () => { ).rejects.toThrow("You are not the owner of this team"); }); + it("throws when the requester is owner of another team", async () => { + expect.assertions(1); + + const team1Owner = await userRepo.save(makeUser("owner@test.com")); + const team1 = await teamService.createTeam(makeTeam(), team1Owner); + + const team2Owner = await userRepo.save(makeUser("req@test.com")); + const team2 = await teamService.createTeam(makeTeam(), team2Owner); + + await userRepo.save({ ...team2Owner, team: team2, teamRequest: team1 }); + + await expect( + teamService.acceptUserToTeam(team1.id, team2Owner.id, team1Owner), + ).rejects.toThrow( + "The user needs to select a new owner for their old team first", + ); + }); + it("allows the team owner to accept a join request", async () => { expect.assertions(2);