Skip to content

Commit

Permalink
Disallow entity creation via API for unpublished datasets
Browse files Browse the repository at this point in the history
  • Loading branch information
ktuite committed Sep 14, 2023
1 parent 1a970c8 commit f507c45
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 5 deletions.
6 changes: 3 additions & 3 deletions lib/model/query/datasets.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const createOrMerge = (name, form, fields) => async ({ one, Actees, Datasets, Pr
// Provision acteeId if necessary.
// Need to check for existing dataset, and if not found, need to also
// fetch the project since the dataset will be an actee child of the project.
const existingDataset = await Datasets.get(projectId, name);
const existingDataset = await Datasets.get(projectId, name, false);
const acteeId = existingDataset.isDefined()
? existingDataset.get().acteeId
: await Projects.getById(projectId).then((o) => o.get())
Expand Down Expand Up @@ -189,7 +189,7 @@ publishIfExists.audit.withResult = true;
////////////////////////////////////////////////////////////////////////////
// DATASET GETTERS

const _get = extender(Dataset)(Dataset.Extended)((fields, extend, options, publishedOnly = false, actorId) => sql`
const _get = extender(Dataset)(Dataset.Extended)((fields, extend, options, publishedOnly, actorId) => sql`
SELECT ${fields} FROM datasets
${extend|| sql`
LEFT JOIN (
Expand Down Expand Up @@ -224,7 +224,7 @@ const getList = (projectId, options = QueryOptions.none) => ({ all }) =>
_get(all, options.withCondition({ projectId }), true);

// Get a dataset by it's project id and name. Commonly used in a resource.
const get = (projectId, name, publishedOnly = false, extended = false) => ({ maybeOne }) => {
const get = (projectId, name, publishedOnly, extended = false) => ({ maybeOne }) => {
const options = extended ? QueryOptions.extended : QueryOptions.none;
return _get(maybeOne, options.withCondition({ projectId, name }), publishedOnly);
};
Expand Down
4 changes: 2 additions & 2 deletions lib/resources/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ module.exports = (service, endpoint) => {

service.post('/projects/:id/datasets/:name/entities', endpoint(async ({ Datasets, Entities }, { auth, body, params, userAgent }) => {

const dataset = await Datasets.get(params.id, params.name).then(getOrNotFound);
const dataset = await Datasets.get(params.id, params.name, true).then(getOrNotFound);

await auth.canOrReject('entity.create', dataset);

Expand All @@ -96,7 +96,7 @@ module.exports = (service, endpoint) => {

service.patch('/projects/:id/datasets/:name/entities/:uuid', endpoint(async ({ Datasets, Entities }, { auth, body, params, query, userAgent, headers }) => {

const dataset = await Datasets.get(params.id, params.name).then(getOrNotFound);
const dataset = await Datasets.get(params.id, params.name, true).then(getOrNotFound);

await auth.canOrReject('entity.update', dataset);

Expand Down
34 changes: 34 additions & 0 deletions test/integration/api/datasets.js
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,40 @@ describe('datasets and entities', () => {
});
}));

it('should return dataset properties from multiple forms where later form publishes dataset', testService(async (service) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms')
.send(testData.forms.multiPropertyEntity)
.set('Content-Type', 'application/xml')
.expect(200);

await asAlice.post('/v1/projects/1/forms?publish=true')
.send(testData.forms.multiPropertyEntity
.replace('multiPropertyEntity', 'multiPropertyEntity2')
.replace('b_q1', 'f_q1')
.replace('d_q2', 'e_q2'))
.set('Content-Type', 'application/xml')
.expect(200);

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

await asAlice.get('/v1/projects/1/datasets/foo')
.expect(200)
.then(({ body }) => {
const { properties } = body;
properties.map((p) => p.name)
.should.be.eql([
'f_q1',
'e_q2',
'a_q3',
'c_q4',
'b_q1',
'd_q2',
]);
});
}));

it('should return dataset properties from multiple forms including updated form with updated schema', testService(async (service) => {
const asAlice = await service.login('alice');

Expand Down
19 changes: 19 additions & 0 deletions test/integration/api/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,25 @@ describe('Entities API', () => {
});
}));

it('should reject creating new entity if dataset not yet published', testService(async (service) => {
const asAlice = await service.login('alice');

await asAlice.post('/v1/projects/1/forms')
.send(testData.forms.simpleEntity)
.expect(200);

await asAlice.get('/v1/projects/1/datasets/people')
.expect(404);

await asAlice.post('/v1/projects/1/datasets/people/entities')
.send({
uuid: '12345678-1234-4123-8234-111111111aaa',
label: 'Johnny Doe',
data: {}
})
.expect(404);
}));

it('should create an Entity', testDataset(async (service) => {
const asAlice = await service.login('alice');

Expand Down

0 comments on commit f507c45

Please sign in to comment.