anonymous form submissions

fixes anonymous form submissions (fixes https://github.com/ohmyform/ohmyform/issue
This commit is contained in:
Michael Schramm 2022-01-03 08:16:39 +01:00
parent 6c0181c09d
commit ea718a2e44
11 changed files with 71 additions and 3 deletions

View File

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- email verification
- idx for fields and logic to have stable order
- ability to load submission by id if token is present
- anonymous form submissions (fixes https://github.com/ohmyform/ohmyform/issues/108)
### Changed

View File

@ -52,6 +52,7 @@
"html-to-text": "^8.1.0",
"inquirer": "^8.2.0",
"ioredis": "^4.28.2",
"ip-anonymize": "^0.1.0",
"matomo-tracker": "^2.2.4",
"mjml": "^4.11.0",
"mysql2": "^2.3.3",

View File

@ -11,6 +11,9 @@ export class FormCreateInput {
@Field({ nullable: true })
readonly showFooter: boolean
@Field({ nullable: true })
readonly anonymousSubmission: boolean
@Field({ nullable: true })
readonly isLive: boolean

View File

@ -21,6 +21,9 @@ export class FormModel {
@Field()
readonly showFooter: boolean
@Field()
readonly anonymousSubmission: boolean
constructor(form: FormEntity) {
this.id = form.id.toString()
this.title = form.title
@ -28,5 +31,6 @@ export class FormModel {
this.lastModified = form.lastModified
this.language = form.language
this.showFooter = form.showFooter
this.anonymousSubmission = form.anonymousSubmission
}
}

View File

@ -19,6 +19,9 @@ export class FormUpdateInput {
@Field({ nullable: true })
readonly showFooter: boolean
@Field({ nullable: true })
readonly anonymousSubmission: boolean
@Field({ nullable: true })
readonly isLive: boolean

View File

@ -61,6 +61,9 @@ export class FormEntity {
@Column()
public isLive: boolean;
@Column({ default: false })
public anonymousSubmission: boolean;
@Column(() => DesignEmbedded)
public design: DesignEmbedded = new DesignEmbedded();
@ -69,5 +72,4 @@ export class FormEntity {
@UpdateDateColumn()
public lastModified: Date
}

View File

@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class anonymous1641193946192 implements MigrationInterface {
name = 'anonymous1641193946192'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `form` ADD `anonymousSubmission` tinyint NOT NULL DEFAULT 0');
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `form` DROP COLUMN `anonymousSubmission`');
}
}

View File

@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class anonymous1641193946192 implements MigrationInterface {
name = 'anonymous1641193946192'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE "form" ADD "anonymousSubmission" boolean NOT NULL DEFAULT false');
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE "form" DROP COLUMN "anonymousSubmission"');
}
}

View File

@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class anonymous1641193946192 implements MigrationInterface {
name = 'anonymous1641193946192'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('CREATE TABLE "temporary_form" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar NOT NULL, "language" varchar(10) NOT NULL, "showFooter" boolean NOT NULL, "isLive" boolean NOT NULL, "created" datetime NOT NULL DEFAULT (datetime(\'now\')), "lastModified" datetime NOT NULL DEFAULT (datetime(\'now\')), "adminId" integer, "startPageId" integer, "endPageId" integer, "analyticsGacode" varchar, "designFont" varchar, "designColorsBackground" varchar, "designColorsQuestion" varchar, "designColorsAnswer" varchar, "designColorsButton" varchar, "designColorsButtonactive" varchar, "designColorsButtontext" varchar, "designLayout" varchar, "anonymousSubmission" boolean NOT NULL DEFAULT (0), CONSTRAINT "FK_a7cb33580bca2b362e5e34fdfcd" FOREIGN KEY ("adminId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_023d9cf1d97e93facc96c86ca70" FOREIGN KEY ("startPageId") REFERENCES "page" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_e5d158932e43cfbf9958931ee01" FOREIGN KEY ("endPageId") REFERENCES "page" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)');
await queryRunner.query('INSERT INTO "temporary_form"("id", "title", "language", "showFooter", "isLive", "created", "lastModified", "adminId", "startPageId", "endPageId", "analyticsGacode", "designFont", "designColorsBackground", "designColorsQuestion", "designColorsAnswer", "designColorsButton", "designColorsButtonactive", "designColorsButtontext", "designLayout") SELECT "id", "title", "language", "showFooter", "isLive", "created", "lastModified", "adminId", "startPageId", "endPageId", "analyticsGacode", "designFont", "designColorsBackground", "designColorsQuestion", "designColorsAnswer", "designColorsButton", "designColorsButtonactive", "designColorsButtontext", "designLayout" FROM "form"');
await queryRunner.query('DROP TABLE "form"');
await queryRunner.query('ALTER TABLE "temporary_form" RENAME TO "form"');
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE "form" RENAME TO "temporary_form"');
await queryRunner.query('CREATE TABLE "form" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar NOT NULL, "language" varchar(10) NOT NULL, "showFooter" boolean NOT NULL, "isLive" boolean NOT NULL, "created" datetime NOT NULL DEFAULT (datetime(\'now\')), "lastModified" datetime NOT NULL DEFAULT (datetime(\'now\')), "adminId" integer, "startPageId" integer, "endPageId" integer, "analyticsGacode" varchar, "designFont" varchar, "designColorsBackground" varchar, "designColorsQuestion" varchar, "designColorsAnswer" varchar, "designColorsButton" varchar, "designColorsButtonactive" varchar, "designColorsButtontext" varchar, "designLayout" varchar, CONSTRAINT "FK_a7cb33580bca2b362e5e34fdfcd" FOREIGN KEY ("adminId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_023d9cf1d97e93facc96c86ca70" FOREIGN KEY ("startPageId") REFERENCES "page" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_e5d158932e43cfbf9958931ee01" FOREIGN KEY ("endPageId") REFERENCES "page" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)');
await queryRunner.query('INSERT INTO "form"("id", "title", "language", "showFooter", "isLive", "created", "lastModified", "adminId", "startPageId", "endPageId", "analyticsGacode", "designFont", "designColorsBackground", "designColorsQuestion", "designColorsAnswer", "designColorsButton", "designColorsButtonactive", "designColorsButtontext", "designLayout") SELECT "id", "title", "language", "showFooter", "isLive", "created", "lastModified", "adminId", "startPageId", "endPageId", "analyticsGacode", "designFont", "designColorsBackground", "designColorsQuestion", "designColorsAnswer", "designColorsButton", "designColorsButtonactive", "designColorsButtontext", "designLayout" FROM "temporary_form"');
await queryRunner.query('DROP TABLE "temporary_form"');
}
}

View File

@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import anonymize from 'ip-anonymize'
import { Repository } from 'typeorm'
import { SubmissionStartInput } from '../../dto/submission/submission.start.input'
import { FormEntity } from '../../entity/form.entity'
@ -24,9 +25,12 @@ export class SubmissionStartService {
): Promise<SubmissionEntity> {
const submission = new SubmissionEntity()
if (!form.anonymousSubmission) {
submission.user = user
}
submission.form = form
submission.user = user
submission.ipAddr = ipAddr || '?'
submission.ipAddr = anonymize(ipAddr, 16, 16) || '?'
submission.timeElapsed = 0
submission.percentageComplete = 0

View File

@ -4551,6 +4551,11 @@ ioredis@^4.17.3, ioredis@^4.28.2:
redis-parser "^3.0.0"
standard-as-callback "^2.1.0"
ip-anonymize@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/ip-anonymize/-/ip-anonymize-0.1.0.tgz#5ead504d01871c5c28189a25382f852036b57f7e"
integrity sha512-cZJu+N5JKKFGMK0eEQWNaQMn2EhCysciVM6eotCJwfqotj16BTfVchKsJCH6mQAT9N0GC7oWRcsZ6Lb8dDiwTA==
ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"