Skip to content

Commit

Permalink
Feature/iot 118 move device (#263)
Browse files Browse the repository at this point in the history
* Added relations to organization for applications and deviceModels. Tbd, if this is the best approach or if another endpoint should be created.

* Added endpoint to change iot devices, and all their connections.

* Added exception for moving sigfox devices for the endpoint.

* Pr fixes

---------

Co-authored-by: Frederik Christ Vestergaard <[email protected]>
  • Loading branch information
MadsApollo and fcv-iteratorIt authored Sep 26, 2024
1 parent e79f365 commit fc5bf77
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 213 deletions.
31 changes: 31 additions & 0 deletions src/controllers/admin-controller/iot-device.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import { MQTTInternalBrokerDeviceDTO } from "@dto/mqtt-internal-broker-device.dt
import { MQTTExternalBrokerDeviceDTO } from "@dto/mqtt-external-broker-device.dto";
import { ApiAuth } from "@auth/swagger-auth-decorator";
import { DownlinkQueueDto } from "@dto/downlink.dto";
import { UpdateIoTDeviceApplication } from "@dto/update-iot-device-application.dto";

@ApiTags("IoT Device")
@Controller("iot-device")
Expand Down Expand Up @@ -260,6 +261,36 @@ export class IoTDeviceController {
return iotDevice;
}

@Put("changeApplication/:id")
@Header("Cache-Control", "none")
@ApiOperation({ summary: "Update an existing IoT-Device" })
@ApiBadRequestResponse()
async changeApplication(
@Req() req: AuthenticatedRequest,
@Param("id", new ParseIntPipe()) id: number,
@Body() updateDto: UpdateIoTDeviceApplication
): Promise<IoTDevice> {
// Old application
const dbIotDevice = await this.iotDeviceService.findOneWithApplicationAndMetadata(id, false);

if (dbIotDevice.type === IoTDeviceType.SigFox) throw new BadRequestException(ErrorCodes.NotValidFormat);

try {
checkIfUserHasAccessToApplication(req, dbIotDevice.application.id, ApplicationAccessScope.Write);
if (updateDto.applicationId !== dbIotDevice.application.id) {
// New application
checkIfUserHasAccessToApplication(req, updateDto.applicationId, ApplicationAccessScope.Write);
}
} catch (err) {
AuditLog.fail(ActionType.UPDATE, IoTDevice.name, req.user.userId, id);
throw err;
}

const iotDevice = await this.iotDeviceService.changeApplication(id, updateDto, req.user.userId);
AuditLog.success(ActionType.UPDATE, IoTDevice.name, req.user.userId, iotDevice.id, iotDevice.name);
return iotDevice;
}

@Post("createMany")
@Header("Cache-Control", "none")
@ApiOperation({ summary: "Create many IoT-Devices" })
Expand Down
14 changes: 14 additions & 0 deletions src/entities/dto/update-iot-device-application.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ApiProperty } from "@nestjs/swagger";

interface DataTargetToPayloadDecoder {
dataTargetId: number;
payloadDecoderId: number;
}

export class UpdateIoTDeviceApplication {
public deviceModelId: number;
public organizationId: number;
public applicationId: number;
@ApiProperty({ required: true })
public dataTargetToPayloadDecoderIds: DataTargetToPayloadDecoder[];
}
4 changes: 4 additions & 0 deletions src/modules/device-management/iot-device.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { EncryptionHelperService } from "@services/encryption-helper.service";
import { CsvGeneratorService } from "@services/csv-generator.service";
import { LorawanDeviceDatabaseEnrichJob } from "@services/device-management/lorawan-device-database-enrich-job";
import { OrganizationModule } from "@modules/user-management/organization.module";
import { DataTargetModule } from "./data-target.module";
import { PayloadDecoderModule } from "./payload-decoder.module";

@Module({
imports: [
Expand All @@ -34,6 +36,8 @@ import { OrganizationModule } from "@modules/user-management/organization.module
forwardRef(() => SigfoxDeviceModule),
forwardRef(() => IoTLoRaWANDeviceModule),
InternalMqttListenerModule,
DataTargetModule,
forwardRef(() => PayloadDecoderModule),
],
exports: [MqttService, IoTDeviceService, IoTDeviceDownlinkService],
controllers: [IoTDeviceController, IoTDevicePayloadDecoderController],
Expand Down
4 changes: 2 additions & 2 deletions src/modules/device-management/payload-decoder.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Module } from "@nestjs/common";
import { forwardRef, Module } from "@nestjs/common";

import { PayloadDecoderController } from "@admin-controller/payload-decoder.controller";
import { DataTargetModule } from "@modules/device-management/data-target.module";
Expand All @@ -8,7 +8,7 @@ import { OrganizationModule } from "@modules/user-management/organization.module
import { PayloadDecoderService } from "@services/data-management/payload-decoder.service";

@Module({
imports: [SharedModule, IoTDeviceModule, DataTargetModule, OrganizationModule],
imports: [SharedModule, forwardRef(() => IoTDeviceModule), DataTargetModule, OrganizationModule],
exports: [PayloadDecoderService],
controllers: [PayloadDecoderController],
providers: [PayloadDecoderService],
Expand Down
6 changes: 3 additions & 3 deletions src/services/device-management/application.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class ApplicationService {
where: orgCondition,
take: query.limit,
skip: query.offset,
relations: ["iotDevices", "dataTargets", "controlledProperties", "deviceTypes"],
relations: ["iotDevices", "dataTargets", "controlledProperties", "deviceTypes", nameof<Application>("belongsTo")],
order: sorting,
});

Expand All @@ -83,7 +83,7 @@ export class ApplicationService {
: { id: In(allowedApplications) },
take: query.limit,
skip: query.offset,
relations: ["iotDevices"],
relations: ["iotDevices", nameof<Application>("belongsTo")],
order: { id: query.sort },
});

Expand All @@ -102,7 +102,7 @@ export class ApplicationService {
where: allowedOrganisations != null ? { belongsTo: In(allowedOrganisations) } : {},
take: +query.limit,
skip: +query.offset,
relations: ["iotDevices", "dataTargets", "controlledProperties", "deviceTypes"],
relations: ["iotDevices", "dataTargets", "controlledProperties", "deviceTypes", nameof<Application>("belongsTo")],
order: sorting,
});

Expand Down
2 changes: 2 additions & 0 deletions src/services/device-management/device-model.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as AJV from "ajv";
import { deviceModelSchema } from "@resources/device-model-schema";
import { UpdateDeviceModelDto } from "@dto/update-device-model.dto";
import { ListAllEntitiesDto } from "@dto/list-all-entities.dto";
import { nameof } from "@helpers/type-helper";

@Injectable()
export class DeviceModelService {
Expand Down Expand Up @@ -52,6 +53,7 @@ export class DeviceModelService {
take: query?.limit ? +query.limit : 100,
skip: query?.offset ? +query.offset : 0,
order: this.getSorting(query),
relations: [nameof<DeviceModel>("belongsTo")],
});

return {
Expand Down
Loading

0 comments on commit fc5bf77

Please sign in to comment.