Skip to content

Commit 4cb99ba

Browse files
authored
Ignore structural change warning on form publish (getodk#749)
* ignore structural change warning on form publish * added test to verify publish event is logged for managed encryption
1 parent ab8f672 commit 4cb99ba

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

lib/model/query/forms.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,14 @@ const _getDraftToken = (form) => {
129129
return generateToken();
130130
};
131131

132-
const createVersion = (partial, form, publish = false) => async ({ run, one, Datasets, FormAttachments, Forms, Keys }) => {
132+
// Parameters:
133+
// ===========
134+
// partial: Partial form definition of the new version
135+
// form: Form frame of existing form
136+
// publish: set true if you want new version to be published
137+
// duplicating: set true if copying form definition from previously uploaded definition, in that cases we don't check for structural change
138+
// as user has already been warned otherwise set false
139+
const createVersion = (partial, form, publish = false, duplicating = false) => async ({ run, one, Datasets, FormAttachments, Forms, Keys }) => {
133140
// Check xmlFormId match
134141
if (form.xmlFormId !== partial.xmlFormId)
135142
return reject(Problem.user.unexpectedValue({ field: 'xmlFormId', value: partial.xmlFormId, reason: 'does not match the form you are updating' }));
@@ -163,8 +170,13 @@ const createVersion = (partial, form, publish = false) => async ({ run, one, Dat
163170
// Only need to check new fields against old fields if the structure does not match
164171
const allFields = await Forms.getMergedFields(form.id);
165172
await Forms.checkFieldDowncast(allFields, fields);
166-
await Forms.checkStructuralChange(prevFields, fields)
167-
.then(Forms.rejectIfWarnings);
173+
174+
// skip checking for structural change if duplicating because user has already
175+
// been warning at the time of form definition upload
176+
if (!duplicating) {
177+
await Forms.checkStructuralChange(prevFields, fields)
178+
.then(Forms.rejectIfWarnings);
179+
}
168180
// If we haven't been rejected or warned yet, make a new schema id
169181
schemaId = await Forms._newSchema();
170182
}
@@ -207,7 +219,7 @@ const createVersion = (partial, form, publish = false) => async ({ run, one, Dat
207219
return savedDef;
208220
};
209221

210-
createVersion.audit = (newDef, partial, form, _, publish) => (log) => ((publish === true)
222+
createVersion.audit = (newDef, partial, form, publish) => (log) => ((publish === true)
211223
? log('form.update.publish', form, { oldDefId: form.currentDefId, newDefId: newDef.id })
212224
: log('form.update.draft.set', form, { oldDraftDefId: form.draftDefId, newDraftDefId: newDef.id }));
213225
createVersion.audit.withResult = true;

lib/resources/forms.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ module.exports = (service, endpoint) => {
125125
.then(Form.fromXml)
126126
// copy forward xlsx reference since no real change was made
127127
.then((partial) => partial.withAux('xls', { xlsBlobId: form.def.xlsBlobId }))
128-
.then((partial) => Forms.createVersion(partial, form, false))
128+
.then((partial) => Forms.createVersion(partial, form, false, true))
129129
.then(() => Forms.getByProjectAndXmlFormId(params.projectId, params.id, false, Form.DraftVersion))
130130
.then(getOrNotFound)
131131
: resolve(form)))

test/integration/api/forms/forms.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,18 @@ describe('api: /projects/:id/forms (create, read, update)', () => {
405405
});
406406
}));
407407

408+
it('should reject with structure changed warning', testService(async (service) => {
409+
const asAlice = await service.login('alice', identity);
410+
411+
await asAlice.post('/v1/projects/1/forms/simple/draft?ignoreWarnings=true')
412+
.send(testData.forms.simple.replace(/age/g, 'address'))
413+
.set('Content-Type', 'application/xml')
414+
.expect(200);
415+
416+
await asAlice.post('/v1/projects/1/forms/simple/draft/publish?ignoreWarnings=true&version=v2')
417+
.expect(200);
418+
}));
419+
408420
it('should reject with xls and structure changed warnings', testService(async (service) => {
409421
const asAlice = await service.login('alice', identity);
410422

test/integration/other/encryption.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,22 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff
678678
csv[2].should.eql([ 'one','Alice','30','one','5','Alice','0','0','','','','0','' ]);
679679
csv[3].should.eql([ '' ]);
680680
}))))));
681+
682+
it('should log publish events in the audits', testService(async (service) => {
683+
const asAlice = await service.login('alice');
684+
685+
// There are the forms in the fixture that get re-published with managed encryption
686+
await asAlice.post('/v1/projects/1/key')
687+
.send({ passphrase: 'supersecret', hint: 'it is a secret' })
688+
.expect(200);
689+
690+
await asAlice.get('/v1/audits?action=form')
691+
.expect(200)
692+
.then(({ body: logs }) => {
693+
logs.forEach(l => l.action.should.be.eql('form.update.publish'));
694+
});
695+
696+
}));
681697
});
682698
});
683699

0 commit comments

Comments
 (0)