fix race issue

This commit is contained in:
Philipinho
2026-08-19 21:46:01 +01:00
parent 8c2c49ea6d
commit ab43031375
2 changed files with 33 additions and 12 deletions
@@ -339,15 +339,25 @@ export class SpaceMemberService {
return; return;
} }
await executeTx(this.db, async (trx) => {
await trx
.selectFrom('spaces')
.select('id')
.where('id', '=', dto.spaceId)
.forUpdate()
.executeTakeFirst();
if (spaceMember.role === SpaceRole.ADMIN) { if (spaceMember.role === SpaceRole.ADMIN) {
await this.validateLastAdmin(dto.spaceId); await this.validateLastAdmin(dto.spaceId, trx);
} }
await this.spaceMemberRepo.updateSpaceMember( await this.spaceMemberRepo.updateSpaceMember(
{ role: dto.role }, { role: dto.role },
spaceMember.id, spaceMember.id,
dto.spaceId, dto.spaceId,
trx,
); );
});
this.auditService.log({ this.auditService.log({
event: AuditEvent.SPACE_MEMBER_ROLE_CHANGED, event: AuditEvent.SPACE_MEMBER_ROLE_CHANGED,
@@ -368,10 +378,14 @@ export class SpaceMemberService {
}); });
} }
async validateLastAdmin(spaceId: string): Promise<void> { async validateLastAdmin(
spaceId: string,
trx?: KyselyTransaction,
): Promise<void> {
const spaceOwnerCount = await this.spaceMemberRepo.roleCountBySpaceId( const spaceOwnerCount = await this.spaceMemberRepo.roleCountBySpaceId(
SpaceRole.ADMIN, SpaceRole.ADMIN,
spaceId, spaceId,
trx,
); );
if (spaceOwnerCount === 1) { if (spaceOwnerCount === 1) {
throw new BadRequestException( throw new BadRequestException(
@@ -46,8 +46,10 @@ export class SpaceMemberRepo {
updatableSpaceMember: UpdatableSpaceMember, updatableSpaceMember: UpdatableSpaceMember,
spaceMemberId: string, spaceMemberId: string,
spaceId: string, spaceId: string,
trx?: KyselyTransaction,
): Promise<void> { ): Promise<void> {
await this.db const db = dbOrTx(this.db, trx);
await db
.updateTable('spaceMembers') .updateTable('spaceMembers')
.set(updatableSpaceMember) .set(updatableSpaceMember)
.where('id', '=', spaceMemberId) .where('id', '=', spaceMemberId)
@@ -92,8 +94,13 @@ export class SpaceMemberRepo {
.execute(); .execute();
} }
async roleCountBySpaceId(role: string, spaceId: string): Promise<number> { async roleCountBySpaceId(
const { count } = await this.db role: string,
spaceId: string,
trx?: KyselyTransaction,
): Promise<number> {
const db = dbOrTx(this.db, trx);
const { count } = await db
.selectFrom('spaceMembers') .selectFrom('spaceMembers')
.select((eb) => eb.fn.count('role').as('count')) .select((eb) => eb.fn.count('role').as('count'))
.where('role', '=', role) .where('role', '=', role)