mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 20:14:54 +00:00
delete propogation
This commit is contained in:
10
src/space/commands/disable-space.command.ts
Normal file
10
src/space/commands/disable-space.command.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { SpaceEntity } from '@app/common/modules/space';
|
||||||
|
|
||||||
|
export class DisableSpaceCommand {
|
||||||
|
constructor(
|
||||||
|
public readonly param: {
|
||||||
|
spaceUuid: string;
|
||||||
|
orphanSpace: SpaceEntity;
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
}
|
||||||
1
src/space/commands/index.ts
Normal file
1
src/space/commands/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './disable-space.command';
|
||||||
@ -67,8 +67,8 @@ export class SpaceController {
|
|||||||
description: ControllerRoute.SPACE.ACTIONS.DELETE_SPACE_DESCRIPTION,
|
description: ControllerRoute.SPACE.ACTIONS.DELETE_SPACE_DESCRIPTION,
|
||||||
})
|
})
|
||||||
@Delete('/:spaceUuid')
|
@Delete('/:spaceUuid')
|
||||||
async deleteSpace(@Param() params: GetSpaceParam){
|
async deleteSpace(@Param() params: GetSpaceParam) {
|
||||||
return await this.spaceService.deleteSpace(params);
|
return await this.spaceService.delete(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
|
|||||||
100
src/space/handlers/disable-space.handler.ts
Normal file
100
src/space/handlers/disable-space.handler.ts
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import { SpaceEntity } from '@app/common/modules/space';
|
||||||
|
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||||
|
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
|
||||||
|
import { DeviceService } from 'src/device/services';
|
||||||
|
import { UserSpaceService } from 'src/users/services';
|
||||||
|
import { DataSource } from 'typeorm';
|
||||||
|
import { DisableSpaceCommand } from '../commands';
|
||||||
|
import {
|
||||||
|
SubSpaceService,
|
||||||
|
SpaceLinkService,
|
||||||
|
SpaceSceneService,
|
||||||
|
} from '../services';
|
||||||
|
import { TagService } from '../services/tag';
|
||||||
|
|
||||||
|
@CommandHandler(DisableSpaceCommand)
|
||||||
|
export class DisableSpaceHandler
|
||||||
|
implements ICommandHandler<DisableSpaceCommand>
|
||||||
|
{
|
||||||
|
constructor(
|
||||||
|
private readonly subSpaceService: SubSpaceService,
|
||||||
|
private readonly userService: UserSpaceService,
|
||||||
|
private readonly tagService: TagService,
|
||||||
|
private readonly deviceService: DeviceService,
|
||||||
|
private readonly spaceLinkService: SpaceLinkService,
|
||||||
|
private readonly sceneService: SpaceSceneService,
|
||||||
|
private readonly dataSource: DataSource,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async execute(command: DisableSpaceCommand): Promise<void> {
|
||||||
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { spaceUuid, orphanSpace } = command.param;
|
||||||
|
|
||||||
|
const space = await queryRunner.manager.findOne(SpaceEntity, {
|
||||||
|
where: { uuid: spaceUuid, disabled: false },
|
||||||
|
relations: [
|
||||||
|
'subspaces',
|
||||||
|
'parent',
|
||||||
|
'tags',
|
||||||
|
'devices',
|
||||||
|
'outgoingConnections',
|
||||||
|
'incomingConnections',
|
||||||
|
'scenes',
|
||||||
|
'children',
|
||||||
|
'userSpaces',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!space) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Space with UUID ${spaceUuid} not found`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space.children && space.children.length > 0) {
|
||||||
|
for (const child of space.children) {
|
||||||
|
await this.execute(
|
||||||
|
new DisableSpaceCommand({ spaceUuid: child.uuid, orphanSpace }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagUuids = space.tags?.map((tag) => tag.uuid) || [];
|
||||||
|
const subspaceDtos =
|
||||||
|
space.subspaces?.map((subspace) => ({
|
||||||
|
subspaceUuid: subspace.uuid,
|
||||||
|
})) || [];
|
||||||
|
const deletionTasks = [
|
||||||
|
this.subSpaceService.deleteSubspaces(subspaceDtos, queryRunner),
|
||||||
|
this.userService.deleteUserSpace(space.uuid),
|
||||||
|
this.tagService.deleteTags(tagUuids, queryRunner),
|
||||||
|
this.deviceService.deleteDevice(
|
||||||
|
space.devices,
|
||||||
|
orphanSpace,
|
||||||
|
queryRunner,
|
||||||
|
),
|
||||||
|
this.spaceLinkService.deleteSpaceLink(space, queryRunner),
|
||||||
|
this.sceneService.deleteScenes(space, queryRunner),
|
||||||
|
];
|
||||||
|
|
||||||
|
await Promise.all(deletionTasks);
|
||||||
|
|
||||||
|
// Mark space as disabled
|
||||||
|
space.disabled = true;
|
||||||
|
await queryRunner.manager.save(space);
|
||||||
|
|
||||||
|
await queryRunner.commitTransaction();
|
||||||
|
} catch (error) {
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
console.error(`Failed to disable space: ${error.message}`);
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/space/handlers/index.ts
Normal file
1
src/space/handlers/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './disable-space.handler';
|
||||||
@ -30,7 +30,6 @@ export class ValidationService {
|
|||||||
return { community: community.data, project: project };
|
return { community: community.data, project: project };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async validateSpaceWithinCommunityAndProject(
|
async validateSpaceWithinCommunityAndProject(
|
||||||
communityUuid: string,
|
communityUuid: string,
|
||||||
projectUuid: string,
|
projectUuid: string,
|
||||||
@ -44,7 +43,14 @@ export class ValidationService {
|
|||||||
async validateSpace(spaceUuid: string): Promise<SpaceEntity> {
|
async validateSpace(spaceUuid: string): Promise<SpaceEntity> {
|
||||||
const space = await this.spaceRepository.findOne({
|
const space = await this.spaceRepository.findOne({
|
||||||
where: { uuid: spaceUuid, disabled: false },
|
where: { uuid: spaceUuid, disabled: false },
|
||||||
relations: ['subspaces', 'tags'],
|
relations: [
|
||||||
|
'parent',
|
||||||
|
'children',
|
||||||
|
'subspaces',
|
||||||
|
'tags',
|
||||||
|
'subspaces.tags',
|
||||||
|
'devices',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!space) {
|
if (!space) {
|
||||||
|
|||||||
@ -21,13 +21,14 @@ import { SpaceLinkService } from './space-link';
|
|||||||
import { SubSpaceService } from './subspace';
|
import { SubSpaceService } from './subspace';
|
||||||
import { DataSource, Not, QueryRunner } from 'typeorm';
|
import { DataSource, Not, QueryRunner } from 'typeorm';
|
||||||
import { ValidationService } from './space-validation.service';
|
import { ValidationService } from './space-validation.service';
|
||||||
import { ORPHAN_SPACE_NAME } from '@app/common/constants/orphan-constant';
|
import {
|
||||||
|
ORPHAN_COMMUNITY_NAME,
|
||||||
|
ORPHAN_SPACE_NAME,
|
||||||
|
} from '@app/common/constants/orphan-constant';
|
||||||
|
import { CommandBus } from '@nestjs/cqrs';
|
||||||
import { TagService } from './tag';
|
import { TagService } from './tag';
|
||||||
import { SpaceModelService } from 'src/space-model/services';
|
import { SpaceModelService } from 'src/space-model/services';
|
||||||
import { UserSpaceService } from 'src/users/services';
|
import { DisableSpaceCommand } from '../commands';
|
||||||
import { DeviceService } from 'src/device/services';
|
|
||||||
import { SpaceSceneService } from './space-scene.service';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceService {
|
export class SpaceService {
|
||||||
constructor(
|
constructor(
|
||||||
@ -38,9 +39,7 @@ export class SpaceService {
|
|||||||
private readonly validationService: ValidationService,
|
private readonly validationService: ValidationService,
|
||||||
private readonly tagService: TagService,
|
private readonly tagService: TagService,
|
||||||
private readonly spaceModelService: SpaceModelService,
|
private readonly spaceModelService: SpaceModelService,
|
||||||
private readonly userService: UserSpaceService,
|
private commandBus: CommandBus,
|
||||||
private readonly deviceService: DeviceService,
|
|
||||||
private readonly sceneService: SpaceSceneService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createSpace(
|
async createSpace(
|
||||||
@ -228,20 +227,17 @@ export class SpaceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async delete(params: GetSpaceParam): Promise<BaseResponseDto> {
|
async delete(params: GetSpaceParam): Promise<BaseResponseDto> {
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
|
||||||
|
|
||||||
await queryRunner.connect();
|
|
||||||
await queryRunner.startTransaction();
|
|
||||||
try {
|
try {
|
||||||
const { communityUuid, spaceUuid, projectUuid } = params;
|
const { communityUuid, spaceUuid, projectUuid } = params;
|
||||||
|
|
||||||
const space =
|
const { project } =
|
||||||
await this.validationService.validateSpaceWithinCommunityAndProject(
|
await this.validationService.validateCommunityAndProject(
|
||||||
communityUuid,
|
communityUuid,
|
||||||
projectUuid,
|
projectUuid,
|
||||||
spaceUuid,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const space = await this.validationService.validateSpace(spaceUuid);
|
||||||
|
|
||||||
if (space.spaceName === ORPHAN_SPACE_NAME) {
|
if (space.spaceName === ORPHAN_SPACE_NAME) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`space ${ORPHAN_SPACE_NAME} cannot be deleted`,
|
`space ${ORPHAN_SPACE_NAME} cannot be deleted`,
|
||||||
@ -249,37 +245,22 @@ export class SpaceService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space.tags?.length) {
|
const orphanSpace = await this.spaceRepository.findOne({
|
||||||
const deleteSpaceTagsDtos = space.tags.map((tag) => tag.uuid);
|
where: {
|
||||||
await this.tagService.deleteTags(deleteSpaceTagsDtos, queryRunner);
|
community: {
|
||||||
}
|
uuid: `${ORPHAN_COMMUNITY_NAME}-${project.name}`,
|
||||||
|
},
|
||||||
|
spaceName: ORPHAN_SPACE_NAME,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (space.subspaces?.length) {
|
await this.disableSpace(space, orphanSpace);
|
||||||
const deleteSubspaceDtos = space.subspaces.map((subspace) => ({
|
|
||||||
subspaceUuid: subspace.uuid,
|
|
||||||
}));
|
|
||||||
|
|
||||||
await this.subSpaceService.deleteSubspaces(
|
|
||||||
deleteSubspaceDtos,
|
|
||||||
queryRunner,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryRunner.manager.update(
|
|
||||||
this.spaceRepository.target,
|
|
||||||
{ uuid: params.spaceUuid },
|
|
||||||
{ disabled: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
await queryRunner.commitTransaction();
|
|
||||||
|
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
message: `Space with ID ${spaceUuid} successfully deleted`,
|
message: `Space with ID ${spaceUuid} successfully deleted`,
|
||||||
statusCode: HttpStatus.OK,
|
statusCode: HttpStatus.OK,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await queryRunner.rollbackTransaction();
|
|
||||||
|
|
||||||
if (error instanceof HttpException) {
|
if (error instanceof HttpException) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@ -287,11 +268,15 @@ export class SpaceService {
|
|||||||
'An error occurred while deleting the space',
|
'An error occurred while deleting the space',
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
);
|
);
|
||||||
} finally {
|
|
||||||
await queryRunner.release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async disableSpace(space: SpaceEntity, orphanSpace: SpaceEntity) {
|
||||||
|
await this.commandBus.execute(
|
||||||
|
new DisableSpaceCommand({ spaceUuid: space.uuid, orphanSpace }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async updateSpace(
|
async updateSpace(
|
||||||
params: GetSpaceParam,
|
params: GetSpaceParam,
|
||||||
updateSpaceDto: UpdateSpaceDto,
|
updateSpaceDto: UpdateSpaceDto,
|
||||||
@ -368,71 +353,6 @@ export class SpaceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteSpace(params: GetSpaceParam) {
|
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
|
||||||
const { spaceUuid } = params;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await queryRunner.connect();
|
|
||||||
await queryRunner.startTransaction();
|
|
||||||
|
|
||||||
const spaces = await this.spaceRepository.find({
|
|
||||||
where: { parent: { uuid: spaceUuid }, disabled: false },
|
|
||||||
relations: [
|
|
||||||
'parent',
|
|
||||||
'children',
|
|
||||||
'subspaces',
|
|
||||||
'tags',
|
|
||||||
'subspaces.tags',
|
|
||||||
'devices',
|
|
||||||
], // Include parent and children relations
|
|
||||||
});
|
|
||||||
//this.disableSpace(space, orphanSpace);
|
|
||||||
return spaces;
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof HttpException) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HttpException(
|
|
||||||
`An error occurred while deleting the space ${error}`,
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async disableSpace(space: SpaceEntity, orphanSpace: SpaceEntity) {
|
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
|
||||||
await queryRunner.connect();
|
|
||||||
await queryRunner.startTransaction();
|
|
||||||
try {
|
|
||||||
const deleteSubspaceDtos = space.subspaces?.map((subspace) => ({
|
|
||||||
subspaceUuid: subspace.uuid,
|
|
||||||
}));
|
|
||||||
const deleteSpaceTagsDtos = space.tags?.map((tag) => tag.uuid);
|
|
||||||
|
|
||||||
await this.userService.deleteUserSpace(space.uuid);
|
|
||||||
await this.subSpaceService.deleteSubspaces(
|
|
||||||
deleteSubspaceDtos,
|
|
||||||
queryRunner,
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.tagService.deleteTags(deleteSpaceTagsDtos, queryRunner);
|
|
||||||
|
|
||||||
await this.deviceService.deleteDevice(
|
|
||||||
space.devices,
|
|
||||||
orphanSpace,
|
|
||||||
queryRunner,
|
|
||||||
);
|
|
||||||
await this.spaceLinkService.deleteSpaceLink(space, queryRunner);
|
|
||||||
await this.sceneService.deleteScenes(space, queryRunner);
|
|
||||||
} catch (error) {
|
|
||||||
await queryRunner.rollbackTransaction();
|
|
||||||
} finally {
|
|
||||||
await queryRunner.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateSpaceProperties(
|
private updateSpaceProperties(
|
||||||
space: SpaceEntity,
|
space: SpaceEntity,
|
||||||
updateSpaceDto: UpdateSpaceDto,
|
updateSpaceDto: UpdateSpaceDto,
|
||||||
|
|||||||
@ -61,9 +61,13 @@ import {
|
|||||||
import { UserSpaceService } from 'src/users/services';
|
import { UserSpaceService } from 'src/users/services';
|
||||||
import { UserDevicePermissionService } from 'src/user-device-permission/services';
|
import { UserDevicePermissionService } from 'src/user-device-permission/services';
|
||||||
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
||||||
|
import { CqrsModule } from '@nestjs/cqrs';
|
||||||
|
import { DisableSpaceHandler } from './handlers';
|
||||||
|
|
||||||
|
export const CommandHandlers = [DisableSpaceHandler];
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, SpaceRepositoryModule, CommunityModule],
|
imports: [ConfigModule, SpaceRepositoryModule, CommunityModule, CqrsModule],
|
||||||
controllers: [
|
controllers: [
|
||||||
SpaceController,
|
SpaceController,
|
||||||
SpaceUserController,
|
SpaceUserController,
|
||||||
@ -110,6 +114,7 @@ import { PermissionTypeRepository } from '@app/common/modules/permission/reposit
|
|||||||
UserDevicePermissionService,
|
UserDevicePermissionService,
|
||||||
DeviceUserPermissionRepository,
|
DeviceUserPermissionRepository,
|
||||||
PermissionTypeRepository,
|
PermissionTypeRepository,
|
||||||
|
...CommandHandlers,
|
||||||
],
|
],
|
||||||
exports: [SpaceService],
|
exports: [SpaceService],
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user