diff --git a/bundles.json b/bundles.json index 898ca3d738..79ab2dd246 100644 --- a/bundles.json +++ b/bundles.json @@ -18,6 +18,7 @@ "platform/features/scrolling", "platform/features/events", "platform/forms", + "platform/identity", "platform/persistence/queue", "platform/policy", "platform/entanglement", diff --git a/example/identity/bundle.json b/example/identity/bundle.json new file mode 100644 index 0000000000..85704050e7 --- /dev/null +++ b/example/identity/bundle.json @@ -0,0 +1,12 @@ +{ + "extensions": { + "components": [ + { + "implementation": "ExampleIdentityService.js", + "provides": "identityService", + "type": "provider", + "depends": [ "dialogService" ] + } + ] + } +} diff --git a/example/identity/src/ExampleIdentityService.js b/example/identity/src/ExampleIdentityService.js new file mode 100644 index 0000000000..465bc9e0f1 --- /dev/null +++ b/example/identity/src/ExampleIdentityService.js @@ -0,0 +1,75 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define( + function () { + "use strict"; + + var DEFAULT_IDENTITY = { key: "user", name: "Example User" }, + DIALOG_STRUCTURE = { + name: "Identify Yourself", + sections: [{ rows: [ + { + name: "User ID", + control: "textfield", + key: "key", + required: true + }, + { + name: "Human name", + control: "textfield", + key: "name", + required: true + } + ]}] + }; + + + /** + * Example implementation of an identity service. This prompts the + * user to enter a name and user ID; in a more realistic + * implementation, this would be read from a server, possibly + * prompting for a user name and password (or similar) as + * appropriate. + * + * @implements {IdentityService} + * @memberof platform/identity + */ + function ExampleIdentityProvider(dialogService) { + // Handle rejected dialog messages by treating the + // current user as undefined. + function echo(v) { return v; } + function giveUndefined() { return undefined; } + + this.userPromise = + dialogService.getUserInput(DIALOG_STRUCTURE, DEFAULT_IDENTITY) + .then(echo, giveUndefined); + } + + ExampleIdentityProvider.prototype.getUser = function () { + return this.userPromise; + }; + + return ExampleIdentityProvider; + } +); diff --git a/platform/commonUI/browse/bundle.json b/platform/commonUI/browse/bundle.json index c5ee5e7198..3f30f0e658 100644 --- a/platform/commonUI/browse/bundle.json +++ b/platform/commonUI/browse/bundle.json @@ -93,11 +93,6 @@ { "key": "navigationService", "implementation": "navigation/NavigationService.js" - }, - { - "key": "creationService", - "implementation": "creation/CreationService.js", - "depends": [ "persistenceService", "$q", "$log" ] } ], "actions": [ @@ -115,7 +110,7 @@ "depends": [ "urlService", "$window" ], "group": "windowing", "glyph": "y", - "priority": "preferred" + "priority": "preferred" }, { "key": "fullscreen", @@ -123,7 +118,7 @@ "category": "view-control", "group": "windowing", "glyph": "z", - "priority": "default" + "priority": "default" } ], "views": [ @@ -146,6 +141,13 @@ "type": "provider", "implementation": "creation/CreateActionProvider.js", "depends": [ "typeService", "dialogService", "creationService", "policyService" ] + }, + { + "key": "CreationService", + "provides": "creationService", + "type": "provider", + "implementation": "creation/CreationService.js", + "depends": [ "persistenceService", "$q", "$log" ] } ], "runs": [ diff --git a/platform/commonUI/browse/src/creation/CreateWizard.js b/platform/commonUI/browse/src/creation/CreateWizard.js index 4073ed7e90..e902301977 100644 --- a/platform/commonUI/browse/src/creation/CreateWizard.js +++ b/platform/commonUI/browse/src/creation/CreateWizard.js @@ -59,10 +59,10 @@ define( var locatingType = locatingObject && locatingObject.getCapability('type'); return locatingType && policyService.allow( - "composition", - locatingType, - type - ); + "composition", + locatingType, + type + ); } sections.push({ @@ -77,6 +77,9 @@ define( row.key = index; return row; + }).filter(function (row) { + // Only show rows which have defined controls + return row && row.control; }) }); diff --git a/platform/commonUI/browse/src/creation/CreationService.js b/platform/commonUI/browse/src/creation/CreationService.js index 110a49c216..3dd96d289e 100644 --- a/platform/commonUI/browse/src/creation/CreationService.js +++ b/platform/commonUI/browse/src/creation/CreationService.js @@ -55,6 +55,10 @@ define( * space an object is created within (as it is possible to * have multiple persistence spaces attached.) * + * Note that the model passed in for object creation may be + * modified to attach additional initial properties associated + * with domain object creation. + * * @param {object} model the model for the newly-created * domain object * @param {DomainObject} parent the domain object which @@ -67,12 +71,6 @@ define( var persistence = parent.getCapability("persistence"), self = this; - // Store the location of an object relative to it's parent. - function addLocationToModel(modelId, model, parent) { - model.location = parent.getId(); - return model; - } - // Persist the new domain object's model; it will be fully // constituted as a domain object when loaded back, as all // domain object models are. @@ -135,7 +133,6 @@ define( // 2. Create a model with that ID in the persistence space // 3. Add that ID to return self.$q.when(uuid()).then(function (id) { - model = addLocationToModel(id, model, parent); return doPersist(persistence.getSpace(), id, model); }).then(function (id) { return addToComposition(id, parent, persistence); diff --git a/platform/commonUI/browse/test/creation/CreateWizardSpec.js b/platform/commonUI/browse/test/creation/CreateWizardSpec.js index 7cd78e5178..c4453e7432 100644 --- a/platform/commonUI/browse/test/creation/CreateWizardSpec.js +++ b/platform/commonUI/browse/test/creation/CreateWizardSpec.js @@ -42,7 +42,9 @@ define( "property" + name, [ "getDefinition", "getValue", "setValue" ] ); - mockProperty.getDefinition.andReturn({}); + mockProperty.getDefinition.andReturn({ + control: "textfield" + }); mockProperty.getValue.andReturn(name); return mockProperty; } @@ -157,4 +159,4 @@ define( }); } -); \ No newline at end of file +); diff --git a/platform/commonUI/browse/test/creation/CreationServiceSpec.js b/platform/commonUI/browse/test/creation/CreationServiceSpec.js index 7f15afe061..bdcd752c6c 100644 --- a/platform/commonUI/browse/test/creation/CreationServiceSpec.js +++ b/platform/commonUI/browse/test/creation/CreationServiceSpec.js @@ -201,16 +201,6 @@ define( expect(mockLog.error).toHaveBeenCalled(); }); - it("stores location on new domainObjects", function () { - var model = { name: "my model" }, - objectPromise = creationService.createObject( - model, - mockParentObject - ); - - expect(model.location).toBe('parentId'); - }); - }); } ); diff --git a/platform/core/src/capabilities/MetadataCapability.js b/platform/core/src/capabilities/MetadataCapability.js index 242b35b6dc..ea48d79042 100644 --- a/platform/core/src/capabilities/MetadataCapability.js +++ b/platform/core/src/capabilities/MetadataCapability.js @@ -50,8 +50,8 @@ define( function formatTimestamp(timestamp) { return typeof timestamp === 'number' ? - (moment.utc(timestamp).format(TIME_FORMAT) + " UTC") : - undefined; + (moment.utc(timestamp).format(TIME_FORMAT) + " UTC") : + undefined; } function getProperties() { diff --git a/platform/core/src/capabilities/PersistenceCapability.js b/platform/core/src/capabilities/PersistenceCapability.js index 8c7e08e17d..74a6bc52e7 100644 --- a/platform/core/src/capabilities/PersistenceCapability.js +++ b/platform/core/src/capabilities/PersistenceCapability.js @@ -72,7 +72,12 @@ define( */ PersistenceCapability.prototype.persist = function () { var domainObject = this.domainObject, - modified = domainObject.getModel().modified; + model = domainObject.getModel(), + modified = model.modified, + persistenceService = this.persistenceService, + persistenceFn = model.persisted !== undefined ? + this.persistenceService.updateObject : + this.persistenceService.createObject; // Update persistence timestamp... domainObject.useCapability("mutation", function (model) { @@ -80,11 +85,11 @@ define( }, modified); // ...and persist - return this.persistenceService.updateObject( + return persistenceFn.apply(persistenceService, [ this.getSpace(), domainObject.getId(), domainObject.getModel() - ); + ]); }; /** diff --git a/platform/core/test/capabilities/PersistenceCapabilitySpec.js b/platform/core/test/capabilities/PersistenceCapabilitySpec.js index 83fac3b3e7..253b011838 100644 --- a/platform/core/test/capabilities/PersistenceCapabilitySpec.js +++ b/platform/core/test/capabilities/PersistenceCapabilitySpec.js @@ -48,7 +48,7 @@ define( beforeEach(function () { mockPersistenceService = jasmine.createSpyObj( "persistenceService", - [ "updateObject", "readObject" ] + [ "updateObject", "readObject", "createObject", "deleteObject" ] ); mockDomainObject = { getId: function () { return id; }, @@ -68,10 +68,24 @@ define( ); }); - it("makes a call to the persistence service when invoked", function () { + it("creates unpersisted objects with the persistence service", function () { + // Verify precondition; no call made during constructor + expect(mockPersistenceService.createObject).not.toHaveBeenCalled(); + + persistence.persist(); + + expect(mockPersistenceService.createObject).toHaveBeenCalledWith( + SPACE, + id, + model + ); + }); + + it("updates previously persisted objects with the persistence service", function () { // Verify precondition; no call made during constructor expect(mockPersistenceService.updateObject).not.toHaveBeenCalled(); + model.persisted = 12321; persistence.persist(); expect(mockPersistenceService.updateObject).toHaveBeenCalledWith( @@ -112,4 +126,4 @@ define( }); } -); \ No newline at end of file +); diff --git a/platform/entanglement/bundle.json b/platform/entanglement/bundle.json index c50ac31baf..f85c5cdf4c 100644 --- a/platform/entanglement/bundle.json +++ b/platform/entanglement/bundle.json @@ -33,6 +33,11 @@ } ], "components": [ + { + "type": "decorator", + "provides": "creationService", + "implementation": "services/LocatingCreationDecorator.js" + } ], "controllers": [ ], diff --git a/platform/entanglement/src/services/LocatingCreationDecorator.js b/platform/entanglement/src/services/LocatingCreationDecorator.js new file mode 100644 index 0000000000..041cc38138 --- /dev/null +++ b/platform/entanglement/src/services/LocatingCreationDecorator.js @@ -0,0 +1,49 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/*global define */ + +define( + function () { + "use strict"; + + /** + * Adds a `location` property to newly-created domain objects. + * @constructor + * @augments {platform/commonUI/browse.CreationService} + * @memberof platform/entanglement + */ + function LocatingCreationDecorator(creationService) { + this.creationService = creationService; + } + + LocatingCreationDecorator.prototype.createObject = function (model, parent) { + if (parent && parent.getId) { + model.location = parent.getId(); + } + return this.creationService.createObject(model, parent); + }; + + return LocatingCreationDecorator; + } +); + diff --git a/platform/entanglement/test/services/LocatingCreationDecoratorSpec.js b/platform/entanglement/test/services/LocatingCreationDecoratorSpec.js new file mode 100644 index 0000000000..aa3cbce68a --- /dev/null +++ b/platform/entanglement/test/services/LocatingCreationDecoratorSpec.js @@ -0,0 +1,79 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/*global define,describe,beforeEach,it,jasmine,expect */ + +define( + [ + '../../src/services/LocatingCreationDecorator' + ], + function (LocatingCreationDecorator) { + "use strict"; + + describe("LocatingCreationDecorator", function () { + var mockCreationService, + mockPromise, + mockParent, + decorator; + + beforeEach(function () { + mockCreationService = jasmine.createSpyObj( + 'creationService', + ['createObject'] + ); + mockPromise = jasmine.createSpyObj( + 'promise', + ['then'] + ); + mockParent = jasmine.createSpyObj( + 'domainObject', + ['getCapability', 'getId', 'getModel', 'hasCapability', 'useCapability'] + ); + mockCreationService.createObject.andReturn(mockPromise); + mockParent.getId.andReturn('test-id'); + decorator = new LocatingCreationDecorator(mockCreationService); + }); + + it("delegates to its decorated service", function () { + expect(decorator.createObject( + { someKey: "some value" }, + mockParent + )).toEqual(mockPromise); // promise returned by decoratee + }); + + it("adds a location property", function () { + decorator.createObject( + { someKey: "some value" }, + mockParent + ); + expect(mockCreationService.createObject).toHaveBeenCalledWith( + { + someKey: "some value", + location: "test-id" // Parent's identifier + }, + mockParent + ); + }); + + }); + } +); diff --git a/platform/entanglement/test/suite.json b/platform/entanglement/test/suite.json index fe3c32cbef..9dfceb5c0f 100644 --- a/platform/entanglement/test/suite.json +++ b/platform/entanglement/test/suite.json @@ -4,5 +4,6 @@ "services/LinkService", "services/MoveService", "services/LocationService", + "services/LocatingCreationDecorator", "capabilities/LocationCapability" ] diff --git a/platform/identity/bundle.json b/platform/identity/bundle.json new file mode 100644 index 0000000000..9b3e1eac2b --- /dev/null +++ b/platform/identity/bundle.json @@ -0,0 +1,41 @@ +{ + "extensions": { + "components": [ + { + "implementation": "IdentityAggregator.js", + "type": "aggregator", + "provides": "identityService", + "depends": [ "$q" ] + }, + { + "implementation": "IdentityProvider.js", + "type": "provider", + "provides": "identityService", + "depends": [ "$q" ], + "priority": "fallback" + }, + { + "type": "decorator", + "provides": "creationService", + "implementation": "IdentityCreationDecorator.js", + "depends": [ "identityService" ] + } + ], + "indicators": [ + { + "implementation": "IdentityIndicator.js", + "depends": [ "identityService" ] + } + ], + "types": [ + { + "properties": [ + { + "key": "creator", + "name": "Creator" + } + ] + } + ] + } +} diff --git a/platform/identity/src/IdentityAggregator.js b/platform/identity/src/IdentityAggregator.js new file mode 100644 index 0000000000..c1d9481223 --- /dev/null +++ b/platform/identity/src/IdentityAggregator.js @@ -0,0 +1,93 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +/** + * Defines interfaces and common infrastructure for establishing + * a user's identity. + * @namespace platform/identity + */ +define( + function () { + "use strict"; + + /** + * Provides information about the currently logged-in + * user, if available. + * + * @interface IdentityService + */ + + /** + * Get information about the current user. This returns a promise + * which will resolve to metadata about the user, or undefined if + * no information about the user is available. + * + * @method IdentityService#getUser + * @returns {Promise.} a promise for metadata about + * the current user + */ + + /** + * Metadata about a user. + * + * @typedef IdentityMetadata + * @property {string} name the user's human-readable name + * @property {string} key the user's machine-readable name + */ + + /** + * Aggregator for multiple identity services. Exposes the first + * defined identity provided by any provider, according to + * priority order. + * + * @constructor + * @implements {IdentityService} + * @memberof platform/identity + */ + function IdentityAggregator($q, providers) { + this.providers = providers; + this.$q = $q; + } + + function delegateGetUser(provider) { + return provider.getUser(); + } + + function identity(value) { + return value; + } + + function giveFirst(results) { + return results.filter(identity)[0]; + } + + IdentityAggregator.prototype.getUser = function () { + var $q = this.$q, + promises = this.providers.map(delegateGetUser); + + return $q.all(promises).then(giveFirst); + }; + + return IdentityAggregator; + } +); diff --git a/platform/identity/src/IdentityCreationDecorator.js b/platform/identity/src/IdentityCreationDecorator.js new file mode 100644 index 0000000000..0581b2ae8f --- /dev/null +++ b/platform/identity/src/IdentityCreationDecorator.js @@ -0,0 +1,55 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/*global define */ + +define( + function () { + "use strict"; + + /** + * Adds a `creator` property to newly-created domain objects. + * @constructor + * @augments {platform/commonUI/browse.CreationService} + * @memberof platform/entanglement + */ + function IdentityCreationDecorator(identityService, creationService) { + this.identityService = identityService; + this.creationService = creationService; + } + + IdentityCreationDecorator.prototype.createObject = function (model, parent) { + var creationService = this.creationService, + identityService = this.identityService; + + return identityService.getUser().then(function (user) { + if (user && user.key) { + model.creator = user.key; + } + return creationService.createObject(model, parent); + }); + }; + + return IdentityCreationDecorator; + } +); + diff --git a/platform/identity/src/IdentityIndicator.js b/platform/identity/src/IdentityIndicator.js new file mode 100644 index 0000000000..bee8648f26 --- /dev/null +++ b/platform/identity/src/IdentityIndicator.js @@ -0,0 +1,63 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define( + [], + function () { + "use strict"; + + /** + * Indicator showing the currently logged-in user. + * @constructor + * @memberof platform/identity + * @implements {Indicator} + * @param {IdentityService} identityService the identity service + */ + function IdentityIndicator(identityService) { + // Track the current connection state + var self = this; + + identityService.getUser().then(function (user) { + if (user && user.key) { + self.text = user.name || user.key; + self.description = "Logged in as " + user.key; + } + }); + } + + IdentityIndicator.prototype.getGlyph = function () { + return this.text && "P"; + }; + IdentityIndicator.prototype.getGlyphClass = function () { + return undefined; + }; + IdentityIndicator.prototype.getText = function () { + return this.text; + }; + IdentityIndicator.prototype.getDescription = function () { + return this.description; + }; + + return IdentityIndicator; + } +); diff --git a/platform/identity/src/IdentityProvider.js b/platform/identity/src/IdentityProvider.js new file mode 100644 index 0000000000..5acb4a2c97 --- /dev/null +++ b/platform/identity/src/IdentityProvider.js @@ -0,0 +1,55 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +/** + * Defines interfaces and common infrastructure for establishing + * a user's identity. + * @namespace platform/identity + */ +define( + function () { + "use strict"; + + var UNKNOWN_USER = { + key: "unknown", + name: "Unknown User" + }; + + /** + * Default implementation of an identity service. Provides an + * unkown user. + * @constructor + * @implements {IdentityService} + * @memberof platform/identity + */ + function IdentityProvider($q) { + this.userPromise = $q.when(UNKNOWN_USER); + } + + IdentityProvider.prototype.getUser = function () { + return this.userPromise; + }; + + return IdentityProvider; + } +); diff --git a/platform/identity/test/IdentityAggregatorSpec.js b/platform/identity/test/IdentityAggregatorSpec.js new file mode 100644 index 0000000000..07d41c0ce8 --- /dev/null +++ b/platform/identity/test/IdentityAggregatorSpec.js @@ -0,0 +1,143 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise,describe,it,expect,beforeEach,waitsFor,runs,jasmine*/ + +define( + ["../src/IdentityAggregator"], + function (IdentityAggregator) { + "use strict"; + + describe("The identity aggregator", function () { + var mockProviders, + mockQ, + resolves, + mockPromise, + mockCallback, + testUsers, + aggregator; + + function callbackCalled() { + return mockCallback.calls.length > 0; + } + + function resolveProviderPromises() { + ['a', 'b', 'c'].forEach(function (id, i) { + resolves[id](testUsers[i]); + }); + } + + beforeEach(function () { + testUsers = [ + { key: "user0", name: "User Zero" }, + { key: "user1", name: "User One" }, + { key: "user2", name: "User Two" } + ]; + + resolves = {}; + + mockProviders = ['a', 'b', 'c'].map(function (id) { + var mockProvider = jasmine.createSpyObj( + 'provider-' + id, + [ 'getUser' ] + ); + + mockProvider.getUser.andReturn(new Promise(function (r) { + resolves[id] = r; + })); + + return mockProvider; + }); + + mockQ = jasmine.createSpyObj('$q', ['all']); + mockQ.all.andCallFake(function (promises) { + return Promise.all(promises); + }); + + mockCallback = jasmine.createSpy('callback'); + + aggregator = new IdentityAggregator( + mockQ, + mockProviders + ); + }); + + it("delegates to the aggregated providers", function () { + // Verify precondition + mockProviders.forEach(function (p) { + expect(p.getUser).not.toHaveBeenCalled(); + }); + + aggregator.getUser(); + + mockProviders.forEach(function (p) { + expect(p.getUser).toHaveBeenCalled(); + }); + }); + + it("returns the first result when it is defined", function () { + aggregator.getUser().then(mockCallback); + + resolveProviderPromises(); + + waitsFor(callbackCalled); + runs(function () { + expect(mockCallback).toHaveBeenCalledWith(testUsers[0]); + }); + }); + + it("returns a later result when earlier results are undefined", function () { + testUsers[0] = undefined; + + aggregator.getUser().then(mockCallback); + + resolveProviderPromises(); + + waitsFor(callbackCalled); + runs(function () { + expect(mockCallback).toHaveBeenCalledWith(testUsers[1]); + }); + }); + + it("returns undefined when no providers expose users", function () { + testUsers = [ undefined, undefined, undefined ]; + + aggregator.getUser().then(mockCallback); + + resolveProviderPromises(); + + waitsFor(callbackCalled); + runs(function () { + expect(mockCallback).toHaveBeenCalledWith(undefined); + }); + }); + + it("returns undefined when there are no providers", function () { + new IdentityAggregator(mockQ, []).getUser().then(mockCallback); + waitsFor(callbackCalled); + runs(function () { + expect(mockCallback).toHaveBeenCalledWith(undefined); + }); + }); + + }); + } +); diff --git a/platform/identity/test/IdentityCreationDecoratorSpec.js b/platform/identity/test/IdentityCreationDecoratorSpec.js new file mode 100644 index 0000000000..91021a7a8f --- /dev/null +++ b/platform/identity/test/IdentityCreationDecoratorSpec.js @@ -0,0 +1,107 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/*global define,describe,beforeEach,it,jasmine,expect,Promise,waitsFor,runs */ + +define( + [ + '../src/IdentityCreationDecorator' + ], + function (IdentityCreationDecorator) { + "use strict"; + + describe("IdentityCreationDecorator", function () { + var mockIdentityService, + mockCreationService, + mockParent, + mockCreatedObject, + mockCallback, + decorator; + + function calledBack() { + return mockCallback.calls.length > 0; + } + + beforeEach(function () { + mockCallback = jasmine.createSpy('callback'); + mockIdentityService = jasmine.createSpyObj( + 'identityService', + ['getUser'] + ); + mockCreationService = jasmine.createSpyObj( + 'creationService', + ['createObject'] + ); + mockParent = jasmine.createSpyObj( + 'parentObject', + ['getCapability', 'getId', 'getModel', 'hasCapability', 'useCapability'] + ); + mockCreatedObject = jasmine.createSpyObj( + 'domainObject', + ['getCapability', 'getId', 'getModel', 'hasCapability', 'useCapability'] + ); + mockCreationService.createObject + .andReturn(Promise.resolve(mockCreatedObject)); + mockIdentityService.getUser + .andReturn(Promise.resolve({ key: "test-user-id" })); + mockParent.getId.andReturn('test-id'); + decorator = new IdentityCreationDecorator( + mockIdentityService, + mockCreationService + ); + }); + + it("delegates to its decorated service when identity is available", function () { + var testModel = { someKey: "some value" }; + + decorator.createObject(testModel, mockParent) + .then(mockCallback); + + waitsFor(calledBack); + runs(function () { + expect(mockCallback) + .toHaveBeenCalledWith(mockCreatedObject); + }); + }); + + it("adds a creator property", function () { + var testModel = { someKey: "some value" }; + + decorator.createObject(testModel, mockParent) + .then(mockCallback); + + waitsFor(calledBack); + runs(function () { + expect(mockCallback) + .toHaveBeenCalledWith(mockCreatedObject); + // Make sure arguments were delegated appropriately + expect(mockCreationService.createObject) + .toHaveBeenCalledWith( + { someKey: "some value", creator: "test-user-id" }, + mockParent + ); + }); + }); + + }); + } +); diff --git a/platform/identity/test/IdentityIndicatorSpec.js b/platform/identity/test/IdentityIndicatorSpec.js new file mode 100644 index 0000000000..335ca69669 --- /dev/null +++ b/platform/identity/test/IdentityIndicatorSpec.js @@ -0,0 +1,76 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ["../src/IdentityIndicator"], + function (IdentityIndicator) { + "use strict"; + + describe("The identity indicator", function () { + var mockPromise, + mockIdentityService, + indicator; + + beforeEach(function () { + mockPromise = jasmine.createSpyObj('promise', ['then']); + mockIdentityService = jasmine.createSpyObj( + 'identityService', + ['getUser'] + ); + + mockIdentityService.getUser.andReturn(mockPromise); + + indicator = new IdentityIndicator(mockIdentityService); + }); + + it("shows information about the current user", function () { + mockPromise.then.mostRecentCall.args[0]({ + key: "testuserid", + name: "A User" + }); + // Should have a single character glyph + expect(indicator.getGlyph().length).toEqual(1); + expect(indicator.getGlyphClass()).toBeUndefined(); + expect(indicator.getText()).toEqual("A User"); + expect(indicator.getDescription().indexOf("testuserid")) + .not.toEqual(-1); + }); + + it("shows nothing while no user information is available", function () { + expect(indicator.getGlyph()).toBeUndefined(); + expect(indicator.getGlyphClass()).toBeUndefined(); + expect(indicator.getText()).toBeUndefined(); + expect(indicator.getDescription()).toBeUndefined(); + }); + + it("shows nothing when there is no identity information", function () { + mockPromise.then.mostRecentCall.args[0](undefined); + expect(indicator.getGlyph()).toBeUndefined(); + expect(indicator.getGlyphClass()).toBeUndefined(); + expect(indicator.getText()).toBeUndefined(); + expect(indicator.getDescription()).toBeUndefined(); + }); + + }); + } +); diff --git a/platform/identity/test/IdentityProviderSpec.js b/platform/identity/test/IdentityProviderSpec.js new file mode 100644 index 0000000000..85867642a8 --- /dev/null +++ b/platform/identity/test/IdentityProviderSpec.js @@ -0,0 +1,63 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/*global define,describe,beforeEach,it,jasmine,expect,Promise,waitsFor,runs */ + +define( + [ + '../src/IdentityProvider' + ], + function (IdentityProvider) { + "use strict"; + + describe("IdentityProvider", function () { + var mockQ, mockCallback, provider; + + function calledBack() { + return mockCallback.calls.length > 0; + } + + beforeEach(function () { + mockCallback = jasmine.createSpy('callback'); + mockQ = jasmine.createSpyObj('$q', ['when']); + mockQ.when.andCallFake(function (v) { + return Promise.resolve(v); + }); + + provider = new IdentityProvider(mockQ); + }); + + it("provides an unknown user", function () { + provider.getUser().then(mockCallback); + + waitsFor(calledBack); + runs(function () { + expect(mockCallback).toHaveBeenCalledWith({ + key: jasmine.any(String), + name: jasmine.any(String) + }); + }); + }); + + }); + } +); diff --git a/platform/identity/test/suite.json b/platform/identity/test/suite.json new file mode 100644 index 0000000000..15fe7e4caa --- /dev/null +++ b/platform/identity/test/suite.json @@ -0,0 +1,6 @@ +[ + "IdentityAggregator", + "IdentityCreationDecorator", + "IdentityIndicator", + "IdentityProvider" +]