Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/entities/application.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,7 @@ export class Application extends DbBaseEntity {

@Column({ nullable: true })
chirpstackId?: string;

@Column({ type: "jsonb", nullable: true })
metadata: JSON;
}
6 changes: 6 additions & 0 deletions src/entities/dto/create-application.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IsPhoneNumberString } from "@helpers/phone-number.validator";
import { nameof } from "@helpers/type-helper";
import { ApiProperty } from "@nestjs/swagger";
import { ArrayUnique, IsArray, IsBoolean, IsEnum, IsOptional, IsString, MaxLength, MinLength } from "class-validator";
import { IsMetadataJsonObject } from "@helpers/is-metadata-json-object.validator";

export class CreateApplicationDto {
@ApiProperty({ required: true })
Expand Down Expand Up @@ -96,4 +97,9 @@ export class CreateApplicationDto {
@IsString()
@MaxLength(1024)
chirpstackId?: string;

@ApiProperty({ required: false })
@IsOptional()
@IsMetadataJsonObject(nameof<CreateApplicationDto>("metadata"))
metadata?: JSON;
}
55 changes: 55 additions & 0 deletions src/helpers/is-metadata-json-object.validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ErrorCodes } from "@enum/error-codes.enum";
import {
registerDecorator,
ValidationArguments,
ValidationOptions,
ValidatorConstraint,
ValidatorConstraintInterface,
} from "class-validator";

@ValidatorConstraint({ name: "isMetadataJsonObject", async: false })
export class IsMetadataJsonObjectConstraint implements ValidatorConstraintInterface {
private message = "";

public validate(value: any, args: ValidationArguments): boolean {
const [propertyName] = args.constraints;
this.message = `${propertyName} must be an object with non-empty string keys and values`;

if (typeof value !== "object") {
return false;
}
try {
for (const key of Object.keys(value)) {
if (typeof key !== "string" || key.trim() === "") {
this.message = ErrorCodes.InvalidKeyInKeyValuePair;
return false;
}
if (typeof value[key] !== "string" || value[key].trim() === "") {
this.message = ErrorCodes.InvalidValueInKeyValuePair;
return false;
}
}
} catch (error) {
return false;
}

return true;
}

public defaultMessage(_args: ValidationArguments): string {
return this.message;
}
}

export function IsMetadataJsonObject(property: string, validationOptions?: ValidationOptions) {
return function (object: unknown, propertyName: string): void {
registerDecorator({
name: "isMetadataJsonObject",
target: object.constructor,
propertyName: propertyName,
constraints: [property],
options: validationOptions,
validator: IsMetadataJsonObjectConstraint,
});
};
}
14 changes: 14 additions & 0 deletions src/migration/1773923548971-add-application-metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class AddApplicationMetadata1773923548971 implements MigrationInterface {
name = 'AddApplicationMetadata1773923548971'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "application" ADD "metadata" jsonb`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "application" DROP COLUMN "metadata"`);
}

}
1 change: 1 addition & 0 deletions src/services/device-management/application.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ export class ApplicationService {
application.personalData = applicationDto.personalData;
application.hardware = applicationDto.hardware;
application.permissions = await this.permissionService.findManyByIds(applicationDto.permissionIds);
application.metadata = applicationDto.metadata;

// Set metadata dependencies
application.controlledProperties = applicationDto.controlledProperties
Expand Down