diff --git a/app/api/entities/specs/denormalization.spec.ts b/app/api/entities/specs/denormalization.spec.ts index 183ded5951..87faa11a74 100644 --- a/app/api/entities/specs/denormalization.spec.ts +++ b/app/api/entities/specs/denormalization.spec.ts @@ -42,6 +42,7 @@ describe('Denormalize relationships', () => { describe('title and basic property (text)', () => { it('should update denormalized title and icon', async () => { const fixtures: DBFixture = { + relationtypes: [factory.relationType('rel1')], templates: [ factory.template('templateA', [ factory.relationshipProp('relationship', 'templateB', 'text'), @@ -232,6 +233,7 @@ describe('Denormalize relationships', () => { describe('when the relationship property has no content', () => { const fixtures: DBFixture = { + relationtypes: [factory.relationType('rel1')], templates: [ factory.template('templateA', [ factory.relationshipProp('relationship', '', { content: '' }), @@ -289,6 +291,7 @@ describe('Denormalize relationships', () => { beforeEach(async () => { jest.spyOn(translations, 'updateContext').mockImplementation(async () => 'ok'); const fixtures: DBFixture = { + relationtypes: [factory.relationType('rel1')], templates: [ factory.template('templateA', [ factory.inherit('relationship', 'templateB', 'multiselect'), @@ -383,6 +386,7 @@ describe('Denormalize relationships', () => { describe('inherited relationship', () => { beforeEach(async () => { const fixtures: DBFixture = { + relationtypes: [factory.relationType('rel1')], templates: [ factory.template('templateA', [ factory.inherit('relationship', 'templateB', 'relationshipB'), @@ -444,6 +448,7 @@ describe('Denormalize relationships', () => { beforeEach(async () => { await load( { + relationtypes: [factory.relationType('rel1')], templates: [ factory.template('templateA', [ factory.inherit('relationshipA', 'templateB', 'relationshipB'), diff --git a/app/api/entities/specs/fixtures.js b/app/api/entities/specs/fixtures.js index 5bba0346f3..89908daeb2 100644 --- a/app/api/entities/specs/fixtures.js +++ b/app/api/entities/specs/fixtures.js @@ -683,6 +683,12 @@ export default { name: 'templateForGetWithRelationships', }, ], + relationtypes: [ + { _id: relationType1 }, + { _id: relationType2 }, + { _id: relationType3 }, + { _id: relationType4 }, + ], connections: [ { _id: referenceId, entity: 'shared', template: null, hub: hub1, entityData: {} }, { _id: db.id(), entity: 'shared2', template: relationType1, hub: hub1, entityData: {} }, diff --git a/app/api/relationships/relationships.js b/app/api/relationships/relationships.js index 4d9458ca8c..dc5e07bff9 100644 --- a/app/api/relationships/relationships.js +++ b/app/api/relationships/relationships.js @@ -270,6 +270,20 @@ export default { ).map(r => r.sharedId) ); + const relTypesToSave = new Set( + relsFlat + .map(r => (r.template && Object.hasOwn(r.template, '_id') ? r.template._id : r.template)) + .filter(r => r) + ); + + const existingRelationshipTypes = await relationtypes.count({ + _id: { $in: Array.from(relTypesToSave) }, + }); + + if (relTypesToSave.size !== existingRelationshipTypes) { + throw new Error('Some relationship types do not exist'); + } + const relationships = rels.map(_group => { let group = _group.filter(r => existingEntities.has(r.entity)); if (group.length === 1 && !group[0].hub) { diff --git a/app/api/relationships/specs/relationships.spec.js b/app/api/relationships/specs/relationships.spec.js index 86cfe45bc8..086cc6c034 100644 --- a/app/api/relationships/specs/relationships.spec.js +++ b/app/api/relationships/specs/relationships.spec.js @@ -302,6 +302,22 @@ describe('relationships', () => { }); }); + describe('when creating relationships using non existent relationship types', () => { + it('should throw an error', async () => { + const nonExistentRelationshipType = db.id(); + await expect(async () => + relationships.save( + [ + { entity: 'entity3', template: relation2 }, + { entity: 'entity2', template: nonExistentRelationshipType }, + { entity: 'entity4', template: null }, + ], + 'en' + ) + ).rejects.toBeInstanceOf(Error); + }); + }); + describe('when creating relationships to non existent entities', () => { it('should not create them', async () => { const relations = await relationships.save( @@ -373,11 +389,17 @@ describe('relationships', () => { }); it('should update correctly if template is null', async () => { - const reference = await relationships.getById(connectionID1); + let reference = await relationships.getById(connectionID1); reference.template = { _id: null }; const [savedReference] = await relationships.save(reference, 'en'); expect(savedReference.entity).toBe('entity_id'); expect(savedReference.template).toBe(null); + + reference = await relationships.getById(connectionID1); + reference.template = null; + const [savedRef2] = await relationships.save(reference, 'en'); + expect(savedRef2.entity).toBe('entity_id'); + expect(savedRef2.template).toBe(null); }); }); diff --git a/app/api/relationtypes/relationtypes.js b/app/api/relationtypes/relationtypes.js index bb2ec02088..01b992bdab 100644 --- a/app/api/relationtypes/relationtypes.js +++ b/app/api/relationtypes/relationtypes.js @@ -92,6 +92,10 @@ export default { return model.get(query); }, + count(query) { + return model.count(query); + }, + getById(id) { return model.getById(id); }, diff --git a/app/api/search.v2/specs/sorting.spec.ts b/app/api/search.v2/specs/sorting.spec.ts index acca5b8ac6..e89866c68c 100644 --- a/app/api/search.v2/specs/sorting.spec.ts +++ b/app/api/search.v2/specs/sorting.spec.ts @@ -41,6 +41,7 @@ describe('Sorting', () => { await setupTestingEnviroment( { + relationtypes: [factory.relationType('rel1')], templates: [ factory.template('templateA', [ factory.property('textProperty', 'text'),