From c2982afd9c86b5781af8cabfbfbae966ea880dda Mon Sep 17 00:00:00 2001 From: Matthew White Date: Fri, 26 Apr 2024 00:12:19 -0400 Subject: [PATCH] Exclude deleted forms from linkedForms (#1130) Closes getodk/central#643. --- lib/model/query/datasets.js | 2 +- test/integration/api/datasets.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/model/query/datasets.js b/lib/model/query/datasets.js index b4f4777b9..dac2ed8e5 100644 --- a/lib/model/query/datasets.js +++ b/lib/model/query/datasets.js @@ -341,7 +341,7 @@ const getMetadata = (dataset) => async ({ all, Datasets }) => { const _getLinkedForms = (datasetName, projectId) => sql` SELECT DISTINCT f."xmlFormId", coalesce(fd.name, f."xmlFormId") "name" FROM form_attachments fa - JOIN forms f ON f.id = fa."formId" + JOIN forms f ON f.id = fa."formId" AND f."deletedAt" IS NULL JOIN form_defs fd ON f."currentDefId" = fd.id JOIN datasets ds ON ds.id = fa."datasetId" WHERE ds.name = ${datasetName} diff --git a/test/integration/api/datasets.js b/test/integration/api/datasets.js index 2dbfea03b..2bfedd86e 100644 --- a/test/integration/api/datasets.js +++ b/test/integration/api/datasets.js @@ -1362,6 +1362,38 @@ describe('datasets and entities', () => { })); + it('should not return a linked form that has been deleted', testService(async (service) => { + const asAlice = await service.login('alice'); + await asAlice.post('/v1/projects/1/forms?publish=true') + .send(testData.forms.simpleEntity) + .set('Content-Type', 'application/xml') + .expect(200); + const withAttachments = testData.forms.withAttachments + .replace('goodone.csv', 'people.csv'); + await asAlice.post('/v1/projects/1/forms?publish=true') + .send(withAttachments) + .set('Content-Type', 'application/xml') + .expect(200); + await asAlice.post('/v1/projects/1/forms?publish=true') + .send(withAttachments + .replace('id="withAttachments"', 'id="withAttachments2"')) + .set('Content-Type', 'application/xml') + .expect(200); + const { body: beforeDeletion } = await asAlice.get('/v1/projects/1/datasets/people') + .expect(200); + beforeDeletion.linkedForms.map(form => form.xmlFormId).should.eql([ + 'withAttachments', + 'withAttachments2' + ]); + await asAlice.delete('/v1/projects/1/forms/withAttachments2') + .expect(200); + const { body: afterDeletion } = await asAlice.get('/v1/projects/1/datasets/people') + .expect(200); + afterDeletion.linkedForms.map(form => form.xmlFormId).should.eql([ + 'withAttachments' + ]); + })); + it('should return properties of a dataset in order', testService(async (service) => { const asAlice = await service.login('alice');