Skip to content

Commit

Permalink
changing code and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ktuite committed Oct 15, 2024
1 parent 23adbc8 commit d885fdf
Show file tree
Hide file tree
Showing 3 changed files with 244 additions and 3 deletions.
15 changes: 14 additions & 1 deletion lib/model/query/forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,20 @@ createVersion.audit = (newDef, partial, form, publish) => (log) => ((publish ===
? log('form.update.publish', form, { oldDefId: form.currentDefId, newDefId: newDef.id })
: log('form.update.draft.set', form, { oldDraftDefId: form.draftDefId, newDraftDefId: newDef.id }));
createVersion.audit.withResult = true;
createVersion.audit.logEvenIfAnonymous = true;

// This is used in the rare case where we want to change and update a FormDef in place without
// creating a new def. This is basically a wrapper around _updateDef that also logs an event.
const replaceDef = (partial, form) => async ({ Forms }) => {
const { version, hash, sha, sha256 } = partial.def;
await Forms._updateDef(form.def, { xml: partial.xml, version, hash, sha, sha256 });
// all this does is changed updatedAt
await Forms._update(form, { updatedAt: (new Date()).toISOString() });
};

replaceDef.audit = (_, form) => (log) =>
log('form.update.draft.replace', form, { upgrade: 'Updated entities-version in form to 2024.1' });
replaceDef.audit.logEvenIfAnonymous = true;

////////////////////////////////////////////////////////////////////////////////
// PUBLISHING MANAGEMENT
Expand Down Expand Up @@ -807,7 +820,7 @@ module.exports = {
_insertFormFields,
_createNew, createNew, _createNewDef, createVersion,
publish, clearDraft,
_update, update, _updateDef, del, restore, purge,
_update, update, _updateDef, replaceDef, del, restore, purge,
clearUnneededDrafts,
setManagedKey,
getByAuthForOpenRosa,
Expand Down
5 changes: 3 additions & 2 deletions lib/worker/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,17 @@ const updateEntitiesVersion = async ({ Forms }, event) => {
const publishedVersion = await Forms.getByProjectAndXmlFormId(projectId, xmlFormId, true, Form.PublishedVersion).then(o => o.orNull());
if (publishedVersion && publishedVersion.currentDefId != null) {
const partial = await _upgradeEntityVersion(publishedVersion);
if (partial != null)
if (partial != null) {
await Forms.createVersion(partial, publishedVersion, true, true);
}
}

const draftVersion = await Forms.getByProjectAndXmlFormId(projectId, xmlFormId, true, Form.DraftVersion).then(o => o.orNull());
if (draftVersion && draftVersion.draftDefId != null) {
const partial = await _upgradeEntityVersion(draftVersion);
// update xml and version in place
if (partial != null)
await Forms._updateDef(draftVersion.def, { xml: partial.xml, version: partial.def.version });
await Forms.replaceDef(partial, draftVersion);
}
};

Expand Down
227 changes: 227 additions & 0 deletions test/integration/other/form-entities-version.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { readFileSync } = require('fs');
const should = require('should');
const config = require('config');
const appRoot = require('app-root-path');
const { testService } = require('../setup');
const testData = require('../../data/xml');
Expand Down Expand Up @@ -309,9 +311,234 @@ describe('Update / migrate entities-version within form', () => {
]);
});
}));

it('should update the formList once the form changes', testService(async (service, container) => {
const { Forms, Audits } = container;
const asAlice = await service.login('alice');
const domain = config.get('default.env.domain');

// Publish a form
await asAlice.post('/v1/projects/1/forms?publish=true')
.send(testData.forms.updateEntity)
.set('Content-Type', 'application/xml')
.expect(200);

// Create a draft as well
await asAlice.post('/v1/projects/1/forms/updateEntity/draft')
.expect(200);

const token = await asAlice.get('/v1/projects/1/forms/updateEntity/draft')
.expect(200)
.then(({ body }) => body.draftToken);

await asAlice.get('/v1/projects/1/formList')
.set('X-OpenRosa-Version', '1.0')
.expect(200)
.then(({ text }) => text.should.containEql(`<xform>
<formID>updateEntity</formID>
<name>updateEntity</name>
<version>1.0</version>
<hash>md5:e4902c380ef428aa3d35e4ed17ea6c04</hash>
<downloadUrl>${domain}/v1/projects/1/forms/updateEntity.xml</downloadUrl>
</xform>`));

await asAlice.get(`/v1/test/${token}/projects/1/forms/updateEntity/draft/formList`)
.set('X-OpenRosa-Version', '1.0')
.expect(200)
.then(({ text }) => text.should.containEql(`<xform>
<formID>updateEntity</formID>
<name>updateEntity</name>
<version>1.0</version>
<hash>md5:e4902c380ef428aa3d35e4ed17ea6c04</hash>
<downloadUrl>${domain}/v1/test/${token}/projects/1/forms/updateEntity/draft.xml</downloadUrl>
</xform>`));

const { acteeId } = await Forms.getByProjectAndXmlFormId(1, 'updateEntity').then(o => o.get());
await Audits.log(null, 'upgrade.process.form.entities_version', { acteeId });

// Run form upgrade
await exhaust(container);

await asAlice.get('/v1/projects/1/formList')
.set('X-OpenRosa-Version', '1.0')
.expect(200)
.then(({ text }) => text.should.containEql(`<xform>
<formID>updateEntity</formID>
<name>updateEntity</name>
<version>1.0[upgrade]</version>
<hash>md5:77292dd9e1ad532bb5a4f7128e0a9596</hash>
<downloadUrl>${domain}/v1/projects/1/forms/updateEntity.xml</downloadUrl>
</xform>`));

await asAlice.get(`/v1/test/${token}/projects/1/forms/updateEntity/draft/formList`)
.set('X-OpenRosa-Version', '1.0')
.expect(200)
.then(({ text }) => text.should.containEql(`<xform>
<formID>updateEntity</formID>
<name>updateEntity</name>
<version>1.0[upgrade]</version>
<hash>md5:77292dd9e1ad532bb5a4f7128e0a9596</hash>
<downloadUrl>${domain}/v1/test/${token}/projects/1/forms/updateEntity/draft.xml</downloadUrl>
</xform>`));
}));

it('should update the updatedAt timestamps on the form when updating a draft form', testService(async (service, container) => {
const { Forms, Audits } = container;
const asAlice = await service.login('alice');

// Upload a form and publish it
await asAlice.post('/v1/projects/1/forms')
.send(testData.forms.updateEntity)
.set('Content-Type', 'application/xml')
.expect(200);

// check updatedAt on the draft form
await asAlice.get('/v1/projects/1/forms/updateEntity')
.expect(200)
.then(({ body }) => {
should(body.updatedAt).be.null();
});

const { acteeId } = await Forms.getByProjectAndXmlFormId(1, 'updateEntity').then(o => o.get());
await Audits.log(null, 'upgrade.process.form.entities_version', { acteeId });

// Run form upgrade
await exhaust(container);

await asAlice.get('/v1/projects/1/forms/updateEntity')
.expect(200)
.then(({ body }) => {
body.updatedAt.should.be.a.recentIsoDate();
});
}));

it('should update the updatedAt timestamps on the form when updating a published form', testService(async (service, container) => {
const { Forms, Audits } = container;
const asAlice = await service.login('alice');

// Upload a form and publish it
await asAlice.post('/v1/projects/1/forms?publish=true')
.send(testData.forms.updateEntity)
.set('Content-Type', 'application/xml')
.expect(200);

// check updatedAt on the draft form
await asAlice.get('/v1/projects/1/forms/updateEntity')
.expect(200)
.then(({ body }) => {
should(body.updatedAt).be.null();
});

const { acteeId } = await Forms.getByProjectAndXmlFormId(1, 'updateEntity').then(o => o.get());
await Audits.log(null, 'upgrade.process.form.entities_version', { acteeId });

// Run form upgrade
await exhaust(container);

await asAlice.get('/v1/projects/1/forms/updateEntity')
.expect(200)
.then(({ body }) => {
body.updatedAt.should.be.a.recentIsoDate();
});
}));
});

describe('audit logging and errors', () => {
it('should log events about the upgrade for a published form', testService(async (service, container) => {
const { Forms, Audits } = container;
const asAlice = await service.login('alice');

// Upload a form and publish it
await asAlice.post('/v1/projects/1/forms?publish=true')
.send(testData.forms.updateEntity)
.set('Content-Type', 'application/xml')
.expect(200);

const { acteeId } = await Forms.getByProjectAndXmlFormId(1, 'updateEntity').then(o => o.get());
await Audits.log(null, 'upgrade.process.form.entities_version', { acteeId });

// Run form upgrade
await exhaust(container);

await asAlice.get('/v1/audits')
.expect(200)
.then(({ body }) => {
const actions = body.map(a => a.action);
actions.should.eql([
'form.update.publish',
'upgrade.process.form.entities_version',
'form.update.publish',
'dataset.create',
'form.create',
'user.session.create'
]);
});
}));

it('should log events about the upgrade for a draft form', testService(async (service, container) => {
const { Forms, Audits } = container;
const asAlice = await service.login('alice');

// Upload a form and publish it
await asAlice.post('/v1/projects/1/forms')
.send(testData.forms.updateEntity)
.set('Content-Type', 'application/xml')
.expect(200);

const { acteeId } = await Forms.getByProjectAndXmlFormId(1, 'updateEntity').then(o => o.get());
await Audits.log(null, 'upgrade.process.form.entities_version', { acteeId });

// Run form upgrade
await exhaust(container);

await asAlice.get('/v1/audits')
.expect(200)
.then(({ body }) => {
const actions = body.map(a => a.action);
actions.should.eql([
'form.update.draft.replace',
'upgrade.process.form.entities_version',
'form.create',
'user.session.create'
]);
});
}));

it('should log events about the upgrade for a published and draft form', testService(async (service, container) => {
const { Forms, Audits } = container;
const asAlice = await service.login('alice');

// Upload a form and publish it
await asAlice.post('/v1/projects/1/forms?publish=true')
.send(testData.forms.updateEntity)
.set('Content-Type', 'application/xml')
.expect(200);

await asAlice.post('/v1/projects/1/forms/updateEntity/draft');

const { acteeId } = await Forms.getByProjectAndXmlFormId(1, 'updateEntity').then(o => o.get());
await Audits.log(null, 'upgrade.process.form.entities_version', { acteeId });

// Run form upgrade
await exhaust(container);

await asAlice.get('/v1/audits')
.expect(200)
.then(({ body }) => {
const actions = body.map(a => a.action);
actions.should.eql([
'form.update.draft.replace',
'form.update.publish',
'upgrade.process.form.entities_version',
'form.update.draft.set',
'form.update.publish',
'dataset.create',
'form.create',
'user.session.create'
]);
});
}));

it('should update the audit log event for a successful upgrade', testService(async (service, container) => {
const { Forms, Audits } = container;
const asAlice = await service.login('alice');
Expand Down

0 comments on commit d885fdf

Please sign in to comment.