fix(backend): Status-Guard fuer Move/Split/Merge auf inaktiven Voelkern

Beim Live-Test im Browser gefunden: move/split/merge liessen sich auch
auf einem bereits DISSOLVED/MERGED-Volk aufrufen und wuerden dort
klaglos durchlaufen - ein Datenintegritaetsproblem, kein reines
UI-Detail. assertActive() wirft jetzt ConflictException (409), wenn
das betroffene Volk (bzw. bei merge: Ziel- und alle zu vereinigenden
Voelker) nicht ACTIVE ist.

Neuer Unit-Test + neuer e2e-Test (dissolve, danach move -> 409).
This commit is contained in:
Nick Szaunig committed 2026-08-21 18:20:48 +02:00
1 parent d3f321f1b5
commit a71b31df38
3 files changed
+34 -2

No files matched your search

@@ -1,4 +1,8 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import {
ConflictException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { AuditLogService } from '../audit/audit-log.service';
import { Colony } from '../../generated/prisma';
@@ -27,6 +31,14 @@ export class ColoniesService {
return colony;
}
private assertActive(colony: Colony): void {
if (colony.status !== 'ACTIVE') {
throw new ConflictException(
`Colony ${colony.id} is not active (status: ${colony.status})`,
);
}
}
async create(dto: CreateColonyDto, actingUserId: string): Promise<Colony> {
const colony = await this.prisma.colony.create({ data: { ...dto } });
await this.auditLog.record({
@@ -66,6 +78,7 @@ export class ColoniesService {
actingUserId: string,
): Promise<Colony> {
const before = await this.findById(id);
this.assertActive(before);
const colony = await this.prisma.$transaction(async (tx) => {
const updated = await tx.colony.update({
where: { id },
@@ -98,6 +111,7 @@ export class ColoniesService {
actingUserId: string,
): Promise<Colony> {
const parent = await this.findById(id);
this.assertActive(parent);
const child = await this.prisma.$transaction(async (tx) => {
const created = await tx.colony.create({
data: {
@@ -134,6 +148,7 @@ export class ColoniesService {
actingUserId: string,
): Promise<Colony> {
const survivor = await this.findById(id);
this.assertActive(survivor);
await this.prisma.$transaction(async (tx) => {
for (const mergedColonyId of dto.mergedColonyIds) {
const merged = await tx.colony.findUnique({
@@ -142,6 +157,7 @@ export class ColoniesService {
if (!merged) {
throw new NotFoundException(`Colony ${mergedColonyId} not found`);
}
this.assertActive(merged);
await tx.colony.update({
where: { id: mergedColonyId },
data: { status: 'MERGED', deactivatedAt: new Date() },