mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-16 02:36:19 +00:00
subspace endpoints
This commit is contained in:
@ -155,4 +155,26 @@ export class ControllerRoute {
|
||||
'Deletes a specific subspace within a given space and community.';
|
||||
};
|
||||
};
|
||||
|
||||
static SUBSPACE_DEVICE = class {
|
||||
public static readonly ROUTE =
|
||||
'/communities/:communityUuid/spaces/:spaceUuid/subspaces/:subSpaceUuid/devices';
|
||||
|
||||
static ACTIONS = class {
|
||||
public static readonly LIST_SUBSPACE_DEVICE_SUMMARY =
|
||||
'List devices in a subspace';
|
||||
public static readonly LIST_SUBSPACE_DEVICE_DESCRIPTION =
|
||||
'Retrieves a list of all devices associated with a specified subspace.';
|
||||
|
||||
public static readonly ASSOCIATE_SUBSPACE_DEVICE_SUMMARY =
|
||||
'Associate a device to a subspace';
|
||||
public static readonly ASSOCIATE_SUBSPACE_DEVICE_DESCRIPTION =
|
||||
'Associates a device with a specific subspace, enabling it to be managed within that subspace context.';
|
||||
|
||||
public static readonly DISASSOCIATE_SUBSPACE_DEVICE_SUMMARY =
|
||||
'Disassociate a device from a subspace';
|
||||
public static readonly DISASSOCIATE_SUBSPACE_DEVICE_DESCRIPTION =
|
||||
'Removes the association of a device from a specific subspace, making it no longer managed within that subspace.';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './space.controller';
|
||||
export * from './space-user.controller';
|
||||
export * from './subspace.controller';
|
||||
export * from './subspace';
|
||||
|
2
src/space/controllers/subspace/index.ts
Normal file
2
src/space/controllers/subspace/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './subspace.controller';
|
||||
export * from './subspace-device.controller';
|
64
src/space/controllers/subspace/subspace-device.controller.ts
Normal file
64
src/space/controllers/subspace/subspace-device.controller.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||
import { Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { DeviceSubSpaceParam, GetSubSpaceParam } from '../../dtos';
|
||||
import { SubspaceDeviceService } from 'src/space/services';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
|
||||
@ApiTags('Space Module')
|
||||
@Controller({
|
||||
version: '1',
|
||||
path: ControllerRoute.SUBSPACE_DEVICE.ROUTE,
|
||||
})
|
||||
export class SubSpaceDeviceController {
|
||||
constructor(private readonly subspaceDeviceService: SubspaceDeviceService) {}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary:
|
||||
ControllerRoute.SUBSPACE_DEVICE.ACTIONS.LIST_SUBSPACE_DEVICE_SUMMARY,
|
||||
description:
|
||||
ControllerRoute.SUBSPACE_DEVICE.ACTIONS.LIST_SUBSPACE_DEVICE_DESCRIPTION,
|
||||
})
|
||||
@Get()
|
||||
async listDevicesInSubspace(
|
||||
@Param() params: GetSubSpaceParam,
|
||||
): Promise<BaseResponseDto> {
|
||||
return await this.subspaceDeviceService.listDevicesInSubspace(params);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary:
|
||||
ControllerRoute.SUBSPACE_DEVICE.ACTIONS.ASSOCIATE_SUBSPACE_DEVICE_SUMMARY,
|
||||
description:
|
||||
ControllerRoute.SUBSPACE_DEVICE.ACTIONS
|
||||
.ASSOCIATE_SUBSPACE_DEVICE_DESCRIPTION,
|
||||
})
|
||||
@Post('/:deviceUuid')
|
||||
async associateDeviceToSubspace(
|
||||
@Param() params: DeviceSubSpaceParam,
|
||||
): Promise<BaseResponseDto> {
|
||||
return await this.subspaceDeviceService.associateDeviceToSubspace(params);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary:
|
||||
ControllerRoute.SUBSPACE_DEVICE.ACTIONS
|
||||
.DISASSOCIATE_SUBSPACE_DEVICE_SUMMARY,
|
||||
description:
|
||||
ControllerRoute.SUBSPACE_DEVICE.ACTIONS
|
||||
.DISASSOCIATE_SUBSPACE_DEVICE_DESCRIPTION,
|
||||
})
|
||||
@Post('/:deviceUuid')
|
||||
async disassociateDeviceFromSubspace(
|
||||
@Param() params: DeviceSubSpaceParam,
|
||||
): Promise<BaseResponseDto> {
|
||||
return await this.subspaceDeviceService.associateDeviceToSubspace(params);
|
||||
}
|
||||
}
|
@ -10,9 +10,9 @@ import {
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { SubSpaceService } from '../services';
|
||||
import { SubSpaceService } from '../../services';
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { AddSubspaceDto, GetSpaceParam, GetSubSpaceParam } from '../dtos';
|
||||
import { AddSubspaceDto, GetSpaceParam, GetSubSpaceParam } from '../../dtos';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||
import { PaginationRequestGetListDto } from '@app/common/dto/pagination.request.dto';
|
12
src/space/dtos/subspace/add.subspace-device.param.ts
Normal file
12
src/space/dtos/subspace/add.subspace-device.param.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsUUID } from 'class-validator';
|
||||
import { GetSubSpaceParam } from './get.subspace.param';
|
||||
|
||||
export class DeviceSubSpaceParam extends GetSubSpaceParam {
|
||||
@ApiProperty({
|
||||
description: 'UUID of the device',
|
||||
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
|
||||
})
|
||||
@IsUUID()
|
||||
deviceUuid: string;
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
export * from './add.subspace.dto';
|
||||
export * from './get.subspace.param';
|
||||
export * from './add.subspace-device.param';
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './space.service';
|
||||
export * from './space-user.service';
|
||||
export * from './subspace.service';
|
||||
export * from './subspace';
|
||||
|
@ -107,23 +107,23 @@ export class SpaceService {
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(spaceId: string): Promise<BaseResponseDto> {
|
||||
async findOne(spaceUuid: string): Promise<BaseResponseDto> {
|
||||
try {
|
||||
const space = await this.spaceRepository.findOne({
|
||||
where: {
|
||||
uuid: spaceId,
|
||||
uuid: spaceUuid,
|
||||
},
|
||||
});
|
||||
|
||||
// If space is not found, throw a NotFoundException
|
||||
if (!space) {
|
||||
throw new HttpException(
|
||||
`Space with UUID ${spaceId} not found`,
|
||||
`Space with UUID ${spaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
return new SuccessResponseDto({
|
||||
message: `Space with ID ${spaceId} successfully fetched`,
|
||||
message: `Space with ID ${spaceUuid} successfully fetched`,
|
||||
data: space,
|
||||
});
|
||||
} catch (error) {
|
||||
@ -138,28 +138,31 @@ export class SpaceService {
|
||||
}
|
||||
}
|
||||
|
||||
async delete(spaceId: string, communityId: string): Promise<BaseResponseDto> {
|
||||
async delete(
|
||||
spaceUuid: string,
|
||||
communityUuid: string,
|
||||
): Promise<BaseResponseDto> {
|
||||
try {
|
||||
// First, check if the community exists
|
||||
const community = await this.communityRepository.findOne({
|
||||
where: { uuid: communityId },
|
||||
where: { uuid: communityUuid },
|
||||
});
|
||||
|
||||
if (!community) {
|
||||
throw new HttpException(
|
||||
`Community with ID ${communityId} not found`,
|
||||
`Community with ID ${communityUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the space exists
|
||||
const space = await this.spaceRepository.findOne({
|
||||
where: { uuid: spaceId, community: { uuid: communityId } },
|
||||
where: { uuid: spaceUuid, community: { uuid: communityUuid } },
|
||||
});
|
||||
|
||||
if (!space) {
|
||||
throw new HttpException(
|
||||
`Space with ID ${spaceId} not found`,
|
||||
`Space with ID ${spaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
@ -168,7 +171,7 @@ export class SpaceService {
|
||||
await this.spaceRepository.remove(space);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: `Space with ID ${spaceId} successfully deleted`,
|
||||
message: `Space with ID ${spaceUuid} successfully deleted`,
|
||||
statusCode: HttpStatus.OK,
|
||||
});
|
||||
} catch (error) {
|
||||
@ -183,7 +186,7 @@ export class SpaceService {
|
||||
}
|
||||
|
||||
async updateSpace(
|
||||
spaceId: string,
|
||||
spaceUuid: string,
|
||||
communityId: string,
|
||||
updateSpaceDto: AddSpaceDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
@ -202,12 +205,12 @@ export class SpaceService {
|
||||
|
||||
// Check if the space exists
|
||||
const space = await this.spaceRepository.findOne({
|
||||
where: { uuid: spaceId, community: { uuid: communityId } },
|
||||
where: { uuid: spaceUuid, community: { uuid: communityId } },
|
||||
});
|
||||
|
||||
if (!space) {
|
||||
throw new HttpException(
|
||||
`Space with ID ${spaceId} not found`,
|
||||
`Space with ID ${spaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
@ -241,7 +244,7 @@ export class SpaceService {
|
||||
await this.spaceRepository.save(space);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: `Space with ID ${spaceId} successfully updated`,
|
||||
message: `Space with ID ${spaceUuid} successfully updated`,
|
||||
data: space,
|
||||
statusCode: HttpStatus.OK,
|
||||
});
|
||||
@ -256,15 +259,17 @@ export class SpaceService {
|
||||
}
|
||||
}
|
||||
|
||||
async getSpacesHierarchyForSpace(spaceId: string): Promise<BaseResponseDto> {
|
||||
async getSpacesHierarchyForSpace(
|
||||
spaceUuid: string,
|
||||
): Promise<BaseResponseDto> {
|
||||
const space = await this.spaceRepository.findOne({
|
||||
where: { uuid: spaceId },
|
||||
where: { uuid: spaceUuid },
|
||||
});
|
||||
|
||||
// If the space doesn't exist, throw a 404 error
|
||||
if (!space) {
|
||||
throw new HttpException(
|
||||
`Space with ID ${spaceId} not found`,
|
||||
`Space with ID ${spaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
@ -272,7 +277,7 @@ export class SpaceService {
|
||||
try {
|
||||
// Get all spaces that are children of the provided space, including the parent-child relations
|
||||
const spaces = await this.spaceRepository.find({
|
||||
where: { parent: { uuid: spaceId } },
|
||||
where: { parent: { uuid: spaceUuid } },
|
||||
relations: ['parent', 'children'], // Include parent and children relations
|
||||
});
|
||||
|
||||
@ -280,7 +285,7 @@ export class SpaceService {
|
||||
const spaceHierarchy = this.buildSpaceHierarchy(spaces);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: `Spaces under space ${spaceId} successfully fetched in hierarchy`,
|
||||
message: `Spaces under space ${spaceUuid} successfully fetched in hierarchy`,
|
||||
data: spaceHierarchy,
|
||||
statusCode: HttpStatus.OK,
|
||||
});
|
||||
|
2
src/space/services/subspace/index.ts
Normal file
2
src/space/services/subspace/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './subspace.service';
|
||||
export * from './subspace-device.service';
|
128
src/space/services/subspace/subspace-device.service.ts
Normal file
128
src/space/services/subspace/subspace-device.service.ts
Normal file
@ -0,0 +1,128 @@
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||
import {
|
||||
SpaceRepository,
|
||||
SubspaceRepository,
|
||||
} from '@app/common/modules/space/repositories';
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { DeviceSubSpaceParam, GetSubSpaceParam } from '../../dtos';
|
||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||
|
||||
@Injectable()
|
||||
export class SubspaceDeviceService {
|
||||
constructor(
|
||||
private readonly spaceRepository: SpaceRepository,
|
||||
private readonly communityRepository: CommunityRepository,
|
||||
private readonly subspaceRepository: SubspaceRepository,
|
||||
private readonly deviceRepository: DeviceRepository,
|
||||
) {}
|
||||
|
||||
async listDevicesInSubspace(
|
||||
params: GetSubSpaceParam,
|
||||
): Promise<BaseResponseDto> {
|
||||
const { subSpaceUuid, spaceUuid, communityUuid } = params;
|
||||
|
||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||
|
||||
const subspace = await this.findSubspaceWithDevices(subSpaceUuid);
|
||||
return new SuccessResponseDto({
|
||||
data: subspace.devices,
|
||||
message: 'Successfully retrieved list of devices',
|
||||
});
|
||||
}
|
||||
|
||||
async associateDeviceToSubspace(params: DeviceSubSpaceParam) {
|
||||
const { subSpaceUuid, deviceUuid, spaceUuid, communityUuid } = params;
|
||||
|
||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||
|
||||
const subspace = await this.findSubspace(subSpaceUuid);
|
||||
const device = await this.findDevice(deviceUuid);
|
||||
|
||||
device.subspace = subspace;
|
||||
await this.deviceRepository.save(device);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
data: device,
|
||||
message: 'Successfully associated device to subspace',
|
||||
});
|
||||
}
|
||||
|
||||
async disassociateDeviceFromSubspace(params: DeviceSubSpaceParam) {
|
||||
const { subSpaceUuid, deviceUuid, spaceUuid, communityUuid } = params;
|
||||
|
||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||
|
||||
await this.findSubspace(subSpaceUuid);
|
||||
const device = await this.findDevice(deviceUuid);
|
||||
|
||||
device.subspace = null;
|
||||
await this.deviceRepository.save(device);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
data: device,
|
||||
message: 'Successfully dissociated device from subspace',
|
||||
});
|
||||
}
|
||||
|
||||
// Helper method to validate community and space
|
||||
private async validateCommunityAndSpace(
|
||||
communityUuid: string,
|
||||
spaceUuid: string,
|
||||
) {
|
||||
const community = await this.communityRepository.findOne({
|
||||
where: { uuid: communityUuid },
|
||||
});
|
||||
if (!community) {
|
||||
this.throwNotFound('Community', communityUuid);
|
||||
}
|
||||
|
||||
const space = await this.spaceRepository.findOne({
|
||||
where: { uuid: spaceUuid, community: { uuid: communityUuid } },
|
||||
});
|
||||
if (!space) {
|
||||
this.throwNotFound('Space', spaceUuid);
|
||||
}
|
||||
return space;
|
||||
}
|
||||
|
||||
// Helper method to find subspace with devices relation
|
||||
private async findSubspaceWithDevices(subSpaceUuid: string) {
|
||||
const subspace = await this.subspaceRepository.findOne({
|
||||
where: { uuid: subSpaceUuid },
|
||||
relations: ['devices'],
|
||||
});
|
||||
if (!subspace) {
|
||||
this.throwNotFound('Subspace', subSpaceUuid);
|
||||
}
|
||||
return subspace;
|
||||
}
|
||||
|
||||
private async findSubspace(subSpaceUuid: string) {
|
||||
const subspace = await this.subspaceRepository.findOne({
|
||||
where: { uuid: subSpaceUuid },
|
||||
});
|
||||
if (!subspace) {
|
||||
this.throwNotFound('Subspace', subSpaceUuid);
|
||||
}
|
||||
return subspace;
|
||||
}
|
||||
|
||||
private async findDevice(deviceUuid: string) {
|
||||
const device = await this.deviceRepository.findOne({
|
||||
where: { uuid: deviceUuid },
|
||||
});
|
||||
if (!device) {
|
||||
this.throwNotFound('Device', deviceUuid);
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
private throwNotFound(entity: string, uuid: string) {
|
||||
throw new HttpException(
|
||||
`${entity} with ID ${uuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import {
|
||||
SubspaceRepository,
|
||||
} from '@app/common/modules/space/repositories';
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { AddSubspaceDto, GetSpaceParam, GetSubSpaceParam } from '../dtos';
|
||||
import { AddSubspaceDto, GetSpaceParam, GetSubSpaceParam } from '../../dtos';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import {
|
||||
TypeORMCustomModel,
|
@ -6,7 +6,12 @@ import {
|
||||
SpaceUserController,
|
||||
SubSpaceController,
|
||||
} from './controllers';
|
||||
import { SpaceService, SpaceUserService, SubSpaceService } from './services';
|
||||
import {
|
||||
SpaceService,
|
||||
SpaceUserService,
|
||||
SubspaceDeviceService,
|
||||
SubSpaceService,
|
||||
} from './services';
|
||||
import {
|
||||
SpaceRepository,
|
||||
SubspaceRepository,
|
||||
@ -16,14 +21,22 @@ import {
|
||||
UserRepository,
|
||||
UserSpaceRepository,
|
||||
} from '@app/common/modules/user/repositories';
|
||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule, SpaceRepositoryModule],
|
||||
controllers: [SpaceController, SpaceUserController, SubSpaceController],
|
||||
controllers: [
|
||||
SpaceController,
|
||||
SpaceUserController,
|
||||
SubSpaceController,
|
||||
SubSpaceController,
|
||||
],
|
||||
providers: [
|
||||
SpaceService,
|
||||
SubSpaceService,
|
||||
SubspaceDeviceService,
|
||||
SpaceRepository,
|
||||
DeviceRepository,
|
||||
CommunityRepository,
|
||||
SubspaceRepository,
|
||||
UserSpaceRepository,
|
||||
|
Reference in New Issue
Block a user