[NIFIREG-126] adding some polish and testing around deep links

This closes #99.

Signed-off-by: Kevin Doran <kdo...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi-registry/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-registry/commit/1bb1e2b6
Tree: http://git-wip-us.apache.org/repos/asf/nifi-registry/tree/1bb1e2b6
Diff: http://git-wip-us.apache.org/repos/asf/nifi-registry/diff/1bb1e2b6

Branch: refs/heads/master
Commit: 1bb1e2b654c17784a1dec36b53239c7d9ed48f3b
Parents: ed86f1a
Author: Scott Aslan <scottyas...@gmail.com>
Authored: Fri Feb 9 10:19:26 2018 -0500
Committer: Kevin Doran <kdo...@apache.org>
Committed: Fri Feb 9 14:25:26 2018 -0500

----------------------------------------------------------------------
 .travis.yml                                     |    2 +-
 .../nifi/registry/service/RegistryService.java  |   92 +-
 .../registry/web/api/AccessPolicyResource.java  |    8 +-
 .../registry/web/api/BucketFlowResource.java    |    8 +-
 .../nifi/registry/web/api/TenantResource.java   |   24 +-
 .../web/api/UnsecuredNiFiRegistryClientIT.java  |    2 +-
 .../src/main/frontend/karma.conf.js             |    8 +-
 .../platform/core/common/styles/_buttons.scss   |    5 +
 .../core/common/styles/_checkboxes.scss         |    4 +
 .../platform/core/common/styles/_menus.scss     |    1 +
 .../nf-registry-administration.spec.js          |    2 -
 .../users/nf-registry-users-administration.html |   12 +-
 .../users/nf-registry-users-administration.js   |   20 +-
 .../nf-registry-users-adminstration.spec.js     |    4 +-
 .../manage-group/nf-registry-manage-group.js    |   17 +-
 .../nf-registry-manage-group.spec.js            | 2403 ++++++++++++++++++
 .../manage-user/nf-registry-manage-user.js      |   31 +-
 .../manage-user/nf-registry-manage-user.spec.js | 1816 +++++++++++++
 .../nf-registry-workflow-administration.html    |   16 +-
 .../nf-registry-workflow-administration.spec.js |    4 +-
 .../nf-registry-manage-bucket.html              |    2 +-
 .../manage-bucket/nf-registry-manage-bucket.js  |   54 +-
 .../nf-registry-manage-bucket.spec.js           |  766 ++++++
 .../nf-registry-bucket-grid-list-viewer.js      |   36 +-
 .../nf-registry-bucket-grid-list-viewer.spec.js |   50 +-
 .../nf-registry-droplet-grid-list-viewer.js     |   41 +-
 ...nf-registry-droplet-grid-list-viewer.spec.js |   72 +-
 .../registry/nf-registry-grid-list-viewer.html  |    6 +-
 .../nf-registry-grid-list-viewer.spec.js        |    4 +-
 .../explorer/nf-registry-explorer.spec.js       |    2 -
 .../src/main/webapp/nf-registry.module.js       |    2 -
 .../src/main/webapp/nf-registry.routes.js       |    5 +
 .../src/main/webapp/nf-registry.spec.js         |    2 -
 .../src/main/webapp/services/nf-registry.api.js |   62 +-
 .../webapp/services/nf-registry.api.spec.js     |  453 +++-
 .../services/nf-registry.auth-guard.service.js  |  237 +-
 .../nf-registry.auth-guard.service.spec.js      |  629 +++++
 .../webapp/services/nf-registry.auth.service.js |   46 -
 .../main/webapp/services/nf-registry.service.js |   25 -
 .../webapp/services/nf-registry.service.spec.js |    4 +-
 .../services/nf-registry.token.interceptor.js   |   14 +-
 .../src/main/webapp/systemjs.builder.config.js  |    1 -
 42 files changed, 6594 insertions(+), 398 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 8b2bc35..d416986 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -55,5 +55,5 @@ install: true
 
 #build commands
 script:
-    - mvn -T 2C clean install -Pintegration-tests,contrib-check
+    - mvn -T 2C clean install -Pintegration-tests,contrib-check,jsUnitTests
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
 
b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
index fad517f..802121e 100644
--- 
a/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
+++ 
b/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
@@ -149,7 +149,9 @@ public class RegistryService {
         try {
             final BucketEntity bucket = 
metadataService.getBucketById(bucketIdentifier);
             if (bucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             return DataModelMapper.map(bucket);
@@ -196,7 +198,9 @@ public class RegistryService {
             // ensure a bucket with the given id exists
             final BucketEntity existingBucketById = 
metadataService.getBucketById(bucket.getIdentifier());
             if (existingBucketById == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucket.getIdentifier());
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucket.getIdentifier());
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // ensure a different bucket with the same name does not exist
@@ -239,7 +243,9 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // for each flow in the bucket, delete all snapshots from the flow 
persistence provider
@@ -267,7 +273,9 @@ public class RegistryService {
         try {
             final BucketEntity bucket = 
metadataService.getBucketById(bucketIdentifier);
             if (bucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             final List<BucketItem> bucketItems = new ArrayList<>();
@@ -336,7 +344,9 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // ensure another flow with the same name doesn't exist
@@ -371,12 +381,16 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             final FlowEntity existingFlow = 
metadataService.getFlowByIdWithSnapshotCounts(flowIdentifier);
             if (existingFlow == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist for identifier " + flowIdentifier);
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
flowIdentifier);
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if (!existingBucket.getId().equals(existingFlow.getBucketId())) {
@@ -398,7 +412,9 @@ public class RegistryService {
         try {
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketId);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketId);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketId);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // return non-verbose set of flows for the given bucket
@@ -431,12 +447,16 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(versionedFlow.getBucketIdentifier());
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + versionedFlow.getBucketIdentifier());
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
versionedFlow.getBucketIdentifier());
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             final FlowEntity existingFlow = 
metadataService.getFlowByIdWithSnapshotCounts(versionedFlow.getIdentifier());
             if (existingFlow == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist for identifier " + versionedFlow.getIdentifier());
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
versionedFlow.getIdentifier());
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if (!existingBucket.getId().equals(existingFlow.getBucketId())) {
@@ -486,13 +506,17 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // ensure the flow exists
             final FlowEntity existingFlow = 
metadataService.getFlowById(flowIdentifier);
             if (existingFlow == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist for identifier " + flowIdentifier);
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
flowIdentifier);
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if (!existingBucket.getId().equals(existingFlow.getBucketId())) {
@@ -536,13 +560,17 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(snapshotMetadata.getBucketIdentifier());
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + snapshotMetadata.getBucketIdentifier());
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
snapshotMetadata.getBucketIdentifier());
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // ensure the flow exists, we need to use "with counts" here so we 
can return this is a part of the response
             final FlowEntity existingFlow = 
metadataService.getFlowByIdWithSnapshotCounts(snapshotMetadata.getFlowIdentifier());
             if (existingFlow == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist for identifier " + snapshotMetadata.getFlowIdentifier());
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
snapshotMetadata.getFlowIdentifier());
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if (!existingBucket.getId().equals(existingFlow.getBucketId())) {
@@ -614,13 +642,17 @@ public class RegistryService {
         try {
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // we need to populate the version count here so we have to do 
this retrieval instead of snapshotEntity.getFlow()
             final FlowEntity flowEntityWithCount = 
metadataService.getFlowByIdWithSnapshotCounts(flowIdentifier);
             if (flowEntityWithCount == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist with identifier " + flowIdentifier);
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
flowIdentifier);
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if 
(!existingBucket.getId().equals(flowEntityWithCount.getBucketId())) {
@@ -630,7 +662,9 @@ public class RegistryService {
             // ensure the snapshot exists
             final FlowSnapshotEntity snapshotEntity = 
metadataService.getFlowSnapshot(flowIdentifier, version);
             if (snapshotEntity == null) {
-                throw new ResourceNotFoundException("Versioned flow snapshot 
does not exist for flow " + flowIdentifier + " and version " + version);
+                LOGGER.warn("The specified flow snapshot id [{}] does not 
exist for version [{}].", flowIdentifier, version);
+
+                throw new ResourceNotFoundException("The specified versioned 
flow snapshot does not exist for this flow.");
             }
 
             // get the serialized bytes of the snapshot
@@ -683,13 +717,17 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // ensure the flow exists
             final FlowEntity existingFlow = 
metadataService.getFlowById(flowIdentifier);
             if (existingFlow == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist for identifier " + flowIdentifier);
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
flowIdentifier);
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if (!existingBucket.getId().equals(existingFlow.getBucketId())) {
@@ -724,13 +762,17 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // ensure the flow exists
             final FlowEntity existingFlow = 
metadataService.getFlowById(flowIdentifier);
             if (existingFlow == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist for identifier " + flowIdentifier);
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
flowIdentifier);
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if (!existingBucket.getId().equals(existingFlow.getBucketId())) {
@@ -763,13 +805,17 @@ public class RegistryService {
             // ensure the bucket exists
             final BucketEntity existingBucket = 
metadataService.getBucketById(bucketIdentifier);
             if (existingBucket == null) {
-                throw new ResourceNotFoundException("Bucket does not exist for 
identifier " + bucketIdentifier);
+                LOGGER.warn("The specified bucket id [{}] does not exist.", 
bucketIdentifier);
+
+                throw new ResourceNotFoundException("The specified bucket ID 
does not exist in this registry.");
             }
 
             // ensure the flow exists
             final FlowEntity existingFlow = 
metadataService.getFlowById(flowIdentifier);
             if (existingFlow == null) {
-                throw new ResourceNotFoundException("Versioned flow does not 
exist for identifier " + flowIdentifier);
+                LOGGER.warn("The specified flow id [{}] does not exist.", 
flowIdentifier);
+
+                throw new ResourceNotFoundException("The specified flow ID 
does not exist in this bucket.");
             }
 
             if (!existingBucket.getId().equals(existingFlow.getBucketId())) {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java
 
b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java
index f918d4c..68bc493 100644
--- 
a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java
+++ 
b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessPolicyResource.java
@@ -174,7 +174,9 @@ public class AccessPolicyResource extends 
AuthorizableApplicationResource {
 
         final AccessPolicy accessPolicy = 
authorizationService.getAccessPolicy(identifier);
         if (accessPolicy == null) {
-            throw new ResourceNotFoundException("No access policy found with 
ID + " + identifier);
+            logger.warn("The specified access policy id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified policy does not 
exist in this registry.");
         }
 
         return generateOkResponse(accessPolicy).build();
@@ -309,7 +311,9 @@ public class AccessPolicyResource extends 
AuthorizableApplicationResource {
         authorizeAccess(RequestAction.DELETE);
         AccessPolicy deletedPolicy = 
authorizationService.deleteAccessPolicy(identifier);
         if (deletedPolicy == null) {
-            throw new ResourceNotFoundException("No access policy found with 
ID + " + identifier);
+            logger.warn("The specified access policy id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified policy does not 
exist in this registry.");
         }
         return generateOkResponse(deletedPolicy).build();
     }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
 
b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
index dbe6407..e645a40 100644
--- 
a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
+++ 
b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
@@ -333,7 +333,9 @@ public class BucketFlowResource extends 
AuthorizableApplicationResource {
 
         final VersionedFlowSnapshotMetadata latest = 
registryService.getLatestFlowSnapshotMetadata(bucketId, flowId);
         if (latest == null) {
-            throw new ResourceNotFoundException("No flow versions found for 
flow with id " + flowId);
+            logger.warn("The specified flow id [{}] does not exist.", flowId);
+
+            throw new ResourceNotFoundException("The specified flow ID does 
not exist in this bucket.");
         }
 
         final VersionedFlowSnapshot lastSnapshot = 
registryService.getFlowSnapshot(bucketId, flowId, latest.getVersion());
@@ -367,7 +369,9 @@ public class BucketFlowResource extends 
AuthorizableApplicationResource {
 
         final VersionedFlowSnapshotMetadata latest = 
registryService.getLatestFlowSnapshotMetadata(bucketId, flowId);
         if (latest == null) {
-            throw new ResourceNotFoundException("No flow versions found for 
flow with id " + flowId);
+            logger.warn("The specified flow id [{}] does not exist.", flowId);
+
+            throw new ResourceNotFoundException("The specified flow ID does 
not exist in this bucket.");
         }
 
         linkService.populateSnapshotLinks(latest);

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TenantResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TenantResource.java
 
b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TenantResource.java
index 07db72b..1d838c4 100644
--- 
a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TenantResource.java
+++ 
b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TenantResource.java
@@ -182,7 +182,9 @@ public class TenantResource extends 
AuthorizableApplicationResource {
 
         final User user = authorizationService.getUser(identifier);
         if (user == null) {
-            throw new ResourceNotFoundException("No user found with identifier 
" + identifier);
+            logger.warn("The specified user id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified user ID does 
not exist in this registry.");
         }
         return generateOkResponse(user).build();
     }
@@ -230,7 +232,9 @@ public class TenantResource extends 
AuthorizableApplicationResource {
 
         final User updatedUser = authorizationService.updateUser(requestUser);
         if (updatedUser == null) {
-            throw new ResourceNotFoundException("No user found with identifier 
" + identifier);
+            logger.warn("The specified user id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified user ID does 
not exist in this registry.");
         }
 
         return generateOkResponse(updatedUser).build();
@@ -268,7 +272,9 @@ public class TenantResource extends 
AuthorizableApplicationResource {
 
         final User user = authorizationService.deleteUser(identifier);
         if (user == null) {
-            throw new ResourceNotFoundException("No user found with identifier 
" + identifier);
+            logger.warn("The specified user id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified user ID does 
not exist in this registry.");
         }
         return generateOkResponse(user).build();
     }
@@ -382,7 +388,9 @@ public class TenantResource extends 
AuthorizableApplicationResource {
 
         final UserGroup userGroup = 
authorizationService.getUserGroup(identifier);
         if (userGroup == null) {
-            throw new ResourceNotFoundException("No group found with 
identifier " + identifier);
+            logger.warn("The specified user group id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified user group ID 
does not exist in this registry.");
         }
 
         return generateOkResponse(userGroup).build();
@@ -432,7 +440,9 @@ public class TenantResource extends 
AuthorizableApplicationResource {
 
         UserGroup updatedUserGroup = 
authorizationService.updateUserGroup(requestUserGroup);
         if (updatedUserGroup == null) {
-            throw new ResourceNotFoundException("No group found with 
identifier " + identifier);
+            logger.warn("The specified user group id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified user group ID 
does not exist in this registry.");
         }
 
         return generateOkResponse(updatedUserGroup).build();
@@ -470,7 +480,9 @@ public class TenantResource extends 
AuthorizableApplicationResource {
 
         final UserGroup userGroup = 
authorizationService.deleteUserGroup(identifier);
         if (userGroup == null) {
-            throw new ResourceNotFoundException("No group found with 
identifier " + identifier);
+            logger.warn("The specified user group id [{}] does not exist.", 
identifier);
+
+            throw new ResourceNotFoundException("The specified user group ID 
does not exist in this registry.");
         }
 
         return generateOkResponse(userGroup).build();

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
 
b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
index c733f26..d093943 100644
--- 
a/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
+++ 
b/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
@@ -243,7 +243,7 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
             
snapshotClient.getLatestMetadata(snapshotFlow.getBucketIdentifier(), 
"DOES-NOT-EXIST");
             Assert.fail("Should have thrown exception");
         } catch (NiFiRegistryException nfe) {
-            Assert.assertEquals("Error retrieving latest snapshot metadata: 
Versioned flow does not exist for identifier DOES-NOT-EXIST", nfe.getMessage());
+            Assert.assertEquals("Error retrieving latest snapshot metadata: 
The specified flow ID does not exist in this bucket.", nfe.getMessage());
         }
 
         // ---------------------- TEST ITEMS --------------------------//

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/frontend/karma.conf.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/frontend/karma.conf.js 
b/nifi-registry-web-ui/src/main/frontend/karma.conf.js
index 8a63bfd..27a521d 100644
--- a/nifi-registry-web-ui/src/main/frontend/karma.conf.js
+++ b/nifi-registry-web-ui/src/main/frontend/karma.conf.js
@@ -28,8 +28,8 @@ module.exports = function (config) {
         frameworks: ['jasmine'],
         customLaunchers: {
             Chrome_travis_ci: {
-                base: 'Chrome',
-                flags: []
+                base: 'ChromeHeadless',
+                flags: ['--no-sandbox']
             }
         },
         plugins: [
@@ -142,7 +142,7 @@ module.exports = function (config) {
         preprocessors: {
             'webapp/**/!(*spec|*mock|*stub|*config|*extras|*fds-demo).js': 
'coverage'
         },
-        reporters: ['kjhtml', 'coverage'],
+        reporters: ['kjhtml', 'spec', 'coverage'],
         coverageReporter: {
             type: 'html',
             dir: 'coverage/'
@@ -155,7 +155,7 @@ module.exports = function (config) {
         logLevel: config.LOG_INFO,
         autoWatch: true,
         browsers: ['Chrome'],
-        singleRun: true
+        singleRun: false
     });
 
     if (process.env.TRAVIS) {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss 
b/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss
index c8d4802..8b316ea 100644
--- a/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss
+++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss
@@ -75,6 +75,11 @@ body[fds] .mat-raised-button.cdk-focused:focus {
 
 body[fds] .mat-raised-button[disabled] {
   opacity: .6;
+  cursor: not-allowed;
+}
+
+body[fds] .mat-button-toggle-disabled .mat-button-toggle-label-content {
+  cursor: not-allowed;
 }
 
 body[fds] .mat-button-focus-overlay {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss 
b/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss
index 353ec0a..0268fde 100644
--- a/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss
+++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss
@@ -79,3 +79,7 @@ body[fds] .mat-pseudo-checkbox-checked, body[fds] 
.mat-pseudo-checkbox-indetermi
   height: 10px;
   width: 10px;
 }
+
+body[fds] .mat-checkbox-disabled {
+  cursor: not-allowed;
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss 
b/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss
index 5a0c6a9..fdd9194 100644
--- a/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss
+++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss
@@ -38,6 +38,7 @@ body[fds] .regular-button-menu .mat-menu-item:hover {
 body[fds] .mat-menu-item[disabled] {
   color: rgba(0, 0, 0, 0.38);
   background-color: #ffffff;
+  cursor: not-allowed;
 }
 
 body[fds] .mat-menu-item .mat-icon {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js
index 7d1165e..90b4965 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js
@@ -20,7 +20,6 @@ var ngCoreTesting = require('@angular/core/testing');
 var ngCommon = require('@angular/common');
 var ngCommonHttp = require('@angular/common/http');
 var NfRegistryTokenInterceptor = 
require('nifi-registry/services/nf-registry.token.interceptor.js');
-var NfRegistryAuthService = 
require('nifi-registry/services/nf-registry.auth.service.js');
 var NfStorage = require('nifi-registry/services/nf-storage.service.js');
 var ngPlatformBrowser = require('@angular/platform-browser');
 var NfRegistry = require('nifi-registry/nf-registry.js');
@@ -79,7 +78,6 @@ describe('NfRegistryAdministration Component', function () {
             ],
             providers: [
                 NfRegistryService,
-                NfRegistryAuthService,
                 NfRegistryApi,
                 NfStorage,
                 {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
index 501a8a7..7a31b0a 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
@@ -23,9 +23,11 @@ limitations under the License.
                       [items]="nfRegistryService.autoCompleteUsersAndGroups"
                       (add)="nfRegistryService.usersSearchAdd($event)"
                       
(remove)="nfRegistryService.usersSearchRemove($event)"></td-chips>
-            <button class="push-top-sm push-right-sm" color="fds-secondary" 
mat-raised-button (click)="addUser()">
-                Add User
-            </button>
+            <div 
matTooltip="{{(!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite)
 ? 'You do not have permission. Please contact your system administrator.': 
''}}">
+                <button class="push-top-sm push-right-sm" 
color="fds-secondary" mat-raised-button (click)="addUser()" 
[disabled]="!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite">
+                    Add User
+                </button>
+            </div>
             <button class="push-top-sm" color="fds-primary"
                     mat-raised-button [matMenuTriggerFor]="userActionMenu">
                 Actions<i class="fa fa-caret-down" aria-hidden="true"></i>
@@ -39,8 +41,8 @@ limitations under the License.
                     <span>Delete</span>
                 </button>
             </div>
-            <div matTooltip="{{(nfRegistryService.getSelectedGroups().length > 
0) ? 'Only users can be added when creating a new group. Please deselect any 
groups to enable.': ''}}">
-                <button mat-menu-item 
[disabled]="(nfRegistryService.getSelectedGroups().length > 0)"
+            <div matTooltip="{{(nfRegistryService.getSelectedGroups().length > 
0) ? 'Only users can be added when creating a new group. Please deselect any 
groups to enable.': 
(!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite) ? 'You do 
not have permission. Please contact your system administrator.': ''}}">
+                <button mat-menu-item 
[disabled]="(nfRegistryService.getSelectedGroups().length > 0) || 
!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite"
                     (click)="createNewGroup()">
                     <span>Create new group</span>
                 </button>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
index 89ce645..77f9906 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
@@ -65,10 +65,22 @@ NfRegistryUsersAdministration.prototype = {
                 );
             })
             .subscribe(function (response) {
-                var users = response[0];
-                var groups = response[1];
-                self.nfRegistryService.users = users;
-                self.nfRegistryService.groups = groups;
+                if (!response[0].status || response[0].status === 200) {
+                    var users = response[0];
+                    self.nfRegistryService.users = users;
+                } else if (response[0].status === 404) {
+                    
self.router.navigateByUrl('/nifi-registry/administration/users');
+                } else if (response[0].status === 409) {
+                    
self.router.navigateByUrl('/nifi-registry/administration/workflow');
+                }
+                if (!response[1].status || response[1].status === 200) {
+                    var groups = response[1];
+                    self.nfRegistryService.groups = groups;
+                } else if (response[1].status === 404) {
+                    
self.router.navigateByUrl('/nifi-registry/administration/users');
+                } else if (response[1].status === 409) {
+                    
self.router.navigateByUrl('/nifi-registry/administration/workflow');
+                }
                 self.nfRegistryService.filterUsersAndGroups();
                 self.nfRegistryService.inProgress = false;
             });

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-adminstration.spec.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-adminstration.spec.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-adminstration.spec.js
index c99700c..f0bb42e 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-adminstration.spec.js
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-adminstration.spec.js
@@ -42,7 +42,6 @@ var ngMoment = require('angular2-moment');
 var rxjs = require('rxjs/Rx');
 var ngCommonHttp = require('@angular/common/http');
 var NfRegistryTokenInterceptor = 
require('nifi-registry/services/nf-registry.token.interceptor.js');
-var NfRegistryAuthService = 
require('nifi-registry/services/nf-registry.auth.service.js');
 var NfStorage = require('nifi-registry/services/nf-storage.service.js');
 var NfLoginComponent = 
require('nifi-registry/components/login/nf-registry-login.js');
 var NfUserLoginComponent = 
require('nifi-registry/components/login/dialogs/nf-registry-user-login.js');
@@ -87,7 +86,6 @@ describe('NfRegistryUsersAdministration Component', function 
() {
             ],
             providers: [
                 NfRegistryService,
-                NfRegistryAuthService,
                 NfRegistryApi,
                 NfStorage,
                 {
@@ -120,7 +118,7 @@ describe('NfRegistryUsersAdministration Component', 
function () {
 
         // Spy
         spyOn(nfRegistryApi, 'ticketExchange').and.callFake(function () 
{}).and.returnValue(rxjs.Observable.of({}));
-        spyOn(nfRegistryService, 'loadCurrentUser').and.callFake(function () 
{}).and.returnValue(rxjs.Observable.of({}));
+        spyOn(nfRegistryApi, 'loadCurrentUser').and.callFake(function () 
{}).and.returnValue(rxjs.Observable.of({}));
         spyOn(nfRegistryApi, 'getUsers').and.callFake(function () {
         }).and.returnValue(rxjs.Observable.of([{
             "identifier": "2e04b4fb-9513-47bb-aa74-1ae34616bfdc",

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/1bb1e2b6/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js
index 9aaa684..4afff3e 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js
@@ -63,17 +63,22 @@ NfRegistryManageGroup.prototype = {
      */
     ngOnInit: function () {
         var self = this;
-        this.nfRegistryService.sidenav.open();
-
         // subscribe to the route params
         this.$subscription = self.route.params
             .switchMap(function (params) {
                 return self.nfRegistryApi.getUserGroup(params['groupId']);
             })
             .subscribe(function (response) {
-                self.nfRegistryService.group = response;
-                self._groupname = response.identity;
-                self.filterUsers();
+                if (!response.status || response.status === 200) {
+                    self.nfRegistryService.sidenav.open();
+                    self.nfRegistryService.group = response;
+                    self._groupname = response.identity;
+                    self.filterUsers();
+                } else if (response.status === 404) {
+                    
self.router.navigateByUrl('/nifi-registry/administration/users');
+                } else if (response.status === 409) {
+                    
self.router.navigateByUrl('/nifi-registry/administration/workflow');
+                }
             });
     },
 
@@ -542,7 +547,7 @@ NfRegistryManageGroup.prototype = {
                     color: '#1EB475',
                     duration: 3000
                 });
-            } else if (response.status === 404) {
+            } else if (response.status === 409) {
                 self._groupname = self.nfRegistryService.group.identity;
                 self.dialogService.openConfirm({
                     title: 'Error',

Reply via email to