diff --git a/src/plugins/importFromJSONAction/ImportFromJSONAction.js b/src/plugins/importFromJSONAction/ImportFromJSONAction.js index 9003fbe5eb..4aa5f14bb1 100644 --- a/src/plugins/importFromJSONAction/ImportFromJSONAction.js +++ b/src/plugins/importFromJSONAction/ImportFromJSONAction.js @@ -150,16 +150,15 @@ export default class ImportAsJSONAction { * @param {string} namespace * @returns {object} */ - _generateNewIdentifiers(tree, namespace) { + _generateNewIdentifiers(tree, newNamespace) { // For each domain object in the file, generate new ID, replace in tree Object.keys(tree.openmct).forEach((domainObjectId) => { - const newId = { - namespace, - key: uuid() - }; - const oldId = parseKeyString(domainObjectId); + const newId = { + namespace: newNamespace, + key: uuid() + }; tree = this._rewriteId(oldId, newId, tree); }, this); @@ -228,22 +227,32 @@ export default class ImportAsJSONAction { _rewriteId(oldId, newId, tree) { let newIdKeyString = this.openmct.objects.makeKeyString(newId); let oldIdKeyString = this.openmct.objects.makeKeyString(oldId); - tree = JSON.stringify(tree).replace(new RegExp(oldIdKeyString, 'g'), newIdKeyString); - - return JSON.parse(tree, (key, value) => { + const newTreeString = JSON.stringify(tree).replace( + new RegExp(oldIdKeyString, 'g'), + newIdKeyString + ); + const newTree = JSON.parse(newTreeString, (key, value) => { if ( value !== undefined && value !== null && Object.prototype.hasOwnProperty.call(value, 'key') && - Object.prototype.hasOwnProperty.call(value, 'namespace') && - value.key === oldId.key && - value.namespace === oldId.namespace + Object.prototype.hasOwnProperty.call(value, 'namespace') ) { - return newId; - } else { - return value; + // first check if key is messed up from regex and contains a colon + // if it does, repair it + if (value.key.includes(':')) { + const splitKey = value.key.split(':'); + value.key = splitKey[1]; + value.namespace = splitKey[0]; + } + // now check if we need to replace the id + if (value.key === oldId.key && value.namespace === oldId.namespace) { + return newId; + } } + return value; }); + return newTree; } /** * @private diff --git a/src/plugins/importFromJSONAction/ImportFromJSONActionSpec.js b/src/plugins/importFromJSONAction/ImportFromJSONActionSpec.js index e9995ea6bf..b1d582cb49 100644 --- a/src/plugins/importFromJSONAction/ImportFromJSONActionSpec.js +++ b/src/plugins/importFromJSONAction/ImportFromJSONActionSpec.js @@ -135,11 +135,75 @@ describe('The import JSON action', function () { selectFile: { name: 'imported object', // eslint-disable-next-line prettier/prettier - body: "{\"openmct\":{\"c28d230d-e909-4a3e-9840-d9ef469dda70\":{\"identifier\":{\"key\":\"c28d230d-e909-4a3e-9840-d9ef469dda70\",\"namespace\":\"\"},\"name\":\"Unnamed Overlay Plot\",\"type\":\"telemetry.plot.overlay\",\"composition\":[],\"configuration\":{\"series\":[]},\"modified\":1695837546833,\"location\":\"mine\",\"created\":1695837546833,\"persisted\":1695837546833,\"__proto__\":{\"toString\":\"foobar\"}}},\"rootId\":\"c28d230d-e909-4a3e-9840-d9ef469dda70\"}" + body: '{"openmct":{"c28d230d-e909-4a3e-9840-d9ef469dda70":{"identifier":{"key":"c28d230d-e909-4a3e-9840-d9ef469dda70","namespace":""},"name":"Unnamed Overlay Plot","type":"telemetry.plot.overlay","composition":[],"configuration":{"series":[]},"modified":1695837546833,"location":"mine","created":1695837546833,"persisted":1695837546833,"__proto__":{"toString":"foobar"}}},"rootId":"c28d230d-e909-4a3e-9840-d9ef469dda70"}' } }; return Promise.resolve(pollutedResponse); } }); + it('preserves the integrity of the namespace and key during import', async () => { + const incomingObject = { + openmct: { + '7323f02a-06ac-438d-bd58-6d6e33b8741e': { + name: 'Some Folder', + type: 'folder', + composition: [ + { + key: '9f6c2d21-5ec8-434c-9fe8-31614ae6d7e6', + namespace: '' + } + ], + modified: 1710843256162, + location: 'mine', + created: 1710843243471, + persisted: 1710843256162, + identifier: { + namespace: '', + key: '7323f02a-06ac-438d-bd58-6d6e33b8741e' + } + }, + '9f6c2d21-5ec8-434c-9fe8-31614ae6d7e6': { + name: 'Some Clock', + type: 'clock', + configuration: { + baseFormat: 'YYYY/MM/DD hh:mm:ss', + use24: 'clock12', + timezone: 'UTC' + }, + modified: 1710843256152, + location: '7323f02a-06ac-438d-bd58-6d6e33b8741e', + created: 1710843256152, + persisted: 1710843256152, + identifier: { + namespace: '', + key: '9f6c2d21-5ec8-434c-9fe8-31614ae6d7e6' + } + } + }, + rootId: '7323f02a-06ac-438d-bd58-6d6e33b8741e' + }; + + const targetDomainObject = { + identifier: { + namespace: 'starJones', + key: '84438cda-a071-48d1-b9bf-d77bd53e59ba' + }, + type: 'folder' + }; + spyOn(openmct.objects, 'save').and.callFake((model) => Promise.resolve(model)); + try { + await importFromJSONAction.onSave(targetDomainObject, { + selectFile: { body: JSON.stringify(incomingObject) } + }); + + for (const callArgs of openmct.objects.save.calls.allArgs()) { + const savedObject = callArgs[0]; // Assuming the first argument is the object being saved. + expect(savedObject.identifier.key.includes(':')).toBeFalse(); // Ensure no colon in the key. + expect(savedObject.identifier.namespace).toBe(targetDomainObject.identifier.namespace); + } + } catch (error) { + fail(error); + } + }); });