diff --git a/CHANGELOG.md b/CHANGELOG.md index 03b831a..e3f7c45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added +- allow one field nested data to be submitted + ### Changed ### Fixed - only update user fields in update mutation if they changed - form delete +- field submission without value field ### Security diff --git a/src/entity/submission.field.entity.ts b/src/entity/submission.field.entity.ts index e3921e0..c386622 100644 --- a/src/entity/submission.field.entity.ts +++ b/src/entity/submission.field.entity.ts @@ -2,8 +2,12 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, RelationId } from 't import { FormFieldEntity } from './form.field.entity' import { SubmissionEntity } from './submission.entity' -export interface SubmissionFieldContent { - [key: string]: string | string[] | number | number[] | boolean | boolean[] +type Simple = string | number | boolean + +export type SubmissionFieldContent = Simple | Simple[] | { + [key: string]: Simple | Simple[] | { + [key: string]: Simple | Simple[] + } } @Entity({ name: 'submission_field' }) diff --git a/src/service/submission/submission.notification.service.ts b/src/service/submission/submission.notification.service.ts index 95a5a05..4c03460 100644 --- a/src/service/submission/submission.notification.service.ts +++ b/src/service/submission/submission.notification.service.ts @@ -79,8 +79,8 @@ export class SubmissionNotificationService { return fallback } - if (typeof data.value === 'string') { - return data.value + if (typeof data === 'string') { + return data } return fallback diff --git a/src/service/submission/submission.set.field.service.ts b/src/service/submission/submission.set.field.service.ts index 9a7111b..bfc7df6 100644 --- a/src/service/submission/submission.set.field.service.ts +++ b/src/service/submission/submission.set.field.service.ts @@ -84,7 +84,7 @@ export class SubmissionSetFieldService { field: SubmissionFieldEntity, data: string ): SubmissionFieldContent { - let raw: { [key: string]: unknown } + let raw: SubmissionFieldContent const context = { field: field.fieldId, @@ -92,21 +92,49 @@ export class SubmissionSetFieldService { } try { - raw = JSON.parse(data) as { [key: string]: unknown } + raw = JSON.parse(data) as SubmissionFieldContent } catch (e) { this.logger.warn(context, 'received invalid data for field') return { value: null } } - if (typeof raw !== 'object' || Array.isArray(raw)) { - this.logger.warn(context, 'only object supported for data') - return { value: null } + if (Array.isArray(raw)) { + return raw.map((row: unknown, index) => { + switch (typeof row) { + case 'number': + case 'string': + case 'boolean': + case 'undefined': + return row + } + + if (row === null) { + return row + } + + this.logger.warn({ + ...context, + path: `${index}`, + }, 'invalid data in array') + valid = false + + return null + }) + } + + if ( + [ + 'number', + 'string', + 'boolean', + 'undefined', + ].includes(typeof raw) + ) { + return raw } // now ensure data structure - const result = { - value: null, - } + const result = {} let valid = true @@ -147,6 +175,48 @@ export class SubmissionSetFieldService { return } + if (typeof value === 'object') { + result[String(key)] = {} + + for (const subKey of Object.keys(value)) { + const subValue = raw[String(key)][String(subKey)] + + switch (typeof subValue) { + case 'number': + case 'string': + case 'boolean': + result[String(key)][String(subKey)] = subValue + return + } + + if (Array.isArray(subValue)) { + result[String(key)][String(subKey)] = subValue.map((row: unknown, index) => { + switch (typeof row) { + case 'number': + case 'string': + case 'boolean': + case 'undefined': + return row + } + + if (row === null) { + return row + } + + this.logger.warn({ + ...context, + path: `${key}/${subKey}/${index}`, + }, 'invalid data in array') + valid = false + + return null + }) + + return + } + } + } + this.logger.warn({ ...context, path: String(key),