Handle empty namespaces in import (#7619)

* handle blank namespaces in import

---------

Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
Scott Bell 2024-03-19 21:05:14 +01:00 committed by GitHub
parent e305b46d88
commit b2b0837592
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 89 additions and 16 deletions

View File

@ -150,16 +150,15 @@ export default class ImportAsJSONAction {
* @param {string} namespace * @param {string} namespace
* @returns {object} * @returns {object}
*/ */
_generateNewIdentifiers(tree, namespace) { _generateNewIdentifiers(tree, newNamespace) {
// For each domain object in the file, generate new ID, replace in tree // For each domain object in the file, generate new ID, replace in tree
Object.keys(tree.openmct).forEach((domainObjectId) => { Object.keys(tree.openmct).forEach((domainObjectId) => {
const newId = {
namespace,
key: uuid()
};
const oldId = parseKeyString(domainObjectId); const oldId = parseKeyString(domainObjectId);
const newId = {
namespace: newNamespace,
key: uuid()
};
tree = this._rewriteId(oldId, newId, tree); tree = this._rewriteId(oldId, newId, tree);
}, this); }, this);
@ -228,22 +227,32 @@ export default class ImportAsJSONAction {
_rewriteId(oldId, newId, tree) { _rewriteId(oldId, newId, tree) {
let newIdKeyString = this.openmct.objects.makeKeyString(newId); let newIdKeyString = this.openmct.objects.makeKeyString(newId);
let oldIdKeyString = this.openmct.objects.makeKeyString(oldId); let oldIdKeyString = this.openmct.objects.makeKeyString(oldId);
tree = JSON.stringify(tree).replace(new RegExp(oldIdKeyString, 'g'), newIdKeyString); const newTreeString = JSON.stringify(tree).replace(
new RegExp(oldIdKeyString, 'g'),
return JSON.parse(tree, (key, value) => { newIdKeyString
);
const newTree = JSON.parse(newTreeString, (key, value) => {
if ( if (
value !== undefined && value !== undefined &&
value !== null && value !== null &&
Object.prototype.hasOwnProperty.call(value, 'key') && Object.prototype.hasOwnProperty.call(value, 'key') &&
Object.prototype.hasOwnProperty.call(value, 'namespace') && Object.prototype.hasOwnProperty.call(value, 'namespace')
value.key === oldId.key &&
value.namespace === oldId.namespace
) { ) {
return newId; // first check if key is messed up from regex and contains a colon
} else { // if it does, repair it
return value; 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 * @private

View File

@ -135,11 +135,75 @@ describe('The import JSON action', function () {
selectFile: { selectFile: {
name: 'imported object', name: 'imported object',
// eslint-disable-next-line prettier/prettier // 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); 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);
}
});
}); });